1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Incorporate styled-jsx (#420)

* integrate styled-jsx

* define styles of pages with styled-jsx

* bump styled-jsx

* bump styled-jsx

* error-debug: fix style

* bump styled-jsx

* fix examples to use styled-jsx

* bump styled-jsx
This commit is contained in:
Naoyuki Kanezawa 2016-12-20 03:42:19 +09:00 committed by Guillermo Rauch
parent 26c485a22f
commit a87ef1a7af
12 changed files with 168 additions and 182 deletions

View file

@ -1,21 +0,0 @@
import React, { Component } from 'react'
import { style } from 'next/css'
export default class CrazyCSS extends Component {
spans () {
const out = []
for (let i = 0; i < 1000; i++) {
out.push(<span key={i} class={spanStyles[`padding-${i}`]}>This is ${i}</span>)
}
return out
}
render () {
return <div>{this.spans()}</div>
}
}
const spanStyles = {}
for (let i = 0; i < 1000; i++) {
spanStyles[`padding-${i}`] = style({ padding: i })
}

View file

@ -1,19 +1,19 @@
import React from 'react'
import style from 'next/css'
export default () => (
<div className={styles}>
<div className='hello'>
<p>Hello World</p>
<style jsx>{`
.hello {
font: 15px Helvetica, Arial, sans-serif;
background: #eee;
padding: 100px;
text-align: center;
transition: 100ms ease-in background;
}
.hello:hover {
background: #ccc;
}
`}</style>
</div>
)
const styles = style({
font: '15px Helvetica, Arial, sans-serif',
background: '#eee',
padding: '100px',
textAlign: 'center',
transition: '100ms ease-in background',
':hover': {
background: '#ccc'
}
})

View file

@ -1,11 +1,13 @@
import React from 'react'
import style from 'next/css'
export default ({ children }) => (
<p className={styles}>{children}</p>
<p>
{children}
<style jsx>{`
p {
font: 13px Helvetica, Arial;
margin: 10px 0;
}
`}</style>
</p>
)
const styles = style({
font: '13px Helvetica, Arial',
margin: '10px 0'
})

View file

@ -1,21 +1,21 @@
import React from 'react'
import style from 'next/css'
export default ({ title, children }) => (
<div className={mainStyle}>
<h1 className={titleStyle}>{ title }</h1>
<div className='main'>
<h1>{ title }</h1>
{ children }
<style jsx>{`
.main {
font: 15px Helvetica, Arial;
border: 1px solid #eee;
padding: 0 10px;
}
h1 {
font-size: 16px;
font-weight: bold;
margin: 10px 0;
}
`}</style>
</div>
)
const mainStyle = style({
font: '15px Helvetica, Arial',
border: '1px solid #eee',
padding: '0 10px'
})
const titleStyle = style({
fontSize: '16px',
fontWeight: 'bold',
margin: '10px 0'
})

View file

@ -1,16 +1,15 @@
import React from 'react'
import P from '../components/paragraph'
import Post from '../components/post'
import style from 'next/css'
export default () => (
<div className={styles.main}>
<div className='main'>
<Post title='My first blog post'>
<P>Hello there</P>
<P>This is an example of a componentized blog post</P>
</Post>
<Hr />
<hr />
<Post title='My second blog post'>
<P>Hello there</P>
@ -18,31 +17,30 @@ export default () => (
<P>Wa-hoo!</P>
</Post>
<Hr />
<hr />
<Post title='The final blog post'>
<P>C'est fin</P>
</Post>
<style jsx>{`
.main {
margin: auto;
max-width: 420px;
padding: 10px;
}
hr {
width: 100px;
border-width: 0;
margin: 20px auto;
text-align: center;
}
hr::before {
content: "***";
color: #ccc;
}
`}</style>
</div>
)
const Hr = () => <hr className={styles.hr} />
const styles = {
main: style({
margin: 'auto',
maxWidth: '420px',
padding: '10px'
}),
hr: style({
width: '100px',
borderWidth: 0,
margin: '20px auto',
textAlign: 'center',
'::before': {
content: '"***"',
color: '#ccc'
}
})
}

View file

@ -65,6 +65,7 @@
"send": "0.14.1",
"source-map-support": "0.4.6",
"strip-ansi": "3.0.1",
"styled-jsx": "0.2.1",
"url": "0.11.0",
"webpack": "1.14.0",
"webpack-dev-middleware": "1.9.0",

View file

@ -1,7 +1,5 @@
import React from 'react'
import ansiHTML from 'ansi-html'
import Head from 'next/head'
import style from 'next/css'
export default class ErrorDebug extends React.Component {
static getInitialProps ({ err }) {
@ -12,21 +10,47 @@ export default class ErrorDebug extends React.Component {
render () {
const { name, message, stack, path } = this.props
return <div className={styles.errorDebug}>
<Head>
<style dangerouslySetInnerHTML={{ __html: `
body {
background: #a6004c;
margin: 0;
}
`}} />
</Head>
{path ? <div className={styles.heading}>Error in {path}</div> : null}
return <div className='errorDebug'>
{path ? <div className='heading'>Error in {path}</div> : null}
{
name === 'ModuleBuildError'
? <pre className={styles.message} dangerouslySetInnerHTML={{ __html: ansiHTML(encodeHtml(message)) }} />
: <pre className={styles.message}>{stack}</pre>
? <pre className='message' dangerouslySetInnerHTML={{ __html: ansiHTML(encodeHtml(message)) }} />
: <pre className='message'>{stack}</pre>
}
<style jsx global>{`
body {
background: #a6004c;
margin: 0;
}
`}</style>
<style jsx>{`
.errorDebug {
height: 100vh;
padding: 16px;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.message {
font-family: "SF Mono", "Roboto Mono", "Fira Mono", menlo-regular, monospace;
font-size: 10px;
color: #fbe7f1;
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
}
.heading {
font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif;
font-size: 13px;
font-weight: bold;
color: #ff84bf;
margin-bottom: 20pxl
}
`}</style>
</div>
}
}
@ -35,40 +59,6 @@ const encodeHtml = str => {
return str.replace(/</g, '&lt;').replace(/>/g, '&gt;')
}
const styles = {
body: style({
background: '#a6004c',
margin: 0
}),
errorDebug: style({
height: '100vh',
padding: '16px',
boxSizing: 'border-box',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center'
}),
message: style({
fontFamily: '"SF Mono", "Roboto Mono", "Fira Mono", menlo-regular, monospace',
fontSize: '10px',
color: '#fbe7f1',
margin: 0,
whiteSpace: 'pre-wrap',
wordWrap: 'break-word'
}),
heading: style({
fontFamily: '-apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif',
fontSize: '13px',
fontWeight: 'bold',
color: '#ff84bf',
marginBottom: '20px'
})
}
// see color definitions of babel-code-frame:
// https://github.com/babel/babel/blob/master/packages/babel-code-frame/src/index.js

View file

@ -1,5 +1,4 @@
import React from 'react'
import style from 'next/css'
export default class Error extends React.Component {
static getInitialProps ({ res, xhr }) {
@ -13,54 +12,53 @@ export default class Error extends React.Component {
? 'This page could not be found'
: (statusCode ? 'Internal Server Error' : 'An unexpected error has occurred')
return <div className={styles.error}>
<div className={styles.text}>
{statusCode ? <h1 className={styles.h1}>{statusCode}</h1> : null}
<div className={styles.desc}>
<h2 className={styles.h2}>{title}.</h2>
return <div className='error'>
<div>
{statusCode ? <h1>{statusCode}</h1> : null}
<div className='desc'>
<h2>{title}.</h2>
</div>
</div>
<style jsx>{`
.error {
color: #000;
background: #fff;
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif;
text-align: center;
padding-top: 20%;
}
.desc {
display: inline-block;
text-align: left;
line-height: 49px;
height: 49px;
vertical-align: middle;
}
h1 {
display: inline-block;
border-right: 1px solid rgba(0, 0, 0,.3);
margin: 0;
margin-right: 20px;
padding: 10px 23px;
font-size: 24px;
font-weight: 500;
vertical-align: top;
}
h2 {
font-size: 14px;
font-weight: normal;
margin: 0;
padding: 0;
}
`}</style>
</div>
}
}
const styles = {
error: style({
color: '#000',
background: '#fff',
top: 0,
bottom: 0,
left: 0,
right: 0,
position: 'absolute',
fontFamily: '-apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif',
textAlign: 'center',
paddingTop: '20%'
}),
desc: style({
display: 'inline-block',
textAlign: 'left',
lineHeight: '49px',
height: '49px',
verticalAlign: 'middle'
}),
h1: style({
display: 'inline-block',
borderRight: '1px solid rgba(0, 0, 0,.3)',
margin: 0,
marginRight: '20px',
padding: '10px 23px',
fontSize: '24px',
fontWeight: 500,
verticalAlign: 'top'
}),
h2: style({
fontSize: '14px',
fontWeight: 'normal',
margin: 0,
padding: 0
})
}

View file

@ -120,7 +120,8 @@ export default async function createCompiler (dir, { dev = false } = {}) {
require.resolve('babel-plugin-module-resolver'),
{
alias: {
'ansi-html': require.resolve('ansi-html')
'ansi-html': require.resolve('ansi-html'),
'styled-jsx/style': require.resolve('styled-jsx/style')
}
}
]
@ -143,6 +144,7 @@ export default async function createCompiler (dir, { dev = false } = {}) {
require.resolve('babel-plugin-transform-object-rest-spread'),
require.resolve('babel-plugin-transform-class-properties'),
require.resolve('babel-plugin-transform-runtime'),
require.resolve('styled-jsx/babel'),
[
require.resolve('babel-plugin-module-resolver'),
{
@ -154,7 +156,8 @@ export default async function createCompiler (dir, { dev = false } = {}) {
'next/prefetch': require.resolve('../../lib/prefetch'),
'next/css': require.resolve('../../lib/css'),
'next/head': require.resolve('../../lib/head'),
'next/document': require.resolve('../../server/document')
'next/document': require.resolve('../../server/document'),
'styled-jsx/style': require.resolve('styled-jsx/style')
}
}
]

View file

@ -1,6 +1,7 @@
import React, { Component, PropTypes } from 'react'
import htmlescape from 'htmlescape'
import { renderStatic } from 'glamor/server'
import flush from 'styled-jsx/server'
export default class Document extends Component {
static getInitialProps ({ renderPage }) {
@ -10,7 +11,8 @@ export default class Document extends Component {
head = page.head
return page.html
})
const nextCSS = { css, ids }
const styles = flush()
const nextCSS = { css, ids, styles }
return { html, head, nextCSS }
}
@ -48,7 +50,8 @@ export class Head extends Component {
const { head, nextCSS } = this.context._documentProps
return <head>
{(head || []).map((h, i) => React.cloneElement(h, { key: i }))}
{nextCSS ? <style dangerouslySetInnerHTML={{ __html: nextCSS.css }} /> : null}
{nextCSS && nextCSS.css ? <style dangerouslySetInnerHTML={{ __html: nextCSS.css }} /> : null}
{nextCSS && nextCSS.styles ? nextCSS.styles : null}
{this.props.children}
</head>
}

View file

@ -0,0 +1,6 @@
export default () => (
<div>
<p>This is blue</p>
<style jsx>{`p { color: blue }`}</style>
</div>
)

View file

@ -45,6 +45,12 @@ describe('integration tests', () => {
expect(/<div class="css-\w+">This is red<\/div>/.test(html)).toBeTruthy()
})
test('renders styled jsx', async () => {
const html = await render('/styled-jsx')
expect(html).toMatch(/<style id="__jsx-style-1401785258">p\[data-jsx="1401785258"] {color: blue }[^]+<\/style>/)
expect(html.includes('<div data-jsx="1401785258"><p data-jsx="1401785258">This is blue</p></div>')).toBeTruthy()
})
test('renders properties populated asynchronously', async () => {
const html = await render('/async-props')
expect(html.includes('<p>Diego Milito</p>')).toBeTruthy()
@ -62,8 +68,8 @@ describe('integration tests', () => {
test('error 404', async () => {
const html = await render('/non-existent')
expect(html).toMatch(/<h1 class=".+">404<\/h1>/)
expect(html).toMatch(/<h2 class=".+">This page could not be found\.<\/h2>/)
expect(html).toMatch(/<h1 data-jsx=".+">404<\/h1>/)
expect(html).toMatch(/<h2 data-jsx=".+">This page could not be found\.<\/h2>/)
})
test('finishes response', async () => {