🚀 Big News:Socket Has Acquired Secure Annex.Learn More
Socket
Book a DemoSign in
Socket

vite-plugin-css-url

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vite-plugin-css-url - npm Package Compare versions

Comparing version
0.1.0
to
0.1.1
+212
src/index.ts
import type { ModuleNode, Plugin, ResolvedConfig } from "vite";
import path from "path";
const PLUGIN_NAME = 'vite-plugin-css-url';
function makeUrlParamRE(text: string): RegExp {
return new RegExp(`(\\?|&)${text}(?:&|$)`);
}
const urlParamRE = makeUrlParamRE('url')
const pluginNameRE = makeUrlParamRE(PLUGIN_NAME);
const directRE = makeUrlParamRE('direct')
const postfixRE = /[?#].*$/s
const stripCssExtRE = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/
const cssLangsRE = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/
function ViteCssUrlPlugin(): Plugin {
let config: ResolvedConfig | undefined
function relativeId(id: string): string {
return id.startsWith(config!.root)
? '/' + path.posix.relative(config!.root, id)
: id;
}
return {
name: PLUGIN_NAME,
enforce: 'pre',
configResolved(resolved) {
config = resolved;
},
async resolveId(source, importer, options) {
if (!urlParamRE.test(source)) // ignore imports without ?url
return;
if (!cssLangsRE.test(source)) // ignore non-css imports
return;
const target = removeQueryParams(source, 'url');
const resolution = await this.resolve(target, importer, options);
if (!resolution || resolution.external)
return;
let resolvedId = appendQueryParams(
mapQueryUrl(resolution.id, url => url + '.js'),
PLUGIN_NAME,
);
return {
id: resolvedId,
resolvedBy: PLUGIN_NAME,
moduleSideEffects: false,
}
},
async load(id) {
if (id.startsWith('\0')) // rollup convention
return;
if (!pluginNameRE.test(id))
return;
id = removeQueryParams(id, PLUGIN_NAME);
const targetId = mapQueryUrl(id, url => stripSuffix(url, '.js'));
const relativeTarget = relativeId(targetId);
if (config.command === "serve") {
// In serve mode we just return `<id>?direct` and use the `t=...`
// parameter to ensure the response is not cached.
//
// handleHotUpdate takes care of propagating HMR updates from
// the target module to this one.
let targetUrl = appendQueryParams(relativeTarget, 'direct', `t=${Date.now()}`);
return `export default ${JSON.stringify(targetUrl)};`;
} else {
// In build mode things are a little bit simpler:
// - We run the whole pipeline for <url>?inline and get the
// resulting code.
// - We take that code, extract the CSS string, stick it in a
// new asset file, and emit it.
// - Finally, we emit a rollup constant that evaluates to a URL
// to the asset from step 2.
const targetUrl = appendQueryParams(targetId, 'inline');
const target = await this.load({ id: targetUrl });
let assetName = path.basename(cleanUrl(targetId))
// Canonicalize various css extensions down to '.css'
assetName = assetName.replace(stripCssExtRE, '.css')
const content = JSON.parse(target.code.substring("export default ".length));
const referenceId = this.emitFile({
type: 'asset',
name: assetName,
source: content,
needsCodeReference: true
});
return `export default import.meta.ROLLUP_FILE_URL_${referenceId}`
}
},
/**
* Manually propagate HMR updates from `<file.css>?direct` modules to
* the compiled `<file.css.js>?url` files.
*
* The problem we have with this extension is that `file.css.js?url`
* has a HMR dependency on `file.css?direct` but rollup doesn't know
* about this dependency. We resolve this by manually scanning for
* the relevant dependency whenever we get a HMR update.
*/
async handleHotUpdate(ctx) {
const moduleGraph = ctx.server.moduleGraph;
const seen = new Set();
const stack: ModuleNode[] = [];
for (const module of ctx.modules) {
if (module.id) {
stack.push(module);
seen.add(module.id || module.file);
continue;
}
for (const file of moduleGraph.getModulesByFile(module.file)) {
stack.push(file);
seen.add(file.id || file.file);
}
}
while (stack.length !== 0) {
let module = stack.pop();
console.log(`[module id] ${module.id}`)
// Whenever we get a ?direct module check to see if there is a
// corresponding ?url module. If so, tell the dev server to
// reload the ?url module.
if (directRE.test(module.id)) {
const strippedId = removeQueryParams(module.id, 'direct');
const jsId = mapQueryUrl(strippedId, url => url + '.js');
const targetId = appendQueryParams(jsId, PLUGIN_NAME);
const targetModule = moduleGraph.getModuleById(targetId);
if (targetModule) {
ctx.server.reloadModule(targetModule);
}
}
// Don't propagate through self-accepting modules.
//
// ?direct modules are considered to be self-accepting so we
// need to propagate through them manually.
if (module.isSelfAccepting)
continue;
for (const importer of module.importers) {
if (seen.has(importer.id))
continue;
seen.add(importer.id || importer.file);
stack.push(importer);
}
}
},
};
}
export default ViteCssUrlPlugin;
function cleanUrl(url: string): string {
return url.replace(postfixRE, '')
}
function appendQueryParams(url: string, ...params: string[]): string {
if (params.length === 0)
return url;
let separator = url.includes('?') ? '&' : '?';
let query = params.join('&');
return `${url}${separator}${query}`;
}
function extractQueryParams(url: string): string[] {
let query = url.split('?', 2)[1];
if (!query)
return [];
return query.split('&');
}
function removeQueryParams(url: string, ...params: string[]): string {
let filtered = extractQueryParams(url).filter(p => !params.includes(p));
return appendQueryParams(cleanUrl(url), ...filtered);
}
function mapQueryUrl(url: string, func: (url: string) => string): string {
let [baseurl, query] = url.split('?', 2);
let params = query ? query.split('&') : [];
return appendQueryParams(func(baseurl), ...params);
}
function stripSuffix(str: string, pattern: string): string {
if (str.endsWith(pattern))
return str.substring(0, str.length - pattern.length);
return str;
}
+0
-2

@@ -115,3 +115,2 @@ var __create = Object.create;

const stack = [];
console.dir(ctx);
for (const module2 of ctx.modules) {

@@ -128,3 +127,2 @@ if (module2.id) {

}
console.dir(stack);
while (stack.length !== 0) {

@@ -131,0 +129,0 @@ let module2 = stack.pop();

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { ModuleNode, Plugin, ResolvedConfig } from \"vite\";\nimport path from \"path\";\n\nconst PLUGIN_NAME = 'vite-plugin-css-url';\n\nfunction makeUrlParamRE(text: string): RegExp {\n return new RegExp(`(\\\\?|&)${text}(?:&|$)`);\n}\n\nconst urlParamRE = makeUrlParamRE('url')\nconst pluginNameRE = makeUrlParamRE(PLUGIN_NAME);\nconst directRE = makeUrlParamRE('direct')\nconst postfixRE = /[?#].*$/s\nconst stripCssExtRE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/\nconst cssLangsRE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/\n\nfunction ViteCssUrlPlugin(): Plugin {\n let config: ResolvedConfig | undefined\n\n function relativeId(id: string): string {\n return id.startsWith(config!.root)\n ? '/' + path.posix.relative(config!.root, id)\n : id;\n }\n\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolved) {\n config = resolved;\n },\n\n async resolveId(source, importer, options) {\n if (!urlParamRE.test(source)) // ignore imports without ?url\n return;\n if (!cssLangsRE.test(source)) // ignore non-css imports\n return;\n\n const target = removeQueryParams(source, 'url');\n const resolution = await this.resolve(target, importer, options);\n\n if (!resolution || resolution.external)\n return;\n\n let resolvedId = appendQueryParams(\n mapQueryUrl(resolution.id, url => url + '.js'),\n PLUGIN_NAME,\n );\n\n return {\n id: resolvedId,\n resolvedBy: PLUGIN_NAME,\n moduleSideEffects: false,\n }\n },\n\n async load(id) {\n if (id.startsWith('\\0')) // rollup convention\n return;\n if (!pluginNameRE.test(id))\n return;\n\n id = removeQueryParams(id, PLUGIN_NAME);\n\n const targetId = mapQueryUrl(id, url => stripSuffix(url, '.js'));\n const relativeTarget = relativeId(targetId);\n\n if (config.command === \"serve\") {\n // In serve mode we just return `<id>?direct` and use the `t=...`\n // parameter to ensure the response is not cached.\n //\n // handleHotUpdate takes care of propagating HMR updates from\n // the target module to this one.\n\n let targetUrl = appendQueryParams(relativeTarget, 'direct', `t=${Date.now()}`);\n return `export default ${JSON.stringify(targetUrl)};`;\n } else {\n // In build mode things are a little bit simpler:\n // - We run the whole pipeline for <url>?inline and get the\n // resulting code.\n // - We take that code, extract the CSS string, stick it in a\n // new asset file, and emit it.\n // - Finally, we emit a rollup constant that evaluates to a URL\n // to the asset from step 2.\n\n const targetUrl = appendQueryParams(targetId, 'inline');\n const target = await this.load({ id: targetUrl });\n\n let assetName = path.basename(cleanUrl(targetId))\n\n // Canonicalize various css extensions down to '.css'\n assetName = assetName.replace(stripCssExtRE, '.css')\n\n const content = JSON.parse(target.code.substring(\"export default \".length));\n const referenceId = this.emitFile({\n type: 'asset',\n name: assetName,\n source: content,\n needsCodeReference: true\n });\n\n return `export default import.meta.ROLLUP_FILE_URL_${referenceId}`\n }\n },\n\n /**\n * Manually propagate HMR updates from `<file.css>?direct` modules to\n * the compiled `<file.css.js>?url` files.\n * \n * The problem we have with this extension is that `file.css.js?url`\n * has a HMR dependency on `file.css?direct` but rollup doesn't know\n * about this dependency. We resolve this by manually scanning for\n * the relevant dependency whenever we get a HMR update.\n */\n async handleHotUpdate(ctx) {\n const moduleGraph = ctx.server.moduleGraph;\n const seen = new Set();\n const stack: ModuleNode[] = [];\n\n console.dir(ctx);\n\n for (const module of ctx.modules) {\n if (module.id) {\n stack.push(module);\n seen.add(module.id || module.file);\n continue;\n }\n\n for (const file of moduleGraph.getModulesByFile(module.file)) {\n stack.push(file);\n seen.add(file.id || file.file);\n }\n }\n\n console.dir(stack);\n\n while (stack.length !== 0) {\n let module = stack.pop();\n\n console.log(`[module id] ${module.id}`)\n\n // Whenever we get a ?direct module check to see if there is a\n // corresponding ?url module. If so, tell the dev server to\n // reload the ?url module.\n if (directRE.test(module.id)) {\n const strippedId = removeQueryParams(module.id, 'direct');\n const jsId = mapQueryUrl(strippedId, url => url + '.js');\n const targetId = appendQueryParams(jsId, PLUGIN_NAME);\n\n const targetModule = moduleGraph.getModuleById(targetId);\n if (targetModule) {\n ctx.server.reloadModule(targetModule);\n }\n }\n\n // Don't propagate through self-accepting modules.\n //\n // ?direct modules are considered to be self-accepting so we\n // need to propagate through them manually.\n if (module.isSelfAccepting)\n continue;\n\n for (const importer of module.importers) {\n if (seen.has(importer.id))\n continue;\n\n seen.add(importer.id || importer.file);\n stack.push(importer);\n }\n }\n },\n };\n}\n\nexport default ViteCssUrlPlugin;\n\nfunction cleanUrl(url: string): string {\n return url.replace(postfixRE, '')\n}\n\nfunction appendQueryParams(url: string, ...params: string[]): string {\n if (params.length === 0)\n return url;\n\n let separator = url.includes('?') ? '&' : '?';\n let query = params.join('&');\n\n return `${url}${separator}${query}`;\n}\n\nfunction extractQueryParams(url: string): string[] {\n let query = url.split('?', 2)[1];\n\n if (!query)\n return [];\n return query.split('&');\n}\n\nfunction removeQueryParams(url: string, ...params: string[]): string {\n let filtered = extractQueryParams(url).filter(p => !params.includes(p));\n return appendQueryParams(cleanUrl(url), ...filtered);\n}\n\nfunction mapQueryUrl(url: string, func: (url: string) => string): string {\n let [baseurl, query] = url.split('?', 2);\n let params = query ? query.split('&') : [];\n\n return appendQueryParams(func(baseurl), ...params);\n}\n\nfunction stripSuffix(str: string, pattern: string): string {\n if (str.endsWith(pattern))\n return str.substring(0, str.length - pattern.length);\n return str;\n}\n"],"mappings":"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","names":["path","module"]}
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { ModuleNode, Plugin, ResolvedConfig } from \"vite\";\nimport path from \"path\";\n\nconst PLUGIN_NAME = 'vite-plugin-css-url';\n\nfunction makeUrlParamRE(text: string): RegExp {\n return new RegExp(`(\\\\?|&)${text}(?:&|$)`);\n}\n\nconst urlParamRE = makeUrlParamRE('url')\nconst pluginNameRE = makeUrlParamRE(PLUGIN_NAME);\nconst directRE = makeUrlParamRE('direct')\nconst postfixRE = /[?#].*$/s\nconst stripCssExtRE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/\nconst cssLangsRE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/\n\nfunction ViteCssUrlPlugin(): Plugin {\n let config: ResolvedConfig | undefined\n\n function relativeId(id: string): string {\n return id.startsWith(config!.root)\n ? '/' + path.posix.relative(config!.root, id)\n : id;\n }\n\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolved) {\n config = resolved;\n },\n\n async resolveId(source, importer, options) {\n if (!urlParamRE.test(source)) // ignore imports without ?url\n return;\n if (!cssLangsRE.test(source)) // ignore non-css imports\n return;\n\n const target = removeQueryParams(source, 'url');\n const resolution = await this.resolve(target, importer, options);\n\n if (!resolution || resolution.external)\n return;\n\n let resolvedId = appendQueryParams(\n mapQueryUrl(resolution.id, url => url + '.js'),\n PLUGIN_NAME,\n );\n\n return {\n id: resolvedId,\n resolvedBy: PLUGIN_NAME,\n moduleSideEffects: false,\n }\n },\n\n async load(id) {\n if (id.startsWith('\\0')) // rollup convention\n return;\n if (!pluginNameRE.test(id))\n return;\n\n id = removeQueryParams(id, PLUGIN_NAME);\n\n const targetId = mapQueryUrl(id, url => stripSuffix(url, '.js'));\n const relativeTarget = relativeId(targetId);\n\n if (config.command === \"serve\") {\n // In serve mode we just return `<id>?direct` and use the `t=...`\n // parameter to ensure the response is not cached.\n //\n // handleHotUpdate takes care of propagating HMR updates from\n // the target module to this one.\n\n let targetUrl = appendQueryParams(relativeTarget, 'direct', `t=${Date.now()}`);\n return `export default ${JSON.stringify(targetUrl)};`;\n } else {\n // In build mode things are a little bit simpler:\n // - We run the whole pipeline for <url>?inline and get the\n // resulting code.\n // - We take that code, extract the CSS string, stick it in a\n // new asset file, and emit it.\n // - Finally, we emit a rollup constant that evaluates to a URL\n // to the asset from step 2.\n\n const targetUrl = appendQueryParams(targetId, 'inline');\n const target = await this.load({ id: targetUrl });\n\n let assetName = path.basename(cleanUrl(targetId))\n\n // Canonicalize various css extensions down to '.css'\n assetName = assetName.replace(stripCssExtRE, '.css')\n\n const content = JSON.parse(target.code.substring(\"export default \".length));\n const referenceId = this.emitFile({\n type: 'asset',\n name: assetName,\n source: content,\n needsCodeReference: true\n });\n\n return `export default import.meta.ROLLUP_FILE_URL_${referenceId}`\n }\n },\n\n /**\n * Manually propagate HMR updates from `<file.css>?direct` modules to\n * the compiled `<file.css.js>?url` files.\n * \n * The problem we have with this extension is that `file.css.js?url`\n * has a HMR dependency on `file.css?direct` but rollup doesn't know\n * about this dependency. We resolve this by manually scanning for\n * the relevant dependency whenever we get a HMR update.\n */\n async handleHotUpdate(ctx) {\n const moduleGraph = ctx.server.moduleGraph;\n const seen = new Set();\n const stack: ModuleNode[] = [];\n\n for (const module of ctx.modules) {\n if (module.id) {\n stack.push(module);\n seen.add(module.id || module.file);\n continue;\n }\n\n for (const file of moduleGraph.getModulesByFile(module.file)) {\n stack.push(file);\n seen.add(file.id || file.file);\n }\n }\n\n while (stack.length !== 0) {\n let module = stack.pop();\n\n console.log(`[module id] ${module.id}`)\n\n // Whenever we get a ?direct module check to see if there is a\n // corresponding ?url module. If so, tell the dev server to\n // reload the ?url module.\n if (directRE.test(module.id)) {\n const strippedId = removeQueryParams(module.id, 'direct');\n const jsId = mapQueryUrl(strippedId, url => url + '.js');\n const targetId = appendQueryParams(jsId, PLUGIN_NAME);\n\n const targetModule = moduleGraph.getModuleById(targetId);\n if (targetModule) {\n ctx.server.reloadModule(targetModule);\n }\n }\n\n // Don't propagate through self-accepting modules.\n //\n // ?direct modules are considered to be self-accepting so we\n // need to propagate through them manually.\n if (module.isSelfAccepting)\n continue;\n\n for (const importer of module.importers) {\n if (seen.has(importer.id))\n continue;\n\n seen.add(importer.id || importer.file);\n stack.push(importer);\n }\n }\n },\n };\n}\n\nexport default ViteCssUrlPlugin;\n\nfunction cleanUrl(url: string): string {\n return url.replace(postfixRE, '')\n}\n\nfunction appendQueryParams(url: string, ...params: string[]): string {\n if (params.length === 0)\n return url;\n\n let separator = url.includes('?') ? '&' : '?';\n let query = params.join('&');\n\n return `${url}${separator}${query}`;\n}\n\nfunction extractQueryParams(url: string): string[] {\n let query = url.split('?', 2)[1];\n\n if (!query)\n return [];\n return query.split('&');\n}\n\nfunction removeQueryParams(url: string, ...params: string[]): string {\n let filtered = extractQueryParams(url).filter(p => !params.includes(p));\n return appendQueryParams(cleanUrl(url), ...filtered);\n}\n\nfunction mapQueryUrl(url: string, func: (url: string) => string): string {\n let [baseurl, query] = url.split('?', 2);\n let params = query ? query.split('&') : [];\n\n return appendQueryParams(func(baseurl), ...params);\n}\n\nfunction stripSuffix(str: string, pattern: string): string {\n if (str.endsWith(pattern))\n return str.substring(0, str.length - pattern.length);\n return str;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAiB;AAEjB,IAAM,cAAc;AAEpB,SAAS,eAAe,MAAsB;AAC1C,SAAO,IAAI,OAAO,UAAU,IAAI,SAAS;AAC7C;AAEA,IAAM,aAAa,eAAe,KAAK;AACvC,IAAM,eAAe,eAAe,WAAW;AAC/C,IAAM,WAAW,eAAe,QAAQ;AACxC,IAAM,YAAY;AAClB,IAAM,gBAAgB;AACtB,IAAM,aAAa;AAEnB,SAAS,mBAA2B;AAChC,MAAI;AAEJ,WAAS,WAAW,IAAoB;AACpC,WAAO,GAAG,WAAW,OAAQ,IAAI,IAC3B,MAAM,YAAAA,QAAK,MAAM,SAAS,OAAQ,MAAM,EAAE,IAC1C;AAAA,EACV;AAEA,SAAO;AAAA,IACH,MAAM;AAAA,IACN,SAAS;AAAA,IAET,eAAe,UAAU;AACrB,eAAS;AAAA,IACb;AAAA,IAEA,MAAM,UAAU,QAAQ,UAAU,SAAS;AACvC,UAAI,CAAC,WAAW,KAAK,MAAM;AACvB;AACJ,UAAI,CAAC,WAAW,KAAK,MAAM;AACvB;AAEJ,YAAM,SAAS,kBAAkB,QAAQ,KAAK;AAC9C,YAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,UAAU,OAAO;AAE/D,UAAI,CAAC,cAAc,WAAW;AAC1B;AAEJ,UAAI,aAAa;AAAA,QACb,YAAY,WAAW,IAAI,SAAO,MAAM,KAAK;AAAA,QAC7C;AAAA,MACJ;AAEA,aAAO;AAAA,QACH,IAAI;AAAA,QACJ,YAAY;AAAA,QACZ,mBAAmB;AAAA,MACvB;AAAA,IACJ;AAAA,IAEA,MAAM,KAAK,IAAI;AACX,UAAI,GAAG,WAAW,IAAI;AAClB;AACJ,UAAI,CAAC,aAAa,KAAK,EAAE;AACrB;AAEJ,WAAK,kBAAkB,IAAI,WAAW;AAEtC,YAAM,WAAW,YAAY,IAAI,SAAO,YAAY,KAAK,KAAK,CAAC;AAC/D,YAAM,iBAAiB,WAAW,QAAQ;AAE1C,UAAI,OAAO,YAAY,SAAS;AAO5B,YAAI,YAAY,kBAAkB,gBAAgB,UAAU,KAAK,KAAK,IAAI,CAAC,EAAE;AAC7E,eAAO,kBAAkB,KAAK,UAAU,SAAS,CAAC;AAAA,MACtD,OAAO;AASH,cAAM,YAAY,kBAAkB,UAAU,QAAQ;AACtD,cAAM,SAAS,MAAM,KAAK,KAAK,EAAE,IAAI,UAAU,CAAC;AAEhD,YAAI,YAAY,YAAAA,QAAK,SAAS,SAAS,QAAQ,CAAC;AAGhD,oBAAY,UAAU,QAAQ,eAAe,MAAM;AAEnD,cAAM,UAAU,KAAK,MAAM,OAAO,KAAK,UAAU,kBAAkB,MAAM,CAAC;AAC1E,cAAM,cAAc,KAAK,SAAS;AAAA,UAC9B,MAAM;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,oBAAoB;AAAA,QACxB,CAAC;AAED,eAAO,8CAA8C,WAAW;AAAA,MACpE;AAAA,IACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWA,MAAM,gBAAgB,KAAK;AACvB,YAAM,cAAc,IAAI,OAAO;AAC/B,YAAM,OAAO,oBAAI,IAAI;AACrB,YAAM,QAAsB,CAAC;AAE7B,iBAAWC,WAAU,IAAI,SAAS;AAC9B,YAAIA,QAAO,IAAI;AACX,gBAAM,KAAKA,OAAM;AACjB,eAAK,IAAIA,QAAO,MAAMA,QAAO,IAAI;AACjC;AAAA,QACJ;AAEA,mBAAW,QAAQ,YAAY,iBAAiBA,QAAO,IAAI,GAAG;AAC1D,gBAAM,KAAK,IAAI;AACf,eAAK,IAAI,KAAK,MAAM,KAAK,IAAI;AAAA,QACjC;AAAA,MACJ;AAEA,aAAO,MAAM,WAAW,GAAG;AACvB,YAAIA,UAAS,MAAM,IAAI;AAEvB,gBAAQ,IAAI,eAAeA,QAAO,EAAE,EAAE;AAKtC,YAAI,SAAS,KAAKA,QAAO,EAAE,GAAG;AAC1B,gBAAM,aAAa,kBAAkBA,QAAO,IAAI,QAAQ;AACxD,gBAAM,OAAO,YAAY,YAAY,SAAO,MAAM,KAAK;AACvD,gBAAM,WAAW,kBAAkB,MAAM,WAAW;AAEpD,gBAAM,eAAe,YAAY,cAAc,QAAQ;AACvD,cAAI,cAAc;AACd,gBAAI,OAAO,aAAa,YAAY;AAAA,UACxC;AAAA,QACJ;AAMA,YAAIA,QAAO;AACP;AAEJ,mBAAW,YAAYA,QAAO,WAAW;AACrC,cAAI,KAAK,IAAI,SAAS,EAAE;AACpB;AAEJ,eAAK,IAAI,SAAS,MAAM,SAAS,IAAI;AACrC,gBAAM,KAAK,QAAQ;AAAA,QACvB;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AACJ;AAEA,IAAO,cAAQ;AAEf,SAAS,SAAS,KAAqB;AACnC,SAAO,IAAI,QAAQ,WAAW,EAAE;AACpC;AAEA,SAAS,kBAAkB,QAAgB,QAA0B;AACjE,MAAI,OAAO,WAAW;AAClB,WAAO;AAEX,MAAI,YAAY,IAAI,SAAS,GAAG,IAAI,MAAM;AAC1C,MAAI,QAAQ,OAAO,KAAK,GAAG;AAE3B,SAAO,GAAG,GAAG,GAAG,SAAS,GAAG,KAAK;AACrC;AAEA,SAAS,mBAAmB,KAAuB;AAC/C,MAAI,QAAQ,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;AAE/B,MAAI,CAAC;AACD,WAAO,CAAC;AACZ,SAAO,MAAM,MAAM,GAAG;AAC1B;AAEA,SAAS,kBAAkB,QAAgB,QAA0B;AACjE,MAAI,WAAW,mBAAmB,GAAG,EAAE,OAAO,OAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AACtE,SAAO,kBAAkB,SAAS,GAAG,GAAG,GAAG,QAAQ;AACvD;AAEA,SAAS,YAAY,KAAa,MAAuC;AACrE,MAAI,CAAC,SAAS,KAAK,IAAI,IAAI,MAAM,KAAK,CAAC;AACvC,MAAI,SAAS,QAAQ,MAAM,MAAM,GAAG,IAAI,CAAC;AAEzC,SAAO,kBAAkB,KAAK,OAAO,GAAG,GAAG,MAAM;AACrD;AAEA,SAAS,YAAY,KAAa,SAAyB;AACvD,MAAI,IAAI,SAAS,OAAO;AACpB,WAAO,IAAI,UAAU,GAAG,IAAI,SAAS,QAAQ,MAAM;AACvD,SAAO;AACX;","names":["path","module"]}

