Skip to content

Commit dfb0bba

Browse files
committedDec 2, 2018
feat($core): support Vue SFC as source files
1 parent b3c2f68 commit dfb0bba

File tree

9 files changed

+115
-28
lines changed

9 files changed

+115
-28
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module.exports = () => ({
2+
name: '@vuepress/internal-frontmatter-block',
3+
4+
chainWebpack (config) {
5+
config
6+
.module
7+
.rule('frontmatter-block')
8+
.resourceQuery(/blockType=frontmatter/)
9+
.use('frontmatter-block-loader')
10+
.loader(require.resolve('./loader.js'))
11+
}
12+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const { parseVueFrontmatter: { parseStrippedFrontmatter }} = require('@vuepress/shared-utils')
2+
const { frontmatterEmitter } = require('@vuepress/markdown-loader')
3+
const LRU = require('lru-cache')
4+
const cache = LRU({ max: 1000 })
5+
6+
module.exports = function (source, map) {
7+
const isProd = process.env.NODE_ENV === 'production'
8+
9+
if (!isProd) {
10+
const file = this.resourcePath
11+
// frontmatter changed... need to do a full reload
12+
const cached = cache.get(file)
13+
const parsed = parseStrippedFrontmatter(source)
14+
15+
if (cached &&
16+
cached.data &&
17+
parsed &&
18+
parsed.data &&
19+
JSON.stringify(cached.data) !== JSON.stringify(parsed.data)
20+
) {
21+
// TODO Replace temporary files in bulk to avoid repeated refreshes.
22+
frontmatterEmitter.emit('update')
23+
}
24+
25+
cache.set(file, parsed)
26+
}
27+
28+
this.callback(null, '', map)
29+
}

‎packages/@vuepress/core/lib/prepare/AppContext.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ module.exports = class AppContext {
126126
.use(require('../internal-plugins/pageComponents'))
127127
.use(require('../internal-plugins/transformModule'))
128128
.use(require('../internal-plugins/dataBlock'))
129+
.use(require('../internal-plugins/frontmatterBlock'))
129130
.use('@vuepress/last-updated', !!shouldUseLastUpdated)
130131
.use('@vuepress/register-components', {
131132
componentsDir: [
@@ -244,7 +245,7 @@ module.exports = class AppContext {
244245

245246
async resolvePages () {
246247
// resolve pageFiles
247-
const patterns = ['**/*.md', '!.vuepress', '!node_modules']
248+
const patterns = ['**/*.md', '**/*.vue', '!.vuepress', '!node_modules']
248249
if (this.siteConfig.dest) {
249250
// #654 exclude dest folder when dest dir was set in
250251
// sourceDir but not in '.vuepress'

‎packages/@vuepress/core/lib/prepare/Page.js

+30-24
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const {
1616
fileToPath,
1717
getPermalink,
1818
extractHeaders,
19-
parseFrontmatter
19+
parseFrontmatter,
20+
parseVueFrontmatter
2021
} = require('@vuepress/shared-utils')
2122

2223
/**
@@ -95,29 +96,34 @@ module.exports = class Page {
9596
}
9697

9798
if (this._content) {
98-
const { excerpt, data, content } = parseFrontmatter(this._content)
99-
this._strippedContent = content
100-
this.frontmatter = data
101-
102-
// infer title
103-
const title = inferTitle(this.frontmatter, this._strippedContent)
104-
if (title) {
105-
this.title = title
106-
}
107-
108-
// headers
109-
const headers = extractHeaders(
110-
this._strippedContent,
111-
['h2', 'h3'],
112-
markdown
113-
)
114-
if (headers.length) {
115-
this.headers = headers
116-
}
117-
118-
if (excerpt) {
119-
const { html } = markdown.render(excerpt)
120-
this.excerpt = html
99+
if (this._filePath.endsWith('.md')) {
100+
const { excerpt, data, content } = parseFrontmatter(this._content)
101+
this._strippedContent = content
102+
this.frontmatter = data
103+
104+
// infer title
105+
const title = inferTitle(this.frontmatter, this._strippedContent)
106+
if (title) {
107+
this.title = title
108+
}
109+
110+
// headers
111+
const headers = extractHeaders(
112+
this._strippedContent,
113+
['h2', 'h3'],
114+
markdown
115+
)
116+
if (headers.length) {
117+
this.headers = headers
118+
}
119+
120+
if (excerpt) {
121+
const { html } = markdown.render(excerpt)
122+
this.excerpt = html
123+
}
124+
} else if (this._filePath.endsWith('.vue')) {
125+
const { data = {}} = parseVueFrontmatter(this._content)
126+
this.frontmatter = data
121127
}
122128
}
123129

‎packages/@vuepress/shared-utils/__tests__/isIndexFile.spec.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,25 @@ test('isIndexFile', () => {
77
'INDEX.md',
88
'index.md',
99
'foo/README.md',
10-
'foo/index.md'
10+
'foo/index.md',
11+
'README.vue',
12+
'readme.vue',
13+
'INDEX.vue',
14+
'index.vue',
15+
'foo/README.vue',
16+
'foo/index.vue'
1117
].forEach(file => {
1218
expect(isIndexFile(file)).toBe(true)
1319
});
1420
[
1521
'foo/one.md',
1622
'one.md',
1723
'one-index.md',
18-
'foo/one-index.md'
24+
'foo/one-index.md',
25+
'foo/one.vue',
26+
'one.vue',
27+
'one-index.vue',
28+
'foo/one-index.vue'
1929
].forEach(file => {
2030
expect(isIndexFile(file)).toBe(false)
2131
})

‎packages/@vuepress/shared-utils/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ exports.codegen = require('./lib/codegen')
44
exports.compose = require('./lib/compose')
55
exports.datatypes = require('./lib/datatypes')
66
exports.parseFrontmatter = require('./lib/parseFrontmatter')
7+
exports.parseVueFrontmatter = require('./lib/parseVueFrontmatter')
78

89
exports.unescapeHtml = require('./lib/unescapeHtml')
910
exports.escapeHtml = require('escape-html')

‎packages/@vuepress/shared-utils/lib/fileToPath.js

+4
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ const extRE = /\.(vue|md)$/
66
module.exports = function fileToPath (file) {
77
if (isIndexFile(file)) {
88
// README.md -> /
9+
// README.vue -> /
910
// foo/README.md -> /foo/
11+
// foo/README.vue -> /foo/
1012
return file.replace(indexRE, '/$1')
1113
} else {
1214
// foo.md -> /foo.html
15+
// foo.vue -> /foo.html
1316
// foo/bar.md -> /foo/bar.html
17+
// foo/bar.vue -> /foo/bar.html
1418
return `/${file.replace(extRE, '').replace(/\\/g, '/')}.html`
1519
}
1620
}

‎packages/@vuepress/shared-utils/lib/isIndexFile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const indexRE = /(^|.*\/)(index|readme)\.md$/i
1+
const indexRE = /(^|.*\/)(index|readme)\.(md|vue)$/i
22

33
function isIndexFile (file) {
44
return indexRE.test(file)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const compiler = require('vue-template-compiler')
2+
const { parse } = require('@vue/component-compiler-utils')
3+
const parseFrontmatter = require('./parseFrontmatter')
4+
5+
function parseStrippedFrontmatter (src) {
6+
src = `---\n${src}\n---`
7+
return parseFrontmatter(src)
8+
}
9+
10+
module.exports = src => {
11+
const output = parse({
12+
source: src,
13+
compiler,
14+
needMap: false
15+
})
16+
const find = output.customBlocks.find(block => block.type === 'frontmatter')
17+
const frontmatterRaw = find && find.content
18+
if (frontmatterRaw) {
19+
return parseStrippedFrontmatter(frontmatterRaw)
20+
}
21+
return {}
22+
}
23+
24+
module.exports.parseStrippedFrontmatter = parseStrippedFrontmatter

0 commit comments

Comments
 (0)
Please sign in to comment.