Skip to content

Commit

Permalink
title inferrence
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Apr 5, 2018
1 parent 6471d4f commit 72e5666
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 49 deletions.
5 changes: 5 additions & 0 deletions docs/vuepress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
data: {
title: 'VuePress'
}
}
27 changes: 21 additions & 6 deletions lib/app/Content.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
export default {
created () {
if (this.$ssrContext) {
this.$ssrContext.title = getMetadata(this, 'title') || 'VuePress'
this.$ssrContext.lang = getMetadata(this, 'lang') || 'en'
this.$ssrContext.title = getTitle(this)
this.$ssrContext.lang = getLang(this)
}
},
mounted () {
const updateMeta = () => {
document.title = getMetadata(this, 'title') || 'VuePress'
document.documentElement.lang = getMetadata(this, 'lang') || 'en'
document.title = getTitle(this)
document.documentElement.lang = getLang(this)
}
this.$watch('$page', updateMeta)
updateMeta()
Expand All @@ -24,6 +24,21 @@ export default {
}
}

function getMetadata (vm, key) {
return vm.$page.frontmatter[key] || vm.$page[key] || vm.$site[key]
function getTitle (vm) {
const selfTitle = (
vm.$page.frontmatter.title || // explicit title
vm.$page.title // inferred title
)
const siteTitle = vm.$site.title
return siteTitle
? selfTitle
? siteTitle + ' | ' + selfTitle
: siteTitle
: selfTitle
? selfTitle
: 'VuePress'
}

function getLang (vm) {
return vm.$page.frontmatter.lang
}
16 changes: 16 additions & 0 deletions lib/default-theme/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,19 @@ export default {

<style src="prismjs/themes/prism-tomorrow.css"></style>
<style src="./nprogress.css"></style>
<style>
.theme-container {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
}
pre[class*="language-"] {
line-height: 1.4;
border-radius: 5px;
}
pre[class*="language-"] code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
font-size: 14px;
-webkit-font-smoothing: antialiased;
}
</style>
21 changes: 21 additions & 0 deletions lib/markdown/highlight.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const prism = require('prismjs')
const loadLanguages = require('prismjs/components/index')

module.exports = (str, lang) => {
if (lang === 'vue') {
lang = 'html'
}
if (!prism.languages[lang]) {
try {
loadLanguages([lang])
} catch (e) {
throw new Error(`[vuepress] Syntax highlight for language "${lang}" is not supported.`)
return ''
}
}
if (prism.languages[lang]) {
let res = prism.highlight(str, prism.languages[lang], lang)
return `<pre class="language-${lang}"><code v-pre>${res}</code></pre>`
}
return ''
}
16 changes: 16 additions & 0 deletions lib/markdown/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const highlight = require('./highlight')
const convertRouterLink = require('./link')
const container = require('markdown-it-container')

// TODO extract <style> blocks and <script> blocks
// TODO support inline demo

module.exports = require('markdown-it')({
html: true,
typographer: true,
highlight
})
.use(convertRouterLink)
.use(container, 'tip')
.use(container, 'warning')
.use(container, 'danger')
34 changes: 34 additions & 0 deletions lib/markdown/link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module.exports = md => {
let hasOpenLink = false

md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
const token = tokens[idx]
const hrefIndex = token.attrIndex('href')
if (hrefIndex >= 0) {
const link = token.attrs[hrefIndex]
const href = link[1]
if (!/^https?:/.test(href) && /\.(md|html)$/.test(href)) {
hasOpenLink = true
tokens[idx] = toRouterLink(token, link)
}
}
return self.renderToken(tokens, idx, options)
}

function toRouterLink (token, link) {
link[0] = 'to'
link[1] = link[1].replace(/\.md$/, '.html')
return Object.assign({}, token, {
tag: 'router-link'
})
}

md.renderer.rules.link_close = (tokens, idx, options, env, self) => {
const token = tokens[idx]
if (hasOpenLink) {
token.tag = 'router-link'
hasOpenLink = false
}
return self.renderToken(tokens, idx, options)
}
}
47 changes: 33 additions & 14 deletions lib/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,45 @@ module.exports = async function prepare (sourceDir) {

async function resolveOptions (sourceDir) {
const configPath = path.resolve(sourceDir, 'vuepress.config.js')
const siteConfig = fs.existsSync(configPath) ? require(configPath) : {}
const userConfig = fs.existsSync(configPath) ? require(configPath) : {}

const hasTheme = userConfig.theme || fs.existsSync(path.resolve(sourceDir, '_theme'))

const options = {
siteConfig,
sourceDir,
publicPath: siteConfig.baseUrl || '/',
themePath: path.resolve(__dirname, 'default-theme/Layout.vue'),
notFoundPath: path.resolve(__dirname, 'default-theme/NotFound.vue'),
publicPath: userConfig.baseUrl || '/',
pages: await globby(['**/*.md'], { cwd: sourceDir })
}

// resolve theme
const themePath = path.resolve(sourceDir, '_theme/Layout.vue')
if (fs.existsSync(themePath)) {
options.themePath = themePath
}
if (!hasTheme) {
// use default theme
options.siteConfig = userConfig
options.themePath = path.resolve(__dirname, 'default-theme/Layout.vue')
options.notFoundPath = path.resolve(__dirname, 'default-theme/NotFound.vue')
} else {
// resolve theme
const themeDir = userConfig.theme
? path.resolve(__dirname, `../../${userConfig.theme}`)
: path.resolve(sourceDir, '_theme')
const themeConfigPath = path.resolve(themeDir, 'config.js')
const themeConfig = fs.existsSync(themeConfigPath)
? require(themeConfigPath)
: {}
options.siteConfig = Object.assign(themeConfig, userConfig)

const themePath = path.resolve(themeDir, 'Layout.vue')
if (fs.existsSync(themePath)) {
options.themePath = themePath
} else {
throw new Error('[vuepress] Custom theme must have a Layout.vue file.')
}

const notFoundPath = path.resolve(sourceDir, '_theme/NotFound.vue')
if (fs.existsSync(notFoundPath)) {
options.notFoundPath = notFoundPath
const notFoundPath = path.resolve(themeDir, '/NotFound.vue')
if (fs.existsSync(notFoundPath)) {
options.notFoundPath = notFoundPath
} else {
throw new Error('[vuepress] Custom theme must have a NotFound.vue file.')
}
}

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

options.siteData = Object.assign({}, siteConfig.data, {
options.siteData = Object.assign({}, userConfig.data, {
pages: pagesData
})

Expand Down
31 changes: 2 additions & 29 deletions lib/webpack/markdownLoader.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,8 @@
const prism = require('prismjs')
const md = require('../markdown')
const frontmatter = require('yaml-front-matter')
const loadLanguages = require('prismjs/components/index')

const md = require('markdown-it')({
html: true,
typographer: true,
highlight: (str, lang) => {
if (lang === 'vue') {
lang = 'html'
}
if (!prism.languages[lang]) {
try {
loadLanguages([lang])
} catch (e) {
throw new Error(`[vuepress] Syntax highlight for language "${lang}" is not supported.`)
return ''
}
}
if (prism.languages[lang]) {
let res = prism.highlight(str, prism.languages[lang], lang)
return `<pre class="language-${lang}"><code v-pre>${res}</code></pre>`
}
return ''
}
})

// TODO containers (warning, tip, etc.)
// TODO translate links to router-link & translate md links to html
// TODO support using code blocks as demo

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

0 comments on commit 72e5666

Please sign in to comment.