diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ae2ebd57f..a45719c283 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Svelte changelog
+## 1.12.1
+
+* Deconflict non-helper functions (`addCss` etc) ([#388](https://github.com/sveltejs/svelte/issues/388))
+* Allow reserved words in tags, e.g. `{{class}}` ([#383](https://github.com/sveltejs/svelte/issues/383))
+
## 1.12.0
* Shorthand attributes — `` is equivalent to `` ([#384](https://github.com/sveltejs/svelte/pull/384))
diff --git a/package.json b/package.json
index d2071c6e29..91073752a7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "svelte",
- "version": "1.12.0",
+ "version": "1.12.1",
"description": "The magical disappearing UI framework",
"main": "compiler/svelte.js",
"files": [
diff --git a/src/generators/Generator.js b/src/generators/Generator.js
index f0571d96c1..469b271f85 100644
--- a/src/generators/Generator.js
+++ b/src/generators/Generator.js
@@ -232,6 +232,7 @@ export default class Generator {
const imports = this.imports;
const computations = [];
+ let defaultExport = null;
const templateProperties = {};
if ( js ) {
@@ -251,7 +252,7 @@ export default class Generator {
}
}
- const defaultExport = js.content.body.find( node => node.type === 'ExportDefaultDeclaration' );
+ defaultExport = js.content.body.find( node => node.type === 'ExportDefaultDeclaration' );
if ( defaultExport ) {
const finalNode = js.content.body[ js.content.body.length - 1 ];
@@ -319,6 +320,7 @@ export default class Generator {
return {
computations,
+ defaultExport,
templateProperties
};
}
diff --git a/src/generators/dom/index.js b/src/generators/dom/index.js
index 406e676e95..ebf478f5a2 100644
--- a/src/generators/dom/index.js
+++ b/src/generators/dom/index.js
@@ -3,6 +3,7 @@ import getBuilders from './utils/getBuilders.js';
import CodeBuilder from '../../utils/CodeBuilder.js';
import namespaces from '../../utils/namespaces.js';
import processCss from '../shared/processCss.js';
+import removeObjectKey from '../../utils/removeObjectKey.js';
import visitors from './visitors/index.js';
import Generator from '../Generator.js';
import * as shared from '../../shared/index.js';
@@ -17,6 +18,8 @@ class DomGenerator extends Generator {
// Svelte's builtin `import { get, ... } from 'svelte/shared.js'`;
this.importedNames = {};
this.aliases = {};
+
+ this.importedComponents = {};
}
addElement ( name, renderStatement, needsIdentifier = false ) {
@@ -138,6 +141,10 @@ class DomGenerator extends Generator {
this.uses[ name ] = true;
+ return this.alias( name );
+ }
+
+ alias ( name ) {
if ( !( name in this.aliases ) ) {
let alias = name;
let i = 1;
@@ -158,7 +165,7 @@ export default function dom ( parsed, source, options, names ) {
const generator = new DomGenerator( parsed, source, name, names, visitors, options );
- const { computations, templateProperties } = generator.parseJs();
+ const { computations, defaultExport, templateProperties } = generator.parseJs();
// Remove these after version 2
if ( templateProperties.onrender ) {
@@ -184,11 +191,33 @@ export default function dom ( parsed, source, options, names ) {
const ns = templateProperties.namespace.value.value;
namespace = namespaces[ ns ] || ns;
- // TODO remove the namespace property from the generated code, it's unused past this point
+ removeObjectKey( generator, defaultExport.declaration, 'namespace' );
+ }
+
+ if ( templateProperties.components ) {
+ let hasNonImportedComponent = false;
+ templateProperties.components.value.properties.forEach( property => {
+ const key = property.key.name;
+ const value = source.slice( property.value.start, property.value.end );
+ if ( generator.importedNames[ value ] ) {
+ generator.importedComponents[ key ] = value;
+ } else {
+ hasNonImportedComponent = true;
+ }
+ });
+ if ( hasNonImportedComponent ) {
+ // remove the specific components which were imported, as we'll refer to them directly
+ Object.keys( generator.importedComponents ).forEach ( key => {
+ removeObjectKey( generator, templateProperties.components.value, key );
+ });
+ } else {
+ // remove the entire components portion of the export
+ removeObjectKey( generator, defaultExport.declaration, 'components' );
+ }
}
generator.push({
- name: 'renderMainFragment',
+ name: generator.alias( 'renderMainFragment' ),
namespace,
target: 'target',
localElementDepth: 0,
@@ -238,12 +267,12 @@ export default function dom ( parsed, source, options, names ) {
});
builders.main.addBlock( deindent`
- function applyComputations ( state, newState, oldState, isInitial ) {
+ function ${generator.alias( 'applyComputations' )} ( state, newState, oldState, isInitial ) {
${builder}
}
` );
- builders._set.addLine( `applyComputations( this._state, newState, oldState, false )` );
+ builders._set.addLine( `${generator.alias( 'applyComputations' )}( this._state, newState, oldState, false )` );
}
// TODO is the `if` necessary?
@@ -259,13 +288,13 @@ export default function dom ( parsed, source, options, names ) {
if ( parsed.css && options.css !== false ) {
builders.main.addBlock( deindent`
- var addedCss = false;
- function addCss () {
+ var ${generator.alias( 'addedCss' )} = false;
+ function ${generator.alias( 'addCss' )} () {
var style = ${generator.helper( 'createElement' )}( 'style' );
style.textContent = ${JSON.stringify( processCss( parsed, generator.code ) )};
${generator.helper( 'appendNode' )}( style, document.head );
- addedCss = true;
+ ${generator.alias( 'addedCss' )} = true;
}
` );
}
@@ -276,7 +305,7 @@ export default function dom ( parsed, source, options, names ) {
builders.init.addLine( `this._torndown = false;` );
if ( parsed.css && options.css !== false ) {
- builders.init.addLine( `if ( !addedCss ) addCss();` );
+ builders.init.addLine( `if ( !${generator.alias( 'addedCss' )} ) ${generator.alias( 'addCss' )}();` );
}
if ( generator.hasComponents ) {
@@ -286,7 +315,7 @@ export default function dom ( parsed, source, options, names ) {
if ( generator.hasComplexBindings ) {
builders.init.addBlock( deindent`
this._bindings = [];
- this._fragment = renderMainFragment( this._state, this );
+ this._fragment = ${generator.alias( 'renderMainFragment' )}( this._state, this );
if ( options.target ) this._fragment.mount( options.target, null );
while ( this._bindings.length ) this._bindings.pop()();
` );
@@ -294,7 +323,7 @@ export default function dom ( parsed, source, options, names ) {
builders._set.addLine( `while ( this._bindings.length ) this._bindings.pop()();` );
} else {
builders.init.addBlock( deindent`
- this._fragment = renderMainFragment( this._state, this );
+ this._fragment = ${generator.alias( 'renderMainFragment' )}( this._state, this );
if ( options.target ) this._fragment.mount( options.target, null );
` );
}
@@ -327,7 +356,7 @@ export default function dom ( parsed, source, options, names ) {
if ( templateProperties.computed ) {
constructorBlock.addLine(
- `applyComputations( this._state, this._state, {}, true );`
+ `${generator.alias( 'applyComputations' )}( this._state, this._state, {}, true );`
);
}
@@ -419,4 +448,4 @@ export default function dom ( parsed, source, options, names ) {
}
return generator.generate( builders.main.toString(), options, { name, format } );
-}
\ No newline at end of file
+}
diff --git a/src/generators/dom/visitors/Component.js b/src/generators/dom/visitors/Component.js
index 990b947f7c..7165a8a7c2 100644
--- a/src/generators/dom/visitors/Component.js
+++ b/src/generators/dom/visitors/Component.js
@@ -106,7 +106,7 @@ export default {
componentInitProperties.push(`data: ${name}_initialData`);
}
- const expression = node.name === ':Self' ? generator.name : `template.components.${node.name}`;
+ const expression = node.name === ':Self' ? generator.name : generator.importedComponents[ node.name ] || `template.components.${node.name}`;
local.init.addBlockAtStart( deindent`
${statements.join( '\n\n' )}
diff --git a/src/utils/removeObjectKey.js b/src/utils/removeObjectKey.js
new file mode 100644
index 0000000000..cbd75eb1f5
--- /dev/null
+++ b/src/utils/removeObjectKey.js
@@ -0,0 +1,9 @@
+export default function removeObjectKey ( generator, node, key ) {
+ if ( node.type !== 'ObjectExpression' ) return;
+ const properties = node.properties;
+ const index = properties.findIndex( property => property.key.type === 'Identifier' && property.key.name === key );
+ if ( index === -1 ) return;
+ const a = properties[ index ].start;
+ const b = index < properties.length - 1 ? properties[ index + 1 ].start : properties[ index ].end;
+ generator.code.remove( a, b );
+}
diff --git a/test/generator/samples/deconflict-non-helpers/_config.js b/test/generator/samples/deconflict-non-helpers/_config.js
new file mode 100644
index 0000000000..978e4c27e3
--- /dev/null
+++ b/test/generator/samples/deconflict-non-helpers/_config.js
@@ -0,0 +1,8 @@
+export default {
+ html: `ABCD`,
+
+ test ( assert, component ) {
+ assert.equal( component.get( 'compute' ), 'ABCD' );
+ component.destroy();
+ }
+};
diff --git a/test/generator/samples/deconflict-non-helpers/main.html b/test/generator/samples/deconflict-non-helpers/main.html
new file mode 100644
index 0000000000..8541b090f9
--- /dev/null
+++ b/test/generator/samples/deconflict-non-helpers/main.html
@@ -0,0 +1,17 @@
+{{compute}}
+
+
diff --git a/test/generator/samples/deconflict-non-helpers/module.js b/test/generator/samples/deconflict-non-helpers/module.js
new file mode 100644
index 0000000000..ff4e71e251
--- /dev/null
+++ b/test/generator/samples/deconflict-non-helpers/module.js
@@ -0,0 +1,4 @@
+export const addCss = 'a';
+export const addedCss = 'b';
+export const applyComputations = 'c';
+export const renderMainFragment = 'd';
diff --git a/test/generator/samples/imported-renamed-components/ComponentOne.html b/test/generator/samples/imported-renamed-components/ComponentOne.html
new file mode 100644
index 0000000000..3609f20ebd
--- /dev/null
+++ b/test/generator/samples/imported-renamed-components/ComponentOne.html
@@ -0,0 +1 @@
+One
diff --git a/test/generator/samples/imported-renamed-components/ComponentTwo.html b/test/generator/samples/imported-renamed-components/ComponentTwo.html
new file mode 100644
index 0000000000..3b0086f91c
--- /dev/null
+++ b/test/generator/samples/imported-renamed-components/ComponentTwo.html
@@ -0,0 +1 @@
+Two
diff --git a/test/generator/samples/imported-renamed-components/_config.js b/test/generator/samples/imported-renamed-components/_config.js
new file mode 100644
index 0000000000..9a9e325b84
--- /dev/null
+++ b/test/generator/samples/imported-renamed-components/_config.js
@@ -0,0 +1,3 @@
+export default {
+ html: `OneTwo`
+};
diff --git a/test/generator/samples/imported-renamed-components/main.html b/test/generator/samples/imported-renamed-components/main.html
new file mode 100644
index 0000000000..7c25eaceab
--- /dev/null
+++ b/test/generator/samples/imported-renamed-components/main.html
@@ -0,0 +1,10 @@
+
+
+