From e8be01693cc041f2a9e223b51c657da194851359 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 28 Oct 2018 21:22:00 -0400 Subject: [PATCH 1/3] add replaceAsync util function --- src/utils/replaceAsync.ts | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/utils/replaceAsync.ts diff --git a/src/utils/replaceAsync.ts b/src/utils/replaceAsync.ts new file mode 100644 index 0000000000..362b76b41d --- /dev/null +++ b/src/utils/replaceAsync.ts @@ -0,0 +1,38 @@ +// asynchronous String#replace + +export default async function replaceAsync( + str: string, + re: RegExp, + func: (...any) => Promise +) { + const replacements: Promise[] = []; + str.replace(re, (...args) => { + replacements.push( + func(...args).then( + res => + { + offset: args[args.length - 2], + length: args[0].length, + replacement: res, + } + ) + ); + return ''; + }); + let out = ''; + let lastEnd = 0; + for (const { offset, length, replacement } of await Promise.all( + replacements + )) { + out += str.slice(lastEnd, offset) + replacement; + lastEnd = offset + length; + } + out += str.slice(lastEnd); + return out; +} + +interface Replacement { + offset: number; + length: number; + replacement: string; +} From 65b9a5c8612d13963747aaf62003de80fc952b71 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 28 Oct 2018 21:38:01 -0400 Subject: [PATCH 2/3] make svelte.preprocess run on all matching tags --- src/preprocess/index.ts | 74 +++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/src/preprocess/index.ts b/src/preprocess/index.ts index 047b124991..5abde887dc 100644 --- a/src/preprocess/index.ts +++ b/src/preprocess/index.ts @@ -1,4 +1,5 @@ import { SourceMap } from 'magic-string'; +import replaceAsync from '../utils/replaceAsync'; export interface PreprocessOptions { markup?: (options: { @@ -16,6 +17,11 @@ export type Preprocessor = (options: { filename?: string }) => { code: string, map?: SourceMap | string }; +interface Processed { + code: string; + map?: SourceMap | string; +} + function parseAttributeValue(value: string) { return /^['"]/.test(value) ? value.slice(1, -1) : @@ -31,60 +37,32 @@ function parseAttributes(str: string) { return attrs; } -async function replaceTagContents( - source, - type: 'script' | 'style', - preprocessor: Preprocessor, - options: PreprocessOptions -) { - const exp = new RegExp(`<${type}([\\S\\s]*?)>([\\S\\s]*?)<\\/${type}>`, 'ig'); - const match = exp.exec(source); - - if (match) { - const attributes: Record = parseAttributes(match[1]); - const content: string = match[2]; - const processed: { code: string, map?: SourceMap | string } = await preprocessor({ - content, - attributes, - filename : options.filename - }); - - if (processed && processed.code) { - return ( - source.slice(0, match.index) + - `<${type}>${processed.code}` + - source.slice(match.index + match[0].length) - ); - } - } - - return source; -} - export default async function preprocess( source: string, options: PreprocessOptions ) { - const { markup, style, script } = options; - - if (!!markup) { - const processed: { - code: string, - map?: SourceMap | string - } = await markup({ + if (options.markup) { + const processed: Processed = await options.markup({ content: source, - filename: options.filename + filename: options.filename, }); - - source = processed.code; + source = processed ? processed.code : source; } - - if (!!style) { - source = await replaceTagContents(source, 'style', style, options); - } - - if (!!script) { - source = await replaceTagContents(source, 'script', script, options); + if (options.style || options.script) { + source = await replaceAsync( + source, + /<(script|style)([^]*?)>([^]*?)<\/\1>/gi, + async (match, type, attributes, content) => { + const processed: Processed = + type in options && + (await options[type]({ + content, + attributes: parseAttributes(attributes), + filename: options.filename, + })); + return processed ? `<${type}>${processed.code}` : match; + } + ); } return { @@ -97,4 +75,4 @@ export default async function preprocess( return source; } }; -} \ No newline at end of file +} From e4e4a8d8c2571899bd2bcfd340a8caf788d723e0 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 28 Oct 2018 21:43:02 -0400 Subject: [PATCH 3/3] add test --- test/preprocess/index.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/preprocess/index.js b/test/preprocess/index.js index 044f6965e6..1a636b8588 100644 --- a/test/preprocess/index.js +++ b/test/preprocess/index.js @@ -110,6 +110,42 @@ describe('preprocess', () => { }); }); + it('preprocesses multiple matching tags', () => { + const source = ` + + + + `; + + const expected = ` + + + + `; + + return svelte.preprocess(source, { + script: ({ content }) => { + return { + code: content.toLowerCase() + }; + } + }).then(processed => { + assert.equal(processed.toString(), expected); + }); + }); + it('parses attributes', () => { const source = `