Skip to content

Commit

Permalink
refactor: shortcutPackageResolver
Browse files Browse the repository at this point in the history
  • Loading branch information
ulivz committed Oct 21, 2018
1 parent d6c3832 commit 80cb1d5
Show file tree
Hide file tree
Showing 13 changed files with 476 additions and 251 deletions.
7 changes: 4 additions & 3 deletions packages/@vuepress/core/lib/plugin-api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const instantiateOption = require('./override/instantiateOption')
const { flattenPlugin, normalizePluginsConfig } = require('./util')
const { PLUGIN_OPTION_MAP } = require('./constants')
const {
shortcutPackageResolver: { resolvePlugin },
moduleResolver: { getPluginResolver },
datatypes: { assertTypes, isPlainObject },
env: { isDebug },
logger, chalk
Expand All @@ -24,6 +24,7 @@ module.exports = class PluginAPI {
this._pluginContext = context
this._pluginQueue = []
this._initialized = false
this._pluginResolver = getPluginResolver()
this.initializeOptions(PLUGIN_OPTION_MAP)
}

Expand Down Expand Up @@ -113,8 +114,8 @@ module.exports = class PluginAPI {
*/

normalizePlugin (pluginRaw, pluginOptions = {}) {
let plugin = resolvePlugin(pluginRaw)
if (!plugin.module) {
let plugin = this._pluginResolver.resolve(pluginRaw)
if (!plugin.entry) {
console.warn(`[vuepress] cannot resolve plugin "${pluginRaw}"`)
return this
}
Expand Down
8 changes: 5 additions & 3 deletions packages/@vuepress/core/lib/plugin-api/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const { logger, chalk, datatypes: { assertTypes }} = require('@vuepress/shared-u

/**
* flatten your plugin config by passing in name, options and context.
*
* @param {function|object} module
* @param {string} name
* @param {string} hortcut
Expand All @@ -16,7 +17,7 @@ const { logger, chalk, datatypes: { assertTypes }} = require('@vuepress/shared-u
*/

exports.flattenPlugin = function (
{ module: config, name, shortcut, isLocal },
{ entry: config, name, shortcut, fromDep },
pluginOptions,
pluginContext,
self
Expand Down Expand Up @@ -45,17 +46,18 @@ exports.flattenPlugin = function (
}

// respect name in local plugin config
name = isLocal && config.name || name
name = fromDep && name || config.name
return Object.assign({}, config, {
name,
shortcut: isLocal ? null : shortcut,
shortcut: fromDep ? shortcut : null,
enabled,
$$options: pluginOptions /* used for test */
})
}

/**
* Normalize plugins config in `.vuepress/config.js`
*
* @param pluginsConfig
*/

Expand Down
6 changes: 4 additions & 2 deletions packages/@vuepress/core/lib/prepare/loadTheme.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

const {
fs, path,
shortcutPackageResolver: { resolveTheme },
moduleResolver: { getThemeResolver },
datatypes: { isString },
logger, chalk
} = require('@vuepress/shared-utils')
Expand All @@ -31,6 +31,7 @@ const {
module.exports = async function loadTheme (ctx) {
const { siteConfig, cliOptions, sourceDir, vuepressDir, pluginAPI } = ctx
const theme = siteConfig.theme || cliOptions.theme
const themeResolver = getThemeResolver()

const localThemePath = path.resolve(vuepressDir, 'theme')
const useLocalTheme =
Expand All @@ -47,7 +48,8 @@ module.exports = async function loadTheme (ctx) {
themePath = localThemePath
logger.tip(`\nApply theme located at ${chalk.gray(themePath)}...`)
} else if (isString(theme)) {
const { module: modulePath, name, shortcut } = resolveTheme(theme, sourceDir)
const { entry: modulePath, name, shortcut } = themeResolver.resolve(theme, sourceDir)

if (modulePath.endsWith('.js') || modulePath.endsWith('.vue')) {
themePath = path.parse(modulePath).dir
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
name: 'a'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {}
162 changes: 162 additions & 0 deletions packages/@vuepress/shared-utils/__tests__/moduleResolver.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
jest.mock('vuepress-plugin-a')
jest.mock('@org/vuepress-plugin-a')
jest.mock('@vuepress/plugin-a')

jest.mock('vuepress-theme-a')
jest.mock('@org/vuepress-theme-a')
jest.mock('@vuepress/theme-a')

import path from 'path'
import {
getThemeResolver,
getPluginResolver,
resolveScopePackage
} from '../lib/moduleResolver'
import hash from 'hash-sum'

const MOCK_RELATIVE = '../../../../__mocks__'

function loadMockModule (name) {
return require(`${MOCK_RELATIVE}/${name}`)
}

function resolveMockModule (name) {
return path.resolve(__dirname, `${MOCK_RELATIVE}/${name}`)
}

const fixturesDir = path.resolve(__dirname, 'fixtures')
const themeResolver = getThemeResolver(fixturesDir)
const pluginResolver = getPluginResolver(fixturesDir)

const prevCwd = process.cwd()
beforeAll(() => {
process.chdir(path.resolve(__dirname, 'fixtures'))
})

afterAll(() => {
process.chdir(prevCwd)
})

describe('resolveScopePackage', () => {
test('corrent format', () => {
const pkg = resolveScopePackage('@vuepress/plugin-a')
expect(pkg.org).toBe('vuepress')
expect(pkg.name).toBe('plugin-a')
})

test('incorrect format', () => {
const pkg2 = resolveScopePackage('vuepress/plugin-a')
expect(pkg2).toBe(null)

const pkg3 = resolveScopePackage('vuepress-plugin-a')
expect(pkg3).toBe(null)
})
})

const getBaseAsserts = (type) => [
{ input: 'a', output: ['a', `vuepress-${type}-a`] },
{ input: `vuepress-${type}-a`, output: ['a', `vuepress-${type}-a`] },
{ input: '@vuepress/a', output: ['@vuepress/a', `@vuepress/${type}-a`] },
{ input: '@org/a', output: ['@org/a', `@org/vuepress-${type}-a`] }
]

describe('normalizeRequest', () => {
const normalizeRequest = pluginResolver.normalizeRequest.bind(pluginResolver)

test('base', () => {
const asserts = [
{ input: null, output: [null, null] },
{ input: undefined, output: [null, null] },
...getBaseAsserts('plugin')
]

for (const { input, output } of asserts) {
const { shortcut, name } = normalizeRequest(input)
expect([shortcut, name]).toEqual(output)
}
})

test('object', () => {
const req = {}
const { name, shortcut } = normalizeRequest(req)
expect(shortcut).toBe(`anonymous-${hash(req)}`)
expect(name).toBe(`vuepress-plugin-anonymous-${hash(req)}`)
})

test('object - should respect name', () => {
const req = { name: 'a' }
const { name, shortcut } = normalizeRequest(req)
expect(shortcut).toBe('a')
expect(name).toBe(`vuepress-plugin-a`)
})
})

describe('resolvePlugin', () => {
const resolvePlugin = pluginResolver.resolve.bind(pluginResolver)

test('function', () => {
const plugin = () => {
/* noop */
}
const resolved = resolvePlugin(plugin)
expect(resolved.entry).toBe(plugin)
expect(resolved.fromDep).toBe(false)
})

test('object', () => {
const plugin = {}
const resolved = resolvePlugin(plugin)
expect(resolved.entry).toBe(plugin)
expect(resolved.fromDep).toBe(false)
})

test('from dep', () => {
const asserts = getBaseAsserts('plugin')
for (const { input, output } of asserts) {
const [, name] = output
const resolved = resolvePlugin(input)
expect(resolved.entry).toBe(loadMockModule(name))
}
})

test('relative path', () => {
const resolved = resolvePlugin('./plugin-a')
expect(resolved.entry).toBe(require('./fixtures/plugin-a'))
})

test('aosolute path', () => {
const resolved = resolvePlugin(path.resolve(__dirname, 'fixtures/plugin-a'))
expect(resolved.entry).toBe(require('./fixtures/plugin-a'))
})

test('plugin that cannot be resolved', () => {
expect(resolvePlugin('c').entry).toBe(null)
})
})

describe('resolveTheme', () => {
const resolveTheme = themeResolver.resolve.bind(themeResolver)

test('from dep', () => {
const asserts = getBaseAsserts('theme')
for (const { input, output } of asserts) {
const [, name] = output
const resolved = resolveTheme(input)
expect(resolved.entry).toBe(resolveMockModule(name))
}
})

test('relative path', () => {
const resolved = resolveTheme('./theme-a')
expect(resolved.entry).toBe(path.resolve(__dirname, './fixtures/theme-a'))
})

test('absolute path', () => {
const resolved = resolveTheme(path.resolve(__dirname, 'fixtures/theme-a'))
expect(resolved.entry).toBe(path.resolve(__dirname, './fixtures/theme-a'))
})

test('theme that cannot be resolved', () => {
expect(resolveTheme('c').entry).toBe(null)
})
})

This file was deleted.

Loading

0 comments on commit 80cb1d5

Please sign in to comment.