-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.ts
119 lines (105 loc) · 3.27 KB
/
util.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import * as fs from "https://deno.land/[email protected]/fs/mod.ts"
import * as path from "https://deno.land/[email protected]/path/mod.ts"
export function regulateSlash (s: string) {
return s.replace(/\\/g, '/')
}
export function listFilesRecursive (dir: string, includeFilters: RegExp[], excludeFilters: RegExp[]) {
return fs.walkSync(dir, { includeDirs: false, skip: excludeFilters, match: includeFilters.length > 0 ? includeFilters : undefined })
}
export function applyFiltersToStr (str: string, includeFilters: RegExp[], excludeFilters: RegExp[]) {
if (includeFilters.length > 0) {
if (!includeFilters.some(v => str.match(v) != null)) {
return false
}
}
if (excludeFilters.some(v => str.match(v) != null)) {
return false
}
return true
}
export type RecursiveObject = {
[key: string]: RecursiveObject
}
export function buildHierarchy (arr: string[], separator: RegExp, hierarchy: RecursiveObject = {}) {
if (!separator.global) throw new Error('separator must be global')
for (const s of arr) {
let o = hierarchy
while (true) {
const r = separator.exec(s)
const part = r? s.slice(0, r.index): s
if (!(part in o)) {
o[part] = {}
}
o = o[part]
if (!r) break
}
}
return hierarchy
}
export function walkHierarchy (hierarchy: RecursiveObject, visitor: (parent: string, child: string) => void, myName?: string) {
for (const key of Object.keys(hierarchy)) {
if (myName !== undefined) {
visitor(myName, key)
}
const child = hierarchy[key]
if (child) {
walkHierarchy(child, visitor, key)
}
}
}
export function stripExt (filename: string) {
const ext = path.extname(filename)
return ext.length === 0 ? filename : filename.slice(0, -ext.length)
}
export function findCycleDependencies (data: string[][]) {
let deps = data
const cycles: string[][] = []
while (true) {
while (true) {
const d = deps.filter(v => deps.findIndex(u => u[0] === v[1]) >= 0)
if (d.length === deps.length) {
break
}
deps = d
}
if (deps.length === 0) {
break
}
const indexes = [0]
while (true) {
const lastIndex = indexes[indexes.length - 1]
const i = deps.findIndex(v => v[0] === deps[lastIndex][1])
indexes.push(i)
const ii = indexes.findIndex(v => v === i)
if (ii !== indexes.length - 1) {
cycles.push(indexes.slice(ii).map(x => deps[x][0]))
deps = deps.filter((_v, i) => indexes.findIndex(x => x === i) < 0)
break
}
}
}
return cycles
}
export type ProgressCallback = (current: number, total: number) => void
export class ProgressMarker {
private current = 0
private total = 0
private threshold = 0
private significant = 0
private callback?: ProgressCallback
constructor (total: number, callback?: ProgressCallback, threshold?: number) {
this.total = total
this.callback = callback
if (!threshold) this.threshold = Math.floor(this.total / 100)
}
advance (delta: number) {
this.current += delta
const significant = Math.floor(this.current / this.threshold)
if (significant !== this.significant || this.current === this.total) {
this.significant = significant
if (this.callback) {
this.callback(this.current, this.total)
}
}
}
}