Merge branch 'master' into gh-40

pull/316/head
Rich Harris 8 years ago
commit 357af90bb5

1
.gitignore vendored

@ -11,3 +11,4 @@ coverage
coverage.lcov
test/sourcemaps/*/output.js
test/sourcemaps/*/output.js.map
_actual.json

@ -1,5 +1,11 @@
# Svelte changelog
## 1.8.0
* Prevent duplicate imports ([#308](https://github.com/sveltejs/svelte/issues/308))
* Use `input` events (not `change`) for all input elements other than `checkbox` and `radio`, and textareas ([#309](https://github.com/sveltejs/svelte/pull/309))
* Encapsulate keyframe declarations ([#245](https://github.com/sveltejs/svelte/issues/245))
## 1.7.1
* Deconflict imports and shared helpers ([#222](https://github.com/sveltejs/svelte/issues/222))

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "1.7.1",
"version": "1.8.0",
"description": "The magical disappearing UI framework",
"main": "compiler/svelte.js",
"files": [

@ -6,6 +6,26 @@ export default function processCss ( parsed, code ) {
const attr = `[svelte-${parsed.hash}]`;
const keyframes = new Map();
function walkKeyframes ( node ) {
if ( node.type === 'Atrule' && node.name.toLowerCase() === 'keyframes' ) {
node.expression.children.forEach( expression => {
if ( expression.type === 'Identifier' ) {
const newName = `svelte-${parsed.hash}-${expression.name}`;
code.overwrite( expression.start, expression.end, newName );
keyframes.set( expression.name, newName );
}
});
} else if ( node.children ) {
node.children.forEach( walkKeyframes );
} else if ( node.block ) {
walkKeyframes( node.block );
}
}
parsed.css.children.forEach( walkKeyframes );
function transform ( rule ) {
rule.selector.children.forEach( selector => {
const start = selector.start - offset;
@ -29,11 +49,29 @@ export default function processCss ( parsed, code ) {
code.overwrite( start + offset, end + offset, transformed );
});
rule.block.children.forEach( block => {
if ( block.type === 'Declaration' ) {
const property = block.property.toLowerCase();
if ( property === 'animation' || property === 'animation-name' ) {
block.value.children.forEach( block => {
if ( block.type === 'Identifier' ) {
const name = block.name;
if ( keyframes.has( name ) ) {
code.overwrite( block.start, block.end, keyframes.get( name ) );
}
}
});
}
}
});
}
function walk ( node ) {
if ( node.type === 'Rule' ) {
transform( node );
} else if ( node.type === 'Atrule' && node.name.toLowerCase() === 'keyframes' ) {
// these have already been processed
} else if ( node.children ) {
node.children.forEach( walk );
} else if ( node.block ) {
@ -53,4 +91,4 @@ export default function processCss ( parsed, code ) {
}
return code.slice( parsed.css.content.start, parsed.css.content.end );
}
}

@ -21,9 +21,46 @@ const specials = {
}
};
// based on http://developers.whatwg.org/syntax.html#syntax-tag-omission
const disallowedContents = {
li: [ 'li' ],
dt: [ 'dt', 'dd' ],
dd: [ 'dt', 'dd' ],
p: 'address article aside blockquote div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol p pre section table ul'.split( ' ' ),
rt: [ 'rt', 'rp' ],
rp: [ 'rt', 'rp' ],
optgroup: [ 'optgroup' ],
option: [ 'option', 'optgroup' ],
thead: [ 'tbody', 'tfoot' ],
tbody: [ 'tbody', 'tfoot' ],
tfoot: [ 'tbody' ],
tr: [ 'tr', 'tbody' ],
td: [ 'td', 'th', 'tr' ],
th: [ 'td', 'th', 'tr' ]
};
function stripWhitespace ( element ) {
if ( element.children.length ) {
const firstChild = element.children[0];
const lastChild = element.children[ element.children.length - 1 ];
if ( firstChild.type === 'Text' ) {
firstChild.data = trimStart( firstChild.data );
if ( !firstChild.data ) element.children.shift();
}
if ( lastChild.type === 'Text' ) {
lastChild.data = trimEnd( lastChild.data );
if ( !lastChild.data ) element.children.pop();
}
}
}
export default function tag ( parser ) {
const start = parser.index++;
let parent = parser.current();
if ( parser.eat( '!--' ) ) {
const data = parser.readUntil( /-->/ );
parser.eat( '-->' );
@ -40,8 +77,6 @@ export default function tag ( parser ) {
const isClosingTag = parser.eat( '/' );
// TODO handle cases like <li>one<li>two
const name = readTagName( parser );
parser.allowWhitespace();
@ -53,28 +88,31 @@ export default function tag ( parser ) {
if ( !parser.eat( '>' ) ) parser.error( `Expected '>'` );
const element = parser.current();
// strip leading/trailing whitespace as necessary
if ( element.children.length ) {
const firstChild = element.children[0];
const lastChild = element.children[ element.children.length - 1 ];
if ( firstChild.type === 'Text' ) {
firstChild.data = trimStart( firstChild.data );
if ( !firstChild.data ) element.children.shift();
}
// close any elements that don't have their own closing tags, e.g. <div><p></div>
while ( parent.name !== name ) {
parent.end = start;
parser.stack.pop();
if ( lastChild.type === 'Text' ) {
lastChild.data = trimEnd( lastChild.data );
if ( !lastChild.data ) element.children.pop();
}
parent = parser.current();
}
element.end = parser.index;
// strip leading/trailing whitespace as necessary
stripWhitespace( parent );
parent.end = parser.index;
parser.stack.pop();
return null;
} else if ( parent.name in disallowedContents ) {
// can this be a child of the parent element, or does it implicitly
// close it, like `<li>one<li>two`?
const disallowed = disallowedContents[ parent.name ];
if ( ~disallowed.indexOf( name ) ) {
stripWhitespace( parent );
parent.end = start;
parser.stack.pop();
}
}
const attributes = [];

@ -16,7 +16,8 @@ describe( 'parse', () => {
const input = fs.readFileSync( `test/parser/${dir}/input.html`, 'utf-8' ).replace( /\s+$/, '' );
try {
const actual = JSON.parse( JSON.stringify( svelte.parse( input ) ) );
const actual = svelte.parse( input );
fs.writeFileSync( `test/parser/${dir}/_actual.json`, JSON.stringify( actual, null, '\t' ) );
const expected = require( `./parser/${dir}/output.json` );
assert.deepEqual( actual.html, expected.html );

@ -0,0 +1,5 @@
<ul>
<li>a
<li>b
<li>c
</ul>

@ -0,0 +1,66 @@
{
"hash": 3806276940,
"html": {
"start": 0,
"end": 31,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 31,
"type": "Element",
"name": "ul",
"attributes": [],
"children": [
{
"start": 6,
"end": 13,
"type": "Element",
"name": "li",
"attributes": [],
"children": [
{
"start": 10,
"end": 13,
"type": "Text",
"data": "a"
}
]
},
{
"start": 13,
"end": 20,
"type": "Element",
"name": "li",
"attributes": [],
"children": [
{
"start": 17,
"end": 20,
"type": "Text",
"data": "b"
}
]
},
{
"start": 20,
"end": 26,
"type": "Element",
"name": "li",
"attributes": [],
"children": [
{
"start": 24,
"end": 26,
"type": "Text",
"data": "c\n"
}
]
}
]
}
]
},
"css": null,
"js": null
}
Loading…
Cancel
Save