Files
vuepress/packages/@vuepress/shared-utils/lib/shortcutPackageResolver.js
T
ULIVZ f81f3732f6 feat: refine theme API
1. Support scope package and shortcut like plugin.
2. Support relative path for 'layout' and 'notFound' option.
2018-09-02 22:55:44 +08:00

101 lines
2.9 KiB
JavaScript

const { isDebug } = require('./env')
const { resolveModule, loadModule } = require('./module')
const {
isString,
assertTypes
} = require('./datatypes')
const SCOPE_PACKAGE_RE = /^@(.*)\/(.*)/
/**
* Delightful pakcage shortcut resolving utility.
* @param {steing} type 'plugin', 'theme', or others.
* @param {string} org
* @returns {function}
*/
function shortcutPackageResolver (
type = 'plugin',
org = 'vuepress',
allowedTypes = [String],
load = false
) {
let anonymousPluginIdx = 0
const NON_SCOPE_PREFIX = `${org}-${type}-`
const SCOPE_PREFIX = `@${org}/${type}-`
const SHORT_PREFIX_SLICE_LENGTH = type.length + 1
const FULL_PREFIX_SLICE_LENGTH = SHORT_PREFIX_SLICE_LENGTH + org.length + 1
return function (req, cwd) {
let _module
let name
let shortcut
let isLocal = false
const { valid, warnMsg } = assertTypes(req, allowedTypes)
if (!valid) {
throw new Error(`Invalid value for "${type}": ${warnMsg}`)
}
if (!isString(req)) {
_module = req
name = shortcut = req.name || `anonymous-${++anonymousPluginIdx}`
isLocal = true
} else {
try {
shortcut = req.startsWith(NON_SCOPE_PREFIX)
? req.slice(FULL_PREFIX_SLICE_LENGTH)
: req
name = `${NON_SCOPE_PREFIX}${shortcut}`
_module = load ? loadModule(name, cwd) : resolveModule(name, cwd)
} catch (err) {
const pkg = module.exports.resolveScopePackage(req)
try {
if (pkg) {
// speicial handling for default org.
if (pkg.org === org) {
shortcut = pkg.name.startsWith(`${type}-`)
? pkg.name.slice(SHORT_PREFIX_SLICE_LENGTH)
: pkg.name
name = `${SCOPE_PREFIX}${shortcut}`
} else {
shortcut = pkg.name.startsWith(NON_SCOPE_PREFIX)
? pkg.name.slice(FULL_PREFIX_SLICE_LENGTH)
: pkg.name
name = `@${pkg.org}/${NON_SCOPE_PREFIX}${shortcut}`
}
shortcut = `@${pkg.org}/${shortcut}`
_module = load ? loadModule(name, cwd) : resolveModule(name, cwd)
} else {
throw new Error(`Invalid ${type} usage ${req}.`)
}
} catch (err2) {
if (isDebug) {
console.error(err2)
}
name = shortcut = req
_module = null
}
}
}
return { module: _module, name, shortcut, isLocal }
}
}
module.exports = shortcutPackageResolver
module.exports.resolveScopePackage = function resolveScopePackage (name) {
if (SCOPE_PACKAGE_RE.test(name)) {
return {
org: RegExp.$1,
name: RegExp.$2
}
}
return null
}
module.exports.resolvePlugin = shortcutPackageResolver(
'plugin', 'vuepress', [String, Function, Object], true /* load module */
)
module.exports.resolveTheme = shortcutPackageResolver(
'theme', 'vuepress', [String]
)