@@ -82,3 +82,2 @@ // src/index.ts

const stack = [];
console.dir(ctx);
for (const module of ctx.modules) {

@@ -95,3 +94,2 @@ if (module.id) {

}
console.dir(stack);
while (stack.length !== 0) {

@@ -98,0 +96,0 @@ let module = stack.pop();

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { ModuleNode, Plugin, ResolvedConfig } from \"vite\";\nimport path from \"path\";\n\nconst PLUGIN_NAME = 'vite-plugin-css-url';\n\nfunction makeUrlParamRE(text: string): RegExp {\n return new RegExp(`(\\\\?|&)${text}(?:&|$)`);\n}\n\nconst urlParamRE = makeUrlParamRE('url')\nconst pluginNameRE = makeUrlParamRE(PLUGIN_NAME);\nconst directRE = makeUrlParamRE('direct')\nconst postfixRE = /[?#].*$/s\nconst stripCssExtRE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/\nconst cssLangsRE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/\n\nfunction ViteCssUrlPlugin(): Plugin {\n let config: ResolvedConfig | undefined\n\n function relativeId(id: string): string {\n return id.startsWith(config!.root)\n ? '/' + path.posix.relative(config!.root, id)\n : id;\n }\n\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolved) {\n config = resolved;\n },\n\n async resolveId(source, importer, options) {\n if (!urlParamRE.test(source)) // ignore imports without ?url\n return;\n if (!cssLangsRE.test(source)) // ignore non-css imports\n return;\n\n const target = removeQueryParams(source, 'url');\n const resolution = await this.resolve(target, importer, options);\n\n if (!resolution || resolution.external)\n return;\n\n let resolvedId = appendQueryParams(\n mapQueryUrl(resolution.id, url => url + '.js'),\n PLUGIN_NAME,\n );\n\n return {\n id: resolvedId,\n resolvedBy: PLUGIN_NAME,\n moduleSideEffects: false,\n }\n },\n\n async load(id) {\n if (id.startsWith('\\0')) // rollup convention\n return;\n if (!pluginNameRE.test(id))\n return;\n\n id = removeQueryParams(id, PLUGIN_NAME);\n\n const targetId = mapQueryUrl(id, url => stripSuffix(url, '.js'));\n const relativeTarget = relativeId(targetId);\n\n if (config.command === \"serve\") {\n // In serve mode we just return `<id>?direct` and use the `t=...`\n // parameter to ensure the response is not cached.\n //\n // handleHotUpdate takes care of propagating HMR updates from\n // the target module to this one.\n\n let targetUrl = appendQueryParams(relativeTarget, 'direct', `t=${Date.now()}`);\n return `export default ${JSON.stringify(targetUrl)};`;\n } else {\n // In build mode things are a little bit simpler:\n // - We run the whole pipeline for <url>?inline and get the\n // resulting code.\n // - We take that code, extract the CSS string, stick it in a\n // new asset file, and emit it.\n // - Finally, we emit a rollup constant that evaluates to a URL\n // to the asset from step 2.\n\n const targetUrl = appendQueryParams(targetId, 'inline');\n const target = await this.load({ id: targetUrl });\n\n let assetName = path.basename(cleanUrl(targetId))\n\n // Canonicalize various css extensions down to '.css'\n assetName = assetName.replace(stripCssExtRE, '.css')\n\n const content = JSON.parse(target.code.substring(\"export default \".length));\n const referenceId = this.emitFile({\n type: 'asset',\n name: assetName,\n source: content,\n needsCodeReference: true\n });\n\n return `export default import.meta.ROLLUP_FILE_URL_${referenceId}`\n }\n },\n\n /**\n * Manually propagate HMR updates from `<file.css>?direct` modules to\n * the compiled `<file.css.js>?url` files.\n * \n * The problem we have with this extension is that `file.css.js?url`\n * has a HMR dependency on `file.css?direct` but rollup doesn't know\n * about this dependency. We resolve this by manually scanning for\n * the relevant dependency whenever we get a HMR update.\n */\n async handleHotUpdate(ctx) {\n const moduleGraph = ctx.server.moduleGraph;\n const seen = new Set();\n const stack: ModuleNode[] = [];\n\n console.dir(ctx);\n\n for (const module of ctx.modules) {\n if (module.id) {\n stack.push(module);\n seen.add(module.id || module.file);\n continue;\n }\n\n for (const file of moduleGraph.getModulesByFile(module.file)) {\n stack.push(file);\n seen.add(file.id || file.file);\n }\n }\n\n console.dir(stack);\n\n while (stack.length !== 0) {\n let module = stack.pop();\n\n console.log(`[module id] ${module.id}`)\n\n // Whenever we get a ?direct module check to see if there is a\n // corresponding ?url module. If so, tell the dev server to\n // reload the ?url module.\n if (directRE.test(module.id)) {\n const strippedId = removeQueryParams(module.id, 'direct');\n const jsId = mapQueryUrl(strippedId, url => url + '.js');\n const targetId = appendQueryParams(jsId, PLUGIN_NAME);\n\n const targetModule = moduleGraph.getModuleById(targetId);\n if (targetModule) {\n ctx.server.reloadModule(targetModule);\n }\n }\n\n // Don't propagate through self-accepting modules.\n //\n // ?direct modules are considered to be self-accepting so we\n // need to propagate through them manually.\n if (module.isSelfAccepting)\n continue;\n\n for (const importer of module.importers) {\n if (seen.has(importer.id))\n continue;\n\n seen.add(importer.id || importer.file);\n stack.push(importer);\n }\n }\n },\n };\n}\n\nexport default ViteCssUrlPlugin;\n\nfunction cleanUrl(url: string): string {\n return url.replace(postfixRE, '')\n}\n\nfunction appendQueryParams(url: string, ...params: string[]): string {\n if (params.length === 0)\n return url;\n\n let separator = url.includes('?') ? '&' : '?';\n let query = params.join('&');\n\n return `${url}${separator}${query}`;\n}\n\nfunction extractQueryParams(url: string): string[] {\n let query = url.split('?', 2)[1];\n\n if (!query)\n return [];\n return query.split('&');\n}\n\nfunction removeQueryParams(url: string, ...params: string[]): string {\n let filtered = extractQueryParams(url).filter(p => !params.includes(p));\n return appendQueryParams(cleanUrl(url), ...filtered);\n}\n\nfunction mapQueryUrl(url: string, func: (url: string) => string): string {\n let [baseurl, query] = url.split('?', 2);\n let params = query ? query.split('&') : [];\n\n return appendQueryParams(func(baseurl), ...params);\n}\n\nfunction stripSuffix(str: string, pattern: string): string {\n if (str.endsWith(pattern))\n return str.substring(0, str.length - pattern.length);\n return str;\n}\n"],"mappings":"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","names":[]}
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { ModuleNode, Plugin, ResolvedConfig } from \"vite\";\nimport path from \"path\";\n\nconst PLUGIN_NAME = 'vite-plugin-css-url';\n\nfunction makeUrlParamRE(text: string): RegExp {\n return new RegExp(`(\\\\?|&)${text}(?:&|$)`);\n}\n\nconst urlParamRE = makeUrlParamRE('url')\nconst pluginNameRE = makeUrlParamRE(PLUGIN_NAME);\nconst directRE = makeUrlParamRE('direct')\nconst postfixRE = /[?#].*$/s\nconst stripCssExtRE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/\nconst cssLangsRE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/\n\nfunction ViteCssUrlPlugin(): Plugin {\n let config: ResolvedConfig | undefined\n\n function relativeId(id: string): string {\n return id.startsWith(config!.root)\n ? '/' + path.posix.relative(config!.root, id)\n : id;\n }\n\n return {\n name: PLUGIN_NAME,\n enforce: 'pre',\n\n configResolved(resolved) {\n config = resolved;\n },\n\n async resolveId(source, importer, options) {\n if (!urlParamRE.test(source)) // ignore imports without ?url\n return;\n if (!cssLangsRE.test(source)) // ignore non-css imports\n return;\n\n const target = removeQueryParams(source, 'url');\n const resolution = await this.resolve(target, importer, options);\n\n if (!resolution || resolution.external)\n return;\n\n let resolvedId = appendQueryParams(\n mapQueryUrl(resolution.id, url => url + '.js'),\n PLUGIN_NAME,\n );\n\n return {\n id: resolvedId,\n resolvedBy: PLUGIN_NAME,\n moduleSideEffects: false,\n }\n },\n\n async load(id) {\n if (id.startsWith('\\0')) // rollup convention\n return;\n if (!pluginNameRE.test(id))\n return;\n\n id = removeQueryParams(id, PLUGIN_NAME);\n\n const targetId = mapQueryUrl(id, url => stripSuffix(url, '.js'));\n const relativeTarget = relativeId(targetId);\n\n if (config.command === \"serve\") {\n // In serve mode we just return `<id>?direct` and use the `t=...`\n // parameter to ensure the response is not cached.\n //\n // handleHotUpdate takes care of propagating HMR updates from\n // the target module to this one.\n\n let targetUrl = appendQueryParams(relativeTarget, 'direct', `t=${Date.now()}`);\n return `export default ${JSON.stringify(targetUrl)};`;\n } else {\n // In build mode things are a little bit simpler:\n // - We run the whole pipeline for <url>?inline and get the\n // resulting code.\n // - We take that code, extract the CSS string, stick it in a\n // new asset file, and emit it.\n // - Finally, we emit a rollup constant that evaluates to a URL\n // to the asset from step 2.\n\n const targetUrl = appendQueryParams(targetId, 'inline');\n const target = await this.load({ id: targetUrl });\n\n let assetName = path.basename(cleanUrl(targetId))\n\n // Canonicalize various css extensions down to '.css'\n assetName = assetName.replace(stripCssExtRE, '.css')\n\n const content = JSON.parse(target.code.substring(\"export default \".length));\n const referenceId = this.emitFile({\n type: 'asset',\n name: assetName,\n source: content,\n needsCodeReference: true\n });\n\n return `export default import.meta.ROLLUP_FILE_URL_${referenceId}`\n }\n },\n\n /**\n * Manually propagate HMR updates from `<file.css>?direct` modules to\n * the compiled `<file.css.js>?url` files.\n * \n * The problem we have with this extension is that `file.css.js?url`\n * has a HMR dependency on `file.css?direct` but rollup doesn't know\n * about this dependency. We resolve this by manually scanning for\n * the relevant dependency whenever we get a HMR update.\n */\n async handleHotUpdate(ctx) {\n const moduleGraph = ctx.server.moduleGraph;\n const seen = new Set();\n const stack: ModuleNode[] = [];\n\n for (const module of ctx.modules) {\n if (module.id) {\n stack.push(module);\n seen.add(module.id || module.file);\n continue;\n }\n\n for (const file of moduleGraph.getModulesByFile(module.file)) {\n stack.push(file);\n seen.add(file.id || file.file);\n }\n }\n\n while (stack.length !== 0) {\n let module = stack.pop();\n\n console.log(`[module id] ${module.id}`)\n\n // Whenever we get a ?direct module check to see if there is a\n // corresponding ?url module. If so, tell the dev server to\n // reload the ?url module.\n if (directRE.test(module.id)) {\n const strippedId = removeQueryParams(module.id, 'direct');\n const jsId = mapQueryUrl(strippedId, url => url + '.js');\n const targetId = appendQueryParams(jsId, PLUGIN_NAME);\n\n const targetModule = moduleGraph.getModuleById(targetId);\n if (targetModule) {\n ctx.server.reloadModule(targetModule);\n }\n }\n\n // Don't propagate through self-accepting modules.\n //\n // ?direct modules are considered to be self-accepting so we\n // need to propagate through them manually.\n if (module.isSelfAccepting)\n continue;\n\n for (const importer of module.importers) {\n if (seen.has(importer.id))\n continue;\n\n seen.add(importer.id || importer.file);\n stack.push(importer);\n }\n }\n },\n };\n}\n\nexport default ViteCssUrlPlugin;\n\nfunction cleanUrl(url: string): string {\n return url.replace(postfixRE, '')\n}\n\nfunction appendQueryParams(url: string, ...params: string[]): string {\n if (params.length === 0)\n return url;\n\n let separator = url.includes('?') ? '&' : '?';\n let query = params.join('&');\n\n return `${url}${separator}${query}`;\n}\n\nfunction extractQueryParams(url: string): string[] {\n let query = url.split('?', 2)[1];\n\n if (!query)\n return [];\n return query.split('&');\n}\n\nfunction removeQueryParams(url: string, ...params: string[]): string {\n let filtered = extractQueryParams(url).filter(p => !params.includes(p));\n return appendQueryParams(cleanUrl(url), ...filtered);\n}\n\nfunction mapQueryUrl(url: string, func: (url: string) => string): string {\n let [baseurl, query] = url.split('?', 2);\n let params = query ? query.split('&') : [];\n\n return appendQueryParams(func(baseurl), ...params);\n}\n\nfunction stripSuffix(str: string, pattern: string): string {\n if (str.endsWith(pattern))\n return str.substring(0, str.length - pattern.length);\n return str;\n}\n"],"mappings":"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","names":[]}
{
"name": "vite-plugin-css-url",
"version": "0.1.0",
"version": "0.1.1",
"description": "Make ?url imports work for css in vite",

@@ -19,6 +19,6 @@ "license": "MIT",

"files": [
"/dist"
"/dist",
"/src"
],
"devDependencies": {
"@types/debug": "^4.1.9",
"@types/node": "^20.8.4",

@@ -25,0 +25,0 @@ "tsup": "^7.2.0",