start work on <slot>

pull/787/head
Rich Harris 7 years ago
parent c7dda9ff79
commit d734a6b823

@ -1,7 +1,7 @@
import attributeLookup from './lookup'; import attributeLookup from './lookup';
import deindent from '../../../../utils/deindent'; import deindent from '../../../../utils/deindent';
import { stringify } from '../../../../utils/stringify'; import { stringify } from '../../../../utils/stringify';
import getStaticAttributeValue from './getStaticAttributeValue'; import getStaticAttributeValue from '../shared/getStaticAttributeValue';
import { DomGenerator } from '../../index'; import { DomGenerator } from '../../index';
import Block from '../../Block'; import Block from '../../Block';
import { Node } from '../../../../interfaces'; import { Node } from '../../../../interfaces';

@ -1,6 +1,6 @@
import deindent from '../../../../utils/deindent'; import deindent from '../../../../utils/deindent';
import flattenReference from '../../../../utils/flattenReference'; import flattenReference from '../../../../utils/flattenReference';
import getStaticAttributeValue from './getStaticAttributeValue'; import getStaticAttributeValue from '../shared/getStaticAttributeValue';
import { DomGenerator } from '../../index'; import { DomGenerator } from '../../index';
import Block from '../../Block'; import Block from '../../Block';
import { Node } from '../../../../interfaces'; import { Node } from '../../../../interfaces';

@ -1,5 +1,6 @@
import deindent from '../../../../utils/deindent'; import deindent from '../../../../utils/deindent';
import visit from '../../visit'; import visit from '../../visit';
import visitSlot from '../Slot';
import visitComponent from '../Component'; import visitComponent from '../Component';
import visitWindow from './meta/Window'; import visitWindow from './meta/Window';
import visitAttribute from './Attribute'; import visitAttribute from './Attribute';

@ -0,0 +1,35 @@
import { DomGenerator } from '../index';
import Block from '../Block';
import getStaticAttributeValue from './shared/getStaticAttributeValue';
import { Node } from '../../../interfaces';
import { State } from '../interfaces';
export default function visitSlot(
generator: DomGenerator,
block: Block,
state: State,
node: Node
) {
const slotName = getStaticAttributeValue(node, 'name');
const name = block.getUniqueName(`slot_${slotName || 'default'}`);
const parentNode = state.parentNode || '#target';
block.addVariable(name);
block.addElement(
name,
`@createElement('slot')`,
`@claimElement(${state.parentNodes}, 'slot', {${slotName ? ` name: '${slotName}' ` : ''}})`,
parentNode
);
// block.builders.mount.addLine(
// `if ( #component._yield ) #component._yield.mount( ${parentNode}, null );`
// );
// block.builders.unmount.addLine(
// `if ( #component._yield ) #component._yield.unmount();`
// );
}

