提交 bc1e088b 编写于 作者: J JJ Kasper 提交者: Tim Neutkens

Make styles compatible in AMP mode (#7060)

* Make styles compatible in AMP mode

* bump

* Update to parse styles from fragment for
backwards compat in AMP mode

* Add test for AMP styles fragment support
上级 80210bc3
...@@ -193,7 +193,7 @@ export class Head extends Component { ...@@ -193,7 +193,7 @@ export class Head extends Component {
} else if (type === 'link' && props.rel === 'canonical') { } else if (type === 'link' && props.rel === 'canonical') {
badProp = 'rel="canonical"' badProp = 'rel="canonical"'
} else if (type === 'script') { } else if (type === 'script') {
// only block if // only block if
// 1. it has a src and isn't pointing to ampproject's CDN // 1. it has a src and isn't pointing to ampproject's CDN
// 2. it is using dangerouslySetInnerHTML without a type or // 2. it is using dangerouslySetInnerHTML without a type or
// a type of text/javascript // a type of text/javascript
...@@ -214,6 +214,27 @@ export class Head extends Component { ...@@ -214,6 +214,27 @@ export class Head extends Component {
} }
return child return child
}) })
// try to parse styles from fragment for backwards compat
let curStyles = styles
if (amphtml && styles && styles.props &&
Array.isArray(styles.props.children)
) {
curStyles = []
const hasStyles = el => (
el && el.props &&
el.props.dangerouslySetInnerHTML &&
el.props.dangerouslySetInnerHTML.__html
)
styles.props.children.map(child => {
if (Array.isArray(child)) {
child.map(el => hasStyles(el) && curStyles.push(el))
} else if (hasStyles(child)) {
curStyles.push(child)
}
})
}
return ( return (
<head {...this.props}> <head {...this.props}>
{children} {children}
...@@ -237,7 +258,7 @@ export class Head extends Component { ...@@ -237,7 +258,7 @@ export class Head extends Component {
<style <style
amp-custom="" amp-custom=""
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: styles __html: curStyles
.map(style => style.props.dangerouslySetInnerHTML.__html) .map(style => style.props.dangerouslySetInnerHTML.__html)
.join('') .join('')
.replace(/\/\*# sourceMappingURL=.*\*\//g, '') .replace(/\/\*# sourceMappingURL=.*\*\//g, '')
......
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps (ctx) {
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
<style dangerouslySetInnerHTML={{
__html: `html { background: hotpink; }`
}} />
</>
)
}
}
render () {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
import { withAmp } from 'next/amp'
export default withAmp(() => (
<div>
<p>Hello world!</p>
<style jsx>{`
p {
font-size: 16.4px;
}
`}</style>
</div>
))
/* eslint-env jest */
/* global jasmine */
import { join } from 'path'
import cheerio from 'cheerio'
import { validateAMP } from 'amp-test-utils'
import {
stopApp,
startApp,
nextBuild,
nextServer,
renderViaHTTP
} from 'next-test-utils'
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60
const appDir = join(__dirname, '../')
let appPort
let server
let app
describe('AMP Fragment Styles', () => {
beforeAll(async () => {
await nextBuild(appDir)
app = nextServer({
dir: join(__dirname, '../'),
dev: false,
quiet: true
})
server = await startApp(app)
appPort = server.address().port
})
afterAll(() => stopApp(server))
it('adds styles from fragment in AMP mode correctly', async () => {
const html = await renderViaHTTP(appPort, '/', { amp: 1 })
await validateAMP(html)
const $ = cheerio.load(html)
const styles = $('style[amp-custom]').text()
expect(styles).toMatch(/background:(.*|)hotpink/)
expect(styles).toMatch(/font-size:(.*|)16\.4px/)
})
})
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册