diff --git a/CHANGELOG.md b/CHANGELOG.md index 57f80501ab..aeb5ea53b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Svelte changelog +## 1.6.7 + +* SSR: Fix apostrophes ([#267](https://github.com/sveltejs/svelte/issues/267)) +* Add `xmlns` attributes to SVGs ([#262](https://github.com/sveltejs/svelte/pull/262)) + +## 1.6.6 + +* Omit text from comment anchors ([#247](https://github.com/sveltejs/svelte/issues/247)) +* Handle `xlink` attributes ([#264](https://github.com/sveltejs/svelte/issues/264)) + +## 1.6.5 + +* Handle `` declarations ([#255](https://github.com/sveltejs/svelte/pull/255)) + +## 1.6.4 + +* Fix updates of yields inside each blocks ([20e1b05](https://github.com/sveltejs/svelte/commit/20e1b05c45dc9fcddfe2e7c5c9fc3109f0d45fa9)) +* SSR: Handle attributes with values that begin with a number ([#248](https://github.com/sveltejs/svelte/issues/248)) +* Handle multiline comments in CSS ([#252](https://github.com/sveltejs/svelte/issues/252)) + ## 1.6.3 * Fix `{{yield}}` bugs for components inside `if` and `each` blocks ([#230](https://github.com/sveltejs/svelte/issues/230), [#231](https://github.com/sveltejs/svelte/issues/231)) diff --git a/package.json b/package.json index 95e2b0b1f3..5997390973 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "1.6.3", + "version": "1.6.7", "description": "The magical disappearing UI framework", "main": "compiler/svelte.js", "files": [ diff --git a/src/generators/dom/index.js b/src/generators/dom/index.js index 929d737700..649252557d 100644 --- a/src/generators/dom/index.js +++ b/src/generators/dom/index.js @@ -98,9 +98,9 @@ class DomGenerator extends Generator { ` ); } - createAnchor ( name, description = '' ) { + createAnchor ( name ) { this.uses.createComment = true; - const renderStatement = `createComment( ${JSON.stringify( description )} )`; + const renderStatement = `createComment()`; this.addElement( name, renderStatement, true ); } @@ -174,11 +174,11 @@ export default function dom ( parsed, source, options, names ) { const builders = { main: new CodeBuilder(), init: new CodeBuilder(), - set: new CodeBuilder() + _set: new CodeBuilder() }; - builders.set.addLine( 'var oldState = this._state;' ); - builders.set.addLine( 'this._state = Object.assign( {}, oldState, newState );' ); + builders._set.addLine( 'var oldState = this._state;' ); + builders._set.addLine( 'this._state = Object.assign( {}, oldState, newState );' ); if ( computations.length ) { const builder = new CodeBuilder(); @@ -197,11 +197,11 @@ export default function dom ( parsed, source, options, names ) { } ` ); - builders.set.addLine( `applyComputations( this._state, newState, oldState )` ); + builders._set.addLine( `applyComputations( this._state, newState, oldState )` ); } // TODO is the `if` necessary? - builders.set.addBlock( deindent` + builders._set.addBlock( deindent` dispatchObservers( this, this._observers.pre, newState, oldState ); if ( this._fragment ) this._fragment.update( newState, this._state ); dispatchObservers( this, this._observers.post, newState, oldState ); @@ -246,7 +246,7 @@ export default function dom ( parsed, source, options, names ) { while ( this._bindings.length ) this._bindings.pop()(); ` ); - builders.set.addLine( `while ( this._bindings.length ) this._bindings.pop()();` ); + builders._set.addLine( `while ( this._bindings.length ) this._bindings.pop()();` ); } else { builders.init.addBlock( deindent` this._fragment = renderMainFragment( this._state, this ); @@ -255,15 +255,10 @@ export default function dom ( parsed, source, options, names ) { } if ( generator.hasComponents ) { - const statement = deindent` - while ( this._renderHooks.length ) { - var hook = this._renderHooks.pop(); - hook.fn.call( hook.context ); - } - `; + const statement = `this._flush();`; builders.init.addBlock( statement ); - builders.set.addBlock( statement ); + builders._set.addBlock( statement ); } if ( templateProperties.onrender ) { @@ -310,6 +305,8 @@ export default function dom ( parsed, source, options, names ) { ${name}.prototype.fire = fire; ${name}.prototype.observe = observe; ${name}.prototype.on = on; + ${name}.prototype.set = set; + ${name}.prototype._flush = _flush; ` : deindent` ${name}.prototype.get = ${shared.get}; @@ -319,11 +316,15 @@ export default function dom ( parsed, source, options, names ) { ${name}.prototype.observe = ${shared.observe}; ${name}.prototype.on = ${shared.on}; + + ${name}.prototype.set = ${shared.set}; + + ${name}.prototype._flush = ${shared._flush}; ` ); builders.main.addBlock( deindent` - ${name}.prototype.set = function set ( newState ) { - ${builders.set} + ${name}.prototype._set = function _set ( newState ) { + ${builders._set} }; ${name}.prototype.teardown = function teardown ( detach ) { @@ -341,7 +342,7 @@ export default function dom ( parsed, source, options, names ) { throw new Error( `Components with shared helpers must be compiled to ES2015 modules (format: 'es')` ); } - const names = [ 'get', 'fire', 'observe', 'on', 'dispatchObservers' ].concat( Object.keys( generator.uses ) ); + const names = [ 'get', 'fire', 'observe', 'on', 'set', '_flush', 'dispatchObservers' ].concat( Object.keys( generator.uses ) ); builders.main.addLineAtStart( `import { ${names.join( ', ' )} } from ${JSON.stringify( sharedPath )}` ); diff --git a/src/generators/dom/visitors/EachBlock.js b/src/generators/dom/visitors/EachBlock.js index 2799a421b8..700e16ef7a 100644 --- a/src/generators/dom/visitors/EachBlock.js +++ b/src/generators/dom/visitors/EachBlock.js @@ -21,7 +21,7 @@ export default { const { dependencies, snippet } = generator.contextualise( node.expression ); const anchor = `${name}_anchor`; - generator.createAnchor( anchor, `#each ${generator.source.slice( node.expression.start, node.expression.end )}` ); + generator.createAnchor( anchor ); generator.current.builders.init.addLine( `var ${name}_value = ${snippet};` ); generator.current.builders.init.addLine( `var ${iterations} = [];` ); diff --git a/src/generators/dom/visitors/IfBlock.js b/src/generators/dom/visitors/IfBlock.js index 02133e539d..5ceb42d48b 100644 --- a/src/generators/dom/visitors/IfBlock.js +++ b/src/generators/dom/visitors/IfBlock.js @@ -41,7 +41,7 @@ export default { const conditionsAndBlocks = getConditionsAndBlocks( generator, node, generator.getUniqueName( `renderIfBlock` ) ); const anchor = `${name}_anchor`; - generator.createAnchor( anchor, `#if ${generator.source.slice( node.expression.start, node.expression.end )}` ); + generator.createAnchor( anchor ); generator.current.builders.init.addBlock( deindent` function ${getBlock} ( ${params} ) { diff --git a/src/generators/dom/visitors/YieldTag.js b/src/generators/dom/visitors/YieldTag.js index 5fefcd73a3..98996486c1 100644 --- a/src/generators/dom/visitors/YieldTag.js +++ b/src/generators/dom/visitors/YieldTag.js @@ -1,7 +1,7 @@ export default { enter ( generator ) { const anchor = `yield_anchor`; - generator.createAnchor( anchor, 'yield' ); + generator.createAnchor( anchor ); generator.current.builders.mount.addLine( `component._yield && component._yield.mount( ${generator.current.target}, ${anchor} );` diff --git a/src/generators/dom/visitors/attributes/addElementAttributes.js b/src/generators/dom/visitors/attributes/addElementAttributes.js index 490d330348..c91d369b6d 100644 --- a/src/generators/dom/visitors/attributes/addElementAttributes.js +++ b/src/generators/dom/visitors/attributes/addElementAttributes.js @@ -5,15 +5,24 @@ import flattenReference from '../../../../utils/flattenReference.js'; export default function addElementAttributes ( generator, node, local ) { node.attributes.forEach( attribute => { + const name = attribute.name; + if ( attribute.type === 'Attribute' ) { - let metadata = local.namespace ? null : attributeLookup[ attribute.name ]; + let metadata = local.namespace ? null : attributeLookup[ name ]; if ( metadata && metadata.appliesTo && !~metadata.appliesTo.indexOf( node.name ) ) metadata = null; let dynamic = false; - const isBoundOptionValue = node.name === 'option' && attribute.name === 'value'; // TODO check it's actually bound + const isBoundOptionValue = node.name === 'option' && name === 'value'; // TODO check it's actually bound const propertyName = isBoundOptionValue ? '__value' : metadata && metadata.propertyName; + const isXlink = name.slice( 0, 6 ) === 'xlink:'; + + // xlink is a special case... we could maybe extend this to generic + // namespaced attributes but I'm not sure that's applicable in + // HTML5? + const helper = isXlink ? 'setXlinkAttribute' : 'setAttribute'; + if ( attribute.value === true ) { // attributes without values, e.g.