Skip to content

Commit 8e1a392

Browse files
authored
[#111] Make styleId an optional string or function (#110)
* feat: allow for unique styleId when relativeCssInjection * fix: remove dash when there is no styleId * fix: only run changes if styleId exists * fix: move uuid to devDependencies + update README * fix: PR comments * fix: remove empty line * fix: remove empty line * fix: remove empty line * fix: remove unused duplicate test * refactor: styleId as callback function
1 parent 57f36d5 commit 8e1a392

File tree

5 files changed

+69
-6
lines changed

5 files changed

+69
-6
lines changed

README.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ export default {
5353
}
5454
```
5555

56-
#### styleId (string)
56+
#### styleId (string | function)
5757

58-
If you provide a `string` for `styleId` param the code of injection will set the `id` attribute of the `style` element
58+
If you provide a `string` for `styleId` param, the code of injection will set the `id` attribute of the `style` element
5959
with the value of the parameter provided. This is an example:
6060

6161
```ts
@@ -77,6 +77,25 @@ The output injected into the DOM will look like this example:
7777
</head>
7878
```
7979

80+
If you provide a `function` for `styleId` param, it will run that function and return a string. It's especially useful if you use `relativeCSSInjection` and want unique styleIds for each file.
81+
82+
```ts
83+
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
84+
85+
export default {
86+
plugins: [
87+
cssInjectedByJsPlugin({styleId: () => `foo-${Math.random() * 100}`}),
88+
]
89+
}
90+
```
91+
92+
```html
93+
<head>
94+
<style id="foo-1234">/* Generated CSS rules */</style>
95+
<style id="foo-4321">/* Generated CSS rules */</style>
96+
</head>
97+
```
98+
8099
#### preRenderCSSCode (function)
81100

82101
You can use the `preRenderCSSCode` parameter to make specific changes to your CSS before it is printed in the output JS

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export default function cssInjectedByJsPlugin({
6767
injectCode,
6868
injectCodeFunction,
6969
useStrictCSP,
70-
buildOptions: config.build,
70+
buildOptions: config.build
7171
});
7272

7373
const cssAssetsFilter = (asset: OutputAsset): boolean => {

src/interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { BuildOptions } from 'vite';
55
export interface BaseOptions {
66
injectCode?: InjectCode;
77
injectCodeFunction?: InjectCodeFunction;
8-
styleId?: string;
8+
styleId?: string | (() => string);
99
topExecutionPriority?: boolean;
1010
useStrictCSP?: boolean;
1111
}

src/utils.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { OutputAsset, OutputBundle, OutputChunk } from 'rollup';
33
import type { BuildCSSInjectionConfiguration, CSSInjectionConfiguration, PluginConfiguration } from './interface';
44

55
interface InjectCodeOptions {
6-
styleId?: string;
6+
styleId?: string | (() => string);
77
useStrictCSP?: boolean;
88
}
99

@@ -29,11 +29,19 @@ export async function buildCSSInjectionCode({
2929
}: BuildCSSInjectionConfiguration): Promise<OutputChunk | null> {
3030
let { minify, target } = buildOptions;
3131

32+
const generatedStyleId = typeof styleId === 'function' ? styleId() : styleId;
33+
3234
const res = await build({
3335
root: '',
3436
configFile: false,
3537
logLevel: 'error',
36-
plugins: [injectionCSSCodePlugin({ cssToInject, styleId, injectCode, injectCodeFunction, useStrictCSP })],
38+
plugins: [injectionCSSCodePlugin({
39+
cssToInject,
40+
styleId: generatedStyleId,
41+
injectCode,
42+
injectCodeFunction,
43+
useStrictCSP
44+
})],
3745
build: {
3846
write: false,
3947
target,

test/utils.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,42 @@ describe('utils', () => {
6969
expect(getComputedStyle(document.body).color).toBe('red');
7070
});
7171

72+
test('Generate JS that applies styles with callback styleID', async () => {
73+
const styleId = () => `styleId-${Math.random()}`;
74+
const builds = await Promise.all([
75+
buildCSSInjectionCode({
76+
cssToInject: 'body { color: red; }',
77+
styleId,
78+
buildOptions: { minify: true, target: 'es2015' },
79+
}),
80+
buildCSSInjectionCode({
81+
cssToInject: 'body { background: blue; }',
82+
styleId,
83+
buildOptions: { minify: true, target: 'es2015' },
84+
})
85+
]);
86+
87+
builds?.map((output) => {
88+
const $script = document.createElement('script');
89+
$script.textContent = output?.code || 'throw new Error("UNCAUGHT ERROR")';
90+
document.head.appendChild($script);
91+
});
92+
93+
// Doesn't error
94+
expect(onerror).not.toBeCalled();
95+
96+
// StyleId applied
97+
const styles = document.head.querySelectorAll(`style[id^=styleId-]`);
98+
99+
expect(styles).toHaveLength(2);
100+
// Expect unique style ids
101+
expect([...new Set(styles.map((style) => style.id))]).toHaveLength(2)
102+
103+
// Applied style!
104+
expect(getComputedStyle(document.body).color).toBe('red');
105+
expect(getComputedStyle(document.body).background).toBe('blue');
106+
});
107+
72108
test('Generate JS that applies styles, without styleId', async () => {
73109
const output = await buildCSSInjectionCode({
74110
cssToInject: 'body { color: red; }',

0 commit comments

Comments
 (0)