Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/css/Selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ export default class Selector {
while (i-- > 1) {
const selector = block.selectors[i];
if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
validator.error(`:global(...) must be the first element in a compound selector`, selector);
validator.error(selector, {
code: `css-invalid-global`,
message: `:global(...) must be the first element in a compound selector`
});
}
}
});
Expand All @@ -120,7 +123,10 @@ export default class Selector {

for (let i = start; i < end; i += 1) {
if (this.blocks[i].global) {
validator.error(`:global(...) can be at the start or end of a selector sequence, but not in the middle`, this.blocks[i].selectors[0]);
validator.error(this.blocks[i].selectors[0], {
code: `css-invalid-global`,
message: `:global(...) can be at the start or end of a selector sequence, but not in the middle`
});
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/css/Stylesheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ export default class Stylesheet {
const message = `Unused CSS selector`;

onwarn({
code: `css-unused-selector`,
message,
frame,
loc: { line: line + 1, column },
Expand Down
1 change: 1 addition & 0 deletions src/generators/wrapModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ function getGlobals(dependencies: Dependency[], options: CompileOptions) {
onerror(error);
} else {
const warning = {
code: `options-missing-globals`,
message: `No name was supplied for imported module '${d.source}'. Guessing '${d.name}', but you should use options.globals`,
};

Expand Down
1 change: 1 addition & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface Warning {
loc?: { line: number; column: number; pos?: number };
end?: { line: number; column: number; };
pos?: number;
code: string;
message: string;
filename?: string;
frame?: string;
Expand Down
40 changes: 32 additions & 8 deletions src/parse/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,19 @@ export class Parser {
const current = this.current();

const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
this.error(`${type} was left open`, current.start);
const slug = current.type === 'Element' ? 'element' : 'block';

this.error({
code: `unclosed-${slug}`,
message: `${type} was left open`
}, current.start);
}

if (state !== fragment) {
this.error('Unexpected end of input');
this.error({
code: `unexpected-eof`,
message: 'Unexpected end of input'
});
}

if (this.html.children.length) {
Expand All @@ -97,12 +105,16 @@ export class Parser {
}

acornError(err: any) {
this.error(err.message.replace(/ \(\d+:\d+\)$/, ''), err.pos);
this.error({
code: `parse-error`,
message: err.message.replace(/ \(\d+:\d+\)$/, '')
}, err.pos);
}

error(message: string, index = this.index) {
error({ code, message }: { code: string, message: string }, index = this.index) {
error(message, {
name: 'ParseError',
code,
source: this.template,
start: index,
filename: this.filename
Expand All @@ -116,7 +128,10 @@ export class Parser {
}

if (required) {
this.error(message || `Expected ${str}`);
this.error({
code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
message: message || `Expected ${str}`
});
}

return false;
Expand Down Expand Up @@ -164,15 +179,21 @@ export class Parser {
const identifier = this.template.slice(this.index, this.index = i);

if (reservedNames.has(identifier)) {
this.error(`'${identifier}' is a reserved word in JavaScript and cannot be used here`, start);
this.error({
code: `unexpected-reserved-word`,
message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`
}, start);
}

return identifier;
}

readUntil(pattern: RegExp) {
if (this.index >= this.template.length)
this.error('Unexpected end of input');
this.error({
code: `unexpected-eof`,
message: 'Unexpected end of input'
});

const start = this.index;
const match = pattern.exec(this.template.slice(start));
Expand All @@ -192,7 +213,10 @@ export class Parser {

requireWhitespace() {
if (!whitespace.test(this.template[this.index])) {
this.error(`Expected whitespace`);
this.error({
code: `missing-whitespace`,
message: `Expected whitespace`
});
}

this.allowWhitespace();
Expand Down
24 changes: 21 additions & 3 deletions src/parse/read/directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@ import { parseExpressionAt } from 'acorn';
import repeat from '../../utils/repeat';
import { Parser } from '../index';

const DIRECTIVES = {
const DIRECTIVES: Record<string, {
names: string[];
attribute: (
start: number,
end: number,
type: string,
name: string,
expression?: any,
directiveName?: string
) => { start: number, end: number, type: string, name: string, value?: any, expression?: any };
allowedExpressionTypes: string[];
error: string;
}> = {
Ref: {
names: ['ref'],
attribute(start, end, type, name) {
Expand Down Expand Up @@ -143,7 +155,10 @@ export function readDirective(
try {
expression = readExpression(parser, expressionStart, quoteMark);
if (directive.allowedExpressionTypes.indexOf(expression.type) === -1) {
parser.error(directive.error, expressionStart);
parser.error({
code: `invalid-directive-value`,
message: directive.error
}, expressionStart);
}
} catch (err) {
if (parser.template[expressionStart] === '{') {
Expand All @@ -155,7 +170,10 @@ export function readDirective(
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({
code: `invalid-directive-value`,
message
}, expressionStart);
}

throw err;
Expand Down
5 changes: 4 additions & 1 deletion src/parse/read/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ export default function readScript(parser: Parser, start: number, attributes: No
const scriptStart = parser.index;
const scriptEnd = parser.template.indexOf(scriptClosingTag, scriptStart);

if (scriptEnd === -1) parser.error(`<script> must have a closing tag`);
if (scriptEnd === -1) parser.error({
code: `unclosed-script`,
message: `<script> must have a closing tag`
});

const source =
repeat(' ', scriptStart) + parser.template.slice(scriptStart, scriptEnd);
Expand Down
5 changes: 4 additions & 1 deletion src/parse/read/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ export default function readStyle(parser: Parser, start: number, attributes: Nod
});
} catch (err) {
if (err.name === 'CssSyntaxError') {
parser.error(err.message, err.offset);
parser.error({
code: `css-syntax-error`,
message: err.message
}, err.offset);
} else {
throw err;
}
Expand Down
56 changes: 42 additions & 14 deletions src/parse/state/mustache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ export default function mustache(parser: Parser) {
} else if (block.type === 'AwaitBlock') {
expected = 'await';
} else {
parser.error(`Unexpected block closing tag`);
parser.error({
code: `unexpected-block-close`,
message: `Unexpected block closing tag`
});
}

parser.eat(expected, true);
Expand Down Expand Up @@ -86,9 +89,10 @@ export default function mustache(parser: Parser) {
} else if (parser.eat(parser.v2 ? ':elseif' : 'elseif')) {
const block = parser.current();
if (block.type !== 'IfBlock')
parser.error(
'Cannot have an {{elseif ...}} block outside an {{#if ...}} block'
);
parser.error({
code: `invalid-elseif-placement`,
message: 'Cannot have an {{elseif ...}} block outside an {{#if ...}} block'
});

parser.requireWhitespace();

Expand Down Expand Up @@ -117,9 +121,10 @@ export default function mustache(parser: Parser) {
} else if (parser.eat(parser.v2 ? ':else' : 'else')) {
const block = parser.current();
if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
parser.error(
'Cannot have an {{else}} block outside an {{#if ...}} or {{#each ...}} block'
);
parser.error({
code: `invalid-else-placement`,
message: 'Cannot have an {{else}} block outside an {{#if ...}} or {{#each ...}} block'
});
}

parser.allowWhitespace();
Expand Down Expand Up @@ -191,7 +196,10 @@ export default function mustache(parser: Parser) {
} else if (parser.eat('await')) {
type = 'AwaitBlock';
} else {
parser.error(`Expected if, each or await`);
parser.error({
code: `expected-block-type`,
message: `Expected if, each or await`
});
}

parser.requireWhitespace();
Expand Down Expand Up @@ -249,28 +257,42 @@ export default function mustache(parser: Parser) {
parser.allowWhitespace();

const destructuredContext = parser.readIdentifier();
if (!destructuredContext) parser.error(`Expected name`);
if (!destructuredContext) parser.error({
code: `expected-name`,
message: `Expected name`
});

block.destructuredContexts.push(destructuredContext);
parser.allowWhitespace();
} while (parser.eat(','));

if (!block.destructuredContexts.length) parser.error(`Expected name`);
if (!block.destructuredContexts.length) parser.error({
code: `expected-name`,
message: `Expected name`
});

block.context = block.destructuredContexts.join('_');

parser.allowWhitespace();
parser.eat(']', true);
} else {
block.context = parser.readIdentifier();
if (!block.context) parser.error(`Expected name`);
if (!block.context) parser.error({
code: `expected-name`,
message: `Expected name`
});
}

parser.allowWhitespace();

if (parser.eat(',')) {
parser.allowWhitespace();
block.index = parser.readIdentifier();
if (!block.index) parser.error(`Expected name`);
if (!block.index) parser.error({
code: `expected-name`,
message: `Expected name`
});

parser.allowWhitespace();
}

Expand All @@ -287,7 +309,10 @@ export default function mustache(parser: Parser) {
expression.property.computed ||
expression.property.type !== 'Identifier'
) {
parser.error('invalid key', expression.start);
parser.error({
code: `invalid-key`,
message: 'invalid key'
}, expression.start);
}

block.key = expression.property.name;
Expand All @@ -296,7 +321,10 @@ export default function mustache(parser: Parser) {
parser.allowWhitespace();
} else if (parser.eat('@')) {
block.key = parser.readIdentifier();
if (!block.key) parser.error(`Expected name`);
if (!block.key) parser.error({
code: `expected-name`,
message: `Expected name`
});
parser.allowWhitespace();
}
}
Expand Down
Loading