mirror of https://github.com/sveltejs/svelte
commit
fc7e6e6827
@ -0,0 +1,2 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
@ -0,0 +1,2 @@
|
|||||||
|
export { default as parse } from './parse/index.js';
|
||||||
|
export { default as generate } from './generate/index.js';
|
@ -0,0 +1,35 @@
|
|||||||
|
import * as assert from 'assert';
|
||||||
|
import parse from './index.js';
|
||||||
|
|
||||||
|
describe( 'parse', () => {
|
||||||
|
it( 'is a function', () => {
|
||||||
|
assert.equal( typeof parse, 'function' );
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'parses a single element', () => {
|
||||||
|
const template = `<span>test</span>`;
|
||||||
|
|
||||||
|
assert.deepEqual( parse( template ), {
|
||||||
|
start: 0,
|
||||||
|
end: 17,
|
||||||
|
type: 'Fragment',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
start: 0,
|
||||||
|
end: 17,
|
||||||
|
type: 'Element',
|
||||||
|
name: 'span',
|
||||||
|
attributes: {},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
start: 6,
|
||||||
|
end: 10,
|
||||||
|
type: 'Text',
|
||||||
|
data: 'test'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,134 @@
|
|||||||
|
import { locate } from 'locate-character';
|
||||||
|
|
||||||
|
const validNameChar = /[a-zA-Z0-9_$]/;
|
||||||
|
|
||||||
|
export default function parse ( template ) {
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
const root = {
|
||||||
|
start: 0,
|
||||||
|
end: template.length,
|
||||||
|
type: 'Fragment',
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const stack = [ root ];
|
||||||
|
let current = root;
|
||||||
|
|
||||||
|
function error ( message ) {
|
||||||
|
const { line, column } = locate( template, i );
|
||||||
|
throw new Error( `${message} (${line}:${column})` );
|
||||||
|
}
|
||||||
|
|
||||||
|
function match ( str ) {
|
||||||
|
return template.slice( i, i + str.length ) === str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fragment () {
|
||||||
|
const char = template[i];
|
||||||
|
|
||||||
|
while ( char === ' ' ) {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( char === '<' ) {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( match( '{{' ) ) {
|
||||||
|
return mustache;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tag () {
|
||||||
|
const start = i++;
|
||||||
|
let char = template[ i ];
|
||||||
|
|
||||||
|
const isClosingTag = char === '/';
|
||||||
|
|
||||||
|
if ( isClosingTag ) {
|
||||||
|
// this is a closing tag
|
||||||
|
i += 1;
|
||||||
|
char = template[ i ];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO handle cases like <li>one<li>two
|
||||||
|
|
||||||
|
let name = '';
|
||||||
|
|
||||||
|
while ( validNameChar.test( char ) ) {
|
||||||
|
name += char;
|
||||||
|
i += 1;
|
||||||
|
char = template[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isClosingTag ) {
|
||||||
|
if ( char !== '>' ) error( `Expected '>'` );
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
current.end = i;
|
||||||
|
stack.pop();
|
||||||
|
current = stack[ stack.length - 1 ];
|
||||||
|
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
const element = {
|
||||||
|
start,
|
||||||
|
end: null, // filled in later
|
||||||
|
type: 'Element',
|
||||||
|
name,
|
||||||
|
attributes: {},
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
|
||||||
|
current.children.push( element );
|
||||||
|
stack.push( element );
|
||||||
|
|
||||||
|
current = element;
|
||||||
|
|
||||||
|
if ( char === '>' ) {
|
||||||
|
i += 1;
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function text () {
|
||||||
|
const start = i;
|
||||||
|
|
||||||
|
let data = '';
|
||||||
|
|
||||||
|
while ( i < template.length && template[i] !== '<' && !match( '{{' ) ) {
|
||||||
|
data += template[ i++ ];
|
||||||
|
}
|
||||||
|
|
||||||
|
current.children.push({
|
||||||
|
start,
|
||||||
|
end: i,
|
||||||
|
type: 'Text',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
function attributes () {
|
||||||
|
const char = template[i];
|
||||||
|
if ( char === '>' ) {
|
||||||
|
i += 1;
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let state = fragment;
|
||||||
|
|
||||||
|
while ( i < template.length ) {
|
||||||
|
state = state();
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
--require reify
|
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "svelte",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "The frameworkless UI framework",
|
||||||
|
"main": "dist/svelte-compiler.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha --opts mocha.opts --recursive ./**/__test__.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://gitlab.com/Rich-Harris/svelte.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"UI",
|
||||||
|
"framework",
|
||||||
|
"templates",
|
||||||
|
"templating"
|
||||||
|
],
|
||||||
|
"author": "Rich Harris",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://gitlab.com/Rich-Harris/svelte/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://gitlab.com/Rich-Harris/svelte#README",
|
||||||
|
"devDependencies": {
|
||||||
|
"mocha": "^3.1.2",
|
||||||
|
"reify": "^0.4.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"locate-character": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue