Merge remote-tracking branch 'sveltejs/master'

* sveltejs/master:
  -> v1.0.7
  use decodeCharacterReferences in text.js, not tag.js
  -> v1.0.6
  upgrade magic-string, fix sourcemaps
  add .json extension to the ESLint config file
  add links to gulp/Metalsmith plugins
  more sourcemap stuff
  Convert entities of all text nodes
  add infrastructure for sourcemap tests
  Adding link to Browserify transform
  dont use options.filename for original code when generating magicstring bundle (#43)
pull/7738/head
Fabrice Weinberg 9 years ago
commit 1772050f2e

2
.gitignore vendored

@ -4,3 +4,5 @@ dist
.nyc_output .nyc_output
coverage coverage
coverage.lcov coverage.lcov
test/sourcemaps/*/output.js
test/sourcemaps/*/output.js.map

@ -1,5 +1,13 @@
# Svelte changelog # Svelte changelog
## 1.0.7
* Correctly escape HTML entities ([#85](https://github.com/sveltejs/svelte/issues/85))
## 1.0.6
* Generate useful sourcemaps ([#60](https://github.com/sveltejs/svelte/issues/60))
## 1.0.5 ## 1.0.5
* Ensure compiler only generates ES5 code ([#75](https://github.com/sveltejs/svelte/issues/75)) * Ensure compiler only generates ES5 code ([#75](https://github.com/sveltejs/svelte/issues/75))

@ -8,6 +8,9 @@ This is the Svelte compiler, which is primarily intended for authors of tooling
* [svelte-cli](https://github.com/sveltejs/svelte-cli) Command line interface for compiling components * [svelte-cli](https://github.com/sveltejs/svelte-cli) Command line interface for compiling components
* [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) Rollup plugin * [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) Rollup plugin
* [sveltify](https://github.com/tehshrike/sveltify) - Browserify transform
* [gulp-svelte](https://github.com/shinnn/gulp-svelte) - gulp plugin
* [metalsmith-svelte](https://github.com/shinnn/metalsmith-svelte) - Metalsmith plugin
* More to come! * More to come!

@ -86,7 +86,7 @@ export default function generate ( parsed, source, options ) {
const { name } = flattenReference( node ); const { name } = flattenReference( node );
if ( parent && parent.type === 'CallExpression' && node === parent.callee ) { if ( parent && parent.type === 'CallExpression' && node === parent.callee ) {
if ( generator.helpers[ name ] ) generator.code.insertRight( node.start, `template.helpers.` ); if ( generator.helpers[ name ] ) generator.code.prependRight( node.start, `template.helpers.` );
return; return;
} }
@ -102,7 +102,7 @@ export default function generate ( parsed, source, options ) {
if ( !~usedContexts.indexOf( context ) ) usedContexts.push( context ); if ( !~usedContexts.indexOf( context ) ) usedContexts.push( context );
} else { } else {
dependencies.push( node.name ); dependencies.push( node.name );
generator.code.insertRight( node.start, `root.` ); generator.code.prependRight( node.start, `root.` );
if ( !~usedContexts.indexOf( 'root' ) ) usedContexts.push( 'root' ); if ( !~usedContexts.indexOf( 'root' ) ) usedContexts.push( 'root' );
} }
@ -204,19 +204,19 @@ export default function generate ( parsed, source, options ) {
while ( /\s/.test( source[ i - 1 ] ) ) i--; while ( /\s/.test( source[ i - 1 ] ) ) i--;
const indentation = source.slice( i, defaultExport.start ); const indentation = source.slice( i, defaultExport.start );
generator.code.insertLeft( finalNode.end, `\n\n${indentation}return template;` ); generator.code.appendLeft( finalNode.end, `\n\n${indentation}return template;` );
} }
defaultExport.declaration.properties.forEach( prop => { defaultExport.declaration.properties.forEach( prop => {
templateProperties[ prop.key.name ] = prop.value; templateProperties[ prop.key.name ] = prop.value;
}); });
generator.code.insertRight( parsed.js.content.start, 'var template = (function () {' ); generator.code.prependRight( parsed.js.content.start, 'var template = (function () {' );
} else { } else {
generator.code.insertRight( parsed.js.content.start, '(function () {' ); generator.code.prependRight( parsed.js.content.start, '(function () {' );
} }
generator.code.insertLeft( parsed.js.content.end, '}());' ); generator.code.appendLeft( parsed.js.content.end, '}());' );
[ 'helpers', 'events', 'components' ].forEach( key => { [ 'helpers', 'events', 'components' ].forEach( key => {
if ( templateProperties[ key ] ) { if ( templateProperties[ key ] ) {
@ -508,30 +508,35 @@ export default function generate ( parsed, source, options ) {
function addString ( str ) { function addString ( str ) {
compiled.addSource({ compiled.addSource({
filename: options.filename,
content: new MagicString( str ) content: new MagicString( str )
}); });
} }
addString( getIntro( format, options, imports ) ); const intro = getIntro( format, options, imports );
if ( intro ) addString( intro );
// a filename is necessary for sourcemap generation
const filename = options.filename || 'SvelteComponent.html';
parts.forEach( str => { parts.forEach( str => {
const chunk = str.replace( pattern, '' );
if ( chunk ) addString( chunk );
const match = pattern.exec( str ); const match = pattern.exec( str );
addString( str.replace( pattern, '' ) ); const snippet = generator.code.snip( +match[1], +match[2] );
compiled.addSource({ compiled.addSource({
filename: options.filename, filename,
content: generator.code.snip( +match[1], +match[2] ) content: snippet
}); });
}); });
compiled.append( finalChunk ); addString( finalChunk );
addString( '\n\n' + getOutro( format, constructorName, options, imports ) ); addString( '\n\n' + getOutro( format, constructorName, options, imports ) );
return { return {
code: compiled.toString(), code: compiled.toString(),
map: compiled.generateMap() map: compiled.generateMap({ includeContent: true })
}; };
} }

@ -80,7 +80,7 @@ export default function addComponentAttributes ( generator, node, local ) {
else if ( attribute.type === 'EventHandler' ) { else if ( attribute.type === 'EventHandler' ) {
// TODO verify that it's a valid callee (i.e. built-in or declared method) // TODO verify that it's a valid callee (i.e. built-in or declared method)
generator.addSourcemapLocations( attribute.expression ); generator.addSourcemapLocations( attribute.expression );
generator.code.insertRight( attribute.expression.start, 'component.' ); generator.code.prependRight( attribute.expression.start, 'component.' );
const usedContexts = new Set(); const usedContexts = new Set();
attribute.expression.arguments.forEach( arg => { attribute.expression.arguments.forEach( arg => {

@ -116,7 +116,7 @@ export default function addElementAttributes ( generator, node, local ) {
else if ( attribute.type === 'EventHandler' ) { else if ( attribute.type === 'EventHandler' ) {
// TODO verify that it's a valid callee (i.e. built-in or declared method) // TODO verify that it's a valid callee (i.e. built-in or declared method)
generator.addSourcemapLocations( attribute.expression ); generator.addSourcemapLocations( attribute.expression );
generator.code.insertRight( attribute.expression.start, 'component.' ); generator.code.prependRight( attribute.expression.start, 'component.' );
const usedContexts = new Set(); const usedContexts = new Set();
attribute.expression.arguments.forEach( arg => { attribute.expression.arguments.forEach( arg => {

@ -1,3 +1,5 @@
import { decodeCharacterReferences } from '../utils/html.js';
export default function text ( parser ) { export default function text ( parser ) {
const start = parser.index; const start = parser.index;
@ -11,7 +13,7 @@ export default function text ( parser ) {
start, start,
end: parser.index, end: parser.index,
type: 'Text', type: 'Text',
data data: decodeCharacterReferences( data )
}); });
return null; return null;

@ -1,6 +1,6 @@
{ {
"name": "svelte", "name": "svelte",
"version": "1.0.5", "version": "1.0.7",
"description": "The magical disappearing UI framework", "description": "The magical disappearing UI framework",
"main": "dist/svelte.js", "main": "dist/svelte.js",
"files": [ "files": [
@ -47,7 +47,7 @@
"fuzzyset.js": "0.0.1", "fuzzyset.js": "0.0.1",
"jsdom": "^9.8.3", "jsdom": "^9.8.3",
"locate-character": "^2.0.0", "locate-character": "^2.0.0",
"magic-string": "^0.16.0", "magic-string": "^0.19.0",
"mocha": "^3.1.2", "mocha": "^3.1.2",
"node-resolve": "^1.3.3", "node-resolve": "^1.3.3",
"nyc": "^9.0.1", "nyc": "^9.0.1",
@ -56,6 +56,7 @@
"rollup-plugin-buble": "^0.14.0", "rollup-plugin-buble": "^0.14.0",
"rollup-plugin-commonjs": "^5.0.5", "rollup-plugin-commonjs": "^5.0.5",
"rollup-plugin-node-resolve": "^2.0.0", "rollup-plugin-node-resolve": "^2.0.0",
"source-map": "^0.5.6",
"source-map-support": "^0.4.6" "source-map-support": "^0.4.6"
}, },
"nyc": { "nyc": {

@ -0,0 +1,26 @@
{
"html": {
"start": 0,
"end": 24,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 24,
"type": "Element",
"name": "p",
"attributes": [],
"children": [
{
"start": 3,
"end": 20,
"type": "Text",
"data": "Hello & World"
}
]
}
]
},
"css": null,
"js": null
}

@ -0,0 +1,17 @@
{
"html": {
"start": 0,
"end": 17,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 17,
"type": "Text",
"data": "Hello & World"
}
]
},
"css": null,
"js": null
}

@ -0,0 +1,34 @@
export function test ({ assert, smc, locateInSource, locateInGenerated }) {
const expected = locateInSource( 'foo.bar.baz' );
let loc;
let actual;
loc = locateInGenerated( 'foo.bar.baz' );
actual = smc.originalPositionFor({
line: loc.line + 1,
column: loc.column
});
assert.deepEqual( actual, {
source: 'SvelteComponent.html',
name: null,
line: expected.line + 1,
column: expected.column
});
loc = locateInGenerated( 'foo.bar.baz', loc.character + 1 );
actual = smc.originalPositionFor({
line: loc.line + 1,
column: loc.column
});
assert.deepEqual( actual, {
source: 'SvelteComponent.html',
name: null,
line: expected.line + 1,
column: expected.column
});
}

@ -0,0 +1,9 @@
<div></div>
<script>
export default {
onrender () {
console.log( 42 );
}
}
</script>

@ -0,0 +1,16 @@
export function test ({ assert, smc, locateInSource, locateInGenerated }) {
const expected = locateInSource( '42' );
const loc = locateInGenerated( '42' );
const actual = smc.originalPositionFor({
line: loc.line + 1,
column: loc.column
});
assert.deepEqual( actual, {
source: 'SvelteComponent.html',
name: null,
line: expected.line + 1,
column: expected.column
});
}

@ -5,6 +5,8 @@ import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import jsdom from 'jsdom'; import jsdom from 'jsdom';
import * as acorn from 'acorn'; import * as acorn from 'acorn';
import { SourceMapConsumer } from 'source-map';
import { getLocator } from 'locate-character';
import * as consoleGroup from 'console-group'; import * as consoleGroup from 'console-group';
consoleGroup.install(); consoleGroup.install();
@ -468,4 +470,29 @@ describe( 'svelte', () => {
}); });
}); });
}); });
describe( 'sourcemaps', () => {
fs.readdirSync( 'test/sourcemaps' ).forEach( dir => {
if ( dir[0] === '.' ) return;
const solo = exists( `test/sourcemaps/${dir}/solo` );
( solo ? it.only : it )( dir, () => {
const input = fs.readFileSync( `test/sourcemaps/${dir}/input.html`, 'utf-8' ).replace( /\s+$/, '' );
const { code, map } = svelte.compile( input );
fs.writeFileSync( `test/sourcemaps/${dir}/output.js`, `${code}\n//# sourceMappingURL=output.js.map` );
fs.writeFileSync( `test/sourcemaps/${dir}/output.js.map`, JSON.stringify( map, null, ' ' ) );
const { test } = require( `./sourcemaps/${dir}/test.js` );
const smc = new SourceMapConsumer( map );
const locateInSource = getLocator( input );
const locateInGenerated = getLocator( code );
test({ assert, code, map, smc, locateInSource, locateInGenerated });
});
});
});
}); });

Loading…
Cancel
Save