@ -1,5 +1,5 @@
import { parseExpressionAt } from 'acorn'; import { parseExpressionAt } from 'acorn';
import spaces from '../../utils/spaces'; import repeat from '../../utils/repeat';
import { Parser } from '../index'; import { Parser } from '../index';
function readExpression(parser: Parser, start: number, quoteMark: string|null) { function readExpression(parser: Parser, start: number, quoteMark: string|null) {
@ -31,7 +31,7 @@ function readExpression(parser: Parser, start: number, quoteMark: string|null) {
} }
} }
const expression = parseExpressionAt(spaces(start) + str, start); const expression = parseExpressionAt(repeat(' ', start) + str, start);
parser.index = expression.end; parser.index = expression.end;
parser.allowWhitespace(); parser.allowWhitespace();
@ -101,7 +101,7 @@ export function readBindingDirective(
b = parser.index; b = parser.index;
} }
const source = spaces(a) + parser.template.slice(a, b); const source = repeat(' ', a) + parser.template.slice(a, b);
value = parseExpressionAt(source, a); value = parseExpressionAt(source, a);
if (value.type !== 'Identifier' && value.type !== 'MemberExpression') { if (value.type !== 'Identifier' && value.type !== 'MemberExpression') {

@ -1,5 +1,5 @@
import { parse } from 'acorn'; import { parse } from 'acorn';
import spaces from '../../utils/spaces'; import repeat from '../../utils/repeat';
import { Parser } from '../index'; import { Parser } from '../index';
import { Node } from '../../interfaces'; import { Node } from '../../interfaces';
@ -12,7 +12,7 @@ export default function readScript(parser: Parser, start: number, attributes: No
if (scriptEnd === -1) parser.error(`<script> must have a closing tag`); if (scriptEnd === -1) parser.error(`<script> must have a closing tag`);
const source = const source =
spaces(scriptStart) + parser.template.slice(scriptStart, scriptEnd); repeat(' ', scriptStart) + parser.template.slice(scriptStart, scriptEnd);
parser.index = scriptEnd + scriptClosingTag.length; parser.index = scriptEnd + scriptClosingTag.length;
let ast; let ast;

@ -1,3 +1,5 @@
import repeat from './repeat';
enum ChunkType { enum ChunkType {
Line, Line,
Block Block
@ -8,6 +10,8 @@ export default class CodeBuilder {
first: ChunkType; first: ChunkType;
last: ChunkType; last: ChunkType;
lastCondition: string; lastCondition: string;
conditionStack: string[];
indent: string;
constructor(str = '') { constructor(str = '') {
this.result = str; this.result = str;
@ -19,19 +23,21 @@ export default class CodeBuilder {
this.last = initial; this.last = initial;
this.lastCondition = null; this.lastCondition = null;
this.conditionStack = [];
this.indent = '';
} }
addConditional(condition: string, body: string) { addConditional(condition: string, body: string) {
body = body.replace(/^/gm, '\t'); body = body.replace(/^/gm, `${this.indent}\t`);
if (condition === this.lastCondition) { if (condition === this.lastCondition) {
this.result += `\n${body}`; this.result += `\n${body}`;
} else { } else {
if (this.lastCondition) { if (this.lastCondition) {
this.result += `\n}`; this.result += `\n${this.indent}}`;
} }
this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}if ( ${condition} ) {\n${body}`; this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}${this.indent}if ( ${condition} ) {\n${body}`;
this.lastCondition = condition; this.lastCondition = condition;
} }
@ -40,14 +46,14 @@ export default class CodeBuilder {
addLine(line: string) { addLine(line: string) {
if (this.lastCondition) { if (this.lastCondition) {
this.result += `\n}`; this.result += `\n${this.indent}}`;
this.lastCondition = null; this.lastCondition = null;
} }
if (this.last === ChunkType.Block) { if (this.last === ChunkType.Block) {
this.result += `\n\n${line}`; this.result += `\n\n${this.indent}${line}`;
} else if (this.last === ChunkType.Line) { } else if (this.last === ChunkType.Line) {
this.result += `\n${line}`; this.result += `\n${this.indent}${line}`;
} else { } else {
this.result += line; this.result += line;
} }
@ -58,9 +64,9 @@ export default class CodeBuilder {
addLineAtStart(line: string) { addLineAtStart(line: string) {
if (this.first === ChunkType.Block) { if (this.first === ChunkType.Block) {
this.result = `${line}\n\n${this.result}`; this.result = `${line}\n\n${this.indent}${this.result}`;
} else if (this.first === ChunkType.Line) { } else if (this.first === ChunkType.Line) {
this.result = `${line}\n${this.result}`; this.result = `${line}\n${this.indent}${this.result}`;
} else { } else {
this.result += line; this.result += line;
} }
@ -70,13 +76,15 @@ export default class CodeBuilder {
} }
addBlock(block: string) { addBlock(block: string) {
if (this.indent) block = block.replace(/^/gm, `${this.indent}`);
if (this.lastCondition) { if (this.lastCondition) {
this.result += `\n}`; this.result += `\n${this.indent}}`;
this.lastCondition = null; this.lastCondition = null;
} }
if (this.result) { if (this.result) {
this.result += `\n\n${block}`; this.result += `\n\n${this.indent}${block}`;
} else { } else {
this.result += block; this.result += block;
} }
@ -87,7 +95,7 @@ export default class CodeBuilder {
addBlockAtStart(block: string) { addBlockAtStart(block: string) {
if (this.result) { if (this.result) {
this.result = `${block}\n\n${this.result}`; this.result = `${block}\n\n${this.indent}${this.result}`;
} else { } else {
this.result += block; this.result += block;
} }
@ -100,6 +108,16 @@ export default class CodeBuilder {
return this.result === ''; return this.result === '';
} }
pushCondition(condition: string) {
this.conditionStack.push(condition);
this.indent = repeat('\t', this.conditionStack.length);
}
popCondition() {
this.conditionStack.pop();
this.indent = repeat('\t', this.conditionStack.length);
}
toString() { toString() {
return this.result.trim() + (this.lastCondition ? `\n}` : ``); return this.result.trim() + (this.lastCondition ? `\n}` : ``);
} }

@ -1,4 +1,4 @@
import spaces from './spaces'; import repeat from './repeat';
function tabsToSpaces(str: string) { function tabsToSpaces(str: string) {
return str.replace(/^\t+/, match => match.split('\t').join(' ')); return str.replace(/^\t+/, match => match.split('\t').join(' '));
@ -26,7 +26,7 @@ export default function getCodeFrame(
if (isErrorLine) { if (isErrorLine) {
const indicator = const indicator =
spaces(digits + 2 + tabsToSpaces(str.slice(0, column)).length) + '^'; repeat(' ', digits + 2 + tabsToSpaces(str.slice(0, column)).length) + '^';
return `${lineNum}: ${tabsToSpaces(str)}\n${indicator}`; return `${lineNum}: ${tabsToSpaces(str)}\n${indicator}`;
} }

@ -0,0 +1,5 @@
export default function repeat(str: string, i: number) {
let result = '';
while (i--) result += str;
return result;
}

@ -1,5 +0,0 @@
export default function spaces(i: number) {
let result = '';
while (i--) result += ' ';
return result;
}

@ -0,0 +1,4 @@
export default {
solo: true,
html: '<p><slot>Hello</slot></p>'
};

@ -0,0 +1,13 @@
<Nested>
hello
</Nested>
<script>
import Nested from './Nested.html';
export default {
components: {
Nested
}
};
</script>
Loading…
Cancel
Save