Skip to content

Commit 72e5666

Browse files
committed
title inferrence
1 parent 6471d4f commit 72e5666

File tree

8 files changed

+148
-49
lines changed

8 files changed

+148
-49
lines changed

docs/vuepress.config.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
data: {
3+
title: 'VuePress'
4+
}
5+
}

lib/app/Content.js

+21-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
export default {
22
created () {
33
if (this.$ssrContext) {
4-
this.$ssrContext.title = getMetadata(this, 'title') || 'VuePress'
5-
this.$ssrContext.lang = getMetadata(this, 'lang') || 'en'
4+
this.$ssrContext.title = getTitle(this)
5+
this.$ssrContext.lang = getLang(this)
66
}
77
},
88
mounted () {
99
const updateMeta = () => {
10-
document.title = getMetadata(this, 'title') || 'VuePress'
11-
document.documentElement.lang = getMetadata(this, 'lang') || 'en'
10+
document.title = getTitle(this)
11+
document.documentElement.lang = getLang(this)
1212
}
1313
this.$watch('$page', updateMeta)
1414
updateMeta()
@@ -24,6 +24,21 @@ export default {
2424
}
2525
}
2626

27-
function getMetadata (vm, key) {
28-
return vm.$page.frontmatter[key] || vm.$page[key] || vm.$site[key]
27+
function getTitle (vm) {
28+
const selfTitle = (
29+
vm.$page.frontmatter.title || // explicit title
30+
vm.$page.title // inferred title
31+
)
32+
const siteTitle = vm.$site.title
33+
return siteTitle
34+
? selfTitle
35+
? siteTitle + ' | ' + selfTitle
36+
: siteTitle
37+
: selfTitle
38+
? selfTitle
39+
: 'VuePress'
40+
}
41+
42+
function getLang (vm) {
43+
return vm.$page.frontmatter.lang
2944
}

lib/default-theme/Layout.vue

+16
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,19 @@ export default {
3434

3535
<style src="prismjs/themes/prism-tomorrow.css"></style>
3636
<style src="./nprogress.css"></style>
37+
<style>
38+
.theme-container {
39+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
40+
}
41+
42+
pre[class*="language-"] {
43+
line-height: 1.4;
44+
border-radius: 5px;
45+
}
46+
47+
pre[class*="language-"] code {
48+
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
49+
font-size: 14px;
50+
-webkit-font-smoothing: antialiased;
51+
}
52+
</style>

lib/markdown/highlight.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const prism = require('prismjs')
2+
const loadLanguages = require('prismjs/components/index')
3+
4+
module.exports = (str, lang) => {
5+
if (lang === 'vue') {
6+
lang = 'html'
7+
}
8+
if (!prism.languages[lang]) {
9+
try {
10+
loadLanguages([lang])
11+
} catch (e) {
12+
throw new Error(`[vuepress] Syntax highlight for language "${lang}" is not supported.`)
13+
return ''
14+
}
15+
}
16+
if (prism.languages[lang]) {
17+
let res = prism.highlight(str, prism.languages[lang], lang)
18+
return `<pre class="language-${lang}"><code v-pre>${res}</code></pre>`
19+
}
20+
return ''
21+
}

lib/markdown/index.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const highlight = require('./highlight')
2+
const convertRouterLink = require('./link')
3+
const container = require('markdown-it-container')
4+
5+
// TODO extract <style> blocks and <script> blocks
6+
// TODO support inline demo
7+
8+
module.exports = require('markdown-it')({
9+
html: true,
10+
typographer: true,
11+
highlight
12+
})
13+
.use(convertRouterLink)
14+
.use(container, 'tip')
15+
.use(container, 'warning')
16+
.use(container, 'danger')

lib/markdown/link.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module.exports = md => {
2+
let hasOpenLink = false
3+
4+
md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
5+
const token = tokens[idx]
6+
const hrefIndex = token.attrIndex('href')
7+
if (hrefIndex >= 0) {
8+
const link = token.attrs[hrefIndex]
9+
const href = link[1]
10+
if (!/^https?:/.test(href) && /\.(md|html)$/.test(href)) {
11+
hasOpenLink = true
12+
tokens[idx] = toRouterLink(token, link)
13+
}
14+
}
15+
return self.renderToken(tokens, idx, options)
16+
}
17+
18+
function toRouterLink (token, link) {
19+
link[0] = 'to'
20+
link[1] = link[1].replace(/\.md$/, '.html')
21+
return Object.assign({}, token, {
22+
tag: 'router-link'
23+
})
24+
}
25+
26+
md.renderer.rules.link_close = (tokens, idx, options, env, self) => {
27+
const token = tokens[idx]
28+
if (hasOpenLink) {
29+
token.tag = 'router-link'
30+
hasOpenLink = false
31+
}
32+
return self.renderToken(tokens, idx, options)
33+
}
34+
}

lib/prepare.js

+33-14
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,45 @@ module.exports = async function prepare (sourceDir) {
3131

3232
async function resolveOptions (sourceDir) {
3333
const configPath = path.resolve(sourceDir, 'vuepress.config.js')
34-
const siteConfig = fs.existsSync(configPath) ? require(configPath) : {}
34+
const userConfig = fs.existsSync(configPath) ? require(configPath) : {}
35+
36+
const hasTheme = userConfig.theme || fs.existsSync(path.resolve(sourceDir, '_theme'))
3537

3638
const options = {
37-
siteConfig,
3839
sourceDir,
39-
publicPath: siteConfig.baseUrl || '/',
40-
themePath: path.resolve(__dirname, 'default-theme/Layout.vue'),
41-
notFoundPath: path.resolve(__dirname, 'default-theme/NotFound.vue'),
40+
publicPath: userConfig.baseUrl || '/',
4241
pages: await globby(['**/*.md'], { cwd: sourceDir })
4342
}
4443

45-
// resolve theme
46-
const themePath = path.resolve(sourceDir, '_theme/Layout.vue')
47-
if (fs.existsSync(themePath)) {
48-
options.themePath = themePath
49-
}
44+
if (!hasTheme) {
45+
// use default theme
46+
options.siteConfig = userConfig
47+
options.themePath = path.resolve(__dirname, 'default-theme/Layout.vue')
48+
options.notFoundPath = path.resolve(__dirname, 'default-theme/NotFound.vue')
49+
} else {
50+
// resolve theme
51+
const themeDir = userConfig.theme
52+
? path.resolve(__dirname, `../../${userConfig.theme}`)
53+
: path.resolve(sourceDir, '_theme')
54+
const themeConfigPath = path.resolve(themeDir, 'config.js')
55+
const themeConfig = fs.existsSync(themeConfigPath)
56+
? require(themeConfigPath)
57+
: {}
58+
options.siteConfig = Object.assign(themeConfig, userConfig)
59+
60+
const themePath = path.resolve(themeDir, 'Layout.vue')
61+
if (fs.existsSync(themePath)) {
62+
options.themePath = themePath
63+
} else {
64+
throw new Error('[vuepress] Custom theme must have a Layout.vue file.')
65+
}
5066

51-
const notFoundPath = path.resolve(sourceDir, '_theme/NotFound.vue')
52-
if (fs.existsSync(notFoundPath)) {
53-
options.notFoundPath = notFoundPath
67+
const notFoundPath = path.resolve(themeDir, '/NotFound.vue')
68+
if (fs.existsSync(notFoundPath)) {
69+
options.notFoundPath = notFoundPath
70+
} else {
71+
throw new Error('[vuepress] Custom theme must have a NotFound.vue file.')
72+
}
5473
}
5574

5675
const pagesData = options.pages.map(file => {
@@ -75,7 +94,7 @@ async function resolveOptions (sourceDir) {
7594
return data
7695
})
7796

78-
options.siteData = Object.assign({}, siteConfig.data, {
97+
options.siteData = Object.assign({}, userConfig.data, {
7998
pages: pagesData
8099
})
81100

lib/webpack/markdownLoader.js

+2-29
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,8 @@
1-
const prism = require('prismjs')
1+
const md = require('../markdown')
22
const frontmatter = require('yaml-front-matter')
3-
const loadLanguages = require('prismjs/components/index')
4-
5-
const md = require('markdown-it')({
6-
html: true,
7-
typographer: true,
8-
highlight: (str, lang) => {
9-
if (lang === 'vue') {
10-
lang = 'html'
11-
}
12-
if (!prism.languages[lang]) {
13-
try {
14-
loadLanguages([lang])
15-
} catch (e) {
16-
throw new Error(`[vuepress] Syntax highlight for language "${lang}" is not supported.`)
17-
return ''
18-
}
19-
}
20-
if (prism.languages[lang]) {
21-
let res = prism.highlight(str, prism.languages[lang], lang)
22-
return `<pre class="language-${lang}"><code v-pre>${res}</code></pre>`
23-
}
24-
return ''
25-
}
26-
})
27-
28-
// TODO containers (warning, tip, etc.)
29-
// TODO translate links to router-link & translate md links to html
30-
// TODO support using code blocks as demo
313

324
module.exports = function (src) {
5+
currentFile = this.resourcePath
336
const content = frontmatter.loadFront(src).__content
347
const html = md.render(content)
358
return `<template><div class="markdown">${html}</div></template>`

0 commit comments

Comments
 (0)