From 5d27d3fda75c45b340c0d892e80ce13220475db2 Mon Sep 17 00:00:00 2001 From: Jacob Mischka Date: Mon, 9 Oct 2017 20:38:26 -0500 Subject: [PATCH 1/3] Add array destructuring for each contexts Fixes #888 --- src/generators/dom/Block.ts | 2 + src/generators/dom/preprocess.ts | 6 ++ src/parse/state/mustache.ts | 25 ++++++- .../each-block-destructured/input.html | 3 + .../each-block-destructured/output.json | 67 +++++++++++++++++++ 5 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 test/parser/samples/each-block-destructured/input.html create mode 100644 test/parser/samples/each-block-destructured/output.json diff --git a/src/generators/dom/Block.ts b/src/generators/dom/Block.ts index 6b696b5ad5..53ae519465 100644 --- a/src/generators/dom/Block.ts +++ b/src/generators/dom/Block.ts @@ -29,6 +29,7 @@ export default class Block { name: string; expression: Node; context: string; + destructuredContexts?: string[]; comment?: string; key: string; @@ -75,6 +76,7 @@ export default class Block { this.name = options.name; this.expression = options.expression; this.context = options.context; + this.destructuredContexts = options.destructuredContexts; this.comment = options.comment; // for keyed each blocks diff --git a/src/generators/dom/preprocess.ts b/src/generators/dom/preprocess.ts index 1ac7098555..9b98539897 100644 --- a/src/generators/dom/preprocess.ts +++ b/src/generators/dom/preprocess.ts @@ -229,6 +229,12 @@ const preprocessors = { const contexts = new Map(block.contexts); contexts.set(node.context, context); + if (node.destructuredContexts) { + for (const i = 0; i < node.destructuredContexts.length; i++) { + contexts.set(node.destructuredContexts[i], `${context}[${i}]`); + } + } + const indexes = new Map(block.indexes); if (node.index) indexes.set(node.index, node.context); diff --git a/src/parse/state/mustache.ts b/src/parse/state/mustache.ts index 6fc842449c..d71642cd1f 100644 --- a/src/parse/state/mustache.ts +++ b/src/parse/state/mustache.ts @@ -161,8 +161,29 @@ export default function mustache(parser: Parser) { parser.eat('as', true); parser.requireWhitespace(); - block.context = parser.read(validIdentifier); // TODO check it's not a keyword - if (!block.context) parser.error(`Expected name`); + if (parser.eat('[')) { + parser.allowWhitespace(); + + block.destructuredContexts = []; + + do { + parser.allowWhitespace(); + const destructuredContext = parser.read(validIdentifier); + if (!destructuredContext) parser.error(`Expected name`); + block.destructuredContexts.push(destructuredContext); + parser.allowWhitespace(); + } while (parser.eat(',')); + + if (!block.destructuredContexts.length) parser.error(`Expected name`); + block.context = block.destructuredContexts.join('_'); + + parser.allowWhitespace(); + parser.eat(']', true); + } else { + block.context = parser.read(validIdentifier); // TODO check it's not a keyword + + if (!block.context) parser.error(`Expected name`); + } parser.allowWhitespace(); diff --git a/test/parser/samples/each-block-destructured/input.html b/test/parser/samples/each-block-destructured/input.html new file mode 100644 index 0000000000..7209f5503d --- /dev/null +++ b/test/parser/samples/each-block-destructured/input.html @@ -0,0 +1,3 @@ +{{#each animals as [key, value]}} +

{{key}}: {{value}}

