diff --git a/src/compiler/preprocess/index.ts b/src/compiler/preprocess/index.ts index ab2ede29e0..46ebc83181 100644 --- a/src/compiler/preprocess/index.ts +++ b/src/compiler/preprocess/index.ts @@ -13,8 +13,10 @@ interface SourceUpdate { dependencies?: string[]; } +const regex_filepath_separator = /[/\\]/; + function get_file_basename(filename: string) { - return filename.split(/[/\\]/).pop(); + return filename.split(regex_filepath_separator).pop(); } /** @@ -120,20 +122,27 @@ function processed_tag_to_code( return tag_open_code.concat(content_code).concat(tag_close_code); } +const regex_whitespace = /\s+/; +const regex_unquoted_value = /^['"](.*)['"]$/; + function parse_tag_attributes(str: string) { // note: won't work with attribute values containing spaces. return str - .split(/\s+/) + .split(regex_whitespace) .filter(Boolean) .reduce((attrs, attr) => { const i = attr.indexOf('='); const [key, value] = i > 0 ? [attr.slice(0, i), attr.slice(i + 1)] : [attr]; - const [, unquoted] = (value && value.match(/^['"](.*)['"]$/)) || []; + const [, unquoted] = (value && value.match(regex_unquoted_value)) || []; return { ...attrs, [key]: unquoted ?? value ?? true }; }, {}); } + +const regex_style_tags = /|([^]*?)<\/style>|\/>)/gi; +const regex_script_tags = /|([^]*?)<\/script>|\/>)/gi; + /** * Calculate the updates required to process all instances of the specified tag. */ @@ -143,10 +152,7 @@ async function process_tag( source: Source ): Promise { const { filename, source: markup } = source; - const tag_regex = - tag_name === 'style' - ? /|([^]*?)<\/style>|\/>)/gi - : /|([^]*?)<\/script>|\/>)/gi; + const tag_regex = tag_name === 'style' ? regex_style_tags : regex_script_tags; const dependencies: string[] = []; @@ -190,7 +196,7 @@ async function process_markup(process: MarkupPreprocessor, source: Source) { string: processed.code, map: processed.map ? // TODO: can we use decode_sourcemap? - typeof processed.map === 'string' + typeof processed.map === 'string' ? JSON.parse(processed.map) : processed.map : undefined, diff --git a/src/compiler/utils/extract_svelte_ignore.ts b/src/compiler/utils/extract_svelte_ignore.ts index 306ba872d6..4931929639 100644 --- a/src/compiler/utils/extract_svelte_ignore.ts +++ b/src/compiler/utils/extract_svelte_ignore.ts @@ -3,9 +3,11 @@ import { flatten } from './flatten'; const pattern = /^\s*svelte-ignore\s+([\s\S]+)\s*$/m; +const regex_no_whitespace_character = /[^\S]/; + 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) : []; + return match ? match[1].split(regex_no_whitespace_character).map(x => x.trim()).filter(Boolean) : []; } export function extract_svelte_ignore_from_comments }>(node: Node): string[] { diff --git a/src/compiler/utils/get_code_frame.ts b/src/compiler/utils/get_code_frame.ts index 1097f5b3d2..14ca44badb 100644 --- a/src/compiler/utils/get_code_frame.ts +++ b/src/compiler/utils/get_code_frame.ts @@ -1,5 +1,7 @@ +const regex_tabs = /^\t+/; + function tabs_to_spaces(str: string) { - return str.replace(/^\t+/, match => match.split('\t').join(' ')); + return str.replace(regex_tabs, match => match.split('\t').join(' ')); } export default function get_code_frame( diff --git a/src/compiler/utils/mapped_code.ts b/src/compiler/utils/mapped_code.ts index 04fa05be9a..b816ae8b83 100644 --- a/src/compiler/utils/mapped_code.ts +++ b/src/compiler/utils/mapped_code.ts @@ -182,6 +182,8 @@ export class MappedCode { return new MappedCode(string, map); } + private static regex_line_token = /([^\d\w\s]|\s+)/g; + static from_source({ source, file_basename, get_location }: Source): MappedCode { let offset: SourceLocation = get_location(0); @@ -195,7 +197,7 @@ export class MappedCode { const line_list = source.split('\n'); for (let line = 0; line < line_list.length; line++) { map.mappings.push([]); - const token_list = line_list[line].split(/([^\d\w\s]|\s+)/g); + const token_list = line_list[line].split(this.regex_line_token); for (let token = 0, column = 0; token < token_list.length; token++) { if (token_list[token] == '') continue; map.mappings[line].push([column, 0, offset.line + line, column]); @@ -245,7 +247,7 @@ export function combine_sourcemaps( if (!map.file) delete map.file; // skip optional field `file` // When source maps are combined and the leading map is empty, sources is not set. - // Add the filename to the empty array in this case. + // Add the filename to the empty array in this case. // Further improvements to remapping may help address this as well https://github.com/ampproject/remapping/issues/116 if (!map.sources.length) map.sources = [filename]; @@ -289,6 +291,8 @@ export function apply_preprocessor_sourcemap(filename: string, svelte_map: Sourc return result_map as SourceMap; } +const regex_data_uri = /data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(\S*)/; + // parse attached sourcemap in processed.code export function parse_attached_sourcemap(processed: Processed, tag_name: 'script' | 'style'): void { const r_in = '[#@]\\s*sourceMappingURL\\s*=\\s*(\\S*)'; @@ -302,7 +306,7 @@ export function parse_attached_sourcemap(processed: Processed, tag_name: 'script } processed.code = processed.code.replace(regex, (_, match1, match2) => { const map_url = (tag_name == 'script') ? (match1 || match2) : match1; - const map_data = (map_url.match(/data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(\S*)/) || [])[1]; + const map_data = (map_url.match(regex_data_uri) || [])[1]; if (map_data) { // sourceMappingURL is data URL if (processed.map) { diff --git a/src/compiler/utils/names.ts b/src/compiler/utils/names.ts index 9d5b78fceb..84b731bc01 100644 --- a/src/compiler/utils/names.ts +++ b/src/compiler/utils/names.ts @@ -65,10 +65,15 @@ export function is_valid(str: string): boolean { return true; } +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) { return name - .replace(/[^a-zA-Z0-9_]+/g, '_') - .replace(/^_/, '') - .replace(/_$/, '') - .replace(/^[0-9]/, '_$&'); + .replace(regex_non_standard_characters, '_') + .replace(regex_starts_with_underscore, '') + .replace(regex_ends_with_underscore, '') + .replace(regex_starts_with_number, '_$&'); }