baby steps towards

pull/1367/head
Rich Harris 7 years ago
parent a7c1c380d4
commit d3afc4c0f3

@ -17,6 +17,7 @@ import clone from '../utils/clone';
import Stylesheet from '../css/Stylesheet'; import Stylesheet from '../css/Stylesheet';
import { test } from '../config'; import { test } from '../config';
import nodes from './nodes/index'; import nodes from './nodes/index';
import Fragment from './nodes/Fragment';
import { Node, GenerateOptions, ShorthandImport, Parsed, CompileOptions, CustomElementOptions } from '../interfaces'; import { Node, GenerateOptions, ShorthandImport, Parsed, CompileOptions, CustomElementOptions } from '../interfaces';
interface Computation { interface Computation {
@ -83,6 +84,7 @@ export default class Generator {
source: string; source: string;
name: string; name: string;
options: CompileOptions; options: CompileOptions;
fragment: Fragment;
customElement: CustomElementOptions; customElement: CustomElementOptions;
tag: string; tag: string;
@ -191,6 +193,7 @@ export default class Generator {
throw new Error(`No tag name specified`); // TODO better error throw new Error(`No tag name specified`); // TODO better error
} }
this.fragment = new Fragment(this, parsed.html);
this.walkTemplate(); this.walkTemplate();
if (!this.customElement) this.stylesheet.reify(); if (!this.customElement) this.stylesheet.reify();
} }
@ -711,7 +714,6 @@ export default class Generator {
expectedProperties, expectedProperties,
helpers helpers
} = this; } = this;
const { html } = this.parsed;
const contextualise = ( const contextualise = (
node: Node, contextDependencies: Map<string, string[]>, node: Node, contextDependencies: Map<string, string[]>,
@ -782,7 +784,7 @@ export default class Generator {
return parentIsHead(node.parent); return parentIsHead(node.parent);
} }
walk(html, { walk(this.fragment, {
enter(node: Node, parent: Node, key: string) { enter(node: Node, parent: Node, key: string) {
// TODO this is hacky as hell // TODO this is hacky as hell
if (key === 'parent') return this.skip(); if (key === 'parent') return this.skip();

@ -70,8 +70,8 @@ export default function dom(
namespace, namespace,
} = generator; } = generator;
parsed.html.build(); generator.fragment.build();
const { block } = parsed.html; const { block } = generator.fragment;
// prevent fragment being created twice (#1063) // prevent fragment being created twice (#1063)
if (options.customElement) block.builders.create.addLine(`this.c = @noop;`); if (options.customElement) block.builders.create.addLine(`this.c = @noop;`);

@ -12,34 +12,22 @@ export interface StyleProp {
value: Node[]; value: Node[];
} }
export default class Attribute { export default class Attribute extends Node {
type: 'Attribute'; type: 'Attribute';
start: number; start: number;
end: number; end: number;
generator: DomGenerator; compiler: DomGenerator;
parent: Element; parent: Element;
name: string; name: string;
value: true | Node[] value: true | Node[]
expression: Node; expression: Node;
constructor({ constructor(compiler, parent, info) {
generator, super(compiler, parent, info);
name,
value, this.name = info.name;
parent this.value = info.value;
}: {
generator: DomGenerator,
name: string,
value: Node[],
parent: Element
}) {
this.type = 'Attribute';
this.generator = generator;
this.parent = parent;
this.name = name;
this.value = value;
} }
render(block: Block) { render(block: Block) {

@ -17,6 +17,7 @@ import Transition from './Transition';
import Action from './Action'; import Action from './Action';
import Text from './Text'; import Text from './Text';
import * as namespaces from '../../utils/namespaces'; import * as namespaces from '../../utils/namespaces';
import mapChildren from './shared/mapChildren';
export default class Element extends Node { export default class Element extends Node {
type: 'Element'; type: 'Element';
@ -24,6 +25,29 @@ export default class Element extends Node {
attributes: (Attribute | Binding | EventHandler | Ref | Transition | Action)[]; // TODO split these up sooner attributes: (Attribute | Binding | EventHandler | Ref | Transition | Action)[]; // TODO split these up sooner
children: Node[]; children: Node[];
constructor(compiler, parent, info: any) {
super(compiler, parent, info);
this.name = info.name;
this.children = mapChildren(compiler, parent, info.children);
this.attributes = [];
// TODO bindings etc
info.attributes.forEach(node => {
switch (node.type) {
case 'Attribute':
case 'Spread':
this.attributes.push(new Attribute(compiler, this, node));
break;
default:
throw new Error(`Not implemented: ${node.type}`);
}
});
// TODO break out attributes and directives here
}
init( init(
block: Block, block: Block,
stripWhitespace: boolean, stripWhitespace: boolean,

@ -1,11 +1,18 @@
import Node from './shared/Node'; import Node from './shared/Node';
import { DomGenerator } from '../dom/index'; import { DomGenerator } from '../dom/index';
import Generator from '../Generator';
import mapChildren from './shared/mapChildren';
import Block from '../dom/Block'; import Block from '../dom/Block';
export default class Fragment extends Node { export default class Fragment extends Node {
block: Block; block: Block;
children: Node[]; children: Node[];
constructor(compiler: Generator, info: any) {
super(compiler, info);
this.children = mapChildren(compiler, this, info.children);
}
init() { init() {
this.block = new Block({ this.block = new Block({
generator: this.generator, generator: this.generator,

@ -6,7 +6,7 @@ export default class MustacheTag extends Tag {
init(block: Block) { init(block: Block) {
this.cannotUseInnerHTML(); this.cannotUseInnerHTML();
this.var = block.getUniqueName('text'); this.var = block.getUniqueName('text');
block.addDependencies(this.metadata.dependencies); block.addDependencies(this.expression.dependencies);
} }
build( build(

@ -0,0 +1,11 @@
import Generator from '../../Generator';
export default class Expression {
compiler: Generator;
info: any;
constructor(compiler, info) {
this.compiler = compiler;
this.info = info;
}
}

@ -1,28 +1,20 @@
import { DomGenerator } from '../../dom/index'; import { DomGenerator } from '../../dom/index';
import Generator from './../../Generator';
import Block from '../../dom/Block'; import Block from '../../dom/Block';
import { trimStart, trimEnd } from '../../../utils/trim'; import { trimStart, trimEnd } from '../../../utils/trim';
export default class Node { export default class Node {
type: string; compiler: Generator;
start: number;
end: number;
[key: string]: any;
metadata?: {
dependencies: string[];
snippet: string;
};
parent: Node; parent: Node;
prev?: Node; prev?: Node;
next?: Node; next?: Node;
generator: DomGenerator;
canUseInnerHTML: boolean; canUseInnerHTML: boolean;
var: string; var: string;
constructor(data: Record<string, any>) { constructor(compiler: Generator, parent, info: any) {
Object.assign(this, data); this.compiler = compiler;
this.parent = parent;
} }
cannotUseInnerHTML() { cannotUseInnerHTML() {

@ -1,7 +1,15 @@
import Node from './Node'; import Node from './Node';
import Expression from './Expression';
import Block from '../../dom/Block'; import Block from '../../dom/Block';
export default class Tag extends Node { export default class Tag extends Node {
expression: Expression;
constructor(compiler, parent, info) {
super(compiler, parent, info);
this.expression = new Expression(compiler, info.expression);
}
renameThisMethod( renameThisMethod(
block: Block, block: Block,
update: ((value: string) => string) update: ((value: string) => string)

@ -0,0 +1,27 @@
import Element from '../Element';
import Text from '../Text';
import MustacheTag from '../MustacheTag';
import Node from './Node';
function getConstructor(type): typeof Node {
switch (type) {
case 'Element': return Element;
case 'Text': return Text;
case 'MustacheTag': return MustacheTag;
default: throw new Error(`Not implemented: ${type}`);
}
}
export default function mapChildren(compiler, parent, children: any[]) {
let last = null;
return children.map(child => {
const constructor = getConstructor(child.type);
const node = new constructor(compiler, parent, child);
if (last) last.next = node;
node.prev = last;
last = node;
return node;
});
}

@ -1,4 +1,5 @@
export default { export default {
solo: true,
html: `<div style="color: red;">red</div>`, html: `<div style="color: red;">red</div>`,
test ( assert, component, target ) { test ( assert, component, target ) {

@ -6,7 +6,8 @@
"noEmitOnError": true, "noEmitOnError": true,
"allowJs": true, "allowJs": true,
"lib": ["es5", "es6", "dom"], "lib": ["es5", "es6", "dom"],
"importHelpers": true "importHelpers": true,
"moduleResolution": "node"
}, },
"include": [ "include": [
"src" "src"

Loading…
Cancel
Save