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

feat: transform vue template with posthtml #479

Merged
merged 9 commits into from
Sep 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

const ChainedMap = require('webpack-chain/src/ChainedMap')
const resolvePackage = require('../utils/resolvePackage')
const Plugin = require('./Plugin')
const Options = require('./Options')

Expand All @@ -29,4 +30,25 @@ module.exports = class MarkdownItChain extends ChainedMap {

return this.plugins.get(name)
}

loadPlugins(rawPluginList, cwd) {
const pluginList = rawPluginList.map(plugin => {
if (typeof plugin === 'string') {
plugin = { resolve: plugin }
}

plugin.resolve = resolvePackage(plugin.resolve, { cwd })
plugin.name = plugin.name || plugin.resolve
plugin.handler = require(plugin.resolve)

return plugin
})

for (const plugin of pluginList) {
this.plugin(plugin.name).use(
plugin.handler,
Array.isArray(plugin.options) ? plugin.options : [plugin.options]
)
}
}
}
1 change: 1 addition & 0 deletions packages/saber/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Saber {
getWebpackConfig: new SyncWaterfallHook(['config', 'opts']),
// Extend markdown-it config
chainMarkdown: new SyncHook(['config']),
chainTemplate: new SyncHook(['config']),
emitRoutes: new AsyncSeriesHook(),
// Called after running webpack
afterBuild: new AsyncSeriesHook(),
Expand Down
22 changes: 0 additions & 22 deletions packages/saber/lib/markdown/__test__/link-plugin.test.js

This file was deleted.

67 changes: 0 additions & 67 deletions packages/saber/lib/markdown/link-plugin.js

This file was deleted.

40 changes: 11 additions & 29 deletions packages/saber/lib/plugins/transformer-markdown.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const MarkdownChain = require('../markdown-chain')
const ConfigChain = require('../config-chain')
const resolvePackage = require('../utils/resolvePackage')

exports.name = 'builtin:transformer-markdown'
Expand Down Expand Up @@ -39,7 +39,7 @@ function transformMarkdown(api, page) {
page
}

const chain = new MarkdownChain()
const chain = new ConfigChain()

chain.options.merge(
Object.assign(
Expand All @@ -52,7 +52,7 @@ function transformMarkdown(api, page) {
)
)

const pluginList = [
const builtInPlugins = [
{
name: 'hoist-tags',
resolve: require.resolve('../markdown/hoist-tags-plugin')
Expand Down Expand Up @@ -82,40 +82,22 @@ function transformMarkdown(api, page) {
lineNumbers: markdown.lineNumbers
}
},
{
name: 'link',
resolve: require.resolve('../markdown/link-plugin')
},
{
name: 'task-list',
resolve: require.resolve('../markdown/task-list-plugin')
},
...(markdown.plugins
? markdown.plugins.map(p => {
if (typeof p === 'string') {
p = { resolve: p }
}

p.name = p.name || p.resolve
p.resolve = resolvePackage(p.resolve, { cwd: configDir })
return p
})
: [])
}
]

for (const plugin of pluginList) {
chain
.plugin(plugin.name)
.use(
typeof plugin.resolve === 'string'
? require(plugin.resolve)
: plugin.resolve,
Array.isArray(plugin.options) ? plugin.options : [plugin.options]
)
}
// Load built-in plugins
chain.loadPlugins(builtInPlugins, configDir)

api.hooks.chainMarkdown.call(chain)

// Load plugins from config file
if (markdown.plugins) {
chain.loadPlugins(markdown.plugins, configDir)
}

const { options, plugins } = chain.toConfig()

if (typeof options.highlight === 'string') {
Expand Down
1 change: 1 addition & 0 deletions packages/saber/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"object-assign": "^4.1.1",
"open": "^6.4.0",
"polka": "^0.5.1",
"posthtml": "^0.11.6",
"prettier": "^1.17.0",
"pretty-ms": "^5.0.0",
"resolve-from": "^5.0.0",
Expand Down
7 changes: 6 additions & 1 deletion packages/saber/vue-renderer/app/create-app.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import './polyfills'
import '#cache/runtime-polyfills'
import { join, dirname } from 'path'
import Vue from 'vue'
import Meta from 'vue-meta'
import layouts from '#cache/layouts'
import createRouter from './router'
import Layout from './components/LayoutManager.vue'
import ClientOnly from './components/ClientOnly'
import extendBrowserApi from '#cache/extend-browser-api'
import { join, dirname } from './helpers/path'
import injectConfig from './helpers/inject-config'
import setTransition from './helpers/set-transition'
import scrollHandler from './helpers/scroll-handler'
Expand Down Expand Up @@ -125,6 +125,11 @@ export default context => {
const matched = Array.isArray(link)
? link // The link is already parsed
: /^([^#?]+)([#?].*)?$/.exec(link)

if (!matched) {
return link
}

const relativePath = join(
dirname(this.$route.meta.__relative),
matched[1]
Expand Down
86 changes: 86 additions & 0 deletions packages/saber/vue-renderer/app/helpers/path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// eslint-disable
// Extracted from https://github.com/calvinmetcalf/rollup-plugin-node-builtins/blob/master/src/es6/path.js

function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0
for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i]
if (last === '.') {
parts.splice(i, 1)
} else if (last === '..') {
parts.splice(i, 1)
up++
} else if (up) {
parts.splice(i, 1)
up--
}
}

// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..')
}
}

return parts
}

// Split a filename into [root, dir, basename, ext], unix version
// 'root' is just a slash, or nothing.
var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/
var splitPath = function(filename) {
return splitPathRe.exec(filename).slice(1)
}

// path.normalize(path)
// posix version
function normalize(path) {
var isPathAbsolute = isAbsolute(path),
trailingSlash = path.substr(-1) === '/'

// Normalize the path
path = normalizeArray(
path.split('/').filter(Boolean),
!isPathAbsolute
).join('/')

if (!path && !isPathAbsolute) {
path = '.'
}
if (path && trailingSlash) {
path += '/'
}

return (isPathAbsolute ? '/' : '') + path
}
// posix version
function isAbsolute(path) {
return path.charAt(0) === '/'
}

// posix version
function join(...paths) {
return normalize(paths.filter(p => typeof p === 'string').join('/'))
}

function dirname(path) {
var result = splitPath(path),
root = result[0],
dir = result[1]

if (!root && !dir) {
// No dirname whatsoever
return '.'
}

if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1)
}

return root + dir
}

