diff --git a/src/parse/read/script.ts b/src/parse/read/script.ts index d88c0a822d..e4391e9d3c 100644 --- a/src/parse/read/script.ts +++ b/src/parse/read/script.ts @@ -35,6 +35,8 @@ export default function readScript(parser: Parser, start: number, attributes: No if (!ast.body.length) return null; ast.start = scriptStart; + visitImports(ast, parser); + return { start, end: parser.index, @@ -42,3 +44,120 @@ export default function readScript(parser: Parser, start: number, attributes: No content: ast, }; } + +function visitImports(ast, parser) { + ast.body + .filter(stmt => stmt.type === 'ImportDeclaration') + .forEach((stmt) => { + const m = /[\.\\]?(\w+)\.html$/g.exec(stmt.source.value); + if (m) { + let componentName; + if (stmt.specifiers.length && stmt.specifiers[0].type === 'ImportDefaultSpecifier') { + componentName = stmt.specifiers[0].local.name; + } else { + componentName = m[1]; + stmt.specifiers.push( + { + "type": "ImportDefaultSpecifier", + "start": stmt.start, + "end": stmt.end, + "local": { + "type": "Identifier", + "start": stmt.source.start, + "end": stmt.source.end, + "name": componentName + } + } + ); + } + exportComponent(ast, parser, stmt, componentName); + } + }); +} + +function exportComponent(ast, parser, importStmt, componentName) { + let wasExported = false; + let exportStatement, exportedComponents; + ast.body + .filter(stmt => stmt.type === 'ExportDefaultDeclaration') + .some((stmt) => { + exportStatement = stmt; + stmt.declaration.properties.some((p) => { + const isComponents = p.type === 'Property' && p.key.name === 'components'; + if (isComponents) { + if (p.value.type !== 'ObjectExpression') + parser.error(`export default must have components as an object`); + else { + exportedComponents = p; + wasExported = exportedComponents.value.properties.some(comp => comp.type === 'Property' && comp.key.name === componentName); + } + } + return wasExported; + }); + return wasExported; + }); + if (!wasExported) { + if (!exportStatement) { + exportStatement = { + "type": "ExportDefaultDeclaration", + "start": importStmt.start, + "end": importStmt.end, + "declaration": { + "type": "ObjectExpression", + "start": importStmt.start, + "end": importStmt.end, + "properties": [ + ] + } + }; + ast.body.push(exportStatement); + } + if (!exportedComponents) { + exportedComponents = { + "type": "Property", + "start": exportStatement.start, + "end": exportStatement.end, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": exportStatement.start, + "end": exportStatement.end, + "name": "components" + }, + "value": { + "type": "ObjectExpression", + "start": exportStatement.start, + "end": exportStatement.end, + "properties": [] + }, + "kind": "init" + }; + exportStatement.declaration.properties.push(exportedComponents); + } + exportedComponents.value.properties.push( + { + "type": "Property", + "start": importStmt.start, + "end": importStmt.end, + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "start": importStmt.start, + "end": importStmt.start, + "name": componentName + }, + "kind": "init", + "value": { + "type": "Identifier", + "start": importStmt.start, + "end": importStmt.start, + "name": componentName + } + } + ); + } +} diff --git a/test/hydration/samples/component/Nested.html b/test/hydration/samples/component-legacy-syntax/Nested.html similarity index 100% rename from test/hydration/samples/component/Nested.html rename to test/hydration/samples/component-legacy-syntax/Nested.html diff --git a/test/hydration/samples/component/_after.html b/test/hydration/samples/component-legacy-syntax/_after.html similarity index 100% rename from test/hydration/samples/component/_after.html rename to test/hydration/samples/component-legacy-syntax/_after.html diff --git a/test/hydration/samples/component/_before.html b/test/hydration/samples/component-legacy-syntax/_before.html similarity index 100% rename from test/hydration/samples/component/_before.html rename to test/hydration/samples/component-legacy-syntax/_before.html diff --git a/test/hydration/samples/component/_config.js b/test/hydration/samples/component-legacy-syntax/_config.js similarity index 100% rename from test/hydration/samples/component/_config.js rename to test/hydration/samples/component-legacy-syntax/_config.js diff --git a/test/hydration/samples/component/main.html b/test/hydration/samples/component-legacy-syntax/main.html similarity index 100% rename from test/hydration/samples/component/main.html rename to test/hydration/samples/component-legacy-syntax/main.html diff --git a/test/hydration/samples/component-short-syntax-with-identifier/Nested.html b/test/hydration/samples/component-short-syntax-with-identifier/Nested.html new file mode 100644 index 0000000000..70bf63ad9d --- /dev/null +++ b/test/hydration/samples/component-short-syntax-with-identifier/Nested.html @@ -0,0 +1 @@ +

nested

\ No newline at end of file diff --git a/test/hydration/samples/component-short-syntax-with-identifier/_after.html b/test/hydration/samples/component-short-syntax-with-identifier/_after.html new file mode 100644 index 0000000000..70bf63ad9d --- /dev/null +++ b/test/hydration/samples/component-short-syntax-with-identifier/_after.html @@ -0,0 +1 @@ +

nested

\ No newline at end of file diff --git a/test/hydration/samples/component-short-syntax-with-identifier/_before.html b/test/hydration/samples/component-short-syntax-with-identifier/_before.html new file mode 100644 index 0000000000..70bf63ad9d --- /dev/null +++ b/test/hydration/samples/component-short-syntax-with-identifier/_before.html @@ -0,0 +1 @@ +

nested

\ No newline at end of file diff --git a/test/hydration/samples/component-short-syntax-with-identifier/_config.js b/test/hydration/samples/component-short-syntax-with-identifier/_config.js new file mode 100644 index 0000000000..c26b3c7ad0 --- /dev/null +++ b/test/hydration/samples/component-short-syntax-with-identifier/_config.js @@ -0,0 +1,17 @@ +export default { + snapshot(target) { + const p = target.querySelector('p'); + + return { + p, + text: p.childNodes[0] + }; + }, + + test(assert, target, snapshot) { + const p = target.querySelector('p'); + + assert.equal(p, snapshot.p); + assert.equal(p.childNodes[0], snapshot.text); + } +}; \ No newline at end of file diff --git a/test/hydration/samples/component-short-syntax-with-identifier/main.html b/test/hydration/samples/component-short-syntax-with-identifier/main.html new file mode 100644 index 0000000000..1880564fc3 --- /dev/null +++ b/test/hydration/samples/component-short-syntax-with-identifier/main.html @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/test/hydration/samples/component-short-syntax/Nested.html b/test/hydration/samples/component-short-syntax/Nested.html new file mode 100644 index 0000000000..70bf63ad9d --- /dev/null +++ b/test/hydration/samples/component-short-syntax/Nested.html @@ -0,0 +1 @@ +

nested

\ No newline at end of file diff --git a/test/hydration/samples/component-short-syntax/_after.html b/test/hydration/samples/component-short-syntax/_after.html new file mode 100644 index 0000000000..70bf63ad9d --- /dev/null +++ b/test/hydration/samples/component-short-syntax/_after.html @@ -0,0 +1 @@ +

nested

\ No newline at end of file diff --git a/test/hydration/samples/component-short-syntax/_before.html b/test/hydration/samples/component-short-syntax/_before.html new file mode 100644 index 0000000000..70bf63ad9d --- /dev/null +++ b/test/hydration/samples/component-short-syntax/_before.html @@ -0,0 +1 @@ +

nested

\ No newline at end of file diff --git a/test/hydration/samples/component-short-syntax/_config.js b/test/hydration/samples/component-short-syntax/_config.js new file mode 100644 index 0000000000..c26b3c7ad0 --- /dev/null +++ b/test/hydration/samples/component-short-syntax/_config.js @@ -0,0 +1,17 @@ +export default { + snapshot(target) { + const p = target.querySelector('p'); + + return { + p, + text: p.childNodes[0] + }; + }, + + test(assert, target, snapshot) { + const p = target.querySelector('p'); + + assert.equal(p, snapshot.p); + assert.equal(p.childNodes[0], snapshot.text); + } +}; \ No newline at end of file diff --git a/test/hydration/samples/component-short-syntax/main.html b/test/hydration/samples/component-short-syntax/main.html new file mode 100644 index 0000000000..f4c736e580 --- /dev/null +++ b/test/hydration/samples/component-short-syntax/main.html @@ -0,0 +1,5 @@ + + + \ No newline at end of file