Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support filename that contains non-ASCII and unicode chars #473

Merged
merged 11 commits into from
May 24, 2018
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ footer: MIT Licensed | Copyright © 2018-present Evan You

### As Easy as 1, 2, 3

- [尤](./尤.md)

``` bash
# install
yarn global add vuepress # OR npm install -g vuepress
Expand Down
3 changes: 3 additions & 0 deletions docs/尤.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 尤

- [雨](./雨.md)
3 changes: 3 additions & 0 deletions docs/溪.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 溪

- [Homepage](./)
3 changes: 3 additions & 0 deletions docs/雨.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 雨

- [溪](./溪.md)
4 changes: 1 addition & 3 deletions lib/app/Content.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { pathToComponentName } from './util'

export default {
functional: true,

Expand All @@ -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
})
Expand Down
8 changes: 0 additions & 8 deletions lib/app/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion lib/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions lib/default-theme/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
Expand Down
19 changes: 16 additions & 3 deletions lib/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果 filepath 包含 ! 号,如:/docs/hello!.md,因为使用了 Webpack,! 前面的内容会被认为是 loader 的配置,见:https://webpack.js.org/concepts/loaders/#inline。在我的 PR 中,我使用了 webpack-virtual-modules 解决了这个问题。

Copy link
Member Author

@ulivz ulivz May 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since webpack does not support the path containing ! and even throw error for that: webpack/webpack#6754 .

So we don't need to introduce webpack-virtual-modules to support ! which should be handled by webpack instead of VuePress.

We don't need to introduce a huge hack to cater to it for an illegal use case.

Copy link
Contributor

@fjc0k fjc0k May 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

哈哈,补充下我的思路。

文件:/docs/hello!.md

我们可以在 VuePress 里读取 hello!.md 的内容,并用它生成一个与 hello!.md 同级的 virtual module,比如:docs/page-1.md,然后 import('docs/page-1.md'),如此即可避免 ! 的问题,同时因为是同级目录,原文件里的路径都不用改变。

Copy link
Member Author

@ulivz ulivz May 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我用中文重申一下:我们没有必要为了一个并不合法的极少数用例来引入庞大的代码hack。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好吧,我想 ! 仅仅是对于 Webpack 不合法。

Copy link
Member Author

@ulivz ulivz May 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

既然 VuePress 基于 Webpack,本着职责清晰的原则,我们不应该在 VuePress 中来解决 Webpack 的问题,万一哪天 Webpack 有自己的解决方案呢?此外,你这种解决方案太复杂了。

如果你需要这个 feature,请给 Webpack 提 Issue 或者 PR,谢谢。

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 += `,
{
Expand Down
4 changes: 4 additions & 0 deletions lib/util/index.js
Original file line number Diff line number Diff line change
@@ -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 => {
Expand Down