Repository navigation
Expand file tree
/
Copy pathutils.ts
More file actions
154 lines (131 loc) · 3.89 KB
/
Copy pathutils.ts
File metadata and controls
154 lines (131 loc) · 3.89 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import _ from 'lodash'
import xml2js from 'xml2js'
import { GeneralObject } from './types'
import type { TOCItem } from './parseEpub'
export interface TraverseNestedObject {
preFilter?: (node: GeneralObject) => boolean
postFilter?: (node: GeneralObject) => boolean
// children must be returned from transformer
// or it may not work as expected
transformer?: (node: GeneralObject, children?: GeneralObject[]) => any
finalTransformer?: (node: GeneralObject) => any
childrenKey: string
}
const xmlParser = new xml2js.Parser()
const cacheNavPool: Record<string, TOCItem> = {
}
/**
* Fix the generated file name according to the title corresponding to toc
*/
export function findRealPath(filePath: string, navs?: TOCItem[]): TOCItem | undefined {
if (!navs) return;
const navChildren: TOCItem[] = [];
for (const n of navs) {
const { path, children } = n
if (cacheNavPool[filePath]) {
return cacheNavPool[filePath]
}
if (path.includes(filePath)) {
cacheNavPool[filePath] = n
return n
}
if (children) navChildren.push(...children)
}
if (navChildren.length > 0) {
return findRealPath(filePath, navChildren)
}
}
// return findRealPath(children, filePath)
// 函数用于清理文件名,将非法字符替换为下划线
export const sanitizeFileName = (fileName: string, replacementChar = '_') => {
const invalidCharsPattern = /[\\/:*?"<>|]/g;
return fileName.replace(invalidCharsPattern, replacementChar);
}
export const xmlToJs = (xml: string) => {
return new Promise<any>((resolve, reject) => {
// @ts-ignore
xmlParser.parseString(xml, (err: Error, object: GeneralObject) => {
if (err) {
reject(err)
} else {
resolve(object)
}
})
})
}
export const determineRoot = (opfPath: string) => {
let root = ''
// set the opsRoot for resolving paths
if (opfPath.match(/\//)) {
// not at top level
root = opfPath.replace(/\/([^\/]+)\.opf/i, '')
if (!root.match(/\/$/)) {
// 以 '/' 结尾,下面的 zip 路径写法会简单很多
root += '/'
}
if (root.match(/^\//)) {
root = root.replace(/^\//, '')
}
}
return root
}
/**
* traverseNestedObject
* a note about config.transformer
* `children` is a recursively transformed object and should be returned for transformer to take effect
* objects without `children` will be transformed by finalTransformer
* @param _rootObject
* @param config
*/
export const traverseNestedObject = (
_rootObject: Object | Object[],
config: TraverseNestedObject,
) => {
const { childrenKey, transformer, preFilter, postFilter, finalTransformer } = config
if (!_rootObject) {
return []
}
const traverse = (rootObject: any | any[]): any[] => {
const makeArray = () => {
if (
Array.isArray(rootObject) ||
_.isArrayLikeObject(rootObject) ||
_.isArrayLike(rootObject)
) {
return rootObject
}
return [rootObject]
}
const rootArray = makeArray()
let result = rootArray
if (preFilter) {
result = _.filter(result, preFilter)
}
result = _.map(result, (object: any, __: string) => {
if (object[childrenKey]) {
const transformedChildren = traverse(object[childrenKey])
// in parseHTML, if a tag is in unwrap list, like <span>aaa<span>bbb</span></span>
// the result needs to be flatten
const children = _.isEmpty(transformedChildren)
? undefined
: _.flattenDeep(transformedChildren)
if (transformer) {
return transformer(object, children)
}
return {
...object,
[childrenKey]: children,
}
}
if (finalTransformer) {
return finalTransformer(object)
}
return object
})
if (postFilter) {
result = _.filter(result, postFilter)
}
return result
}
return _.flattenDeep(traverse(_rootObject))
}