export { dirname, join }
9 changes: 9 additions & 0 deletions packages/saber/vue-renderer/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ class VueRenderer {
getPagePublicFields: api.pages.getPagePublicFields.bind(api.pages)
}

config.module
.rule('transform-template')
.resourceQuery(/\?vue&type=template/)
.use('transform-template-loader')
.loader(require.resolve('./transform-template-loader'))
.options({
plugins: require('./template-plugins')(api)
})

// Add `saber-page` rule under `js` rule to handle .js pages
// prettier-ignore
config.module
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const posthtml = require('posthtml')
const plugin = require('../link')

const transform = source =>
posthtml([plugin()])
.process(source, {
recognizeSelfClosing: true
})
.then(res => res.html)

test('basic', async () => {
const html = await transform(`
<a href="foo">foo</a>
<a href="https://example.com">foo</a>
<a href="mailto:[email protected]">foo</a>
<saber-link to="/foo">foo</saber-link>
<saber-link :to="foo">foo</saber-link>
`)
expect(html).toBe(`
<saber-link :to="$saber.getPageLink('foo')">foo</saber-link>
<a target="_blank" rel="noopener noreferrer" href="https://example.com">foo</a>
<a href="mailto:[email protected]">foo</a>
<saber-link :to="$saber.getPageLink('/foo')">foo</saber-link>
<saber-link :to="foo">foo</saber-link>
`)
})

test('ignore', async () => {
const html = await transform(`<a href="foo" saber-ignore>foo</a>`)
expect(html).toBe(`<a href="foo">foo</a>`)
})
Loading