Skip to content

Commit 85c3231

Browse files
committed
feat: free to name markdown files
1 parent 66bd797 commit 85c3231

File tree

12 files changed

+93
-24
lines changed

12 files changed

+93
-24
lines changed

lib/app/Content.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { pathToComponentName } from './util'
2-
31
export default {
42
functional: true,
53

@@ -11,7 +9,7 @@ export default {
119
},
1210

1311
render (h, { parent, props, data }) {
14-
return h(pathToComponentName(parent.$page.path), {
12+
return h(parent.$page.name, {
1513
class: [props.custom ? 'custom' : '', data.class, data.staticClass],
1614
style: data.style
1715
})

lib/app/util.js

+1-8
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,8 @@ export function injectMixins (options, mixins) {
55
options.mixins.push(...mixins)
66
}
77

8-
export function pathToComponentName (path) {
9-
if (path.charAt(path.length - 1) === '/') {
10-
return `page${path.replace(/\//g, '-') + 'index'}`
11-
} else {
12-
return `page${path.replace(/\//g, '-').replace(/\.html$/, '')}`
13-
}
14-
}
15-
168
export function findPageForPath (pages, path) {
9+
path = decodeURIComponent(path)
1710
for (let i = 0; i < pages.length; i++) {
1811
const page = pages[i]
1912
if (page.path === path) {

lib/default-theme/Layout.vue

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import Home from './Home.vue'
2727
import Navbar from './Navbar.vue'
2828
import Page from './Page.vue'
2929
import Sidebar from './Sidebar.vue'
30-
import { pathToComponentName } from '@app/util'
3130
import store from '@app/store'
3231
import { resolveSidebarItems } from './util'
3332
import throttle from 'lodash.throttle'
@@ -94,7 +93,7 @@ export default {
9493
nprogress.configure({ showSpinner: false })
9594
9695
this.$router.beforeEach((to, from, next) => {
97-
if (to.path !== from.path && !Vue.component(pathToComponentName(to.path))) {
96+
if (to.path !== from.path && !Vue.component(to.name)) {
9897
nprogress.start()
9998
}
10099
next()

lib/default-theme/SidebarLink.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script>
2-
import { isActive, hashRE, groupHeaders } from './util'
2+
import { isActive, hashRE, groupHeaders, getUrlSafePath } from './util'
33
44
export default {
55
functional: true,
@@ -32,7 +32,7 @@ export default {
3232
function renderLink (h, to, text, active) {
3333
return h('router-link', {
3434
props: {
35-
to,
35+
to: getUrlSafePath(to),
3636
activeClass: '',
3737
exactActiveClass: ''
3838
},

lib/default-theme/util.js

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ export const extRE = /\.(md|html)$/
33
export const endingSlashRE = /\/$/
44
export const outboundRE = /^(https?:|mailto:|tel:)/
55

6+
import { getUrlSafePath } from '../util/shared'
7+
export { getUrlSafePath }
8+
69
export function normalize (path) {
710
return path
811
.replace(hashRE, '')
@@ -43,6 +46,7 @@ export function ensureExt (path) {
4346
}
4447

4548
export function isActive (route, path) {
49+
path = getUrlSafePath(path)
4650
const routeHash = route.hash
4751
const linkHash = getHash(path)
4852
if (linkHash && routeHash !== linkHash) {

lib/dev.js

+18
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ module.exports = async function dev (sourceDir, cliOptions = {}) {
5353
// resolve webpack config
5454
let config = createClientConfig(options, cliOptions)
5555

56+
// virtual-modules
57+
let virtualModules
58+
config.plugin('virtual-modules').init(
59+
(Plugin, args) => {
60+
virtualModules = new Plugin(...args)
61+
return virtualModules
62+
}
63+
)
64+
5665
config
5766
.plugin('html')
5867
// using a fork of html-webpack-plugin to avoid it requiring webpack
@@ -84,6 +93,15 @@ module.exports = async function dev (sourceDir, cliOptions = {}) {
8493
portfinder.basePort = cliOptions.port || options.siteConfig.port || 8080
8594
const port = await portfinder.getPortPromise()
8695

96+
// virtual-modules
97+
compiler.hooks.watchRun.tap('vuepress', () => {
98+
delete require.cache[require.resolve('./app/.temp/pageContent')]
99+
const pageContent = require('./app/.temp/pageContent')
100+
Object.keys(pageContent).forEach(pagePath => {
101+
virtualModules.writeModule(pagePath, pageContent[pagePath])
102+
})
103+
})
104+
87105
let isFirst = true
88106
compiler.hooks.done.tap('vuepress', () => {
89107
if (isFirst) {

lib/prepare.js

+32-8
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ const {
99
inferTitle,
1010
extractHeaders,
1111
parseFrontmatter,
12-
getGitLastUpdatedTimeStamp
12+
getGitLastUpdatedTimeStamp,
13+
getUrlSafePath,
14+
getPageComponentName
1315
} = require('./util')
1416

1517
fs.ensureDirSync(tempPath)
@@ -71,6 +73,16 @@ if (!Object.assign) Object.assign = require('object-assign')`
7173
// 7. handle the theme enhanceApp.js
7274
await writeEnhanceTemp('themeEnhanceApp.js', options.themeEnhanceAppPath)
7375

76+
// 8. generate page content
77+
const pageContent = options.siteData.pages.reduce(
78+
(pageContent, { name: componentName, filepath, content }) => {
79+
pageContent[pageFilePathToVirtualPath(filepath, componentName)] = content
80+
return pageContent
81+
},
82+
{}
83+
)
84+
writeTemp('pageContent.js', `module.exports = ${JSON.stringify(pageContent)}`)
85+
7486
return options
7587
}
7688

@@ -204,8 +216,14 @@ async function resolveOptions (sourceDir) {
204216
data.lastUpdated = getGitLastUpdatedTimeStamp(filepath)
205217
}
206218

207-
// extract yaml frontmatter
208219
const content = await fs.readFile(filepath, 'utf-8')
220+
Object.defineProperty(data, 'filepath', { value: filepath })
221+
Object.defineProperty(data, 'content', { value: content })
222+
223+
// get page component name
224+
data.name = getPageComponentName(data.path)
225+
226+
// extract yaml frontmatter
209227
const frontmatter = parseFrontmatter(content)
210228
// infer title
211229
const title = inferTitle(frontmatter)
@@ -297,6 +315,11 @@ function fileToComponentName (file) {
297315
return `${pagePrefix}${normalizedName}`
298316
}
299317

318+
function pageFilePathToVirtualPath (filepath, componentName) {
319+
const { dir, ext } = path.parse(filepath)
320+
return path.join(dir, `__${componentName}__${ext}`)
321+
}
322+
300323
function isIndexFile (file) {
301324
return indexRE.test(file)
302325
}
@@ -310,16 +333,17 @@ async function resolveComponents (sourceDir) {
310333
}
311334

312335
async function genRoutesFile ({ siteData: { pages }, sourceDir, pageFiles }) {
313-
function genRoute ({ path: pagePath }, index) {
336+
function genRoute ({ path: pagePath, content, name: componentName }, index) {
314337
const file = pageFiles[index]
315338
const filePath = path.resolve(sourceDir, file)
316339
let code = `
317340
{
318-
path: ${JSON.stringify(pagePath)},
341+
name: ${JSON.stringify(componentName)},
342+
path: ${JSON.stringify(getUrlSafePath(pagePath))},
319343
component: ThemeLayout,
320344
beforeEnter: (to, from, next) => {
321-
import(${JSON.stringify(filePath)}).then(comp => {
322-
Vue.component(${JSON.stringify(fileToComponentName(file))}, comp.default)
345+
import(${JSON.stringify(pageFilePathToVirtualPath(filePath, componentName))}).then(comp => {
346+
Vue.component(${JSON.stringify(componentName)}, comp.default)
323347
next()
324348
})
325349
}
@@ -328,8 +352,8 @@ async function genRoutesFile ({ siteData: { pages }, sourceDir, pageFiles }) {
328352
if (/\/$/.test(pagePath)) {
329353
code += `,
330354
{
331-
path: ${JSON.stringify(pagePath + 'index.html')},
332-
redirect: ${JSON.stringify(pagePath)}
355+
path: ${JSON.stringify(getUrlSafePath(pagePath + 'index.html'))},
356+
redirect: ${JSON.stringify(getUrlSafePath(pagePath))}
333357
}`
334358
}
335359

lib/util/index.js

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
const spawn = require('cross-spawn')
22
const parseHeaders = require('./parseHeaders')
3+
const shared = require('./shared')
4+
5+
Object.assign(exports, shared)
36

47
exports.parseHeaders = parseHeaders
58

@@ -88,3 +91,12 @@ exports.extractHeaders = (content, include = [], md) => {
8891
exports.getGitLastUpdatedTimeStamp = filepath => {
8992
return parseInt(spawn.sync('git', ['log', '-1', '--format=%ct', filepath]).stdout.toString('utf-8')) * 1000
9093
}
94+
95+
let pageComponentID = 0
96+
const pageComponentsCache = new Map()
97+
exports.getPageComponentName = pagePath => {
98+
if (!pageComponentsCache.has(pagePath)) {
99+
pageComponentsCache.set(pagePath, `page-${pageComponentID++}`)
100+
}
101+
return pageComponentsCache.get(pagePath)
102+
}

lib/util/shared.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
exports.getUrlSafePath = rawPath => {
2+
const [path, anchor] = rawPath.split(/#(?=[^#]*$)/)
3+
return (
4+
path
5+
.split(/[/\\]+/)
6+
.map(name => encodeURIComponent(name))
7+
.join('/')
8+
) + (anchor ? `#${anchor}` : '')
9+
}

lib/webpack/createBaseConfig.js

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module.exports = function createBaseConfig ({
1414
const Config = require('webpack-chain')
1515
const { VueLoaderPlugin } = require('vue-loader')
1616
const CSSExtractPlugin = require('mini-css-extract-plugin')
17+
const VirtualModulesPlugin = require('webpack-virtual-modules')
1718

1819
const isProd = process.env.NODE_ENV === 'production'
1920
const inlineLimit = 10000
@@ -255,5 +256,9 @@ module.exports = function createBaseConfig ({
255256
SW_ENABLED: !!siteConfig.serviceWorker
256257
}])
257258

259+
config
260+
.plugin('virtual-modules')
261+
.use(VirtualModulesPlugin, [require('../app/.temp/pageContent')])
262+
258263
return config
259264
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"webpack-chain": "^4.6.0",
9797
"webpack-merge": "^4.1.2",
9898
"webpack-serve": "^0.3.1",
99+
"webpack-virtual-modules": "^0.1.10",
99100
"webpackbar": "^2.6.1",
100101
"workbox-build": "^3.1.0"
101102
},

yarn.lock

+7-1
Original file line numberDiff line numberDiff line change
@@ -2230,7 +2230,7 @@ de-indent@^1.0.2:
22302230
version "1.0.2"
22312231
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
22322232

2233-
debug@*, debug@^3.1.0:
2233+
debug@*, debug@^3.0.0, debug@^3.1.0:
22342234
version "3.1.0"
22352235
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
22362236
dependencies:
@@ -7472,6 +7472,12 @@ webpack-sources@^1.0.1, webpack-sources@^1.1.0:
74727472
source-list-map "^2.0.0"
74737473
source-map "~0.6.1"
74747474

7475+
webpack-virtual-modules@^0.1.10:
7476+
version "0.1.10"
7477+
resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.1.10.tgz#2039529cbf1007e19f6e897c8d35721cc2c41f68"
7478+
dependencies:
7479+
debug "^3.0.0"
7480+
74757481
webpack@^4.8.1:
74767482
version "4.8.1"
74777483
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.8.1.tgz#59e38f99f2751c931dd09a035aba7bec4b5f916e"

0 commit comments

Comments
 (0)