diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 966a162f9a..4f0d27d974 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,7 @@ 1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device. 2. Install the dependencies: `npm install`. 3. Run `npm link` to link the local repo to NPM. -4. Run `npm run build` to build or `npm run watch` to build and watch for code changes. +4. Run `nuxt build` to build or `nuxt` to build and watch for code changes. 5. Then npm link this repo inside any example app with `npm link nuxt`. 6. Then you can run your example app with the local version of Nuxt.js (You may need to re-run the example app as you change server side code in the Nuxt.js repository). diff --git a/README.md b/README.md index 7fff59fda0..c2c1bee380 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

Build Status Build Status - Windows Build Status + Windows Build Status  Coverage Status Downloads Version @@ -190,7 +190,7 @@ Learn more: https://nuxtjs.org/api/nuxt ## Using nuxt.js as a middleware -You might want to use your own server with you configurations, your API and everything awesome your created with. That's why you can use nuxt.js as a middleware. It's recommended to use it at the end of your middleware since it will handle the rendering of your web application and won't call next(). +You might want to use your own server with your configurations, your API and everything awesome your created with. That's why you can use nuxt.js as a middleware. It's recommended to use it at the end of your middleware since it will handle the rendering of your web application and won't call next(). ```js app.use(nuxt.render) diff --git a/examples/i18n/middleware/i18n.js b/examples/i18n/middleware/i18n.js index acb811260a..bc7a9ecbfc 100644 --- a/examples/i18n/middleware/i18n.js +++ b/examples/i18n/middleware/i18n.js @@ -1,16 +1,21 @@ export default function ({ isHMR, app, store, route, params, error, redirect }) { + const defaultLocale = app.i18n.fallbackLocale // If middleware is called from hot module replacement, ignore it if (isHMR) return // Get locale from params - const locale = params.lang || 'en' + const locale = params.lang || defaultLocale if (store.state.locales.indexOf(locale) === -1) { return error({ message: 'This page could not be found.', statusCode: 404 }) } // Set locale store.commit('SET_LANG', locale) app.i18n.locale = store.state.locale - // If route is /en/... -> redirect to /... - if (locale === 'en' && route.fullPath.indexOf('/en') === 0) { - return redirect(route.fullPath.replace(/^\/en/, '/')) + // If route is //... -> redirect to /... + if (locale === defaultLocale && route.fullPath.indexOf('/' + defaultLocale) === 0) { + const toReplace = '^/' + defaultLocale + const re = new RegExp(toReplace) + return redirect( + route.fullPath.replace(re, '/') + ) } } diff --git a/examples/with-purgecss/README.md b/examples/with-purgecss/README.md new file mode 100644 index 0000000000..bd16434a04 --- /dev/null +++ b/examples/with-purgecss/README.md @@ -0,0 +1,4 @@ +# Nuxt.js with Purgecss (and Tailwind CSS) + +See https://www.purgecss.com + diff --git a/examples/with-purgecss/assets/css/tailwind.css b/examples/with-purgecss/assets/css/tailwind.css new file mode 100644 index 0000000000..d44c6d8c2c --- /dev/null +++ b/examples/with-purgecss/assets/css/tailwind.css @@ -0,0 +1,57 @@ +/** + * This injects Tailwind's base styles, which is a combination of + * Normalize.css and some additional base styles. + * + * You can see the styles here: + * https://github.com/tailwindcss/tailwindcss/blob/master/css/preflight.css + * + * If using `postcss-import`, you should import this line from it's own file: + * + * @import "./tailwind-preflight.css"; + * + * See: https://github.com/tailwindcss/tailwindcss/issues/53#issuecomment-341413622 + */ + @tailwind preflight; + + /** + * Here you would add any of your custom component classes; stuff that you'd + * want loaded *before* the utilities so that the utilities could still + * override them. + * + * Example: + * + * .btn { ... } + * .form-input { ... } + * + * Or if using a preprocessor or `postcss-import`: + * + * @import "components/buttons"; + * @import "components/forms"; + */ + + /** + * This injects all of Tailwind's utility classes, generated based on your + * config file. + * + * If using `postcss-import`, you should import this line from it's own file: + * + * @import "./tailwind-utilities.css"; + * + * See: https://github.com/tailwindcss/tailwindcss/issues/53#issuecomment-341413622 + */ + @tailwind utilities; + + /** + * Here you would add any custom utilities you need that don't come out of the + * box with Tailwind. + * + * Example : + * + * .bg-pattern-graph-paper { ... } + * .skew-45 { ... } + * + * Or if using a preprocessor or `postcss-import`: + * + * @import "utilities/background-patterns"; + * @import "utilities/skew-transforms"; + */ \ No newline at end of file diff --git a/examples/with-purgecss/layouts/default.vue b/examples/with-purgecss/layouts/default.vue new file mode 100644 index 0000000000..f05697c329 --- /dev/null +++ b/examples/with-purgecss/layouts/default.vue @@ -0,0 +1,14 @@ + diff --git a/examples/with-purgecss/nuxt.config.js b/examples/with-purgecss/nuxt.config.js new file mode 100644 index 0000000000..91a2ba93ea --- /dev/null +++ b/examples/with-purgecss/nuxt.config.js @@ -0,0 +1,41 @@ +const path = require('path') +const PurgecssPlugin = require('purgecss-webpack-plugin') +const glob = require('glob-all') + +class TailwindExtractor { + static extract(content) { + return content.match(/[A-z0-9-:/]+/g) || [] + } +} + +module.exports = { + build: { + extractCSS: true, + postcss: [ + require('tailwindcss')('./tailwind.js'), + require('autoprefixer') + ], + extend(config, { isDev }) { + if (!isDev) { + config.plugins.push( + new PurgecssPlugin({ + // purgecss configuration + // https://github.com/FullHuman/purgecss + paths: glob.sync([ + path.join(__dirname, './pages/**/*.vue'), + path.join(__dirname, './layouts/**/*.vue') + ]), + extractors: [ + { + extractor: TailwindExtractor, + extensions: ['vue'] + } + ], + whitelist: ['html', 'body', 'nuxt-progress'] + }) + ) + } + } + }, + css: ['~/assets/css/tailwind.css'] +} diff --git a/examples/with-purgecss/package.json b/examples/with-purgecss/package.json new file mode 100644 index 0000000000..538e7ca36f --- /dev/null +++ b/examples/with-purgecss/package.json @@ -0,0 +1,18 @@ +{ + "name": "nuxt-tailwindcss", + "description": "Nuxt.js with Tailwind CSS", + "scripts": { + "dev": "nuxt", + "build": "nuxt build", + "start": "nuxt start" + }, + "dependencies": { + "nuxt": "latest" + }, + "devDependencies": { + "autoprefixer": "^7.1.6", + "glob-all": "^3.1.0", + "purgecss-webpack-plugin": "^0.20.1", + "tailwindcss": "^0.1.3" + } +} diff --git a/examples/with-purgecss/pages/about.vue b/examples/with-purgecss/pages/about.vue new file mode 100644 index 0000000000..9e13161e79 --- /dev/null +++ b/examples/with-purgecss/pages/about.vue @@ -0,0 +1,19 @@ + + + diff --git a/examples/with-purgecss/pages/index.vue b/examples/with-purgecss/pages/index.vue new file mode 100644 index 0000000000..42b3f02ef1 --- /dev/null +++ b/examples/with-purgecss/pages/index.vue @@ -0,0 +1,17 @@ + diff --git a/examples/with-purgecss/postcss.config.js b/examples/with-purgecss/postcss.config.js new file mode 100644 index 0000000000..6b4212984e --- /dev/null +++ b/examples/with-purgecss/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: [ + require('tailwindcss')('./tailwind.js'), + require('autoprefixer') + ] +} diff --git a/examples/with-purgecss/tailwind.js b/examples/with-purgecss/tailwind.js new file mode 100644 index 0000000000..9a4af76aba --- /dev/null +++ b/examples/with-purgecss/tailwind.js @@ -0,0 +1,744 @@ +/* + +Tailwind - The Utility-First CSS Framework + +A project by Adam Wathan (@adamwathan), Jonathan Reinink (@reinink), +David Hemphill (@davidhemphill) and Steve Schoger (@steveschoger). + +Welcome to the Tailwind config file. This is where you can customize +Tailwind specifically for your project. Don't be intimidated by the +length of this file. It's really just a big JavaScript object and +we've done our very best to explain each section. + +View the full documentation at https://tailwindcss.com. + +|------------------------------------------------------------------------------- +| The default config +|------------------------------------------------------------------------------- +| +| This variable contains the default Tailwind config. You don't have +| to use it, but it can sometimes be helpful to have available. For +| example, you may choose to merge your custom configuration +| values with some of the Tailwind defaults. +| +*/ + +// var defaultConfig = require('tailwindcss').defaultConfig() + +/* +|------------------------------------------------------------------------------- +| Colors https://tailwindcss.com/docs/colors +|------------------------------------------------------------------------------- +| +| Here you can specify the colors used in your project. To get you started, +| we've provided a generous palette of great looking colors that are perfect +| for prototyping, but don't hesitate to change them for your project. You +| own these colors, nothing will break if you change everything about them. +| +| We've used literal color names ("red", "blue", etc.) for the default +| palette, but if you'd rather use functional names like "primary" and +| "secondary", or even a numeric scale like "100" and "200", go for it. +| +*/ + +var colors = { + 'transparent': 'transparent', + + 'black': '#222b2f', + 'grey-darkest': '#364349', + 'grey-darker': '#596a73', + 'grey-dark': '#70818a', + 'grey': '#9babb4', + 'grey-light': '#dae4e9', + 'grey-lighter': '#f3f7f9', + 'grey-lightest': '#fafcfc', + 'white': '#ffffff', + + 'red-darkest': '#420806', + 'red-darker': '#6a1b19', + 'red-dark': '#cc1f1a', + 'red': '#e3342f', + 'red-light': '#ef5753', + 'red-lighter': '#f9acaa', + 'red-lightest': '#fcebea', + + 'orange-darkest': '#542605', + 'orange-darker': '#7f4012', + 'orange-dark': '#de751f', + 'orange': '#f6993f', + 'orange-light': '#faad63', + 'orange-lighter': '#fcd9b6', + 'orange-lightest': '#fff5eb', + + 'yellow-darkest': '#453411', + 'yellow-darker': '#684f1d', + 'yellow-dark': '#f2d024', + 'yellow': '#ffed4a', + 'yellow-light': '#fff382', + 'yellow-lighter': '#fff9c2', + 'yellow-lightest': '#fcfbeb', + + 'green-darkest': '#032d19', + 'green-darker': '#0b4228', + 'green-dark': '#1f9d55', + 'green': '#38c172', + 'green-light': '#51d88a', + 'green-lighter': '#a2f5bf', + 'green-lightest': '#e3fcec', + + 'teal-darkest': '#0d3331', + 'teal-darker': '#174e4b', + 'teal-dark': '#38a89d', + 'teal': '#4dc0b5', + 'teal-light': '#64d5ca', + 'teal-lighter': '#a0f0ed', + 'teal-lightest': '#e8fffe', + + 'blue-darkest': '#05233b', + 'blue-darker': '#103d60', + 'blue-dark': '#2779bd', + 'blue': '#3490dc', + 'blue-light': '#6cb2eb', + 'blue-lighter': '#bcdefa', + 'blue-lightest': '#eff8ff', + + 'indigo-darkest': '#191e38', + 'indigo-darker': '#2f365f', + 'indigo-dark': '#5661b3', + 'indigo': '#6574cd', + 'indigo-light': '#7886d7', + 'indigo-lighter': '#b2b7ff', + 'indigo-lightest': '#e6e8ff', + + 'purple-darkest': '#1f133f', + 'purple-darker': '#352465', + 'purple-dark': '#794acf', + 'purple': '#9561e2', + 'purple-light': '#a779e9', + 'purple-lighter': '#d6bbfc', + 'purple-lightest': '#f3ebff', + + 'pink-darkest': '#45051e', + 'pink-darker': '#72173a', + 'pink-dark': '#eb5286', + 'pink': '#f66d9b', + 'pink-light': '#fa7ea8', + 'pink-lighter': '#ffbbca', + 'pink-lightest': '#ffebef' +} + +module.exports = { + + /* + |----------------------------------------------------------------------------- + | Colors https://tailwindcss.com/docs/colors + |----------------------------------------------------------------------------- + | + | The color palette defined above is also assigned to the "colors" key of + | your Tailwind config. This makes it easy to access them in your CSS + | using Tailwind's config helper. For example: + | + | .error { color: config('colors.red') } + | + */ + + colors: colors, + + /* + |----------------------------------------------------------------------------- + | Screens https://tailwindcss.com/docs/responsive-design + |----------------------------------------------------------------------------- + | + | Screens in Tailwind are translated to CSS media queries. They define the + | responsive breakpoints for your project. By default Tailwind takes a + | "mobile first" approach, where each screen size represents a minimum + | viewport width. Feel free to have as few or as many screens as you + | want, naming them in whatever way you'd prefer for your project. + | + | Tailwind also allows for more complex screen definitions, which can be + | useful in certain situations. Be sure to see the full responsive + | documentation for a complete list of options. + | + | Class name: .{screen}:{utility} + | + */ + + screens: { + 'sm': '576px', + 'md': '768px', + 'lg': '992px', + 'xl': '1200px' + }, + + /* + |----------------------------------------------------------------------------- + | Fonts https://tailwindcss.com/docs/fonts + |----------------------------------------------------------------------------- + | + | Here is where you define your project's font stack, or font families. + | Keep in mind that Tailwind doesn't actually load any fonts for you. + | If you're using custom fonts you'll need to import them prior to + | defining them here. + | + | By default we provide a native font stack that works remarkably well on + | any device or OS you're using, since it just uses the default fonts + | provided by the platform. + | + | Class name: .font-{name} + | + */ + + fonts: { + 'sans': [ + '-apple-system', + 'BlinkMacSystemFont', + 'Segoe UI', + 'Roboto', + 'Oxygen', + 'Ubuntu', + 'Cantarell', + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue' + ], + 'serif': [ + 'Constantia', + 'Lucida Bright', + 'Lucidabright', + 'Lucida Serif', + 'Lucida', + 'DejaVu Serif', + 'Bitstream Vera Serif', + 'Liberation Serif', + 'Georgia', + 'serif' + ], + 'mono': [ + 'Menlo', + 'Monaco', + 'Consolas', + 'Liberation Mono', + 'Courier New', + 'monospace' + ] + }, + + /* + |----------------------------------------------------------------------------- + | Text sizes https://tailwindcss.com/docs/text-sizing + |----------------------------------------------------------------------------- + | + | Here is where you define your text sizes. Name these in whatever way + | makes the most sense to you. We use size names by default, but + | you're welcome to use a numeric scale or even something else + | entirely. + | + | By default Tailwind uses the "rem" unit type for most measurements. + | This allows you to set a root font size which all other sizes are + | then based on. That said, you are free to use whatever units you + | prefer, be it rems, ems, pixels or other. + | + | Class name: .text-{size} + | + */ + + textSizes: { + 'xs': '.75rem', // 12px + 'sm': '.875rem', // 14px + 'base': '1rem', // 16px + 'lg': '1.125rem', // 18px + 'xl': '1.25rem', // 20px + '2xl': '1.5rem', // 24px + '3xl': '1.875rem', // 30px + '4xl': '2.25rem', // 36px + '5xl': '3rem' // 48px + }, + + /* + |----------------------------------------------------------------------------- + | Font weights https://tailwindcss.com/docs/font-weight + |----------------------------------------------------------------------------- + | + | Here is where you define your font weights. We've provided a list of + | common font weight names with their respective numeric scale values + | to get you started. It's unlikely that your project will require + | all of these, so we recommend removing those you don't need. + | + | Class name: .font-{weight} + | + */ + + fontWeights: { + 'hairline': 100, + 'thin': 200, + 'light': 300, + 'normal': 400, + 'medium': 500, + 'semibold': 600, + 'bold': 700, + 'extrabold': 800, + 'black': 900 + }, + + /* + |----------------------------------------------------------------------------- + | Leading (line height) https://tailwindcss.com/docs/line-height + |----------------------------------------------------------------------------- + | + | Here is where you define your line height values, or as we call + | them in Tailwind, leadings. + | + | Class name: .leading-{size} + | + */ + + leading: { + 'none': 1, + 'tight': 1.25, + 'normal': 1.5, + 'loose': 2 + }, + + /* + |----------------------------------------------------------------------------- + | Tracking (letter spacing) https://tailwindcss.com/docs/letter-spacing + |----------------------------------------------------------------------------- + | + | Here is where you define your letter spacing values, or as we call + | them in Tailwind, tracking. + | + | Class name: .tracking-{size} + | + */ + + tracking: { + 'tight': '-0.05em', + 'normal': '0', + 'wide': '0.05em' + }, + + /* + |----------------------------------------------------------------------------- + | Text colors https://tailwindcss.com/docs/text-color + |----------------------------------------------------------------------------- + | + | Here is where you define your text colors. By default these use the + | color palette we defined above, however you're welcome to set these + | independently if that makes sense for your project. + | + | Class name: .text-{color} + | + */ + + textColors: colors, + + /* + |----------------------------------------------------------------------------- + | Background colors https://tailwindcss.com/docs/background-color + |----------------------------------------------------------------------------- + | + | Here is where you define your background colors. By default these use + | the color palette we defined above, however you're welcome to set + | these independently if that makes sense for your project. + | + | Class name: .bg-{color} + | + */ + + backgroundColors: colors, + + /* + |----------------------------------------------------------------------------- + | Border widths https://tailwindcss.com/docs/border-width + |----------------------------------------------------------------------------- + | + | Here is where you define your border widths. Take note that border + | widths require a special "default" value set as well. This is the + | width that will be used when you do not specify a border width. + | + | Class name: .border{-side?}{-width?} + | + */ + + borderWidths: { + default: '1px', + '0': '0', + '2': '2px', + '4': '4px', + '8': '8px' + }, + + /* + |----------------------------------------------------------------------------- + | Border colors https://tailwindcss.com/docs/border-color + |----------------------------------------------------------------------------- + | + | Here is where you define your border colors. By default these use the + | color palette we defined above, however you're welcome to set these + | independently if that makes sense for your project. + | + | Take note that border colors require a special "default" value set + | as well. This is the color that will be used when you do not + | specify a border color. + | + | Class name: .border-{color} + | + */ + + borderColors: Object.assign({ default: colors['grey-light'] }, colors), + + /* + |----------------------------------------------------------------------------- + | Border radius https://tailwindcss.com/docs/border-radius + |----------------------------------------------------------------------------- + | + | Here is where you define your border radius values. If a `default` radius + | is provided, it will be made available as the non-suffixed `.rounded` + | utility. + | + | Class name: .rounded{-radius?} + | + */ + + borderRadius: { + default: '.25rem', + 'sm': '.125rem', + 'lg': '.5rem', + 'full': '9999px', + 'none': '0' + }, + + /* + |----------------------------------------------------------------------------- + | Width https://tailwindcss.com/docs/width + |----------------------------------------------------------------------------- + | + | Here is where you define your width utility sizes. These can be + | percentage based, pixels, rems, or any other units. By default + | we provide a sensible rem based numeric scale, a percentage + | based fraction scale, plus some other common use-cases. You + | can, of course, modify these values as needed. + | + | + | It's also worth mentioning that Tailwind automatically escapes + | invalid CSS class name characters, which allows you to have + | awesome classes like .w-2/3. + | + | Class name: .w-{size} + | + */ + + width: { + 'auto': 'auto', + 'px': '1px', + '1': '0.25rem', + '2': '0.5rem', + '3': '0.75rem', + '4': '1rem', + '6': '1.5rem', + '8': '2rem', + '10': '2.5rem', + '12': '3rem', + '16': '4rem', + '24': '6rem', + '32': '8rem', + '48': '12rem', + '64': '16rem', + '1/2': '50%', + '1/3': '33.33333%', + '2/3': '66.66667%', + '1/4': '25%', + '3/4': '75%', + '1/5': '20%', + '2/5': '40%', + '3/5': '60%', + '4/5': '80%', + '1/6': '16.66667%', + '5/6': '83.33333%', + 'full': '100%', + 'screen': '100vw' + }, + + /* + |----------------------------------------------------------------------------- + | Height https://tailwindcss.com/docs/height + |----------------------------------------------------------------------------- + | + | Here is where you define your height utility sizes. These can be + | percentage based, pixels, rems, or any other units. By default + | we provide a sensible rem based numeric scale plus some other + | common use-cases. You can, of course, modify these values as + | needed. + | + | Class name: .h-{size} + | + */ + + height: { + 'auto': 'auto', + 'px': '1px', + '1': '0.25rem', + '2': '0.5rem', + '3': '0.75rem', + '4': '1rem', + '6': '1.5rem', + '8': '2rem', + '10': '2.5rem', + '12': '3rem', + '16': '4rem', + '24': '6rem', + '32': '8rem', + '48': '12rem', + '64': '16rem', + 'full': '100%', + 'screen': '100vh' + }, + + /* + |----------------------------------------------------------------------------- + | Minimum width https://tailwindcss.com/docs/min-width + |----------------------------------------------------------------------------- + | + | Here is where you define your minimum width utility sizes. These can + | be percentage based, pixels, rems, or any other units. We provide a + | couple common use-cases by default. You can, of course, modify + | these values as needed. + | + | Class name: .min-w-{size} + | + */ + + minWidth: { + '0': '0', + 'full': '100%' + }, + + /* + |----------------------------------------------------------------------------- + | Minimum height https://tailwindcss.com/docs/min-height + |----------------------------------------------------------------------------- + | + | Here is where you define your minimum height utility sizes. These can + | be percentage based, pixels, rems, or any other units. We provide a + | few common use-cases by default. You can, of course, modify these + | values as needed. + | + | Class name: .min-h-{size} + | + */ + + minHeight: { + '0': '0', + 'full': '100%', + 'screen': '100vh' + }, + + /* + |----------------------------------------------------------------------------- + | Maximum width https://tailwindcss.com/docs/max-width + |----------------------------------------------------------------------------- + | + | Here is where you define your maximum width utility sizes. These can + | be percentage based, pixels, rems, or any other units. By default + | we provide a sensible rem based scale and a "full width" size, + | which is basically a reset utility. You can, of course, + | modify these values as needed. + | + | Class name: .max-w-{size} + | + */ + + maxWidth: { + 'xs': '20rem', + 'sm': '30rem', + 'md': '40rem', + 'lg': '50rem', + 'xl': '60rem', + '2xl': '70rem', + '3xl': '80rem', + '4xl': '90rem', + '5xl': '100rem', + 'full': '100%' + }, + + /* + |----------------------------------------------------------------------------- + | Maximum height https://tailwindcss.com/docs/max-height + |----------------------------------------------------------------------------- + | + | Here is where you define your maximum height utility sizes. These can + | be percentage based, pixels, rems, or any other units. We provide a + | couple common use-cases by default. You can, of course, modify + | these values as needed. + | + | Class name: .max-h-{size} + | + */ + + maxHeight: { + 'full': '100%', + 'screen': '100vh' + }, + + /* + |----------------------------------------------------------------------------- + | Padding https://tailwindcss.com/docs/padding + |----------------------------------------------------------------------------- + | + | Here is where you define your padding utility sizes. These can be + | percentage based, pixels, rems, or any other units. By default we + | provide a sensible rem based numeric scale plus a couple other + | common use-cases like "1px". You can, of course, modify these + | values as needed. + | + | Class name: .p{side?}-{size} + | + */ + + padding: { + 'px': '1px', + '0': '0', + '1': '0.25rem', + '2': '0.5rem', + '3': '0.75rem', + '4': '1rem', + '6': '1.5rem', + '8': '2rem' + }, + + /* + |----------------------------------------------------------------------------- + | Margin https://tailwindcss.com/docs/margin + |----------------------------------------------------------------------------- + | + | Here is where you define your margin utility sizes. These can be + | percentage based, pixels, rems, or any other units. By default we + | provide a sensible rem based numeric scale plus a couple other + | common use-cases like "1px". You can, of course, modify these + | values as needed. + | + | Class name: .m{side?}-{size} + | + */ + + margin: { + 'px': '1px', + '0': '0', + '1': '0.25rem', + '2': '0.5rem', + '3': '0.75rem', + '4': '1rem', + '6': '1.5rem', + '8': '2rem' + }, + + /* + |----------------------------------------------------------------------------- + | Negative margin https://tailwindcss.com/docs/negative-margin + |----------------------------------------------------------------------------- + | + | Here is where you define your negative margin utility sizes. These can + | be percentage based, pixels, rems, or any other units. By default we + | provide matching values to the padding scale since these utilities + | generally get used together. You can, of course, modify these + | values as needed. + | + | Class name: .-m{side?}-{size} + | + */ + + negativeMargin: { + 'px': '1px', + '0': '0', + '1': '0.25rem', + '2': '0.5rem', + '3': '0.75rem', + '4': '1rem', + '6': '1.5rem', + '8': '2rem' + }, + + /* + |----------------------------------------------------------------------------- + | Shadows https://tailwindcss.com/docs/shadows + |----------------------------------------------------------------------------- + | + | Here is where you define your shadow utilities. As you can see from + | the defaults we provide, it's possible to apply multiple shadows + | per utility using comma separation. + | + | If a `default` shadow is provided, it will be made available as the non- + | suffixed `.shadow` utility. + | + | Class name: .shadow-{size?} + | + */ + + shadows: { + default: '0 2px 4px 0 rgba(0,0,0,0.10)', + 'md': '0 4px 8px 0 rgba(0,0,0,0.12), 0 2px 4px 0 rgba(0,0,0,0.08)', + 'lg': '0 15px 30px 0 rgba(0,0,0,0.11), 0 5px 15px 0 rgba(0,0,0,0.08)', + 'inner': 'inset 0 2px 4px 0 rgba(0,0,0,0.06)', + 'none': 'none' + }, + + /* + |----------------------------------------------------------------------------- + | Z-index https://tailwindcss.com/docs/z-index + |----------------------------------------------------------------------------- + | + | Here is where you define your z-index utility values. By default we + | provide a sensible numeric scale. You can, of course, modify these + | values as needed. + | + | Class name: .z-{index} + | + */ + + zIndex: { + '0': 0, + '10': 10, + '20': 20, + '30': 30, + '40': 40, + '50': 50, + 'auto': 'auto' + }, + + /* + |----------------------------------------------------------------------------- + | Opacity https://tailwindcss.com/docs/opacity + |----------------------------------------------------------------------------- + | + | Here is where you define your opacity utility values. By default we + | provide a sensible numeric scale. You can, of course, modify these + | values as needed. + | + | Class name: .opacity-{name} + | + */ + + opacity: { + '0': '0', + '25': '.25', + '50': '.5', + '75': '.75', + '100': '1' + }, + + /* + |----------------------------------------------------------------------------- + | Packages + |----------------------------------------------------------------------------- + | + | Here is where you can define the configuration for any Tailwind packages + | you're using. These can be utility packs, component bundles, or even + | complete themes. You'll want to reference each package's + | documentation for a list of settings available for it. + | + */ + + packages: { + } + +} diff --git a/examples/with-vux/layouts/default.vue b/examples/with-vux/layouts/default.vue new file mode 100644 index 0000000000..cc972b0ae7 --- /dev/null +++ b/examples/with-vux/layouts/default.vue @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/examples/with-vux/nuxt.config.js b/examples/with-vux/nuxt.config.js new file mode 100644 index 0000000000..ff07ba04b9 --- /dev/null +++ b/examples/with-vux/nuxt.config.js @@ -0,0 +1,39 @@ +const vuxLoader = require('vux-loader') +const path = require('path') + +module.exports = { + head: { + meta: [ + { charset: 'utf-8' }, + { name: 'viewport', content: 'width=device-width, initial-scale=1, user-scalable=0' } + ] + }, + css: [ + 'vux/src/styles/reset.less', + 'vux/src/styles/1px.less' + ], + plugins: [ + { + src: '~/plugins/vux-plugins', + ssr: false + }, + { + src: '~/plugins/vux-components', + ssr: true + } + ], + build: { + extend(config, { isDev, isClient }) { + const configs = vuxLoader.merge(config, { + options: { + ssr: true + }, + plugins: ['vux-ui', { + name: 'less-theme', + path: path.join(__dirname, './styles/theme.less') + }] + }) + return configs + } + } +} diff --git a/examples/with-vux/package.json b/examples/with-vux/package.json new file mode 100644 index 0000000000..7684d25bd7 --- /dev/null +++ b/examples/with-vux/package.json @@ -0,0 +1,19 @@ +{ + "name": "with-vux", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "nuxt": "latest", + "vux": "^2.8.0" + }, + "scripts": { + "dev": "nuxt", + "build": "nuxt build", + "start": "nuxt start" + }, + "devDependencies": { + "less": "^2.7.3", + "less-loader": "^4.0.6", + "vux-loader": "^1.2.1" + } +} diff --git a/examples/with-vux/pages/index.vue b/examples/with-vux/pages/index.vue new file mode 100644 index 0000000000..5d16695816 --- /dev/null +++ b/examples/with-vux/pages/index.vue @@ -0,0 +1,23 @@ + + + + \ No newline at end of file diff --git a/examples/with-vux/plugins/vux-components.js b/examples/with-vux/plugins/vux-components.js new file mode 100644 index 0000000000..b6a978aa8e --- /dev/null +++ b/examples/with-vux/plugins/vux-components.js @@ -0,0 +1,5 @@ +import Vue from 'vue' +import { Group, Cell } from 'vux' + +Vue.component('group', Group) +Vue.component('cell', Cell) diff --git a/examples/with-vux/plugins/vux-plugins.js b/examples/with-vux/plugins/vux-plugins.js new file mode 100644 index 0000000000..ff22a2598e --- /dev/null +++ b/examples/with-vux/plugins/vux-plugins.js @@ -0,0 +1,12 @@ +import Vue from 'vue' +import { BusPlugin, TransferDom, WechatPlugin, DatetimePlugin, LoadingPlugin, ToastPlugin, AlertPlugin, ConfirmPlugin } from 'vux' + +Vue.use(DatetimePlugin) +Vue.use(LoadingPlugin) +Vue.use(ToastPlugin) +Vue.use(AlertPlugin) +Vue.use(ConfirmPlugin) +Vue.use(WechatPlugin) +Vue.use(BusPlugin) + +Vue.directive('transfer-dom', TransferDom) diff --git a/examples/with-vux/styles/theme.less b/examples/with-vux/styles/theme.less new file mode 100644 index 0000000000..88c363007e --- /dev/null +++ b/examples/with-vux/styles/theme.less @@ -0,0 +1 @@ +@dialog-button-text-primary-color: #FF9900; \ No newline at end of file diff --git a/lib/app/index.js b/lib/app/index.js index 1a2d79fed8..7ba2b65132 100644 --- a/lib/app/index.js +++ b/lib/app/index.js @@ -44,10 +44,10 @@ const defaultTransition = <%= %> async function createApp (ssrContext) { - const router = createRouter() + const router = createRouter(ssrContext) <% if (store) { %> - const store = createStore() + const store = createStore(ssrContext) // Add this.$router into store actions/mutations store.$router = router <% } %> diff --git a/lib/app/router.js b/lib/app/router.js index 47c0f653d9..802c390d3c 100644 --- a/lib/app/router.js +++ b/lib/app/router.js @@ -53,9 +53,20 @@ const scrollBehavior = function (to, from, savedPosition) { window.$nuxt.$once('triggerScroll', () => { // coords will be used if no selector is provided, // or if the selector didn't match any element. - if (to.hash && document.querySelector(to.hash)) { - // scroll to anchor by returning the selector - position = { selector: to.hash } + if (to.hash) { + let hash = to.hash + // CSS.escape() is not supported with IE and Edge. + if (typeof window.CSS !== 'undefined' && typeof window.CSS.escape !== 'undefined') { + hash = '#' + window.CSS.escape(hash.substr(1)) + } + try { + if (document.querySelector(hash)) { + // scroll to anchor by returning the selector + position = { selector: hash } + } + } catch (e) { + console.warn('Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).') + } } resolve(position) }) diff --git a/lib/builder/builder.js b/lib/builder/builder.js index 484c7b0100..3f5a6fe2e7 100644 --- a/lib/builder/builder.js +++ b/lib/builder/builder.js @@ -161,14 +161,7 @@ module.exports = class Builder { } getBabelOptions({ isServer }) { - const options = _.defaults( - {}, - { - babelrc: false, - cacheDirectory: !!this.options.dev - }, - this.options.build.babel - ) + const options = _.clone(this.options.build.babel) if (typeof options.presets === 'function') { options.presets = options.presets({ isServer }) @@ -305,7 +298,7 @@ module.exports = class Builder { })).forEach(f => { const key = f.replace(/\.(js|vue)$/, '') if (/\.vue$/.test(f) || !files[key]) { - files[key] = f + files[key] = f.replace(/(['|"])/g, '\\$1') } }) templateVars.router.routes = createRoutes( diff --git a/lib/common/options.js b/lib/common/options.js index 03d31b874b..c905f84584 100644 --- a/lib/common/options.js +++ b/lib/common/options.js @@ -1,7 +1,7 @@ const _ = require('lodash') const Debug = require('debug') const { join, resolve } = require('path') -const { existsSync } = require('fs') +const { existsSync, readdirSync } = require('fs') const { isUrl, isPureObject } = require('../common/utils') const debug = Debug('nuxt:build') @@ -85,7 +85,12 @@ Options.from = function (_options) { } // If store defined, update store options to true unless explicitly disabled - if (options.store !== false && existsSync(join(options.srcDir, options.dir.store))) { + if ( + options.store !== false && + existsSync(join(options.srcDir, options.dir.store)) && + readdirSync(join(options.srcDir, options.dir.store)) + .find(filename => filename !== 'README.md' && filename[0] !== '.') + ) { options.store = true } @@ -114,6 +119,11 @@ Options.from = function (_options) { options.build.cssSourceMap = options.dev } + // babel cacheDirectory + if (options.build.babel.cacheDirectory === undefined) { + options.build.babel.cacheDirectory = options.dev + } + // Debug errors if (options.debug === undefined) { options.debug = options.dev @@ -203,7 +213,9 @@ Options.defaults = { styleResources: {}, vendor: [], plugins: [], - babel: {}, + babel: { + babelrc: false + }, postcss: {}, templates: [], watch: [], diff --git a/lib/core/middleware/error.js b/lib/core/middleware/error.js index 52e2603ea6..53b6b8f180 100644 --- a/lib/core/middleware/error.js +++ b/lib/core/middleware/error.js @@ -74,6 +74,7 @@ async function readSource(frame) { frame.fileName = sanitizeName(frame.fileName) // Return if fileName is unknown + /* istanbul ignore if */ if (!frame.fileName) { return } diff --git a/lib/core/middleware/nuxt.js b/lib/core/middleware/nuxt.js index 7a7b7ed07e..b2eb7c8939 100644 --- a/lib/core/middleware/nuxt.js +++ b/lib/core/middleware/nuxt.js @@ -69,7 +69,7 @@ module.exports = async function nuxtMiddleware(req, res, next) { if (this.options.render.csp && this.options.render.csp.enabled) { const allowedSources = this.options.render.csp.allowedSources - const policies = this.options.render.csp.policies ? {...this.options.render.csp.policies} : null + const policies = this.options.render.csp.policies let cspStr = `script-src 'self' ${(cspScriptSrcHashes).join(' ')}` if (Array.isArray(allowedSources)) { // For compatible section diff --git a/lib/core/renderer.js b/lib/core/renderer.js index aea3be7d60..4f83e94554 100644 --- a/lib/core/renderer.js +++ b/lib/core/renderer.js @@ -375,7 +375,7 @@ module.exports = class Renderer { ) } - APP += `` + APP += `` APP += context.renderScripts() APP += m.script.text({ body: true }) APP += m.noscript.text({ body: true }) @@ -421,8 +421,11 @@ module.exports = class Renderer { window.scrollTo = () => {} } } + const jsdomErrHandler = err => { throw err } if (opts.virtualConsole !== false) { options.virtualConsole = new jsdom.VirtualConsole().sendTo(console) + // throw error when window creation failed + options.virtualConsole.on('jsdomError', jsdomErrHandler) } url = url || 'http://localhost:3000' const { window } = await jsdom.JSDOM.fromURL(url, options) @@ -440,6 +443,10 @@ module.exports = class Renderer { await new Promise(resolve => { window._onNuxtLoaded = () => resolve(window) }) + if (opts.virtualConsole !== false) { + // after window initialized successfully + options.virtualConsole.removeListener('jsdomError', jsdomErrHandler) + } // Send back window object return window } diff --git a/package.json b/package.json index 2b64dda496..017d763338 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nuxt", - "version": "1.3.0", + "version": "1.4.0", "description": "A minimalistic framework for server-rendered Vue.js applications (inspired by Next.js)", "contributors": [ { diff --git a/test/cli.test.js b/test/cli.test.js index 9789882acd..0696de2c67 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -52,13 +52,17 @@ test.serial('nuxt start', async t => { exitCode = code }) - // Give the process max 10s to start + // Give the process max 20s to start let iterator = 0 - while (!stdout.includes('OPEN') && iterator < 40) { + while (!stdout.includes('OPEN') && iterator < 80) { await Utils.waitFor(250) iterator++ } + if (iterator === 80) { + t.log('WARN: server failed to start successfully in 20 seconds') + } + t.is(error, undefined) t.true(stdout.includes('OPEN'))