mirror of https://github.com/sveltejs/svelte
commit
77fb38a123
@ -0,0 +1,9 @@
|
||||
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 );
|
||||
});
|
@ -0,0 +1,11 @@
|
||||
export interface State {
|
||||
name: string;
|
||||
namespace: string;
|
||||
parentNode: string;
|
||||
isTopLevel: boolean
|
||||
parentNodeName?: string;
|
||||
basename?: string;
|
||||
inEachBlock?: boolean;
|
||||
allUsedContexts?: string[];
|
||||
usesComponent?: boolean;
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
// this file is auto-generated, do not edit it
|
||||
export default {
|
||||
"appendNode": "function appendNode ( node, target ) {\n\ttarget.appendChild( node );\n}",
|
||||
"insertNode": "function insertNode ( node, target, anchor ) {\n\ttarget.insertBefore( node, anchor );\n}",
|
||||
"detachNode": "function detachNode ( node ) {\n\tnode.parentNode.removeChild( node );\n}",
|
||||
"detachBetween": "function detachBetween ( before, after ) {\n\twhile ( before.nextSibling && before.nextSibling !== after ) {\n\t\tbefore.parentNode.removeChild( before.nextSibling );\n\t}\n}",
|
||||
"destroyEach": "function destroyEach ( iterations, detach, start ) {\n\tfor ( var i = start; i < iterations.length; i += 1 ) {\n\t\tif ( iterations[i] ) iterations[i].destroy( detach );\n\t}\n}",
|
||||
"createElement": "function createElement ( name ) {\n\treturn document.createElement( name );\n}",
|
||||
"createSvgElement": "function createSvgElement ( name ) {\n\treturn document.createElementNS( 'http://www.w3.org/2000/svg', name );\n}",
|
||||
"createText": "function createText ( data ) {\n\treturn document.createTextNode( data );\n}",
|
||||
"createComment": "function createComment () {\n\treturn document.createComment( '' );\n}",
|
||||
"addEventListener": "function addEventListener ( node, event, handler ) {\n\tnode.addEventListener( event, handler, false );\n}",
|
||||
"removeEventListener": "function removeEventListener ( node, event, handler ) {\n\tnode.removeEventListener( event, handler, false );\n}",
|
||||
"setAttribute": "function setAttribute ( node, attribute, value ) {\n\tnode.setAttribute( attribute, value );\n}",
|
||||
"setXlinkAttribute": "function setXlinkAttribute ( node, attribute, value ) {\n\tnode.setAttributeNS( 'http://www.w3.org/1999/xlink', attribute, value );\n}",
|
||||
"getBindingGroupValue": "function getBindingGroupValue ( group ) {\n\tvar value = [];\n\tfor ( var i = 0; i < group.length; i += 1 ) {\n\t\tif ( group[i].checked ) value.push( group[i].__value );\n\t}\n\treturn value;\n}",
|
||||
"differs": "function differs ( a, b ) {\n\treturn ( a !== b ) || ( a && ( typeof a === 'object' ) || ( typeof a === 'function' ) );\n}",
|
||||
"dispatchObservers": "function dispatchObservers ( component, group, newState, oldState ) {\n\tfor ( var key in group ) {\n\t\tif ( !( key in newState ) ) continue;\n\n\t\tvar newValue = newState[ key ];\n\t\tvar oldValue = oldState[ key ];\n\n\t\tif ( differs( newValue, oldValue ) ) {\n\t\t\tvar callbacks = group[ key ];\n\t\t\tif ( !callbacks ) continue;\n\n\t\t\tfor ( var i = 0; i < callbacks.length; i += 1 ) {\n\t\t\t\tvar callback = callbacks[i];\n\t\t\t\tif ( callback.__calling ) continue;\n\n\t\t\t\tcallback.__calling = true;\n\t\t\t\tcallback.call( component, newValue, oldValue );\n\t\t\t\tcallback.__calling = false;\n\t\t\t}\n\t\t}\n\t}\n}",
|
||||
"get": "function get ( key ) {\n\treturn key ? this._state[ key ] : this._state;\n}",
|
||||
"fire": "function fire ( eventName, data ) {\n\tvar handlers = eventName in this._handlers && this._handlers[ eventName ].slice();\n\tif ( !handlers ) return;\n\n\tfor ( var i = 0; i < handlers.length; i += 1 ) {\n\t\thandlers[i].call( this, data );\n\t}\n}",
|
||||
"observe": "function observe ( key, callback, options ) {\n\tvar group = ( options && options.defer ) ? this._observers.post : this._observers.pre;\n\n\t( group[ key ] || ( group[ key ] = [] ) ).push( callback );\n\n\tif ( !options || options.init !== false ) {\n\t\tcallback.__calling = true;\n\t\tcallback.call( this, this._state[ key ] );\n\t\tcallback.__calling = false;\n\t}\n\n\treturn {\n\t\tcancel: function () {\n\t\t\tvar index = group[ key ].indexOf( callback );\n\t\t\tif ( ~index ) group[ key ].splice( index, 1 );\n\t\t}\n\t};\n}",
|
||||
"observeDev": "function observeDev ( key, callback, options ) {\n\tvar c = ( key = '' + key ).search( /[^\\w]/ );\n\tif ( c > -1 ) {\n\t\tvar message = \"The first argument to component.observe(...) must be the name of a top-level property\";\n\t\tif ( c > 0 ) message += \", i.e. '\" + key.slice( 0, c ) + \"' rather than '\" + key + \"'\";\n\n\t\tthrow new Error( message );\n\t}\n\n\treturn observe.call( this, key, callback, options );\n}",
|
||||
"on": "function on ( eventName, handler ) {\n\tif ( eventName === 'teardown' ) return this.on( 'destroy', handler );\n\n\tvar handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );\n\thandlers.push( handler );\n\n\treturn {\n\t\tcancel: function () {\n\t\t\tvar index = handlers.indexOf( handler );\n\t\t\tif ( ~index ) handlers.splice( index, 1 );\n\t\t}\n\t};\n}",
|
||||
"onDev": "function onDev ( eventName, handler ) {\n\tif ( eventName === 'teardown' ) {\n\t\tconsole.warn( \"Use component.on('destroy', ...) instead of component.on('teardown', ...) which has been deprecated and will be unsupported in Svelte 2\" );\n\t\treturn this.on( 'destroy', handler );\n\t}\n\n\treturn on.call( this, eventName, handler );\n}",
|
||||
"set": "function set ( newState ) {\n\tthis._set( assign( {}, newState ) );\n\tthis._root._flush();\n}",
|
||||
"_flush": "function _flush () {\n\tif ( !this._renderHooks ) return;\n\n\twhile ( this._renderHooks.length ) {\n\t\tthis._renderHooks.pop()();\n\t}\n}",
|
||||
"proto": "{\n\tget: get,\n\tfire: fire,\n\tobserve: observe,\n\ton: on,\n\tset: set,\n\t_flush: _flush\n}",
|
||||
"protoDev": "{\n\tget: get,\n\tfire: fire,\n\tobserve: observeDev,\n\ton: onDev,\n\tset: set,\n\t_flush: _flush\n}",
|
||||
"linear": "function linear ( t ) {\n\treturn t;\n}",
|
||||
"generateKeyframes": "function generateKeyframes ( a, b, delta, duration, ease, fn, node, style ) {\n\tvar id = '__svelte' + ~~( Math.random() * 1e9 ); // TODO make this more robust\n\tvar keyframes = '@keyframes ' + id + '{\\n';\n\n\tfor ( var p = 0; p <= 1; p += 16.666 / duration ) {\n\t\tvar t = a + delta * ease( p );\n\t\tkeyframes += ( p * 100 ) + '%{' + fn( t ) + '}\\n';\n\t}\n\n\tkeyframes += '100% {' + fn( b ) + '}\\n}';\n\tstyle.textContent += keyframes;\n\n\tdocument.head.appendChild( style );\n\n\tnode.style.animation = ( node.style.animation || '' ).split( ',' )\n\t\t.filter( function ( anim ) {\n\t\t\t// when introing, discard old animations if there are any\n\t\t\treturn anim && ( delta < 0 || !/__svelte/.test( anim ) );\n\t\t})\n\t\t.concat( id + ' ' + duration + 'ms linear 1 forwards' )\n\t\t.join( ', ' );\n}",
|
||||
"wrapTransition": "function wrapTransition ( node, fn, params, intro, outgroup ) {\n\tvar obj = fn( node, params );\n\tvar duration = obj.duration || 300;\n\tvar ease = obj.easing || linear;\n\n\t// TODO share <style> tag between all transitions?\n\tif ( obj.css ) {\n\t\tvar style = document.createElement( 'style' );\n\t}\n\n\tif ( intro && obj.tick ) obj.tick( 0 );\n\n\treturn {\n\t\tt: intro ? 0 : 1,\n\t\trunning: false,\n\t\tprogram: null,\n\t\tpending: null,\n\t\trun: function ( intro, callback ) {\n\t\t\tvar program = {\n\t\t\t\tstart: window.performance.now() + ( obj.delay || 0 ),\n\t\t\t\tintro: intro,\n\t\t\t\tcallback: callback\n\t\t\t};\n\n\t\t\tif ( obj.delay ) {\n\t\t\t\tthis.pending = program;\n\t\t\t} else {\n\t\t\t\tthis.start( program );\n\t\t\t}\n\n\t\t\tif ( !this.running ) {\n\t\t\t\tthis.running = true;\n\t\t\t\ttransitionManager.add( this );\n\t\t\t}\n\t\t},\n\t\tstart: function ( program ) {\n\t\t\tprogram.a = this.t;\n\t\t\tprogram.b = program.intro ? 1 : 0;\n\t\t\tprogram.delta = program.b - program.a;\n\t\t\tprogram.duration = duration * Math.abs( program.b - program.a );\n\t\t\tprogram.end = program.start + program.duration;\n\n\t\t\tif ( obj.css ) {\n\t\t\t\tgenerateKeyframes( program.a, program.b, program.delta, program.duration, ease, obj.css, node, style );\n\t\t\t}\n\n\t\t\tthis.program = program;\n\t\t\tthis.pending = null;\n\t\t},\n\t\tupdate: function ( now ) {\n\t\t\tvar program = this.program;\n\t\t\tif ( !program ) return;\n\n\t\t\tvar p = now - program.start;\n\t\t\tthis.t = program.a + program.delta * ease( p / program.duration );\n\t\t\tif ( obj.tick ) obj.tick( this.t );\n\t\t},\n\t\tdone: function () {\n\t\t\tthis.t = this.program.b;\n\t\t\tif ( obj.tick ) obj.tick( this.t );\n\t\t\tif ( obj.css ) document.head.removeChild( style );\n\t\t\tthis.program.callback();\n\t\t\tthis.program = null;\n\t\t\tthis.running = !!this.pending;\n\t\t},\n\t\tabort: function () {\n\t\t\tif ( obj.tick ) obj.tick( 1 );\n\t\t\tif ( obj.css ) document.head.removeChild( style );\n\t\t\tthis.program = this.pending = null;\n\t\t\tthis.running = false;\n\t\t}\n\t};\n}",
|
||||
"transitionManager": "{\n\trunning: false,\n\ttransitions: [],\n\tbound: null,\n\n\tadd: function ( transition ) {\n\t\tthis.transitions.push( transition );\n\n\t\tif ( !this.running ) {\n\t\t\tthis.running = true;\n\t\t\tthis.next();\n\t\t}\n\t},\n\n\tnext: function () {\n\t\tthis.running = false;\n\n\t\tvar now = window.performance.now();\n\t\tvar i = this.transitions.length;\n\n\t\twhile ( i-- ) {\n\t\t\tvar transition = this.transitions[i];\n\n\t\t\tif ( transition.program && now >= transition.program.end ) {\n\t\t\t\ttransition.done();\n\t\t\t}\n\n\t\t\tif ( transition.pending && now >= transition.pending.start ) {\n\t\t\t\ttransition.start( transition.pending );\n\t\t\t}\n\n\t\t\tif ( transition.running ) {\n\t\t\t\ttransition.update( now );\n\t\t\t\tthis.running = true;\n\t\t\t} else if ( !transition.pending ) {\n\t\t\t\tthis.transitions.splice( i, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( this.running ) {\n\t\t\trequestAnimationFrame( this.bound || ( this.bound = this.next.bind( this ) ) );\n\t\t}\n\t}\n}",
|
||||
"noop": "function noop () {}",
|
||||
"assign": "function assign ( target ) {\n\tfor ( var i = 1; i < arguments.length; i += 1 ) {\n\t\tvar source = arguments[i];\n\t\tfor ( var k in source ) target[k] = source[k];\n\t}\n\n\treturn target;\n}"
|
||||
};
|
@ -1,6 +0,0 @@
|
||||
import visitors from './visitors/index.js';
|
||||
|
||||
export default function visit ( generator, block, state, node ) {
|
||||
const visitor = visitors[ node.type ];
|
||||
visitor( generator, block, state, node );
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import visitors from './visitors/index';
|
||||
import { DomGenerator } from './index';
|
||||
import Block from './Block';
|
||||
import { Node } from '../../interfaces';
|
||||
|
||||
export default function visit ( generator: DomGenerator, block: Block, state, node: Node ) {
|
||||
const visitor = visitors[ node.type ];
|
||||
visitor( generator, block, state, node );
|
||||
}
|
@ -1,4 +1,9 @@
|
||||
export default function visitAttribute ( generator, block, state, node, attribute, local ) {
|
||||
import { DomGenerator } from '../../index';
|
||||
import Block from '../../Block';
|
||||
import { Node } from '../../../../interfaces';
|
||||
import { State } from '../../interfaces';
|
||||
|
||||
export default function visitAttribute ( generator: DomGenerator, block: Block, state: State, node: Node, attribute, local ) {
|
||||
if ( attribute.value === true ) {
|
||||
// attributes without values, e.g. <textarea readonly>
|
||||
local.staticAttributes.push({
|
@ -1,8 +1,12 @@
|
||||
import deindent from '../../../../utils/deindent.js';
|
||||
import flattenReference from '../../../../utils/flattenReference.js';
|
||||
import getSetter from '../shared/binding/getSetter.js';
|
||||
import flattenReference from '../../../../utils/flattenReference';
|
||||
import getSetter from '../shared/binding/getSetter';
|
||||
import { DomGenerator } from '../../index';
|
||||
import Block from '../../Block';
|
||||
import { Node } from '../../../../interfaces';
|
||||
import { State } from '../../interfaces';
|
||||
|
||||
export default function visitBinding ( generator, block, state, node, attribute, local ) {
|
||||
export default function visitBinding ( generator: DomGenerator, block: Block, state: State, node: Node, attribute, local ) {
|
||||
const { name } = flattenReference( attribute.value );
|
||||
const { snippet, contexts, dependencies } = block.contextualise( attribute.value );
|
||||
|
@ -1,12 +1,16 @@
|
||||
import deindent from '../../../../utils/deindent.js';
|
||||
import { DomGenerator } from '../../index';
|
||||
import Block from '../../Block';
|
||||
import { Node } from '../../../../interfaces';
|
||||
import { State } from '../../interfaces';
|
||||
|
||||
export default function visitEventHandler ( generator, block, state, node, attribute, 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)
|
||||
generator.addSourcemapLocations( attribute.expression );
|
||||
generator.code.prependRight( attribute.expression.start, `${block.component}.` );
|
||||
|
||||
const usedContexts = [];
|
||||
attribute.expression.arguments.forEach( arg => {
|
||||
const usedContexts: string[] = [];
|
||||
attribute.expression.arguments.forEach( ( arg: Node ) => {
|
||||
const { contexts } = block.contextualise( arg, null, true );
|
||||
|
||||
contexts.forEach( context => {
|
@ -1,6 +1,10 @@
|
||||
import deindent from '../../../../utils/deindent.js';
|
||||
import { DomGenerator } from '../../index';
|
||||
import Block from '../../Block';
|
||||
import { Node } from '../../../../interfaces';
|
||||
import { State } from '../../interfaces';
|
||||
|
||||
export default function visitRef ( generator, block, state, node, attribute, local ) {
|
||||
export default function visitRef ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node, local ) {
|
||||
generator.usesRefs = true;
|
||||
|
||||
local.create.addLine(
|
@ -1,6 +1,10 @@
|
||||
import deindent from '../../../../utils/deindent.js';
|
||||
import { DomGenerator } from '../../index';
|
||||
import Block from '../../Block';
|
||||
import { Node } from '../../../../interfaces';
|
||||
import { State } from '../../interfaces';
|
||||
|
||||
export default function visitRef ( generator, block, state, node, attribute ) {
|
||||
export default function visitRef ( generator: DomGenerator, block: Block, state: State, node: Node, attribute: Node ) {
|
||||
const name = attribute.name;
|
||||
|
||||
block.builders.create.addLine(
|
@ -1,6 +1,10 @@
|
||||
import deindent from '../../../../utils/deindent.js';
|
||||
import { DomGenerator } from '../../index';
|
||||
import Block from '../../Block';
|
||||
import { Node } from '../../../../interfaces';
|
||||
import { State } from '../../interfaces';
|
||||
|
||||
export default function addTransitions ( generator, block, state, node, intro, outro ) {
|
||||
export default function addTransitions ( generator: DomGenerator, block: Block, state: State, node: Node, intro, outro ) {
|
||||
const wrapTransition = generator.helper( 'wrapTransition' );
|
||||
|
||||
if ( intro === outro ) {
|
@ -1,5 +1,7 @@
|
||||
export default function getStaticAttributeValue ( node, name ) {
|
||||
const attribute = node.attributes.find( attr => attr.name.toLowerCase() === name );
|
||||
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;
|
||||
|
||||
if ( attribute.value.length !== 1 || attribute.value[0].type !== 'Text' ) {
|
@ -1,6 +1,10 @@
|
||||
import deindent from '../../../utils/deindent.js';
|
||||
import { DomGenerator } from '../index';
|
||||
import Block from '../Block';
|
||||
import { Node } from '../../../interfaces';
|
||||
import { State } from '../interfaces';
|
||||
|
||||
export default function visitMustacheTag ( generator, block, state, node ) {
|
||||
export default function visitMustacheTag ( generator: DomGenerator, block: Block, state: State, node: Node ) {
|
||||
const name = node._state.name;
|
||||
const value = block.getUniqueName( `${name}_value` );
|
||||
|
@ -1,6 +1,10 @@
|
||||
import deindent from '../../../utils/deindent.js';
|
||||
import { DomGenerator } from '../index';
|
||||
import Block from '../Block';
|
||||
import { Node } from '../../../interfaces';
|
||||
import { State } from '../interfaces';
|
||||
|
||||
export default function visitRawMustacheTag ( generator, block, state, node ) {
|
||||
export default function visitRawMustacheTag ( generator: DomGenerator, block: Block, state: State, node: Node ) {
|
||||
const name = node._state.basename;
|
||||
const before = node._state.name;
|
||||
const value = block.getUniqueName( `${name}_value` );
|
@ -1,6 +0,0 @@
|
||||
|
||||
|
||||
export default function visitText ( generator, block, state, node ) {
|
||||
if ( !node._state.shouldCreate ) return;
|
||||
block.addElement( node._state.name, `${generator.helper( 'createText' )}( ${JSON.stringify( node.data )} )`, state.parentNode, node.usedAsAnchor );
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import { DomGenerator } from '../index';
|
||||
import Block from '../Block';
|
||||
import { Node } from '../../../interfaces';
|
||||
import { State } from '../interfaces';
|
||||
|
||||
export default function visitText ( generator: DomGenerator, block: Block, state: State, node: Node ) {
|
||||
if ( !node._state.shouldCreate ) return;
|
||||
block.addElement( node._state.name, `${generator.helper( 'createText' )}( ${JSON.stringify( node.data )} )`, state.parentNode, node.usedAsAnchor );
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
export default function visitYieldTag ( generator, block, state ) {
|
||||
import { DomGenerator } from '../index';
|
||||
import Block from '../Block';
|
||||
import { State } from '../interfaces';
|
||||
|
||||
export default function visitYieldTag ( generator: DomGenerator, block: Block, state: State ) {
|
||||
const parentNode = state.parentNode || block.target;
|
||||
|
||||
( state.parentNode ? block.builders.create : block.builders.mount ).addLine(
|
@ -1,17 +0,0 @@
|
||||
import EachBlock from './EachBlock.js';
|
||||
import Element from './Element/Element.js';
|
||||
import IfBlock from './IfBlock.js';
|
||||
import MustacheTag from './MustacheTag.js';
|
||||
import RawMustacheTag from './RawMustacheTag.js';
|
||||
import Text from './Text.js';
|
||||
import YieldTag from './YieldTag.js';
|
||||
|
||||
export default {
|
||||
EachBlock,
|
||||
Element,
|
||||
IfBlock,
|
||||
MustacheTag,
|
||||
RawMustacheTag,
|
||||
Text,
|
||||
YieldTag
|
||||
};
|
@ -0,0 +1,17 @@
|
||||
import EachBlock from './EachBlock';
|
||||
import Element from './Element/Element';
|
||||
import IfBlock from './IfBlock';
|
||||
import MustacheTag from './MustacheTag';
|
||||
import RawMustacheTag from './RawMustacheTag';
|
||||
import Text from './Text';
|
||||
import YieldTag from './YieldTag';
|
||||
|
||||
export default {
|
||||
EachBlock,
|
||||
Element,
|
||||
IfBlock,
|
||||
MustacheTag,
|
||||
RawMustacheTag,
|
||||
Text,
|
||||
YieldTag
|
||||
};
|
@ -1,6 +0,0 @@
|
||||
import visitors from './visitors/index.js';
|
||||
|
||||
export default function visit ( generator, fragment, node ) {
|
||||
const visitor = visitors[ node.type ];
|
||||
visitor( generator, fragment, node );
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import visitors from './visitors/index';
|
||||
import { SsrGenerator } from './index';
|
||||
import Block from './Block';
|
||||
import { Node } from '../../interfaces';
|
||||
|
||||
export default function visit ( generator: SsrGenerator, block: Block, node: Node ) {
|
||||
const visitor = visitors[ node.type ];
|
||||
visitor( generator, block, node );
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
export default function visitMustacheTag ( generator, block, node ) {
|
||||
const { snippet } = block.contextualise( node.expression );
|
||||
generator.append( '${__escape( ' + snippet + ' )}' );
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { SsrGenerator } from '../index';
|
||||
import Block from '../Block';
|
||||
import { Node } from '../../../interfaces';
|
||||
|
||||
export default function visitMustacheTag ( generator: SsrGenerator, block: Block, node: Node ) {
|
||||
const { snippet } = block.contextualise( node.expression );
|
||||
generator.append( '${__escape( ' + snippet + ' )}' );
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
export default function visitRawMustacheTag ( generator, block, node ) {
|
||||
const { snippet } = block.contextualise( node.expression );
|
||||
generator.append( '${' + snippet + '}' );
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { SsrGenerator } from '../index';
|
||||
import Block from '../Block';
|
||||
import { Node } from '../../../interfaces';
|
||||
|
||||
export default function visitRawMustacheTag ( generator: SsrGenerator, block: Block, node: Node ) {
|
||||
const { snippet } = block.contextualise( node.expression );
|
||||
generator.append( '${' + snippet + '}' );
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export default function visitText ( generator, block, node ) {
|
||||
generator.append( node.data.replace( /\${/g, '\\${' ) );
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
import { SsrGenerator } from '../index';
|
||||
import Block from '../Block';
|
||||
import { Node } from '../../../interfaces';
|
||||
|
||||
export default function visitText ( generator: SsrGenerator, block: Block, node: Node ) {
|
||||
generator.append( node.data.replace( /\${/g, '\\${' ) );
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export default function visitYieldTag ( generator ) {
|
||||
generator.append( `\${options && options.yield ? options.yield() : ''}` );
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { SsrGenerator } from '../index';
|
||||
|
||||
export default function visitYieldTag ( generator: SsrGenerator ) {
|
||||
generator.append( `\${options && options.yield ? options.yield() : ''}` );
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
import Comment from './Comment.js';
|
||||
import EachBlock from './EachBlock.js';
|
||||
import Element from './Element.js';
|
||||
import IfBlock from './IfBlock.js';
|
||||
import MustacheTag from './MustacheTag.js';
|
||||
import RawMustacheTag from './RawMustacheTag.js';
|
||||
import Text from './Text.js';
|
||||
import YieldTag from './YieldTag.js';
|
||||
|
||||
export default {
|
||||
Comment,
|
||||
EachBlock,
|
||||
Element,
|
||||
IfBlock,
|
||||
MustacheTag,
|
||||
RawMustacheTag,
|
||||
Text,
|
||||
YieldTag
|
||||
};
|
@ -0,0 +1,19 @@
|
||||
import Comment from './Comment';
|
||||
import EachBlock from './EachBlock';
|
||||
import Element from './Element';
|
||||
import IfBlock from './IfBlock';
|
||||
import MustacheTag from './MustacheTag';
|
||||
import RawMustacheTag from './RawMustacheTag';
|
||||
import Text from './Text';
|
||||
import YieldTag from './YieldTag';
|
||||
|
||||
export default {
|
||||
Comment,
|
||||
EachBlock,
|
||||
Element,
|
||||
IfBlock,
|
||||
MustacheTag,
|
||||
RawMustacheTag,
|
||||
Text,
|
||||
YieldTag
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import getGlobals from './getGlobals.js';
|
||||
import getGlobals from './getGlobals';
|
||||
|
||||
export default function getOutro ( format, name, options, imports ) {
|
||||
export default function getOutro ( format: string, name: string, options, imports ) {
|
||||
if ( format === 'es' ) {
|
||||
return `export default ${name};`;
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
export default function walkHtml ( html, visitors ) {
|
||||
function visit ( node ) {
|
||||
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}` );
|
||||
|
||||
if ( visitor.enter ) visitor.enter( node );
|
||||
|
||||
if ( node.children ) {
|
||||
node.children.forEach( child => {
|
||||
node.children.forEach( ( child: Node ) => {
|
||||
visit( child );
|
||||
});
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
export interface Node {
|
||||
start: number;
|
||||
end: number;
|
||||
type: string;
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
export interface Parser {
|
||||
readonly template: string;
|
||||
readonly filename?: string;
|
||||
|
||||
index: number;
|
||||
stack: Array<Node>;
|
||||
|
||||
html: Node;
|
||||
css: Node;
|
||||
js: Node;
|
||||
metaTags: {};
|
||||
}
|
||||
|
||||
export interface Parsed {
|
||||
hash: number;
|
||||
html: Node;
|
||||
css: Node;
|
||||
js: Node;
|
||||
}
|
||||
|
||||
export interface Warning {
|
||||
loc?: {line: number, column: number, pos: number};
|
||||
message: string
|
||||
filename?: string
|
||||
toString: () => string
|
||||
}
|
||||
|
||||
export interface CompileOptions {
|
||||
format?: string;
|
||||
name?: string;
|
||||
filename?: string;
|
||||
generate?: string;
|
||||
|
||||
dev?: boolean;
|
||||
shared?: boolean | string;
|
||||
|
||||
onerror?: (error: Error) => void
|
||||
onwarn?: (warning: Warning) => void
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
import { locate } from 'locate-character';
|
||||
import fragment from './state/fragment.js';
|
||||
import { whitespace } from '../utils/patterns.js';
|
||||
import { trimStart, trimEnd } from '../utils/trim.js';
|
||||
import getCodeFrame from '../utils/getCodeFrame.js';
|
||||
import hash from './utils/hash.js';
|
||||
|
||||
function ParseError ( message, template, index, filename ) {
|
||||
const { line, column } = locate( template, index );
|
||||
|
||||
this.name = 'ParseError';
|
||||
this.message = message;
|
||||
this.frame = getCodeFrame( template, line, column );
|
||||
|
||||
this.loc = { line: line + 1, column };
|
||||
this.pos = index;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
ParseError.prototype.toString = function () {
|
||||
return `${this.message} (${this.loc.line}:${this.loc.column})\n${this.frame}`;
|
||||
};
|
||||
|
||||
export default function parse ( template, options = {} ) {
|
||||
if ( typeof template !== 'string' ) {
|
||||
throw new TypeError( 'Template must be a string' );
|
||||
}
|
||||
|
||||
template = template.replace( /\s+$/, '' );
|
||||
|
||||
const parser = {
|
||||
index: 0,
|
||||
template,
|
||||
stack: [],
|
||||
metaTags: {},
|
||||
|
||||
current () {
|
||||
return this.stack[ this.stack.length - 1 ];
|
||||
},
|
||||
|
||||
acornError ( err ) {
|
||||
parser.error( err.message.replace( / \(\d+:\d+\)$/, '' ), err.pos );
|
||||
},
|
||||
|
||||
error ( message, index = this.index ) {
|
||||
throw new ParseError( message, this.template, index, options.filename );
|
||||
},
|
||||
|
||||
eat ( str, required ) {
|
||||
if ( this.match( str ) ) {
|
||||
this.index += str.length;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( required ) {
|
||||
this.error( `Expected ${str}` );
|
||||
}
|
||||
},
|
||||
|
||||
match ( str ) {
|
||||
return this.template.slice( this.index, this.index + str.length ) === str;
|
||||
},
|
||||
|
||||
allowWhitespace () {
|
||||
while ( this.index < this.template.length && whitespace.test( this.template[ this.index ] ) ) {
|
||||
this.index++;
|
||||
}
|
||||
},
|
||||
|
||||
read ( pattern ) {
|
||||
const match = pattern.exec( this.template.slice( this.index ) );
|
||||
if ( !match || match.index !== 0 ) return null;
|
||||
|
||||
parser.index += match[0].length;
|
||||
|
||||
return match[0];
|
||||
},
|
||||
|
||||
readUntil ( pattern ) {
|
||||
if ( this.index >= this.template.length ) parser.error( 'Unexpected end of input' );
|
||||
|
||||
const start = this.index;
|
||||
const match = pattern.exec( this.template.slice( start ) );
|
||||
|
||||
if ( match ) {
|
||||
const start = this.index;
|
||||
this.index = start + match.index;
|
||||
return this.template.slice( start, this.index );
|
||||
}
|
||||
|
||||
this.index = this.template.length;
|
||||
return this.template.slice( start );
|
||||
},
|
||||
|
||||
remaining () {
|
||||
return this.template.slice( this.index );
|
||||
},
|
||||
|
||||
requireWhitespace () {
|
||||
if ( !whitespace.test( this.template[ this.index ] ) ) {
|
||||
this.error( `Expected whitespace` );
|
||||
}
|
||||
|
||||
this.allowWhitespace();
|
||||
},
|
||||
|
||||
html: {
|
||||
start: null,
|
||||
end: null,
|
||||
type: 'Fragment',
|
||||
children: []
|
||||
},
|
||||
|
||||
css: null,
|
||||
|
||||
js: null
|
||||
};
|
||||
|
||||
parser.stack.push( parser.html );
|
||||
|
||||
let state = fragment;
|
||||
|
||||
while ( parser.index < parser.template.length ) {
|
||||
state = state( parser ) || fragment;
|
||||
}
|
||||
|
||||
if ( parser.stack.length > 1 ) {
|
||||
const current = parser.current();
|
||||
|
||||
const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
|
||||
parser.error( `${type} was left open`, current.start );
|
||||
}
|
||||
|
||||
if ( state !== fragment ) {
|
||||
parser.error( 'Unexpected end of input' );
|
||||
}
|
||||
|
||||
// trim unnecessary whitespace
|
||||
while ( parser.html.children.length ) {
|
||||
const firstChild = parser.html.children[0];
|
||||
parser.html.start = firstChild.start;
|
||||
|
||||
if ( firstChild.type !== 'Text' ) break;
|
||||
|
||||
const length = firstChild.data.length;
|
||||
firstChild.data = trimStart( firstChild.data );
|
||||
|
||||
if ( firstChild.data === '' ) {
|
||||
parser.html.children.shift();
|
||||
} else {
|
||||
parser.html.start += length - firstChild.data.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while ( parser.html.children.length ) {
|
||||
const lastChild = parser.html.children[ parser.html.children.length - 1 ];
|
||||
parser.html.end = lastChild.end;
|
||||
|
||||
if ( lastChild.type !== 'Text' ) break;
|
||||
|
||||
const length = lastChild.data.length;
|
||||
lastChild.data = trimEnd( lastChild.data );
|
||||
|
||||
if ( lastChild.data === '' ) {
|
||||
parser.html.children.pop();
|
||||
} else {
|
||||
parser.html.end -= length - lastChild.data.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
hash: hash( template ),
|
||||
html: parser.html,
|
||||
css: parser.css,
|
||||
js: parser.js
|
||||
};
|
||||
}
|
@ -0,0 +1,190 @@
|
||||
import { locate, Location } from 'locate-character';
|
||||
import fragment from './state/fragment';
|
||||
import { whitespace } from '../utils/patterns';
|
||||
import { trimStart, trimEnd } from '../utils/trim';
|
||||
import getCodeFrame from '../utils/getCodeFrame';
|
||||
import hash from './utils/hash';
|
||||
import { Node, Parsed } from '../interfaces';
|
||||
import CompileError from '../utils/CompileError'
|
||||
|
||||
class ParseError extends CompileError {
|
||||
constructor ( message: string, template: string, index: number, filename: string ) {
|
||||
super( message, template, index, filename );
|
||||
this.name = 'ParseError';
|
||||
}
|
||||
}
|
||||
|
||||
interface ParserOptions {
|
||||
filename?: string
|
||||
}
|
||||
|
||||
export class Parser {
|
||||
readonly template: string;
|
||||
readonly filename?: string;
|
||||
|
||||
index: number;
|
||||
stack: Array<Node>;
|
||||
|
||||
html: Node;
|
||||
css: Node;
|
||||
js: Node;
|
||||
metaTags: {}
|
||||
|
||||
constructor ( template: string, options: ParserOptions ) {
|
||||
if ( typeof template !== 'string' ) {
|
||||
throw new TypeError( 'Template must be a string' );
|
||||
}
|
||||
|
||||
this.template = template.replace( /\s+$/, '' );
|
||||
this.filename = options.filename;
|
||||
|
||||
this.index = 0;
|
||||
this.stack = [];
|
||||
this.metaTags = {};
|
||||
|
||||
this.html = {
|
||||
start: null,
|
||||
end: null,
|
||||
type: 'Fragment',
|
||||
children: []
|
||||
};
|
||||
|
||||
this.css = null;
|
||||
this.js = null;
|
||||
|
||||
this.stack.push( this.html );
|
||||
|
||||
let state = fragment;
|
||||
|
||||
while ( this.index < this.template.length ) {
|
||||
state = state( this ) || fragment;
|
||||
}
|
||||
|
||||
if ( this.stack.length > 1 ) {
|
||||
const current = this.current();
|
||||
|
||||
const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
|
||||
this.error( `${type} was left open`, current.start );
|
||||
}
|
||||
|
||||
if ( state !== fragment ) {
|
||||
this.error( 'Unexpected end of input' );
|
||||
}
|
||||
|
||||
// trim unnecessary whitespace
|
||||
while ( this.html.children.length ) {
|
||||
const firstChild = this.html.children[0];
|
||||
this.html.start = firstChild.start;
|
||||
|
||||
if ( firstChild.type !== 'Text' ) break;
|
||||
|
||||
const length = firstChild.data.length;
|
||||
firstChild.data = trimStart( firstChild.data );
|
||||
|
||||
if ( firstChild.data === '' ) {
|
||||
this.html.children.shift();
|
||||
} else {
|
||||
this.html.start += length - firstChild.data.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while ( this.html.children.length ) {
|
||||
const lastChild = this.html.children[ this.html.children.length - 1 ];
|
||||
this.html.end = lastChild.end;
|
||||
|
||||
if ( lastChild.type !== 'Text' ) break;
|
||||
|
||||
const length = lastChild.data.length;
|
||||
lastChild.data = trimEnd( lastChild.data );
|
||||
|
||||
if ( lastChild.data === '' ) {
|
||||
this.html.children.pop();
|
||||
} else {
|
||||
this.html.end -= length - lastChild.data.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current () {
|
||||
return this.stack[ this.stack.length - 1 ];
|
||||
}
|
||||
|
||||
acornError ( err: Error ) {
|
||||
this.error( err.message.replace( / \(\d+:\d+\)$/, '' ), err.pos );
|
||||
}
|
||||
|
||||
error ( message: string, index = this.index ) {
|
||||
throw new ParseError( message, this.template, index, this.filename );
|
||||
}
|
||||
|
||||
eat ( str: string, required?: boolean ) {
|
||||
if ( this.match( str ) ) {
|
||||
this.index += str.length;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( required ) {
|
||||
this.error( `Expected ${str}` );
|
||||
}
|
||||
}
|
||||
|
||||
match ( str: string ) {
|
||||
return this.template.slice( this.index, this.index + str.length ) === str;
|
||||
}
|
||||
|
||||
allowWhitespace () {
|
||||
while ( this.index < this.template.length && whitespace.test( this.template[ this.index ] ) ) {
|
||||
this.index++;
|
||||
}
|
||||
}
|
||||
|
||||
read ( pattern: RegExp ) {
|
||||
const match = pattern.exec( this.template.slice( this.index ) );
|
||||
if ( !match || match.index !== 0 ) return null;
|
||||
|
||||
this.index += match[0].length;
|
||||
|
||||
return match[0];
|
||||
}
|
||||
|
||||
readUntil ( pattern: RegExp ) {
|
||||
if ( this.index >= this.template.length ) this.error( 'Unexpected end of input' );
|
||||
|
||||
const start = this.index;
|
||||
const match = pattern.exec( this.template.slice( start ) );
|
||||
|
||||
if ( match ) {
|
||||
const start = this.index;
|
||||
this.index = start + match.index;
|
||||
return this.template.slice( start, this.index );
|
||||
}
|
||||
|
||||
this.index = this.template.length;
|
||||
return this.template.slice( start );
|
||||
}
|
||||
|
||||
remaining () {
|
||||
return this.template.slice( this.index );
|
||||
}
|
||||
|
||||
requireWhitespace () {
|
||||
if ( !whitespace.test( this.template[ this.index ] ) ) {
|
||||
this.error( `Expected whitespace` );
|
||||
}
|
||||
|
||||
this.allowWhitespace();
|
||||
}
|
||||
}
|
||||
|
||||
export default function parse ( template: string, options: ParserOptions = {} ) :Parsed {
|
||||
const parser = new Parser( template, options );
|
||||
|
||||
return {
|
||||
hash: hash( parser.template ),
|
||||
html: parser.html,
|
||||
css: parser.css,
|
||||
js: parser.js
|
||||
};
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
import { parse } from 'acorn';
|
||||
import spaces from '../../utils/spaces.js';
|
||||
import { Parser } from '../index';
|
||||
|
||||
const scriptClosingTag = '<\/script>';
|
||||
|
||||
export default function readScript ( parser, start, attributes ) {
|
||||
export default function readScript ( parser: Parser, start: number, attributes ) {
|
||||
const scriptStart = parser.index;
|
||||
const scriptEnd = parser.template.indexOf( scriptClosingTag, scriptStart );
|
||||
|
@ -1,7 +1,8 @@
|
||||
import parse from 'css-tree/lib/parser/index.js';
|
||||
import walk from 'css-tree/lib/utils/walk.js';
|
||||
import { Parser } from '../index';
|
||||
|
||||
export default function readStyle ( parser, start, attributes ) {
|
||||
export default function readStyle ( parser: Parser, start: number, attributes ) {
|
||||
const contentStart = parser.index;
|
||||
const styles = parser.readUntil( /<\/style>/ );
|
||||
const contentEnd = parser.index;
|
@ -1,15 +0,0 @@
|
||||
import tag from './tag.js';
|
||||
import mustache from './mustache.js';
|
||||
import text from './text.js';
|
||||
|
||||
export default function fragment ( parser ) {
|
||||
if ( parser.match( '<' ) ) {
|
||||
return tag;
|
||||
}
|
||||
|
||||
if ( parser.match( '{{' ) ) {
|
||||
return mustache;
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import tag from './tag';
|
||||
import mustache from './mustache';
|
||||
import text from './text';
|
||||
import { Parser } from '../index';
|
||||
|
||||
export default function fragment ( parser: Parser ) {
|
||||
if ( parser.match( '<' ) ) {
|
||||
return tag;
|
||||
}
|
||||
|
||||
if ( parser.match( '{{' ) ) {
|
||||
return mustache;
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import { decodeCharacterReferences } from '../utils/html.js';
|
||||
import { decodeCharacterReferences } from '../utils/html';
|
||||
import { Parser } from '../index';
|
||||
|
||||
export default function text ( parser ) {
|
||||
export default function text ( parser: Parser ) {
|
||||
const start = parser.index;
|
||||
|
||||
let data = '';
|
@ -1,5 +1,5 @@
|
||||
// https://github.com/darkskyapp/string-hash/blob/master/index.js
|
||||
export default function hash ( str ) {
|
||||
export default function hash ( str: string ) :number {
|
||||
let hash = 5381;
|
||||
let i = str.length;
|
||||
|
@ -0,0 +1,25 @@
|
||||
import { locate } from 'locate-character';
|
||||
import getCodeFrame from '../utils/getCodeFrame';
|
||||
|
||||
export default class CompileError extends Error {
|
||||
frame: string
|
||||
loc: { line: number, column: number }
|
||||
pos: number
|
||||
filename: string
|
||||
|
||||
constructor ( message: string, template: string, index: number, filename: string ) {
|
||||
super( message );
|
||||
|
||||
const { line, column } = locate( template, index );
|
||||
|
||||
this.loc = { line: line + 1, column };
|
||||
this.pos = index;
|
||||
this.filename = filename;
|
||||
|
||||
this.frame = getCodeFrame( template, line, column );
|
||||
}
|
||||
|
||||
toString () {
|
||||
return `${this.message} (${this.loc.line}:${this.loc.column})\n${this.frame}`;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import * as assert from 'assert';
|
||||
import deindent from './deindent.js';
|
||||
import CodeBuilder from './CodeBuilder.js';
|
||||
import CodeBuilder from './CodeBuilder';
|
||||
|
||||
describe( 'deindent', () => {
|
||||
it( 'deindents a simple string', () => {
|
@ -1,4 +1,6 @@
|
||||
export default function flatten ( node ) {
|
||||
import { Node } from '../interfaces';
|
||||
|
||||
export default function flatten ( node: Node ) {
|
||||
const parts = [];
|
||||
const propEnd = node.end;
|
||||
|
@ -1,10 +1,10 @@
|
||||
import spaces from './spaces.js';
|
||||
|
||||
function tabsToSpaces ( str ) {
|
||||
function tabsToSpaces ( str: string ) {
|
||||
return str.replace( /^\t+/, match => match.split( '\t' ).join( ' ' ) );
|
||||
}
|
||||
|
||||
export default function getCodeFrame ( source, line, column ) {
|
||||
export default function getCodeFrame ( source: string, line: number, column: number ) {
|
||||
const lines = source.split( '\n' );
|
||||
|
||||
const frameStart = Math.max( 0, line - 2 );
|
@ -1,4 +1,6 @@
|
||||
export default function isReference ( node, parent ) {
|
||||
import { Node } from '../interfaces';
|
||||
|
||||
export default function isReference ( node: Node, parent: Node ): boolean {
|
||||
if ( node.type === 'MemberExpression' ) {
|
||||
return !node.computed && isReference( node.object, node );
|
||||
}
|
@ -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 ) {
|
||||
export default function isVoidElementName ( name: string ) {
|
||||
return voidElementNames.test( name ) || name.toLowerCase() === '!doctype';
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
import deindent from './deindent.js';
|
||||
|
||||
export default function toSource ( thing ) {
|
||||
if ( typeof thing === 'function' ) {
|
||||
return normaliseIndentation( thing.toString() );
|
||||
}
|
||||
|
||||
if ( Array.isArray( thing ) ) {
|
||||
if ( thing.length === 0 ) return '[]';
|
||||
throw new Error( 'TODO' ); // not currently needed
|
||||
}
|
||||
|
||||
if ( thing && typeof thing === 'object' ) {
|
||||
const keys = Object.keys( thing );
|
||||
if ( keys.length === 0 ) return '{}';
|
||||
|
||||
const props = keys.map( key => `${key}: ${toSource( thing[ key ] )}` ).join( ',\n' );
|
||||
return deindent`
|
||||
{
|
||||
${props}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
return JSON.stringify( thing );
|
||||
}
|
||||
|
||||
function normaliseIndentation ( str ) {
|
||||
const lines = str.split( '\n' ).slice( 1, -1 );
|
||||
let minIndentation = Infinity;
|
||||
|
||||
lines.forEach( line => {
|
||||
if ( !/\S/.test( line ) ) return;
|
||||
const indentation = /^\t*/.exec( line )[0].length;
|
||||
if ( indentation < minIndentation ) minIndentation = indentation;
|
||||
});
|
||||
|
||||
if ( minIndentation !== Infinity && minIndentation !== 1 ) {
|
||||
const pattern = new RegExp( `^\\t{${minIndentation - 1}}`, 'gm' );
|
||||
return str.replace( pattern, '' );
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
import { whitespace } from './patterns.js';
|
||||
import { whitespace } from './patterns';
|
||||
|
||||
export function trimStart ( str ) {
|
||||
export function trimStart ( str: string ) {
|
||||
let i = 0;
|
||||
while ( whitespace.test( str[i] ) ) i += 1;
|
||||
|
||||
return str.slice( i );
|
||||
}
|
||||
|
||||
export function trimEnd ( str ) {
|
||||
export function trimEnd ( str: string ) {
|
||||
let i = str.length;
|
||||
while ( whitespace.test( str[ i - 1 ] ) ) i -= 1;
|
||||
|
@ -1,79 +0,0 @@
|
||||
import validateJs from './js/index.js';
|
||||
import validateHtml from './html/index.js';
|
||||
import { getLocator } from 'locate-character';
|
||||
import getCodeFrame from '../utils/getCodeFrame.js';
|
||||
|
||||
export default function validate ( parsed, source, { onerror, onwarn, name, filename } ) {
|
||||
const locator = getLocator( source );
|
||||
|
||||
const validator = {
|
||||
error: ( message, pos ) => {
|
||||
const { line, column } = locator( pos );
|
||||
|
||||
const error = new Error( message );
|
||||
error.frame = getCodeFrame( source, line, column );
|
||||
error.loc = { line: line + 1, column };
|
||||
error.pos = pos;
|
||||
error.filename = filename;
|
||||
|
||||
error.toString = () => `${error.message} (${error.loc.line}:${error.loc.column})\n${error.frame}`;
|
||||
|
||||
throw error;
|
||||
},
|
||||
|
||||
warn: ( message, pos ) => {
|
||||
const { line, column } = locator( pos );
|
||||
|
||||
const frame = getCodeFrame( source, line, column );
|
||||
|
||||
onwarn({
|
||||
message,
|
||||
frame,
|
||||
loc: { line: line + 1, column },
|
||||
pos,
|
||||
filename,
|
||||
toString: () => `${message} (${line + 1}:${column})\n${frame}`
|
||||
});
|
||||
},
|
||||
|
||||
source,
|
||||
|
||||
namespace: null,
|
||||
defaultExport: null,
|
||||
properties: {},
|
||||
components: new Map(),
|
||||
methods: new Map(),
|
||||
helpers: new Map(),
|
||||
transitions: new Map()
|
||||
};
|
||||
|
||||
try {
|
||||
if ( name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test( name ) ) {
|
||||
const error = new Error( `options.name must be a valid identifier` );
|
||||
throw error;
|
||||
}
|
||||
|
||||
if ( name && !/^[A-Z]/.test( name ) ) {
|
||||
const message = `options.name should be capitalised`;
|
||||
onwarn({
|
||||
message,
|
||||
filename,
|
||||
toString: () => message
|
||||
});
|
||||
}
|
||||
|
||||
if ( parsed.js ) {
|
||||
validateJs( validator, parsed.js );
|
||||
}
|
||||
|
||||
if ( parsed.html ) {
|
||||
validateHtml( validator, parsed.html );
|
||||
}
|
||||
} catch ( err ) {
|
||||
if ( onerror ) {
|
||||
onerror( err );
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue