mirror of https://github.com/sveltejs/svelte
commit
fe75570b91
@ -1,9 +0,0 @@
|
|||||||
const glob = require( 'glob' );
|
|
||||||
const fs = require( 'fs' );
|
|
||||||
|
|
||||||
glob.sync( 'src/**/*.js' ).forEach( file => {
|
|
||||||
console.log( file );
|
|
||||||
const js = fs.readFileSync( file, 'utf-8' );
|
|
||||||
fs.writeFileSync( file.replace( /\.js$/, '.ts' ), js );
|
|
||||||
fs.unlinkSync( file );
|
|
||||||
});
|
|
||||||
@ -1,39 +1,52 @@
|
|||||||
import deindent from '../../../../utils/deindent.js';
|
import deindent from '../../../../utils/deindent';
|
||||||
import { DomGenerator } from '../../index';
|
import { DomGenerator } from '../../index';
|
||||||
import Block from '../../Block';
|
import Block from '../../Block';
|
||||||
import { Node } from '../../../../interfaces';
|
import { Node } from '../../../../interfaces';
|
||||||
import { State } from '../../interfaces';
|
import { State } from '../../interfaces';
|
||||||
|
|
||||||
export default function visitEventHandler ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node, local ) {
|
export default function visitEventHandler(
|
||||||
|
generator: DomGenerator,
|
||||||
|
block: Block,
|
||||||
|
state: State,
|
||||||
|
node: Node,
|
||||||
|
attribute: Node,
|
||||||
|
local
|
||||||
|
) {
|
||||||
// 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.prependRight( attribute.expression.start, `${block.component}.` );
|
generator.code.prependRight(
|
||||||
|
attribute.expression.start,
|
||||||
|
`${block.component}.`
|
||||||
|
);
|
||||||
|
|
||||||
const usedContexts: string[] = [];
|
const usedContexts: string[] = [];
|
||||||
attribute.expression.arguments.forEach( ( arg: Node ) => {
|
attribute.expression.arguments.forEach((arg: Node) => {
|
||||||
const { contexts } = block.contextualise( arg, null, true );
|
const { contexts } = block.contextualise(arg, null, true);
|
||||||
|
|
||||||
contexts.forEach( context => {
|
contexts.forEach(context => {
|
||||||
if ( !~usedContexts.indexOf( context ) ) usedContexts.push( context );
|
if (!~usedContexts.indexOf(context)) usedContexts.push(context);
|
||||||
if ( !~local.allUsedContexts.indexOf( context ) ) local.allUsedContexts.push( context );
|
if (!~local.allUsedContexts.indexOf(context))
|
||||||
|
local.allUsedContexts.push(context);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO hoist event handlers? can do `this.__component.method(...)`
|
// TODO hoist event handlers? can do `this.__component.method(...)`
|
||||||
const declarations = usedContexts.map( name => {
|
const declarations = usedContexts.map(name => {
|
||||||
if ( name === 'state' ) return 'var state = this._context.state;';
|
if (name === 'state') return 'var state = this._context.state;';
|
||||||
|
|
||||||
const listName = block.listNames.get( name );
|
const listName = block.listNames.get(name);
|
||||||
const indexName = block.indexNames.get( name );
|
const indexName = block.indexNames.get(name);
|
||||||
|
|
||||||
return `var ${listName} = this._context.${listName}, ${indexName} = this._context.${indexName}, ${name} = ${listName}[${indexName}]`;
|
return `var ${listName} = this._context.${listName}, ${indexName} = this._context.${indexName}, ${name} = ${listName}[${indexName}]`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const handlerBody = ( declarations.length ? declarations.join( '\n' ) + '\n\n' : '' ) + `[✂${attribute.expression.start}-${attribute.expression.end}✂];`;
|
const handlerBody =
|
||||||
|
(declarations.length ? declarations.join('\n') + '\n\n' : '') +
|
||||||
|
`[✂${attribute.expression.start}-${attribute.expression.end}✂];`;
|
||||||
|
|
||||||
local.create.addBlock( deindent`
|
local.create.addBlock(deindent`
|
||||||
${local.name}.on( '${attribute.name}', function ( event ) {
|
${local.name}.on( '${attribute.name}', function ( event ) {
|
||||||
${handlerBody}
|
${handlerBody}
|
||||||
});
|
});
|
||||||
` );
|
`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,24 @@
|
|||||||
import deindent from '../../../../utils/deindent.js';
|
import deindent from '../../../../utils/deindent';
|
||||||
import { DomGenerator } from '../../index';
|
import { DomGenerator } from '../../index';
|
||||||
import Block from '../../Block';
|
import Block from '../../Block';
|
||||||
import { Node } from '../../../../interfaces';
|
import { Node } from '../../../../interfaces';
|
||||||
import { State } from '../../interfaces';
|
import { State } from '../../interfaces';
|
||||||
|
|
||||||
export default function visitRef ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node, local ) {
|
export default function visitRef(
|
||||||
|
generator: DomGenerator,
|
||||||
|
block: Block,
|
||||||
|
state: State,
|
||||||
|
node: Node,
|
||||||
|
attribute: Node,
|
||||||
|
local
|
||||||
|
) {
|
||||||
generator.usesRefs = true;
|
generator.usesRefs = true;
|
||||||
|
|
||||||
local.create.addLine(
|
local.create.addLine(
|
||||||
`${block.component}.refs.${attribute.name} = ${local.name};`
|
`${block.component}.refs.${attribute.name} = ${local.name};`
|
||||||
);
|
);
|
||||||
|
|
||||||
block.builders.destroy.addLine( deindent`
|
block.builders.destroy.addLine(deindent`
|
||||||
if ( ${block.component}.refs.${attribute.name} === ${local.name} ) ${block.component}.refs.${attribute.name} = null;
|
if ( ${block.component}.refs.${attribute.name} === ${local.name} ) ${block.component}.refs.${attribute.name} = null;
|
||||||
` );
|
`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,25 @@
|
|||||||
import deindent from '../../../../utils/deindent.js';
|
import deindent from '../../../../utils/deindent';
|
||||||
import { DomGenerator } from '../../index';
|
import { DomGenerator } from '../../index';
|
||||||
import Block from '../../Block';
|
import Block from '../../Block';
|
||||||
import { Node } from '../../../../interfaces';
|
import { Node } from '../../../../interfaces';
|
||||||
import { State } from '../../interfaces';
|
import { State } from '../../interfaces';
|
||||||
|
|
||||||
export default function visitRef ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node ) {
|
export default function visitRef(
|
||||||
|
generator: DomGenerator,
|
||||||
|
block: Block,
|
||||||
|
state: State,
|
||||||
|
node: Node,
|
||||||
|
attribute: Node
|
||||||
|
) {
|
||||||
const name = attribute.name;
|
const name = attribute.name;
|
||||||
|
|
||||||
block.builders.create.addLine(
|
block.builders.create.addLine(
|
||||||
`${block.component}.refs.${name} = ${state.parentNode};`
|
`${block.component}.refs.${name} = ${state.parentNode};`
|
||||||
);
|
);
|
||||||
|
|
||||||
block.builders.destroy.addLine( deindent`
|
block.builders.destroy.addLine(deindent`
|
||||||
if ( ${block.component}.refs.${name} === ${state.parentNode} ) ${block.component}.refs.${name} = null;
|
if ( ${block.component}.refs.${name} === ${state.parentNode} ) ${block.component}.refs.${name} = null;
|
||||||
` );
|
`);
|
||||||
|
|
||||||
generator.usesRefs = true; // so this component.refs object is created
|
generator.usesRefs = true; // so this component.refs object is created
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,80 +1,91 @@
|
|||||||
import deindent from '../../../../utils/deindent.js';
|
import deindent from '../../../../utils/deindent';
|
||||||
import { DomGenerator } from '../../index';
|
import { DomGenerator } from '../../index';
|
||||||
import Block from '../../Block';
|
import Block from '../../Block';
|
||||||
import { Node } from '../../../../interfaces';
|
import { Node } from '../../../../interfaces';
|
||||||
import { State } from '../../interfaces';
|
import { State } from '../../interfaces';
|
||||||
|
|
||||||
export default function addTransitions ( generator: DomGenerator, block: Block, state: State, node: Node, intro, outro ) {
|
export default function addTransitions(
|
||||||
const wrapTransition = generator.helper( 'wrapTransition' );
|
generator: DomGenerator,
|
||||||
|
block: Block,
|
||||||
|
state: State,
|
||||||
|
node: Node,
|
||||||
|
intro,
|
||||||
|
outro
|
||||||
|
) {
|
||||||
|
const wrapTransition = generator.helper('wrapTransition');
|
||||||
|
|
||||||
if ( intro === outro ) {
|
if (intro === outro) {
|
||||||
const name = block.getUniqueName( `${state.name}_transition` );
|
const name = block.getUniqueName(`${state.name}_transition`);
|
||||||
const snippet = intro.expression ? block.contextualise( intro.expression ).snippet : '{}';
|
const snippet = intro.expression
|
||||||
|
? block.contextualise(intro.expression).snippet
|
||||||
|
: '{}';
|
||||||
|
|
||||||
block.addVariable( name );
|
block.addVariable(name);
|
||||||
|
|
||||||
const fn = `${generator.alias( 'template' )}.transitions.${intro.name}`;
|
const fn = `${generator.alias('template')}.transitions.${intro.name}`;
|
||||||
|
|
||||||
block.builders.intro.addBlock( deindent`
|
block.builders.intro.addBlock(deindent`
|
||||||
${block.component}._renderHooks.push( function () {
|
${block.component}._renderHooks.push( function () {
|
||||||
if ( !${name} ) ${name} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
|
if ( !${name} ) ${name} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
|
||||||
${name}.run( true, function () {
|
${name}.run( true, function () {
|
||||||
${block.component}.fire( 'intro.end', { node: ${state.name} });
|
${block.component}.fire( 'intro.end', { node: ${state.name} });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
` );
|
`);
|
||||||
|
|
||||||
block.builders.outro.addBlock( deindent`
|
block.builders.outro.addBlock(deindent`
|
||||||
${name}.run( false, function () {
|
${name}.run( false, function () {
|
||||||
${block.component}.fire( 'outro.end', { node: ${state.name} });
|
${block.component}.fire( 'outro.end', { node: ${state.name} });
|
||||||
if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
|
if ( --${block.alias('outros')} === 0 ) ${block.alias('outrocallback')}();
|
||||||
${name} = null;
|
${name} = null;
|
||||||
});
|
});
|
||||||
` );
|
`);
|
||||||
}
|
} else {
|
||||||
|
const introName = intro && block.getUniqueName(`${state.name}_intro`);
|
||||||
else {
|
const outroName = outro && block.getUniqueName(`${state.name}_outro`);
|
||||||
const introName = intro && block.getUniqueName( `${state.name}_intro` );
|
|
||||||
const outroName = outro && block.getUniqueName( `${state.name}_outro` );
|
|
||||||
|
|
||||||
if ( intro ) {
|
if (intro) {
|
||||||
block.addVariable( introName );
|
block.addVariable(introName);
|
||||||
const snippet = intro.expression ? block.contextualise( intro.expression ).snippet : '{}';
|
const snippet = intro.expression
|
||||||
|
? block.contextualise(intro.expression).snippet
|
||||||
|
: '{}';
|
||||||
|
|
||||||
const fn = `${generator.alias( 'template' )}.transitions.${intro.name}`; // TODO add built-in transitions?
|
const fn = `${generator.alias('template')}.transitions.${intro.name}`; // TODO add built-in transitions?
|
||||||
|
|
||||||
if ( outro ) {
|
if (outro) {
|
||||||
block.builders.intro.addBlock( deindent`
|
block.builders.intro.addBlock(deindent`
|
||||||
if ( ${introName} ) ${introName}.abort();
|
if ( ${introName} ) ${introName}.abort();
|
||||||
if ( ${outroName} ) ${outroName}.abort();
|
if ( ${outroName} ) ${outroName}.abort();
|
||||||
` );
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.builders.intro.addBlock( deindent`
|
block.builders.intro.addBlock(deindent`
|
||||||
${block.component}._renderHooks.push( function () {
|
${block.component}._renderHooks.push( function () {
|
||||||
${introName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
|
${introName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
|
||||||
${introName}.run( true, function () {
|
${introName}.run( true, function () {
|
||||||
${block.component}.fire( 'intro.end', { node: ${state.name} });
|
${block.component}.fire( 'intro.end', { node: ${state.name} });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
` );
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( outro ) {
|
if (outro) {
|
||||||
block.addVariable( outroName );
|
block.addVariable(outroName);
|
||||||
const snippet = outro.expression ? block.contextualise( outro.expression ).snippet : '{}';
|
const snippet = outro.expression
|
||||||
|
? block.contextualise(outro.expression).snippet
|
||||||
|
: '{}';
|
||||||
|
|
||||||
const fn = `${generator.alias( 'template' )}.transitions.${outro.name}`;
|
const fn = `${generator.alias('template')}.transitions.${outro.name}`;
|
||||||
|
|
||||||
// TODO hide elements that have outro'd (unless they belong to a still-outroing
|
// TODO hide elements that have outro'd (unless they belong to a still-outroing
|
||||||
// group) prior to their removal from the DOM
|
// group) prior to their removal from the DOM
|
||||||
block.builders.outro.addBlock( deindent`
|
block.builders.outro.addBlock(deindent`
|
||||||
${outroName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, false, null );
|
${outroName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, false, null );
|
||||||
${outroName}.run( false, function () {
|
${outroName}.run( false, function () {
|
||||||
${block.component}.fire( 'outro.end', { node: ${state.name} });
|
${block.component}.fire( 'outro.end', { node: ${state.name} });
|
||||||
if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
|
if ( --${block.alias('outros')} === 0 ) ${block.alias('outrocallback')}();
|
||||||
});
|
});
|
||||||
` );
|
`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
import { Node } from '../../../../interfaces';
|
import { Node } from '../../../../interfaces';
|
||||||
|
|
||||||
export default function getStaticAttributeValue ( node: Node, name: string ) {
|
export default function getStaticAttributeValue(node: Node, name: string) {
|
||||||
const attribute = node.attributes.find( ( attr: Node ) => attr.name.toLowerCase() === name );
|
const attribute = node.attributes.find(
|
||||||
if ( !attribute ) return null;
|
(attr: Node) => attr.name.toLowerCase() === name
|
||||||
|
);
|
||||||
|
if (!attribute) return null;
|
||||||
|
|
||||||
if ( attribute.value.length !== 1 || attribute.value[0].type !== 'Text' ) {
|
if (attribute.value.length !== 1 || attribute.value[0].type !== 'Text') {
|
||||||
// TODO catch this in validation phase, give a more useful error (with location etc)
|
// TODO catch this in validation phase, give a more useful error (with location etc)
|
||||||
throw new Error( `'${name} must be a static attribute` );
|
throw new Error(`'${name} must be a static attribute`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return attribute.value[0].data;
|
return attribute.value[0].data;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,122 +1,235 @@
|
|||||||
// source: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
|
// source: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
|
||||||
const lookup = {
|
const lookup = {
|
||||||
accept: { appliesTo: [ 'form', 'input' ] },
|
accept: { appliesTo: ['form', 'input'] },
|
||||||
'accept-charset': { propertyName: 'acceptCharset', appliesTo: [ 'form' ] },
|
'accept-charset': { propertyName: 'acceptCharset', appliesTo: ['form'] },
|
||||||
accesskey: { propertyName: 'accessKey' },
|
accesskey: { propertyName: 'accessKey' },
|
||||||
action: { appliesTo: [ 'form' ] },
|
action: { appliesTo: ['form'] },
|
||||||
align: { appliesTo: [ 'applet', 'caption', 'col', 'colgroup', 'hr', 'iframe', 'img', 'table', 'tbody', 'td', 'tfoot' , 'th', 'thead', 'tr' ] },
|
align: {
|
||||||
allowfullscreen: { propertyName: 'allowFullscreen', appliesTo: [ 'iframe' ] },
|
appliesTo: [
|
||||||
alt: { appliesTo: [ 'applet', 'area', 'img', 'input' ] },
|
'applet',
|
||||||
async: { appliesTo: [ 'script' ] },
|
'caption',
|
||||||
autocomplete: { appliesTo: [ 'form', 'input' ] },
|
'col',
|
||||||
autofocus: { appliesTo: [ 'button', 'input', 'keygen', 'select', 'textarea' ] },
|
'colgroup',
|
||||||
autoplay: { appliesTo: [ 'audio', 'video' ] },
|
'hr',
|
||||||
autosave: { appliesTo: [ 'input' ] },
|
'iframe',
|
||||||
bgcolor: { propertyName: 'bgColor', appliesTo: [ 'body', 'col', 'colgroup', 'marquee', 'table', 'tbody', 'tfoot', 'td', 'th', 'tr' ] },
|
'img',
|
||||||
border: { appliesTo: [ 'img', 'object', 'table' ] },
|
'table',
|
||||||
buffered: { appliesTo: [ 'audio', 'video' ] },
|
'tbody',
|
||||||
challenge: { appliesTo: [ 'keygen' ] },
|
'td',
|
||||||
charset: { appliesTo: [ 'meta', 'script' ] },
|
'tfoot',
|
||||||
checked: { appliesTo: [ 'command', 'input' ] },
|
'th',
|
||||||
cite: { appliesTo: [ 'blockquote', 'del', 'ins', 'q' ] },
|
'thead',
|
||||||
|
'tr',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
allowfullscreen: { propertyName: 'allowFullscreen', appliesTo: ['iframe'] },
|
||||||
|
alt: { appliesTo: ['applet', 'area', 'img', 'input'] },
|
||||||
|
async: { appliesTo: ['script'] },
|
||||||
|
autocomplete: { appliesTo: ['form', 'input'] },
|
||||||
|
autofocus: { appliesTo: ['button', 'input', 'keygen', 'select', 'textarea'] },
|
||||||
|
autoplay: { appliesTo: ['audio', 'video'] },
|
||||||
|
autosave: { appliesTo: ['input'] },
|
||||||
|
bgcolor: {
|
||||||
|
propertyName: 'bgColor',
|
||||||
|
appliesTo: [
|
||||||
|
'body',
|
||||||
|
'col',
|
||||||
|
'colgroup',
|
||||||
|
'marquee',
|
||||||
|
'table',
|
||||||
|
'tbody',
|
||||||
|
'tfoot',
|
||||||
|
'td',
|
||||||
|
'th',
|
||||||
|
'tr',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
border: { appliesTo: ['img', 'object', 'table'] },
|
||||||
|
buffered: { appliesTo: ['audio', 'video'] },
|
||||||
|
challenge: { appliesTo: ['keygen'] },
|
||||||
|
charset: { appliesTo: ['meta', 'script'] },
|
||||||
|
checked: { appliesTo: ['command', 'input'] },
|
||||||
|
cite: { appliesTo: ['blockquote', 'del', 'ins', 'q'] },
|
||||||
class: { propertyName: 'className' },
|
class: { propertyName: 'className' },
|
||||||
code: { appliesTo: [ 'applet' ] },
|
code: { appliesTo: ['applet'] },
|
||||||
codebase: { propertyName: 'codeBase', appliesTo: [ 'applet' ] },
|
codebase: { propertyName: 'codeBase', appliesTo: ['applet'] },
|
||||||
color: { appliesTo: [ 'basefont', 'font', 'hr' ] },
|
color: { appliesTo: ['basefont', 'font', 'hr'] },
|
||||||
cols: { appliesTo: [ 'textarea' ] },
|
cols: { appliesTo: ['textarea'] },
|
||||||
colspan: { propertyName: 'colSpan', appliesTo: [ 'td', 'th' ] },
|
colspan: { propertyName: 'colSpan', appliesTo: ['td', 'th'] },
|
||||||
content: { appliesTo: [ 'meta' ] },
|
content: { appliesTo: ['meta'] },
|
||||||
contenteditable: { propertyName: 'contentEditable' },
|
contenteditable: { propertyName: 'contentEditable' },
|
||||||
contextmenu: {},
|
contextmenu: {},
|
||||||
controls: { appliesTo: [ 'audio', 'video' ] },
|
controls: { appliesTo: ['audio', 'video'] },
|
||||||
coords: { appliesTo: [ 'area' ] },
|
coords: { appliesTo: ['area'] },
|
||||||
data: { appliesTo: [ 'object' ] },
|
data: { appliesTo: ['object'] },
|
||||||
datetime: { propertyName: 'dateTime', appliesTo: [ 'del', 'ins', 'time' ] },
|
datetime: { propertyName: 'dateTime', appliesTo: ['del', 'ins', 'time'] },
|
||||||
default: { appliesTo: [ 'track' ] },
|
default: { appliesTo: ['track'] },
|
||||||
defer: { appliesTo: [ 'script' ] },
|
defer: { appliesTo: ['script'] },
|
||||||
dir: {},
|
dir: {},
|
||||||
dirname: { propertyName: 'dirName', appliesTo: [ 'input', 'textarea' ] },
|
dirname: { propertyName: 'dirName', appliesTo: ['input', 'textarea'] },
|
||||||
disabled: { appliesTo: [ 'button', 'command', 'fieldset', 'input', 'keygen', 'optgroup', 'option', 'select', 'textarea' ] },
|
disabled: {
|
||||||
download: { appliesTo: [ 'a', 'area' ] },
|
appliesTo: [
|
||||||
|
'button',
|
||||||
|
'command',
|
||||||
|
'fieldset',
|
||||||
|
'input',
|
||||||
|
'keygen',
|
||||||
|
'optgroup',
|
||||||
|
'option',
|
||||||
|
'select',
|
||||||
|
'textarea',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
download: { appliesTo: ['a', 'area'] },
|
||||||
draggable: {},
|
draggable: {},
|
||||||
dropzone: {},
|
dropzone: {},
|
||||||
enctype: { appliesTo: [ 'form' ] },
|
enctype: { appliesTo: ['form'] },
|
||||||
for: { propertyName: 'htmlFor', appliesTo: [ 'label', 'output' ] },
|
for: { propertyName: 'htmlFor', appliesTo: ['label', 'output'] },
|
||||||
form: { appliesTo: [ 'button', 'fieldset', 'input', 'keygen', 'label', 'meter', 'object', 'output', 'progress', 'select', 'textarea' ] },
|
form: {
|
||||||
formaction: { appliesTo: [ 'input', 'button' ] },
|
appliesTo: [
|
||||||
headers: { appliesTo: [ 'td', 'th' ] },
|
'button',
|
||||||
height: { appliesTo: [ 'canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video' ] },
|
'fieldset',
|
||||||
|
'input',
|
||||||
|
'keygen',
|
||||||
|
'label',
|
||||||
|
'meter',
|
||||||
|
'object',
|
||||||
|
'output',
|
||||||
|
'progress',
|
||||||
|
'select',
|
||||||
|
'textarea',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
formaction: { appliesTo: ['input', 'button'] },
|
||||||
|
headers: { appliesTo: ['td', 'th'] },
|
||||||
|
height: {
|
||||||
|
appliesTo: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video'],
|
||||||
|
},
|
||||||
hidden: {},
|
hidden: {},
|
||||||
high: { appliesTo: [ 'meter' ] },
|
high: { appliesTo: ['meter'] },
|
||||||
href: { appliesTo: [ 'a', 'area', 'base', 'link' ] },
|
href: { appliesTo: ['a', 'area', 'base', 'link'] },
|
||||||
hreflang: { appliesTo: [ 'a', 'area', 'link' ] },
|
hreflang: { appliesTo: ['a', 'area', 'link'] },
|
||||||
'http-equiv': { propertyName: 'httpEquiv', appliesTo: [ 'meta' ] },
|
'http-equiv': { propertyName: 'httpEquiv', appliesTo: ['meta'] },
|
||||||
icon: { appliesTo: [ 'command' ] },
|
icon: { appliesTo: ['command'] },
|
||||||
id: {},
|
id: {},
|
||||||
ismap: { propertyName: 'isMap', appliesTo: [ 'img' ] },
|
ismap: { propertyName: 'isMap', appliesTo: ['img'] },
|
||||||
itemprop: {},
|
itemprop: {},
|
||||||
keytype: { appliesTo: [ 'keygen' ] },
|
keytype: { appliesTo: ['keygen'] },
|
||||||
kind: { appliesTo: [ 'track' ] },
|
kind: { appliesTo: ['track'] },
|
||||||
label: { appliesTo: [ 'track' ] },
|
label: { appliesTo: ['track'] },
|
||||||
lang: {},
|
lang: {},
|
||||||
language: { appliesTo: [ 'script' ] },
|
language: { appliesTo: ['script'] },
|
||||||
loop: { appliesTo: [ 'audio', 'bgsound', 'marquee', 'video' ] },
|
loop: { appliesTo: ['audio', 'bgsound', 'marquee', 'video'] },
|
||||||
low: { appliesTo: [ 'meter' ] },
|
low: { appliesTo: ['meter'] },
|
||||||
manifest: { appliesTo: [ 'html' ] },
|
manifest: { appliesTo: ['html'] },
|
||||||
max: { appliesTo: [ 'input', 'meter', 'progress' ] },
|
max: { appliesTo: ['input', 'meter', 'progress'] },
|
||||||
maxlength: { propertyName: 'maxLength', appliesTo: [ 'input', 'textarea' ] },
|
maxlength: { propertyName: 'maxLength', appliesTo: ['input', 'textarea'] },
|
||||||
media: { appliesTo: [ 'a', 'area', 'link', 'source', 'style' ] },
|
media: { appliesTo: ['a', 'area', 'link', 'source', 'style'] },
|
||||||
method: { appliesTo: [ 'form' ] },
|
method: { appliesTo: ['form'] },
|
||||||
min: { appliesTo: [ 'input', 'meter' ] },
|
min: { appliesTo: ['input', 'meter'] },
|
||||||
multiple: { appliesTo: [ 'input', 'select' ] },
|
multiple: { appliesTo: ['input', 'select'] },
|
||||||
muted: { appliesTo: [ 'video' ] },
|
muted: { appliesTo: ['video'] },
|
||||||
name: { appliesTo: [ 'button', 'form', 'fieldset', 'iframe', 'input', 'keygen', 'object', 'output', 'select', 'textarea', 'map', 'meta', 'param' ] },
|
name: {
|
||||||
novalidate: { propertyName: 'noValidate', appliesTo: [ 'form' ] },
|
appliesTo: [
|
||||||
open: { appliesTo: [ 'details' ] },
|
'button',
|
||||||
optimum: { appliesTo: [ 'meter' ] },
|
'form',
|
||||||
pattern: { appliesTo: [ 'input' ] },
|
'fieldset',
|
||||||
ping: { appliesTo: [ 'a', 'area' ] },
|
'iframe',
|
||||||
placeholder: { appliesTo: [ 'input', 'textarea' ] },
|
'input',
|
||||||
poster: { appliesTo: [ 'video' ] },
|
'keygen',
|
||||||
preload: { appliesTo: [ 'audio', 'video' ] },
|
'object',
|
||||||
radiogroup: { appliesTo: [ 'command' ] },
|
'output',
|
||||||
readonly: { propertyName: 'readOnly', appliesTo: [ 'input', 'textarea' ] },
|
'select',
|
||||||
rel: { appliesTo: [ 'a', 'area', 'link' ] },
|
'textarea',
|
||||||
required: { appliesTo: [ 'input', 'select', 'textarea' ] },
|
'map',
|
||||||
reversed: { appliesTo: [ 'ol' ] },
|
'meta',
|
||||||
rows: { appliesTo: [ 'textarea' ] },
|
'param',
|
||||||
rowspan: { propertyName: 'rowSpan', appliesTo: [ 'td', 'th' ] },
|
],
|
||||||
sandbox: { appliesTo: [ 'iframe' ] },
|
},
|
||||||
scope: { appliesTo: [ 'th' ] },
|
novalidate: { propertyName: 'noValidate', appliesTo: ['form'] },
|
||||||
scoped: { appliesTo: [ 'style' ] },
|
open: { appliesTo: ['details'] },
|
||||||
seamless: { appliesTo: [ 'iframe' ] },
|
optimum: { appliesTo: ['meter'] },
|
||||||
selected: { appliesTo: [ 'option' ] },
|
pattern: { appliesTo: ['input'] },
|
||||||
shape: { appliesTo: [ 'a', 'area' ] },
|
ping: { appliesTo: ['a', 'area'] },
|
||||||
size: { appliesTo: [ 'input', 'select' ] },
|
placeholder: { appliesTo: ['input', 'textarea'] },
|
||||||
sizes: { appliesTo: [ 'link', 'img', 'source' ] },
|
poster: { appliesTo: ['video'] },
|
||||||
span: { appliesTo: [ 'col', 'colgroup' ] },
|
preload: { appliesTo: ['audio', 'video'] },
|
||||||
|
radiogroup: { appliesTo: ['command'] },
|
||||||
|
readonly: { propertyName: 'readOnly', appliesTo: ['input', 'textarea'] },
|
||||||
|
rel: { appliesTo: ['a', 'area', 'link'] },
|
||||||
|
required: { appliesTo: ['input', 'select', 'textarea'] },
|
||||||
|
reversed: { appliesTo: ['ol'] },
|
||||||
|
rows: { appliesTo: ['textarea'] },
|
||||||
|
rowspan: { propertyName: 'rowSpan', appliesTo: ['td', 'th'] },
|
||||||
|
sandbox: { appliesTo: ['iframe'] },
|
||||||
|
scope: { appliesTo: ['th'] },
|
||||||
|
scoped: { appliesTo: ['style'] },
|
||||||
|
seamless: { appliesTo: ['iframe'] },
|
||||||
|
selected: { appliesTo: ['option'] },
|
||||||
|
shape: { appliesTo: ['a', 'area'] },
|
||||||
|
size: { appliesTo: ['input', 'select'] },
|
||||||
|
sizes: { appliesTo: ['link', 'img', 'source'] },
|
||||||
|
span: { appliesTo: ['col', 'colgroup'] },
|
||||||
spellcheck: {},
|
spellcheck: {},
|
||||||
src: { appliesTo: [ 'audio', 'embed', 'iframe', 'img', 'input', 'script', 'source', 'track', 'video' ] },
|
src: {
|
||||||
srcdoc: { appliesTo: [ 'iframe' ] },
|
appliesTo: [
|
||||||
srclang: { appliesTo: [ 'track' ] },
|
'audio',
|
||||||
srcset: { appliesTo: [ 'img' ] },
|
'embed',
|
||||||
start: { appliesTo: [ 'ol' ] },
|
'iframe',
|
||||||
step: { appliesTo: [ 'input' ] },
|
'img',
|
||||||
|
'input',
|
||||||
|
'script',
|
||||||
|
'source',
|
||||||
|
'track',
|
||||||
|
'video',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
srcdoc: { appliesTo: ['iframe'] },
|
||||||
|
srclang: { appliesTo: ['track'] },
|
||||||
|
srcset: { appliesTo: ['img'] },
|
||||||
|
start: { appliesTo: ['ol'] },
|
||||||
|
step: { appliesTo: ['input'] },
|
||||||
style: { propertyName: 'style.cssText' },
|
style: { propertyName: 'style.cssText' },
|
||||||
summary: { appliesTo: [ 'table' ] },
|
summary: { appliesTo: ['table'] },
|
||||||
tabindex: { propertyName: 'tabIndex' },
|
tabindex: { propertyName: 'tabIndex' },
|
||||||
target: { appliesTo: [ 'a', 'area', 'base', 'form' ] },
|
target: { appliesTo: ['a', 'area', 'base', 'form'] },
|
||||||
title: {},
|
title: {},
|
||||||
type: { appliesTo: [ 'button', 'input', 'command', 'embed', 'object', 'script', 'source', 'style', 'menu' ] },
|
type: {
|
||||||
usemap: { propertyName: 'useMap', appliesTo: [ 'img', 'input', 'object' ] },
|
appliesTo: [
|
||||||
value: { appliesTo: [ 'button', 'option', 'input', 'li', 'meter', 'progress', 'param', 'select', 'textarea' ] },
|
'button',
|
||||||
width: { appliesTo: [ 'canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video' ] },
|
'input',
|
||||||
wrap: { appliesTo: [ 'textarea' ] }
|
'command',
|
||||||
|
'embed',
|
||||||
|
'object',
|
||||||
|
'script',
|
||||||
|
'source',
|
||||||
|
'style',
|
||||||
|
'menu',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
usemap: { propertyName: 'useMap', appliesTo: ['img', 'input', 'object'] },
|
||||||
|
value: {
|
||||||
|
appliesTo: [
|
||||||
|
'button',
|
||||||
|
'option',
|
||||||
|
'input',
|
||||||
|
'li',
|
||||||
|
'meter',
|
||||||
|
'progress',
|
||||||
|
'param',
|
||||||
|
'select',
|
||||||
|
'textarea',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
appliesTo: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video'],
|
||||||
|
},
|
||||||
|
wrap: { appliesTo: ['textarea'] },
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.keys( lookup ).forEach( name => {
|
Object.keys(lookup).forEach(name => {
|
||||||
const metadata = lookup[ name ];
|
const metadata = lookup[name];
|
||||||
if ( !metadata.propertyName ) metadata.propertyName = name;
|
if (!metadata.propertyName) metadata.propertyName = name;
|
||||||
});
|
});
|
||||||
|
|
||||||
export default lookup;
|
export default lookup;
|
||||||
|
|||||||
@ -1,21 +1,31 @@
|
|||||||
import deindent from '../../../utils/deindent.js';
|
import deindent from '../../../utils/deindent';
|
||||||
import { DomGenerator } from '../index';
|
import { DomGenerator } from '../index';
|
||||||
import Block from '../Block';
|
import Block from '../Block';
|
||||||
import { Node } from '../../../interfaces';
|
import { Node } from '../../../interfaces';
|
||||||
import { State } from '../interfaces';
|
import { State } from '../interfaces';
|
||||||
|
|
||||||
export default function visitMustacheTag ( generator: DomGenerator, block: Block, state: State, node: Node ) {
|
export default function visitMustacheTag(
|
||||||
|
generator: DomGenerator,
|
||||||
|
block: Block,
|
||||||
|
state: State,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const name = node._state.name;
|
const name = node._state.name;
|
||||||
const value = block.getUniqueName( `${name}_value` );
|
const value = block.getUniqueName(`${name}_value`);
|
||||||
|
|
||||||
const { snippet } = block.contextualise( node.expression );
|
const { snippet } = block.contextualise(node.expression);
|
||||||
|
|
||||||
block.addVariable( value );
|
block.addVariable(value);
|
||||||
block.addElement( name, `${generator.helper( 'createText' )}( ${value} = ${snippet} )`, state.parentNode, true );
|
block.addElement(
|
||||||
|
name,
|
||||||
|
`${generator.helper('createText')}( ${value} = ${snippet} )`,
|
||||||
|
state.parentNode,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
block.builders.update.addBlock( deindent`
|
block.builders.update.addBlock(deindent`
|
||||||
if ( ${value} !== ( ${value} = ${snippet} ) ) {
|
if ( ${value} !== ( ${value} = ${snippet} ) ) {
|
||||||
${name}.data = ${value};
|
${name}.data = ${value};
|
||||||
}
|
}
|
||||||
` );
|
`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,40 +1,57 @@
|
|||||||
import deindent from '../../../utils/deindent.js';
|
import deindent from '../../../utils/deindent';
|
||||||
import { DomGenerator } from '../index';
|
import { DomGenerator } from '../index';
|
||||||
import Block from '../Block';
|
import Block from '../Block';
|
||||||
import { Node } from '../../../interfaces';
|
import { Node } from '../../../interfaces';
|
||||||
import { State } from '../interfaces';
|
import { State } from '../interfaces';
|
||||||
|
|
||||||
export default function visitRawMustacheTag ( generator: DomGenerator, block: Block, state: State, node: Node ) {
|
export default function visitRawMustacheTag(
|
||||||
|
generator: DomGenerator,
|
||||||
|
block: Block,
|
||||||
|
state: State,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const name = node._state.basename;
|
const name = node._state.basename;
|
||||||
const before = node._state.name;
|
const before = node._state.name;
|
||||||
const value = block.getUniqueName( `${name}_value` );
|
const value = block.getUniqueName(`${name}_value`);
|
||||||
const after = block.getUniqueName( `${name}_after` );
|
const after = block.getUniqueName(`${name}_after`);
|
||||||
|
|
||||||
const { snippet } = block.contextualise( node.expression );
|
const { snippet } = block.contextualise(node.expression);
|
||||||
|
|
||||||
// we would have used comments here, but the `insertAdjacentHTML` api only
|
// we would have used comments here, but the `insertAdjacentHTML` api only
|
||||||
// exists for `Element`s.
|
// exists for `Element`s.
|
||||||
block.addElement( before, `${generator.helper( 'createElement' )}( 'noscript' )`, state.parentNode, true );
|
block.addElement(
|
||||||
block.addElement( after, `${generator.helper( 'createElement' )}( 'noscript' )`, state.parentNode, true );
|
before,
|
||||||
|
`${generator.helper('createElement')}( 'noscript' )`,
|
||||||
|
state.parentNode,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
block.addElement(
|
||||||
|
after,
|
||||||
|
`${generator.helper('createElement')}( 'noscript' )`,
|
||||||
|
state.parentNode,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
const isToplevel = !state.parentNode;
|
const isToplevel = !state.parentNode;
|
||||||
|
|
||||||
block.builders.create.addLine( `var ${value} = ${snippet};` );
|
block.builders.create.addLine(`var ${value} = ${snippet};`);
|
||||||
const mountStatement = `${before}.insertAdjacentHTML( 'afterend', ${value} );`;
|
const mountStatement = `${before}.insertAdjacentHTML( 'afterend', ${value} );`;
|
||||||
const detachStatement = `${generator.helper( 'detachBetween' )}( ${before}, ${after} );`;
|
const detachStatement = `${generator.helper(
|
||||||
|
'detachBetween'
|
||||||
|
)}( ${before}, ${after} );`;
|
||||||
|
|
||||||
if ( isToplevel ) {
|
if (isToplevel) {
|
||||||
block.builders.mount.addLine( mountStatement );
|
block.builders.mount.addLine(mountStatement);
|
||||||
} else {
|
} else {
|
||||||
block.builders.create.addLine( mountStatement );
|
block.builders.create.addLine(mountStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.builders.update.addBlock( deindent`
|
block.builders.update.addBlock(deindent`
|
||||||
if ( ${value} !== ( ${value} = ${snippet} ) ) {
|
if ( ${value} !== ( ${value} = ${snippet} ) ) {
|
||||||
${detachStatement}
|
${detachStatement}
|
||||||
${mountStatement}
|
${mountStatement}
|
||||||
}
|
}
|
||||||
` );
|
`);
|
||||||
|
|
||||||
block.builders.detachRaw.addBlock( detachStatement );
|
block.builders.detachRaw.addBlock(detachStatement);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
export default function visitComment () {
|
export default function visitComment() {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { SsrGenerator } from '../index';
|
import { SsrGenerator } from '../index';
|
||||||
|
|
||||||
export default function visitYieldTag ( generator: SsrGenerator ) {
|
export default function visitYieldTag(generator: SsrGenerator) {
|
||||||
generator.append( `\${options && options.yield ? options.yield() : ''}` );
|
generator.append(`\${options && options.yield ? options.yield() : ''}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
export default function visitWindow () {
|
export default function visitWindow() {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +1,36 @@
|
|||||||
import getGlobals from './getGlobals';
|
import getGlobals from './getGlobals';
|
||||||
|
|
||||||
export default function getOutro ( format: string, name: string, options, imports ) {
|
export default function getOutro(
|
||||||
if ( format === 'es' ) {
|
format: string,
|
||||||
|
name: string,
|
||||||
|
options,
|
||||||
|
imports
|
||||||
|
) {
|
||||||
|
if (format === 'es') {
|
||||||
return `export default ${name};`;
|
return `export default ${name};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( format === 'amd' ) {
|
if (format === 'amd') {
|
||||||
return `return ${name};\n\n});`;
|
return `return ${name};\n\n});`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( format === 'cjs' ) {
|
if (format === 'cjs') {
|
||||||
return `module.exports = ${name};`;
|
return `module.exports = ${name};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( format === 'iife' ) {
|
if (format === 'iife') {
|
||||||
const globals = getGlobals( imports, options );
|
const globals = getGlobals(imports, options);
|
||||||
return `return ${name};\n\n}(${globals.join( ', ' )}));`;
|
return `return ${name};\n\n}(${globals.join(', ')}));`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( format === 'eval' ) {
|
if (format === 'eval') {
|
||||||
const globals = getGlobals( imports, options );
|
const globals = getGlobals(imports, options);
|
||||||
return `return ${name};\n\n}(${globals.join( ', ' )}));`;
|
return `return ${name};\n\n}(${globals.join(', ')}));`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( format === 'umd' ) {
|
if (format === 'umd') {
|
||||||
return `return ${name};\n\n})));`;
|
return `return ${name};\n\n})));`;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error( `Not implemented: ${format}` );
|
throw new Error(`Not implemented: ${format}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,20 @@
|
|||||||
import { Node } from '../../../interfaces';
|
import { Node } from '../../../interfaces';
|
||||||
|
|
||||||
export default function walkHtml ( html: Node, visitors ) {
|
export default function walkHtml(html: Node, visitors) {
|
||||||
function visit ( node: Node ) {
|
function visit(node: Node) {
|
||||||
const visitor = visitors[ node.type ];
|
const visitor = visitors[node.type];
|
||||||
if ( !visitor ) throw new Error( `Not implemented: ${node.type}` );
|
if (!visitor) throw new Error(`Not implemented: ${node.type}`);
|
||||||
|
|
||||||
if ( visitor.enter ) visitor.enter( node );
|
if (visitor.enter) visitor.enter(node);
|
||||||
|
|
||||||
if ( node.children ) {
|
if (node.children) {
|
||||||
node.children.forEach( ( child: Node ) => {
|
node.children.forEach((child: Node) => {
|
||||||
visit( child );
|
visit(child);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( visitor.leave ) visitor.leave( node );
|
if (visitor.leave) visitor.leave(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
visit( html );
|
visit(html);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,36 +1,37 @@
|
|||||||
import { parse } from 'acorn';
|
import { parse } from 'acorn';
|
||||||
import spaces from '../../utils/spaces.js';
|
import spaces from '../../utils/spaces';
|
||||||
import { Parser } from '../index';
|
import { Parser } from '../index';
|
||||||
|
|
||||||
const scriptClosingTag = '<\/script>';
|
const scriptClosingTag = '</script>';
|
||||||
|
|
||||||
export default function readScript ( parser: Parser, start: number, attributes ) {
|
export default function readScript(parser: Parser, start: number, attributes) {
|
||||||
const scriptStart = parser.index;
|
const scriptStart = parser.index;
|
||||||
const scriptEnd = parser.template.indexOf( scriptClosingTag, scriptStart );
|
const scriptEnd = parser.template.indexOf(scriptClosingTag, scriptStart);
|
||||||
|
|
||||||
if ( scriptEnd === -1 ) parser.error( `<script> must have a closing tag` );
|
if (scriptEnd === -1) parser.error(`<script> must have a closing tag`);
|
||||||
|
|
||||||
const source = spaces( scriptStart ) + parser.template.slice( scriptStart, scriptEnd );
|
const source =
|
||||||
|
spaces(scriptStart) + parser.template.slice(scriptStart, scriptEnd);
|
||||||
parser.index = scriptEnd + scriptClosingTag.length;
|
parser.index = scriptEnd + scriptClosingTag.length;
|
||||||
|
|
||||||
let ast;
|
let ast;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ast = parse( source, {
|
ast = parse(source, {
|
||||||
ecmaVersion: 8,
|
ecmaVersion: 8,
|
||||||
sourceType: 'module'
|
sourceType: 'module',
|
||||||
});
|
});
|
||||||
} catch ( err ) {
|
} catch (err) {
|
||||||
parser.acornError( err );
|
parser.acornError(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !ast.body.length ) return null;
|
if (!ast.body.length) return null;
|
||||||
|
|
||||||
ast.start = scriptStart;
|
ast.start = scriptStart;
|
||||||
return {
|
return {
|
||||||
start,
|
start,
|
||||||
end: parser.index,
|
end: parser.index,
|
||||||
attributes,
|
attributes,
|
||||||
content: ast
|
content: ast,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
// https://github.com/darkskyapp/string-hash/blob/master/index.js
|
// https://github.com/darkskyapp/string-hash/blob/master/index.js
|
||||||
export default function hash ( str: string ) :number {
|
export default function hash(str: string): number {
|
||||||
let hash = 5381;
|
let hash = 5381;
|
||||||
let i = str.length;
|
let i = str.length;
|
||||||
|
|
||||||
while ( i-- ) hash = ( hash * 33 ) ^ str.charCodeAt( i );
|
while (i--) hash = (hash * 33) ^ str.charCodeAt(i);
|
||||||
return hash >>> 0;
|
return hash >>> 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,35 +1,38 @@
|
|||||||
const fs = require( 'fs' );
|
const fs = require('fs');
|
||||||
const path = require( 'path' );
|
const path = require('path');
|
||||||
const acorn = require( 'acorn' );
|
const acorn = require('acorn');
|
||||||
|
|
||||||
const declarations = {};
|
const declarations = {};
|
||||||
|
|
||||||
fs.readdirSync( __dirname ).forEach( file => {
|
fs.readdirSync(__dirname).forEach(file => {
|
||||||
if ( !/^[a-z]+\.js$/.test( file ) ) return;
|
if (!/^[a-z]+\.js$/.test(file)) return;
|
||||||
|
|
||||||
const source = fs.readFileSync( path.join( __dirname, file ), 'utf-8' );
|
const source = fs.readFileSync(path.join(__dirname, file), 'utf-8');
|
||||||
const ast = acorn.parse( source, {
|
const ast = acorn.parse(source, {
|
||||||
ecmaVersion: 6,
|
ecmaVersion: 6,
|
||||||
sourceType: 'module'
|
sourceType: 'module'
|
||||||
});
|
});
|
||||||
|
|
||||||
ast.body.forEach( node => {
|
ast.body.forEach(node => {
|
||||||
if ( node.type !== 'ExportNamedDeclaration' ) return;
|
if (node.type !== 'ExportNamedDeclaration') return;
|
||||||
|
|
||||||
const declaration = node.declaration;
|
const declaration = node.declaration;
|
||||||
if ( !declaration ) return;
|
if (!declaration) return;
|
||||||
|
|
||||||
const name = declaration.type === 'VariableDeclaration' ?
|
const name = declaration.type === 'VariableDeclaration'
|
||||||
declaration.declarations[0].id.name :
|
? declaration.declarations[0].id.name
|
||||||
declaration.id.name;
|
: declaration.id.name;
|
||||||
|
|
||||||
const value = declaration.type === 'VariableDeclaration' ?
|
const value = declaration.type === 'VariableDeclaration'
|
||||||
declaration.declarations[0].init :
|
? declaration.declarations[0].init
|
||||||
declaration;
|
: declaration;
|
||||||
|
|
||||||
declarations[ name ] = source.slice( value.start, value.end );
|
declarations[name] = source.slice(value.start, value.end);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.writeFileSync( 'src/generators/dom/shared.ts', `// this file is auto-generated, do not edit it
|
fs.writeFileSync(
|
||||||
export default ${JSON.stringify( declarations, null, '\t' )};` );
|
'src/generators/dom/shared.ts',
|
||||||
|
`// this file is auto-generated, do not edit it
|
||||||
|
export default ${JSON.stringify(declarations, null, '\t')};`
|
||||||
|
);
|
||||||
|
|||||||
@ -1,68 +1,68 @@
|
|||||||
export function appendNode ( node, target ) {
|
export function appendNode(node, target) {
|
||||||
target.appendChild( node );
|
target.appendChild(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertNode ( node, target, anchor ) {
|
export function insertNode(node, target, anchor) {
|
||||||
target.insertBefore( node, anchor );
|
target.insertBefore(node, anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function detachNode ( node ) {
|
export function detachNode(node) {
|
||||||
node.parentNode.removeChild( node );
|
node.parentNode.removeChild(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function detachBetween ( before, after ) {
|
export function detachBetween(before, after) {
|
||||||
while ( before.nextSibling && before.nextSibling !== after ) {
|
while (before.nextSibling && before.nextSibling !== after) {
|
||||||
before.parentNode.removeChild( before.nextSibling );
|
before.parentNode.removeChild(before.nextSibling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this is out of date
|
// TODO this is out of date
|
||||||
export function destroyEach ( iterations, detach, start ) {
|
export function destroyEach(iterations, detach, start) {
|
||||||
for ( var i = start; i < iterations.length; i += 1 ) {
|
for (var i = start; i < iterations.length; i += 1) {
|
||||||
if ( iterations[i] ) iterations[i].destroy( detach );
|
if (iterations[i]) iterations[i].destroy(detach);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createElement ( name ) {
|
export function createElement(name) {
|
||||||
return document.createElement( name );
|
return document.createElement(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSvgElement ( name ) {
|
export function createSvgElement(name) {
|
||||||
return document.createElementNS( 'http://www.w3.org/2000/svg', name );
|
return document.createElementNS('http://www.w3.org/2000/svg', name);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createText ( data ) {
|
export function createText(data) {
|
||||||
return document.createTextNode( data );
|
return document.createTextNode(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createComment () {
|
export function createComment() {
|
||||||
return document.createComment( '' );
|
return document.createComment('');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addEventListener ( node, event, handler ) {
|
export function addEventListener(node, event, handler) {
|
||||||
node.addEventListener( event, handler, false );
|
node.addEventListener(event, handler, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeEventListener ( node, event, handler ) {
|
export function removeEventListener(node, event, handler) {
|
||||||
node.removeEventListener( event, handler, false );
|
node.removeEventListener(event, handler, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setAttribute ( node, attribute, value ) {
|
export function setAttribute(node, attribute, value) {
|
||||||
node.setAttribute( attribute, value );
|
node.setAttribute(attribute, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setXlinkAttribute ( node, attribute, value ) {
|
export function setXlinkAttribute(node, attribute, value) {
|
||||||
node.setAttributeNS( 'http://www.w3.org/1999/xlink', attribute, value );
|
node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBindingGroupValue ( group ) {
|
export function getBindingGroupValue(group) {
|
||||||
var value = [];
|
var value = [];
|
||||||
for ( var i = 0; i < group.length; i += 1 ) {
|
for (var i = 0; i < group.length; i += 1) {
|
||||||
if ( group[i].checked ) value.push( group[i].__value );
|
if (group[i].checked) value.push(group[i].__value);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toNumber ( value ) {
|
export function toNumber(value) {
|
||||||
return value === '' ? undefined : +value;
|
return value === '' ? undefined : +value;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,107 +1,103 @@
|
|||||||
import { walk } from 'estree-walker';
|
import { walk } from 'estree-walker';
|
||||||
import { Node } from '../interfaces';
|
import { Node } from '../interfaces';
|
||||||
|
|
||||||
export default function annotateWithScopes ( expression: Node ) {
|
export default function annotateWithScopes(expression: Node) {
|
||||||
let scope = new Scope( null, false );
|
let scope = new Scope(null, false);
|
||||||
|
|
||||||
walk( expression, {
|
walk(expression, {
|
||||||
enter ( node: Node ) {
|
enter(node: Node) {
|
||||||
if ( /Function/.test( node.type ) ) {
|
if (/Function/.test(node.type)) {
|
||||||
if ( node.type === 'FunctionDeclaration' ) {
|
if (node.type === 'FunctionDeclaration') {
|
||||||
scope.declarations.add( node.id.name );
|
scope.declarations.add(node.id.name);
|
||||||
} else {
|
} else {
|
||||||
node._scope = scope = new Scope( scope, false );
|
node._scope = scope = new Scope(scope, false);
|
||||||
if ( node.id ) scope.declarations.add( node.id.name );
|
if (node.id) scope.declarations.add(node.id.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.params.forEach( ( param: Node ) => {
|
node.params.forEach((param: Node) => {
|
||||||
extractNames( param ).forEach( name => {
|
extractNames(param).forEach(name => {
|
||||||
scope.declarations.add( name );
|
scope.declarations.add(name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
} else if (/For(?:In|Of)Statement/.test(node.type)) {
|
||||||
|
node._scope = scope = new Scope(scope, true);
|
||||||
else if ( /For(?:In|Of)Statement/.test( node.type ) ) {
|
} else if (node.type === 'BlockStatement') {
|
||||||
node._scope = scope = new Scope( scope, true );
|
node._scope = scope = new Scope(scope, true);
|
||||||
}
|
} else if (/(Function|Class|Variable)Declaration/.test(node.type)) {
|
||||||
|
scope.addDeclaration(node);
|
||||||
else if ( node.type === 'BlockStatement' ) {
|
|
||||||
node._scope = scope = new Scope( scope, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ( /(Function|Class|Variable)Declaration/.test( node.type ) ) {
|
|
||||||
scope.addDeclaration( node );
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
leave ( node: Node ) {
|
leave(node: Node) {
|
||||||
if ( node._scope ) {
|
if (node._scope) {
|
||||||
scope = scope.parent;
|
scope = scope.parent;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Scope {
|
class Scope {
|
||||||
parent: Scope
|
parent: Scope;
|
||||||
block: boolean
|
block: boolean;
|
||||||
declarations: Set<string>
|
declarations: Set<string>;
|
||||||
|
|
||||||
constructor ( parent: Scope, block: boolean ) {
|
constructor(parent: Scope, block: boolean) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.declarations = new Set();
|
this.declarations = new Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
addDeclaration ( node: Node ) {
|
addDeclaration(node: Node) {
|
||||||
if ( node.kind === 'var' && !this.block && this.parent ) {
|
if (node.kind === 'var' && !this.block && this.parent) {
|
||||||
this.parent.addDeclaration( node );
|
this.parent.addDeclaration(node);
|
||||||
} else if ( node.type === 'VariableDeclaration' ) {
|
} else if (node.type === 'VariableDeclaration') {
|
||||||
node.declarations.forEach( ( declarator: Node ) => {
|
node.declarations.forEach((declarator: Node) => {
|
||||||
extractNames( declarator.id ).forEach( name => {
|
extractNames(declarator.id).forEach(name => {
|
||||||
this.declarations.add( name );
|
this.declarations.add(name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.declarations.add( node.id.name );
|
this.declarations.add(node.id.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
has ( name: string ) :boolean {
|
has(name: string): boolean {
|
||||||
return this.declarations.has( name ) || this.parent && this.parent.has( name );
|
return (
|
||||||
|
this.declarations.has(name) || (this.parent && this.parent.has(name))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractNames ( param: Node ) {
|
function extractNames(param: Node) {
|
||||||
const names: string[] = [];
|
const names: string[] = [];
|
||||||
extractors[ param.type ]( names, param );
|
extractors[param.type](names, param);
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
const extractors = {
|
const extractors = {
|
||||||
Identifier ( names: string[], param: Node ) {
|
Identifier(names: string[], param: Node) {
|
||||||
names.push( param.name );
|
names.push(param.name);
|
||||||
},
|
},
|
||||||
|
|
||||||
ObjectPattern ( names: string[], param: Node ) {
|
ObjectPattern(names: string[], param: Node) {
|
||||||
param.properties.forEach( ( prop: Node ) => {
|
param.properties.forEach((prop: Node) => {
|
||||||
extractors[ prop.value.type ]( names, prop.value );
|
extractors[prop.value.type](names, prop.value);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
ArrayPattern ( names: string[], param: Node ) {
|
ArrayPattern(names: string[], param: Node) {
|
||||||
param.elements.forEach( ( element: Node ) => {
|
param.elements.forEach((element: Node) => {
|
||||||
if ( element ) extractors[ element.type ]( names, element );
|
if (element) extractors[element.type](names, element);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
RestElement ( names: string[], param: Node ) {
|
RestElement(names: string[], param: Node) {
|
||||||
extractors[ param.argument.type ]( names, param.argument );
|
extractors[param.argument.type](names, param.argument);
|
||||||
},
|
},
|
||||||
|
|
||||||
AssignmentPattern ( names: string[], param: Node ) {
|
AssignmentPattern(names: string[], param: Node) {
|
||||||
extractors[ param.left.type ]( names, param.left );
|
extractors[param.left.type](names, param.left);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
const start = /\n(\t+)/;
|
|
||||||
|
|
||||||
export default function deindent ( strings, ...values ) {
|
|
||||||
const indentation = start.exec( strings[0] )[1];
|
|
||||||
const pattern = new RegExp( `^${indentation}`, 'gm' );
|
|
||||||
|
|
||||||
let result = strings[0].replace( start, '' ).replace( pattern, '' );
|
|
||||||
|
|
||||||
let trailingIndentation = getTrailingIndentation( result );
|
|
||||||
|
|
||||||
for ( let i = 1; i < strings.length; i += 1 ) {
|
|
||||||
let expression = values[ i - 1 ];
|
|
||||||
const string = strings[i].replace( pattern, '' );
|
|
||||||
|
|
||||||
if ( Array.isArray( expression ) ) {
|
|
||||||
expression = expression.length ? expression.join( '\n' ) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( expression || expression === '' ) {
|
|
||||||
const value = String( expression ).replace( /\n/g, `\n${trailingIndentation}` );
|
|
||||||
result += value + string;
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
let c = result.length;
|
|
||||||
while ( /\s/.test( result[ c - 1 ] ) ) c -= 1;
|
|
||||||
result = result.slice( 0, c ) + string;
|
|
||||||
}
|
|
||||||
|
|
||||||
trailingIndentation = getTrailingIndentation( result );
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.trim().replace( /\t+$/gm, '' );
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTrailingIndentation ( str ) {
|
|
||||||
let i = str.length;
|
|
||||||
while ( str[ i - 1 ] === ' ' || str[ i - 1 ] === '\t' ) i -= 1;
|
|
||||||
return str.slice( i, str.length );
|
|
||||||
}
|
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
const start = /\n(\t+)/;
|
||||||
|
|
||||||
|
export default function deindent(strings: string[], ...values: any[]) {
|
||||||
|
const indentation = start.exec(strings[0])[1];
|
||||||
|
const pattern = new RegExp(`^${indentation}`, 'gm');
|
||||||
|
|
||||||
|
let result = strings[0].replace(start, '').replace(pattern, '');
|
||||||
|
|
||||||
|
let trailingIndentation = getTrailingIndentation(result);
|
||||||
|
|
||||||
|
for (let i = 1; i < strings.length; i += 1) {
|
||||||
|
let expression = values[i - 1];
|
||||||
|
const string = strings[i].replace(pattern, '');
|
||||||
|
|
||||||
|
if (Array.isArray(expression)) {
|
||||||
|
expression = expression.length ? expression.join('\n') : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expression || expression === '') {
|
||||||
|
const value = String(expression).replace(
|
||||||
|
/\n/g,
|
||||||
|
`\n${trailingIndentation}`
|
||||||
|
);
|
||||||
|
result += value + string;
|
||||||
|
} else {
|
||||||
|
let c = result.length;
|
||||||
|
while (/\s/.test(result[c - 1])) c -= 1;
|
||||||
|
result = result.slice(0, c) + string;
|
||||||
|
}
|
||||||
|
|
||||||
|
trailingIndentation = getTrailingIndentation(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.trim().replace(/\t+$/gm, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTrailingIndentation(str: string) {
|
||||||
|
let i = str.length;
|
||||||
|
while (str[i - 1] === ' ' || str[i - 1] === '\t') i -= 1;
|
||||||
|
return str.slice(i, str.length);
|
||||||
|
}
|
||||||
@ -1,21 +1,23 @@
|
|||||||
import { Node } from '../interfaces';
|
import { Node } from '../interfaces';
|
||||||
|
|
||||||
export default function flatten ( node: Node ) {
|
export default function flatten(node: Node) {
|
||||||
const parts = [];
|
const parts = [];
|
||||||
const propEnd = node.end;
|
const propEnd = node.end;
|
||||||
|
|
||||||
while ( node.type === 'MemberExpression' ) {
|
while (node.type === 'MemberExpression') {
|
||||||
if ( node.computed ) return null;
|
if (node.computed) return null;
|
||||||
parts.unshift( node.property.name );
|
parts.unshift(node.property.name);
|
||||||
|
|
||||||
node = node.object;
|
node = node.object;
|
||||||
}
|
}
|
||||||
|
|
||||||
const propStart = node.end;
|
const propStart = node.end;
|
||||||
const name = node.type === 'Identifier' ? node.name : node.type === 'ThisExpression' ? 'this' : null;
|
const name = node.type === 'Identifier'
|
||||||
|
? node.name
|
||||||
|
: node.type === 'ThisExpression' ? 'this' : null;
|
||||||
|
|
||||||
if ( !name ) return null;
|
if (!name) return null;
|
||||||
|
|
||||||
parts.unshift( name );
|
parts.unshift(name);
|
||||||
return { name, parts, keypath: `${name}[✂${propStart}-${propEnd}✂]` };
|
return { name, parts, keypath: `${name}[✂${propStart}-${propEnd}✂]` };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +1,36 @@
|
|||||||
import spaces from './spaces.js';
|
import spaces from './spaces';
|
||||||
|
|
||||||
function tabsToSpaces ( str: string ) {
|
function tabsToSpaces(str: string) {
|
||||||
return str.replace( /^\t+/, match => match.split( '\t' ).join( ' ' ) );
|
return str.replace(/^\t+/, match => match.split('\t').join(' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getCodeFrame ( source: string, line: number, column: number ) {
|
export default function getCodeFrame(
|
||||||
const lines = source.split( '\n' );
|
source: string,
|
||||||
|
line: number,
|
||||||
|
column: number
|
||||||
|
) {
|
||||||
|
const lines = source.split('\n');
|
||||||
|
|
||||||
const frameStart = Math.max( 0, line - 2 );
|
const frameStart = Math.max(0, line - 2);
|
||||||
const frameEnd = Math.min( line + 3, lines.length );
|
const frameEnd = Math.min(line + 3, lines.length);
|
||||||
|
|
||||||
const digits = String( frameEnd + 1 ).length;
|
const digits = String(frameEnd + 1).length;
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
.slice( frameStart, frameEnd )
|
.slice(frameStart, frameEnd)
|
||||||
.map( ( str, i ) => {
|
.map((str, i) => {
|
||||||
const isErrorLine = frameStart + i === line;
|
const isErrorLine = frameStart + i === line;
|
||||||
|
|
||||||
let lineNum = String( i + frameStart + 1 );
|
let lineNum = String(i + frameStart + 1);
|
||||||
while ( lineNum.length < digits ) lineNum = ` ${lineNum}`;
|
while (lineNum.length < digits) lineNum = ` ${lineNum}`;
|
||||||
|
|
||||||
if ( isErrorLine ) {
|
if (isErrorLine) {
|
||||||
const indicator = spaces( digits + 2 + tabsToSpaces( str.slice( 0, column ) ).length ) + '^';
|
const indicator =
|
||||||
return `${lineNum}: ${tabsToSpaces( str )}\n${indicator}`;
|
spaces(digits + 2 + tabsToSpaces(str.slice(0, column)).length) + '^';
|
||||||
|
return `${lineNum}: ${tabsToSpaces(str)}\n${indicator}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${lineNum}: ${tabsToSpaces( str )}`;
|
return `${lineNum}: ${tabsToSpaces(str)}`;
|
||||||
})
|
})
|
||||||
.join( '\n' );
|
.join('\n');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1,26 @@
|
|||||||
export default new Set( [ 'Array', 'Boolean', 'console', 'Date', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'Infinity', 'Intl', 'isFinite', 'isNaN', 'JSON', 'Map', 'Math', 'NaN', 'Number', 'Object', 'parseFloat', 'parseInt', 'RegExp', 'Set', 'String', 'undefined' ] );
|
export default new Set([
|
||||||
|
'Array',
|
||||||
|
'Boolean',
|
||||||
|
'console',
|
||||||
|
'Date',
|
||||||
|
'decodeURI',
|
||||||
|
'decodeURIComponent',
|
||||||
|
'encodeURI',
|
||||||
|
'encodeURIComponent',
|
||||||
|
'Infinity',
|
||||||
|
'Intl',
|
||||||
|
'isFinite',
|
||||||
|
'isNaN',
|
||||||
|
'JSON',
|
||||||
|
'Map',
|
||||||
|
'Math',
|
||||||
|
'NaN',
|
||||||
|
'Number',
|
||||||
|
'Object',
|
||||||
|
'parseFloat',
|
||||||
|
'parseInt',
|
||||||
|
'RegExp',
|
||||||
|
'Set',
|
||||||
|
'String',
|
||||||
|
'undefined',
|
||||||
|
]);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const voidElementNames = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
|
const voidElementNames = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
|
||||||
|
|
||||||
export default function isVoidElementName ( name: string ) {
|
export default function isVoidElementName(name: string) {
|
||||||
return voidElementNames.test( name ) || name.toLowerCase() === '!doctype';
|
return voidElementNames.test(name) || name.toLowerCase() === '!doctype';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,23 @@
|
|||||||
export const html = 'http://www.w3.org/1999/xhtml';
|
export const html = 'http://www.w3.org/1999/xhtml';
|
||||||
export const mathml = 'http://www.w3.org/1998/Math/MathML';
|
export const mathml = 'http://www.w3.org/1998/Math/MathML';
|
||||||
export const svg = 'http://www.w3.org/2000/svg';
|
export const svg = 'http://www.w3.org/2000/svg';
|
||||||
export const xlink = 'http://www.w3.org/1999/xlink';
|
export const xlink = 'http://www.w3.org/1999/xlink';
|
||||||
export const xml = 'http://www.w3.org/XML/1998/namespace';
|
export const xml = 'http://www.w3.org/XML/1998/namespace';
|
||||||
export const xmlns = 'http://www.w3.org/2000/xmlns';
|
export const xmlns = 'http://www.w3.org/2000/xmlns';
|
||||||
|
|
||||||
export const validNamespaces = [
|
export const validNamespaces = [
|
||||||
'html', 'mathml', 'svg', 'xlink', 'xml', 'xmlns',
|
'html',
|
||||||
html, mathml, svg, xlink, xml, xmlns
|
'mathml',
|
||||||
|
'svg',
|
||||||
|
'xlink',
|
||||||
|
'xml',
|
||||||
|
'xmlns',
|
||||||
|
html,
|
||||||
|
mathml,
|
||||||
|
svg,
|
||||||
|
xlink,
|
||||||
|
xml,
|
||||||
|
xmlns,
|
||||||
];
|
];
|
||||||
|
|
||||||
export default { html, mathml, svg, xlink, xml, xmlns };
|
export default { html, mathml, svg, xlink, xml, xmlns };
|
||||||
|
|||||||
@ -1,6 +1,55 @@
|
|||||||
const reservedNames = new Set( [ 'arguments', 'await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'enum', 'eval', 'export', 'extends', 'false', 'finally', 'for', 'function', 'if', 'implements', 'import', 'in', 'instanceof', 'interface', 'let', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield' ] );
|
const reservedNames = new Set([
|
||||||
|
'arguments',
|
||||||
|
'await',
|
||||||
|
'break',
|
||||||
|
'case',
|
||||||
|
'catch',
|
||||||
|
'class',
|
||||||
|
'const',
|
||||||
|
'continue',
|
||||||
|
'debugger',
|
||||||
|
'default',
|
||||||
|
'delete',
|
||||||
|
'do',
|
||||||
|
'else',
|
||||||
|
'enum',
|
||||||
|
'eval',
|
||||||
|
'export',
|
||||||
|
'extends',
|
||||||
|
'false',
|
||||||
|
'finally',
|
||||||
|
'for',
|
||||||
|
'function',
|
||||||
|
'if',
|
||||||
|
'implements',
|
||||||
|
'import',
|
||||||
|
'in',
|
||||||
|
'instanceof',
|
||||||
|
'interface',
|
||||||
|
'let',
|
||||||
|
'new',
|
||||||
|
'null',
|
||||||
|
'package',
|
||||||
|
'private',
|
||||||
|
'protected',
|
||||||
|
'public',
|
||||||
|
'return',
|
||||||
|
'static',
|
||||||
|
'super',
|
||||||
|
'switch',
|
||||||
|
'this',
|
||||||
|
'throw',
|
||||||
|
'true',
|
||||||
|
'try',
|
||||||
|
'typeof',
|
||||||
|
'var',
|
||||||
|
'void',
|
||||||
|
'while',
|
||||||
|
'with',
|
||||||
|
'yield',
|
||||||
|
]);
|
||||||
|
|
||||||
// prevent e.g. `{{#each states as state}}` breaking
|
// prevent e.g. `{{#each states as state}}` breaking
|
||||||
reservedNames.add( 'state' );
|
reservedNames.add('state');
|
||||||
|
|
||||||
export default reservedNames;
|
export default reservedNames;
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
export default function spaces ( i ) {
|
|
||||||
let result = '';
|
|
||||||
while ( i-- ) result += ' ';
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
export default function spaces(i: number) {
|
||||||
|
let result = '';
|
||||||
|
while (i--) result += ' ';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@ -1,15 +1,15 @@
|
|||||||
import { whitespace } from './patterns';
|
import { whitespace } from './patterns';
|
||||||
|
|
||||||
export function trimStart ( str: string ) {
|
export function trimStart(str: string) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while ( whitespace.test( str[i] ) ) i += 1;
|
while (whitespace.test(str[i])) i += 1;
|
||||||
|
|
||||||
return str.slice( i );
|
return str.slice(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trimEnd ( str: string ) {
|
export function trimEnd(str: string) {
|
||||||
let i = str.length;
|
let i = str.length;
|
||||||
while ( whitespace.test( str[ i - 1 ] ) ) i -= 1;
|
while (whitespace.test(str[i - 1])) i -= 1;
|
||||||
|
|
||||||
return str.slice( 0, i );
|
return str.slice(0, i);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import { Validator } from '../../';
|
import { Validator } from '../../';
|
||||||
import { Node } from '../../../interfaces';
|
import { Node } from '../../../interfaces';
|
||||||
|
|
||||||
const disallowed = new Set([ 'Literal', 'ObjectExpression', 'ArrayExpression' ]);
|
const disallowed = new Set(['Literal', 'ObjectExpression', 'ArrayExpression']);
|
||||||
|
|
||||||
export default function data ( validator: Validator, prop: Node ) {
|
export default function data(validator: Validator, prop: Node) {
|
||||||
while ( prop.type === 'ParenthesizedExpression' ) prop = prop.expression;
|
while (prop.type === 'ParenthesizedExpression') prop = prop.expression;
|
||||||
|
|
||||||
// TODO should we disallow references and expressions as well?
|
// TODO should we disallow references and expressions as well?
|
||||||
|
|
||||||
if ( disallowed.has( prop.value.type ) ) {
|
if (disallowed.has(prop.value.type)) {
|
||||||
validator.error( `'data' must be a function`, prop.value.start );
|
validator.error(`'data' must be a function`, prop.value.start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue