mirror of https://github.com/sveltejs/svelte
parent
399ee4595a
commit
84595fb381
@ -1,13 +1,15 @@
|
||||
import { Node } from '../../../../interfaces';
|
||||
|
||||
export default function getStaticAttributeValue ( node: Node, name: string ) {
|
||||
const attribute = node.attributes.find( ( attr: Node ) => attr.name.toLowerCase() === name );
|
||||
if ( !attribute ) return null;
|
||||
export default function getStaticAttributeValue(node: Node, name: string) {
|
||||
const attribute = node.attributes.find(
|
||||
(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)
|
||||
throw new Error( `'${name} must be a static attribute` );
|
||||
throw new Error(`'${name} must be a static attribute`);
|
||||
}
|
||||
|
||||
return attribute.value[0].data;
|
||||
}
|
||||
}
|
||||
|
@ -1,122 +1,235 @@
|
||||
// source: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
|
||||
const lookup = {
|
||||
accept: { appliesTo: [ 'form', 'input' ] },
|
||||
'accept-charset': { propertyName: 'acceptCharset', appliesTo: [ 'form' ] },
|
||||
accept: { appliesTo: ['form', 'input'] },
|
||||
'accept-charset': { propertyName: 'acceptCharset', appliesTo: ['form'] },
|
||||
accesskey: { propertyName: 'accessKey' },
|
||||
action: { appliesTo: [ 'form' ] },
|
||||
align: { appliesTo: [ 'applet', 'caption', 'col', 'colgroup', 'hr', 'iframe', 'img', 'table', 'tbody', 'td', 'tfoot' , 'th', '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' ] },
|
||||
action: { appliesTo: ['form'] },
|
||||
align: {
|
||||
appliesTo: [
|
||||
'applet',
|
||||
'caption',
|
||||
'col',
|
||||
'colgroup',
|
||||
'hr',
|
||||
'iframe',
|
||||
'img',
|
||||
'table',
|
||||
'tbody',
|
||||
'td',
|
||||
'tfoot',
|
||||
'th',
|
||||
'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' },
|
||||
code: { appliesTo: [ 'applet' ] },
|
||||
codebase: { propertyName: 'codeBase', appliesTo: [ 'applet' ] },
|
||||
color: { appliesTo: [ 'basefont', 'font', 'hr' ] },
|
||||
cols: { appliesTo: [ 'textarea' ] },
|
||||
colspan: { propertyName: 'colSpan', appliesTo: [ 'td', 'th' ] },
|
||||
content: { appliesTo: [ 'meta' ] },
|
||||
code: { appliesTo: ['applet'] },
|
||||
codebase: { propertyName: 'codeBase', appliesTo: ['applet'] },
|
||||
color: { appliesTo: ['basefont', 'font', 'hr'] },
|
||||
cols: { appliesTo: ['textarea'] },
|
||||
colspan: { propertyName: 'colSpan', appliesTo: ['td', 'th'] },
|
||||
content: { appliesTo: ['meta'] },
|
||||
contenteditable: { propertyName: 'contentEditable' },
|
||||
contextmenu: {},
|
||||
controls: { appliesTo: [ 'audio', 'video' ] },
|
||||
coords: { appliesTo: [ 'area' ] },
|
||||
data: { appliesTo: [ 'object' ] },
|
||||
datetime: { propertyName: 'dateTime', appliesTo: [ 'del', 'ins', 'time' ] },
|
||||
default: { appliesTo: [ 'track' ] },
|
||||
defer: { appliesTo: [ 'script' ] },
|
||||
controls: { appliesTo: ['audio', 'video'] },
|
||||
coords: { appliesTo: ['area'] },
|
||||
data: { appliesTo: ['object'] },
|
||||
datetime: { propertyName: 'dateTime', appliesTo: ['del', 'ins', 'time'] },
|
||||
default: { appliesTo: ['track'] },
|
||||
defer: { appliesTo: ['script'] },
|
||||
dir: {},
|
||||
dirname: { propertyName: 'dirName', appliesTo: [ 'input', 'textarea' ] },
|
||||
disabled: { appliesTo: [ 'button', 'command', 'fieldset', 'input', 'keygen', 'optgroup', 'option', 'select', 'textarea' ] },
|
||||
download: { appliesTo: [ 'a', 'area' ] },
|
||||
dirname: { propertyName: 'dirName', appliesTo: ['input', 'textarea'] },
|
||||
disabled: {
|
||||
appliesTo: [
|
||||
'button',
|
||||
'command',
|
||||
'fieldset',
|
||||
'input',
|
||||
'keygen',
|
||||
'optgroup',
|
||||
'option',
|
||||
'select',
|
||||
'textarea'
|
||||
]
|
||||
},
|
||||
download: { appliesTo: ['a', 'area'] },
|
||||
draggable: {},
|
||||
dropzone: {},
|
||||
enctype: { appliesTo: [ 'form' ] },
|
||||
for: { propertyName: 'htmlFor', appliesTo: [ 'label', 'output' ] },
|
||||
form: { appliesTo: [ 'button', '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' ] },
|
||||
enctype: { appliesTo: ['form'] },
|
||||
for: { propertyName: 'htmlFor', appliesTo: ['label', 'output'] },
|
||||
form: {
|
||||
appliesTo: [
|
||||
'button',
|
||||
'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: {},
|
||||
high: { appliesTo: [ 'meter' ] },
|
||||
href: { appliesTo: [ 'a', 'area', 'base', 'link' ] },
|
||||
hreflang: { appliesTo: [ 'a', 'area', 'link' ] },
|
||||
'http-equiv': { propertyName: 'httpEquiv', appliesTo: [ 'meta' ] },
|
||||
icon: { appliesTo: [ 'command' ] },
|
||||
high: { appliesTo: ['meter'] },
|
||||
href: { appliesTo: ['a', 'area', 'base', 'link'] },
|
||||
hreflang: { appliesTo: ['a', 'area', 'link'] },
|
||||
'http-equiv': { propertyName: 'httpEquiv', appliesTo: ['meta'] },
|
||||
icon: { appliesTo: ['command'] },
|
||||
id: {},
|
||||
ismap: { propertyName: 'isMap', appliesTo: [ 'img' ] },
|
||||
ismap: { propertyName: 'isMap', appliesTo: ['img'] },
|
||||
itemprop: {},
|
||||
keytype: { appliesTo: [ 'keygen' ] },
|
||||
kind: { appliesTo: [ 'track' ] },
|
||||
label: { appliesTo: [ 'track' ] },
|
||||
keytype: { appliesTo: ['keygen'] },
|
||||
kind: { appliesTo: ['track'] },
|
||||
label: { appliesTo: ['track'] },
|
||||
lang: {},
|
||||
language: { appliesTo: [ 'script' ] },
|
||||
loop: { appliesTo: [ 'audio', 'bgsound', 'marquee', 'video' ] },
|
||||
low: { appliesTo: [ 'meter' ] },
|
||||
manifest: { appliesTo: [ 'html' ] },
|
||||
max: { appliesTo: [ 'input', 'meter', 'progress' ] },
|
||||
maxlength: { propertyName: 'maxLength', appliesTo: [ 'input', 'textarea' ] },
|
||||
media: { appliesTo: [ 'a', 'area', 'link', 'source', 'style' ] },
|
||||
method: { appliesTo: [ 'form' ] },
|
||||
min: { appliesTo: [ 'input', 'meter' ] },
|
||||
multiple: { appliesTo: [ 'input', 'select' ] },
|
||||
muted: { appliesTo: [ 'video' ] },
|
||||
name: { appliesTo: [ 'button', 'form', 'fieldset', 'iframe', 'input', 'keygen', 'object', 'output', 'select', 'textarea', 'map', 'meta', 'param' ] },
|
||||
novalidate: { propertyName: 'noValidate', appliesTo: [ 'form' ] },
|
||||
open: { appliesTo: [ 'details' ] },
|
||||
optimum: { appliesTo: [ 'meter' ] },
|
||||
pattern: { appliesTo: [ 'input' ] },
|
||||
ping: { appliesTo: [ 'a', 'area' ] },
|
||||
placeholder: { appliesTo: [ 'input', 'textarea' ] },
|
||||
poster: { appliesTo: [ 'video' ] },
|
||||
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' ] },
|
||||
language: { appliesTo: ['script'] },
|
||||
loop: { appliesTo: ['audio', 'bgsound', 'marquee', 'video'] },
|
||||
low: { appliesTo: ['meter'] },
|
||||
manifest: { appliesTo: ['html'] },
|
||||
max: { appliesTo: ['input', 'meter', 'progress'] },
|
||||
maxlength: { propertyName: 'maxLength', appliesTo: ['input', 'textarea'] },
|
||||
media: { appliesTo: ['a', 'area', 'link', 'source', 'style'] },
|
||||
method: { appliesTo: ['form'] },
|
||||
min: { appliesTo: ['input', 'meter'] },
|
||||
multiple: { appliesTo: ['input', 'select'] },
|
||||
muted: { appliesTo: ['video'] },
|
||||
name: {
|
||||
appliesTo: [
|
||||
'button',
|
||||
'form',
|
||||
'fieldset',
|
||||
'iframe',
|
||||
'input',
|
||||
'keygen',
|
||||
'object',
|
||||
'output',
|
||||
'select',
|
||||
'textarea',
|
||||
'map',
|
||||
'meta',
|
||||
'param'
|
||||
]
|
||||
},
|
||||
novalidate: { propertyName: 'noValidate', appliesTo: ['form'] },
|
||||
open: { appliesTo: ['details'] },
|
||||
optimum: { appliesTo: ['meter'] },
|
||||
pattern: { appliesTo: ['input'] },
|
||||
ping: { appliesTo: ['a', 'area'] },
|
||||
placeholder: { appliesTo: ['input', 'textarea'] },
|
||||
poster: { appliesTo: ['video'] },
|
||||
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: {},
|
||||
src: { appliesTo: [ 'audio', 'embed', 'iframe', 'img', 'input', 'script', 'source', 'track', 'video' ] },
|
||||
srcdoc: { appliesTo: [ 'iframe' ] },
|
||||
srclang: { appliesTo: [ 'track' ] },
|
||||
srcset: { appliesTo: [ 'img' ] },
|
||||
start: { appliesTo: [ 'ol' ] },
|
||||
step: { appliesTo: [ 'input' ] },
|
||||
src: {
|
||||
appliesTo: [
|
||||
'audio',
|
||||
'embed',
|
||||
'iframe',
|
||||
'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' },
|
||||
summary: { appliesTo: [ 'table' ] },
|
||||
summary: { appliesTo: ['table'] },
|
||||
tabindex: { propertyName: 'tabIndex' },
|
||||
target: { appliesTo: [ 'a', 'area', 'base', 'form' ] },
|
||||
target: { appliesTo: ['a', 'area', 'base', 'form'] },
|
||||
title: {},
|
||||
type: { appliesTo: [ 'button', 'input', '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' ] }
|
||||
type: {
|
||||
appliesTo: [
|
||||
'button',
|
||||
'input',
|
||||
'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 => {
|
||||
const metadata = lookup[ name ];
|
||||
if ( !metadata.propertyName ) metadata.propertyName = name;
|
||||
Object.keys(lookup).forEach(name => {
|
||||
const metadata = lookup[name];
|
||||
if (!metadata.propertyName) metadata.propertyName = name;
|
||||
});
|
||||
|
||||
export default lookup;
|
||||
|
@ -1,3 +1,3 @@
|
||||
export default function visitComment () {
|
||||
export default function visitComment() {
|
||||
// do nothing
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { SsrGenerator } from '../index';
|
||||
|
||||
export default function visitYieldTag ( generator: SsrGenerator ) {
|
||||
generator.append( `\${options && options.yield ? options.yield() : ''}` );
|
||||
}
|
||||
export default function visitYieldTag(generator: SsrGenerator) {
|
||||
generator.append(`\${options && options.yield ? options.yield() : ''}`);
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
export default function visitWindow () {
|
||||
export default function visitWindow() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,36 @@
|
||||
import getGlobals from './getGlobals';
|
||||
|
||||
export default function getOutro ( format: string, name: string, options, imports ) {
|
||||
if ( format === 'es' ) {
|
||||
export default function getOutro(
|
||||
format: string,
|
||||
name: string,
|
||||
options,
|
||||
imports
|
||||
) {
|
||||
if (format === 'es') {
|
||||
return `export default ${name};`;
|
||||
}
|
||||
|
||||
if ( format === 'amd' ) {
|
||||
if (format === 'amd') {
|
||||
return `return ${name};\n\n});`;
|
||||
}
|
||||
|
||||
if ( format === 'cjs' ) {
|
||||
if (format === 'cjs') {
|
||||
return `module.exports = ${name};`;
|
||||
}
|
||||
|
||||
if ( format === 'iife' ) {
|
||||
const globals = getGlobals( imports, options );
|
||||
return `return ${name};\n\n}(${globals.join( ', ' )}));`;
|
||||
if (format === 'iife') {
|
||||
const globals = getGlobals(imports, options);
|
||||
return `return ${name};\n\n}(${globals.join(', ')}));`;
|
||||
}
|
||||
|
||||
if ( format === 'eval' ) {
|
||||
const globals = getGlobals( imports, options );
|
||||
return `return ${name};\n\n}(${globals.join( ', ' )}));`;
|
||||
if (format === 'eval') {
|
||||
const globals = getGlobals(imports, options);
|
||||
return `return ${name};\n\n}(${globals.join(', ')}));`;
|
||||
}
|
||||
|
||||
if ( format === 'umd' ) {
|
||||
if (format === 'umd') {
|
||||
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';
|
||||
|
||||
export default function walkHtml ( html: Node, visitors ) {
|
||||
function visit ( node: Node ) {
|
||||
const visitor = visitors[ node.type ];
|
||||
if ( !visitor ) throw new Error( `Not implemented: ${node.type}` );
|
||||
export default function walkHtml(html: Node, visitors) {
|
||||
function visit(node: Node) {
|
||||
const visitor = visitors[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 ) {
|
||||
node.children.forEach( ( child: Node ) => {
|
||||
visit( child );
|
||||
if (node.children) {
|
||||
node.children.forEach((child: Node) => {
|
||||
visit(child);
|
||||
});
|
||||
}
|
||||
|
||||
if ( visitor.leave ) visitor.leave( node );
|
||||
if (visitor.leave) visitor.leave(node);
|
||||
}
|
||||
|
||||
visit( html );
|
||||
visit(html);
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// 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 i = str.length;
|
||||
|
||||
while ( i-- ) hash = ( hash * 33 ) ^ str.charCodeAt( i );
|
||||
while (i--) hash = (hash * 33) ^ str.charCodeAt(i);
|
||||
return hash >>> 0;
|
||||
}
|
||||
|
@ -1,35 +1,38 @@
|
||||
const fs = require( 'fs' );
|
||||
const path = require( 'path' );
|
||||
const acorn = require( 'acorn' );
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const acorn = require('acorn');
|
||||
|
||||
const declarations = {};
|
||||
|
||||
fs.readdirSync( __dirname ).forEach( file => {
|
||||
if ( !/^[a-z]+\.js$/.test( file ) ) return;
|
||||
fs.readdirSync(__dirname).forEach(file => {
|
||||
if (!/^[a-z]+\.js$/.test(file)) return;
|
||||
|
||||
const source = fs.readFileSync( path.join( __dirname, file ), 'utf-8' );
|
||||
const ast = acorn.parse( source, {
|
||||
const source = fs.readFileSync(path.join(__dirname, file), 'utf-8');
|
||||
const ast = acorn.parse(source, {
|
||||
ecmaVersion: 6,
|
||||
sourceType: 'module'
|
||||
});
|
||||
|
||||
ast.body.forEach( node => {
|
||||
if ( node.type !== 'ExportNamedDeclaration' ) return;
|
||||
ast.body.forEach(node => {
|
||||
if (node.type !== 'ExportNamedDeclaration') return;
|
||||
|
||||
const declaration = node.declaration;
|
||||
if ( !declaration ) return;
|
||||
if (!declaration) return;
|
||||
|
||||
const name = declaration.type === 'VariableDeclaration' ?
|
||||
declaration.declarations[0].id.name :
|
||||
declaration.id.name;
|
||||
const name = declaration.type === 'VariableDeclaration'
|
||||
? declaration.declarations[0].id.name
|
||||
: declaration.id.name;
|
||||
|
||||
const value = declaration.type === 'VariableDeclaration' ?
|
||||
declaration.declarations[0].init :
|
||||
declaration;
|
||||
const value = declaration.type === 'VariableDeclaration'
|
||||
? declaration.declarations[0].init
|
||||
: 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
|
||||
export default ${JSON.stringify( declarations, null, '\t' )};` );
|
||||
fs.writeFileSync(
|
||||
'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 ) {
|
||||
target.appendChild( node );
|
||||
export function appendNode(node, target) {
|
||||
target.appendChild(node);
|
||||
}
|
||||
|
||||
export function insertNode ( node, target, anchor ) {
|
||||
target.insertBefore( node, anchor );
|
||||
export function insertNode(node, target, anchor) {
|
||||
target.insertBefore(node, anchor);
|
||||
}
|
||||
|
||||
export function detachNode ( node ) {
|
||||
node.parentNode.removeChild( node );
|
||||
export function detachNode(node) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
|
||||
export function detachBetween ( before, after ) {
|
||||
while ( before.nextSibling && before.nextSibling !== after ) {
|
||||
before.parentNode.removeChild( before.nextSibling );
|
||||
export function detachBetween(before, after) {
|
||||
while (before.nextSibling && before.nextSibling !== after) {
|
||||
before.parentNode.removeChild(before.nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this is out of date
|
||||
export function destroyEach ( iterations, detach, start ) {
|
||||
for ( var i = start; i < iterations.length; i += 1 ) {
|
||||
if ( iterations[i] ) iterations[i].destroy( detach );
|
||||
export function destroyEach(iterations, detach, start) {
|
||||
for (var i = start; i < iterations.length; i += 1) {
|
||||
if (iterations[i]) iterations[i].destroy(detach);
|
||||
}
|
||||
}
|
||||
|
||||
export function createElement ( name ) {
|
||||
return document.createElement( name );
|
||||
export function createElement(name) {
|
||||
return document.createElement(name);
|
||||
}
|
||||
|
||||
export function createSvgElement ( name ) {
|
||||
return document.createElementNS( 'http://www.w3.org/2000/svg', name );
|
||||
export function createSvgElement(name) {
|
||||
return document.createElementNS('http://www.w3.org/2000/svg', name);
|
||||
}
|
||||
|
||||
export function createText ( data ) {
|
||||
return document.createTextNode( data );
|
||||
export function createText(data) {
|
||||
return document.createTextNode(data);
|
||||
}
|
||||
|
||||
export function createComment () {
|
||||
return document.createComment( '' );
|
||||
export function createComment() {
|
||||
return document.createComment('');
|
||||
}
|
||||
|
||||
export function addEventListener ( node, event, handler ) {
|
||||
node.addEventListener( event, handler, false );
|
||||
export function addEventListener(node, event, handler) {
|
||||
node.addEventListener(event, handler, false);
|
||||
}
|
||||
|
||||
export function removeEventListener ( node, event, handler ) {
|
||||
node.removeEventListener( event, handler, false );
|
||||
export function removeEventListener(node, event, handler) {
|
||||
node.removeEventListener(event, handler, false);
|
||||
}
|
||||
|
||||
export function setAttribute ( node, attribute, value ) {
|
||||
node.setAttribute( attribute, value );
|
||||
export function setAttribute(node, attribute, value) {
|
||||
node.setAttribute(attribute, value);
|
||||
}
|
||||
|
||||
export function setXlinkAttribute ( node, attribute, value ) {
|
||||
node.setAttributeNS( 'http://www.w3.org/1999/xlink', attribute, value );
|
||||
export function setXlinkAttribute(node, attribute, value) {
|
||||
node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);
|
||||
}
|
||||
|
||||
export function getBindingGroupValue ( group ) {
|
||||
export function getBindingGroupValue(group) {
|
||||
var value = [];
|
||||
for ( var i = 0; i < group.length; i += 1 ) {
|
||||
if ( group[i].checked ) value.push( group[i].__value );
|
||||
for (var i = 0; i < group.length; i += 1) {
|
||||
if (group[i].checked) value.push(group[i].__value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export function toNumber ( value ) {
|
||||
export function toNumber(value) {
|
||||
return value === '' ? undefined : +value;
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +1,41 @@
|
||||
const start = /\n(\t+)/;
|
||||
|
||||
export default function deindent ( strings, ...values ) {
|
||||
const indentation = start.exec( strings[0] )[1];
|
||||
const pattern = new RegExp( `^${indentation}`, 'gm' );
|
||||
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 result = strings[0].replace(start, '').replace(pattern, '');
|
||||
|
||||
let trailingIndentation = getTrailingIndentation( result );
|
||||
let trailingIndentation = getTrailingIndentation(result);
|
||||
|
||||
for ( let i = 1; i < strings.length; i += 1 ) {
|
||||
let expression = values[ i - 1 ];
|
||||
const string = strings[i].replace( pattern, '' );
|
||||
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 (Array.isArray(expression)) {
|
||||
expression = expression.length ? expression.join('\n') : null;
|
||||
}
|
||||
|
||||
if ( expression || expression === '' ) {
|
||||
const value = String( expression ).replace( /\n/g, `\n${trailingIndentation}` );
|
||||
if (expression || expression === '') {
|
||||
const value = String(expression).replace(
|
||||
/\n/g,
|
||||
`\n${trailingIndentation}`
|
||||
);
|
||||
result += value + string;
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
let c = result.length;
|
||||
while ( /\s/.test( result[ c - 1 ] ) ) c -= 1;
|
||||
result = result.slice( 0, c ) + string;
|
||||
while (/\s/.test(result[c - 1])) c -= 1;
|
||||
result = result.slice(0, c) + string;
|
||||
}
|
||||
|
||||
trailingIndentation = getTrailingIndentation( result );
|
||||
trailingIndentation = getTrailingIndentation(result);
|
||||
}
|
||||
|
||||
return result.trim().replace( /\t+$/gm, '' );
|
||||
return result.trim().replace(/\t+$/gm, '');
|
||||
}
|
||||
|
||||
function getTrailingIndentation ( str ) {
|
||||
function getTrailingIndentation(str) {
|
||||
let i = str.length;
|
||||
while ( str[ i - 1 ] === ' ' || str[ i - 1 ] === '\t' ) i -= 1;
|
||||
return str.slice( 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';
|
||||
|
||||
export default function flatten ( node: Node ) {
|
||||
export default function flatten(node: Node) {
|
||||
const parts = [];
|
||||
const propEnd = node.end;
|
||||
|
||||
while ( node.type === 'MemberExpression' ) {
|
||||
if ( node.computed ) return null;
|
||||
parts.unshift( node.property.name );
|
||||
while (node.type === 'MemberExpression') {
|
||||
if (node.computed) return null;
|
||||
parts.unshift(node.property.name);
|
||||
|
||||
node = node.object;
|
||||
}
|
||||
|
||||
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}✂]` };
|
||||
}
|
||||
|
@ -1,31 +1,36 @@
|
||||
import spaces from './spaces.js';
|
||||
|
||||
function tabsToSpaces ( str: string ) {
|
||||
return str.replace( /^\t+/, match => match.split( '\t' ).join( ' ' ) );
|
||||
function tabsToSpaces(str: string) {
|
||||
return str.replace(/^\t+/, match => match.split('\t').join(' '));
|
||||
}
|
||||
|
||||
export default function getCodeFrame ( source: string, line: number, column: number ) {
|
||||
const lines = source.split( '\n' );
|
||||
export default function getCodeFrame(
|
||||
source: string,
|
||||
line: number,
|
||||
column: number
|
||||
) {
|
||||
const lines = source.split('\n');
|
||||
|
||||
const frameStart = Math.max( 0, line - 2 );
|
||||
const frameEnd = Math.min( line + 3, lines.length );
|
||||
const frameStart = Math.max(0, line - 2);
|
||||
const frameEnd = Math.min(line + 3, lines.length);
|
||||
|
||||
const digits = String( frameEnd + 1 ).length;
|
||||
const digits = String(frameEnd + 1).length;
|
||||
|
||||
return lines
|
||||
.slice( frameStart, frameEnd )
|
||||
.map( ( str, i ) => {
|
||||
.slice(frameStart, frameEnd)
|
||||
.map((str, i) => {
|
||||
const isErrorLine = frameStart + i === line;
|
||||
|
||||
let lineNum = String( i + frameStart + 1 );
|
||||
while ( lineNum.length < digits ) lineNum = ` ${lineNum}`;
|
||||
let lineNum = String(i + frameStart + 1);
|
||||
while (lineNum.length < digits) lineNum = ` ${lineNum}`;
|
||||
|
||||
if ( isErrorLine ) {
|
||||
const indicator = spaces( digits + 2 + tabsToSpaces( str.slice( 0, column ) ).length ) + '^';
|
||||
return `${lineNum}: ${tabsToSpaces( str )}\n${indicator}`;
|
||||
if (isErrorLine) {
|
||||
const 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)$/;
|
||||
|
||||
export default function isVoidElementName ( name: string ) {
|
||||
return voidElementNames.test( name ) || name.toLowerCase() === '!doctype';
|
||||
export default function isVoidElementName(name: string) {
|
||||
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 svg = 'http://www.w3.org/2000/svg';
|
||||
export const xlink = 'http://www.w3.org/1999/xlink';
|
||||
export const xml = 'http://www.w3.org/XML/1998/namespace';
|
||||
export const xmlns = 'http://www.w3.org/2000/xmlns';
|
||||
export const svg = 'http://www.w3.org/2000/svg';
|
||||
export const xlink = 'http://www.w3.org/1999/xlink';
|
||||
export const xml = 'http://www.w3.org/XML/1998/namespace';
|
||||
export const xmlns = 'http://www.w3.org/2000/xmlns';
|
||||
|
||||
export const validNamespaces = [
|
||||
'html', 'mathml', 'svg', 'xlink', 'xml', 'xmlns',
|
||||
html, mathml, svg, xlink, xml, xmlns
|
||||
'html',
|
||||
'mathml',
|
||||
'svg',
|
||||
'xlink',
|
||||
'xml',
|
||||
'xmlns',
|
||||
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
|
||||
reservedNames.add( 'state' );
|
||||
reservedNames.add('state');
|
||||
|
||||
export default reservedNames;
|
||||
export default reservedNames;
|
||||
|
@ -1,5 +1,5 @@
|
||||
export default function spaces ( i ) {
|
||||
export default function spaces(i) {
|
||||
let result = '';
|
||||
while ( i-- ) result += ' ';
|
||||
while (i--) result += ' ';
|
||||
return result;
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { whitespace } from './patterns';
|
||||
|
||||
export function trimStart ( str: string ) {
|
||||
export function trimStart(str: string) {
|
||||
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;
|
||||
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 { 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 ) {
|
||||
while ( prop.type === 'ParenthesizedExpression' ) prop = prop.expression;
|
||||
export default function data(validator: Validator, prop: Node) {
|
||||
while (prop.type === 'ParenthesizedExpression') prop = prop.expression;
|
||||
|
||||
// TODO should we disallow references and expressions as well?
|
||||
|
||||
if ( disallowed.has( prop.value.type ) ) {
|
||||
validator.error( `'data' must be a function`, prop.value.start );
|
||||
if (disallowed.has(prop.value.type)) {
|
||||
validator.error(`'data' must be a function`, prop.value.start);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
import { Validator } from '../../';
|
||||
import { Node } from '../../../interfaces';
|
||||
|
||||
export default function checkForAccessors ( validator: Validator, properties: Node[], label: string ) {
|
||||
properties.forEach( prop => {
|
||||
if ( prop.kind !== 'init' ) {
|
||||
validator.error( `${label} cannot use getters and setters`, prop.start );
|
||||
export default function checkForAccessors(
|
||||
validator: Validator,
|
||||
properties: Node[],
|
||||
label: string
|
||||
) {
|
||||
properties.forEach(prop => {
|
||||
if (prop.kind !== 'init') {
|
||||
validator.error(`${label} cannot use getters and setters`, prop.start);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { Validator } from '../../';
|
||||
import { Node } from '../../../interfaces';
|
||||
|
||||
export default function checkForComputedKeys ( validator: Validator, properties: Node[] ) {
|
||||
properties.forEach( prop => {
|
||||
if ( prop.key.computed ) {
|
||||
validator.error( `Cannot use computed keys`, prop.start );
|
||||
export default function checkForComputedKeys(
|
||||
validator: Validator,
|
||||
properties: Node[]
|
||||
) {
|
||||
properties.forEach(prop => {
|
||||
if (prop.key.computed) {
|
||||
validator.error(`Cannot use computed keys`, prop.start);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue