diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts index ce6b04f7f5..28cf5ba6af 100644 --- a/src/compiler/compile/css/Selector.ts +++ b/src/compiler/compile/css/Selector.ts @@ -9,6 +9,7 @@ import EachBlock from '../nodes/EachBlock'; import IfBlock from '../nodes/IfBlock'; import AwaitBlock from '../nodes/AwaitBlock'; import compiler_errors from '../compiler_errors'; +import { regex_starts_with_whitespace, regex_ends_with_whitespace } from '../../utils/patterns'; enum BlockAppliesToNode { NotPossible, @@ -340,9 +341,6 @@ 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) { const spread = node.attributes.find(attr => attr.type === 'Spread'); if (spread) return true; diff --git a/src/compiler/compile/css/Stylesheet.ts b/src/compiler/compile/css/Stylesheet.ts index cc03115749..9a3cbe9d13 100644 --- a/src/compiler/compile/css/Stylesheet.ts +++ b/src/compiler/compile/css/Stylesheet.ts @@ -9,6 +9,7 @@ import hash from '../utils/hash'; import compiler_warnings from '../compiler_warnings'; import { extract_ignores_above_position } from '../../utils/extract_svelte_ignore'; import { push_array } from '../../utils/push_array'; +import { regex_only_whitespaces, regex_whitespace } from '../../utils/patterns'; const regex_css_browser_prefix = /^-((webkit)|(moz)|(o)|(ms))-/; @@ -118,9 +119,6 @@ class Rule { } } -const regex_only_whitespace = /^\s+$/; -const regex_whitespace = /\s/; - class Declaration { node: CssNode; @@ -152,7 +150,7 @@ class Declaration { // Don't minify whitespace in custom properties, since some browsers (Chromium < 99) // treat --foo: ; and --foo:; differently - if (first.type === 'Raw' && regex_only_whitespace.test(first.value)) return; + if (first.type === 'Raw' && regex_only_whitespaces.test(first.value)) return; let start = first.start; while (regex_whitespace.test(code.original[start])) start += 1; diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index c54a5e927b..d5fad18f54 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -11,7 +11,7 @@ import StyleDirective from './StyleDirective'; import Text from './Text'; import { namespaces } from '../../utils/namespaces'; import map_children from './shared/map_children'; -import { regex_dimensions, regex_start_newline } from '../../utils/patterns'; +import { regex_dimensions, regex_starts_with_newline, regex_non_whitespace_character } from '../../utils/patterns'; import fuzzymatch from '../../utils/fuzzymatch'; import list from '../../utils/list'; import Let from './Let'; @@ -206,7 +206,6 @@ function is_valid_aria_attribute_value(schema: ARIAPropertyDefinition, value: st 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 { type: 'Element'; @@ -258,7 +257,7 @@ export default class Element extends Node { // places if there's another newline afterwards. // see https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions // see https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element - first.data = first.data.replace(regex_start_newline, ''); + first.data = first.data.replace(regex_starts_with_newline, ''); } } @@ -734,7 +733,7 @@ export default class Element extends Node { if (this.name === 'figure') { const children = this.children.filter(node => { if (node.type === 'Comment') return false; - if (node.type === 'Text') return regex_non_whitespace_characters.test(node.data); + if (node.type === 'Text') return regex_non_whitespace_character.test(node.data); return true; }); diff --git a/src/compiler/compile/nodes/Head.ts b/src/compiler/compile/nodes/Head.ts index a78f32e3d8..1ebe0c053a 100644 --- a/src/compiler/compile/nodes/Head.ts +++ b/src/compiler/compile/nodes/Head.ts @@ -5,8 +5,7 @@ import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; import { TemplateNode } from '../../interfaces'; import compiler_errors from '../compiler_errors'; - -const regex_non_whitespace_characters = /\S/; +import { regex_non_whitespace_character } from '../../utils/patterns'; export default class Head extends Node { type: 'Head'; @@ -22,7 +21,7 @@ export default class Head extends Node { } this.children = map_children(component, parent, scope, info.children.filter(child => { - return (child.type !== 'Text' || regex_non_whitespace_characters.test(child.data)); + return (child.type !== 'Text' || regex_non_whitespace_character.test(child.data)); })); if (this.children.length > 0) { diff --git a/src/compiler/compile/nodes/InlineComponent.ts b/src/compiler/compile/nodes/InlineComponent.ts index f25cc8d1ac..26cfeb7ef9 100644 --- a/src/compiler/compile/nodes/InlineComponent.ts +++ b/src/compiler/compile/nodes/InlineComponent.ts @@ -10,6 +10,7 @@ import TemplateScope from './shared/TemplateScope'; import { INode } from './interfaces'; import { TemplateNode } from '../../interfaces'; import compiler_errors from '../compiler_errors'; +import { regex_only_whitespaces } from '../../utils/patterns'; export default class InlineComponent extends Node { type: 'InlineComponent'; @@ -164,10 +165,8 @@ export default class InlineComponent extends Node { } } -const regex_only_whitespace = /^\s+$/; - function not_whitespace_text(node) { - return !(node.type === 'Text' && regex_only_whitespace.test(node.data)); + return !(node.type === 'Text' && regex_only_whitespaces.test(node.data)); } function get_namespace(parent: Node, explicit_namespace: string) { diff --git a/src/compiler/compile/nodes/Text.ts b/src/compiler/compile/nodes/Text.ts index a8db5115cd..ac6cd9b828 100644 --- a/src/compiler/compile/nodes/Text.ts +++ b/src/compiler/compile/nodes/Text.ts @@ -3,6 +3,7 @@ import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; import { INode } from './interfaces'; import { TemplateNode } from '../../interfaces'; +import { regex_non_whitespace_character } from '../../utils/patterns'; // Whitespace inside one of these elements will not result in // a whitespace node being created in any circumstances. (This @@ -17,7 +18,6 @@ const elements_without_text = new Set([ ]); const regex_ends_with_svg = /svg$/; -const regex_non_whitespace_characters = /\S/; export default class Text extends Node { type: 'Text'; @@ -31,7 +31,7 @@ export default class Text extends Node { } should_skip() { - if (regex_non_whitespace_characters.test(this.data)) return false; + if (regex_non_whitespace_character.test(this.data)) return false; const parent_element = this.find_nearest(/(?:Element|InlineComponent|SlotTemplate|Head)/); if (!parent_element) return false; diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index df530a148a..164e938674 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -3,6 +3,7 @@ import Wrapper from './wrappers/shared/Wrapper'; import { b, x } from 'code-red'; import { Node, Identifier, ArrayPattern } from 'estree'; import { is_head } from './wrappers/shared/is_head'; +import { regex_double_quotes } from '../../utils/patterns'; export interface Bindings { object: Identifier; @@ -23,8 +24,6 @@ export interface BlockOptions { dependencies?: Set; } -const regex_double_quotes = /"/g; - export default class Block { parent?: Block; renderer: Renderer; diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index faab39b74e..c36ca2acd4 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -12,8 +12,7 @@ import { RawSourceMap, DecodedSourceMap } from '@ampproject/remapping/dist/types import { flatten } from '../../utils/flatten'; import check_enable_sourcemap from '../utils/check_enable_sourcemap'; import { push_array } from '../../utils/push_array'; - -const regex_backslashes = /\\/g; +import { regex_backslashes } from '../../utils/patterns'; export default function dom( component: Component, diff --git a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts index 7221299f22..fb604f564e 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts @@ -10,6 +10,7 @@ import handle_select_value_binding from './handle_select_value_binding'; import { Identifier, Node } from 'estree'; import { namespaces } from '../../../../utils/namespaces'; import { boolean_attributes } from '../../../../../shared/boolean_attributes'; +import { regex_double_quotes } from '../../../../utils/patterns'; const non_textlike_input_types = new Set([ 'button', @@ -47,7 +48,6 @@ export class BaseAttributeWrapper { const regex_minus_sign = /-/; const regex_invalid_variable_identifier_characters = /[^a-zA-Z_$]/g; -const regex_double_quotes = /"/g; export default class AttributeWrapper extends BaseAttributeWrapper { node: Attribute; diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 9a676890fc..01f03b5589 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -12,7 +12,7 @@ import { namespaces } from '../../../../utils/namespaces'; import AttributeWrapper from './Attribute'; import StyleAttributeWrapper from './StyleAttribute'; import SpreadAttributeWrapper from './SpreadAttribute'; -import { regex_dimensions, regex_start_newline } from '../../../../utils/patterns'; +import { regex_dimensions, regex_starts_with_newline, regex_backslashes } from '../../../../utils/patterns'; import Binding from './Binding'; import add_to_set from '../../../utils/add_to_set'; import { add_event_handler } from '../shared/add_event_handlers'; @@ -1145,7 +1145,6 @@ export default class ElementWrapper extends Wrapper { } } -const regex_backslashes = /\\/g; const regex_backticks = /`/g; const regex_dollar_signs = /\$/g; @@ -1203,7 +1202,7 @@ function to_html(wrappers: Array`. // see https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element const first = wrapper.fragment.nodes[0]; - if (first && first.node.type === 'Text' && regex_start_newline.test(first.node.data)) { + if (first && first.node.type === 'Text' && regex_starts_with_newline.test(first.node.data)) { state.quasi.value.raw += '\n'; } } @@ -1215,7 +1214,7 @@ function to_html(wrappers: Array`. // see https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions const first = value_attribute.node.chunks[0]; - if (first && first.type === 'Text' && regex_start_newline.test(first.data)) { + if (first && first.type === 'Text' && regex_starts_with_newline.test(first.data)) { state.quasi.value.raw += '\n'; } to_html_for_attr_value(value_attribute, block, literal, state); diff --git a/src/compiler/compile/render_dom/wrappers/Fragment.ts b/src/compiler/compile/render_dom/wrappers/Fragment.ts index 100e707908..1e3b89e97f 100644 --- a/src/compiler/compile/render_dom/wrappers/Fragment.ts +++ b/src/compiler/compile/render_dom/wrappers/Fragment.ts @@ -21,6 +21,7 @@ import Block from '../Block'; import { trim_start, trim_end } from '../../../utils/trim'; import { link } from '../../../utils/link'; import { Identifier } from 'estree'; +import { regex_starts_with_whitespace } from '../../../utils/patterns'; const wrappers = { AwaitBlock, @@ -50,8 +51,6 @@ 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'; } -const regex_starts_with_whitespace = /^\s/; - export default class FragmentWrapper { nodes: Wrapper[]; diff --git a/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts b/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts index 17a99b1426..6512b42862 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts @@ -1,7 +1,7 @@ import Component from '../../../Component'; import { INode } from '../../../nodes/interfaces'; +import { regex_whitespace_characters } from '../../../../utils/patterns'; -const regex_whitespace_characters = /\s/g; export default function create_debugging_comment( node: INode, diff --git a/src/compiler/compile/render_ssr/handlers/Element.ts b/src/compiler/compile/render_ssr/handlers/Element.ts index dc13ac2940..081988b567 100644 --- a/src/compiler/compile/render_ssr/handlers/Element.ts +++ b/src/compiler/compile/render_ssr/handlers/Element.ts @@ -8,7 +8,7 @@ import Expression from '../../nodes/shared/Expression'; import remove_whitespace_children from './utils/remove_whitespace_children'; import fix_attribute_casing from '../../render_dom/wrappers/Element/fix_attribute_casing'; import { namespaces } from '../../../utils/namespaces'; -import { regex_start_newline } from '../../../utils/patterns'; +import { regex_starts_with_newline } from '../../../utils/patterns'; import { Node, Expression as ESExpression } from 'estree'; export default function (node: Element, renderer: Renderer, options: RenderOptions) { @@ -173,7 +173,7 @@ export default function (node: Element, renderer: Renderer, options: RenderOptio const value_attribute = node.attributes.find(({ name }) => name === 'value'); if (value_attribute) { const first = value_attribute.chunks[0]; - if (first && first.type === 'Text' && regex_start_newline.test(first.data)) { + if (first && first.type === 'Text' && regex_starts_with_newline.test(first.data)) { renderer.add_string('\n'); } } @@ -188,7 +188,7 @@ export default function (node: Element, renderer: Renderer, options: RenderOptio // see https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element // see https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions const first = children[0]; - if (first && first.type === 'Text' && regex_start_newline.test(first.data)) { + if (first && first.type === 'Text' && regex_starts_with_newline.test(first.data)) { renderer.add_string('\n'); } } diff --git a/src/compiler/compile/render_ssr/handlers/shared/get_attribute_value.ts b/src/compiler/compile/render_ssr/handlers/shared/get_attribute_value.ts index 5ce1aa3ecc..f431ea01db 100644 --- a/src/compiler/compile/render_ssr/handlers/shared/get_attribute_value.ts +++ b/src/compiler/compile/render_ssr/handlers/shared/get_attribute_value.ts @@ -4,6 +4,7 @@ import Text from '../../../nodes/Text'; import { x } from 'code-red'; import Expression from '../../../nodes/shared/Expression'; import { Expression as ESTreeExpression } from 'estree'; +import { regex_double_quotes } from '../../../../utils/patterns'; export function get_class_attribute_value(attribute: Attribute): ESTreeExpression { // handle special case — `class={possiblyUndefined}` with scoped CSS @@ -15,8 +16,6 @@ export function get_class_attribute_value(attribute: Attribute): ESTreeExpressio return get_attribute_value(attribute); } -const regex_double_quotes = /"/g; - export function get_attribute_value(attribute: Attribute): ESTreeExpression { if (attribute.chunks.length === 0) return x`""`; diff --git a/src/compiler/compile/render_ssr/handlers/utils/remove_whitespace_children.ts b/src/compiler/compile/render_ssr/handlers/utils/remove_whitespace_children.ts index 33584942a9..10ccaefa92 100644 --- a/src/compiler/compile/render_ssr/handlers/utils/remove_whitespace_children.ts +++ b/src/compiler/compile/render_ssr/handlers/utils/remove_whitespace_children.ts @@ -1,8 +1,7 @@ import { INode } from '../../../nodes/interfaces'; import { trim_end, trim_start } from '../../../../utils/trim'; import { link } from '../../../../utils/link'; - -const regex_starts_with_whitespace = /^\s/; +import { regex_starts_with_whitespace } from '../../../../utils/patterns'; // similar logic from `compile/render_dom/wrappers/Fragment` // We want to remove trailing whitespace inside an element/component/block, diff --git a/src/compiler/compile/utils/get_name_from_filename.ts b/src/compiler/compile/utils/get_name_from_filename.ts index 9d045c30df..7c0f805b76 100644 --- a/src/compiler/compile/utils/get_name_from_filename.ts +++ b/src/compiler/compile/utils/get_name_from_filename.ts @@ -1,8 +1,8 @@ +import { regex_starts_with_underscore, regex_ends_with_underscore } from '../../utils/patterns'; + const regex_percentage_characters = /%/g; const regex_file_ending = /\.[^.]+$/; const regex_repeated_invalid_variable_identifier_characters = /[^a-zA-Z_$0-9]+/g; -const regex_starts_with_underscore = /^_/; -const regex_ends_with_underscore = /_$/; const regex_starts_with_digit = /^(\d)/; export default function get_name_from_filename(filename: string) { diff --git a/src/compiler/parse/read/context.ts b/src/compiler/parse/read/context.ts index a63cee4ef2..134d11a6ad 100644 --- a/src/compiler/parse/read/context.ts +++ b/src/compiler/parse/read/context.ts @@ -10,8 +10,7 @@ import { import { parse_expression_at } from '../acorn'; import { Pattern } from 'estree'; import parser_errors from '../errors'; - -const regex_not_newline_characters = /[^\n]/g; +import { regex_not_newline_characters } from '../../utils/patterns'; export default function read_context( parser: Parser diff --git a/src/compiler/parse/read/script.ts b/src/compiler/parse/read/script.ts index c4cb150060..02506ab3d5 100644 --- a/src/compiler/parse/read/script.ts +++ b/src/compiler/parse/read/script.ts @@ -3,8 +3,8 @@ import { Parser } from '../index'; import { Script } from '../../interfaces'; import { Node, Program } from 'estree'; import parser_errors from '../errors'; +import { regex_not_newline_characters } from '../../utils/patterns'; -const regex_not_newline_characters = /[^\n]/g; const regex_closing_script_tag = /<\/script\s*>/; function get_context(parser: Parser, attributes: any[], start: number): string { diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index 34fb2027d2..45885afa96 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -4,6 +4,7 @@ import { MappedCode, SourceLocation, parse_attached_sourcemap, sourcemap_add_off import { decode_map } from './decode_sourcemap'; import { replace_in_code, slice_source } from './replace_in_code'; import { MarkupPreprocessor, Source, Preprocessor, PreprocessorGroup, Processed } from './types'; +import { regex_whitespaces } from '../utils/patterns'; export * from './types'; @@ -122,13 +123,12 @@ function processed_tag_to_code( return tag_open_code.concat(content_code).concat(tag_close_code); } -const regex_whitespace = /\s+/; const regex_quoted_value = /^['"](.*)['"]$/; function parse_tag_attributes(str: string) { // note: won't work with attribute values containing spaces. return str - .split(regex_whitespace) + .split(regex_whitespaces) .filter(Boolean) .reduce((attrs, attr) => { const i = attr.indexOf('='); diff --git a/src/compiler/utils/extract_svelte_ignore.ts b/src/compiler/utils/extract_svelte_ignore.ts index 4217bb0f83..30be2893a4 100644 --- a/src/compiler/utils/extract_svelte_ignore.ts +++ b/src/compiler/utils/extract_svelte_ignore.ts @@ -1,13 +1,12 @@ import { TemplateNode } from '../interfaces'; import { flatten } from './flatten'; +import { regex_whitespace } from './patterns'; -const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m; - -const regex_whitespace_characters = /\s/; +const regex_svelte_ignore = /^\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(regex_whitespace_characters).map(x => x.trim()).filter(Boolean) : []; + const match = regex_svelte_ignore.exec(text); + return match ? match[1].split(regex_whitespace).map(x => x.trim()).filter(Boolean) : []; } export function extract_svelte_ignore_from_comments }>(node: Node): string[] { diff --git a/src/compiler/utils/names.ts b/src/compiler/utils/names.ts index 84b731bc01..303c6297b0 100644 --- a/src/compiler/utils/names.ts +++ b/src/compiler/utils/names.ts @@ -1,5 +1,6 @@ import { isIdentifierStart, isIdentifierChar } from 'acorn'; import full_char_code_at from './full_char_code_at'; +import { regex_starts_with_underscore, regex_ends_with_underscore } from './patterns'; export const reserved = new Set([ 'arguments', @@ -66,8 +67,6 @@ export function is_valid(str: string): boolean { } const regex_non_standard_characters = /[^a-zA-Z0-9_]+/g; -const regex_starts_with_underscore = /^_/; -const regex_ends_with_underscore = /_$/; const regex_starts_with_number = /^[0-9]/; export function sanitize(name: string) { diff --git a/src/compiler/utils/patterns.ts b/src/compiler/utils/patterns.ts index b94df49297..2302be2edb 100644 --- a/src/compiler/utils/patterns.ts +++ b/src/compiler/utils/patterns.ts @@ -1,6 +1,22 @@ -export const regex_whitespace = /[ \t\r\n]/; -export const regex_start_whitespace = /^[ \t\r\n]*/; -export const regex_end_whitespace = /[ \t\r\n]*$/; -export const regex_start_newline = /^\r?\n/; +export const regex_whitespace = /\s/; +export const regex_whitespaces = /\s+/; +export const regex_starts_with_whitespace = /^\s/; +export const regex_ends_with_whitespace = /\s$/; +export const regex_only_whitespaces = /^\s+$/; + +export const regex_whitespace_characters = /\s/g; +export const regex_non_whitespace_character = /\S/; + +export const regex_starts_with_newline = /^\r?\n/; +export const regex_not_newline_characters = /[^\n]/g; + +export const regex_double_quotes = /"/g; + +export const regex_backslashes = /\\/g; + +export const regex_starts_with_underscore = /^_/; +export const regex_ends_with_underscore = /_$/; + +export const regex_invalid_variable_identifier_characters = /[^a-zA-Z0-9_$]/g; export const regex_dimensions = /^(?:offset|client)(?:Width|Height)$/; diff --git a/src/compiler/utils/trim.ts b/src/compiler/utils/trim.ts index 63463cee1f..d64ad25d37 100644 --- a/src/compiler/utils/trim.ts +++ b/src/compiler/utils/trim.ts @@ -1,9 +1,9 @@ -import { regex_start_whitespace, regex_end_whitespace } from './patterns'; +import { regex_starts_with_whitespace, regex_ends_with_whitespace } from './patterns'; export function trim_start(str: string) { - return str.replace(regex_start_whitespace, ''); + return str.replace(regex_starts_with_whitespace, ''); } export function trim_end(str: string) { - return str.replace(regex_end_whitespace, ''); + return str.replace(regex_ends_with_whitespace, ''); }