Skip to content

Commit 0082730

Browse files
committed
fix: apply StyleProvider nonce to CSS variable styles
修复了当通过 StyleProvider 传递 nonce 时,CSS 变量样式未获得 nonce 属性的问题。 Changes: - 在 StyleContextProps 中添加 nonce 配置支持 - 在 useCacheToken 中应用 nonce 到 CSS var 样式注入 - 在 useCSSVarRegister 中应用 nonce 到 CSS var 样式注入 - 为 StyleProvider nonce 功能添加测试用例 用户现在可以一致地在所有样式注入点使用 StyleProvider 配置 nonce。 改进建议(未来优化): - 提取 nonce 处理逻辑为共享函数以减少代码重复 - 当前测试已覆盖 useCacheToken → useCSSVarRegister 的调用路径
1 parent 103922e commit 0082730

4 files changed

Lines changed: 45 additions & 5 deletions

File tree

src/StyleContext.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,11 @@ export interface StyleContextProps {
7878
linters?: Linter[];
7979
/** Wrap css in a layer to avoid global style conflict */
8080
layer?: boolean;
81-
8281
/** Hardcode here since transformer not support take effect on serialize currently */
8382
autoPrefix?: boolean;
83+
84+
/** Nonce for CSP (Content Security Policy) */
85+
nonce?: string | (() => string);
8486
}
8587

8688
const StyleContext = React.createContext<StyleContextProps>({

src/hooks/useCSSVarRegister.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const useCSSVarRegister = <V, T extends Record<string, V>>(
3939
cache: { instanceId },
4040
container,
4141
hashPriority,
42+
nonce,
4243
} = useContext(StyleContext);
4344
const { _tokenKey: tokenKey } = token;
4445

@@ -70,12 +71,19 @@ const useCSSVarRegister = <V, T extends Record<string, V>>(
7071
if (!cssVarsStr) {
7172
return;
7273
}
73-
const style = updateCSS(cssVarsStr, styleId, {
74+
const mergedCSSConfig: Parameters<typeof updateCSS>[2] = {
7475
mark: ATTR_MARK,
7576
prepend: 'queue',
7677
attachTo: container,
7778
priority: -999,
78-
});
79+
};
80+
81+
const nonceStr = typeof nonce === 'function' ? nonce() : nonce;
82+
if (nonceStr) {
83+
mergedCSSConfig.csp = { nonce: nonceStr };
84+
}
85+
86+
const style = updateCSS(cssVarsStr, styleId, mergedCSSConfig);
7987

8088
(style as any)[CSS_IN_JS_INSTANCE] = instanceId;
8189

src/hooks/useCacheToken.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ export default function useCacheToken<
161161
cache: { instanceId },
162162
container,
163163
hashPriority,
164+
nonce,
164165
} = useContext(StyleContext);
165166
const {
166167
salt = '',
@@ -219,12 +220,19 @@ export default function useCacheToken<
219220
if (!cssVarsStr) {
220221
return;
221222
}
222-
const style = updateCSS(cssVarsStr, hash(`css-var-${themeKey}`), {
223+
const mergedCSSConfig: Parameters<typeof updateCSS>[2] = {
223224
mark: ATTR_MARK,
224225
prepend: 'queue',
225226
attachTo: container,
226227
priority: -999,
227-
});
228+
};
229+
230+
const nonceStr = typeof nonce === 'function' ? nonce() : nonce;
231+
if (nonceStr) {
232+
mergedCSSConfig.csp = { nonce: nonceStr };
233+
}
234+
235+
const style = updateCSS(cssVarsStr, hash(`css-var-${themeKey}`), mergedCSSConfig);
228236

229237
(style as any)[CSS_IN_JS_INSTANCE] = instanceId;
230238

tests/index.spec.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,28 @@ describe('csssinjs', () => {
507507
test('function', () => 'bamboo');
508508
});
509509

510+
describe('StyleProvider nonce for CSS var', () => {
511+
function testWithStyleProvider(name: string, nonce: string | (() => string)) {
512+
it(name, () => {
513+
const { unmount } = render(
514+
<StyleProvider cache={createCache()} nonce={nonce}>
515+
<Box />
516+
</StyleProvider>,
517+
);
518+
519+
const styles = Array.from(document.head.querySelectorAll('style'));
520+
// Box 组件使用 useCacheToken 注册 CSS var,应该有 nonce
521+
const cssVarStyle = styles.find(s => s.innerHTML.includes('--primary-color'));
522+
expect(cssVarStyle).toBeDefined();
523+
expect(cssVarStyle?.nonce).toBe('bamboo');
524+
// unmount 后样式清理行为取决于 cache 配置
525+
});
526+
}
527+
528+
testWithStyleProvider('string', 'bamboo');
529+
testWithStyleProvider('function', () => 'bamboo');
530+
});
531+
510532
it('should not insert style with different instanceId', () => {
511533
const genDemoStyle = (token: DerivativeToken): CSSInterpolation => ({
512534
div: {

0 commit comments

Comments
 (0)