+{{/each}} diff --git a/test/parser/samples/each-block-destructured/output.json b/test/parser/samples/each-block-destructured/output.json new file mode 100644 index 0000000000..897fec88b8 --- /dev/null +++ b/test/parser/samples/each-block-destructured/output.json @@ -0,0 +1,67 @@ +{ + "hash": 2621498076, + "html": { + "start": 0, + "end": 70, + "type": "Fragment", + "children": [ + { + "start": 0, + "end": 70, + "type": "EachBlock", + "expression": { + "type": "Identifier", + "start": 8, + "end": 15, + "name": "animals" + }, + "children": [ + { + "start": 35, + "end": 60, + "type": "Element", + "name": "p", + "attributes": [], + "children": [ + { + "start": 38, + "end": 45, + "type": "MustacheTag", + "expression": { + "type": "Identifier", + "start": 40, + "end": 43, + "name": "key" + } + }, + { + "start": 45, + "end": 47, + "type": "Text", + "data": ": " + }, + { + "start": 47, + "end": 56, + "type": "MustacheTag", + "expression": { + "type": "Identifier", + "start": 49, + "end": 54, + "name": "value" + } + } + ] + } + ], + "destructuredContexts": [ + "key", + "value" + ], + "context": "key_value" + } + ] + }, + "css": null, + "js": null +} \ No newline at end of file From ffbc9910274b6eab226eb0a20faacf5fcd43843b Mon Sep 17 00:00:00 2001 From: Jacob Mischka Date: Mon, 9 Oct 2017 21:05:59 -0500 Subject: [PATCH 2/3] Add missing runtime test, add contexts to SSR --- .../server-side-rendering/visitors/EachBlock.ts | 6 ++++++ .../each-block-destructured-array/_config.js | 13 +++++++++++++ .../samples/each-block-destructured-array/main.html | 3 +++ 3 files changed, 22 insertions(+) create mode 100644 test/runtime/samples/each-block-destructured-array/_config.js create mode 100644 test/runtime/samples/each-block-destructured-array/main.html diff --git a/src/generators/server-side-rendering/visitors/EachBlock.ts b/src/generators/server-side-rendering/visitors/EachBlock.ts index 10565f6bf2..09342bf26b 100644 --- a/src/generators/server-side-rendering/visitors/EachBlock.ts +++ b/src/generators/server-side-rendering/visitors/EachBlock.ts @@ -18,6 +18,12 @@ export default function visitEachBlock( const contexts = new Map(block.contexts); contexts.set(node.context, node.context); + if (node.destructuredContexts) { + for (const i = 0; i < node.destructuredContexts.length; i++) { + contexts.set(node.destructuredContexts[i], `${node.context}[${i}]`); + } + } + const indexes = new Map(block.indexes); if (node.index) indexes.set(node.index, node.context); diff --git a/test/runtime/samples/each-block-destructured-array/_config.js b/test/runtime/samples/each-block-destructured-array/_config.js new file mode 100644 index 0000000000..ab7bcfe1b7 --- /dev/null +++ b/test/runtime/samples/each-block-destructured-array/_config.js @@ -0,0 +1,13 @@ +export default { + data: { + animalPaws: { + raccoon: 'hands', + eagle: 'wings' + } + }, + + html: ` +

raccoon: hands

+

eagle: wings

+ ` +}; diff --git a/test/runtime/samples/each-block-destructured-array/main.html b/test/runtime/samples/each-block-destructured-array/main.html new file mode 100644 index 0000000000..ec553692c8 --- /dev/null +++ b/test/runtime/samples/each-block-destructured-array/main.html @@ -0,0 +1,3 @@ +{{#each Object.entries(animalPaws) as [animal, pawType]}} +

{{animal}}: {{pawType}}

+{{/each}} From a60a7e6773d3c1fab006f72876dd7ab45507fe1f Mon Sep 17 00:00:00 2001 From: Jacob Mischka Date: Mon, 9 Oct 2017 21:12:21 -0500 Subject: [PATCH 3/3] Remove Object.entries from test --- .../samples/each-block-destructured-array/_config.js | 8 ++++---- .../samples/each-block-destructured-array/main.html | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/runtime/samples/each-block-destructured-array/_config.js b/test/runtime/samples/each-block-destructured-array/_config.js index ab7bcfe1b7..cd29960426 100644 --- a/test/runtime/samples/each-block-destructured-array/_config.js +++ b/test/runtime/samples/each-block-destructured-array/_config.js @@ -1,9 +1,9 @@ export default { data: { - animalPaws: { - raccoon: 'hands', - eagle: 'wings' - } + animalPawsEntries: [ + ['raccoon', 'hands'], + ['eagle', 'wings'] + ] }, html: ` diff --git a/test/runtime/samples/each-block-destructured-array/main.html b/test/runtime/samples/each-block-destructured-array/main.html index ec553692c8..6ee90537ab 100644 --- a/test/runtime/samples/each-block-destructured-array/main.html +++ b/test/runtime/samples/each-block-destructured-array/main.html @@ -1,3 +1,3 @@ -{{#each Object.entries(animalPaws) as [animal, pawType]}} +{{#each animalPawsEntries as [animal, pawType]}}

{{animal}}: {{pawType}}

{{/each}}