From a0e9cdd3a86432d603d1d92c4f98686e7c0eaee2 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Fri, 22 Sep 2017 10:14:03 +0200 Subject: [PATCH 01/18] chore(module): extract plugins to separate files Separate the md `comp` import plugin template to avoid later broken linting --- lib/module.js | 27 ++++++--- lib/plugins/importMdComps.template.js | 7 +++ lib/plugins/nuxtentBodyComponent.js | 17 ++++++ lib/{plugin.js => plugins/requestContent.js} | 64 ++++++-------------- 4 files changed, 63 insertions(+), 52 deletions(-) create mode 100644 lib/plugins/importMdComps.template.js create mode 100644 lib/plugins/nuxtentBodyComponent.js rename lib/{plugin.js => plugins/requestContent.js} (61%) diff --git a/lib/module.js b/lib/module.js index 11bea43..4509bbd 100644 --- a/lib/module.js +++ b/lib/module.js @@ -109,13 +109,26 @@ export default function ContentModule(moduleOpts) { } ]) - this.addPlugin({ - src: resolve(__dirname, 'plugin.js'), - options: { - ...options, - srcDirFromPlugin: join('~/', srcDir) - } - }) + // 4. Add import md comps plugin + + this.addPlugin({ + src: resolve(__dirname, 'plugins/importMdComps.template.js'), + options: { + srcDirFromPlugin: join('~/', srcDir) + } + }) + + // 4. Add content plugins + + this.addPlugin({ + src: resolve(__dirname, 'plugins/requestContent.js') + }) + + // 5. Add nuxtent-body component plugin + + this.addPlugin({ + src: resolve(__dirname, 'plugins/nuxtentBodyComponent.js') + }) } export { pkg as meta } diff --git a/lib/plugins/importMdComps.template.js b/lib/plugins/importMdComps.template.js new file mode 100644 index 0000000..6029d13 --- /dev/null +++ b/lib/plugins/importMdComps.template.js @@ -0,0 +1,7 @@ +function importAllMdComps (r) { + r.keys().forEach(key => r(key)) +} + +importAllMdComps( + require.context(<%= JSON.stringify(options.srcDirFromPlugin) %>, true, /\.comp\.md$/) +) diff --git a/lib/plugins/nuxtentBodyComponent.js b/lib/plugins/nuxtentBodyComponent.js new file mode 100644 index 0000000..b600443 --- /dev/null +++ b/lib/plugins/nuxtentBodyComponent.js @@ -0,0 +1,17 @@ +import Vue from 'vue' + +Vue.component('nuxtent-body', { + functional: true, + props: { + body: { required: true } + }, + render (h, ctx) { + const { body } = ctx.props + if (typeof body === 'object') { + const MarkdownComponent = mdComps[body.relativePath] + return + } else { + return
+ } + } +}) diff --git a/lib/plugin.js b/lib/plugins/requestContent.js similarity index 61% rename from lib/plugin.js rename to lib/plugins/requestContent.js index 7e7bd55..2617924 100644 --- a/lib/plugin.js +++ b/lib/plugins/requestContent.js @@ -1,46 +1,29 @@ -import Vue from 'vue' - const { join } = require('path') -const options = <%= JSON.stringify(options) %> -const mdComps = {} - -function importAllMdComps (r) { - r.keys().forEach(key => mdComps[key] = r(key)) -} +function toQuery (options = {}) { + let exclude = options.exclude + if (!exclude) return '' -importAllMdComps(require.context( - <%= JSON.stringify(options.srcDirFromPlugin) %>, true, /\.comp\.md$/ -)) + if (Array.isArray(exclude)) return 'exclude=' + exclude.join(',') -Vue.component('nuxtent-body', { - functional: true, - props: { - body: { required: true } - }, - render (h, ctx) { - const { body } = ctx.props - if (typeof body === 'object') { - const MarkdownComponent = mdComps[body.relativePath] - return ( ) - } else { - return (
) - } - } -}) + return 'exclude=' + exclude +} -export default ({ app, isServer, isClient, hotReload, route }) => { - const isNotContentReq = hotReload || route.fullPath.includes('__webpack_hmr?') || route.fullPath.includes('.hot-update.') +export default ({ app, isServer, isClient, isStatic, hotReload, route }) => { + const isNotContentReq = + hotReload || + route.fullPath.includes('__webpack_hmr?') || + route.fullPath.includes('.hot-update.') if (isNotContentReq) return - const isAPI = isServer || !options.isStatic + const isAPI = isServer || !isStatic const cache = {} async function fetchContent (path, permalink, query = '') { if (isAPI) { const apiEndpoint = join(path, permalink + query) - if (options.isDev || !cache[apiEndpoint]) { - cache[apiEndpoint] = (await app.$axios.get(apiEndpoint)).data + if (!isStatic || !cache[apiEndpoint]) { + cache[apiEndpoint] = (await app.$axios.get(apiEndpoint)).data } return cache[apiEndpoint] } else if (isClient) { @@ -51,21 +34,21 @@ export default ({ app, isServer, isClient, hotReload, route }) => { cache[browserPath] = (await app.$axios.get(browserPath)).data } return cache[browserPath] - } - else { - return // static server build + } else { + // static server build } } app.$content = function requestMethod (contentDir) { let query = '' return { - query (options) { // per page query + query (options = {}) { + // per page query query = toQuery(options) return this }, async get (permalink) { - if (typeof permalink !== 'string') throw Error(`Permalink must be a string.`) + if (typeof permalink !== 'string') { throw Error(`Permalink must be a string.`) } return await fetchContent(contentDir, permalink, '?' + query) }, async getBetween (permalink, num1or2, num2 = '') { @@ -87,12 +70,3 @@ export default ({ app, isServer, isClient, hotReload, route }) => { } } } - -function toQuery (options = {}) { - let exclude = options.exclude - if (!exclude) return '' - - if (Array.isArray(exclude)) return 'exclude=' + exclude.join(',') - - return 'exclude=' + exclude -} From bc5c373c036b6497b156a83ed4b1486bca48ca2d Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Fri, 22 Sep 2017 10:20:24 +0200 Subject: [PATCH 02/18] chore(lint): add `prettier-standard` on git precommit Add `git-exec-and-restage`, `husky`, `lint-staged` and `prettier-standard` devDependencies Add `standard-js` badge to README --- README.md | 2 ++ package.json | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/README.md b/README.md index dc83e19..657d62a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Nuxtent +[![js-standard-style](https://cdn.rawgit.com/standard/standard/master/badge.svg)](http://standardjs.com) + The goal of Nuxtent is to make using Nuxt for content heavy sites as easy as using Jekyll, Hugo, or any other static site generator. It does in two main ways: diff --git a/package.json b/package.json index 4ad0c03..499aca8 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,9 @@ "nuxtent": "bin/nuxtent" }, "scripts": { + "#": "handled by husky", + "precommit": "lint-staged", + "#": "handled by husky", "unit": "cross-env NODE_ENV=development karma start test/unit/karma.conf.js", "e2e": "cross-env NODE_ENV=test ava --verbose --serial test/e2e", "test": "npm run unit --single-run && npm run e2e", @@ -63,13 +66,17 @@ "chai": "^4.1.0", "cross-env": "^5.0.1", "express": "^4.15.3", + "git-exec-and-restage": "^1.0.1", + "husky": "^0.14.3", "jsdom": "^11.1.0", "karma": "^1.7.0", "karma-mocha": "^1.3.0", "karma-rollup-preprocessor": "^4.0.2", "karma-sinon-chai": "^1.3.1", + "lint-staged": "^4.2.1", "mocha": "^3.5.0", "nuxt": "^1.0.0-rc11", + "prettier-standard": "^6.0.0", "request-promise-native": "^1.0.4", "rollup": "^0.50.0", "rollup-plugin-babel": "^3.0.2", @@ -84,6 +91,11 @@ "sinon": "^3.0.0", "sinon-chai": "^2.12.0" }, + "lint-staged": { + "[!template].js": [ + "git-exec-and-restage prettier-standard" + ] + }, "ava": { "require": [ "babel-register" From a364f7206646b82ce6c95abff0073e8b7fb447d9 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Fri, 22 Sep 2017 10:29:12 +0200 Subject: [PATCH 03/18] chore(lint): lint all supported files --- docs/nuxt.config.js | 14 +- docs/nuxtent.config.js | 28 ++- examples/content-navigation/nuxt.config.js | 6 +- examples/content-navigation/nuxtent.config.js | 2 +- examples/custom-build/nuxt.config.js | 6 +- examples/custom-build/nuxtent.config.js | 20 +- examples/i18n/nuxt.config.js | 4 +- examples/i18n/nuxtent.config.js | 5 +- examples/markdown-components/nuxt.config.js | 4 +- .../markdown-components/nuxtent.config.js | 2 +- .../multiple-content-types/nuxt.config.js | 4 +- .../multiple-content-types/nuxtent.config.js | 28 ++- examples/single-content-type/nuxt.config.js | 10 +- examples/sitemap/nuxt.config.js | 16 +- index.js | 6 +- lib/content/api.js | 29 ++- lib/content/build.js | 36 +-- lib/content/database.js | 31 +-- lib/content/page.js | 53 +++-- lib/loader.js | 26 ++- lib/module.js | 207 +++++++++--------- lib/plugins/requestContent.js | 6 +- lib/util/parsers.js | 15 +- test/e2e/complex.test.js | 36 ++- test/e2e/simple.test.js | 14 +- test/fixtures/nuxt.config.js | 6 +- test/fixtures/nuxt.js | 18 +- test/unit/karma.conf.js | 38 ++-- test/unit/specs/database.spec.js | 1 - 29 files changed, 371 insertions(+), 300 deletions(-) diff --git a/docs/nuxt.config.js b/docs/nuxt.config.js index f016b60..198663e 100644 --- a/docs/nuxt.config.js +++ b/docs/nuxt.config.js @@ -4,15 +4,15 @@ module.exports = { meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, - { hid: 'description', name: 'description', content: 'Nuxtent Documentation' } + { + hid: 'description', + name: 'description', + content: 'Nuxtent Documentation' + } ], - link: [ - { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } - ] + link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }] }, - modules: [ - 'nuxtent' - ], + modules: ['nuxtent'], css: [ 'prismjs/themes/prism-coy.css', { src: '~/assets/sass/base.sass', lang: 'sass' } diff --git a/docs/nuxtent.config.js b/docs/nuxtent.config.js index c5be098..c11fd68 100644 --- a/docs/nuxtent.config.js +++ b/docs/nuxtent.config.js @@ -6,29 +6,33 @@ module.exports = { page: 'guide/_slug', permalink: ':slug', isPost: false, - generate: [ - 'get', - 'getAll' - ] + generate: ['get', 'getAll'] }, parsers: { md: { highlight: (code, lang) => { - return Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup) + return Prism.highlight( + code, + Prism.languages[lang] || Prism.languages.markup + ) }, use: [ - [externalLinks, { - target: '_blank', - rel: 'noopener' - }] + [ + externalLinks, + { + target: '_blank', + rel: 'noopener' + } + ] ] } }, api: { - baseURL: process.env.NODE_ENV === 'production' - ? 'https://nuxtent.now.sh' - : 'http://localhost:3000' + baseURL: + process.env.NODE_ENV === 'production' + ? 'https://nuxtent.now.sh' + : 'http://localhost:3000' } } diff --git a/examples/content-navigation/nuxt.config.js b/examples/content-navigation/nuxt.config.js index a6df76c..f4e0404 100644 --- a/examples/content-navigation/nuxt.config.js +++ b/examples/content-navigation/nuxt.config.js @@ -5,9 +5,7 @@ module.exports = { { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: 'Nuxt.js project' } - ], + ] }, - modules: [ - 'nuxtent' - ] + modules: ['nuxtent'] } diff --git a/examples/content-navigation/nuxtent.config.js b/examples/content-navigation/nuxtent.config.js index a951e41..b298eeb 100644 --- a/examples/content-navigation/nuxtent.config.js +++ b/examples/content-navigation/nuxtent.config.js @@ -1,7 +1,7 @@ module.exports = { content: { page: '/guide/_slug', - permalink: ":slug", + permalink: ':slug', isPost: false } } diff --git a/examples/custom-build/nuxt.config.js b/examples/custom-build/nuxt.config.js index a6df76c..f4e0404 100644 --- a/examples/custom-build/nuxt.config.js +++ b/examples/custom-build/nuxt.config.js @@ -5,9 +5,7 @@ module.exports = { { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: 'Nuxt.js project' } - ], + ] }, - modules: [ - 'nuxtent' - ] + modules: ['nuxtent'] } diff --git a/examples/custom-build/nuxtent.config.js b/examples/custom-build/nuxtent.config.js index b601c20..ea06a04 100644 --- a/examples/custom-build/nuxtent.config.js +++ b/examples/custom-build/nuxtent.config.js @@ -1,22 +1,28 @@ const Prism = require('prismjs') module.exports = { - content: { // basic content configuration + content: { + // basic content configuration permalink: ':slug', isPost: false }, - parser: { // custom parser options + parser: { + // custom parser options md: { highlight: (code, lang) => { - return Prism.highlight(code, Prism.languages[lang] || Prism.languages.markup) + return Prism.highlight( + code, + Prism.languages[lang] || Prism.languages.markup + ) } } }, - api: { // custom url for development and production builds - baseURL: process.env.NODE_ENV ? - 'https://production-url.now.sh' : - 'http://localhost:3000' + api: { + // custom url for development and production builds + baseURL: process.env.NODE_ENV + ? 'https://production-url.now.sh' + : 'http://localhost:3000' } } diff --git a/examples/i18n/nuxt.config.js b/examples/i18n/nuxt.config.js index c70fe7f..72f3412 100755 --- a/examples/i18n/nuxt.config.js +++ b/examples/i18n/nuxt.config.js @@ -1,6 +1,4 @@ module.exports = { loading: { color: 'cyan' }, - modules: [ - 'nuxtent' - ] + modules: ['nuxtent'] } diff --git a/examples/i18n/nuxtent.config.js b/examples/i18n/nuxtent.config.js index 9ece0f1..bce45c2 100644 --- a/examples/i18n/nuxtent.config.js +++ b/examples/i18n/nuxtent.config.js @@ -3,8 +3,5 @@ const contentOptions = { } module.exports = { - content: [ - ['en', contentOptions], - ['fe', contentOptions] - ] + content: [['en', contentOptions], ['fe', contentOptions]] } diff --git a/examples/markdown-components/nuxt.config.js b/examples/markdown-components/nuxt.config.js index 36fc9c0..72dbf09 100644 --- a/examples/markdown-components/nuxt.config.js +++ b/examples/markdown-components/nuxt.config.js @@ -1,5 +1,3 @@ module.exports = { - modules: [ - 'nuxtent' - ] + modules: ['nuxtent'] } diff --git a/examples/markdown-components/nuxtent.config.js b/examples/markdown-components/nuxtent.config.js index dee73a6..55e2bb5 100644 --- a/examples/markdown-components/nuxtent.config.js +++ b/examples/markdown-components/nuxtent.config.js @@ -1,7 +1,7 @@ module.exports = { content: { page: '/_slug', - permalink: "/:slug", + permalink: '/:slug', isPost: false, generate: ['get'] } diff --git a/examples/multiple-content-types/nuxt.config.js b/examples/multiple-content-types/nuxt.config.js index 36fc9c0..72dbf09 100644 --- a/examples/multiple-content-types/nuxt.config.js +++ b/examples/multiple-content-types/nuxt.config.js @@ -1,5 +1,3 @@ module.exports = { - modules: [ - 'nuxtent' - ] + modules: ['nuxtent'] } diff --git a/examples/multiple-content-types/nuxtent.config.js b/examples/multiple-content-types/nuxtent.config.js index 58c6a17..1850a78 100644 --- a/examples/multiple-content-types/nuxtent.config.js +++ b/examples/multiple-content-types/nuxtent.config.js @@ -1,15 +1,21 @@ module.exports = { content: [ - ['posts', { - page: '/_post', - permalink: ":year/:slug", - generate: ['get', 'getAll'] - }], - ['projects', { - page: '/projects/slug', - permalink: "/:slug", - isPost: false, - generate: ['get', 'getAll'] - }] + [ + 'posts', + { + page: '/_post', + permalink: ':year/:slug', + generate: ['get', 'getAll'] + } + ], + [ + 'projects', + { + page: '/projects/slug', + permalink: '/:slug', + isPost: false, + generate: ['get', 'getAll'] + } + ] ] } diff --git a/examples/single-content-type/nuxt.config.js b/examples/single-content-type/nuxt.config.js index 066f286..1ca0e52 100644 --- a/examples/single-content-type/nuxt.config.js +++ b/examples/single-content-type/nuxt.config.js @@ -1,13 +1,13 @@ module.exports = { - modules: [ - 'nuxtent' - ], + modules: ['nuxtent'], nuxtent: { content: { page: '/_post', permalink: ':year/:slug', - generate: [ // assets to generate static build - 'get', 'getAll' + generate: [ + // assets to generate static build + 'get', + 'getAll' ] } } diff --git a/examples/sitemap/nuxt.config.js b/examples/sitemap/nuxt.config.js index ab37212..0000e48 100644 --- a/examples/sitemap/nuxt.config.js +++ b/examples/sitemap/nuxt.config.js @@ -1,25 +1,23 @@ const axios = require('axios') module.exports = { - modules: [ - 'nuxtent', - '@nuxtjs/sitemap' - ], + modules: ['nuxtent', '@nuxtjs/sitemap'], nuxtent: { content: { page: '/_post', permalink: ':year/:slug', - generate: [ // assets to generate static build - 'get', 'getAll' + generate: [ + // assets to generate static build + 'get', + 'getAll' ] } }, sitemap: { generate: true, routes: function () { - return axios.get('http://localhost:3000/content-api') - .then((res) => { - return res.data.map((page) => page.path ) + return axios.get('http://localhost:3000/content-api').then(res => { + return res.data.map(page => page.path) }) } } diff --git a/index.js b/index.js index 7f19959..c734eba 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -const nuxtentModule = require("./dist/module.js"); +const nuxtentModule = require('./dist/module.js') -module.exports = nuxtentModule.default; -module.exports.meta = nuxtentModule.meta; +module.exports = nuxtentModule.default +module.exports.meta = nuxtentModule.meta diff --git a/lib/content/api.js b/lib/content/api.js index 2b94e73..b6be421 100644 --- a/lib/content/api.js +++ b/lib/content/api.js @@ -11,11 +11,14 @@ export default function createRouter (options) { // for multiple content types, show the content configuration in the root request if (!options.content['/']) { - router.use("/", new Router().get('/', (req, res) => { - response(res).json({ - 'content-endpoints': Object.keys(options.content) + router.use( + '/', + new Router().get('/', (req, res) => { + response(res).json({ + 'content-endpoints': Object.keys(options.content) + }) }) - })) + ) } Object.keys(options.content).forEach(dirName => { @@ -41,30 +44,32 @@ function curryResponseHandler (endpoint, options) { logRequest(permalink, api.serverPrefix, api.baseURL) - if (permalink === '/') { // request multiple pages from directory + if (permalink === '/') { + // request multiple pages from directory if (between) send.json(db.findBetween(between, query)) else if (only) send.json(db.findOnly(only, query)) else send.json(db.findAll(query)) - } else { // request single page + } else { + // request single page if (db.exists(permalink)) send.json(db.find(permalink, query)) else send.notFound() } } } -export const response = (res) => ({ - json(data) { +export const response = res => ({ + json (data) { res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify(data), 'utf-8') console.log(` Response sent successfully.`) }, - error(err) { + error (err) { console.log(` Failed to send response.`, error) res.statusCode = 500 res.statusMessage = 'Internal Server Error' res.end(err.stack || String(err)) }, - notFound() { + notFound () { console.log(` Page not found.`) res.statusCode = 404 res.statusMessage = 'Not Found' @@ -73,6 +78,8 @@ export const response = (res) => ({ }) function logRequest (permalink, apiPrefix, baseURL) { - console.log(`${chalk.blue(apiPrefix)} ${chalk.green('GET')} ${baseURL + permalink}`) + console.log( + `${chalk.blue(apiPrefix)} ${chalk.green('GET')} ${baseURL + permalink}` + ) return permalink } diff --git a/lib/content/build.js b/lib/content/build.js index 31a8e30..a96b01c 100644 --- a/lib/content/build.js +++ b/lib/content/build.js @@ -3,7 +3,8 @@ import createDatabase from './database' const { isArray, concat } = Array const { join } = require('path') -const buildPath = (permalink, section, { buildDir }) => { // browser build path +const buildPath = (permalink, section, { buildDir }) => { + // browser build path // convert the permalink's slashes to periods so that // generated content is not overly nested const allButFirstSlash = /(?!^\/)\// @@ -11,13 +12,21 @@ const buildPath = (permalink, section, { buildDir }) => { // browser build path return join(buildDir, section, filePath) + '.json' } -const routeName = (routePath) => { +const routeName = routePath => { const firstSlash = /^\// - return routePath.replace(firstSlash, '').replace('/', '-').replace('_', '') + return routePath + .replace(firstSlash, '') + .replace('/', '-') + .replace('_', '') } -const asset = (object) => { // webpack asset - const content = JSON.stringify(object, null, process.env.NODE_ENV === 'production' ? 0 : 2) +const asset = object => { + // webpack asset + const content = JSON.stringify( + object, + null, + process.env.NODE_ENV === 'production' ? 0 : 2 + ) return { source: () => content, size: () => content.length } } @@ -28,9 +37,9 @@ const asset = (object) => { // webpack asset export default function buildContent ({ nuxt, options }) { const { sitePath, srcDir, content } = options - let routePages = [] // dynamic pages to create + let routePages = [] // dynamic pages to create let routePaths = new Map() // paths to reconfigure - let assetMap = new Map() // browser assets to generate + let assetMap = new Map() // browser assets to generate Object.keys(content).forEach(dirName => { const { page, generate, permalink } = content[dirName] @@ -48,7 +57,7 @@ export default function buildContent ({ nuxt, options }) { generate.forEach(reqType => { const req = {} if (typeof reqType === 'string') { - req['method'] = reqType + req['method'] = reqType } else if (Array.isArray(reqType)) { const [reqMethod, reqOptions] = reqType req['method'] = reqMethod @@ -60,7 +69,7 @@ export default function buildContent ({ nuxt, options }) { case 'get': if (!page) throw new Error('You must specify a page path') const pathPrefix = getPrefix(name) - db.findAll(req['query']).forEach((page) => { + db.findAll(req['query']).forEach(page => { routePages.push(join(pathPrefix, page.permalink)) assetMap.set(buildPath(page.permalink, dirName, options), page) }) @@ -78,7 +87,9 @@ export default function buildContent ({ nuxt, options }) { ) break default: - throw new Error(`The ${req['method']} is not supported for static builds.`) + throw new Error( + `The ${req['method']} is not supported for static builds.` + ) } }) } @@ -98,8 +109,7 @@ function interceptRoutes (nuxt, routePaths) { route.children.forEach(nestedRoute => { if (routePaths.has(nestedRoute.name)) { const isOptional = nestedRoute.path.match(/\?$/) - if (isOptional) nestedRoute.path = routePaths.get(nestedRoute.name) + '?' - else nestedRoute.path = routePaths.get(nestedRoute.name) + if (isOptional) { nestedRoute.path = routePaths.get(nestedRoute.name) + '?' } else nestedRoute.path = routePaths.get(nestedRoute.name) } }) } @@ -117,7 +127,7 @@ function addRoutes (nuxtOpts, routeData) { function addAssets (nuxtOpts, assetMap) { nuxtOpts.build.plugins.push({ - apply(compiler) { + apply (compiler) { compiler.plugin('emit', (compilation, cb) => { assetMap.forEach((page, buildPath) => { compilation.assets[buildPath] = asset(page) diff --git a/lib/content/database.js b/lib/content/database.js index 1f6fca3..d4dc5d3 100644 --- a/lib/content/database.js +++ b/lib/content/database.js @@ -9,15 +9,18 @@ export default function createDatabase (contentPath, dirName, options) { const dirPath = join(contentPath, dirName) const dirOpts = { ...content[dirName], parsers } - const pagesMap = globAndApply(dirPath, new Map(), - ({ index, fileName, section }, store ) => { + const pagesMap = globAndApply( + dirPath, + new Map(), + ({ index, fileName, section }, store) => { const filePath = join(contentPath, dirName, section, fileName) const meta = { index, fileName, section, dirName, filePath } - const lazyPage = prepPage(meta, dirOpts,isDev) + const lazyPage = prepPage(meta, dirOpts, isDev) store.set(lazyPage.permalink, lazyPage) - }) + } + ) - const pagesArr = [ ...pagesMap.values() ] + const pagesArr = [...pagesMap.values()] return { exists (permalink) { @@ -28,18 +31,20 @@ export default function createDatabase (contentPath, dirName, options) { return pagesMap.get(permalink).create(query) }, - findOnly(onlyArg, query) { + findOnly (onlyArg, query) { if (typeof onlyArg === 'string') onlyArg = onlyArg.split(',') const [startIndex, endIndex] = onlyArg let currIndex = max(0, parseInt(startIndex)) - let finalIndex = endIndex !== undefined - ? min(parseInt(endIndex), pagesArr.length - 1) : null + let finalIndex = + endIndex !== undefined + ? min(parseInt(endIndex), pagesArr.length - 1) + : null if (!finalIndex) return pagesArr[currIndex].create(query) const pages = [] - while(currIndex <= finalIndex && finalIndex !== 0) { + while (currIndex <= finalIndex && finalIndex !== 0) { pages.push(pagesArr[currIndex]) currIndex++ } @@ -47,7 +52,7 @@ export default function createDatabase (contentPath, dirName, options) { return pages.map(page => page.create(query)) }, - findBetween(betweenStr, query) { + findBetween (betweenStr, query) { const { findOnly } = this const [currPermalink, numStr1, numStr2] = betweenStr.split(',') @@ -55,7 +60,7 @@ export default function createDatabase (contentPath, dirName, options) { const currPage = pagesMap.get(currPermalink).create(query) const { index } = currPage.meta - const total = pagesArr.length -1 + const total = pagesArr.length - 1 const num1 = parseInt(numStr1 || 0) const num2 = numStr2 !== undefined ? parseInt(numStr2) : null @@ -68,7 +73,7 @@ export default function createDatabase (contentPath, dirName, options) { let afterRange if (num2 === 0 || (!num2 && num1 === 0)) afterRange = [] - else afterRange = [min(index + 1, total), min(index + (num2 || num1), total)] + else { afterRange = [min(index + 1, total), min(index + (num2 || num1), total)] } const beforePages = findOnly(beforeRange, query) const afterPages = findOnly(afterRange, query) @@ -86,7 +91,7 @@ function globAndApply (dirPath, fileStore, applyFn, nestedPath = '/') { const stats = readdirSync(dirPath).reverse() // posts more useful in reverse order stats.forEach((stat, index) => { const statPath = join(dirPath, stat) - if(statSync(statPath).isFile()) { + if (statSync(statPath).isFile()) { const fileData = { index, fileName: stat, section: nestedPath } applyFn(fileData, fileStore) } else globAndApply(statPath, fileStore, applyFn, join(nestedPath, stat)) diff --git a/lib/content/page.js b/lib/content/page.js index dd77120..9af5932 100644 --- a/lib/content/page.js +++ b/lib/content/page.js @@ -9,9 +9,15 @@ export default function prepPage (meta, options, isDev) { const cached = {} return { create (params = {}) { - const props = new Set( - ['meta', 'date', 'path', 'permalink', 'anchors', 'attributes', 'body'] - ) + const props = new Set([ + 'meta', + 'date', + 'path', + 'permalink', + 'anchors', + 'attributes', + 'body' + ]) if (params.exclude) { params.exclude.split(',').forEach(prop => { @@ -21,7 +27,7 @@ export default function prepPage (meta, options, isDev) { let data = {} props.forEach(prop => { - if (prop === 'attributes') data = { ...this[prop], ...data } + if (prop === 'attributes') data = { ...this[prop], ...data } else data[prop] = this[prop] }) @@ -53,8 +59,10 @@ export default function prepPage (meta, options, isDev) { const { year, month, day } = splitDate(date) const params = { section, slug, date, year, month, day } const toPermalink = permalinkCompiler(options.permalink) - cached.permalink = join('/', toPermalink(params, { pretty: true }) - .replace(/%2F/gi, "/")) // make url encoded slash pretty + cached.permalink = join( + '/', + toPermalink(params, { pretty: true }).replace(/%2F/gi, '/') + ) // make url encoded slash pretty } return cached.permalink }, @@ -65,15 +73,18 @@ export default function prepPage (meta, options, isDev) { const { _rawData } = this const level = options.anchorsLevel - const anchorsExp = new RegExp([ - '(`{3}[\\s\\S]*?`{3}|`{1}[^`].*?`{1}[^`]*?)', // code snippet - `(#{${level + 1},})`, // other heading - `(?:^|\\s)#{${level}}[^#](.*)`, // heading text - ].join('|'), 'g') + const anchorsExp = new RegExp( + [ + '(`{3}[\\s\\S]*?`{3}|`{1}[^`].*?`{1}[^`]*?)', // code snippet + `(#{${level + 1},})`, // other heading + `(?:^|\\s)#{${level}}[^#](.*)` // heading text + ].join('|'), + 'g' + ) let result let anchors = [] - while (result = anchorsExp.exec(_rawData)) { + while ((result = anchorsExp.exec(_rawData))) { let [match, codeSnippet, otherHeading, headingText] = result if (!(codeSnippet || otherHeading) && headingText) { const anchor = `#${paramCase(headingText)}` @@ -81,7 +92,8 @@ export default function prepPage (meta, options, isDev) { } } cached.anchors = anchors - } else { // yaml file + } else { + // yaml file cached.anchors = [] } } @@ -98,16 +110,16 @@ export default function prepPage (meta, options, isDev) { const { parsers } = options const { dirName, section, fileName } = meta if (fileName.search(/\.comp\.md$/) > -1) { - const relativePath = '.' + join(dirName, section, fileName) + const relativePath = '.' + join(dirName, section, fileName) cached.body = { relativePath // component body compiled by loader and imported separately } } else if (fileName.search(/\.md$/) > -1) { - cached.body = parsers.mdParser(parsers.md, options) + cached.body = parsers + .mdParser(parsers.md, options) .render(_rawData.body) // markdown to html } else if (fileName.search(/\.yaml$/) > -1) { - cached.body = parsers.yamlParser() - .render(_rawData.body) // yaml to json + cached.body = parsers.yamlParser().render(_rawData.body) // yaml to json } } return cached.body @@ -118,7 +130,7 @@ export default function prepPage (meta, options, isDev) { const { filePath, fileName, section } = meta if (options.isPost) { const fileDate = fileName.match(/!?(\d{4}-\d{2}-\d{2})/) // YYYY-MM-DD - if (!fileDate) throw Error(`Post in "${section}" does not have a date!`) + if (!fileDate) { throw Error(`Post in "${section}" does not have a date!`) } cached.date = fileDate[0] } else { const stats = statSync(filePath) @@ -128,7 +140,6 @@ export default function prepPage (meta, options, isDev) { return cached.date }, - get _rawData () { if (isDev || !cached.data) { const source = readFileSync(meta.filePath).toString() @@ -147,13 +158,13 @@ export default function prepPage (meta, options, isDev) { function getSlug (fileName) { const onlyName = fileName .replace(/(\.comp)?(\.[0-9a-z]+$)/, '') // remove any ext - .replace(/!?(\d{4}-\d{2}-\d{2}-)/, '') // remove date and hypen + .replace(/!?(\d{4}-\d{2}-\d{2}-)/, '') // remove date and hypen return paramCase(onlyName) } function splitDate (date) { const dateData = date.split('-') - return { + return { year: dateData[0], month: dateData[1], day: dateData[2] diff --git a/lib/loader.js b/lib/loader.js index cfd2573..8e868cf 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -6,12 +6,12 @@ const uppercamelcase = require('uppercamelcase') const paramCase = require('param-case') const fm = require('front-matter') -const mdCompParser = (mdParser) => { +const mdCompParser = mdParser => { // we need to add the `v-pre` snippet to code snippets so // that mustage tags (`{{ }}`) are interpreted as raw text - const codeRules = ['code_inline', 'code_block', 'fence' ] - const parser = mergeParserRules(mdParser, codeRules, (str) => { - return str.replace(/( { + return str.replace(/( { const mdComponent = (source, moduleOpts, dirOpts) => { const { sitePath, componentsDir, parsers } = moduleOpts - const compExp = new RegExp([ - '(`{3}[\\s\\S]*?`{3}|`{1}[^`].*?`{1}[^`])', // code snippet - '@\\[(.*?)\\](?:\\((.*?)\\))?', // markdown component - '@[]' or '@[]()' - ].join('|'), 'g') + const compExp = new RegExp( + [ + '(`{3}[\\s\\S]*?`{3}|`{1}[^`].*?`{1}[^`])', // code snippet + '@\\[(.*?)\\](?:\\((.*?)\\))?' // markdown component - '@[]' or '@[]()' + ].join('|'), + 'g' + ) let result const comps = {} - while (result = compExp.exec(source)) { + while ((result = compExp.exec(source))) { let [match, codeSnippet, name, props] = result if (!codeSnippet) { const compName = uppercamelcase(paramCase(name)) @@ -58,7 +61,8 @@ module.exports = function (source) { const { template, components } = mdComponent(body, moduleOpts, dirOpts) const allImports = Object.keys(components) - .map(key => `import ${key} from '~/components/${components[key]}'`).join('\n') + .map(key => `import ${key} from '~/components/${components[key]}'`) + .join('\n') const allComponents = Object.keys(components).join(', ') @@ -108,7 +112,7 @@ function getSection (path) { return section === '' ? '/' : section } -function getExt(basePath, name) { +function getExt (basePath, name) { if (existsSync(basePath + name + '.vue')) return '.vue' else if (existsSync(basePath + name + '.js')) return '.js' else throw new Error(`"${name}" does not exist at ${basePath}`) diff --git a/lib/module.js b/lib/module.js index 4509bbd..3624d66 100644 --- a/lib/module.js +++ b/lib/module.js @@ -6,108 +6,119 @@ import { mdParser, yamlParser } from './util/parsers' import pkg from '../package.json' -const port = process.env.PORT || process.env.npm_package_config_nuxt_port || 3000 -const host = process.env.HOST || process.env.npm_package_config_nuxt_host || 'localhost' - -const nuxtentConfig = (nuxtOpts) => { - const rootConfig = resolve(nuxtOpts.rootDir, 'nuxtent.config.js') - try { - return require(rootConfig) - } catch (err) { - if (err.code === "MODULE_NOT_FOUND") { - return nuxtOpts.nuxtent - } - throw new Error (`[Invalid Nuxtent configuration] ${err}`) - } +const port = + process.env.PORT || process.env.npm_package_config_nuxt_port || 3000 +const host = + process.env.HOST || process.env.npm_package_config_nuxt_host || 'localhost' + +const nuxtentConfig = nuxtOpts => { + const rootConfig = resolve(nuxtOpts.rootDir, 'nuxtent.config.js') + try { + return require(rootConfig) + } catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + return nuxtOpts.nuxtent + } + throw new Error(`[Invalid Nuxtent configuration] ${err}`) + } } const contentOptions = (content, defaults) => { - const opts = {} - if (!Array.isArray(content)) opts['/'] = { ...defaults, ...content } - else { - content.forEach(strOrArr => { - const dirName = Array.isArray(strOrArr) ? strOrArr[0] : strOrArr - const dirOpts = Array.isArray(strOrArr) ? strOrArr[1] : {} - if (dirName === '/' && registered.length > 1) { // prevent endpoint conflict - throw new Error('Top level files not allowed with nested registered directories') - } - opts[join('/', dirName)] = { ...defaults, ...dirOpts } - }) - } - return opts + const opts = {} + if (!Array.isArray(content)) opts['/'] = { ...defaults, ...content } + else { + content.forEach(strOrArr => { + const dirName = Array.isArray(strOrArr) ? strOrArr[0] : strOrArr + const dirOpts = Array.isArray(strOrArr) ? strOrArr[1] : {} + if (dirName === '/' && registered.length > 1) { + // prevent endpoint conflict + throw new Error( + 'Top level files not allowed with nested registered directories' + ) + } + opts[join('/', dirName)] = { ...defaults, ...dirOpts } + }) + } + return opts } -export default function ContentModule(moduleOpts) { - const userOptions = nuxtentConfig(this.options) - - const options = { - isDev: this.nuxt.options.dev, - srcPath: this.options.rootDir, - sitePath: this.options.srcDir, - srcDir: '/content', - componentsDir: '/components', - buildDir: `/content`, - isStatic: userOptions.isStatic || process.env.STATIC || false, - - content: contentOptions(userOptions.content, { - page: null, - permalink: ':slug', - anchorsLevel: 1, - isPost: true, - generate: [] - }), - - parsers: { - md: Object.assign({}, { - highlight: null, - use: [] - }, userOptions.parsers && userOptions.parsers.md ? userOptions.parsers.md : {}), - mdParser, - yamlParser - }, - - api: { - baseURL: '', - ...userOptions.api, - serverPrefix: `/content-api`, - browserPrefix: `/_nuxt/content` - } - } - - const { srcDir, content, api } = options - - // 1. Configure and build dynamic content pages - - this.extendBuild(config => { - config.module.rules.push({ - test: /\.comp\.md$/, - use: [ - 'vue-loader', - { loader: 'nuxtent/dist/loader.js', options } - ] - }) - }) - - buildContent({ - nuxt: this, - options - }) - - // 2. Add content API - - this.addServerMiddleware({ - path: api.serverPrefix, - handler: createRouter(options) - }) - - // 3. Add request helpers - - this.requireModule([ - '@nuxtjs/axios', { - baseURL: api.baseURL + api.serverPrefix, - browserBaseURL: api.baseURL + (process.env.STATIC ? api.browserPrefix : api.serverPrefix) - } - ]) +export default function ContentModule (moduleOpts) { + const userOptions = nuxtentConfig(this.options) + + const options = { + isDev: this.nuxt.options.dev, + srcPath: this.options.rootDir, + sitePath: this.options.srcDir, + srcDir: '/content', + componentsDir: '/components', + buildDir: `/content`, + isStatic: userOptions.isStatic || process.env.STATIC || false, + + content: contentOptions(userOptions.content, { + page: null, + permalink: ':slug', + anchorsLevel: 1, + isPost: true, + generate: [] + }), + + parsers: { + md: Object.assign( + {}, + { + highlight: null, + use: [] + }, + userOptions.parsers && userOptions.parsers.md + ? userOptions.parsers.md + : {} + ), + mdParser, + yamlParser + }, + + api: { + baseURL: '', + ...userOptions.api, + serverPrefix: `/content-api`, + browserPrefix: `/_nuxt/content` + } + } + + const { srcDir, content, api } = options + + // 1. Configure and build dynamic content pages + + this.extendBuild(config => { + config.module.rules.push({ + test: /\.comp\.md$/, + use: ['vue-loader', { loader: 'nuxtent/dist/loader.js', options }] + }) + }) + + buildContent({ + nuxt: this, + options + }) + + // 2. Add content API + + this.addServerMiddleware({ + path: api.serverPrefix, + handler: createRouter(options) + }) + + // 3. Add request helpers + + this.requireModule([ + '@nuxtjs/axios', + { + baseURL: api.baseURL + api.serverPrefix, + browserBaseURL: + api.baseURL + + (process.env.STATIC ? api.browserPrefix : api.serverPrefix) + } + ]) // 4. Add import md comps plugin @@ -119,7 +130,7 @@ export default function ContentModule(moduleOpts) { }) // 4. Add content plugins - + this.addPlugin({ src: resolve(__dirname, 'plugins/requestContent.js') }) diff --git a/lib/plugins/requestContent.js b/lib/plugins/requestContent.js index 2617924..2bbb36d 100644 --- a/lib/plugins/requestContent.js +++ b/lib/plugins/requestContent.js @@ -35,7 +35,7 @@ export default ({ app, isServer, isClient, isStatic, hotReload, route }) => { } return cache[browserPath] } else { - // static server build + // static server build } } @@ -48,7 +48,9 @@ export default ({ app, isServer, isClient, isStatic, hotReload, route }) => { return this }, async get (permalink) { - if (typeof permalink !== 'string') { throw Error(`Permalink must be a string.`) } + if (typeof permalink !== 'string') { + throw Error(`Permalink must be a string.`) + } return await fetchContent(contentDir, permalink, '?' + query) }, async getBetween (permalink, num1or2, num2 = '') { diff --git a/lib/util/parsers.js b/lib/util/parsers.js index 94da231..656341c 100644 --- a/lib/util/parsers.js +++ b/lib/util/parsers.js @@ -12,13 +12,18 @@ export const mdParser = ({ highlight, use }, { anchorsLevel }) => { }) const plugins = [ - [markdownAnchors, { - level: [anchorsLevel] - }] + [ + markdownAnchors, + { + level: [anchorsLevel] + } + ] ].concat(use) plugins.forEach(plugin => { - Array.isArray(plugin) ? parser.use.apply(parser, plugin) : parser.use(plugin) + Array.isArray(plugin) + ? parser.use.apply(parser, plugin) + : parser.use(plugin) }) return parser @@ -26,6 +31,6 @@ export const mdParser = ({ highlight, use }, { anchorsLevel }) => { export const yamlParser = () => { return { - render: yamlit.safeLoad + render: yamlit.safeLoad } } diff --git a/test/e2e/complex.test.js b/test/e2e/complex.test.js index e6e4cc7..78b2a9f 100644 --- a/test/e2e/complex.test.js +++ b/test/e2e/complex.test.js @@ -2,7 +2,7 @@ import { resolve } from 'path' import test from 'ava' -import { get, commonBefore, commonAfter } from "../fixtures/nuxt"; +import { get, commonBefore, commonAfter } from '../fixtures/nuxt' test.before('Init Nuxt and Nuxtent', async () => { await commonBefore( @@ -12,14 +12,14 @@ test.before('Init Nuxt and Nuxtent', async () => { 'posts', { page: '/posts/_slug', - permalink: '/:year/:slug', + permalink: '/:year/:slug' } ], [ 'projects', { page: '/projects/_slug', - permalink: "/projects/:slug", + permalink: '/projects/:slug', isPost: false } ] @@ -33,30 +33,46 @@ test.before('Init Nuxt and Nuxtent', async () => { test('index', async t => { const html = await get('/') - t.true(html.includes('

Nuxtent

See my first postSee all my postsSee my first projectSee all my projects
')) + t.true( + html.includes( + '

Nuxtent

See my first postSee all my postsSee my first projectSee all my projects
' + ) + ) }) test('posts content - get', async t => { const html = await get('/2016/first-post') - t.true(html.includes('

My First Post

This is my first post!

')) + t.true( + html.includes('

My First Post

This is my first post!

') + ) }) test('posts content - getAll', async t => { const html = await get('/archives') - t.true(html.includes('

Posts

')) + t.true( + html.includes( + '

Posts

' + ) + ) }) test('projects content - get', async t => { const html = await get('/projects/ency') - t.true(html.includes( -`

Project: Ency.js

Pretty cool plugin!

+ t.true( + html.includes( + `

Project: Ency.js

Pretty cool plugin!

` - )) + ) + ) }) test('projects content - getAll', async t => { const html = await get('/projects/') - t.true(html.includes('

Projects

')) + t.true( + html.includes( + '

Projects

' + ) + ) }) test.after('Closing server and nuxt.js', async () => { diff --git a/test/e2e/simple.test.js b/test/e2e/simple.test.js index 71c94d7..1d87bc3 100644 --- a/test/e2e/simple.test.js +++ b/test/e2e/simple.test.js @@ -2,14 +2,14 @@ import { resolve } from 'path' import test from 'ava' -import { get, commonBefore, commonAfter } from "../fixtures/nuxt"; +import { get, commonBefore, commonAfter } from '../fixtures/nuxt' test.before('Init Nuxt and Nuxtent', async () => { await commonBefore( { content: { page: '/_slug', - permalink: '/:year/:slug', + permalink: '/:year/:slug' } }, { @@ -25,12 +25,18 @@ test('index', async t => { test('content - get', async t => { const html = await get('/2016/first-post') - t.true(html.includes('

My First Post

This is my first post!

')) + t.true( + html.includes('

My First Post

This is my first post!

') + ) }) test('content - getAll', async t => { const html = await get('/archives') - t.true(html.includes('

All Posts

')) + t.true( + html.includes( + '

All Posts

' + ) + ) }) test.after('Closing server and nuxt.js', async () => { diff --git a/test/fixtures/nuxt.config.js b/test/fixtures/nuxt.config.js index 5338741..25d5dc1 100644 --- a/test/fixtures/nuxt.config.js +++ b/test/fixtures/nuxt.config.js @@ -1,12 +1,10 @@ import nuxtent from '../../lib/module' -export default (nuxtentConfig) => ({ +export default nuxtentConfig => ({ dev: false, render: { resourceHints: false }, - modules: [ - nuxtent - ], + modules: [nuxtent], nuxtent: nuxtentConfig }) diff --git a/test/fixtures/nuxt.js b/test/fixtures/nuxt.js index c232e42..c959c85 100644 --- a/test/fixtures/nuxt.js +++ b/test/fixtures/nuxt.js @@ -14,21 +14,19 @@ let nuxt const commonBefore = (nuxtentConfig, config = {}) => async () => { const mergedConfig = { - ...baseConfig( - { - ...nuxtentConfig, - api: { - baseURL: `http://localhost:${process.env.PORT}` - }, + ...baseConfig({ + ...nuxtentConfig, + api: { + baseURL: `http://localhost:${process.env.PORT}` } - ), + }), ...config } // Build a fresh nuxt - nuxt = new Nuxt(mergedConfig); - await new Builder(nuxt).build(); - await nuxt.listen(process.env.PORT); + nuxt = new Nuxt(mergedConfig) + await new Builder(nuxt).build() + await nuxt.listen(process.env.PORT) } const commonAfter = async () => { diff --git a/test/unit/karma.conf.js b/test/unit/karma.conf.js index 79455c9..2edbddc 100644 --- a/test/unit/karma.conf.js +++ b/test/unit/karma.conf.js @@ -1,27 +1,25 @@ module.exports = function (config) { - config.set({ - frameworks: ['mocha', 'sinon-chai'], + config.set({ + frameworks: ['mocha', 'sinon-chai'], - files: [ - './specs/**.spec.js', - ], + files: ['./specs/**.spec.js'], - preprocessors: { - '../../lib/module.js': ['rollup'], - '../../lib/content/**.js': ['rollup'], - './specs/**.spec.js': ['rollup'], - }, + preprocessors: { + '../../lib/module.js': ['rollup'], + '../../lib/content/**.js': ['rollup'], + './specs/**.spec.js': ['rollup'] + }, - rollupPreprocessor: { - plugins: [ - require('rollup-plugin-node-resolve')(), - require('rollup-plugin-node-builtins')(), - require('rollup-plugin-babel')(), - require('rollup-plugin-commonjs')() - ], + rollupPreprocessor: { + plugins: [ + require('rollup-plugin-node-resolve')(), + require('rollup-plugin-node-builtins')(), + require('rollup-plugin-babel')(), + require('rollup-plugin-commonjs')() + ], format: 'umd', moduleName: `nuxtContent`, - sourceMap: 'inline' - } - }) + sourceMap: 'inline' + } + }) } diff --git a/test/unit/specs/database.spec.js b/test/unit/specs/database.spec.js index 2ebea28..d5bac72 100644 --- a/test/unit/specs/database.spec.js +++ b/test/unit/specs/database.spec.js @@ -5,7 +5,6 @@ import createDatabase from '../../../lib/content/database' import { resolve } from 'path' describe('database API', function () { - it('loads single content type', () => { const contentPath = '../../fixtures/single-content-type/content' const dirName = '/' From 5ab467ccfeb7141da191b01ea49ef23c46506af7 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Fri, 22 Sep 2017 10:42:54 +0200 Subject: [PATCH 04/18] chore(build): fix rollup build according to new plugins folder structure --- rollup.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rollup.config.js b/rollup.config.js index 74402e7..7b934c6 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -47,7 +47,7 @@ export default [ plugins: [ json(), copy({ - 'lib/plugin.js': 'dist/plugin.js', + 'lib/plugins': 'dist/plugins', 'lib/loader.js': 'dist/loader.js' }), ...corePlugins() From ead3b6af89c392abcb5f4145da12f874be6291dc Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Fri, 22 Sep 2017 15:43:26 +0200 Subject: [PATCH 05/18] chore(lint): add `eslint` on npm `pretest` Add `eslint`, `babel-eslint`, `eslint-config-i-am-meticulous`, `eslint-config-prettier`, `eslint-config-standard`, `eslint-plugin-ava`, `eslint-plugin-babel`, `eslint-plugin-node`, `eslint-plugin-promise` and `eslint-plugin-standard` devDependencies --- .eslintignore | 4 ++++ .eslintrc | 22 ++++++++++++++++++++++ lib/plugins/importMdComps.template.js | 2 ++ package.json | 12 ++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 .eslintignore create mode 100644 .eslintrc diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..c8f0acb --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +node_modules/ +lib/plugins/importMdComps.template.js +dist/ +nuxt/ diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..747b130 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,22 @@ +{ + "root": true, + "parser": "babel-eslint", + "parserOptions": { + "ecmaVersion": 8, + "sourceType": "module" + }, + "env": { + "node": true, + "es6": true + }, + "plugins": [ + "babel", + "ava" + ], + "extends": [ + "eslint-config-standard", + "eslint-config-i-am-meticulous", + "plugin:ava/recommended", + "eslint-config-prettier" + ] +} diff --git a/lib/plugins/importMdComps.template.js b/lib/plugins/importMdComps.template.js index 6029d13..a0b4030 100644 --- a/lib/plugins/importMdComps.template.js +++ b/lib/plugins/importMdComps.template.js @@ -1,3 +1,5 @@ +/* eslint-disable */ + function importAllMdComps (r) { r.keys().forEach(key => r(key)) } diff --git a/package.json b/package.json index 499aca8..1185b77 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "#": "handled by husky", "precommit": "lint-staged", "#": "handled by husky", + "lint": "eslint --fix \"**/*.js\"", + "pretest": "npm run lint", "unit": "cross-env NODE_ENV=development karma start test/unit/karma.conf.js", "e2e": "cross-env NODE_ENV=test ava --verbose --serial test/e2e", "test": "npm run unit --single-run && npm run e2e", @@ -55,6 +57,7 @@ "@nuxtjs/axios": "^3.0.1", "ava": "^0.22.0", "babel-cli": "^6.26.0", + "babel-eslint": "^8.0.0", "babel-plugin-external-helpers": "^6.22.0", "babel-plugin-istanbul": "^4.1.5", "babel-plugin-transform-async-to-generator": "^6.24.1", @@ -65,6 +68,15 @@ "babel-register": "^6.26.0", "chai": "^4.1.0", "cross-env": "^5.0.1", + "eslint": "^4.7.2", + "eslint-config-i-am-meticulous": "^7.0.1", + "eslint-config-prettier": "^2.5.0", + "eslint-config-standard": "^10.2.1", + "eslint-plugin-ava": "^4.2.2", + "eslint-plugin-babel": "^4.1.2", + "eslint-plugin-node": "^5.1.1", + "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-standard": "^3.0.1", "express": "^4.15.3", "git-exec-and-restage": "^1.0.1", "husky": "^0.14.3", From fb49d2db8763e6776cf3e42715d7090bdc7716f7 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Fri, 22 Sep 2017 17:15:59 +0200 Subject: [PATCH 06/18] chore(module): merge back `nuxtent-body` and `mdComps` plugins Restore access to compiled vue components to `nuxtent-body` Add new template name to .eslintignore --- .eslintignore | 2 +- lib/module.js | 25 ++++++++----------- ...nt.js => nuxtentBodyComponent.template.js} | 10 ++++++++ 3 files changed, 21 insertions(+), 16 deletions(-) rename lib/plugins/{nuxtentBodyComponent.js => nuxtentBodyComponent.template.js} (63%) diff --git a/.eslintignore b/.eslintignore index c8f0acb..773205f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,4 @@ node_modules/ -lib/plugins/importMdComps.template.js +lib/plugins/nuxtentBodyComponent.template.js dist/ nuxt/ diff --git a/lib/module.js b/lib/module.js index 3624d66..eb193d5 100644 --- a/lib/module.js +++ b/lib/module.js @@ -1,11 +1,11 @@ import { resolve, join } from 'path' +import pkg from '../package.json' + import createRouter from './content/api' import buildContent from './content/build' import { mdParser, yamlParser } from './util/parsers' -import pkg from '../package.json' - const port = process.env.PORT || process.env.npm_package_config_nuxt_port || 3000 const host = @@ -25,12 +25,13 @@ const nuxtentConfig = nuxtOpts => { const contentOptions = (content, defaults) => { const opts = {} - if (!Array.isArray(content)) opts['/'] = { ...defaults, ...content } - else { + if (!Array.isArray(content)) { + opts['/'] = { ...defaults, ...content } + } else { content.forEach(strOrArr => { const dirName = Array.isArray(strOrArr) ? strOrArr[0] : strOrArr const dirOpts = Array.isArray(strOrArr) ? strOrArr[1] : {} - if (dirName === '/' && registered.length > 1) { + if (dirName === '/' && content.length > 1) { // prevent endpoint conflict throw new Error( 'Top level files not allowed with nested registered directories' @@ -85,7 +86,7 @@ export default function ContentModule (moduleOpts) { } } - const { srcDir, content, api } = options + const { srcDir, api } = options // 1. Configure and build dynamic content pages @@ -120,26 +121,20 @@ export default function ContentModule (moduleOpts) { } ]) - // 4. Add import md comps plugin + // 4. Add nuxtent-body component plugin, and md components import this.addPlugin({ - src: resolve(__dirname, 'plugins/importMdComps.template.js'), + src: resolve(__dirname, 'plugins/nuxtentBodyComponent.template.js'), options: { srcDirFromPlugin: join('~/', srcDir) } }) - // 4. Add content plugins + // 5. Add content plugins this.addPlugin({ src: resolve(__dirname, 'plugins/requestContent.js') }) - - // 5. Add nuxtent-body component plugin - - this.addPlugin({ - src: resolve(__dirname, 'plugins/nuxtentBodyComponent.js') - }) } export { pkg as meta } diff --git a/lib/plugins/nuxtentBodyComponent.js b/lib/plugins/nuxtentBodyComponent.template.js similarity index 63% rename from lib/plugins/nuxtentBodyComponent.js rename to lib/plugins/nuxtentBodyComponent.template.js index b600443..8d4ea55 100644 --- a/lib/plugins/nuxtentBodyComponent.js +++ b/lib/plugins/nuxtentBodyComponent.template.js @@ -1,5 +1,15 @@ import Vue from 'vue' +const mdComps = {} + +function importAllMdComps (r) { + r.keys().forEach(key => (mdComps[key] = r(key))) +} + +importAllMdComps( + require.context(<%= JSON.stringify(options.srcDirFromPlugin) %>, true, /\.comp\.md$/) +) + Vue.component('nuxtent-body', { functional: true, props: { From 912883c005fe7666331def612e3ca07b2e4e2627 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Fri, 22 Sep 2017 17:22:53 +0200 Subject: [PATCH 07/18] chore(lint): correct all linting errors Add "import/no-unresolved" exception for examples Temporary ignore eslint errors for unit tests --- docs/package.json | 2 +- examples/.eslintrc | 5 +++++ examples/custom-build/package.json | 18 ++++++++++++++++++ lib/content/api.js | 13 +++++++------ lib/content/build.js | 21 ++++++++++++--------- lib/content/database.js | 3 ++- lib/content/page.js | 22 +++++++++++++--------- lib/loader.js | 21 +++++++++++---------- lib/plugins/importMdComps.template.js | 9 --------- lib/plugins/requestContent.js | 2 +- test/unit/specs/database.spec.js | 1 + 11 files changed, 71 insertions(+), 46 deletions(-) create mode 100644 examples/.eslintrc create mode 100644 examples/custom-build/package.json delete mode 100644 lib/plugins/importMdComps.template.js diff --git a/docs/package.json b/docs/package.json index bbcce2d..59e13b1 100644 --- a/docs/package.json +++ b/docs/package.json @@ -9,7 +9,7 @@ "markdown-it-link-attributes": "^1.0.0", "nuxt": "1.0.0-alpha.3", "nuxtent": "0.2.59", - "prismjs": "^1.6.0" + "prismjs": "^1.8.1" }, "scripts": { "dev": "nuxt", diff --git a/examples/.eslintrc b/examples/.eslintrc new file mode 100644 index 0000000..8f2e1a6 --- /dev/null +++ b/examples/.eslintrc @@ -0,0 +1,5 @@ +{ + rules: { + "import/no-unresolved": 0 + } +} diff --git a/examples/custom-build/package.json b/examples/custom-build/package.json new file mode 100644 index 0000000..aeb4e0e --- /dev/null +++ b/examples/custom-build/package.json @@ -0,0 +1,18 @@ +{ + "name": "nuxtent-example", + "version": "1.0.0", + "description": "nuxtent custom-build example", + "author": "Alid Castano ", + "dependencies": { + "@nuxtjs/axios": "^2.2.1", + "nuxt": "^1.0.0-rc3", + "nuxtent": "latest", + "prismjs": "^1.8.1" + }, + "scripts": { + "dev": "nuxt", + "build": "nuxt build", + "start": "nuxt start", + "generate": "nuxtent generate" + } +} diff --git a/lib/content/api.js b/lib/content/api.js index b6be421..60a50df 100644 --- a/lib/content/api.js +++ b/lib/content/api.js @@ -1,10 +1,10 @@ +import { join } from 'path' +import { parse } from 'querystring' + import chalk from 'chalk' -import createDatabase from './database' import { Router } from 'express' -const fs = require('fs') -const { join } = require('path') -const { parse } = require('querystring') +import createDatabase from './database' export default function createRouter (options) { const router = Router() @@ -30,7 +30,7 @@ export default function createRouter (options) { } function curryResponseHandler (endpoint, options) { - const { sitePath, srcDir, api, content } = options + const { sitePath, srcDir, api } = options const contentPath = join(sitePath, srcDir) @@ -39,6 +39,7 @@ function curryResponseHandler (endpoint, options) { return function sendContent (req, res) { const send = response(res) const permalink = req.params['0'] + // eslint-disable-next-line no-unused-vars const [_, queryStr] = req.url.match(/\?(.*)/) || [] const { only, between, ...query } = parse(queryStr) @@ -64,7 +65,7 @@ export const response = res => ({ console.log(` Response sent successfully.`) }, error (err) { - console.log(` Failed to send response.`, error) + console.log(` Failed to send response.`, err) res.statusCode = 500 res.statusMessage = 'Internal Server Error' res.end(err.stack || String(err)) diff --git a/lib/content/build.js b/lib/content/build.js index a96b01c..00efff7 100644 --- a/lib/content/build.js +++ b/lib/content/build.js @@ -1,7 +1,6 @@ -import createDatabase from './database' +import { join } from 'path' -const { isArray, concat } = Array -const { join } = require('path') +import createDatabase from './database' const buildPath = (permalink, section, { buildDir }) => { // browser build path @@ -37,9 +36,9 @@ const asset = object => { export default function buildContent ({ nuxt, options }) { const { sitePath, srcDir, content } = options - let routePages = [] // dynamic pages to create - let routePaths = new Map() // paths to reconfigure - let assetMap = new Map() // browser assets to generate + const routePages = [] // dynamic pages to create + const routePaths = new Map() // paths to reconfigure + const assetMap = new Map() // browser assets to generate Object.keys(content).forEach(dirName => { const { page, generate, permalink } = content[dirName] @@ -66,14 +65,17 @@ export default function buildContent ({ nuxt, options }) { } switch (req['method']) { - case 'get': - if (!page) throw new Error('You must specify a page path') + case 'get': { + if (!page) { + throw new Error('You must specify a page path') + } const pathPrefix = getPrefix(name) db.findAll(req['query']).forEach(page => { routePages.push(join(pathPrefix, page.permalink)) assetMap.set(buildPath(page.permalink, dirName, options), page) }) break + } case 'getAll': assetMap.set( buildPath('_all', dirName, options), @@ -121,7 +123,7 @@ function addRoutes (nuxtOpts, routeData) { if (!('generate' in nuxtOpts)) nuxtOpts.generate = {} if (!('routes' in nuxtOpts.generate)) nuxtOpts.generate.routes = [] const { routes } = nuxtOpts.generate - if (isArray(routes)) nuxtOpts.generate.routes = routes.concat(routeData) + if (Array.isArray(routes)) nuxtOpts.generate.routes = routes.concat(routeData) else throw new Error(`"generate.routes" must be an array`) } @@ -141,6 +143,7 @@ function addAssets (nuxtOpts, assetMap) { function getPrefix (routeName, topLevelPrefix = '/') { const result = routeName.match(/(^[a-zA-Z]*)(-)/) // matches `prefix-` if (result) { + // eslint-disable-next-line no-unused-vars const [_, prefix] = result if (prefix !== 'index') return join('/', prefix) } diff --git a/lib/content/database.js b/lib/content/database.js index d4dc5d3..3f20b28 100644 --- a/lib/content/database.js +++ b/lib/content/database.js @@ -2,6 +2,7 @@ import prepPage from './page' const { readdirSync, statSync } = require('fs') const { join } = require('path') + const { max, min } = Math export default function createDatabase (contentPath, dirName, options) { @@ -36,7 +37,7 @@ export default function createDatabase (contentPath, dirName, options) { const [startIndex, endIndex] = onlyArg let currIndex = max(0, parseInt(startIndex)) - let finalIndex = + const finalIndex = endIndex !== undefined ? min(parseInt(endIndex), pagesArr.length - 1) : null diff --git a/lib/content/page.js b/lib/content/page.js index 9af5932..3deb6c8 100644 --- a/lib/content/page.js +++ b/lib/content/page.js @@ -1,9 +1,12 @@ -const { existsSync, readFileSync, statSync } = require('fs') -const { join } = require('path') -const fm = require('front-matter') -const moment = require('moment') -const paramCase = require('param-case') -const permalinkCompiler = require('path-to-regexp').compile +import { join } from 'path' +import { readFileSync, statSync } from 'fs' + +import fm from 'front-matter' +import moment from 'moment' +import paramCase from 'param-case' +import pathToRegexp from 'path-to-regexp' + +const permalinkCompiler = pathToRegexp.compile export default function prepPage (meta, options, isDev) { const cached = {} @@ -42,7 +45,7 @@ export default function prepPage (meta, options, isDev) { const { permalink } = this if (isDev || !options.routes) return permalink const dynamicRoute = options.routes.find(route => route.method === 'get') - const nestedPath = /([^_][a-zA-z]*?)\/[^a-z\_]*/ + const nestedPath = /([^_][a-zA-z]*?)\/[^a-z_]*/ const matchedPath = dynamicRoute.path.match(nestedPath) if (matchedPath && matchedPath[1] !== 'index') { return join(matchedPath[1] + permalink) @@ -83,9 +86,10 @@ export default function prepPage (meta, options, isDev) { ) let result - let anchors = [] + const anchors = [] while ((result = anchorsExp.exec(_rawData))) { - let [match, codeSnippet, otherHeading, headingText] = result + // eslint-disable-next-line no-unused-vars + const [match, codeSnippet, otherHeading, headingText] = result if (!(codeSnippet || otherHeading) && headingText) { const anchor = `#${paramCase(headingText)}` anchors.push([anchor, headingText]) diff --git a/lib/loader.js b/lib/loader.js index 8e868cf..8d44f59 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -1,10 +1,10 @@ -const fs = require('fs') -const loaderUtils = require('loader-utils') -const { existsSync, readFileSync } = require('fs') -const { join } = require('path') -const uppercamelcase = require('uppercamelcase') -const paramCase = require('param-case') -const fm = require('front-matter') +import { existsSync } from 'fs' +import { join } from 'path' + +import loaderUtils from 'loader-utils' +import uppercamelcase from 'uppercamelcase' +import paramCase from 'param-case' +import fm from 'front-matter' const mdCompParser = mdParser => { // we need to add the `v-pre` snippet to code snippets so @@ -30,7 +30,7 @@ const mdComponent = (source, moduleOpts, dirOpts) => { let result const comps = {} while ((result = compExp.exec(source))) { - let [match, codeSnippet, name, props] = result + const [match, codeSnippet, name, props] = result if (!codeSnippet) { const compName = uppercamelcase(paramCase(name)) if (!comps[compName]) { @@ -45,7 +45,7 @@ const mdComponent = (source, moduleOpts, dirOpts) => { const { mdParser, md } = parsers return { - template: mdCompParser(parsers.mdParser(md, dirOpts)).render(source), + template: mdCompParser(mdParser(md, dirOpts)).render(source), components: comps } } @@ -108,7 +108,8 @@ function getDirOpts (moduleOpts, section) { function getSection (path) { // capture '/content/closestSubsection' or '/content' - const [match, section] = path.match(/\/content([\/][a-zA-Z\-_]*|$)/) + // eslint-disable-next-line no-unused-vars + const [match, section] = path.match(/\/content([/][a-zA-Z\-_]*|$)/) return section === '' ? '/' : section } diff --git a/lib/plugins/importMdComps.template.js b/lib/plugins/importMdComps.template.js deleted file mode 100644 index a0b4030..0000000 --- a/lib/plugins/importMdComps.template.js +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-disable */ - -function importAllMdComps (r) { - r.keys().forEach(key => r(key)) -} - -importAllMdComps( - require.context(<%= JSON.stringify(options.srcDirFromPlugin) %>, true, /\.comp\.md$/) -) diff --git a/lib/plugins/requestContent.js b/lib/plugins/requestContent.js index 2bbb36d..02d1cc6 100644 --- a/lib/plugins/requestContent.js +++ b/lib/plugins/requestContent.js @@ -1,7 +1,7 @@ const { join } = require('path') function toQuery (options = {}) { - let exclude = options.exclude + const exclude = options.exclude if (!exclude) return '' if (Array.isArray(exclude)) return 'exclude=' + exclude.join(',') diff --git a/test/unit/specs/database.spec.js b/test/unit/specs/database.spec.js index d5bac72..e380e1a 100644 --- a/test/unit/specs/database.spec.js +++ b/test/unit/specs/database.spec.js @@ -1,3 +1,4 @@ +/* eslint-disable */ /* global describe, it, expect, beforeEach, sinon */ import createDatabase from '../../../lib/content/database' From 9cc1d848c38c8500a2aa2c52842a91185a4d2dd3 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Fri, 22 Sep 2017 17:42:08 +0200 Subject: [PATCH 08/18] chore(build): fix rollup build --- rollup.config.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rollup.config.js b/rollup.config.js index 7b934c6..a797d6e 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -9,7 +9,7 @@ import copy from 'rollup-plugin-copy' const version = process.env.VERSION || require('./package.json').version -const corePlugins = () => [ +const corePlugins = [ resolve(), commonjs({ include: 'node_modules/**' @@ -50,9 +50,12 @@ export default [ 'lib/plugins': 'dist/plugins', 'lib/loader.js': 'dist/loader.js' }), - ...corePlugins() + ...corePlugins ], external: [ + 'fs', + 'path', + 'querystring', 'express', 'axios' ], From c2b96b0b4e5baf793f13d97e20b13d1ce9f76fa5 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 03:26:06 +0200 Subject: [PATCH 09/18] chore(format): add .editorconfig --- .editorconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5d12634 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false From d3f56c8d66c237c143fc670020b7980793002c67 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 03:40:41 +0200 Subject: [PATCH 10/18] chore(module): replace all remaining `require` statements by `import` --- lib/content/database.js | 6 +++--- lib/plugins/requestContent.js | 2 +- lib/util/parsers.js | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/content/database.js b/lib/content/database.js index 3f20b28..903547e 100644 --- a/lib/content/database.js +++ b/lib/content/database.js @@ -1,7 +1,7 @@ -import prepPage from './page' +import { join } from 'path' +import { readdirSync, statSync } from 'fs' -const { readdirSync, statSync } = require('fs') -const { join } = require('path') +import prepPage from './page' const { max, min } = Math diff --git a/lib/plugins/requestContent.js b/lib/plugins/requestContent.js index 02d1cc6..82fbbc3 100644 --- a/lib/plugins/requestContent.js +++ b/lib/plugins/requestContent.js @@ -1,4 +1,4 @@ -const { join } = require('path') +import { join } from 'path' function toQuery (options = {}) { const exclude = options.exclude diff --git a/lib/util/parsers.js b/lib/util/parsers.js index 656341c..d49a834 100644 --- a/lib/util/parsers.js +++ b/lib/util/parsers.js @@ -1,6 +1,6 @@ -const yamlit = require('js-yaml') -const markdownit = require('markdown-it') -const markdownAnchors = require('markdown-it-anchor') +import yamlit from 'js-yaml' +import markdownit from 'markdown-it' +import markdownAnchors from 'markdown-it-anchor' export const mdParser = ({ highlight, use }, { anchorsLevel }) => { const parser = markdownit({ From bbaf96e647c9763178f291de9826569e8ac31ca8 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 04:00:26 +0200 Subject: [PATCH 11/18] chore(build): optimize rollup build --- package.json | 1 - rollup.config.js | 16 ++++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 1185b77..76f05e1 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,6 @@ "rollup-plugin-copy": "^0.2.3", "rollup-plugin-filesize": "^1.2.1", "rollup-plugin-json": "^2.3.0", - "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-resolve": "^3.0.0", "rollup-plugin-uglify-es": "0.0.1", "rollup-watch": "^4.0.0", diff --git a/rollup.config.js b/rollup.config.js index a797d6e..67edb5c 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,23 +1,26 @@ import resolve from 'rollup-plugin-node-resolve' import json from 'rollup-plugin-json' -import builtins from 'rollup-plugin-node-builtins' import babel from 'rollup-plugin-babel' import commonjs from 'rollup-plugin-commonjs' import uglify from 'rollup-plugin-uglify-es' import filesize from 'rollup-plugin-filesize' import copy from 'rollup-plugin-copy' -const version = process.env.VERSION || require('./package.json').version +import pkg from './package.json' + +const version = process.env.VERSION || pkg.version +const external = Object.keys(pkg.dependencies || {}) const corePlugins = [ - resolve(), + resolve({ + preferBuiltins: false + }), commonjs({ include: 'node_modules/**' }), babel({ plugins: ['external-helpers'] }), - builtins(), uglify(), filesize() ] @@ -53,11 +56,12 @@ export default [ ...corePlugins ], external: [ - 'fs', 'path', + 'fs', 'querystring', 'express', - 'axios' + 'axios', + ...external ], globals: { express: 'express' From 9f554ef2ca995729eec4bd9e9d26979f61f78666 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 04:25:15 +0200 Subject: [PATCH 12/18] chore(package): fix test directory --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 76f05e1..9e00455 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "doc": "docs", "example": "examples", "lib": "lib", - "test": "tests" + "test": "test" }, "author": "Alid Castano" } From 05494cbaee50aa844702a686360db8b5f15dc942 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 04:26:09 +0200 Subject: [PATCH 13/18] chore(module): remove unused `nuxtent` binaries --- bin/nuxtent | 26 ---------------- bin/nuxtent-generate | 74 -------------------------------------------- package.json | 3 -- 3 files changed, 103 deletions(-) delete mode 100755 bin/nuxtent delete mode 100644 bin/nuxtent-generate diff --git a/bin/nuxtent b/bin/nuxtent deleted file mode 100755 index 9602a22..0000000 --- a/bin/nuxtent +++ /dev/null @@ -1,26 +0,0 @@ -#! /usr/bin/env node - -const { join } = require('path') - -const defaultCommand = 'generate' -const commands = new Set([ - defaultCommand -]) - -var cmd = process.argv[2] - -if (commands.has(cmd)) { - process.argv.splice(2, 1) -} else { - cmd = defaultCommand -} - -const bin = join(__dirname, 'nuxtent-' + cmd) - -process.on('unhandledRejection', function (err) { - /* eslint-disable no-console */ - console.error(err) - console.error('[nuxt] Unhandled promise rejection: ' + err) -}) - -require(bin) diff --git a/bin/nuxtent-generate b/bin/nuxtent-generate deleted file mode 100644 index 677e659..0000000 --- a/bin/nuxtent-generate +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env node - -process.env.DEBUG = process.env.DEBUG || 'nuxt:*' -process.env.STATIC = true - -const fs = require('fs') -const parseArgs = require('minimist') -const debug = require('debug')('nuxt:generate') - -const { Nuxt, Builder, Generator } = require('nuxt') -const { resolve } = require('path') - -const argv = parseArgs(process.argv.slice(2), { - alias: { - h: 'help', - c: 'config-file' - }, - boolean: ['h'], - string: ['c'], - default: { - c: 'nuxt.config.js' - } -}) - -const port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port -const host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host - - -if (argv.help) { - console.log(` - Description - Generate a static web application (server-rendered) - Usage - $ nuxt generate - Options - --config-file, -c Path to Nuxt.js config file (default: nuxt.config.js) - --help, -h Displays this message - `) - process.exit(0) -} - -const rootDir = resolve(argv._[0] || '.') -const nuxtConfigFile = resolve(rootDir, argv['config-file']) - -var options = {} -if (fs.existsSync(nuxtConfigFile)) { - options = require(nuxtConfigFile) -} else if (argv['config-file'] !== 'nuxt.config.js') { - console.error(`> Could not load config file ${argv['config-file']}`) - process.exit(1) -} -if (typeof options.rootDir !== 'string') { - options.rootDir = rootDir -} -options.dev = false // Force production mode (no webpack middleware called) - -debug('Generating...') -const nuxt = new Nuxt(options) - -nuxt.listen(port, host).then(()=> { - const generator = new Generator(nuxt, new Builder(nuxt)) - generator.generate() - .then(() => { - debug('Generate done') - nuxt.close() - process.exit(0) - }) - .catch((err) => { - console.error(err) // eslint-disable-line no-console - nuxt.close() - process.exit(1) - }) - -}) diff --git a/package.json b/package.json index 9e00455..1b79a34 100644 --- a/package.json +++ b/package.json @@ -22,9 +22,6 @@ "Static" ], "license": "MIT ", - "bin": { - "nuxtent": "bin/nuxtent" - }, "scripts": { "#": "handled by husky", "precommit": "lint-staged", From 66e3e738efba4e664fc79c5362c6a351c09968e7 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 13:54:31 +0200 Subject: [PATCH 14/18] chore(test): remove `rollup-plugin-node-builtins` --- test/unit/karma.conf.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/karma.conf.js b/test/unit/karma.conf.js index 2edbddc..b502d64 100644 --- a/test/unit/karma.conf.js +++ b/test/unit/karma.conf.js @@ -13,7 +13,6 @@ module.exports = function (config) { rollupPreprocessor: { plugins: [ require('rollup-plugin-node-resolve')(), - require('rollup-plugin-node-builtins')(), require('rollup-plugin-babel')(), require('rollup-plugin-commonjs')() ], From 85c0b2010c55db79d1c458b7b6c347bf311fc8c9 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 13:57:01 +0200 Subject: [PATCH 15/18] chore(lint): force curly braces around if statements --- .eslintrc | 8 +++++++- lib/content/api.js | 10 +++++----- lib/content/build.js | 12 ++++++------ lib/content/database.js | 16 ++++++++-------- lib/content/page.js | 8 ++++---- lib/loader.js | 12 ++++++------ lib/plugins/requestContent.js | 6 +++--- 7 files changed, 39 insertions(+), 33 deletions(-) diff --git a/.eslintrc b/.eslintrc index 747b130..162fe0f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -18,5 +18,11 @@ "eslint-config-i-am-meticulous", "plugin:ava/recommended", "eslint-config-prettier" - ] + ], + "rules": { + "curly": [ + "error", + "all" + ] + } } diff --git a/lib/content/api.js b/lib/content/api.js index 60a50df..3bc7ceb 100644 --- a/lib/content/api.js +++ b/lib/content/api.js @@ -47,13 +47,13 @@ function curryResponseHandler (endpoint, options) { if (permalink === '/') { // request multiple pages from directory - if (between) send.json(db.findBetween(between, query)) - else if (only) send.json(db.findOnly(only, query)) - else send.json(db.findAll(query)) + if (between) {send.json(db.findBetween(between, query))} + else if (only) {send.json(db.findOnly(only, query))} + else {send.json(db.findAll(query))} } else { // request single page - if (db.exists(permalink)) send.json(db.find(permalink, query)) - else send.notFound() + if (db.exists(permalink)) {send.json(db.find(permalink, query))} + else {send.notFound()} } } } diff --git a/lib/content/build.js b/lib/content/build.js index 00efff7..a6f75aa 100644 --- a/lib/content/build.js +++ b/lib/content/build.js @@ -111,7 +111,7 @@ function interceptRoutes (nuxt, routePaths) { route.children.forEach(nestedRoute => { if (routePaths.has(nestedRoute.name)) { const isOptional = nestedRoute.path.match(/\?$/) - if (isOptional) { nestedRoute.path = routePaths.get(nestedRoute.name) + '?' } else nestedRoute.path = routePaths.get(nestedRoute.name) + if (isOptional) { nestedRoute.path = routePaths.get(nestedRoute.name) + '?' } else {nestedRoute.path = routePaths.get(nestedRoute.name)} } }) } @@ -120,11 +120,11 @@ function interceptRoutes (nuxt, routePaths) { } function addRoutes (nuxtOpts, routeData) { - if (!('generate' in nuxtOpts)) nuxtOpts.generate = {} - if (!('routes' in nuxtOpts.generate)) nuxtOpts.generate.routes = [] + if (!('generate' in nuxtOpts)) {nuxtOpts.generate = {}} + if (!('routes' in nuxtOpts.generate)) {nuxtOpts.generate.routes = []} const { routes } = nuxtOpts.generate - if (Array.isArray(routes)) nuxtOpts.generate.routes = routes.concat(routeData) - else throw new Error(`"generate.routes" must be an array`) + if (Array.isArray(routes)) {nuxtOpts.generate.routes = routes.concat(routeData)} + else {throw new Error(`"generate.routes" must be an array`)} } function addAssets (nuxtOpts, assetMap) { @@ -145,7 +145,7 @@ function getPrefix (routeName, topLevelPrefix = '/') { if (result) { // eslint-disable-next-line no-unused-vars const [_, prefix] = result - if (prefix !== 'index') return join('/', prefix) + if (prefix !== 'index') {return join('/', prefix)} } return topLevelPrefix } diff --git a/lib/content/database.js b/lib/content/database.js index 903547e..164ad5a 100644 --- a/lib/content/database.js +++ b/lib/content/database.js @@ -33,7 +33,7 @@ export default function createDatabase (contentPath, dirName, options) { }, findOnly (onlyArg, query) { - if (typeof onlyArg === 'string') onlyArg = onlyArg.split(',') + if (typeof onlyArg === 'string') {onlyArg = onlyArg.split(',')} const [startIndex, endIndex] = onlyArg let currIndex = max(0, parseInt(startIndex)) @@ -42,7 +42,7 @@ export default function createDatabase (contentPath, dirName, options) { ? min(parseInt(endIndex), pagesArr.length - 1) : null - if (!finalIndex) return pagesArr[currIndex].create(query) + if (!finalIndex) {return pagesArr[currIndex].create(query)} const pages = [] while (currIndex <= finalIndex && finalIndex !== 0) { @@ -57,7 +57,7 @@ export default function createDatabase (contentPath, dirName, options) { const { findOnly } = this const [currPermalink, numStr1, numStr2] = betweenStr.split(',') - if (!pagesMap.has(currPermalink)) return [] + if (!pagesMap.has(currPermalink)) {return []} const currPage = pagesMap.get(currPermalink).create(query) const { index } = currPage.meta @@ -66,14 +66,14 @@ export default function createDatabase (contentPath, dirName, options) { const num1 = parseInt(numStr1 || 0) const num2 = numStr2 !== undefined ? parseInt(numStr2) : null - if (num1 === 0 && num2 === 0) return [currPage] + if (num1 === 0 && num2 === 0) {return [currPage]} let beforeRange - if (num1 === 0) beforeRange = [] - else beforeRange = [max(0, index - num1), max(min(index - 1, total), 0)] + if (num1 === 0) {beforeRange = []} + else {beforeRange = [max(0, index - num1), max(min(index - 1, total), 0)]} let afterRange - if (num2 === 0 || (!num2 && num1 === 0)) afterRange = [] + if (num2 === 0 || (!num2 && num1 === 0)) {afterRange = []} else { afterRange = [min(index + 1, total), min(index + (num2 || num1), total)] } const beforePages = findOnly(beforeRange, query) @@ -95,7 +95,7 @@ function globAndApply (dirPath, fileStore, applyFn, nestedPath = '/') { if (statSync(statPath).isFile()) { const fileData = { index, fileName: stat, section: nestedPath } applyFn(fileData, fileStore) - } else globAndApply(statPath, fileStore, applyFn, join(nestedPath, stat)) + } else {globAndApply(statPath, fileStore, applyFn, join(nestedPath, stat))} }) return fileStore } diff --git a/lib/content/page.js b/lib/content/page.js index 3deb6c8..d68f803 100644 --- a/lib/content/page.js +++ b/lib/content/page.js @@ -24,14 +24,14 @@ export default function prepPage (meta, options, isDev) { if (params.exclude) { params.exclude.split(',').forEach(prop => { - if (props.has(prop)) props.delete(prop) + if (props.has(prop)) {props.delete(prop)} }) } let data = {} props.forEach(prop => { - if (prop === 'attributes') data = { ...this[prop], ...data } - else data[prop] = this[prop] + if (prop === 'attributes') {data = { ...this[prop], ...data }} + else {data[prop] = this[prop]} }) return data @@ -43,7 +43,7 @@ export default function prepPage (meta, options, isDev) { get path () { const { permalink } = this - if (isDev || !options.routes) return permalink + if (isDev || !options.routes) {return permalink} const dynamicRoute = options.routes.find(route => route.method === 'get') const nestedPath = /([^_][a-zA-z]*?)\/[^a-z_]*/ const matchedPath = dynamicRoute.path.match(nestedPath) diff --git a/lib/loader.js b/lib/loader.js index 8d44f59..31981bc 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -88,7 +88,7 @@ function mergeParserRules (parser, rules, fn) { if (parser.renderer && parser.renderer.rules) { const parserRules = parser.renderer.rules rules.forEach(function (rule) { - if (!parserRules[rule]) return + if (!parserRules[rule]) {return} const defaultRule = parserRules[rule] parserRules[rule] = function () { return fn(defaultRule.apply(this, arguments)) @@ -102,8 +102,8 @@ function getDirOpts (moduleOpts, section) { // configuration options can be for root files ('/') but regex for section also // captures closest subsection, so we first check that since you can't configure // both root files and nested sections - if (moduleOpts.content['/']) return moduleOpts.content['/'] - else return moduleOpts.content[section] + if (moduleOpts.content['/']) {return moduleOpts.content['/']} + else {return moduleOpts.content[section]} } function getSection (path) { @@ -114,7 +114,7 @@ function getSection (path) { } function getExt (basePath, name) { - if (existsSync(basePath + name + '.vue')) return '.vue' - else if (existsSync(basePath + name + '.js')) return '.js' - else throw new Error(`"${name}" does not exist at ${basePath}`) + if (existsSync(basePath + name + '.vue')) {return '.vue'} + else if (existsSync(basePath + name + '.js')) {return '.js'} + else {throw new Error(`"${name}" does not exist at ${basePath}`)} } diff --git a/lib/plugins/requestContent.js b/lib/plugins/requestContent.js index 82fbbc3..d22f696 100644 --- a/lib/plugins/requestContent.js +++ b/lib/plugins/requestContent.js @@ -2,9 +2,9 @@ import { join } from 'path' function toQuery (options = {}) { const exclude = options.exclude - if (!exclude) return '' + if (!exclude) {return ''} - if (Array.isArray(exclude)) return 'exclude=' + exclude.join(',') + if (Array.isArray(exclude)) {return 'exclude=' + exclude.join(',')} return 'exclude=' + exclude } @@ -14,7 +14,7 @@ export default ({ app, isServer, isClient, isStatic, hotReload, route }) => { hotReload || route.fullPath.includes('__webpack_hmr?') || route.fullPath.includes('.hot-update.') - if (isNotContentReq) return + if (isNotContentReq) {return} const isAPI = isServer || !isStatic const cache = {} From 2b65ba9955a5ac2da20239eb7636454c95477bab Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 18:40:48 +0200 Subject: [PATCH 16/18] chore(loader): replace back `import` by `require` statements to fix webpack build --- lib/loader.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/loader.js b/lib/loader.js index 31981bc..b7be998 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -1,10 +1,10 @@ -import { existsSync } from 'fs' -import { join } from 'path' +const { existsSync } = require('fs') +const { join } = require('path') -import loaderUtils from 'loader-utils' -import uppercamelcase from 'uppercamelcase' -import paramCase from 'param-case' -import fm from 'front-matter' +const loaderUtils = require('loader-utils') +const uppercamelcase = require('uppercamelcase') +const paramCase = require('param-case') +const fm = require('front-matter') const mdCompParser = mdParser => { // we need to add the `v-pre` snippet to code snippets so From ebd54609344e48a83f9ea8f89fda3859439de8ca Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 18:45:24 +0200 Subject: [PATCH 17/18] fix(loader): fix `nuxtent-body` component Add `.default` in component require, compatibility with `vue-loader` v.13.0.0 --- lib/plugins/nuxtentBodyComponent.template.js | 28 +++++++++++--------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/plugins/nuxtentBodyComponent.template.js b/lib/plugins/nuxtentBodyComponent.template.js index 8d4ea55..aaa8709 100644 --- a/lib/plugins/nuxtentBodyComponent.template.js +++ b/lib/plugins/nuxtentBodyComponent.template.js @@ -3,7 +3,7 @@ import Vue from 'vue' const mdComps = {} function importAllMdComps (r) { - r.keys().forEach(key => (mdComps[key] = r(key))) + r.keys().forEach(key => (mdComps[key] = r(key).default)) } importAllMdComps( @@ -11,17 +11,21 @@ importAllMdComps( ) Vue.component('nuxtent-body', { - functional: true, - props: { - body: { required: true } - }, - render (h, ctx) { - const { body } = ctx.props - if (typeof body === 'object') { - const MarkdownComponent = mdComps[body.relativePath] - return + render: function(h) { + if (typeof this.body === 'object' && this.body.relativePath) { + const MarkdownComponent = mdComps[this.body.relativePath] + return h(MarkdownComponent) } else { - return
+ return h('div', { + domProps: { + innerHTML: this.body + } + }); + } + }, + props: { + body: { + type: [Object, String] } } -}) +}); From 55c406bff75aa7e86b9db79e888fa80bc64dd123 Mon Sep 17 00:00:00 2001 From: Mehdi Lahlou Date: Sat, 23 Sep 2017 22:41:20 +0200 Subject: [PATCH 18/18] chore(lint): fix tab instead of space --- .eslintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index 162fe0f..a661af0 100644 --- a/.eslintrc +++ b/.eslintrc @@ -14,7 +14,7 @@ "ava" ], "extends": [ - "eslint-config-standard", + "eslint-config-standard", "eslint-config-i-am-meticulous", "plugin:ava/recommended", "eslint-config-prettier"