Skip to content

Commit

Permalink
Merge pull request #1330 from sveltejs/gh-1318
Browse files Browse the repository at this point in the history
implement syntax changes
  • Loading branch information
Rich-Harris authored Apr 14, 2018
2 parents eed32f7 + 2b3fe0e commit 813e077
Show file tree
Hide file tree
Showing 271 changed files with 14,612 additions and 208 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ coverage.lcov
test/sourcemaps/samples/*/output.js
test/sourcemaps/samples/*/output.js.map
_actual.*
_actual-v2.*
_actual-bundle.*
src/generators/dom/shared.ts
package-lock.json
Expand Down
4 changes: 2 additions & 2 deletions src/generators/Generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@ export default class Generator {

node.generator = generator;

if (node.type === 'Element' && (node.name === ':Component' || node.name === ':Self' || generator.components.has(node.name))) {
if (node.type === 'Element' && (node.name === ':Component' || node.name === ':Self' || node.name === 'svelte:component' || node.name === 'svelte:self' || generator.components.has(node.name))) {
node.type = 'Component';
Object.setPrototypeOf(node, nodes.Component.prototype);
} else if (node.type === 'Element' && node.name === 'title' && parentIsHead(parent)) { // TODO do this in parse?
Expand Down Expand Up @@ -875,7 +875,7 @@ export default class Generator {
this.skip();
}

if (node.type === 'Component' && node.name === ':Component') {
if (node.type === 'Component' && (node.name === ':Component' || node.name === 'svelte:component')) {
node.metadata = contextualise(node.expression, contextDependencies, indexes, false);
}

Expand Down
8 changes: 4 additions & 4 deletions src/generators/nodes/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ export default class Component extends Node {

this.var = block.getUniqueName(
(
this.name === ':Self' ? this.generator.name :
this.name === ':Component' ? 'switch_instance' :
(this.name === ':Self' || this.name === 'svelte:self') ? this.generator.name :
(this.name === ':Component' || this.name === 'svelte:component') ? 'switch_instance' :
this.name
).toLowerCase()
);
Expand Down Expand Up @@ -292,7 +292,7 @@ export default class Component extends Node {
`;
}

if (this.name === ':Component') {
if (this.name === ':Component' || this.name === 'svelte:component') {
const switch_value = block.getUniqueName('switch_value');
const switch_props = block.getUniqueName('switch_props');

Expand Down Expand Up @@ -386,7 +386,7 @@ export default class Component extends Node {

block.builders.destroy.addLine(`if (${name}) ${name}.destroy(false);`);
} else {
const expression = this.name === ':Self'
const expression = (this.name === ':Self' || this.name === 'svelte:self')
? generator.name
: `%components-${this.name}`;

Expand Down
2 changes: 1 addition & 1 deletion src/generators/nodes/EachBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export default class EachBlock extends Node {

// hack the sourcemap, so that if data is missing the bug
// is easy to find
let c = this.start + 3;
let c = this.start + 2;
while (generator.source[c] !== 'e') c += 1;
generator.code.overwrite(c, c + 4, 'length');
const length = `[✂${c}-${c+4}✂]`;
Expand Down
4 changes: 2 additions & 2 deletions src/generators/server-side-rendering/visitors/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ export default function visitComponent(
.concat(bindingProps)
.join(', ')} }`;

const isDynamicComponent = node.name === ':Component';
const isDynamicComponent = node.name === ':Component' || node.name === 'svelte:component';
if (isDynamicComponent) block.contextualise(node.expression);

const expression = (
node.name === ':Self' ? generator.name :
(node.name === ':Self' || node.name === 'svelte:self') ? generator.name :
isDynamicComponent ? `((${node.metadata.snippet}) || __missingComponent)` :
`%components-${node.name}`
);
Expand Down
2 changes: 2 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ export interface CompileOptions {

onerror?: (error: Error) => void;
onwarn?: (warning: Warning) => void;

parser?: 'v2';
}

export interface GenerateOptions {
Expand Down
4 changes: 4 additions & 0 deletions src/parse/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import error from '../utils/error';
interface ParserOptions {
filename?: string;
bind?: boolean;
parser?: 'v2';
}

type ParserState = (parser: Parser) => (ParserState | void);

export class Parser {
readonly v2: boolean;
readonly template: string;
readonly filename?: string;

Expand All @@ -32,6 +34,8 @@ export class Parser {
allowBindings: boolean;

constructor(template: string, options: ParserOptions) {
this.v2 = options.parser === 'v2';

if (typeof template !== 'string') {
throw new TypeError('Template must be a string');
}
Expand Down
29 changes: 17 additions & 12 deletions src/parse/read/directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,20 +140,25 @@ export function readDirective(

const expressionStart = parser.index;

if (parser.eat('{{')) {
let message = 'directive values should not be wrapped';
const expressionEnd = parser.template.indexOf('}}', expressionStart);
if (expressionEnd !== -1) {
const value = parser.template.slice(parser.index, expressionEnd);
message += ` — use '${value}', not '{{${value}}}'`;
try {
expression = readExpression(parser, expressionStart, quoteMark);
if (directive.allowedExpressionTypes.indexOf(expression.type) === -1) {
parser.error(directive.error, expressionStart);
}
} catch (err) {
if (parser.template[expressionStart] === '{') {
// assume the mistake was wrapping the directive arguments.
// this could yield false positives! but hopefully not too many
let message = 'directive values should not be wrapped';
const expressionEnd = parser.template.indexOf((parser.v2 ? '}' : '}}'), expressionStart);
if (expressionEnd !== -1) {
const value = parser.template.slice(expressionStart + (parser.v2 ? 1 : 2), expressionEnd);
message += ` — use '${value}', not '${parser.v2 ? `{${value}}` : `{{${value}}}`}'`;
}
parser.error(message, expressionStart);
}

parser.error(message, expressionStart);
}

expression = readExpression(parser, expressionStart, quoteMark);
if (directive.allowedExpressionTypes.indexOf(expression.type) === -1) {
parser.error(directive.error, expressionStart);
throw err;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/parse/read/expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const literals = new Map([['true', true], ['false', false], ['null', null]]);
export default function readExpression(parser: Parser) {
const start = parser.index;

const name = parser.readUntil(/\s*}}/);
const name = parser.readUntil(parser.v2 ? /\s*}/ : /\s*}}/);
if (name && /^[a-z]+$/.test(name)) {
const end = start + name.length;

Expand Down
2 changes: 1 addition & 1 deletion src/parse/state/fragment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default function fragment(parser: Parser) {
return tag;
}

if (parser.match('{{')) {
if (parser.match(parser.v2 ? '{' : '{{')) {
return mustache;
}

Expand Down
86 changes: 62 additions & 24 deletions src/parse/state/mustache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function trimWhitespace(block: Node, trimBefore: boolean, trimAfter: boolean) {

export default function mustache(parser: Parser) {
const start = parser.index;
parser.index += 2;
parser.index += parser.v2 ? 1 : 2;

parser.allowWhitespace();

Expand Down Expand Up @@ -61,7 +61,7 @@ export default function mustache(parser: Parser) {

parser.eat(expected, true);
parser.allowWhitespace();
parser.eat('}}', true);
parser.eat(parser.v2 ? '}' : '}}', true);

while (block.elseif) {
block.end = parser.index;
Expand All @@ -83,7 +83,7 @@ export default function mustache(parser: Parser) {

block.end = parser.index;
parser.stack.pop();
} else if (parser.eat('elseif')) {
} else if (parser.eat(parser.v2 ? ':elseif' : 'elseif')) {
const block = parser.current();
if (block.type !== 'IfBlock')
parser.error(
Expand All @@ -95,7 +95,7 @@ export default function mustache(parser: Parser) {
const expression = readExpression(parser);

parser.allowWhitespace();
parser.eat('}}', true);
parser.eat(parser.v2 ? '}' : '}}', true);

block.else = {
start: parser.index,
Expand All @@ -114,7 +114,7 @@ export default function mustache(parser: Parser) {
};

parser.stack.push(block.else.children[0]);
} else if (parser.eat('else')) {
} else if (parser.eat(parser.v2 ? ':else' : 'else')) {
const block = parser.current();
if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
parser.error(
Expand All @@ -123,7 +123,7 @@ export default function mustache(parser: Parser) {
}

parser.allowWhitespace();
parser.eat('}}', true);
parser.eat(parser.v2 ? '}' : '}}', true);

block.else = {
start: parser.index,
Expand All @@ -133,7 +133,7 @@ export default function mustache(parser: Parser) {
};

parser.stack.push(block.else);
} else if (parser.eat('then')) {
} else if (parser.eat(parser.v2 ? ':then' : 'then')) {
// TODO DRY out this and the next section
const pendingBlock = parser.current();
if (pendingBlock.type === 'PendingBlock') {
Expand All @@ -145,7 +145,7 @@ export default function mustache(parser: Parser) {
awaitBlock.value = parser.readIdentifier();

parser.allowWhitespace();
parser.eat('}}', true);
parser.eat(parser.v2 ? '}' : '}}', true);

const thenBlock: Node = {
start,
Expand All @@ -157,7 +157,7 @@ export default function mustache(parser: Parser) {
awaitBlock.then = thenBlock;
parser.stack.push(thenBlock);
}
} else if (parser.eat('catch')) {
} else if (parser.eat(parser.v2 ? ':catch' : 'catch')) {
const thenBlock = parser.current();
if (thenBlock.type === 'ThenBlock') {
thenBlock.end = start;
Expand All @@ -168,7 +168,7 @@ export default function mustache(parser: Parser) {
awaitBlock.error = parser.readIdentifier();

parser.allowWhitespace();
parser.eat('}}', true);
parser.eat(parser.v2 ? '}' : '}}', true);

const catchBlock: Node = {
start,
Expand Down Expand Up @@ -274,7 +274,27 @@ export default function mustache(parser: Parser) {
parser.allowWhitespace();
}

if (parser.eat('@')) {
if (parser.eat('(')) {
parser.allowWhitespace();

const expression = readExpression(parser);

// TODO eventually, we should accept any expression, and turn
// it into a function. For now, assume that every expression
// follows the `foo.id` pattern, and equates to `@id`
if (
expression.type !== 'MemberExpression' ||
expression.property.computed ||
expression.property.type !== 'Identifier'
) {
parser.error('invalid key', expression.start);
}

block.key = expression.property.name;
parser.allowWhitespace();
parser.eat(')', true);
parser.allowWhitespace();
} else if (parser.eat('@')) {
block.key = parser.readIdentifier();
if (!block.key) parser.error(`Expected name`);
parser.allowWhitespace();
Expand All @@ -288,7 +308,7 @@ export default function mustache(parser: Parser) {
parser.allowWhitespace();
}

parser.eat('}}', true);
parser.eat(parser.v2 ? '}' : '}}', true);

parser.current().children.push(block);
parser.stack.push(block);
Expand All @@ -302,22 +322,40 @@ export default function mustache(parser: Parser) {
// {{yield}}
// TODO deprecate
parser.allowWhitespace();
parser.eat('}}', true);

parser.current().children.push({
start,
end: parser.index,
type: 'Element',
name: 'slot',
attributes: [],
children: []
});
} else if (parser.eat('{')) {
if (parser.v2) {
const expressionEnd = parser.index;

parser.eat('}', true);
parser.current().children.push({
start,
end: parser.index,
type: 'MustacheTag',
expression: {
start: expressionEnd - 5,
end: expressionEnd,
type: 'Identifier',
name: 'yield'
}
});
} else {
parser.eat('}}', true);

parser.current().children.push({
start,
end: parser.index,
type: 'Element',
name: 'slot',
attributes: [],
children: []
});
}
} else if (parser.eat(parser.v2 ? '@html' : '{')) {
// {{{raw}}} mustache
const expression = readExpression(parser);

parser.allowWhitespace();
parser.eat('}}}', true);
parser.eat(parser.v2 ? '}' : '}}}', true);

parser.current().children.push({
start,
Expand All @@ -329,7 +367,7 @@ export default function mustache(parser: Parser) {
const expression = readExpression(parser);

parser.allowWhitespace();
parser.eat('}}', true);
parser.eat(parser.v2 ? '}' : '}}', true);

parser.current().children.push({
start,
Expand Down
Loading

0 comments on commit 813e077

Please sign in to comment.