vite-plugin-css-injected-by-js
Advanced tools
Comparing version 2.2.0 to 2.3.0
@@ -1,8 +0,3 @@ | ||
import { InjectCode } from './utils.js'; | ||
import { Plugin } from 'vite'; | ||
type Options = { | ||
injectCode?: InjectCode; | ||
styleId?: string; | ||
topExecutionPriority?: boolean; | ||
}; | ||
import { PluginConfiguration } from './interface'; | ||
/** | ||
@@ -13,3 +8,2 @@ * Inject the CSS compiled with JS. | ||
*/ | ||
export default function cssInjectedByJsPlugin({ topExecutionPriority, styleId, injectCode }?: Options | undefined): Plugin; | ||
export {}; | ||
export default function cssInjectedByJsPlugin({ topExecutionPriority, styleId, injectCode, injectCodeFunction, useStrictCSP }?: PluginConfiguration | undefined): Plugin; |
import { OutputChunk } from 'rollup'; | ||
import { BuildCSSInjectionConfiguration } from './interface'; | ||
interface InjectCodeOptions { | ||
styleId?: string; | ||
useStrictCSP?: boolean; | ||
} | ||
export type InjectCode = (cssCode: string, options: InjectCodeOptions) => string; | ||
export declare function buildCSSInjectionCode(cssToInject: string, styleId?: string, injectCode?: InjectCode): Promise<OutputChunk | null>; | ||
export type InjectCodeFunction = (cssCode: string, options: InjectCodeOptions) => void; | ||
export declare function buildCSSInjectionCode({ cssToInject, styleId, injectCode, injectCodeFunction, useStrictCSP, }: BuildCSSInjectionConfiguration): Promise<OutputChunk | null>; | ||
export declare function removeLinkStyleSheets(html: string, cssFileName: string): string; | ||
export {}; |
@@ -18,3 +18,3 @@ "use strict"; | ||
*/ | ||
function cssInjectedByJsPlugin({ topExecutionPriority, styleId, injectCode } = { | ||
function cssInjectedByJsPlugin({ topExecutionPriority, styleId, injectCode, injectCodeFunction, useStrictCSP } = { | ||
topExecutionPriority: true, | ||
@@ -41,2 +41,4 @@ styleId: '', | ||
const jsAssets = Object.keys(bundle).filter((i) => bundle[i].type == 'chunk' && | ||
// @ts-ignore isEntry is supported by the highest parent of the OutputChunk type | ||
bundle[i].isEntry == true && | ||
bundle[i].fileName.match(/.[cm]?js$/) != null && | ||
@@ -46,3 +48,6 @@ !bundle[i].fileName.includes('polyfill')); | ||
const cssAsset = bundle[cssName]; | ||
const result = previousValue + cssAsset.source; | ||
const cssAssetSource = typeof cssAsset.source == 'string' | ||
? cssAsset.source.replace(/(\r\n|\n|\r)+$/gm, '') | ||
: cssAsset.source; | ||
const result = previousValue + cssAssetSource; | ||
delete bundle[cssName]; | ||
@@ -62,4 +67,11 @@ return result; | ||
} | ||
const jsAsset = bundle[jsAssets[0]]; | ||
const cssInjectionCode = yield (0, utils_js_1.buildCSSInjectionCode)(cssToInject, styleId, injectCode); | ||
// This should be always the root of the application | ||
const jsAsset = bundle[jsAssets[jsAssets.length - 1]]; | ||
const cssInjectionCode = yield (0, utils_js_1.buildCSSInjectionCode)({ | ||
cssToInject, | ||
styleId, | ||
injectCode, | ||
injectCodeFunction, | ||
useStrictCSP, | ||
}); | ||
const appCode = jsAsset.code; | ||
@@ -66,0 +78,0 @@ jsAsset.code = topExecutionPriority ? '' : appCode; |
@@ -15,4 +15,4 @@ "use strict"; | ||
const cssInjectedByJsId = '\0vite/all-css'; | ||
const defaultInjectCode = (cssCode, { styleId }) => `try{if(typeof document != 'undefined'){var elementStyle = document.createElement('style');${typeof styleId == 'string' && styleId.length > 0 ? `elementStyle.id = '${styleId}';` : ''}elementStyle.appendChild(document.createTextNode(${cssCode}));document.head.appendChild(elementStyle);}}catch(e){console.error('vite-plugin-css-injected-by-js', e);}`; | ||
function buildCSSInjectionCode(cssToInject, styleId, injectCode) { | ||
const defaultInjectCode = (cssCode, { styleId, useStrictCSP }) => `try{if(typeof document != 'undefined'){var elementStyle = document.createElement('style');${typeof styleId == 'string' && styleId.length > 0 ? `elementStyle.id = '${styleId}';` : ''}${useStrictCSP ? `elementStyle.nonce = document.head.querySelector('meta[property=csp-nonce]')?.content;` : ''}elementStyle.appendChild(document.createTextNode(${cssCode}));document.head.appendChild(elementStyle);}}catch(e){console.error('vite-plugin-css-injected-by-js', e);}`; | ||
function buildCSSInjectionCode({ cssToInject, styleId, injectCode, injectCodeFunction, useStrictCSP, }) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -23,3 +23,3 @@ const res = yield (0, vite_1.build)({ | ||
logLevel: 'error', | ||
plugins: [injectionCSSCodePlugin(cssToInject, styleId, injectCode)], | ||
plugins: [injectionCSSCodePlugin({ cssToInject, styleId, injectCode, injectCodeFunction, useStrictCSP })], | ||
build: { | ||
@@ -48,9 +48,3 @@ write: false, | ||
exports.buildCSSInjectionCode = buildCSSInjectionCode; | ||
/** | ||
* @param {string} cssToInject | ||
* @param {string|null} styleId | ||
* @param {InjectCode|null} injectCode | ||
* @return {Plugin} | ||
*/ | ||
function injectionCSSCodePlugin(cssToInject, styleId, injectCode) { | ||
function injectionCSSCodePlugin({ cssToInject, injectCode, injectCodeFunction, styleId, useStrictCSP, }) { | ||
return { | ||
@@ -66,4 +60,7 @@ name: 'vite:injection-css-code-plugin', | ||
const cssCode = JSON.stringify(cssToInject.trim()); | ||
if (injectCodeFunction) { | ||
return `(${injectCodeFunction})(${cssCode}, ${JSON.stringify({ styleId, useStrictCSP })})`; | ||
} | ||
const injectFunction = injectCode || defaultInjectCode; | ||
return injectFunction(cssCode, { styleId }); | ||
return injectFunction(cssCode, { styleId, useStrictCSP }); | ||
} | ||
@@ -70,0 +67,0 @@ }, |
@@ -1,8 +0,3 @@ | ||
import { InjectCode } from './utils.js'; | ||
import { Plugin } from 'vite'; | ||
type Options = { | ||
injectCode?: InjectCode; | ||
styleId?: string; | ||
topExecutionPriority?: boolean; | ||
}; | ||
import { PluginConfiguration } from './interface'; | ||
/** | ||
@@ -13,3 +8,2 @@ * Inject the CSS compiled with JS. | ||
*/ | ||
export default function cssInjectedByJsPlugin({ topExecutionPriority, styleId, injectCode }?: Options | undefined): Plugin; | ||
export {}; | ||
export default function cssInjectedByJsPlugin({ topExecutionPriority, styleId, injectCode, injectCodeFunction, useStrictCSP }?: PluginConfiguration | undefined): Plugin; |
import { OutputChunk } from 'rollup'; | ||
import { BuildCSSInjectionConfiguration } from './interface'; | ||
interface InjectCodeOptions { | ||
styleId?: string; | ||
useStrictCSP?: boolean; | ||
} | ||
export type InjectCode = (cssCode: string, options: InjectCodeOptions) => string; | ||
export declare function buildCSSInjectionCode(cssToInject: string, styleId?: string, injectCode?: InjectCode): Promise<OutputChunk | null>; | ||
export type InjectCodeFunction = (cssCode: string, options: InjectCodeOptions) => void; | ||
export declare function buildCSSInjectionCode({ cssToInject, styleId, injectCode, injectCodeFunction, useStrictCSP, }: BuildCSSInjectionConfiguration): Promise<OutputChunk | null>; | ||
export declare function removeLinkStyleSheets(html: string, cssFileName: string): string; | ||
export {}; |
@@ -7,3 +7,3 @@ import { buildCSSInjectionCode, removeLinkStyleSheets } from './utils.js'; | ||
*/ | ||
export default function cssInjectedByJsPlugin({ topExecutionPriority, styleId, injectCode } = { | ||
export default function cssInjectedByJsPlugin({ topExecutionPriority, styleId, injectCode, injectCodeFunction, useStrictCSP } = { | ||
topExecutionPriority: true, | ||
@@ -29,2 +29,4 @@ styleId: '', | ||
const jsAssets = Object.keys(bundle).filter((i) => bundle[i].type == 'chunk' && | ||
// @ts-ignore isEntry is supported by the highest parent of the OutputChunk type | ||
bundle[i].isEntry == true && | ||
bundle[i].fileName.match(/.[cm]?js$/) != null && | ||
@@ -34,3 +36,6 @@ !bundle[i].fileName.includes('polyfill')); | ||
const cssAsset = bundle[cssName]; | ||
const result = previousValue + cssAsset.source; | ||
const cssAssetSource = typeof cssAsset.source == 'string' | ||
? cssAsset.source.replace(/(\r\n|\n|\r)+$/gm, '') | ||
: cssAsset.source; | ||
const result = previousValue + cssAssetSource; | ||
delete bundle[cssName]; | ||
@@ -50,4 +55,11 @@ return result; | ||
} | ||
const jsAsset = bundle[jsAssets[0]]; | ||
const cssInjectionCode = await buildCSSInjectionCode(cssToInject, styleId, injectCode); | ||
// This should be always the root of the application | ||
const jsAsset = bundle[jsAssets[jsAssets.length - 1]]; | ||
const cssInjectionCode = await buildCSSInjectionCode({ | ||
cssToInject, | ||
styleId, | ||
injectCode, | ||
injectCodeFunction, | ||
useStrictCSP, | ||
}); | ||
const appCode = jsAsset.code; | ||
@@ -54,0 +66,0 @@ jsAsset.code = topExecutionPriority ? '' : appCode; |
import { build } from 'vite'; | ||
const cssInjectedByJsId = '\0vite/all-css'; | ||
const defaultInjectCode = (cssCode, { styleId }) => `try{if(typeof document != 'undefined'){var elementStyle = document.createElement('style');${typeof styleId == 'string' && styleId.length > 0 ? `elementStyle.id = '${styleId}';` : ''}elementStyle.appendChild(document.createTextNode(${cssCode}));document.head.appendChild(elementStyle);}}catch(e){console.error('vite-plugin-css-injected-by-js', e);}`; | ||
export async function buildCSSInjectionCode(cssToInject, styleId, injectCode) { | ||
const defaultInjectCode = (cssCode, { styleId, useStrictCSP }) => `try{if(typeof document != 'undefined'){var elementStyle = document.createElement('style');${typeof styleId == 'string' && styleId.length > 0 ? `elementStyle.id = '${styleId}';` : ''}${useStrictCSP ? `elementStyle.nonce = document.head.querySelector('meta[property=csp-nonce]')?.content;` : ''}elementStyle.appendChild(document.createTextNode(${cssCode}));document.head.appendChild(elementStyle);}}catch(e){console.error('vite-plugin-css-injected-by-js', e);}`; | ||
export async function buildCSSInjectionCode({ cssToInject, styleId, injectCode, injectCodeFunction, useStrictCSP, }) { | ||
const res = await build({ | ||
@@ -9,3 +9,3 @@ root: '', | ||
logLevel: 'error', | ||
plugins: [injectionCSSCodePlugin(cssToInject, styleId, injectCode)], | ||
plugins: [injectionCSSCodePlugin({ cssToInject, styleId, injectCode, injectCodeFunction, useStrictCSP })], | ||
build: { | ||
@@ -32,9 +32,3 @@ write: false, | ||
} | ||
/** | ||
* @param {string} cssToInject | ||
* @param {string|null} styleId | ||
* @param {InjectCode|null} injectCode | ||
* @return {Plugin} | ||
*/ | ||
function injectionCSSCodePlugin(cssToInject, styleId, injectCode) { | ||
function injectionCSSCodePlugin({ cssToInject, injectCode, injectCodeFunction, styleId, useStrictCSP, }) { | ||
return { | ||
@@ -50,4 +44,7 @@ name: 'vite:injection-css-code-plugin', | ||
const cssCode = JSON.stringify(cssToInject.trim()); | ||
if (injectCodeFunction) { | ||
return `(${injectCodeFunction})(${cssCode}, ${JSON.stringify({ styleId, useStrictCSP })})`; | ||
} | ||
const injectFunction = injectCode || defaultInjectCode; | ||
return injectFunction(cssCode, { styleId }); | ||
return injectFunction(cssCode, { styleId, useStrictCSP }); | ||
} | ||
@@ -54,0 +51,0 @@ }, |
102
package.json
{ | ||
"name": "vite-plugin-css-injected-by-js", | ||
"version": "2.2.0", | ||
"description": "A Vite plugin that takes the CSS and adds it to the page through the JS. For those who want a single JS file.", | ||
"main": "dist/cjs/index.js", | ||
"module": "dist/esm/index.js", | ||
"exports": { | ||
".": { | ||
"types": "./dist/esm/declarations/index.d.ts", | ||
"import": "./dist/esm/index.js", | ||
"require": "./dist/cjs/index.js" | ||
} | ||
}, | ||
"typings": "dist/esm/declarations/index.d.ts", | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"build": "rm -rf dist && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./cjs-esm-fixup", | ||
"format": "prettier 'src/*.ts' --write" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/marco-prontera/vite-plugin-css-injected-by-js.git" | ||
}, | ||
"keywords": [ | ||
"vite", | ||
"vite-plugin", | ||
"plugin", | ||
"typescript", | ||
"css-injected-by-js", | ||
"single-js-file", | ||
"css", | ||
"js" | ||
], | ||
"peerDependencies": { | ||
"vite": ">2.0.0-0" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^18.11.15", | ||
"prettier": "^2.8.1", | ||
"typescript": "^4.9.4", | ||
"vite": "^4.0.1" | ||
}, | ||
"author": "Marco Prontera", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/marco-prontera/vite-plugin-css-injected-by-js/issues" | ||
}, | ||
"homepage": "https://github.com/marco-prontera/vite-plugin-css-injected-by-js#readme" | ||
"name": "vite-plugin-css-injected-by-js", | ||
"version": "2.3.0", | ||
"description": "A Vite plugin that takes the CSS and adds it to the page through the JS. For those who want a single JS file.", | ||
"main": "dist/cjs/index.js", | ||
"module": "dist/esm/index.js", | ||
"exports": { | ||
".": { | ||
"types": "./dist/esm/declarations/index.d.ts", | ||
"import": "./dist/esm/index.js", | ||
"require": "./dist/cjs/index.js" | ||
} | ||
}, | ||
"typings": "dist/esm/declarations/index.d.ts", | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"test": "vitest", | ||
"ci-test": "vitest run", | ||
"build": "npm run ci-test && rm -rf dist && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./cjs-esm-fixup", | ||
"format": "prettier '{src,test}/*.ts' --write" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/marco-prontera/vite-plugin-css-injected-by-js.git" | ||
}, | ||
"keywords": [ | ||
"vite", | ||
"vite-plugin", | ||
"plugin", | ||
"typescript", | ||
"css-injected-by-js", | ||
"single-js-file", | ||
"css", | ||
"js" | ||
], | ||
"peerDependencies": { | ||
"vite": ">2.0.0-0" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^18.11.15", | ||
"happy-dom": "^8.1.3", | ||
"prettier": "^2.8.1", | ||
"typescript": "^4.9.4", | ||
"vite": "^4.0.1", | ||
"vitest": "^0.27.0" | ||
}, | ||
"author": "Marco Prontera", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/marco-prontera/vite-plugin-css-injected-by-js/issues" | ||
}, | ||
"homepage": "https://github.com/marco-prontera/vite-plugin-css-injected-by-js#readme" | ||
} |
@@ -27,2 +27,3 @@ # Vite Plugin: CssInjectedByJs | ||
For now, you can configure only when the injection of CSS is done at execution time ```topExecutionPriority```. | ||
#### topExecutionPriority | ||
@@ -78,2 +79,49 @@ The default behavior adds the injection of CSS before your bundle code. | ||
#### injectCodeFunction | ||
If you prefer to specify the injectCode as a plain function you can use the `injectCodeFunction` param. | ||
The `injectCodeFunction` function is a void function that will be called at runtime application with two arguments: | ||
- cssCode (the `string` that contains all the css code that need to be injected via JavaScript) | ||
- options (a simple object that currently contains only the `styleId` param) | ||
This is an example: | ||
```ts | ||
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js' | ||
export default { | ||
plugins: [ | ||
cssInjectedByJsPlugin({ | ||
injectCodeFunction: function injectCodeCustomRunTimeFunction(cssCode, options) { | ||
try { | ||
if (typeof document != 'undefined') { | ||
var elementStyle = document.createElement('style'); | ||
elementStyle.appendChild(document.createTextNode(${cssCode})); | ||
document.head.appendChild(elementStyle); | ||
} | ||
} catch (e) { | ||
console.error('vite-plugin-css-injected-by-js', e); | ||
} | ||
} | ||
}), | ||
] | ||
} | ||
``` | ||
#### useStrictCSP | ||
The `useStrictCSP` configuration option adds a nonce to style tags based on `<meta property="csp-nonce" content={{ nonce }} />`. | ||
See the following [link](https://cssinjs.org/csp/?v=v10.9.2) for more information. | ||
This is an example: | ||
```ts | ||
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js' | ||
export default { | ||
plugins: [ | ||
cssInjectedByJsPlugin({useStrictCSP: true}), | ||
] | ||
} | ||
``` | ||
The tag `<meta property="csp-nonce" content={{ nonce }} />` (nonce should be replaced with the value) must be present in your html page. | ||
The `content` value of that tag will be provided to the `nonce` property of the `style` element that will be injected by our default injection code. | ||
## Contributing | ||
@@ -80,0 +128,0 @@ When you make changes to plugin locally, you may want to build the js from the typescript file of the plugin. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23125
17
337
138
6