baby steps towards #1316

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

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

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

@ -17,6 +17,7 @@ import Transition from './Transition';
import Action from './Action';
import Text from './Text';
import * as namespaces from '../../utils/namespaces';
import mapChildren from './shared/mapChildren';
export default class Element extends Node {
type: 'Element';
@ -24,6 +25,29 @@ export default class Element extends Node {
attributes: (Attribute | Binding | EventHandler | Ref | Transition | Action)[]; // TODO split these up sooner
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(
block: Block,
stripWhitespace: boolean,

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

@ -6,7 +6,7 @@ export default class MustacheTag extends Tag {
init(block: Block) {
this.cannotUseInnerHTML();
this.var = block.getUniqueName('text');
block.addDependencies(this.metadata.dependencies);
block.addDependencies(this.expression.dependencies);
}
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 Generator from './../../Generator';
import Block from '../../dom/Block';
import { trimStart, trimEnd } from '../../../utils/trim';
export default class Node {
type: string;
start: number;
end: number;
[key: string]: any;
metadata?: {
dependencies: string[];
snippet: string;
};
compiler: Generator;
parent: Node;
prev?: Node;
next?: Node;
generator: DomGenerator;
canUseInnerHTML: boolean;
var: string;
constructor(data: Record<string, any>) {
Object.assign(this, data);
constructor(compiler: Generator, parent, info: any) {
this.compiler = compiler;
this.parent = parent;
}
cannotUseInnerHTML() {

@ -1,7 +1,15 @@
import Node from './Node';
import Expression from './Expression';
import Block from '../../dom/Block';
export default class Tag extends Node {
expression: Expression;
constructor(compiler, parent, info) {
super(compiler, parent, info);
this.expression = new Expression(compiler, info.expression);
}
renameThisMethod(
block: Block,
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 {
solo: true,
html: `<div style="color: red;">red</div>`,
test ( assert, component, target ) {

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

Loading…
Cancel
Save