From 566e68103330353e87d4278174236f0eda75724a Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Thu, 24 May 2018 23:49:50 +0800 Subject: [PATCH] feat: support filename that contains non-ASCII and unicode chars (#473) --- lib/app/Content.js | 4 +--- lib/app/util.js | 8 -------- lib/build.js | 2 +- lib/default-theme/Layout.vue | 5 +++-- lib/prepare.js | 19 ++++++++++++++++--- lib/util/index.js | 4 ++++ 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/app/Content.js b/lib/app/Content.js index 4b3b4c88f5..46628195e6 100644 --- a/lib/app/Content.js +++ b/lib/app/Content.js @@ -1,5 +1,3 @@ -import { pathToComponentName } from './util' - export default { functional: true, @@ -11,7 +9,7 @@ export default { }, render (h, { parent, props, data }) { - return h(pathToComponentName(parent.$page.path), { + return h(parent.$page.key, { class: [props.custom ? 'custom' : '', data.class, data.staticClass], style: data.style }) diff --git a/lib/app/util.js b/lib/app/util.js index ceafb220c6..c11172240e 100644 --- a/lib/app/util.js +++ b/lib/app/util.js @@ -5,14 +5,6 @@ export function injectMixins (options, mixins) { options.mixins.push(...mixins) } -export function pathToComponentName (path) { - if (path.charAt(path.length - 1) === '/') { - return `page${path.replace(/\//g, '-') + 'index'}` - } else { - return `page${path.replace(/\//g, '-').replace(/\.html$/, '')}` - } -} - export function findPageForPath (pages, path) { for (let i = 0; i < pages.length; i++) { const page = pages[i] diff --git a/lib/build.js b/lib/build.js index 149f9f93a0..b96f1096b4 100644 --- a/lib/build.js +++ b/lib/build.js @@ -153,7 +153,7 @@ module.exports = async function build (sourceDir, cliOptions = {}) { console.error(chalk.red(`Error rendering ${pagePath}:`)) throw e } - const filename = pagePath.replace(/\/$/, '/index.html').replace(/^\//, '') + const filename = decodeURIComponent(pagePath.replace(/\/$/, '/index.html').replace(/^\//, '')) const filePath = path.resolve(outDir, filename) await fs.ensureDir(path.dirname(filePath)) await fs.writeFile(filePath, html) diff --git a/lib/default-theme/Layout.vue b/lib/default-theme/Layout.vue index 329b8e2ebd..7b422a41fa 100644 --- a/lib/default-theme/Layout.vue +++ b/lib/default-theme/Layout.vue @@ -27,7 +27,6 @@ import Home from './Home.vue' import Navbar from './Navbar.vue' import Page from './Page.vue' import Sidebar from './Sidebar.vue' -import { pathToComponentName } from '@app/util' import { resolveSidebarItems } from './util' export default { @@ -86,11 +85,13 @@ export default { }, mounted () { + window.addEventListener('scroll', this.onScroll) + // configure progress bar nprogress.configure({ showSpinner: false }) this.$router.beforeEach((to, from, next) => { - if (to.path !== from.path && !Vue.component(pathToComponentName(to.path))) { + if (to.path !== from.path && !Vue.component(to.name)) { nprogress.start() } next() diff --git a/lib/prepare.js b/lib/prepare.js index 28bffafa73..eaecbee09a 100644 --- a/lib/prepare.js +++ b/lib/prepare.js @@ -5,6 +5,7 @@ const createMarkdown = require('./markdown') const loadConfig = require('./util/loadConfig') const tempPath = path.resolve(__dirname, 'app/.temp') const { + encodePath, inferTitle, extractHeaders, parseFrontmatter, @@ -181,8 +182,10 @@ async function resolveOptions (sourceDir) { // resolve pagesData const pagesData = await Promise.all(pageFiles.map(async (file) => { const filepath = path.resolve(sourceDir, file) + const key = 'v-' + Math.random().toString(16).slice(2) const data = { - path: fileToPath(file) + key, + path: encodePath(fileToPath(file)) } if (shouldResolveLastUpdated) { @@ -296,21 +299,31 @@ async function resolveComponents (sourceDir) { } async function genRoutesFile ({ siteData: { pages }, sourceDir, pageFiles }) { - function genRoute ({ path: pagePath }, index) { + function genRoute ({ path: pagePath, key: componentName }, index) { const file = pageFiles[index] const filePath = path.resolve(sourceDir, file) let code = ` { + name: ${JSON.stringify(componentName)}, path: ${JSON.stringify(pagePath)}, component: ThemeLayout, beforeEnter: (to, from, next) => { import(${JSON.stringify(filePath)}).then(comp => { - Vue.component(${JSON.stringify(fileToComponentName(file))}, comp.default) + Vue.component(${JSON.stringify(componentName)}, comp.default) next() }) } }` + const dncodedPath = decodeURIComponent(pagePath) + if (dncodedPath !== pagePath) { + code += `, + { + path: ${JSON.stringify(dncodedPath)}, + redirect: ${JSON.stringify(pagePath)} + }` + } + if (/\/$/.test(pagePath)) { code += `, { diff --git a/lib/util/index.js b/lib/util/index.js index b9266dc85e..b881b5fb9d 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -1,6 +1,10 @@ const spawn = require('cross-spawn') const parseHeaders = require('./parseHeaders') +exports.encodePath = function (path) { + return path.split('/').map(item => encodeURIComponent(item)).join('/') +} + exports.parseHeaders = parseHeaders exports.normalizeHeadTag = tag => {