Skip to content

Commit

Permalink
fix: calculate label of external mod
Browse files Browse the repository at this point in the history
  • Loading branch information
nieyuyao committed Jun 11, 2022
1 parent ca9983a commit 1d0a97b
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 16 deletions.
103 changes: 87 additions & 16 deletions packages/ui/client/composables/module-graph.ts
Expand Up @@ -9,23 +9,94 @@ export type ModuleGraph = Graph<ModuleType, ModuleNode, ModuleLink>
export type ModuleGraphController = GraphController<ModuleType, ModuleNode, ModuleLink>
export type ModuleGraphConfig = GraphConfig<ModuleType, ModuleNode, ModuleLink>

function defineExternalModuleNode(module: string): ModuleNode {
let label = module
if (label.includes('/node_modules/'))
label = label.split(/\/node_modules\//g).pop()!
else
label = label.split(/\//g).pop()!
export interface ModuleLabelItem {
id: string
raw: string
splits: string[]
candidate: string
finished: boolean
}

return defineNode<ModuleType, ModuleNode>({
color: 'var(--color-node-external)',
label: {
color: 'var(--color-node-external)',
fontSize: '0.875rem',
text: label,
},
isFocused: false,
export function calcExternalLabels(labels: ModuleLabelItem[]): Map<string, string> {
const result: Map<string, string> = new Map()
const splitMap: Map<string, number[]> = new Map()
const firsts: number[] = []
while (true) {
let finishedCount = 0
labels.forEach((label, i) => {
const { splits, finished } = label
// record the candidate as final label text when label is marked finished
if (finished) {
finishedCount++
const { raw, candidate } = label
result.set(raw, candidate)
return
}
if (splits.length === 0) {
label.finished = true
return
}
const head = splits[0]
if (splitMap.has(head)) {
label.candidate += label.candidate === '' ? head : `/${head}`
splitMap.get(head)?.push(i)
splits.shift()
// eslint-disable-next-line @typescript-eslint/brace-style
} else {
splitMap.set(head, [i])
// record the index of the label where the head first appears
firsts.push(i)
}
})
// update candidate of label which index appears in first array
firsts.forEach((i) => {
const label = labels[i]
const head = label.splits.shift()
label.candidate += label.candidate === '' ? head : `/${head}`
})
splitMap.forEach((value) => {
if (value.length === 1) {
const index = value[0]
labels[index].finished = true
}
})
splitMap.clear()
firsts.length = 0
if (finishedCount === labels.length)
break
}
return result
}

export function createModuleLabelItem(module: string): ModuleLabelItem {
let raw = module
if (raw.includes('/node_modules/'))
raw = module.split(/\/node_modules\//g).pop()!
const splits = raw.split(/\//g)
return {
raw,
splits,
candidate: '',
finished: false,
id: module,
type: 'external',
}
}

function defineExternalModuleNodes(modules: string[]): ModuleNode[] {
const labels: ModuleLabelItem[] = modules.map(module => createModuleLabelItem(module))
const map = calcExternalLabels(labels)
return labels.map(({ raw, id }) => {
return defineNode<ModuleType, ModuleNode>({
color: 'var(--color-node-external)',
label: {
color: 'var(--color-node-external)',
fontSize: '0.875rem',
text: map.get(raw) ?? '',
},
isFocused: false,
id,
type: 'external',
})
})
}

Expand All @@ -47,7 +118,7 @@ export function getModuleGraph(data: ModuleGraphData, rootPath: string | undefin
if (!data)
return defineGraph({})

const externalizedNodes = data.externalized.map(module => defineExternalModuleNode(module)) ?? []
const externalizedNodes = defineExternalModuleNodes(data.externalized)
const inlinedNodes = data.inlined.map(module => defineInlineModuleNode(module, module === rootPath)) ?? []
const nodes = [...externalizedNodes, ...inlinedNodes]
const nodeMap = Object.fromEntries(nodes.map(node => [node.id, node]))
Expand Down
50 changes: 50 additions & 0 deletions test/core/test/module-label.test.ts
@@ -0,0 +1,50 @@
import { expect, test } from 'vitest'
import { calcExternalLabels, createModuleLabelItem } from '../../../packages/ui/client/composables/module-graph'

const getExternalLabelsObj = (modules: string[]) => {
const labels = modules.map(module => createModuleLabelItem(module))
return Object.fromEntries(calcExternalLabels(labels))
}

test('calculate label of external module', () => {
const modules1: string[] = []
expect(getExternalLabelsObj(modules1)).toEqual({})
const modules2 = ['']
expect(getExternalLabelsObj(modules2)).toEqual({ '': '' })
const modules3 = [
'org/testA',
'org/testB',
]
expect(getExternalLabelsObj(modules3)).toEqual({
'org/testA': 'org/testA',
'org/testB': 'org/testB',
})
const modules4 = [...modules3, 'org/testC']
expect(getExternalLabelsObj(modules4)).toEqual({
'org/testA': 'org/testA',
'org/testB': 'org/testB',
'org/testC': 'org/testC',
})
const modules5 = [
'orgA',
'orgB',
]
expect(getExternalLabelsObj(modules5)).toEqual({
orgA: 'orgA',
orgB: 'orgB',
})
const modules6 = ['orgA', 'orgB', 'orgA/dist']
expect(getExternalLabelsObj(modules6)).toEqual({
'orgA': 'orgA',
'orgB': 'orgB',
'orgA/dist': 'orgA/dist',
})
const modules7 = [
'@testing-library/jest-dom/dist/index.js',
'@testing-library/react/dist/index.js',
]
expect(getExternalLabelsObj(modules7)).toEqual({
'@testing-library/jest-dom/dist/index.js': '@testing-library/jest-dom',
'@testing-library/react/dist/index.js': '@testing-library/react',
})
})

0 comments on commit 1d0a97b

Please sign in to comment.