@nuxt/generator
Advanced tools
+217
-37
| /*! | ||
| * @nuxt/generator v2.12.2 (c) 2016-2020 | ||
| * @nuxt/generator v2.13.0 (c) 2016-2020 | ||
@@ -15,8 +15,71 @@ * - All the amazing contributors | ||
| const path = _interopDefault(require('path')); | ||
| const Chalk = _interopDefault(require('chalk')); | ||
| const chalk = _interopDefault(require('chalk')); | ||
| const consola = _interopDefault(require('consola')); | ||
| const fsExtra = _interopDefault(require('fs-extra')); | ||
| const htmlMinifier = _interopDefault(require('html-minifier')); | ||
| const nodeHtmlParser = require('node-html-parser'); | ||
| const utils = require('@nuxt/utils'); | ||
| function _typeof(obj) { | ||
| "@babel/helpers - typeof"; | ||
| if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { | ||
| _typeof = function (obj) { | ||
| return typeof obj; | ||
| }; | ||
| } else { | ||
| _typeof = function (obj) { | ||
| return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; | ||
| }; | ||
| } | ||
| return _typeof(obj); | ||
| } | ||
| function isObject(val) { | ||
| return val !== null && _typeof(val) === 'object' && !Array.isArray(val); | ||
| } | ||
| function _defu(baseObj, defaults) { | ||
| if (!isObject(baseObj)) { | ||
| return _defu({}, defaults); | ||
| } | ||
| if (!isObject(defaults)) { | ||
| return _defu(baseObj, {}); | ||
| } | ||
| var obj = Object.assign({}, defaults); | ||
| for (var key in baseObj) { | ||
| if (key === '__proto__' || key === 'constructor') { | ||
| continue; | ||
| } | ||
| var val = baseObj[key]; | ||
| if (val === null) { | ||
| continue; | ||
| } | ||
| if (isObject(val) && isObject(obj[key])) { | ||
| obj[key] = _defu(val, obj[key]); | ||
| } else { | ||
| obj[key] = val; | ||
| } | ||
| } | ||
| return obj; | ||
| } | ||
| function defu() { | ||
| for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
| args[_key] = arguments[_key]; | ||
| } | ||
| return args.reduce(_defu, {}); | ||
| } | ||
| var defu_1 = defu; | ||
| class Generator { | ||
@@ -27,2 +90,3 @@ constructor (nuxt, builder) { | ||
| this.builder = builder; | ||
| this.isFullStatic = false; | ||
@@ -37,2 +101,8 @@ // Set variables | ||
| ); | ||
| // Shared payload | ||
| this._payload = null; | ||
| this.setPayload = (payload) => { | ||
| this._payload = defu_1(payload, this._payload); | ||
| }; | ||
| } | ||
@@ -42,11 +112,16 @@ | ||
| consola.debug('Initializing generator...'); | ||
| await this.initiate({ build, init }); | ||
| // Payloads for full static | ||
| if (this.isFullStatic) { | ||
| consola.info('Full static mode activated'); | ||
| const { staticAssets } = this.options.generate; | ||
| this.staticAssetsDir = path.resolve(this.distNuxtPath, staticAssets.dir, staticAssets.version); | ||
| this.staticAssetsBase = this.options.generate.staticAssets.versionBase; | ||
| } | ||
| consola.debug('Preparing routes for generate...'); | ||
| const routes = await this.initRoutes(); | ||
| consola.info('Generating pages'); | ||
| const errors = await this.generateRoutes(routes); | ||
@@ -58,2 +133,3 @@ | ||
| await this.nuxt.callHook('generate:done', this, errors); | ||
| await this.nuxt.callHook('export:done', this, { errors }); | ||
@@ -69,2 +145,3 @@ return { errors } | ||
| await this.nuxt.callHook('generate:before', this, this.options.generate); | ||
| await this.nuxt.callHook('export:before', this); | ||
@@ -77,2 +154,19 @@ if (build) { | ||
| await this.builder.build(); | ||
| this.isFullStatic = utils.isFullStatic(this.options); | ||
| } else { | ||
| const hasBuilt = await fsExtra.exists(path.resolve(this.options.buildDir, 'dist', 'server', 'client.manifest.json')); | ||
| if (!hasBuilt) { | ||
| const fullStaticArgs = utils.isFullStatic(this.options) ? ' --target static' : ''; | ||
| throw new Error( | ||
| `No build files found in ${this.srcBuiltPath}.\nPlease run \`nuxt build${fullStaticArgs}\` before calling \`nuxt export\`` | ||
| ) | ||
| } | ||
| const config = this.getBuildConfig(); | ||
| if (!config || (config.target !== utils.TARGETS.static && !this.options._legacyGenerate)) { | ||
| throw new Error( | ||
| `In order to use \`nuxt export\`, you need to run \`nuxt build --target static\`` | ||
| ) | ||
| } | ||
| this.isFullStatic = config.isFullStatic; | ||
| this.options.render.ssr = config.ssr; | ||
| } | ||
@@ -100,10 +194,10 @@ | ||
| } | ||
| // Generate only index.html for router.mode = 'hash' | ||
| let routes = | ||
| this.options.router.mode === 'hash' | ||
| ? ['/'] | ||
| : utils.flatRoutes(this.options.router.routes); | ||
| routes = routes.filter(route => this.options.generate.exclude.every(regex => !regex.test(route))); | ||
| let routes = []; | ||
| // Generate only index.html for router.mode = 'hash' or client-side apps | ||
| if (this.options.router.mode === 'hash') { | ||
| routes = ['/']; | ||
| } else { | ||
| routes = utils.flatRoutes(this.getAppRoutes()); | ||
| } | ||
| routes = routes.filter(route => this.shouldGenerateRoute(route)); | ||
| routes = this.decorateWithPayloads(routes, generateRoutes); | ||
@@ -113,2 +207,3 @@ | ||
| await this.nuxt.callHook('generate:extendRoutes', routes); | ||
| await this.nuxt.callHook('export:extendRoutes', { routes }); | ||
@@ -118,10 +213,41 @@ return routes | ||
| shouldGenerateRoute (route) { | ||
| return this.options.generate.exclude.every((regex) => { | ||
| if (typeof regex === 'string') { | ||
| return regex !== route | ||
| } | ||
| return !regex.test(route) | ||
| }) | ||
| } | ||
| getBuildConfig () { | ||
| try { | ||
| return require(path.join(this.options.buildDir, 'nuxt/config.json')) | ||
| } catch (err) { | ||
| return null | ||
| } | ||
| } | ||
| getAppRoutes () { | ||
| return require(path.join(this.options.buildDir, 'routes.json')) | ||
| } | ||
| async generateRoutes (routes) { | ||
| const errors = []; | ||
| this.routes = []; | ||
| this.generatedRoutes = new Set(); | ||
| routes.forEach(({ route, ...props }) => { | ||
| route = decodeURI(route); | ||
| this.routes.push({ route, ...props }); | ||
| // Add routes to the tracked generated routes (for crawler) | ||
| this.generatedRoutes.add(route); | ||
| }); | ||
| // Start generate process | ||
| while (routes.length) { | ||
| while (this.routes.length) { | ||
| let n = 0; | ||
| await Promise.all( | ||
| routes | ||
| this.routes | ||
| .splice(0, this.options.generate.concurrency) | ||
@@ -148,8 +274,8 @@ .map(async ({ route, payload }) => { | ||
| let line = Chalk[color](` ${route}\n\n`); | ||
| let line = chalk[color](` ${route}\n\n`); | ||
| if (isHandled) { | ||
| line += Chalk.grey(JSON.stringify(error, undefined, 2) + '\n'); | ||
| line += chalk.grey(JSON.stringify(error, undefined, 2) + '\n'); | ||
| } else { | ||
| line += Chalk.grey(error.stack || error.message || `${error}`); | ||
| line += chalk.grey(error.stack || error.message || `${error}`); | ||
| } | ||
@@ -179,3 +305,6 @@ | ||
| // Render and write the SPA template to the fallback path | ||
| let { html } = await this.nuxt.server.renderRoute('/', { spa: true }); | ||
| let { html } = await this.nuxt.server.renderRoute('/', { | ||
| spa: true, | ||
| staticAssetsBase: this.staticAssetsBase | ||
| }); | ||
@@ -189,2 +318,3 @@ try { | ||
| await fsExtra.writeFile(fallbackPath, html, 'utf8'); | ||
| consola.success('Client-side fallback created: `' + fallback + '`'); | ||
| } | ||
@@ -194,5 +324,7 @@ | ||
| // Clean destination folder | ||
| await fsExtra.remove(this.distPath); | ||
| await fsExtra.emptyDir(this.distPath); | ||
| consola.info(`Generating output directory: ${path.basename(this.distPath)}/`); | ||
| await this.nuxt.callHook('generate:distRemoved', this); | ||
| await this.nuxt.callHook('export:distRemoved', this); | ||
@@ -203,4 +335,9 @@ // Copy static and built files | ||
| } | ||
| // Copy .nuxt/dist/client/ to dist/_nuxt/ | ||
| await fsExtra.copy(this.srcBuiltPath, this.distNuxtPath); | ||
| if (this.payloadDir) { | ||
| await fsExtra.ensureDir(this.payloadDir); | ||
| } | ||
| // Add .nojekyll file to let GitHub Pages add the _nuxt/ folder | ||
@@ -212,2 +349,3 @@ // https://help.github.com/articles/files-that-start-with-an-underscore-are-missing/ | ||
| await this.nuxt.callHook('generate:distCopied', this); | ||
| await this.nuxt.callHook('export:distCopied', this); | ||
| } | ||
@@ -237,8 +375,51 @@ | ||
| const setPayload = (_payload) => { | ||
| payload = defu_1(_payload, payload); | ||
| }; | ||
| // Apply shared payload | ||
| if (this._payload) { | ||
| payload = defu_1(payload, this._payload); | ||
| } | ||
| await this.nuxt.callHook('generate:route', { route, setPayload }); | ||
| await this.nuxt.callHook('export:route', { route, setPayload }); | ||
| try { | ||
| const res = await this.nuxt.server.renderRoute(route, { | ||
| _generate: true, | ||
| payload | ||
| }) | ||
| ;({ html } = res); | ||
| const renderContext = { | ||
| payload, | ||
| staticAssetsBase: this.staticAssetsBase | ||
| }; | ||
| const res = await this.nuxt.server.renderRoute(route, renderContext); | ||
| html = res.html; | ||
| // If crawler activated and called from generateRoutes() | ||
| if (this.options.generate.crawler && this.options.render.ssr) { | ||
| const possibleTrailingSlash = this.options.router.trailingSlash ? '/' : ''; | ||
| nodeHtmlParser.parse(html).querySelectorAll('a').map((el) => { | ||
| const sanitizedHref = (el.getAttribute('href') || '') | ||
| .replace(this.options.router.base, '/') | ||
| .replace(/\/+$/, '') | ||
| .split('?')[0] | ||
| .split('#')[0] | ||
| .trim(); | ||
| const route = decodeURI(sanitizedHref + possibleTrailingSlash); | ||
| if (route.startsWith('/') && !path.extname(route) && this.shouldGenerateRoute(route) && !this.generatedRoutes.has(route)) { | ||
| this.generatedRoutes.add(route); | ||
| this.routes.push({ route }); | ||
| } | ||
| }); | ||
| } | ||
| // Save Static Assets | ||
| if (this.staticAssetsDir && renderContext.staticAssets) { | ||
| for (const asset of renderContext.staticAssets) { | ||
| const assetPath = path.join(this.staticAssetsDir, asset.path); | ||
| await fsExtra.ensureDir(path.dirname(assetPath)); | ||
| await fsExtra.writeFile(assetPath, asset.src, 'utf-8'); | ||
| } | ||
| } | ||
| if (res.error) { | ||
@@ -251,6 +432,4 @@ pageErrors.push({ type: 'handled', route, error: res.error }); | ||
| await this.nuxt.callHook('generate:routeFailed', { | ||
| route, | ||
| errors: pageErrors | ||
| }); | ||
| await this.nuxt.callHook('generate:routeFailed', { route, errors: pageErrors }); | ||
| await this.nuxt.callHook('export:routeFailed', { route, errors: pageErrors }); | ||
| consola.error(this._formatErrors(pageErrors)); | ||
@@ -281,5 +460,9 @@ | ||
| // Call hook to let user update the path & html | ||
| const page = { route, path: fileName, html }; | ||
| const page = { route, path: fileName, html, exclude: false }; | ||
| await this.nuxt.callHook('generate:page', page); | ||
| await this.nuxt.callHook('export:page', { page, errors: pageErrors }); | ||
| if (page.exclude) { | ||
| return false | ||
| } | ||
| page.path = path.join(this.distPath, page.path); | ||
@@ -291,13 +474,10 @@ | ||
| await this.nuxt.callHook('generate:routeCreated', { | ||
| route, | ||
| path: page.path, | ||
| errors: pageErrors | ||
| }); | ||
| await this.nuxt.callHook('generate:routeCreated', { route, path: page.path, errors: pageErrors }); | ||
| await this.nuxt.callHook('export:routeCreated', { route, path: page.path, errors: pageErrors }); | ||
| if (pageErrors.length) { | ||
| consola.error('Error generating ' + route); | ||
| consola.error(`Error generating route "${route}": ${pageErrors.map(e => e.error.message).join(', ')}`); | ||
| errors.push(...pageErrors); | ||
| } else { | ||
| consola.success('Generated ' + route); | ||
| consola.success(`Generated route "${route}"`); | ||
| } | ||
@@ -304,0 +484,0 @@ |
+5
-4
| { | ||
| "name": "@nuxt/generator", | ||
| "version": "2.12.2", | ||
| "version": "2.13.0", | ||
| "repository": "nuxt/nuxt.js", | ||
@@ -11,7 +11,8 @@ "license": "MIT", | ||
| "dependencies": { | ||
| "@nuxt/utils": "2.12.2", | ||
| "@nuxt/utils": "2.13.0", | ||
| "chalk": "^3.0.0", | ||
| "consola": "^2.11.3", | ||
| "consola": "^2.13.0", | ||
| "fs-extra": "^8.1.0", | ||
| "html-minifier": "^4.0.0" | ||
| "html-minifier": "^4.0.0", | ||
| "node-html-parser": "^1.2.19" | ||
| }, | ||
@@ -18,0 +19,0 @@ "publishConfig": { |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
15562
64.76%401
62.35%6
20%5
66.67%+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
Updated
Updated