vue hello world项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
2.4 KiB

3 years ago
// @ts-check
const { warn } = require('./logger')
/** @typedef {{after?: string|Array<string>}} Apply */
/** @typedef {{id: string, apply: Apply}} Plugin */
/** @typedef {{after: Set<string>}} OrderParams */
/** @type {Map<string, OrderParams>} */
const orderParamsCache = new Map()
/**
*
* @param {Plugin} plugin
* @returns {OrderParams}
*/
function getOrderParams (plugin) {
if (!process.env.VUE_CLI_TEST && orderParamsCache.has(plugin.id)) {
return orderParamsCache.get(plugin.id)
}
const apply = plugin.apply
let after = new Set()
if (typeof apply.after === 'string') {
after = new Set([apply.after])
} else if (Array.isArray(apply.after)) {
after = new Set(apply.after)
}
if (!process.env.VUE_CLI_TEST) {
orderParamsCache.set(plugin.id, { after })
}
return { after }
}
/**
* See leetcode 210
* @param {Array<Plugin>} plugins
* @returns {Array<Plugin>}
*/
function topologicalSorting (plugins) {
/** @type {Map<string, Plugin>} */
const pluginsMap = new Map(plugins.map(p => [p.id, p]))
/** @type {Map<Plugin, number>} */
const indegrees = new Map()
/** @type {Map<Plugin, Array<Plugin>>} */
const graph = new Map()
plugins.forEach(p => {
const after = getOrderParams(p).after
indegrees.set(p, after.size)
if (after.size === 0) return
for (const id of after) {
const prerequisite = pluginsMap.get(id)
// remove invalid data
if (!prerequisite) {
indegrees.set(p, indegrees.get(p) - 1)
continue
}
if (!graph.has(prerequisite)) {
graph.set(prerequisite, [])
}
graph.get(prerequisite).push(p)
}
})
const res = []
const queue = []
indegrees.forEach((d, p) => {
if (d === 0) queue.push(p)
})
while (queue.length) {
const cur = queue.shift()
res.push(cur)
const neighbors = graph.get(cur)
if (!neighbors) continue
neighbors.forEach(n => {
const degree = indegrees.get(n) - 1
indegrees.set(n, degree)
if (degree === 0) {
queue.push(n)
}
})
}
const valid = res.length === plugins.length
if (!valid) {
warn(`No proper plugin execution order found.`)
return plugins
}
return res
}
/**
* Arrange plugins by 'after' property.
* @param {Array<Plugin>} plugins
* @returns {Array<Plugin>}
*/
function sortPlugins (plugins) {
if (plugins.length < 2) return plugins
return topologicalSorting(plugins)
}
module.exports = {
topologicalSorting,
sortPlugins
}