diff --git a/package.json b/package.json index f47a600d..ff34d0a4 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,8 @@ "@types/pug": "^2.0.4", "@types/sass": "^1.16.0", "detect-indent": "^6.0.0", + "magic-string": "^0.25.7", + "sorcery": "^0.10.0", "strip-indent": "^3.0.0" }, "peerDependencies": { diff --git a/src/autoProcess.ts b/src/autoProcess.ts index c1f05dd5..3951ea7c 100644 --- a/src/autoProcess.ts +++ b/src/autoProcess.ts @@ -60,7 +60,7 @@ type AutoPreprocessOptions = { export const transform = async ( name: string, options: TransformerOptions, - { content, map, filename, attributes }: TransformerArgs, + { content, markup, map, filename, attributes }: TransformerArgs, ): Promise => { if (options === false) { return { code: content }; @@ -75,6 +75,7 @@ export const transform = async ( return transformer({ content, + markup, filename, map, attributes, @@ -151,6 +152,7 @@ export function sveltePreprocess( ): Preprocessor => async (svelteFile) => { let { content, + markup, filename, lang, alias, @@ -187,6 +189,7 @@ export function sveltePreprocess( const transformed = await transform(lang, transformerOptions, { content, + markup, filename, attributes, }); @@ -205,6 +208,7 @@ export function sveltePreprocess( if (transformers.replace) { const transformed = await transform('replace', transformers.replace, { content, + markup: content, filename, }); @@ -221,11 +225,13 @@ export function sveltePreprocess( const script: PreprocessorGroup['script'] = async ({ content, attributes, + markup: fullMarkup, filename, }) => { const transformResult: Processed = await scriptTransformer({ content, attributes, + markup: fullMarkup, filename, }); @@ -235,7 +241,7 @@ export function sveltePreprocess( const transformed = await transform( 'babel', getTransformerOptions('babel'), - { content: code, map, filename, attributes }, + { content: code, markup: fullMarkup, map, filename, attributes }, ); code = transformed.code; @@ -250,11 +256,13 @@ export function sveltePreprocess( const style: PreprocessorGroup['style'] = async ({ content, attributes, + markup: fullMarkup, filename, }) => { const transformResult = await cssTransformer({ content, attributes, + markup: fullMarkup, filename, }); @@ -275,6 +283,7 @@ export function sveltePreprocess( const transformed = await transform('postcss', postcssOptions, { content: code, + markup: fullMarkup, map, filename, attributes, @@ -288,7 +297,7 @@ export function sveltePreprocess( const transformed = await transform( 'globalStyle', getTransformerOptions('globalStyle'), - { content: code, map, filename, attributes }, + { content: code, markup: fullMarkup, map, filename, attributes }, ); code = transformed.code; diff --git a/src/modules/markup.ts b/src/modules/markup.ts index 704842fd..fb0fc273 100644 --- a/src/modules/markup.ts +++ b/src/modules/markup.ts @@ -1,5 +1,35 @@ import type { Transformer, Preprocessor } from '../types'; +/** Create a tag matching regexp. */ +export function createTagRegex(tagName: string, flags?: string): RegExp { + return new RegExp( + `|<${tagName}(\\s[^]*?)?(?:>([^]*?)<\\/${tagName}>|\\/>)`, + flags, + ); +} + +/** Strip script and style tags from markup. */ +export function stripTags(markup: string): string { + return markup + .replace(createTagRegex('style', 'gi'), '') + .replace(createTagRegex('script', 'gi'), ''); +} + +/** Transform an attribute string into a key-value object */ +export function parseAttributes(attributesStr: string): Record { + return attributesStr + .split(/\s+/) + .filter(Boolean) + .reduce((acc: Record, attr) => { + const [name, value] = attr.split('='); + + // istanbul ignore next + acc[name] = value ? value.replace(/['"]/g, '') : true; + + return acc; + }, {}); +} + export async function transformMarkup( { content, filename }: { content: string; filename: string }, transformer: Preprocessor | Transformer, @@ -9,35 +39,29 @@ export async function transformMarkup( markupTagName = markupTagName.toLocaleLowerCase(); - const markupPattern = new RegExp( - `/|<${markupTagName}(\\s[^]*?)?(?:>([^]*?)<\\/${markupTagName}>|\\/>)`, - ); + const markupPattern = createTagRegex(markupTagName); const templateMatch = content.match(markupPattern); /** If no