diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 9001d09f68..dfd794f3a3 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -36,6 +36,7 @@ import { DecodedSourceMap, RawSourceMap } from '@ampproject/remapping/dist/types import { clone } from '../utils/clone'; import compiler_warnings from './compiler_warnings'; import compiler_errors from './compiler_errors'; +import { extract_svelte_ignore_from_comments } from './utils/extract_svelte_ignore'; interface ComponentOptions { namespace?: string; @@ -476,6 +477,14 @@ export default class Component { } extract_exports(node) { + const ignores = extract_svelte_ignore_from_comments(node); + if (ignores.length) this.push_ignores(ignores); + const result = this._extract_exports(node); + if (ignores.length) this.pop_ignores(); + return result; + } + + private _extract_exports(node) { if (node.type === 'ExportDefaultDeclaration') { this.error(node, compiler_errors.default_export); } @@ -1169,6 +1178,9 @@ export default class Component { }> = []; this.ast.instance.content.body.forEach(node => { + const ignores = extract_svelte_ignore_from_comments(node); + if (ignores.length) this.push_ignores(ignores); + if (node.type === 'LabeledStatement' && node.label.name === '$') { this.reactive_declaration_nodes.add(node); @@ -1246,6 +1258,8 @@ export default class Component { declaration }); } + + if (ignores.length) this.pop_ignores(); }); const lookup = new Map(); diff --git a/src/compiler/compile/css/Stylesheet.ts b/src/compiler/compile/css/Stylesheet.ts index 76ffe94397..6dd7d17f5f 100644 --- a/src/compiler/compile/css/Stylesheet.ts +++ b/src/compiler/compile/css/Stylesheet.ts @@ -7,6 +7,7 @@ import Component from '../Component'; import { CssNode } from './interfaces'; import hash from '../utils/hash'; import compiler_warnings from '../compiler_warnings'; +import { extract_svelte_ignore } from '../utils/extract_svelte_ignore'; function remove_css_prefix(name: string): string { return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, ''); @@ -447,10 +448,37 @@ export default class Stylesheet { } warn_on_unused_selectors(component: Component) { + const ignores = this.get_ignores(); + if (ignores.length) component.push_ignores(ignores); + this.children.forEach(child => { child.warn_on_unused_selector((selector: Selector) => { component.warn(selector.node, compiler_warnings.css_unused_selector(this.source.slice(selector.node.start, selector.node.end))); }); }); + + if (ignores.length) component.pop_ignores(); + } + + private get_ignores(): string[] { + const previous_node_idx = !this.ast.css ? -1 : this.ast.html.children.findIndex(child => child.end === this.ast.css.start); + if (previous_node_idx === -1) { + return []; + } + + for (let i = previous_node_idx; i >= 0; i--) { + const node = this.ast.html.children[i]; + if (node.type !== 'Comment' && node.type !== 'Text') { + return []; + } + if (node.type === 'Comment') { + const ignores = extract_svelte_ignore(node.data || ''); + if (ignores.length) { + return ignores; + } + } + } + + return []; } } diff --git a/src/compiler/compile/nodes/Comment.ts b/src/compiler/compile/nodes/Comment.ts index 4e871d17f4..c3eb8cd615 100644 --- a/src/compiler/compile/nodes/Comment.ts +++ b/src/compiler/compile/nodes/Comment.ts @@ -1,10 +1,9 @@ import { TemplateNode } from '../../interfaces'; import Component from '../Component'; +import { extract_svelte_ignore } from '../utils/extract_svelte_ignore'; import Node from './shared/Node'; import TemplateScope from './shared/TemplateScope'; -const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m; - export default class Comment extends Node { type: 'Comment'; data: string; @@ -13,8 +12,6 @@ export default class Comment extends Node { constructor(component: Component, parent: Node, scope: TemplateScope, info: TemplateNode) { super(component, parent, scope, info); this.data = info.data; - - const match = pattern.exec(this.data); - this.ignores = match ? match[1].split(/[^\S]/).map(x => x.trim()).filter(Boolean) : []; + this.ignores = extract_svelte_ignore(this.data) } } diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index fc9c5b87dd..23effa1d5f 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -10,6 +10,7 @@ import { ClassDeclaration, FunctionExpression, Node, Statement, ObjectExpression import { apply_preprocessor_sourcemap } from '../../utils/mapped_code'; import { RawSourceMap, DecodedSourceMap } from '@ampproject/remapping/dist/types/types'; import { Node as PeriscopicNode } from 'periscopic'; +import { flatten } from '../utils/flatten'; export default function dom( component: Component, @@ -551,18 +552,5 @@ export default function dom( body.push(declaration); } - return { js: flatten(body, []), css }; -} - -function flatten(nodes: any[], target: any[]) { - for (let i = 0; i < nodes.length; i += 1) { - const node = nodes[i]; - if (Array.isArray(node)) { - flatten(node, target); - } else { - target.push(node); - } - } - - return target; + return { js: flatten(body), css }; } diff --git a/src/compiler/compile/utils/extract_svelte_ignore.ts b/src/compiler/compile/utils/extract_svelte_ignore.ts new file mode 100644 index 0000000000..c00f0f91f4 --- /dev/null +++ b/src/compiler/compile/utils/extract_svelte_ignore.ts @@ -0,0 +1,12 @@ +import { flatten } from "./flatten"; + +const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m; + +export function extract_svelte_ignore(text: string): string[] { + const match = pattern.exec(text); + return match ? match[1].split(/[^\S]/).map(x => x.trim()).filter(Boolean) : []; +} + +export function extract_svelte_ignore_from_comments }>(node: Node): string[] { + return flatten((node.leadingComments || []).map(comment => extract_svelte_ignore(comment.value))); +} diff --git a/src/compiler/compile/utils/flatten.ts b/src/compiler/compile/utils/flatten.ts new file mode 100644 index 0000000000..53557a2eee --- /dev/null +++ b/src/compiler/compile/utils/flatten.ts @@ -0,0 +1,14 @@ +export function flatten(nodes: T[][], target?: T[]): T[]; +export function flatten(nodes: T[], target?: T[]): T[]; +export function flatten(nodes: any[], target: any[] = []): any[] { + for (let i = 0; i < nodes.length; i += 1) { + const node = nodes[i]; + if (Array.isArray(node)) { + flatten(node, target); + } else { + target.push(node); + } + } + + return target; +} diff --git a/test/validator/samples/silence-warnings.solo/input.svelte b/test/validator/samples/silence-warnings.solo/input.svelte new file mode 100644 index 0000000000..0e473f51db --- /dev/null +++ b/test/validator/samples/silence-warnings.solo/input.svelte @@ -0,0 +1,15 @@ + + + + + + diff --git a/test/validator/samples/silence-warnings.solo/warnings.json b/test/validator/samples/silence-warnings.solo/warnings.json new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/test/validator/samples/silence-warnings.solo/warnings.json @@ -0,0 +1 @@ +[]