Skip to content

Commit

Permalink
allow using children data and attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
kbrsh committed Jun 16, 2019
1 parent 99b1e6f commit 1354e5e
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 85 deletions.
87 changes: 53 additions & 34 deletions packages/moon/dist/moon.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,14 @@
} else {
// Return a dynamic match if there is a dynamic name or a local.
isStatic = false;
return name[0] === "$" ? name : "md." + name;

if (name[0] === "$") {
return name;
} else if (name === "children") {
return "mc";
} else {
return "md." + name;
}
}
});
return {
Expand Down Expand Up @@ -936,57 +943,69 @@
var attributes = element.attributes;
var prelude = "";
var data = "{";
var children = "[";
var children = "";
var separator = "";

for (var attribute in attributes) {
var attributeValue = attributes[attribute]; // Mark the data as dynamic if there are any dynamic attributes.
var attributeValue = attributes[attribute]; // A `children` attribute takes place of component children.

if (!attributeValue.isStatic) {
staticData = false;
}
if (attribute === "children") {
if (!attributeValue.isStatic) {
staticChildren = false;
}

children = attributeValue.value;
} else {
// Mark the data as dynamic if there are any dynamic attributes.
if (!attributeValue.isStatic) {
staticData = false;
}

data += separator + "\"" + attribute + "\":" + attributeValue.value;
separator = ",";
data += separator + "\"" + attribute + "\":" + attributeValue.value;
separator = ",";
}
}

data += "}"; // Generate children.
data += "}"; // Generate children if they weren't provided in an attribute.

var elementChildren = element.children;
var generateChildren = [];
separator = "";
if (attributes.children === undefined) {
var elementChildren = element.children;
var generateChildren = [];
children += "[";
separator = "";

for (var i = 0; i < elementChildren.length; i++) {
var generateChild = generateNode(elementChildren[i], element, i, variable, staticParts, staticPartsMap); // Mark the children as dynamic if any child is dynamic.
for (var i = 0; i < elementChildren.length; i++) {
var generateChild = generateNode(elementChildren[i], element, i, variable, staticParts, staticPartsMap); // Mark the children as dynamic if any child is dynamic.

if (!generateChild.isStatic) {
staticChildren = false;
} // Update the variable counter.
if (!generateChild.isStatic) {
staticChildren = false;
} // Update the variable counter.


variable = generateChild.variable;
generateChildren.push(generateChild);
}
variable = generateChild.variable;
generateChildren.push(generateChild);
}

for (var _i = 0; _i < generateChildren.length; _i++) {
var _generateChild = generateChildren[_i];
for (var _i = 0; _i < generateChildren.length; _i++) {
var _generateChild = generateChildren[_i];

if (staticChildren || !_generateChild.isStatic) {
// If the children are static or the children and child node are
// dynamic, then append the child as a part of the node as usual.
prelude += _generateChild.prelude;
children += separator + _generateChild.node;
} else {
// If the children are dynamic and the child node is static, then use
// a static node in place of the static child.
children += separator + generateStaticPart(_generateChild.prelude, _generateChild.node, staticParts, staticPartsMap);
if (staticChildren || !_generateChild.isStatic) {
// If the children are static or the children and child node are
// dynamic, then append the child as a part of the node as usual.
prelude += _generateChild.prelude;
children += separator + _generateChild.node;
} else {
// If the children are dynamic and the child node is static, then use
// a static node in place of the static child.
children += separator + generateStaticPart(_generateChild.prelude, _generateChild.node, staticParts, staticPartsMap);
}

separator = ",";
}

separator = ",";
children += "]";
}

children += "]";

if (staticData && !staticChildren) {
// If only the data is static, hoist it out.
data = generateStaticPart("", data, staticParts, staticPartsMap);
Expand Down
2 changes: 1 addition & 1 deletion packages/moon/dist/moon.min.js

Large diffs are not rendered by default.

110 changes: 61 additions & 49 deletions packages/moon/src/compiler/generator/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,72 +39,84 @@ export function generateNode(element, parent, index, variable, staticParts, stat
const attributes = element.attributes;
let prelude = "";
let data = "{";
let children = "[";
let children = "";
let separator = "";

for (const attribute in attributes) {
const attributeValue = attributes[attribute];

// Mark the data as dynamic if there are any dynamic attributes.
if (!attributeValue.isStatic) {
staticData = false;
}

data += `${separator}"${attribute}":${attributeValue.value}`;
separator = ",";
}
// A `children` attribute takes place of component children.
if (attribute === "children") {
if (!attributeValue.isStatic) {
staticChildren = false;
}

data += "}";
children = attributeValue.value;
} else {
// Mark the data as dynamic if there are any dynamic attributes.
if (!attributeValue.isStatic) {
staticData = false;
}

// Generate children.
const elementChildren = element.children;
const generateChildren = [];
separator = "";

for (let i = 0; i < elementChildren.length; i++) {
const generateChild = generateNode(
elementChildren[i],
element,
i,
variable,
staticParts,
staticPartsMap
);

// Mark the children as dynamic if any child is dynamic.
if (!generateChild.isStatic) {
staticChildren = false;
data += `${separator}"${attribute}":${attributeValue.value}`;
separator = ",";
}

// Update the variable counter.
variable = generateChild.variable;

generateChildren.push(generateChild);
}

for (let i = 0; i < generateChildren.length; i++) {
const generateChild = generateChildren[i];
data += "}";

if (staticChildren || !generateChild.isStatic) {
// If the children are static or the children and child node are
// dynamic, then append the child as a part of the node as usual.
prelude += generateChild.prelude;
children += separator + generateChild.node;
} else {
// If the children are dynamic and the child node is static, then use
// a static node in place of the static child.
children += separator + generateStaticPart(
generateChild.prelude,
generateChild.node,
// Generate children if they weren't provided in an attribute.
if (attributes.children === undefined) {
const elementChildren = element.children;
const generateChildren = [];
children += "[";
separator = "";

for (let i = 0; i < elementChildren.length; i++) {
const generateChild = generateNode(
elementChildren[i],
element,
i,
variable,
staticParts,
staticPartsMap
);

// Mark the children as dynamic if any child is dynamic.
if (!generateChild.isStatic) {
staticChildren = false;
}

// Update the variable counter.
variable = generateChild.variable;

generateChildren.push(generateChild);
}

separator = ",";
}
for (let i = 0; i < generateChildren.length; i++) {
const generateChild = generateChildren[i];

if (staticChildren || !generateChild.isStatic) {
// If the children are static or the children and child node are
// dynamic, then append the child as a part of the node as usual.
prelude += generateChild.prelude;
children += separator + generateChild.node;
} else {
// If the children are dynamic and the child node is static, then use
// a static node in place of the static child.
children += separator + generateStaticPart(
generateChild.prelude,
generateChild.node,
staticParts,
staticPartsMap
);
}

separator = ",";
}

children += "]";
children += "]";
}

if (staticData && !staticChildren) {
// If only the data is static, hoist it out.
Expand Down
9 changes: 8 additions & 1 deletion packages/moon/src/compiler/lexer/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,14 @@ function scopeExpression(expression) {
} else {
// Return a dynamic match if there is a dynamic name or a local.
isStatic = false;
return name[0] === "$" ? name : "md." + name;

if (name[0] === "$") {
return name;
} else if (name === "children") {
return "mc";
} else {
return "md." + name;
}
}
});

Expand Down
14 changes: 14 additions & 0 deletions packages/moon/test/compiler/generator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ test("generate dynamic attributes", () => {
);
});

test("generate static children attribute", () => {
assertGenerate(
"<div foo={bar} children={[]}></div>",
"if(ms[0]===undefined){ms[0]=[];}return m(0,\"div\",{\"foo\":md.bar},ms[0]);"
);
});

test("generate dynamic children attribute", () => {
assertGenerate(
"<div children={children}></div>",
"if(ms[0]===undefined){ms[0]={};}return m(0,\"div\",ms[0],mc);"
);
});

test("generate events", () => {
assertGenerate(
"<div><h1 id='bar' class={foo} @click={doSomething}>Test</h1><p>test {message}</p></div>",
Expand Down
4 changes: 4 additions & 0 deletions packages/moon/test/compiler/lexer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ test("lex attributes", () => {
expect(lex(`<div id="test-id" class='test-class' for='input' dynamic={true} local={$local} nested={{foo: {bar: true}, baz: false}} self>`)).toEqual([{"attributes": {"id": {"value": "\"test-id\"", "isStatic": true}, "className": {"value": "'test-class'", "isStatic": true}, "htmlFor": {"value": "'input'", "isStatic": true}, "dynamic": {"value": "true", "isStatic": true}, "local": {"value": "$local", "isStatic": false}, "self": {"value": "true", "isStatic": true}, "nested": {"value": "{foo: {bar: true}, baz: false}", "isStatic": true}}, "closed": false, "type": "tagOpen", "value": "div"}]);
});

test("lex `children` data reference", () => {
expect(lex(`<div data={children}></div>`)).toEqual([{"attributes": {"data": {"isStatic": false, "value": "mc"}}, "closed": false, "type": "tagOpen", "value": "div"}, {"type": "tagClose", "value": "div"}]);
});

test("lex events", () => {
expect(lex(`<div id="test-id" class='test-class' dynamic={true} self @event={doSomething}>`)).toEqual([{"attributes": {"id": {"value": "\"test-id\"", "isStatic": true}, "className": {"value": "'test-class'", "isStatic": true}, dynamic: {"value": "true", "isStatic": true}, "@event": {"value": "[md.doSomething,md,mc]", "isStatic": false}, self: {"value": "true", "isStatic": true}}, "closed": false, "type": "tagOpen", "value": "div"}]);
});
Expand Down

0 comments on commit 1354e5e

Please sign in to comment.