optimize `.test() calls

pull/7716/head
Ivan Hofer 4 years ago committed by tanhauhau
parent 7261ff0acf
commit 445fe983ac

@ -48,6 +48,8 @@ interface ComponentOptions {
} }
const regex_leading_directory_separator = /^[/\\]/; const regex_leading_directory_separator = /^[/\\]/;
const regex_starts_with_Export = /^Export/;
const regex_contains_Function = /Function/;
export default class Component { export default class Component {
stats: Stats; stats: Stats;
@ -640,7 +642,7 @@ export default class Component {
body.splice(i, 1); body.splice(i, 1);
} }
if (/^Export/.test(node.type)) { if (regex_starts_with_Export.test(node.type)) {
const replacement = this.extract_exports(node, true); const replacement = this.extract_exports(node, true);
if (replacement) { if (replacement) {
body[i] = replacement; body[i] = replacement;
@ -797,7 +799,7 @@ export default class Component {
return this.skip(); return this.skip();
} }
if (/^Export/.test(node.type)) { if (regex_starts_with_Export.test(node.type)) {
const replacement = component.extract_exports(node); const replacement = component.extract_exports(node);
if (replacement) { if (replacement) {
this.replace(replacement); this.replace(replacement);
@ -920,7 +922,7 @@ export default class Component {
} }
if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) { if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
if (!((/Function/.test(parent.type) && prop === 'params') || (parent.type === 'VariableDeclarator' && prop === 'id'))) { if (!((regex_contains_Function.test(parent.type) && prop === 'params') || (parent.type === 'VariableDeclarator' && prop === 'id'))) {
return this.error(node as any, compiler_errors.contextual_store); return this.error(node as any, compiler_errors.contextual_store);
} }
} }
@ -967,7 +969,7 @@ export default class Component {
walk(this.ast.instance.content, { walk(this.ast.instance.content, {
enter(node: Node) { enter(node: Node) {
if (/Function/.test(node.type)) { if (regex_contains_Function.test(node.type)) {
return this.skip(); return this.skip();
} }
@ -1462,6 +1464,8 @@ export default class Component {
} }
} }
const regex_valid_tag_name = /^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/;
function process_component_options(component: Component, nodes) { function process_component_options(component: Component, nodes) {
const component_options: ComponentOptions = { const component_options: ComponentOptions = {
immutable: component.compile_options.immutable || false, immutable: component.compile_options.immutable || false,
@ -1507,7 +1511,7 @@ function process_component_options(component: Component, nodes) {
return component.error(attribute, compiler_errors.invalid_tag_attribute); return component.error(attribute, compiler_errors.invalid_tag_attribute);
} }
if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) { if (tag && !regex_valid_tag_name.test(tag)) {
return component.error(attribute, compiler_errors.invalid_tag_property); return component.error(attribute, compiler_errors.invalid_tag_property);
} }

@ -25,6 +25,8 @@ const whitelist_attribute_selector = new Map([
['dialog', new Set(['open'])] ['dialog', new Set(['open'])]
]); ]);
const regex_is_single_css_selector = /[^\\],(?!([^([]+[^\\]|[^([\\])[)\]])/;
export default class Selector { export default class Selector {
node: CssNode; node: CssNode;
stylesheet: Stylesheet; stylesheet: Stylesheet;
@ -157,7 +159,7 @@ export default class Selector {
for (const block of this.blocks) { for (const block of this.blocks) {
for (const selector of block.selectors) { for (const selector of block.selectors) {
if (selector.type === 'PseudoClassSelector' && selector.name === 'global') { if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
if (/[^\\],(?!([^([]+[^\\]|[^([\\])[)\]])/.test(selector.children[0].value)) { if (regex_is_single_css_selector.test(selector.children[0].value)) {
component.error(selector, compiler_errors.css_invalid_global_selector); component.error(selector, compiler_errors.css_invalid_global_selector);
} }
} }
@ -338,6 +340,9 @@ function test_attribute(operator, expected_value, case_insensitive, value) {
} }
} }
const regex_starts_with_whitespace = /^\s/;
const regex_ends_with_whitespace = /\s$/;
function attribute_matches(node: CssNode, name: string, expected_value: string, operator: string, case_insensitive: boolean) { function attribute_matches(node: CssNode, name: string, expected_value: string, operator: string, case_insensitive: boolean) {
const spread = node.attributes.find(attr => attr.type === 'Spread'); const spread = node.attributes.find(attr => attr.type === 'Spread');
if (spread) return true; if (spread) return true;
@ -373,7 +378,7 @@ function attribute_matches(node: CssNode, name: string, expected_value: string,
const start_with_space = []; const start_with_space = [];
const remaining = []; const remaining = [];
current_possible_values.forEach((current_possible_value: string) => { current_possible_values.forEach((current_possible_value: string) => {
if (/^\s/.test(current_possible_value)) { if (regex_starts_with_whitespace.test(current_possible_value)) {
start_with_space.push(current_possible_value); start_with_space.push(current_possible_value);
} else { } else {
remaining.push(current_possible_value); remaining.push(current_possible_value);
@ -394,7 +399,7 @@ function attribute_matches(node: CssNode, name: string, expected_value: string,
prev_values = combined; prev_values = combined;
start_with_space.forEach((value: string) => { start_with_space.forEach((value: string) => {
if (/\s$/.test(value)) { if (regex_ends_with_whitespace.test(value)) {
possible_values.add(value); possible_values.add(value);
} else { } else {
prev_values.push(value); prev_values.push(value);
@ -408,7 +413,7 @@ function attribute_matches(node: CssNode, name: string, expected_value: string,
} }
current_possible_values.forEach((current_possible_value: string) => { current_possible_values.forEach((current_possible_value: string) => {
if (/\s$/.test(current_possible_value)) { if (regex_ends_with_whitespace.test(current_possible_value)) {
possible_values.add(current_possible_value); possible_values.add(current_possible_value);
} else { } else {
prev_values.push(current_possible_value); prev_values.push(current_possible_value);

@ -118,6 +118,9 @@ class Rule {
} }
} }
const regex_only_whitespace = /^\s+$/;
const regex_whitespace = /\s/;
class Declaration { class Declaration {
node: CssNode; node: CssNode;
@ -149,10 +152,10 @@ class Declaration {
// Don't minify whitespace in custom properties, since some browsers (Chromium < 99) // Don't minify whitespace in custom properties, since some browsers (Chromium < 99)
// treat --foo: ; and --foo:; differently // treat --foo: ; and --foo:; differently
if (first.type === 'Raw' && /^\s+$/.test(first.value)) return; if (first.type === 'Raw' && regex_only_whitespace.test(first.value)) return;
let start = first.start; let start = first.start;
while (/\s/.test(code.original[start])) start += 1; while (regex_whitespace.test(code.original[start])) start += 1;
if (start - c > 1) { if (start - c > 1) {
code.overwrite(c, start, ':'); code.overwrite(c, start, ':');

@ -35,6 +35,9 @@ const valid_options = [
'cssHash' 'cssHash'
]; ];
const regex_valid_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
const regex_starts_with_lowercase_character = /^[a-z]/;
function validate_options(options: CompileOptions, warnings: Warning[]) { function validate_options(options: CompileOptions, warnings: Warning[]) {
const { name, filename, loopGuardTimeout, dev, namespace } = options; const { name, filename, loopGuardTimeout, dev, namespace } = options;
@ -48,11 +51,11 @@ function validate_options(options: CompileOptions, warnings: Warning[]) {
} }
}); });
if (name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(name)) { if (name && !regex_valid_identifier.test(name)) {
throw new Error(`options.name must be a valid identifier (got '${name}')`); throw new Error(`options.name must be a valid identifier (got '${name}')`);
} }
if (name && /^[a-z]/.test(name)) { if (name && regex_starts_with_lowercase_character.test(name)) {
const message = 'options.name should be capitalised'; const message = 'options.name should be capitalised';
warnings.push({ warnings.push({
code: 'options-lowercase-name', code: 'options-lowercase-name',

@ -203,7 +203,10 @@ function is_valid_aria_attribute_value(schema: ARIAPropertyDefinition, value: st
} }
} }
const regex_any_repeated_whitespace = /[\s]+/g; const regex_any_repeated_whitespaces = /[\s]+/g;
const regex_heading_tags = /^h[1-6]$/;
const regex_illegal_attribute_character = /(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/;
const regex_non_whitespace_characters = /\S/;
export default class Element extends Node { export default class Element extends Node {
type: 'Element'; type: 'Element';
@ -400,7 +403,7 @@ export default class Element extends Node {
// Errors // Errors
if (/(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/.test(name)) { if (regex_illegal_attribute_character.test(name)) {
return component.error(attribute, compiler_errors.illegal_attribute(name)); return component.error(attribute, compiler_errors.illegal_attribute(name));
} }
@ -466,7 +469,7 @@ export default class Element extends Node {
component.warn(attribute, compiler_warnings.a11y_unknown_aria_attribute(type, match)); component.warn(attribute, compiler_warnings.a11y_unknown_aria_attribute(type, match));
} }
if (name === 'aria-hidden' && /^h[1-6]$/.test(this.name)) { if (name === 'aria-hidden' && regex_heading_tags.test(this.name)) {
component.warn(attribute, compiler_warnings.a11y_hidden(this.name)); component.warn(attribute, compiler_warnings.a11y_hidden(this.name));
} }
@ -731,7 +734,7 @@ export default class Element extends Node {
if (this.name === 'figure') { if (this.name === 'figure') {
const children = this.children.filter(node => { const children = this.children.filter(node => {
if (node.type === 'Comment') return false; if (node.type === 'Comment') return false;
if (node.type === 'Text') return /\S/.test(node.data); if (node.type === 'Text') return regex_non_whitespace_characters.test(node.data);
return true; return true;
}); });
@ -990,7 +993,7 @@ export default class Element extends Node {
if (attribute && !attribute.is_true) { if (attribute && !attribute.is_true) {
attribute.chunks.forEach((chunk, index) => { attribute.chunks.forEach((chunk, index) => {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
let data = chunk.data.replace(regex_any_repeated_whitespace, ' '); let data = chunk.data.replace(regex_any_repeated_whitespaces, ' ');
if (index === 0) { if (index === 0) {
data = data.trimLeft(); data = data.trimLeft();
} else if (index === attribute.chunks.length - 1) { } else if (index === attribute.chunks.length - 1) {
@ -1019,10 +1022,12 @@ function should_have_attribute(
node.component.warn(node, compiler_warnings.a11y_missing_attribute(name, article, sequence)); node.component.warn(node, compiler_warnings.a11y_missing_attribute(name, article, sequence));
} }
const regex_minus_sign = /-/;
function within_custom_element(parent: INode) { function within_custom_element(parent: INode) {
while (parent) { while (parent) {
if (parent.type === 'InlineComponent') return false; if (parent.type === 'InlineComponent') return false;
if (parent.type === 'Element' && /-/.test(parent.name)) return true; if (parent.type === 'Element' && regex_minus_sign.test(parent.name)) return true;
parent = parent.parent; parent = parent.parent;
} }
return false; return false;

@ -6,6 +6,8 @@ import { Identifier } from 'estree';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { TemplateNode } from '../../interfaces'; import { TemplateNode } from '../../interfaces';
const regex_FunctionExpression = /FunctionExpression/;
export default class EventHandler extends Node { export default class EventHandler extends Node {
type: 'EventHandler'; type: 'EventHandler';
name: string; name: string;
@ -25,7 +27,7 @@ export default class EventHandler extends Node {
this.expression = new Expression(component, this, template_scope, info.expression); this.expression = new Expression(component, this, template_scope, info.expression);
this.uses_context = this.expression.uses_context; this.uses_context = this.expression.uses_context;
if (/FunctionExpression/.test(info.expression.type) && info.expression.params.length === 0) { if (regex_FunctionExpression.test(info.expression.type) && info.expression.params.length === 0) {
// TODO make this detection more accurate — if `event.preventDefault` isn't called, and // TODO make this detection more accurate — if `event.preventDefault` isn't called, and
// `event` is passed to another function, we can make it passive // `event` is passed to another function, we can make it passive
this.can_make_passive = true; this.can_make_passive = true;
@ -55,7 +57,7 @@ export default class EventHandler extends Node {
} }
const node = this.expression.node; const node = this.expression.node;
if (/FunctionExpression/.test(node.type)) { if (regex_FunctionExpression.test(node.type)) {
return false; return false;
} }

@ -6,6 +6,8 @@ import TemplateScope from './shared/TemplateScope';
import { TemplateNode } from '../../interfaces'; import { TemplateNode } from '../../interfaces';
import compiler_errors from '../compiler_errors'; import compiler_errors from '../compiler_errors';
const regex_non_whitespace_characters = /\S/;
export default class Head extends Node { export default class Head extends Node {
type: 'Head'; type: 'Head';
children: any[]; // TODO children: any[]; // TODO
@ -20,7 +22,7 @@ export default class Head extends Node {
} }
this.children = map_children(component, parent, scope, info.children.filter(child => { this.children = map_children(component, parent, scope, info.children.filter(child => {
return (child.type !== 'Text' || /\S/.test(child.data)); return (child.type !== 'Text' || regex_non_whitespace_characters.test(child.data));
})); }));
if (this.children.length > 0) { if (this.children.length > 0) {

@ -164,8 +164,10 @@ export default class InlineComponent extends Node {
} }
} }
const regex_only_whitespace = /^\s+$/;
function not_whitespace_text(node) { function not_whitespace_text(node) {
return !(node.type === 'Text' && /^\s+$/.test(node.data)); return !(node.type === 'Text' && regex_only_whitespace.test(node.data));
} }
function get_namespace(parent: Node, explicit_namespace: string) { function get_namespace(parent: Node, explicit_namespace: string) {

@ -16,6 +16,9 @@ const elements_without_text = new Set([
'video' 'video'
]); ]);
const regex_ends_with_svg = /svg$/;
const regex_non_whitespace_characters = /\S/;
export default class Text extends Node { export default class Text extends Node {
type: 'Text'; type: 'Text';
data: string; data: string;
@ -28,7 +31,7 @@ export default class Text extends Node {
} }
should_skip() { should_skip() {
if (/\S/.test(this.data)) return false; if (regex_non_whitespace_characters.test(this.data)) return false;
const parent_element = this.find_nearest(/(?:Element|InlineComponent|SlotTemplate|Head)/); const parent_element = this.find_nearest(/(?:Element|InlineComponent|SlotTemplate|Head)/);
if (!parent_element) return false; if (!parent_element) return false;
@ -37,7 +40,7 @@ export default class Text extends Node {
if (parent_element.type === 'InlineComponent') return parent_element.children.length === 1 && this === parent_element.children[0]; if (parent_element.type === 'InlineComponent') return parent_element.children.length === 1 && this === parent_element.children[0];
// svg namespace exclusions // svg namespace exclusions
if (/svg$/.test(parent_element.namespace)) { if (regex_ends_with_svg.test(parent_element.namespace)) {
if (this.prev && this.prev.type === 'Element' && this.prev.name === 'tspan') return false; if (this.prev && this.prev.type === 'Element' && this.prev.name === 'tspan') return false;
} }

@ -4,6 +4,8 @@ import Node from './Node';
import { INode } from '../interfaces'; import { INode } from '../interfaces';
import compiler_warnings from '../../compiler_warnings'; import compiler_warnings from '../../compiler_warnings';
const regex_non_whitespace_characters = /\S/;
export default class AbstractBlock extends Node { export default class AbstractBlock extends Node {
block: Block; block: Block;
children: INode[]; children: INode[];
@ -17,7 +19,7 @@ export default class AbstractBlock extends Node {
const child = this.children[0]; const child = this.children[0];
if (!child || (child.type === 'Text' && !/[^\s]/.test(child.data))) { if (!child || (child.type === 'Text' && !regex_non_whitespace_characters.test(child.data))) {
this.component.warn(this, compiler_warnings.empty_block); this.component.warn(this, compiler_warnings.empty_block);
} }
} }

@ -21,6 +21,8 @@ import compiler_errors from '../../compiler_errors';
type Owner = INode; type Owner = INode;
const regex_FunctionExpression = /FunctionExpression/;
export default class Expression { export default class Expression {
type: 'Expression' = 'Expression'; type: 'Expression' = 'Expression';
component: Component; component: Component;
@ -72,7 +74,7 @@ export default class Expression {
scope = map.get(node); scope = map.get(node);
} }
if (!function_expression && /FunctionExpression/.test(node.type)) { if (!function_expression && regex_FunctionExpression.test(node.type)) {
function_expression = node; function_expression = node;
} }

@ -42,7 +42,7 @@ export class BaseAttributeWrapper {
} }
} }
render(_block: Block) {} render(_block: Block) { }
} }
const regex_minus_sign = /-/; const regex_minus_sign = /-/;
@ -385,13 +385,14 @@ function should_cache(attribute: AttributeWrapper) {
return attribute.is_src || attribute.node.should_cache(); return attribute.is_src || attribute.node.should_cache();
} }
const regex_checked_or_group = /checked|group/;
function is_indirectly_bound_value(attribute: AttributeWrapper) { function is_indirectly_bound_value(attribute: AttributeWrapper) {
const element = attribute.parent; const element = attribute.parent;
return attribute.name === 'value' && return attribute.name === 'value' &&
(element.node.name === 'option' || // TODO check it's actually bound (element.node.name === 'option' || // TODO check it's actually bound
(element.node.name === 'input' && (element.node.name === 'input' &&
element.node.bindings.some( element.node.bindings.some(
(binding) => (binding) => regex_checked_or_group.test(binding.name)
/checked|group/.test(binding.name)
))); )));
} }

@ -109,6 +109,7 @@ function optimize_style(value: Array<Text | Expression>) {
} }
const regex_important_flag = /\s*!important\s*$/; const regex_important_flag = /\s*!important\s*$/;
const regex_semicolon_or_Whitespace = /[;\s]/;
function get_style_value(chunks: Array<Text | Expression>) { function get_style_value(chunks: Array<Text | Expression>) {
const value: Array<Text | Expression> = []; const value: Array<Text | Expression> = [];
@ -155,7 +156,7 @@ function get_style_value(chunks: Array<Text | Expression>) {
} as Text); } as Text);
} }
while (/[;\s]/.test(chunk.data[c])) c += 1; while (regex_semicolon_or_Whitespace.test(chunk.data[c])) c += 1;
const remaining_data = chunk.data.slice(c); const remaining_data = chunk.data.slice(c);
if (remaining_data) { if (remaining_data) {

@ -34,12 +34,16 @@ interface BindingGroup {
bindings: Binding[]; bindings: Binding[];
} }
const regex_radio_or_checkbox_or_file = /radio|checkbox|file/;
const regex_radio_or_checkbox_or_range_or_file = /radio|checkbox|range|file/;
const events = [ const events = [
{ {
event_names: ['input'], event_names: ['input'],
filter: (node: Element, _name: string) => filter: (node: Element, _name: string) =>
node.name === 'textarea' || node.name === 'textarea' ||
node.name === 'input' && !/radio|checkbox|range|file/.test(node.get_static_attribute_value('type') as string) node.name === 'input' &&
!regex_radio_or_checkbox_or_range_or_file.test(node.get_static_attribute_value('type') as string)
}, },
{ {
event_names: ['input'], event_names: ['input'],
@ -51,7 +55,8 @@ const events = [
event_names: ['change'], event_names: ['change'],
filter: (node: Element, _name: string) => filter: (node: Element, _name: string) =>
node.name === 'select' || node.name === 'select' ||
node.name === 'input' && /radio|checkbox|file/.test(node.get_static_attribute_value('type') as string) node.name === 'input' &&
regex_radio_or_checkbox_or_file.test(node.get_static_attribute_value('type') as string)
}, },
{ {
event_names: ['change', 'input'], event_names: ['change', 'input'],

@ -50,6 +50,8 @@ function trimmable_at(child: INode, next_sibling: Wrapper): boolean {
return (next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/)) || next_sibling.node.prev.type === 'EachBlock'; return (next_sibling.node.find_nearest(/EachBlock/) === child.find_nearest(/EachBlock/)) || next_sibling.node.prev.type === 'EachBlock';
} }
const regex_starts_with_whitespace = /^\s/;
export default class FragmentWrapper { export default class FragmentWrapper {
nodes: Wrapper[]; nodes: Wrapper[];
@ -92,7 +94,7 @@ export default class FragmentWrapper {
// *unless* there is no whitespace between this node and its next sibling // *unless* there is no whitespace between this node and its next sibling
if (this.nodes.length === 0) { if (this.nodes.length === 0) {
const should_trim = ( const should_trim = (
next_sibling ? (next_sibling.node.type === 'Text' && /^\s/.test(next_sibling.node.data) && trimmable_at(child, next_sibling)) : !child.has_ancestor('EachBlock') next_sibling ? (next_sibling.node.type === 'Text' && regex_starts_with_whitespace.test(next_sibling.node.data) && trimmable_at(child, next_sibling)) : !child.has_ancestor('EachBlock')
); );
if (should_trim && !child.keep_space()) { if (should_trim && !child.keep_space()) {

@ -5,6 +5,8 @@ import Wrapper from './shared/Wrapper';
import { x } from 'code-red'; import { x } from 'code-red';
import { Identifier } from 'estree'; import { Identifier } from 'estree';
const regex_non_whitespace_characters = /[\S\u00A0]/;
export default class TextWrapper extends Wrapper { export default class TextWrapper extends Wrapper {
node: Text; node: Text;
data: string; data: string;
@ -27,7 +29,7 @@ export default class TextWrapper extends Wrapper {
use_space() { use_space() {
if (this.renderer.component.component_options.preserveWhitespace) return false; if (this.renderer.component.component_options.preserveWhitespace) return false;
if (/[\S\u00A0]/.test(this.data)) return false; if (regex_non_whitespace_characters.test(this.data)) return false;
return !this.node.within_pre(); return !this.node.within_pre();
} }

@ -2,6 +2,8 @@ import { INode } from '../../../nodes/interfaces';
import { trim_end, trim_start } from '../../../../utils/trim'; import { trim_end, trim_start } from '../../../../utils/trim';
import { link } from '../../../../utils/link'; import { link } from '../../../../utils/link';
const regex_starts_with_whitespace = /^\s/;
// similar logic from `compile/render_dom/wrappers/Fragment` // similar logic from `compile/render_dom/wrappers/Fragment`
// We want to remove trailing whitespace inside an element/component/block, // We want to remove trailing whitespace inside an element/component/block,
// *unless* there is no whitespace between this node and its next sibling // *unless* there is no whitespace between this node and its next sibling
@ -22,7 +24,7 @@ export default function remove_whitespace_children(children: INode[], next?: INo
if (nodes.length === 0) { if (nodes.length === 0) {
const should_trim = next const should_trim = next
? next.type === 'Text' && ? next.type === 'Text' &&
/^\s/.test(next.data) && regex_starts_with_whitespace.test(next.data) &&
trimmable_at(child, next) trimmable_at(child, next)
: !child.has_ancestor('EachBlock'); : !child.has_ancestor('EachBlock');

@ -55,6 +55,7 @@ function parent_is_head(stack) {
const regex_closing_textarea_tag = /^<\/textarea(\s[^>]*)?>/i; const regex_closing_textarea_tag = /^<\/textarea(\s[^>]*)?>/i;
const regex_closing_comment = /-->/; const regex_closing_comment = /-->/;
const regex_capital_letter = /[A-Z]/;
export default function tag(parser: Parser) { export default function tag(parser: Parser) {
const start = parser.index++; const start = parser.index++;
@ -107,7 +108,7 @@ export default function tag(parser: Parser) {
const type = meta_tags.has(name) const type = meta_tags.has(name)
? meta_tags.get(name) ? meta_tags.get(name)
: (/[A-Z]/.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'InlineComponent' : (regex_capital_letter.test(name[0]) || name === 'svelte:self' || name === 'svelte:component') ? 'InlineComponent'
: name === 'svelte:fragment' ? 'SlotTemplate' : name === 'svelte:fragment' ? 'SlotTemplate'
: name === 'title' && parent_is_head(parser.stack) ? 'Title' : name === 'title' && parent_is_head(parser.stack) ? 'Title'
: name === 'slot' && !parser.customElement ? 'Slot' : 'Element'; : name === 'slot' && !parser.customElement ? 'Slot' : 'Element';

@ -3,11 +3,11 @@ import { flatten } from './flatten';
const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m; const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m;
const regex_no_whitespace_character = /[^\S]/; const regex_whitespace_characters = /\s/;
export function extract_svelte_ignore(text: string): string[] { export function extract_svelte_ignore(text: string): string[] {
const match = pattern.exec(text); const match = pattern.exec(text);
return match ? match[1].split(regex_no_whitespace_character).map(x => x.trim()).filter(Boolean) : []; return match ? match[1].split(regex_whitespace_characters).map(x => x.trim()).filter(Boolean) : [];
} }
export function extract_svelte_ignore_from_comments<Node extends { leadingComments?: Array<{value: string}> }>(node: Node): string[] { export function extract_svelte_ignore_from_comments<Node extends { leadingComments?: Array<{value: string}> }>(node: Node): string[] {

Loading…
Cancel
Save