Core

Get an overview of virtual DOM, diffing process, rendering, components, and single-file components.

Before we move to the core concepts and techniques, we need to transform the output of the parsing stage to another tree-like structure.

Transformer

The transformer provides methods to transform an AST structure that is generated in the compilation stage into a virtual DOM tree structure. It will be used as input to the diffing process.

Below is the implementation of the method.

You can enter an AST object as an input at the bottom of the widget to run the code.

DetailsTransformer

Press + to interact
index.js
util.js
stdin.js
constants.js
import { Constants } from './constants'
import { run } from "./stdin";
import { stringify, removeWs, generateKey, isAliasObject, isVirtualDomTreeObject } from './util';
// Input example: {"value":{"type":"node","value":["<",[],["d","i","v"],[" "],"/>"]},"cursor":7}
function transform(ast) {
var vdomNode = {};
if (Array.isArray(ast)) {
for (let i = 0; i < ast.length; i++) {
vdomNode = Object.assign(vdomNode, this.generate(ast[i]))
}
} else if (isAliasObject(ast)) {
const type = ast.type;
if (type === Constants.NODE) {
const value = ast.value;
vdomNode.children = null;
vdomNode.attributes = null;
vdomNode.type = stringify(value[2]);
vdomNode.key = generateKey(vdomNode.type);
} else if (type === Constants.NODE_DATA) {
const value = ast.value;
vdomNode.children = null;
vdomNode.type = stringify(value[2]);
vdomNode.key = generateKey(vdomNode.type);
const attributes = value[4].value;
const attributesLength = attributes.length;
if (attributesLength === 0) {
vdomNode.attributes = null;
} else {
vdomNode.attributes = [];
for (let i = 0; i < attributesLength; i++) {
const pair = attributes[i];
var attribute = {};
attribute[pair[0].join('')] = pair[2][1].toString().split(',').join('');
vdomNode.attributes.push(attribute);
}
if (vdomNode.attributes.length === 0) {
vdomNode.attributes = null;
}
}
} else if (type === Constants.NODE_DATA_CHILDREN) {
const value = ast.value;
vdomNode.type = stringify(value[2]);
vdomNode.key = generateKey(vdomNode.type);
const attributes = value[4].value;
const attributesLength = attributes.length;
if (attributesLength === 0) {
vdomNode.attributes = null;
} else {
vdomNode.attributes = [];
for (let i = 0; i < attributesLength; i++) {
const pair = attributes[i];
let attribute = {};
attribute[stringify(pair[0])] = stringify(pair[2][1].toString().split(','));
vdomNode.attributes.push(attribute);
}
if (vdomNode.attributes.length === 0) {
vdomNode.attributes = null;
}
}
const children = value[6];
const childrenLength = children.length;
if (childrenLength === 0) {
vdomNode.children = null;
} else {
vdomNode.children = [];
for (let i = 0; i < childrenLength; i++) {
const child = children[i];
const childGenerated = this.generate(child);
if (isVirtualDomTreeObject(childGenerated) || typeof childGenerated == "string") {
vdomNode.children.push(childGenerated);
}
}
if (vdomNode.children.length === 0) {
vdomNode.children = null;
}
}
} else if (type === Constants.TEXT) {
const text = ast.value;
const textNoWhitespace = removeWs(stringify(text));
if (textNoWhitespace != "") {
return textNoWhitespace;
}
} else if (type === Constants.INTERPOLATION) {
const interpolation = ast.value[1].value;
const interpolationNoWhitespace = removeWs(stringify(interpolation));
if (interpolationNoWhitespace != "") {
return Constants.BRACKET_OPEN + interpolationNoWhitespace + Constants.BRACKET_CLOSE;
}
}
}
return vdomNode;
}
run(transform);

Enter the input below

Virtual DOM

...