2019-06-06 23:12:57 +08:00
|
|
|
import path from 'path'
|
2019-06-20 04:36:42 +08:00
|
|
|
import fs from 'fs'
|
2019-06-19 21:05:16 +08:00
|
|
|
import markdownIt from 'markdown-it'
|
|
|
|
import miLinkAttributes from 'markdown-it-link-attributes'
|
|
|
|
import miAnchor from 'markdown-it-anchor'
|
|
|
|
import uslug from 'uslug'
|
2019-12-04 17:30:50 +08:00
|
|
|
import Mode from 'frontmatter-markdown-loader/mode'
|
2020-01-14 16:04:09 +08:00
|
|
|
|
|
|
|
import { Configuration } from '@nuxt/types'
|
|
|
|
import pkg from './package.json'
|
2020-01-09 19:22:15 +08:00
|
|
|
import generateTextbookToc from './hooks/generate-textbook-toc'
|
2019-06-06 14:30:22 +08:00
|
|
|
|
2019-06-19 21:05:16 +08:00
|
|
|
const md = markdownIt({
|
|
|
|
linkify: true,
|
|
|
|
html: true
|
|
|
|
})
|
|
|
|
md.use(miLinkAttributes, {
|
|
|
|
pattern: /^https?:/,
|
|
|
|
attrs: {
|
|
|
|
target: '_blank',
|
|
|
|
rel: 'noopener'
|
|
|
|
}
|
|
|
|
})
|
|
|
|
md.use(miAnchor, {
|
2019-12-05 21:24:45 +08:00
|
|
|
slugify (id) { return uslug(id) }
|
2019-06-19 21:05:16 +08:00
|
|
|
})
|
|
|
|
|
2020-01-14 16:04:09 +08:00
|
|
|
const config: Configuration = {
|
2019-09-05 16:06:14 +08:00
|
|
|
mode: 'universal',
|
2019-06-06 14:30:22 +08:00
|
|
|
|
2019-12-27 01:58:03 +08:00
|
|
|
env: {
|
|
|
|
analyticsScriptUrl: process.env.NODE_ENV === 'development'
|
|
|
|
? 'https://dev.console.test.cloud.ibm.com/analytics/build/bluemix-analytics.min.js'
|
|
|
|
: 'https://cloud.ibm.com/analytics/build/bluemix-analytics.min.js',
|
|
|
|
analyticsKey: process.env.NODE_ENV === 'development'
|
|
|
|
? 'zbHWEXPUfXm0K6C7HbegwB5ewDEC8o1H'
|
|
|
|
: 'ffdYLviQze3kzomaINXNk6NwpY9LlXcw'
|
|
|
|
},
|
|
|
|
|
2019-06-06 14:30:22 +08:00
|
|
|
/*
|
|
|
|
** Headers of the page
|
|
|
|
*/
|
|
|
|
head: {
|
|
|
|
title: pkg.name,
|
|
|
|
meta: [
|
|
|
|
{ charset: 'utf-8' },
|
|
|
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
|
|
|
{ hid: 'description', name: 'description', content: pkg.description }
|
|
|
|
],
|
|
|
|
link: [
|
|
|
|
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
|
2019-12-27 01:58:03 +08:00
|
|
|
]
|
2019-06-06 14:30:22 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Customize the progress-bar color
|
|
|
|
*/
|
|
|
|
loading: { color: '#fff' },
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Global CSS
|
|
|
|
*/
|
|
|
|
css: [
|
|
|
|
],
|
|
|
|
|
|
|
|
/*
|
2020-01-08 19:13:51 +08:00
|
|
|
** Plugins to load before mounting the App.
|
2019-06-06 14:30:22 +08:00
|
|
|
*/
|
|
|
|
plugins: [
|
2020-01-08 19:13:51 +08:00
|
|
|
'~/plugins/router-hooks.ts',
|
2019-10-21 05:18:36 +08:00
|
|
|
'~/plugins/directives.ts',
|
2019-11-27 16:28:33 +08:00
|
|
|
'~/plugins/deep-load.ts',
|
2019-12-26 17:09:18 +08:00
|
|
|
{ src: '~/plugins/hotjar.ts', mode: 'client' },
|
|
|
|
{ src: '~/plugins/segment-analytics.ts', mode: 'client' }
|
2019-06-06 14:30:22 +08:00
|
|
|
],
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Nuxt.js modules
|
|
|
|
*/
|
|
|
|
modules: [
|
2019-11-07 19:11:45 +08:00
|
|
|
'@nuxtjs/style-resources'
|
2019-06-06 14:30:22 +08:00
|
|
|
],
|
|
|
|
|
2019-11-07 19:11:45 +08:00
|
|
|
styleResources: {
|
|
|
|
/*
|
|
|
|
** Do not include styles! Only variables, mixins and functions.
|
|
|
|
*/
|
|
|
|
scss: [
|
|
|
|
'./assets/scss/mq.scss',
|
|
|
|
'./assets/scss/mixins.scss'
|
|
|
|
]
|
|
|
|
},
|
|
|
|
|
2019-08-31 23:28:28 +08:00
|
|
|
/*
|
|
|
|
** Migrating from Nuxt 2.8.x to 2.9.y
|
|
|
|
** https://typescript.nuxtjs.org/migration.html
|
|
|
|
*/
|
|
|
|
buildModules: [
|
|
|
|
['@nuxt/typescript-build', {
|
|
|
|
typeCheck: true,
|
|
|
|
ignoreNotFoundWarnings: true
|
|
|
|
}]
|
|
|
|
],
|
|
|
|
|
2019-06-06 14:30:22 +08:00
|
|
|
/*
|
|
|
|
** Build configuration
|
|
|
|
*/
|
|
|
|
build: {
|
|
|
|
/*
|
|
|
|
** You can extend webpack config here
|
|
|
|
*/
|
2019-12-05 21:24:45 +08:00
|
|
|
extend (config) {
|
2020-01-14 16:04:09 +08:00
|
|
|
config.module = config.module || { rules: [] }
|
2019-06-06 23:12:57 +08:00
|
|
|
config.module.rules.push({
|
|
|
|
test: /\.md$/,
|
|
|
|
loader: 'frontmatter-markdown-loader',
|
2019-07-24 20:20:06 +08:00
|
|
|
include: path.resolve(__dirname, 'content'),
|
2019-06-06 23:12:57 +08:00
|
|
|
options: {
|
2019-12-05 02:15:02 +08:00
|
|
|
mode: [Mode.VUE_RENDER_FUNCTIONS, Mode.VUE_COMPONENT, Mode.HTML],
|
2019-06-06 23:12:57 +08:00
|
|
|
vue: {
|
2019-07-24 20:20:06 +08:00
|
|
|
root: 'content'
|
2019-06-19 21:05:16 +08:00
|
|
|
},
|
|
|
|
markdown: (body) => {
|
|
|
|
return md.render(body)
|
2019-06-06 23:12:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2019-06-25 04:23:22 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
// TODO: Workaround for dealing with. Remove once its solved:
|
|
|
|
// https://github.com/nuxt/nuxt.js/issues/3877
|
|
|
|
splitChunks: {
|
|
|
|
layouts: true
|
2019-06-06 14:30:22 +08:00
|
|
|
}
|
2019-06-19 21:05:16 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
router: {
|
2020-01-20 16:14:04 +08:00
|
|
|
scrollBehavior (to, from) {
|
|
|
|
const nuxt = window.$nuxt
|
|
|
|
|
|
|
|
// Force `triggerScroll` when navigating through the page.
|
|
|
|
// Did not found the event `triggerScroll` documented but it is used in
|
|
|
|
// the default behaviour to ensure the page has loaded:
|
|
|
|
// https://github.com/nuxt/nuxt.js/blob/e3ba6c290dd60e1a8c5b7daec72982a667a7fe04/packages/vue-app/template/router.scrollBehavior.js
|
|
|
|
if (to.path === from.path && to.hash !== from.hash) {
|
|
|
|
nuxt.$nextTick(() => nuxt.$emit('triggerScroll'))
|
2019-06-19 21:05:16 +08:00
|
|
|
}
|
|
|
|
|
2020-01-20 16:14:04 +08:00
|
|
|
return new Promise((resolve) => {
|
|
|
|
nuxt.$once('triggerScroll', () => {
|
|
|
|
if (!to.hash) {
|
|
|
|
return resolve()
|
|
|
|
}
|
|
|
|
|
|
|
|
const el: HTMLElement | null = document.querySelector(to.hash)
|
|
|
|
if (!el) {
|
|
|
|
console.warn('Trying to navigate to a missing element', to.hash)
|
|
|
|
return resolve()
|
|
|
|
}
|
|
|
|
|
|
|
|
if ('scrollBehavior' in document.documentElement.style) {
|
|
|
|
window.scrollTo({ top: el.offsetTop, behavior: 'smooth' })
|
|
|
|
} else {
|
|
|
|
window.scrollTo(0, el.offsetTop)
|
|
|
|
}
|
|
|
|
|
|
|
|
return resolve()
|
|
|
|
})
|
|
|
|
})
|
2019-06-19 21:05:16 +08:00
|
|
|
}
|
2019-06-20 04:36:42 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
generate: {
|
|
|
|
routes: (function () {
|
2020-01-21 20:52:21 +08:00
|
|
|
const events = getContentUrls('events')
|
|
|
|
const experiments = getContentUrls('experiments')
|
2019-07-30 01:16:07 +08:00
|
|
|
return events.concat(experiments)
|
2020-01-21 20:52:21 +08:00
|
|
|
|
|
|
|
function getContentUrls (contentRoot: string): string[] {
|
|
|
|
return fs.readdirSync(path.resolve(__dirname, 'content', contentRoot))
|
|
|
|
.filter(isContentAndNotReadme)
|
|
|
|
.map(toContentUrl(contentRoot))
|
|
|
|
}
|
|
|
|
|
|
|
|
function isContentAndNotReadme (filename: string): boolean {
|
|
|
|
return path.extname(filename) === '.md' &&
|
|
|
|
path.parse(filename).name.toUpperCase() !== 'README'
|
|
|
|
}
|
|
|
|
|
|
|
|
function toContentUrl (contentRoot: string): (s: string) => string {
|
|
|
|
return (filename: string): string => {
|
|
|
|
return `/${contentRoot}/${path.parse(filename).name}`
|
|
|
|
}
|
|
|
|
}
|
2019-06-20 04:36:42 +08:00
|
|
|
})()
|
2019-10-29 16:53:51 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
hooks: {
|
|
|
|
build: {
|
2019-12-05 21:24:45 +08:00
|
|
|
before () {
|
2019-10-29 16:53:51 +08:00
|
|
|
generateTextbookToc(
|
2019-12-05 01:22:33 +08:00
|
|
|
'./static/textbook/preface.html',
|
2019-10-29 16:53:51 +08:00
|
|
|
'./content/education/textbook-toc.md'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2019-06-06 14:30:22 +08:00
|
|
|
}
|
|
|
|
}
|
2020-01-14 16:04:09 +08:00
|
|
|
|
|
|
|
export default config
|