mirror of
https://github.com/wahyd4/vuepress.git
synced 2026-08-09 13:26:08 +10:00
198 lines
4.7 KiB
JavaScript
198 lines
4.7 KiB
JavaScript
import Vue from 'vue'
|
|
import layoutComponents from '@internal/layout-components'
|
|
import pageComponents from '@internal/page-components'
|
|
|
|
/**
|
|
* Create a cached version of a pure function.
|
|
*/
|
|
function cached (fn) {
|
|
const cache = Object.create(null)
|
|
// eslint-disable-next-line func-names
|
|
return function cachedFn (str) {
|
|
const hit = cache[str]
|
|
// eslint-disable-next-line no-return-assign
|
|
return hit || (cache[str] = fn(str))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Camelize a hyphen-delimited string.
|
|
*/
|
|
const camelizeRE = /-(\w)/g
|
|
const camelize = cached(str => {
|
|
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
|
|
})
|
|
|
|
/**
|
|
* Hyphenate a camelCase string.
|
|
*/
|
|
const hyphenateRE = /\B([A-Z])/g
|
|
const hyphenate = cached(str => {
|
|
return str.replace(hyphenateRE, '-$1').toLowerCase()
|
|
})
|
|
|
|
/**
|
|
* Capitalize a string.
|
|
*/
|
|
const capitalize = cached(str => {
|
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
})
|
|
|
|
/**
|
|
* This method was for securely getting Vue component when components
|
|
* are named in different style.
|
|
*
|
|
* e.g. a component named `a-b` can be also getted by `AB`, It's the
|
|
* same the other way round
|
|
*
|
|
* @param {function} getter a function of getting component by name
|
|
* @param {string} name component's name
|
|
* @returns {Component|AsyncComponent}
|
|
*/
|
|
export function getComponent (getter, name) {
|
|
if (!name) return
|
|
if (getter(name)) return getter(name)
|
|
|
|
const isKebabCase = name.includes('-')
|
|
if (isKebabCase) return getter(capitalize(camelize(name)))
|
|
|
|
return getter(capitalize(name)) || getter(hyphenate(name))
|
|
}
|
|
|
|
const asyncComponents = Object.assign({}, layoutComponents, pageComponents)
|
|
const asyncComponentsGetter = name => asyncComponents[name]
|
|
const pageComponentsGetter = layout => pageComponents[layout]
|
|
const layoutComponentsGetter = layout => layoutComponents[layout]
|
|
const globalComponentsGetter = name => Vue.component(name)
|
|
|
|
export function getPageAsyncComponent (pageKey) {
|
|
return getComponent(pageComponentsGetter, pageKey)
|
|
}
|
|
|
|
export function getLayoutAsyncComponent (layout) {
|
|
return getComponent(layoutComponentsGetter, layout)
|
|
}
|
|
|
|
export function getAsyncComponent (name) {
|
|
return getComponent(asyncComponentsGetter, name)
|
|
}
|
|
|
|
export function getVueComponent (name) {
|
|
return getComponent(globalComponentsGetter, name)
|
|
}
|
|
|
|
export function ensureAsyncComponentsLoaded (...names) {
|
|
return Promise.all(names.filter(v => v).map(async (name) => {
|
|
if (!getVueComponent(name) && getAsyncComponent(name)) {
|
|
const comp = await getAsyncComponent(name)()
|
|
Vue.component(name, comp.default)
|
|
}
|
|
}))
|
|
}
|
|
|
|
/**
|
|
* Inject option to Vue SFC
|
|
* @param {object} options
|
|
* @param {string} key
|
|
* @param {any} value
|
|
*/
|
|
export function injectComponentOption (options, key, value) {
|
|
const arrayInject = () => {
|
|
if (!options[key]) options[key] = []
|
|
options[key].push(...value)
|
|
}
|
|
const objectInject = () => {
|
|
if (!options[key]) options[key] = {}
|
|
Object.assign(options[key], value)
|
|
}
|
|
// const primitiveInject = () => options[key] = value
|
|
|
|
switch (key) {
|
|
case 'components': objectInject(); break
|
|
case 'mixins': arrayInject(); break
|
|
default: throw new Error('Unknown option name.')
|
|
}
|
|
}
|
|
|
|
export function findPageForPath (pages, path) {
|
|
for (let i = 0; i < pages.length; i++) {
|
|
const page = pages[i]
|
|
if (page.path === path) {
|
|
return page
|
|
}
|
|
}
|
|
return {
|
|
path: '',
|
|
frontmatter: {}
|
|
}
|
|
}
|
|
|
|
export function findPageByKey (pages, key) {
|
|
for (let i = 0; i < pages.length; i++) {
|
|
const page = pages[i]
|
|
if (page.key === key) {
|
|
return page
|
|
}
|
|
}
|
|
return {
|
|
path: '',
|
|
frontmatter: {}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Normalize config.
|
|
* This utility is mainly for plugin developers. For some
|
|
* plugins that need internationalize the text. but it's
|
|
* not recommenbded to let plugin care about to the internal
|
|
* i18n implementation, so this utility was born.
|
|
*
|
|
*
|
|
* Usage:
|
|
*
|
|
* import { normalizeConfig } from '@app/util'
|
|
* export default {
|
|
* data () {
|
|
* return { config }
|
|
* }
|
|
* computed: {
|
|
* normalizedConfig() {
|
|
* return normalizeConfig(this, config)
|
|
* }
|
|
* }
|
|
* }
|
|
*
|
|
*
|
|
* e.g.
|
|
*
|
|
* Config: : 'Text'
|
|
* Normalized Config: 'Text'
|
|
*
|
|
* Config: : { '/': 'Text', '/zh/': '文本' }
|
|
* Normalized Config: 'Text' or '文本'
|
|
*
|
|
* @param {Vue} component
|
|
* @param {any} rawConfig
|
|
* @returns {any}
|
|
*/
|
|
export function normalizeConfig (component, rawConfig) {
|
|
const { $localePath } = component
|
|
if (typeof rawConfig === 'object' && rawConfig[$localePath]) {
|
|
return rawConfig[$localePath]
|
|
}
|
|
return rawConfig
|
|
}
|
|
|
|
/**
|
|
* Set global info in `window.__VUEPRESS__` for debugging.
|
|
*
|
|
* @param {string}key
|
|
* @param {any} value
|
|
*/
|
|
export function setGlobalInfo (key, value) {
|
|
if (typeof window === 'undefined' || !window.__VUEPRESS__) {
|
|
return
|
|
}
|
|
window.__VUEPRESS__[key] = value
|
|
}
|