|
|
@ -1,25 +1,25 @@
|
|
|
|
import { SourceMap } from 'magic-string';
|
|
|
|
import { SourceMap } from 'magic-string';
|
|
|
|
import replaceAsync from '../utils/replaceAsync';
|
|
|
|
import replaceAsync from '../utils/replaceAsync';
|
|
|
|
|
|
|
|
|
|
|
|
export interface PreprocessOptions {
|
|
|
|
export interface PreprocessorGroup {
|
|
|
|
markup?: (options: {
|
|
|
|
markup?: (options: {
|
|
|
|
content: string,
|
|
|
|
content: string,
|
|
|
|
filename: string
|
|
|
|
filename: string
|
|
|
|
}) => { code: string, map?: SourceMap | string };
|
|
|
|
}) => { code: string, map?: SourceMap | string, dependencies?: string[] };
|
|
|
|
style?: Preprocessor;
|
|
|
|
style?: Preprocessor;
|
|
|
|
script?: Preprocessor;
|
|
|
|
script?: Preprocessor;
|
|
|
|
filename?: string
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export type Preprocessor = (options: {
|
|
|
|
export type Preprocessor = (options: {
|
|
|
|
content: string,
|
|
|
|
content: string,
|
|
|
|
attributes: Record<string, string | boolean>,
|
|
|
|
attributes: Record<string, string | boolean>,
|
|
|
|
filename?: string
|
|
|
|
filename?: string
|
|
|
|
}) => { code: string, map?: SourceMap | string };
|
|
|
|
}) => { code: string, map?: SourceMap | string, dependencies?: string[] };
|
|
|
|
|
|
|
|
|
|
|
|
interface Processed {
|
|
|
|
interface Processed {
|
|
|
|
code: string;
|
|
|
|
code: string;
|
|
|
|
map?: SourceMap | string;
|
|
|
|
map?: SourceMap | string;
|
|
|
|
|
|
|
|
dependencies?: string[];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function parseAttributeValue(value: string) {
|
|
|
|
function parseAttributeValue(value: string) {
|
|
|
@ -39,28 +39,55 @@ function parseAttributes(str: string) {
|
|
|
|
|
|
|
|
|
|
|
|
export default async function preprocess(
|
|
|
|
export default async function preprocess(
|
|
|
|
source: string,
|
|
|
|
source: string,
|
|
|
|
options: PreprocessOptions
|
|
|
|
preprocessor: PreprocessorGroup | PreprocessorGroup[],
|
|
|
|
|
|
|
|
options?: { filename?: string }
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
if (options.markup) {
|
|
|
|
const filename = (options && options.filename) || preprocessor.filename; // legacy
|
|
|
|
const processed: Processed = await options.markup({
|
|
|
|
const dependencies = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const preprocessors = Array.isArray(preprocessor) ? preprocessor : [preprocessor];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const markup = preprocessors.map(p => p.markup).filter(Boolean);
|
|
|
|
|
|
|
|
const script = preprocessors.map(p => p.script).filter(Boolean);
|
|
|
|
|
|
|
|
const style = preprocessors.map(p => p.style).filter(Boolean);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const fn of markup) {
|
|
|
|
|
|
|
|
const processed: Processed = await fn({
|
|
|
|
content: source,
|
|
|
|
content: source,
|
|
|
|
filename: options.filename,
|
|
|
|
filename
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
if (processed && processed.dependencies) dependencies.push(...processed.dependencies);
|
|
|
|
source = processed ? processed.code : source;
|
|
|
|
source = processed ? processed.code : source;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (options.style || options.script) {
|
|
|
|
|
|
|
|
|
|
|
|
for (const fn of script) {
|
|
|
|
|
|
|
|
source = await replaceAsync(
|
|
|
|
|
|
|
|
source,
|
|
|
|
|
|
|
|
/<script([^]*?)>([^]*?)<\/script>/gi,
|
|
|
|
|
|
|
|
async (match, attributes, content) => {
|
|
|
|
|
|
|
|
const processed: Processed = await fn({
|
|
|
|
|
|
|
|
content,
|
|
|
|
|
|
|
|
attributes: parseAttributes(attributes),
|
|
|
|
|
|
|
|
filename
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
if (processed && processed.dependencies) dependencies.push(...processed.dependencies);
|
|
|
|
|
|
|
|
return processed ? `<script${attributes}>${processed.code}</script>` : match;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const fn of style) {
|
|
|
|
source = await replaceAsync(
|
|
|
|
source = await replaceAsync(
|
|
|
|
source,
|
|
|
|
source,
|
|
|
|
/<(script|style)([^]*?)>([^]*?)<\/\1>/gi,
|
|
|
|
/<style([^]*?)>([^]*?)<\/style>/gi,
|
|
|
|
async (match, type, attributes, content) => {
|
|
|
|
async (match, attributes, content) => {
|
|
|
|
const processed: Processed =
|
|
|
|
const processed: Processed = await fn({
|
|
|
|
type in options &&
|
|
|
|
|
|
|
|
(await options[type]({
|
|
|
|
|
|
|
|
content,
|
|
|
|
content,
|
|
|
|
attributes: parseAttributes(attributes),
|
|
|
|
attributes: parseAttributes(attributes),
|
|
|
|
filename: options.filename,
|
|
|
|
filename
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
return processed ? `<${type}${attributes}>${processed.code}</${type}>` : match;
|
|
|
|
if (processed && processed.dependencies) dependencies.push(...processed.dependencies);
|
|
|
|
|
|
|
|
return processed ? `<style${attributes}>${processed.code}</style>` : match;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -71,6 +98,9 @@ export default async function preprocess(
|
|
|
|
// script { code: scriptCode, map: scriptMap },
|
|
|
|
// script { code: scriptCode, map: scriptMap },
|
|
|
|
// markup { code: markupCode, map: markupMap },
|
|
|
|
// markup { code: markupCode, map: markupMap },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
code: source,
|
|
|
|
|
|
|
|
dependencies: [...new Set(dependencies)],
|
|
|
|
|
|
|
|
|
|
|
|
toString() {
|
|
|
|
toString() {
|
|
|
|
return source;
|
|
|
|
return source;
|
|
|
|
}
|
|
|
|
}
|
|
|
|