Skip to content

Commit

Permalink
baby steps towards #1316
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Apr 22, 2018
1 parent a7c1c38 commit d3afc4c
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 38 deletions.
6 changes: 4 additions & 2 deletions src/generators/Generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -83,6 +84,7 @@ export default class Generator {
source: string;
name: string;
options: CompileOptions;
fragment: Fragment;

customElement: CustomElementOptions;
tag: string;
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -711,7 +714,6 @@ export default class Generator {
expectedProperties,
helpers
} = this;
const { html } = this.parsed;

const contextualise = (
node: Node, contextDependencies: Map<string, string[]>,
Expand Down Expand Up @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions src/generators/dom/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;`);
Expand Down
26 changes: 7 additions & 19 deletions src/generators/nodes/Attribute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
24 changes: 24 additions & 0 deletions src/generators/nodes/Element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,37 @@ 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';
name: string;
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,
Expand Down
7 changes: 7 additions & 0 deletions src/generators/nodes/Fragment.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/generators/nodes/MustacheTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
11 changes: 11 additions & 0 deletions src/generators/nodes/shared/Expression.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
18 changes: 5 additions & 13 deletions src/generators/nodes/shared/Node.ts
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down
8 changes: 8 additions & 0 deletions src/generators/nodes/shared/Tag.ts
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
27 changes: 27 additions & 0 deletions src/generators/nodes/shared/mapChildren.ts
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions test/runtime/samples/attribute-dynamic/_config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default {
solo: true,
html: `<div style="color: red;">red</div>`,

test ( assert, component, target ) {
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"noEmitOnError": true,
"allowJs": true,
"lib": ["es5", "es6", "dom"],
"importHelpers": true
"importHelpers": true,
"moduleResolution": "node"
},
"include": [
"src"
Expand Down

0 comments on commit d3afc4c

Please sign in to comment.