Skip to content

Commit

Permalink
fix styles mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed Aug 31, 2021
1 parent 92dacb4 commit 3a4cff8
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 19 deletions.
3 changes: 2 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ import App from './app'
function Head() {
const registry = useStyleRegistry()
const styles = registry.styles()
registry.flush()
return <head>{styles}</head>
}

Expand Down Expand Up @@ -378,7 +379,7 @@ import nanoid from 'nanoid'
const nonce = Buffer.from(nanoid()).toString('base64') //ex: N2M0MDhkN2EtMmRkYi00MTExLWFhM2YtNDhkNTc4NGJhMjA3
```

You must then pass a nonce to either `flushToReact({ nonce })` or `flushToHTML({ nonce })` **and** set a `<meta property="csp-nonce" content={nonce} />` tag.
You must then pass a nonce to `registry.styles({ nonce })` **and** set a `<meta property="csp-nonce" content={nonce} />` tag.

Your CSP policy must share the same nonce as well (the header nonce needs to match the html nonce and remain unpredictable).
`Content-Security-Policy: default-src 'self'; style-src 'self' 'nonce-N2M0MDhkN2EtMmRkYi00MTExLWFhM2YtNDhkNTc4NGJhMjA3';`
Expand Down
8 changes: 3 additions & 5 deletions src/stylesheet-registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ export function useStyleRegistry() {

return useMemo(
() => ({
styles() {
return mapRulesToStyle(registry.cssRules())
styles(options) {
return mapRulesToStyle(registry.cssRules(), options)
},
flush() {
registry.flush()
Expand All @@ -192,9 +192,7 @@ export function useStyleRegistry() {
)
}

function mapRulesToStyle(options = {}) {
const registry = useStyleRegistry()
const cssRules = registry.styles()
function mapRulesToStyle(cssRules, options = {}) {
return cssRules.map(args => {
const id = args[0]
const css = args[1]
Expand Down
41 changes: 28 additions & 13 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import plugin from '../src/babel'
import JSXStyle from '../src/style'
import {
StyleSheetRegistry,
StyleSheetContext
StyleSheetContext,
useStyleRegistry
} from '../src/stylesheet-registry'
import _transform, { transformSource as _transformSource } from './_transform'

Expand All @@ -25,9 +26,7 @@ const flushToHTML = (registry, options = {}) => {
}, '')
}

function flushToReact(registry, options = {}) {
const cssRules = registry.cssRules()
registry.flush()
function mapCssRulesToReact(cssRules, options = {}) {
return cssRules.map(args => {
const id = args[0]
const css = args[1]
Expand All @@ -43,6 +42,12 @@ function flushToReact(registry, options = {}) {
})
}

function flushToReact(registry, options = {}) {
const cssRules = registry.cssRules()
registry.flush()
return mapCssRulesToReact(cssRules, options)
}

const transform = (file, opts = {}) =>
_transform(file, {
plugins: [plugin],
Expand Down Expand Up @@ -180,6 +185,16 @@ test('works with exported non-jsx style (CommonJS modules)', async t => {
})

test('sever rendering with hook api', t => {
function Head() {
const registry = useStyleRegistry()
const styles = registry.styles()
registry.flush()
// should be empty and `push` won't effect styles
const stylesAfterFlushed = registry.styles()
styles.push(...stylesAfterFlushed)
return React.createElement('head', null, styles)
}

function App() {
const color = 'green'
return React.createElement(
Expand All @@ -190,25 +205,25 @@ test('sever rendering with hook api', t => {
)
}

// Expected CSS
const expected =
// Expected DOM string
const styles =
'<style id="__jsx-2">div { color: blue }</style>' +
'<style id="__jsx-3">div { color: green }</style>'

const expected = `<head>${styles}</head>`

const registry = new StyleSheetRegistry()
const createApp = () =>
const createContextualApp = type =>
React.createElement(
StyleSheetContext.Provider,
{ value: registry },
React.createElement(App)
React.createElement(type)
)

// Render using react
ReactDOM.renderToString(createApp())
const html = ReactDOM.renderToStaticMarkup(
React.createElement('head', null, flushToReact(registry))
)
t.is(html, `<head>${expected}</head>`)
ReactDOM.renderToString(createContextualApp(App))
const html = ReactDOM.renderToStaticMarkup(createContextualApp(Head))
t.is(html, expected)
})

test('server rendering', t => {
Expand Down

0 comments on commit 3a4cff8

Please sign in to comment.