vite-plugin-css-position 2.1.1-next.1 → 2.1.1-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ The plugin accepts optional configuration:
|
|
|
90
90
|
```typescript
|
|
91
91
|
viteCssPosition({
|
|
92
92
|
enableDev: true,
|
|
93
|
-
|
|
93
|
+
cssPerChunk: true,
|
|
94
94
|
});
|
|
95
95
|
```
|
|
96
96
|
|
|
@@ -98,12 +98,12 @@ viteCssPosition({
|
|
|
98
98
|
|
|
99
99
|
- **`instanceId`** - A custom identifier for the plugin instance. Useful when you have multiple instances or need to avoid conflicts. Defaults to a random UUID.
|
|
100
100
|
- **`enableDev`** - When `true`, enables CSS injection during development mode. Defaults to `false`. Enable this for HMR support
|
|
101
|
-
- **`
|
|
101
|
+
- **`cssPerChunk`** - When `true`, each chunk's CSS is injected relative to that chunk instead of being bundled into the entry. This enables **component-level granular lazy-loading**: a code-split component's styles are only injected at the `StylesTarget` position when the component is actually loaded. Defaults to `false` (all CSS is injected up front — the previous behavior, fully backward compatible). Requires `build.cssCodeSplit` (Vite's default; it is forced on when `cssPerChunk` is enabled).
|
|
102
102
|
- **`jsAssetsFilterFunction`** - Filter function `(chunk) => boolean` to control which JS output chunk(s) receive the CSS injection code. Useful with multiple entry points.
|
|
103
103
|
|
|
104
104
|
### Lazy-loading styles for code-split components
|
|
105
105
|
|
|
106
|
-
With `
|
|
106
|
+
With `cssPerChunk: true`, styles imported by a dynamically imported component are placed in that
|
|
107
107
|
component's own chunk. When the component is loaded, its CSS is injected at the `StylesTarget`
|
|
108
108
|
position — perfect for Shadow-DOM micro frontends that should not ship all CSS up front:
|
|
109
109
|
|
package/dist/index.d.ts
CHANGED
|
@@ -6,17 +6,17 @@ interface ViteCustomCssPositionOptions {
|
|
|
6
6
|
instanceId?: string;
|
|
7
7
|
enableDev?: boolean;
|
|
8
8
|
/**
|
|
9
|
-
* Inject each
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Inject each chunk's CSS relative to that chunk instead of bundling all CSS
|
|
10
|
+
* into the entry. Enables component-level granular lazy-loading of stylesheets:
|
|
11
|
+
* a code-split component's styles are only injected when the component (chunk)
|
|
12
|
+
* is actually loaded.
|
|
13
13
|
*
|
|
14
14
|
* `false` (default) keeps the previous behavior (all CSS in the entry, loaded
|
|
15
15
|
* up front) and is fully backward compatible.
|
|
16
16
|
*
|
|
17
17
|
* @default false
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
cssPerChunk?: boolean;
|
|
20
20
|
/**
|
|
21
21
|
* Filter function to determine which JS file(s) should receive the CSS injection code.
|
|
22
22
|
* Useful when building multiple entry points and you want CSS only in specific entries.
|
package/dist/index.js
CHANGED
|
@@ -5,5 +5,5 @@ import{hash as e,randomUUID as t}from"crypto";function n(e){return e.viteMetadat
|
|
|
5
5
|
}
|
|
6
6
|
})()`}const o={};function s(e,t){let n=e[t];if(n!==void 0&&n.source){let e=n.source;o[t]=e instanceof Uint8Array?new TextDecoder().decode(e):`${e}`}return o[t]??``}function c(e,t){return t.reduce((t,n)=>{let r=s(e,n);return delete e[n],t+r},``)}function l(e){return e.type==`chunk`&&e.fileName.match(/.[cm]?js(?:\?.+)?$/)!=null}function u(e){return e.isEntry&&!e.fileName.includes(`polyfill`)}function d(e,t){if(typeof t!=`function`){let t=Object.keys(e).filter(t=>{let n=e[t];return n!==void 0&&l(n)&&u(n)}),n=t[t.length-1];return n===void 0?[]:(t.length>1&&r(`[vite-plugin-css-position] identified "${n}" as one of multiple "entry" output files to put the CSS injection code. If this is not the intended file, use the "jsAssetsFilterFunction" option to specify the desired output file.`),[n])}return Object.entries(e).filter(([,e])=>l(e)&&t(e)).map(([e])=>e)}function f(e,t){let r={},i=d(e,typeof t==`function`?t:()=>!0);if(i.length===0)throw Error(`Unable to locate the JavaScript asset for adding the CSS injection code. It is recommended to review your configurations.`);for(let t of i){let i=e[t];if(i===void 0||i.type===`asset`)continue;let a=n(i);if(!a||a.size===0)continue;let o=r[t]||[];o.push(...a.values()),r[t]=o}return r}function p(e,t,n){let r=e.replace(/\/\*\s*empty css\s*\*\//g,``);return e=n?``:r,e+=t,e+=n?r:``,e}function m(e,t){for(let n in e){let r=e[n];if(r===void 0||r.type!==`chunk`)continue;let i=r.viteMetadata;i&&i.importedCss.size>0&&i.importedCss.forEach(e=>{t.includes(e)||(i.importedCss=new Set)})}}function h(e,t){let n=RegExp(`<link rel=".*"[^>]*?href=".*/?${t}"[^>]*?>`);return e.replace(n,``)}function g(e){return/\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/.test(e)}function _(e,t,n){for(let[r,i]of Object.entries(t)){let t=c(e,i),a=t.length>0?n(t):``,o=e[r];o.code=p(o.code,a,!0)}}const v=new Map;let y=``;function b(e,t,n,r){let i=d(e,r);if(i.length==0)throw Error(`Unable to locate the JavaScript asset for adding the CSS injection code. It is recommended to review your configurations.`);let a=c(e,t),o=a.length>0?n(a):``;for(let t of i){let n=e[t];n.facadeModuleId!=null&&n.isEntry&&o!=``&&(n.facadeModuleId!=y&&v.clear(),y=n.facadeModuleId,v.set(n.facadeModuleId,o)),o==``&&n.isEntry&&n.facadeModuleId!=null&&typeof v.get(n.facadeModuleId)==`string`&&(o=v.get(n.facadeModuleId)),n.code=p(n.code,o,!0)}}function x(e){let{globalVarName:t,eventName:n,relative:o,jsAssetsFilterFunction:s}=e,c,l=[{apply:`build`,enforce:`post`,name:`vite-plugin-css-position-injection`,config(e,t){t.command===`build`&&o&&(e.build??={},e.build.cssCodeSplit===!1&&r(`[vite-plugin-css-position] Override of 'build.cssCodeSplit' to true; it must be true when 'lazy' is enabled.`),e.build.cssCodeSplit=!0)},configResolved(e){c=e},generateBundle(e,a){if(c.build.ssr)return;let l=e=>i(t,n,JSON.stringify(e.trim())),u=Object.keys(a).filter(e=>{let t=a[e];return t!==void 0&&t.type==`asset`&&t.fileName.endsWith(`.css`)}),d=[];o?(_(a,f(a,s),l),d=u.filter(e=>!!a[e]),d.length>0&&r(`[vite-plugin-css-position] Some CSS assets were not included in any known JS: ${d.join(`,`)}`)):b(a,u,l,s),m(a,d);let p=Object.keys(a).filter(e=>e.endsWith(`.html`));for(let e of p){let t=a[e],n=t.source instanceof Uint8Array?new TextDecoder().decode(t.source):`${t.source}`;u.forEach(e=>{d.includes(e)||(n=h(n,e),t.source=n)})}}}];return e.enableDev&&(r(`[vite-plugin-css-position] Experimental dev mode activated!`),l.push({name:`vite-plugin-css-position-injection-dev`,apply:`serve`,enforce:`post`,transform(e,r){if(!g(r))return;let o=a(t,n,r),s=i(t,n,`__vite__css`,{type:`text/css`,"data-vite-dev-id":r}),c=e.replace(`__vite__updateStyle(__vite__id, __vite__css)`,`;
|
|
7
7
|
`+o+`;
|
|
8
|
-
`+s);return c=c.replace(`__vite__removeStyle(__vite__id)`,o),{code:c,map:null}}})),l}function S(e){let n=e?.instanceId||t().replace(/-/g,``),r=`
|
|
8
|
+
`+s);return c=c.replace(`__vite__removeStyle(__vite__id)`,o),{code:c,map:null}}})),l}function S(e){let n=e?.instanceId||t().replace(/-/g,``).slice(0,4),r=`__vcssp_c_${n}`,i=`__vcssp_e_${n}`;return[{name:`vite-plugin-custom-css-position`,config(e){return{...e,define:{...e.define,__VITE_CSS_POS_GLOBAL_VAR_NAME__:JSON.stringify(r),__VITE_CSS_POS_EVENT_NAME__:JSON.stringify(i)}}}},...x({globalVarName:r,eventName:i,enableDev:e?.enableDev??!1,relative:e?.cssPerChunk??!1,jsAssetsFilterFunction:e?.jsAssetsFilterFunction})]}export{S as viteCssPosition,S as viteReactCssPosition};
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["cssSourceCache: Record<string, string>","chunksWithCss: Record<string, string[]>","config: ResolvedConfig","plugins: Plugin[]","unusedCssAssets: string[]"],"sources":["../src/cssInjection.ts","../src/viteCustomCssPosition.ts"],"sourcesContent":["/**\n * CSS-by-JS injection core, vendored and trimmed from\n * `vite-plugin-css-injected-by-js` (v3.5.2) by Marco Prontera.\n *\n * Original: https://github.com/marco-prontera/vite-plugin-css-injected-by-js\n * Licensed under the MIT License — Copyright (c) 2023 Marco Prontera.\n *\n * This is a focused port: instead of creating `<style>` elements directly, the\n * generated injection code stores the CSS into a global Map and dispatches an\n * event, which the `StylesTarget` component reacts to in order to render the\n * styles at a custom position (e.g. inside a Shadow DOM). Unlike the original it\n * does NOT run a nested Vite build to produce the injection code; the snippet is\n * built directly and wrapped in an IIFE.\n */\nimport { hash } from \"crypto\";\nimport type { Plugin, ResolvedConfig, Rollup } from \"vite\";\n\nexport interface CssInjectionOptions {\n /** Name of the global variable holding the styles Map. */\n globalVarName: string;\n /** Name of the window event dispatched on style updates. */\n eventName: string;\n /** Enable the experimental dev-mode (HMR) transform. */\n enableDev: boolean;\n /**\n * Inject CSS relative to each JS chunk (incl. lazily loaded ones) instead of\n * concatenating everything into the entry chunk. Enables component-level\n * granular lazy-loading of stylesheets.\n */\n relative: boolean;\n /** Filter which JS chunks receive the CSS injection code. */\n jsAssetsFilterFunction?: ((chunk: Rollup.OutputChunk) => boolean) | undefined;\n}\n\n// CSS is injected before the rest of the chunk's code (parity with the original\n// plugin's default `topExecutionPriority: true`).\nconst TOP_EXECUTION_PRIORITY = true;\n\n// `viteMetadata.importedCss` is a Vite augmentation of Rollup's chunk type that\n// isn't surfaced through Vite's re-exported `Rollup` namespace; access it via a\n// local typed view.\ntype ChunkWithCssMeta = Rollup.OutputChunk & {\n viteMetadata?: { importedCss: Set<string> };\n};\n\nfunction importedCssOf(chunk: Rollup.OutputChunk): Set<string> | undefined {\n return (chunk as ChunkWithCssMeta).viteMetadata?.importedCss;\n}\n\nfunction warnLog(msg: string): void {\n console.warn(`\\x1b[33m \\n${msg} \\x1b[39m`);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Injection code generation */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Build the runtime snippet that registers the given CSS in the global Map and\n * notifies listeners. Wrapped in an IIFE so the local `const`s don't leak into\n * (or collide within) the chunk scope it is appended to.\n *\n * @param cssCodeExpr A JS expression evaluating to the CSS string. In build mode\n * this is a JSON string literal; in dev mode it's the `__vite__css` variable.\n * @param attributes Attributes to attach to the rendered `<style>` (dev only).\n */\nfunction buildInjectionCode(\n globalVarName: string,\n eventName: string,\n cssCodeExpr: string,\n attributes?: Record<string, string>\n): string {\n const attributesString = JSON.stringify(attributes || {});\n const id = `\"${\n attributes?.[\"data-vite-dev-id\"] ?? hash(\"sha1\", cssCodeExpr).substring(0, 12)\n }\"`;\n const body =\n `const css = ${cssCodeExpr};const id = ${id};const attributes = JSON.parse('${attributesString}');` +\n `window.${globalVarName} = window.${globalVarName} || new Map();` +\n `window.${globalVarName}.set(id, {css, attributes});` +\n `window.dispatchEvent( new Event('${eventName}') );`;\n return `(()=>{${body}})();`;\n}\n\n/** Code executed (dev mode) to remove a previously injected style on HMR update. */\nfunction buildRemoveStyleCode(globalVarName: string, eventName: string, id: string): string {\n return `(() => {\n if(window.${globalVarName} && window.${globalVarName}.has('${id}')) {\n window.${globalVarName}.delete('${id}');\n window.dispatchEvent( new Event('${eventName}') );\n }\n })()`;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Bundle helpers (ported from vite-plugin-css-injected-by-js utils) */\n/* -------------------------------------------------------------------------- */\n\n// The cache must be global since the execution context differs per entry.\nconst cssSourceCache: Record<string, string> = {};\n\nfunction extractCss(bundle: Rollup.OutputBundle, cssName: string): string {\n const cssAsset = bundle[cssName] as Rollup.OutputAsset | undefined;\n if (cssAsset !== undefined && cssAsset.source) {\n const cssSource = cssAsset.source;\n cssSourceCache[cssName] =\n cssSource instanceof Uint8Array ? new TextDecoder().decode(cssSource) : `${cssSource}`;\n }\n return cssSourceCache[cssName] ?? \"\";\n}\n\nfunction concatCssAndDeleteFromBundle(bundle: Rollup.OutputBundle, cssAssets: string[]): string {\n return cssAssets.reduce((previous, cssName) => {\n const cssSource = extractCss(bundle, cssName);\n delete bundle[cssName];\n return previous + cssSource;\n }, \"\");\n}\n\nfunction isJsOutputChunk(chunk: Rollup.OutputAsset | Rollup.OutputChunk): chunk is Rollup.OutputChunk {\n return chunk.type == \"chunk\" && chunk.fileName.match(/.[cm]?js(?:\\?.+)?$/) != null;\n}\n\nfunction defaultJsAssetsFilter(chunk: Rollup.OutputChunk): boolean {\n return chunk.isEntry && !chunk.fileName.includes(\"polyfill\");\n}\n\nfunction getJsTargetBundleKeys(\n bundle: Rollup.OutputBundle,\n jsAssetsFilterFunction?: (chunk: Rollup.OutputChunk) => boolean\n): string[] {\n if (typeof jsAssetsFilterFunction != \"function\") {\n const jsAssets = Object.keys(bundle).filter((i) => {\n const asset = bundle[i];\n return asset !== undefined && isJsOutputChunk(asset) && defaultJsAssetsFilter(asset);\n });\n const jsTargetFileName = jsAssets[jsAssets.length - 1];\n if (jsTargetFileName === undefined) {\n return [];\n }\n if (jsAssets.length > 1) {\n warnLog(\n `[vite-plugin-css-position] identified \"${jsTargetFileName}\" as one of multiple \"entry\" output files to put the CSS injection code. ` +\n 'If this is not the intended file, use the \"jsAssetsFilterFunction\" option to specify the desired output file.'\n );\n }\n return [jsTargetFileName];\n }\n return Object.entries(bundle)\n .filter(([, chunk]) => isJsOutputChunk(chunk) && jsAssetsFilterFunction(chunk))\n .map(([key]) => key);\n}\n\nfunction buildJsCssMap(\n bundle: Rollup.OutputBundle,\n jsAssetsFilterFunction?: (chunk: Rollup.OutputChunk) => boolean\n): Record<string, string[]> {\n const chunksWithCss: Record<string, string[]> = {};\n const bundleKeys = getJsTargetBundleKeys(\n bundle,\n typeof jsAssetsFilterFunction == \"function\" ? jsAssetsFilterFunction : () => true\n );\n if (bundleKeys.length === 0) {\n throw new Error(\n \"Unable to locate the JavaScript asset for adding the CSS injection code. It is recommended to review your configurations.\"\n );\n }\n for (const key of bundleKeys) {\n const chunk = bundle[key];\n if (chunk === undefined || chunk.type === \"asset\") {\n continue;\n }\n const importedCss = importedCssOf(chunk);\n if (!importedCss || importedCss.size === 0) {\n continue;\n }\n const chunkStyles = chunksWithCss[key] || [];\n chunkStyles.push(...importedCss.values());\n chunksWithCss[key] = chunkStyles;\n }\n return chunksWithCss;\n}\n\nfunction buildOutputChunkWithCssInjectionCode(\n jsAssetCode: string,\n cssInjectionCode: string,\n topExecutionPriorityFlag: boolean\n): string {\n const appCode = jsAssetCode.replace(/\\/\\*\\s*empty css\\s*\\*\\//g, \"\");\n jsAssetCode = topExecutionPriorityFlag ? \"\" : appCode;\n jsAssetCode += cssInjectionCode;\n jsAssetCode += !topExecutionPriorityFlag ? \"\" : appCode;\n return jsAssetCode;\n}\n\nfunction clearImportedCssViteMetadataFromBundle(\n bundle: Rollup.OutputBundle,\n unusedCssAssets: string[]\n): void {\n // Required to exclude removed files from manifest.json\n for (const key in bundle) {\n const chunk = bundle[key];\n if (chunk === undefined || chunk.type !== \"chunk\") {\n continue;\n }\n const meta = (chunk as ChunkWithCssMeta).viteMetadata;\n if (meta && meta.importedCss.size > 0) {\n meta.importedCss.forEach((importedCssFileName: string) => {\n if (!unusedCssAssets.includes(importedCssFileName)) {\n meta.importedCss = new Set();\n }\n });\n }\n }\n}\n\nfunction removeLinkStyleSheets(html: string, cssFileName: string): string {\n const removeCSS = new RegExp(`<link rel=\".*\"[^>]*?href=\".*/?${cssFileName}\"[^>]*?>`);\n return html.replace(removeCSS, \"\");\n}\n\nfunction isCSSRequest(request: string): boolean {\n const CSS_LANGS_RE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/;\n return CSS_LANGS_RE.test(request);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Injection modes */\n/* -------------------------------------------------------------------------- */\n\nfunction relativeCssInjection(\n bundle: Rollup.OutputBundle,\n assetsWithCss: Record<string, string[]>,\n makeInjection: (css: string) => string\n): void {\n for (const [jsAssetName, cssAssets] of Object.entries(assetsWithCss)) {\n const assetCss = concatCssAndDeleteFromBundle(bundle, cssAssets);\n const cssInjectionCode = assetCss.length > 0 ? makeInjection(assetCss) : \"\";\n const jsAsset = bundle[jsAssetName] as Rollup.OutputChunk;\n jsAsset.code = buildOutputChunkWithCssInjectionCode(\n jsAsset.code,\n cssInjectionCode,\n TOP_EXECUTION_PRIORITY\n );\n }\n}\n\n// Reuse CSS across sequential builds for the same entry (e.g. multiple formats).\nconst globalCSSCodeEntryCache = new Map<string, string>();\nlet previousFacadeModuleId = \"\";\n\nfunction globalCssInjection(\n bundle: Rollup.OutputBundle,\n cssAssets: string[],\n makeInjection: (css: string) => string,\n jsAssetsFilterFunction: ((chunk: Rollup.OutputChunk) => boolean) | undefined\n): void {\n const jsTargetBundleKeys = getJsTargetBundleKeys(bundle, jsAssetsFilterFunction);\n if (jsTargetBundleKeys.length == 0) {\n throw new Error(\n \"Unable to locate the JavaScript asset for adding the CSS injection code. It is recommended to review your configurations.\"\n );\n }\n const allCssCode = concatCssAndDeleteFromBundle(bundle, cssAssets);\n let cssInjectionCode = allCssCode.length > 0 ? makeInjection(allCssCode) : \"\";\n\n for (const jsTargetKey of jsTargetBundleKeys) {\n const jsAsset = bundle[jsTargetKey] as Rollup.OutputChunk;\n if (jsAsset.facadeModuleId != null && jsAsset.isEntry && cssInjectionCode != \"\") {\n if (jsAsset.facadeModuleId != previousFacadeModuleId) {\n globalCSSCodeEntryCache.clear();\n }\n previousFacadeModuleId = jsAsset.facadeModuleId;\n globalCSSCodeEntryCache.set(jsAsset.facadeModuleId, cssInjectionCode);\n }\n if (\n cssInjectionCode == \"\" &&\n jsAsset.isEntry &&\n jsAsset.facadeModuleId != null &&\n typeof globalCSSCodeEntryCache.get(jsAsset.facadeModuleId) == \"string\"\n ) {\n cssInjectionCode = globalCSSCodeEntryCache.get(jsAsset.facadeModuleId) as string;\n }\n jsAsset.code = buildOutputChunkWithCssInjectionCode(\n jsAsset.code,\n cssInjectionCode,\n TOP_EXECUTION_PRIORITY\n );\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Plugin factory */\n/* -------------------------------------------------------------------------- */\n\nexport function cssInjectionPlugins(options: CssInjectionOptions): Plugin[] {\n const { globalVarName, eventName, relative, jsAssetsFilterFunction } = options;\n let config: ResolvedConfig;\n\n const plugins: Plugin[] = [\n {\n apply: \"build\",\n enforce: \"post\",\n name: \"vite-plugin-css-position-injection\",\n config(c, env) {\n if (env.command === \"build\" && relative) {\n c.build ??= {};\n if (c.build.cssCodeSplit === false) {\n warnLog(\n \"[vite-plugin-css-position] Override of 'build.cssCodeSplit' to true; it must be true when 'lazy' is enabled.\"\n );\n }\n c.build.cssCodeSplit = true;\n }\n },\n configResolved(resolved) {\n config = resolved;\n },\n generateBundle(_opts, bundle) {\n if (config.build.ssr) {\n return;\n }\n const makeInjection = (css: string) =>\n buildInjectionCode(globalVarName, eventName, JSON.stringify(css.trim()));\n\n const cssAssets = Object.keys(bundle).filter((i) => {\n const asset = bundle[i];\n return asset !== undefined && asset.type == \"asset\" && asset.fileName.endsWith(\".css\");\n });\n let unusedCssAssets: string[] = [];\n\n if (relative) {\n const assetsWithCss = buildJsCssMap(bundle, jsAssetsFilterFunction);\n relativeCssInjection(bundle, assetsWithCss, makeInjection);\n unusedCssAssets = cssAssets.filter((cssAsset) => !!bundle[cssAsset]);\n if (unusedCssAssets.length > 0) {\n warnLog(\n `[vite-plugin-css-position] Some CSS assets were not included in any known JS: ${unusedCssAssets.join(\",\")}`\n );\n }\n } else {\n globalCssInjection(bundle, cssAssets, makeInjection, jsAssetsFilterFunction);\n }\n\n clearImportedCssViteMetadataFromBundle(bundle, unusedCssAssets);\n\n const htmlFiles = Object.keys(bundle).filter((i) => i.endsWith(\".html\"));\n for (const name of htmlFiles) {\n const htmlChunk = bundle[name] as Rollup.OutputAsset;\n let replacedHtml =\n htmlChunk.source instanceof Uint8Array\n ? new TextDecoder().decode(htmlChunk.source)\n : `${htmlChunk.source}`;\n cssAssets.forEach((cssName) => {\n if (!unusedCssAssets.includes(cssName)) {\n replacedHtml = removeLinkStyleSheets(replacedHtml, cssName);\n htmlChunk.source = replacedHtml;\n }\n });\n }\n },\n },\n ];\n\n if (options.enableDev) {\n warnLog(\"[vite-plugin-css-position] Experimental dev mode activated!\");\n plugins.push({\n name: \"vite-plugin-css-position-injection-dev\",\n apply: \"serve\",\n enforce: \"post\",\n transform(src, id) {\n if (!isCSSRequest(id)) {\n return;\n }\n const removeStyleCode = buildRemoveStyleCode(globalVarName, eventName, id);\n const injectCode = buildInjectionCode(globalVarName, eventName, \"__vite__css\", {\n type: \"text/css\",\n \"data-vite-dev-id\": id,\n });\n // removeStyleCode runs first since the inject snippet doesn't handle the\n // dev update case on its own.\n let injectionCode = src.replace(\n \"__vite__updateStyle(__vite__id, __vite__css)\",\n \";\\n\" + removeStyleCode + \";\\n\" + injectCode\n );\n injectionCode = injectionCode.replace(\"__vite__removeStyle(__vite__id)\", removeStyleCode);\n return { code: injectionCode, map: null };\n },\n });\n }\n\n return plugins;\n}\n","import type { Plugin, Rollup } from \"vite\";\nimport { randomUUID } from \"crypto\";\nimport { cssInjectionPlugins } from \"./cssInjection\";\n\ntype JsAssetsFilterFunction = (chunk: Rollup.OutputChunk) => boolean;\n\nexport interface ViteCustomCssPositionOptions {\n instanceId?: string;\n enableDev?: boolean;\n /**\n * Inject each (including lazily loaded) chunk's CSS relative to that chunk\n * instead of bundling all CSS into the entry. Enables component-level granular\n * lazy-loading of stylesheets: a code-split component's styles are only injected\n * when the component is actually loaded.\n *\n * `false` (default) keeps the previous behavior (all CSS in the entry, loaded\n * up front) and is fully backward compatible.\n *\n * @default false\n */\n lazy?: boolean;\n /**\n * Filter function to determine which JS file(s) should receive the CSS injection code.\n * Useful when building multiple entry points and you want CSS only in specific entries.\n * @param chunk - The output chunk being processed\n * @returns true if CSS should be injected into this chunk\n */\n jsAssetsFilterFunction?: JsAssetsFilterFunction;\n}\n\nexport default function viteCustomCssPosition(\n options?: ViteCustomCssPositionOptions\n): Plugin | Plugin[] {\n const instanceId = options?.instanceId || randomUUID().replace(/-/g, \"\");\n\n const globalVarName = `__vite_c_css_pos_initial_${instanceId}`;\n const eventName = `__vite_c_css_pos_update_${instanceId}`;\n\n const cssPlugins = cssInjectionPlugins({\n globalVarName,\n eventName,\n enableDev: options?.enableDev ?? false,\n relative: options?.lazy ?? false,\n jsAssetsFilterFunction: options?.jsAssetsFilterFunction,\n });\n\n return [\n {\n name: \"vite-plugin-custom-css-position\",\n config(c) {\n return {\n ...c,\n define: {\n ...c.define,\n __VITE_CSS_POS_GLOBAL_VAR_NAME__: JSON.stringify(globalVarName),\n __VITE_CSS_POS_EVENT_NAME__: JSON.stringify(eventName),\n },\n };\n },\n },\n ...cssPlugins,\n ];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["cssSourceCache: Record<string, string>","chunksWithCss: Record<string, string[]>","config: ResolvedConfig","plugins: Plugin[]","unusedCssAssets: string[]"],"sources":["../src/cssInjection.ts","../src/viteCustomCssPosition.ts"],"sourcesContent":["/**\n * CSS-by-JS injection core, vendored and trimmed from\n * `vite-plugin-css-injected-by-js` (v3.5.2) by Marco Prontera.\n *\n * Original: https://github.com/marco-prontera/vite-plugin-css-injected-by-js\n * Licensed under the MIT License — Copyright (c) 2023 Marco Prontera.\n *\n * This is a focused port: instead of creating `<style>` elements directly, the\n * generated injection code stores the CSS into a global Map and dispatches an\n * event, which the `StylesTarget` component reacts to in order to render the\n * styles at a custom position (e.g. inside a Shadow DOM). Unlike the original it\n * does NOT run a nested Vite build to produce the injection code; the snippet is\n * built directly and wrapped in an IIFE.\n */\nimport { hash } from \"crypto\";\nimport type { Plugin, ResolvedConfig, Rollup } from \"vite\";\n\nexport interface CssInjectionOptions {\n /** Name of the global variable holding the styles Map. */\n globalVarName: string;\n /** Name of the window event dispatched on style updates. */\n eventName: string;\n /** Enable the experimental dev-mode (HMR) transform. */\n enableDev: boolean;\n /**\n * Inject CSS relative to each JS chunk (incl. lazily loaded ones) instead of\n * concatenating everything into the entry chunk. Enables component-level\n * granular lazy-loading of stylesheets.\n */\n relative: boolean;\n /** Filter which JS chunks receive the CSS injection code. */\n jsAssetsFilterFunction?: ((chunk: Rollup.OutputChunk) => boolean) | undefined;\n}\n\n// CSS is injected before the rest of the chunk's code (parity with the original\n// plugin's default `topExecutionPriority: true`).\nconst TOP_EXECUTION_PRIORITY = true;\n\n// `viteMetadata.importedCss` is a Vite augmentation of Rollup's chunk type that\n// isn't surfaced through Vite's re-exported `Rollup` namespace; access it via a\n// local typed view.\ntype ChunkWithCssMeta = Rollup.OutputChunk & {\n viteMetadata?: { importedCss: Set<string> };\n};\n\nfunction importedCssOf(chunk: Rollup.OutputChunk): Set<string> | undefined {\n return (chunk as ChunkWithCssMeta).viteMetadata?.importedCss;\n}\n\nfunction warnLog(msg: string): void {\n console.warn(`\\x1b[33m \\n${msg} \\x1b[39m`);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Injection code generation */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Build the runtime snippet that registers the given CSS in the global Map and\n * notifies listeners. Wrapped in an IIFE so the local `const`s don't leak into\n * (or collide within) the chunk scope it is appended to.\n *\n * @param cssCodeExpr A JS expression evaluating to the CSS string. In build mode\n * this is a JSON string literal; in dev mode it's the `__vite__css` variable.\n * @param attributes Attributes to attach to the rendered `<style>` (dev only).\n */\nfunction buildInjectionCode(\n globalVarName: string,\n eventName: string,\n cssCodeExpr: string,\n attributes?: Record<string, string>\n): string {\n const attributesString = JSON.stringify(attributes || {});\n const id = `\"${\n attributes?.[\"data-vite-dev-id\"] ?? hash(\"sha1\", cssCodeExpr).substring(0, 12)\n }\"`;\n const body =\n `const css = ${cssCodeExpr};const id = ${id};const attributes = JSON.parse('${attributesString}');` +\n `window.${globalVarName} = window.${globalVarName} || new Map();` +\n `window.${globalVarName}.set(id, {css, attributes});` +\n `window.dispatchEvent( new Event('${eventName}') );`;\n return `(()=>{${body}})();`;\n}\n\n/** Code executed (dev mode) to remove a previously injected style on HMR update. */\nfunction buildRemoveStyleCode(globalVarName: string, eventName: string, id: string): string {\n return `(() => {\n if(window.${globalVarName} && window.${globalVarName}.has('${id}')) {\n window.${globalVarName}.delete('${id}');\n window.dispatchEvent( new Event('${eventName}') );\n }\n })()`;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Bundle helpers (ported from vite-plugin-css-injected-by-js utils) */\n/* -------------------------------------------------------------------------- */\n\n// The cache must be global since the execution context differs per entry.\nconst cssSourceCache: Record<string, string> = {};\n\nfunction extractCss(bundle: Rollup.OutputBundle, cssName: string): string {\n const cssAsset = bundle[cssName] as Rollup.OutputAsset | undefined;\n if (cssAsset !== undefined && cssAsset.source) {\n const cssSource = cssAsset.source;\n cssSourceCache[cssName] =\n cssSource instanceof Uint8Array ? new TextDecoder().decode(cssSource) : `${cssSource}`;\n }\n return cssSourceCache[cssName] ?? \"\";\n}\n\nfunction concatCssAndDeleteFromBundle(bundle: Rollup.OutputBundle, cssAssets: string[]): string {\n return cssAssets.reduce((previous, cssName) => {\n const cssSource = extractCss(bundle, cssName);\n delete bundle[cssName];\n return previous + cssSource;\n }, \"\");\n}\n\nfunction isJsOutputChunk(chunk: Rollup.OutputAsset | Rollup.OutputChunk): chunk is Rollup.OutputChunk {\n return chunk.type == \"chunk\" && chunk.fileName.match(/.[cm]?js(?:\\?.+)?$/) != null;\n}\n\nfunction defaultJsAssetsFilter(chunk: Rollup.OutputChunk): boolean {\n return chunk.isEntry && !chunk.fileName.includes(\"polyfill\");\n}\n\nfunction getJsTargetBundleKeys(\n bundle: Rollup.OutputBundle,\n jsAssetsFilterFunction?: (chunk: Rollup.OutputChunk) => boolean\n): string[] {\n if (typeof jsAssetsFilterFunction != \"function\") {\n const jsAssets = Object.keys(bundle).filter((i) => {\n const asset = bundle[i];\n return asset !== undefined && isJsOutputChunk(asset) && defaultJsAssetsFilter(asset);\n });\n const jsTargetFileName = jsAssets[jsAssets.length - 1];\n if (jsTargetFileName === undefined) {\n return [];\n }\n if (jsAssets.length > 1) {\n warnLog(\n `[vite-plugin-css-position] identified \"${jsTargetFileName}\" as one of multiple \"entry\" output files to put the CSS injection code. ` +\n 'If this is not the intended file, use the \"jsAssetsFilterFunction\" option to specify the desired output file.'\n );\n }\n return [jsTargetFileName];\n }\n return Object.entries(bundle)\n .filter(([, chunk]) => isJsOutputChunk(chunk) && jsAssetsFilterFunction(chunk))\n .map(([key]) => key);\n}\n\nfunction buildJsCssMap(\n bundle: Rollup.OutputBundle,\n jsAssetsFilterFunction?: (chunk: Rollup.OutputChunk) => boolean\n): Record<string, string[]> {\n const chunksWithCss: Record<string, string[]> = {};\n const bundleKeys = getJsTargetBundleKeys(\n bundle,\n typeof jsAssetsFilterFunction == \"function\" ? jsAssetsFilterFunction : () => true\n );\n if (bundleKeys.length === 0) {\n throw new Error(\n \"Unable to locate the JavaScript asset for adding the CSS injection code. It is recommended to review your configurations.\"\n );\n }\n for (const key of bundleKeys) {\n const chunk = bundle[key];\n if (chunk === undefined || chunk.type === \"asset\") {\n continue;\n }\n const importedCss = importedCssOf(chunk);\n if (!importedCss || importedCss.size === 0) {\n continue;\n }\n const chunkStyles = chunksWithCss[key] || [];\n chunkStyles.push(...importedCss.values());\n chunksWithCss[key] = chunkStyles;\n }\n return chunksWithCss;\n}\n\nfunction buildOutputChunkWithCssInjectionCode(\n jsAssetCode: string,\n cssInjectionCode: string,\n topExecutionPriorityFlag: boolean\n): string {\n const appCode = jsAssetCode.replace(/\\/\\*\\s*empty css\\s*\\*\\//g, \"\");\n jsAssetCode = topExecutionPriorityFlag ? \"\" : appCode;\n jsAssetCode += cssInjectionCode;\n jsAssetCode += !topExecutionPriorityFlag ? \"\" : appCode;\n return jsAssetCode;\n}\n\nfunction clearImportedCssViteMetadataFromBundle(\n bundle: Rollup.OutputBundle,\n unusedCssAssets: string[]\n): void {\n // Required to exclude removed files from manifest.json\n for (const key in bundle) {\n const chunk = bundle[key];\n if (chunk === undefined || chunk.type !== \"chunk\") {\n continue;\n }\n const meta = (chunk as ChunkWithCssMeta).viteMetadata;\n if (meta && meta.importedCss.size > 0) {\n meta.importedCss.forEach((importedCssFileName: string) => {\n if (!unusedCssAssets.includes(importedCssFileName)) {\n meta.importedCss = new Set();\n }\n });\n }\n }\n}\n\nfunction removeLinkStyleSheets(html: string, cssFileName: string): string {\n const removeCSS = new RegExp(`<link rel=\".*\"[^>]*?href=\".*/?${cssFileName}\"[^>]*?>`);\n return html.replace(removeCSS, \"\");\n}\n\nfunction isCSSRequest(request: string): boolean {\n const CSS_LANGS_RE = /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/;\n return CSS_LANGS_RE.test(request);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Injection modes */\n/* -------------------------------------------------------------------------- */\n\nfunction relativeCssInjection(\n bundle: Rollup.OutputBundle,\n assetsWithCss: Record<string, string[]>,\n makeInjection: (css: string) => string\n): void {\n for (const [jsAssetName, cssAssets] of Object.entries(assetsWithCss)) {\n const assetCss = concatCssAndDeleteFromBundle(bundle, cssAssets);\n const cssInjectionCode = assetCss.length > 0 ? makeInjection(assetCss) : \"\";\n const jsAsset = bundle[jsAssetName] as Rollup.OutputChunk;\n jsAsset.code = buildOutputChunkWithCssInjectionCode(\n jsAsset.code,\n cssInjectionCode,\n TOP_EXECUTION_PRIORITY\n );\n }\n}\n\n// Reuse CSS across sequential builds for the same entry (e.g. multiple formats).\nconst globalCSSCodeEntryCache = new Map<string, string>();\nlet previousFacadeModuleId = \"\";\n\nfunction globalCssInjection(\n bundle: Rollup.OutputBundle,\n cssAssets: string[],\n makeInjection: (css: string) => string,\n jsAssetsFilterFunction: ((chunk: Rollup.OutputChunk) => boolean) | undefined\n): void {\n const jsTargetBundleKeys = getJsTargetBundleKeys(bundle, jsAssetsFilterFunction);\n if (jsTargetBundleKeys.length == 0) {\n throw new Error(\n \"Unable to locate the JavaScript asset for adding the CSS injection code. It is recommended to review your configurations.\"\n );\n }\n const allCssCode = concatCssAndDeleteFromBundle(bundle, cssAssets);\n let cssInjectionCode = allCssCode.length > 0 ? makeInjection(allCssCode) : \"\";\n\n for (const jsTargetKey of jsTargetBundleKeys) {\n const jsAsset = bundle[jsTargetKey] as Rollup.OutputChunk;\n if (jsAsset.facadeModuleId != null && jsAsset.isEntry && cssInjectionCode != \"\") {\n if (jsAsset.facadeModuleId != previousFacadeModuleId) {\n globalCSSCodeEntryCache.clear();\n }\n previousFacadeModuleId = jsAsset.facadeModuleId;\n globalCSSCodeEntryCache.set(jsAsset.facadeModuleId, cssInjectionCode);\n }\n if (\n cssInjectionCode == \"\" &&\n jsAsset.isEntry &&\n jsAsset.facadeModuleId != null &&\n typeof globalCSSCodeEntryCache.get(jsAsset.facadeModuleId) == \"string\"\n ) {\n cssInjectionCode = globalCSSCodeEntryCache.get(jsAsset.facadeModuleId) as string;\n }\n jsAsset.code = buildOutputChunkWithCssInjectionCode(\n jsAsset.code,\n cssInjectionCode,\n TOP_EXECUTION_PRIORITY\n );\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Plugin factory */\n/* -------------------------------------------------------------------------- */\n\nexport function cssInjectionPlugins(options: CssInjectionOptions): Plugin[] {\n const { globalVarName, eventName, relative, jsAssetsFilterFunction } = options;\n let config: ResolvedConfig;\n\n const plugins: Plugin[] = [\n {\n apply: \"build\",\n enforce: \"post\",\n name: \"vite-plugin-css-position-injection\",\n config(c, env) {\n if (env.command === \"build\" && relative) {\n c.build ??= {};\n if (c.build.cssCodeSplit === false) {\n warnLog(\n \"[vite-plugin-css-position] Override of 'build.cssCodeSplit' to true; it must be true when 'lazy' is enabled.\"\n );\n }\n c.build.cssCodeSplit = true;\n }\n },\n configResolved(resolved) {\n config = resolved;\n },\n generateBundle(_opts, bundle) {\n if (config.build.ssr) {\n return;\n }\n const makeInjection = (css: string) =>\n buildInjectionCode(globalVarName, eventName, JSON.stringify(css.trim()));\n\n const cssAssets = Object.keys(bundle).filter((i) => {\n const asset = bundle[i];\n return asset !== undefined && asset.type == \"asset\" && asset.fileName.endsWith(\".css\");\n });\n let unusedCssAssets: string[] = [];\n\n if (relative) {\n const assetsWithCss = buildJsCssMap(bundle, jsAssetsFilterFunction);\n relativeCssInjection(bundle, assetsWithCss, makeInjection);\n unusedCssAssets = cssAssets.filter((cssAsset) => !!bundle[cssAsset]);\n if (unusedCssAssets.length > 0) {\n warnLog(\n `[vite-plugin-css-position] Some CSS assets were not included in any known JS: ${unusedCssAssets.join(\",\")}`\n );\n }\n } else {\n globalCssInjection(bundle, cssAssets, makeInjection, jsAssetsFilterFunction);\n }\n\n clearImportedCssViteMetadataFromBundle(bundle, unusedCssAssets);\n\n const htmlFiles = Object.keys(bundle).filter((i) => i.endsWith(\".html\"));\n for (const name of htmlFiles) {\n const htmlChunk = bundle[name] as Rollup.OutputAsset;\n let replacedHtml =\n htmlChunk.source instanceof Uint8Array\n ? new TextDecoder().decode(htmlChunk.source)\n : `${htmlChunk.source}`;\n cssAssets.forEach((cssName) => {\n if (!unusedCssAssets.includes(cssName)) {\n replacedHtml = removeLinkStyleSheets(replacedHtml, cssName);\n htmlChunk.source = replacedHtml;\n }\n });\n }\n },\n },\n ];\n\n if (options.enableDev) {\n warnLog(\"[vite-plugin-css-position] Experimental dev mode activated!\");\n plugins.push({\n name: \"vite-plugin-css-position-injection-dev\",\n apply: \"serve\",\n enforce: \"post\",\n transform(src, id) {\n if (!isCSSRequest(id)) {\n return;\n }\n const removeStyleCode = buildRemoveStyleCode(globalVarName, eventName, id);\n const injectCode = buildInjectionCode(globalVarName, eventName, \"__vite__css\", {\n type: \"text/css\",\n \"data-vite-dev-id\": id,\n });\n // removeStyleCode runs first since the inject snippet doesn't handle the\n // dev update case on its own.\n let injectionCode = src.replace(\n \"__vite__updateStyle(__vite__id, __vite__css)\",\n \";\\n\" + removeStyleCode + \";\\n\" + injectCode\n );\n injectionCode = injectionCode.replace(\"__vite__removeStyle(__vite__id)\", removeStyleCode);\n return { code: injectionCode, map: null };\n },\n });\n }\n\n return plugins;\n}\n","import type { Plugin, Rollup } from \"vite\";\nimport { randomUUID } from \"crypto\";\nimport { cssInjectionPlugins } from \"./cssInjection\";\n\ntype JsAssetsFilterFunction = (chunk: Rollup.OutputChunk) => boolean;\n\nexport interface ViteCustomCssPositionOptions {\n instanceId?: string;\n enableDev?: boolean;\n /**\n * Inject each chunk's CSS relative to that chunk instead of bundling all CSS\n * into the entry. Enables component-level granular lazy-loading of stylesheets:\n * a code-split component's styles are only injected when the component (chunk)\n * is actually loaded.\n *\n * `false` (default) keeps the previous behavior (all CSS in the entry, loaded\n * up front) and is fully backward compatible.\n *\n * @default false\n */\n cssPerChunk?: boolean;\n /**\n * Filter function to determine which JS file(s) should receive the CSS injection code.\n * Useful when building multiple entry points and you want CSS only in specific entries.\n * @param chunk - The output chunk being processed\n * @returns true if CSS should be injected into this chunk\n */\n jsAssetsFilterFunction?: JsAssetsFilterFunction;\n}\n\nexport default function viteCustomCssPosition(\n options?: ViteCustomCssPositionOptions,\n): Plugin | Plugin[] {\n const instanceId =\n options?.instanceId || randomUUID().replace(/-/g, \"\").slice(0, 4);\n\n const globalVarName = `__vcssp_c_${instanceId}`;\n const eventName = `__vcssp_e_${instanceId}`;\n\n const cssPlugins = cssInjectionPlugins({\n globalVarName,\n eventName,\n enableDev: options?.enableDev ?? false,\n relative: options?.cssPerChunk ?? false,\n jsAssetsFilterFunction: options?.jsAssetsFilterFunction,\n });\n\n return [\n {\n name: \"vite-plugin-custom-css-position\",\n config(c) {\n return {\n ...c,\n define: {\n ...c.define,\n __VITE_CSS_POS_GLOBAL_VAR_NAME__: JSON.stringify(globalVarName),\n __VITE_CSS_POS_EVENT_NAME__: JSON.stringify(eventName),\n },\n };\n },\n },\n ...cssPlugins,\n ];\n}\n"],"mappings":"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"}
|