v-transform 2.2.1 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/package.json +10 -10
- package/src/dump.js +66 -66
- package/src/index.js +29 -29
- package/src/loader.js +72 -72
- package/src/parser.js +140 -140
- package/src/prepare.js +23 -23
- package/src/transform.js +93 -93
- package/.trunk/trunk.yaml +0 -5
- package/dist/blindDate/dimension.json +0 -138
- package/dist/lifeRestart/en-us/achievement.json +0 -1487
- package/dist/lifeRestart/en-us/age.json +0 -71820
- package/dist/lifeRestart/en-us/character.json +0 -1594
- package/dist/lifeRestart/en-us/events.json +0 -13164
- package/dist/lifeRestart/en-us/talents.json +0 -1817
- package/dist/lifeRestart/specialthanks.json +0 -4591
- package/dist/lifeRestart/zh-cn/achievement.json +0 -1487
- package/dist/lifeRestart/zh-cn/age.json +0 -71820
- package/dist/lifeRestart/zh-cn/character.json +0 -1594
- package/dist/lifeRestart/zh-cn/events.json +0 -13164
- package/dist/lifeRestart/zh-cn/talents.json +0 -1817
- package/dist/motleycrowd/achievement.json +0 -1513
- package/dist/motleycrowd/badge.json +0 -1587
- package/dist/motleycrowd/card.json +0 -22
- package/dist/motleycrowd/reward.json +0 -884
- package/dist/question/question.json +0 -1306
- package/dist/question/result.json +0 -260
package/src/parser.js
CHANGED
|
@@ -1,140 +1,140 @@
|
|
|
1
|
-
import yaml from 'js-yaml'
|
|
2
|
-
|
|
3
|
-
function isCommentKey(key) {
|
|
4
|
-
return key.startsWith('#')
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function isJsonKey(key) {
|
|
8
|
-
return key.startsWith('@')
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function processHeaderColumn(col, head, layer, subs, json) {
|
|
12
|
-
let key = head[col].trim()
|
|
13
|
-
if (isCommentKey(key)) return
|
|
14
|
-
if (isJsonKey(key)) {
|
|
15
|
-
json.push(col)
|
|
16
|
-
key = key.substr(1)
|
|
17
|
-
}
|
|
18
|
-
const [first, ...parts] = key.split(/[.:]/).map(p => p.trim())
|
|
19
|
-
if (!subs[first]) layer.push(first)
|
|
20
|
-
if (parts.length > 0) {
|
|
21
|
-
if (!subs[first]) subs[first] = {}
|
|
22
|
-
subs[first][col] = parts.join('.')
|
|
23
|
-
} else if (first.endsWith('[]')) {
|
|
24
|
-
if (!subs[first]) subs[first] = []
|
|
25
|
-
subs[first].push(col)
|
|
26
|
-
} else {
|
|
27
|
-
subs[first] = col
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function createObjectSub(key, subs) {
|
|
32
|
-
subs = [parseStruct(subs[key])]
|
|
33
|
-
key = key.substr(0, key.length - 2)
|
|
34
|
-
return { type: 'object', key, subs }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function createArraySub(key, subs) {
|
|
38
|
-
if (Array.isArray(subs[key]))
|
|
39
|
-
subs = subs[key].map(source => ({ type: 'value', source }))
|
|
40
|
-
else subs = [parseStruct(subs[key])]
|
|
41
|
-
key = key.substr(0, key.length - 2)
|
|
42
|
-
return { type: 'array', key, subs }
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function createValueSub(key, subs) {
|
|
46
|
-
const source = subs[key]
|
|
47
|
-
if (key.startsWith('$')) key = key.substr(1)
|
|
48
|
-
return { type: 'value', key, source }
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function createNestedObjectSub(key, subs) {
|
|
52
|
-
return { type: 'object', key, subs: parseStruct(subs[key]).subs }
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function createSubFromKey(key, subs) {
|
|
56
|
-
if (key.endsWith('{}')) return createObjectSub(key, subs)
|
|
57
|
-
if (key.endsWith('[]')) return createArraySub(key, subs)
|
|
58
|
-
if (typeof subs[key] === 'string') return createValueSub(key, subs)
|
|
59
|
-
return createNestedObjectSub(key, subs)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function parseStruct(head) {
|
|
63
|
-
const layer = []
|
|
64
|
-
const subs = {}
|
|
65
|
-
const json = []
|
|
66
|
-
for (const col in head) processHeaderColumn(col, head, layer, subs, json)
|
|
67
|
-
const struct = { type: 'object', subs: [], json }
|
|
68
|
-
for (const key of layer) {
|
|
69
|
-
if (key.startsWith('$')) struct.key = `#${subs[key]}`
|
|
70
|
-
const sub = createSubFromKey(key, subs)
|
|
71
|
-
struct.subs.push(sub)
|
|
72
|
-
}
|
|
73
|
-
return struct
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function formatRow({ type, key, source, subs }, row, original, json) {
|
|
77
|
-
if (('' + row[0]).startsWith('#')) return null
|
|
78
|
-
if (key?.startsWith('#')) key = row[key.substr(1)]
|
|
79
|
-
switch (type) {
|
|
80
|
-
case 'value':
|
|
81
|
-
return formatValue(key, source, row[source], json)
|
|
82
|
-
case 'array':
|
|
83
|
-
return formatArray(key, subs, row, original, json)
|
|
84
|
-
case 'object':
|
|
85
|
-
return formatObject(key, subs, row, original, json)
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function formatValue(key, source, value, json) {
|
|
90
|
-
if (value == null) return null
|
|
91
|
-
if (json.includes(source)) value = yaml.load(value)
|
|
92
|
-
return { key, value }
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function formatArray(key, subs, row, original, json) {
|
|
96
|
-
const arr = original?.[key] || []
|
|
97
|
-
for (const sub of subs) {
|
|
98
|
-
const data = formatRow(sub, row, arr, json)
|
|
99
|
-
if (data) arr.push(data.value)
|
|
100
|
-
}
|
|
101
|
-
return arr.length ? { key, value: arr } : null
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function formatObject(key, subs, row, original, json) {
|
|
105
|
-
const obj = original?.[key] || {}
|
|
106
|
-
let hasData = false
|
|
107
|
-
for (const sub of subs) {
|
|
108
|
-
const data = formatRow(sub, row, obj, json)
|
|
109
|
-
if (data) {
|
|
110
|
-
hasData = true
|
|
111
|
-
obj[data.key] = data.value
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return hasData ? { key, value: obj } : null
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function formatSheet(struct, rawSheet, json) {
|
|
118
|
-
let data
|
|
119
|
-
if (struct.key == void 0) {
|
|
120
|
-
data = []
|
|
121
|
-
for (const row of rawSheet) {
|
|
122
|
-
const temp = formatRow(struct, row, null, json)
|
|
123
|
-
if (temp) data.push(temp.value)
|
|
124
|
-
}
|
|
125
|
-
} else {
|
|
126
|
-
data = {}
|
|
127
|
-
for (const row of rawSheet) {
|
|
128
|
-
const temp = formatRow(struct, row, data, json)
|
|
129
|
-
if (temp) data[temp.key] = temp.value
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return data
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export function parser(rawSheet) {
|
|
137
|
-
const struct = parseStruct(rawSheet.shift())
|
|
138
|
-
rawSheet.shift()
|
|
139
|
-
return formatSheet(struct, rawSheet, struct.json)
|
|
140
|
-
}
|
|
1
|
+
import yaml from 'js-yaml'
|
|
2
|
+
|
|
3
|
+
function isCommentKey(key) {
|
|
4
|
+
return key.startsWith('#')
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function isJsonKey(key) {
|
|
8
|
+
return key.startsWith('@')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function processHeaderColumn(col, head, layer, subs, json) {
|
|
12
|
+
let key = head[col].trim()
|
|
13
|
+
if (isCommentKey(key)) return
|
|
14
|
+
if (isJsonKey(key)) {
|
|
15
|
+
json.push(col)
|
|
16
|
+
key = key.substr(1)
|
|
17
|
+
}
|
|
18
|
+
const [first, ...parts] = key.split(/[.:]/).map(p => p.trim())
|
|
19
|
+
if (!subs[first]) layer.push(first)
|
|
20
|
+
if (parts.length > 0) {
|
|
21
|
+
if (!subs[first]) subs[first] = {}
|
|
22
|
+
subs[first][col] = parts.join('.')
|
|
23
|
+
} else if (first.endsWith('[]')) {
|
|
24
|
+
if (!subs[first]) subs[first] = []
|
|
25
|
+
subs[first].push(col)
|
|
26
|
+
} else {
|
|
27
|
+
subs[first] = col
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function createObjectSub(key, subs) {
|
|
32
|
+
subs = [parseStruct(subs[key])]
|
|
33
|
+
key = key.substr(0, key.length - 2)
|
|
34
|
+
return { type: 'object', key, subs }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function createArraySub(key, subs) {
|
|
38
|
+
if (Array.isArray(subs[key]))
|
|
39
|
+
subs = subs[key].map(source => ({ type: 'value', source }))
|
|
40
|
+
else subs = [parseStruct(subs[key])]
|
|
41
|
+
key = key.substr(0, key.length - 2)
|
|
42
|
+
return { type: 'array', key, subs }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createValueSub(key, subs) {
|
|
46
|
+
const source = subs[key]
|
|
47
|
+
if (key.startsWith('$')) key = key.substr(1)
|
|
48
|
+
return { type: 'value', key, source }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function createNestedObjectSub(key, subs) {
|
|
52
|
+
return { type: 'object', key, subs: parseStruct(subs[key]).subs }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function createSubFromKey(key, subs) {
|
|
56
|
+
if (key.endsWith('{}')) return createObjectSub(key, subs)
|
|
57
|
+
if (key.endsWith('[]')) return createArraySub(key, subs)
|
|
58
|
+
if (typeof subs[key] === 'string') return createValueSub(key, subs)
|
|
59
|
+
return createNestedObjectSub(key, subs)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function parseStruct(head) {
|
|
63
|
+
const layer = []
|
|
64
|
+
const subs = {}
|
|
65
|
+
const json = []
|
|
66
|
+
for (const col in head) processHeaderColumn(col, head, layer, subs, json)
|
|
67
|
+
const struct = { type: 'object', subs: [], json }
|
|
68
|
+
for (const key of layer) {
|
|
69
|
+
if (key.startsWith('$')) struct.key = `#${subs[key]}`
|
|
70
|
+
const sub = createSubFromKey(key, subs)
|
|
71
|
+
struct.subs.push(sub)
|
|
72
|
+
}
|
|
73
|
+
return struct
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function formatRow({ type, key, source, subs }, row, original, json) {
|
|
77
|
+
if (('' + row[0]).startsWith('#')) return null
|
|
78
|
+
if (key?.startsWith('#')) key = row[key.substr(1)]
|
|
79
|
+
switch (type) {
|
|
80
|
+
case 'value':
|
|
81
|
+
return formatValue(key, source, row[source], json)
|
|
82
|
+
case 'array':
|
|
83
|
+
return formatArray(key, subs, row, original, json)
|
|
84
|
+
case 'object':
|
|
85
|
+
return formatObject(key, subs, row, original, json)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function formatValue(key, source, value, json) {
|
|
90
|
+
if (value == null) return null
|
|
91
|
+
if (json.includes(source)) value = yaml.load(value)
|
|
92
|
+
return { key, value }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function formatArray(key, subs, row, original, json) {
|
|
96
|
+
const arr = original?.[key] || []
|
|
97
|
+
for (const sub of subs) {
|
|
98
|
+
const data = formatRow(sub, row, arr, json)
|
|
99
|
+
if (data) arr.push(data.value)
|
|
100
|
+
}
|
|
101
|
+
return arr.length ? { key, value: arr } : null
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function formatObject(key, subs, row, original, json) {
|
|
105
|
+
const obj = original?.[key] || {}
|
|
106
|
+
let hasData = false
|
|
107
|
+
for (const sub of subs) {
|
|
108
|
+
const data = formatRow(sub, row, obj, json)
|
|
109
|
+
if (data) {
|
|
110
|
+
hasData = true
|
|
111
|
+
obj[data.key] = data.value
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return hasData ? { key, value: obj } : null
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function formatSheet(struct, rawSheet, json) {
|
|
118
|
+
let data
|
|
119
|
+
if (struct.key == void 0) {
|
|
120
|
+
data = []
|
|
121
|
+
for (const row of rawSheet) {
|
|
122
|
+
const temp = formatRow(struct, row, null, json)
|
|
123
|
+
if (temp) data.push(temp.value)
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
data = {}
|
|
127
|
+
for (const row of rawSheet) {
|
|
128
|
+
const temp = formatRow(struct, row, data, json)
|
|
129
|
+
if (temp) data[temp.key] = temp.value
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return data
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function parser(rawSheet) {
|
|
137
|
+
const struct = parseStruct(rawSheet.shift())
|
|
138
|
+
rawSheet.shift()
|
|
139
|
+
return formatSheet(struct, rawSheet, struct.json)
|
|
140
|
+
}
|
package/src/prepare.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import { readFile } from 'node:fs/promises'
|
|
3
|
-
import { read, utils } from 'xlsx'
|
|
4
|
-
|
|
5
|
-
export async function prepare(xlsxPath) {
|
|
6
|
-
switch (path.extname(xlsxPath)) {
|
|
7
|
-
case '.xls':
|
|
8
|
-
case '.xlsx':
|
|
9
|
-
break
|
|
10
|
-
default:
|
|
11
|
-
return []
|
|
12
|
-
}
|
|
13
|
-
const xlsxFileBuffer = await readFile(xlsxPath)
|
|
14
|
-
const xlsx = read(xlsxFileBuffer, { type: 'buffer' })
|
|
15
|
-
const datas = []
|
|
16
|
-
for (const name in xlsx.Sheets) {
|
|
17
|
-
const sheetRawData = xlsx.Sheets[name]
|
|
18
|
-
if (!sheetRawData['!ref']) break
|
|
19
|
-
const data = utils.sheet_to_json(sheetRawData, { header: 1 })
|
|
20
|
-
datas.push({ name, data })
|
|
21
|
-
}
|
|
22
|
-
return datas
|
|
23
|
-
}
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { readFile } from 'node:fs/promises'
|
|
3
|
+
import { read, utils } from 'xlsx'
|
|
4
|
+
|
|
5
|
+
export async function prepare(xlsxPath) {
|
|
6
|
+
switch (path.extname(xlsxPath)) {
|
|
7
|
+
case '.xls':
|
|
8
|
+
case '.xlsx':
|
|
9
|
+
break
|
|
10
|
+
default:
|
|
11
|
+
return []
|
|
12
|
+
}
|
|
13
|
+
const xlsxFileBuffer = await readFile(xlsxPath)
|
|
14
|
+
const xlsx = read(xlsxFileBuffer, { type: 'buffer' })
|
|
15
|
+
const datas = []
|
|
16
|
+
for (const name in xlsx.Sheets) {
|
|
17
|
+
const sheetRawData = xlsx.Sheets[name]
|
|
18
|
+
if (!sheetRawData['!ref']) break
|
|
19
|
+
const data = utils.sheet_to_json(sheetRawData, { header: 1 })
|
|
20
|
+
datas.push({ name, data })
|
|
21
|
+
}
|
|
22
|
+
return datas
|
|
23
|
+
}
|
package/src/transform.js
CHANGED
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import { load } from './loader.js'
|
|
3
|
-
import { prepare } from './prepare.js'
|
|
4
|
-
import { parser } from './parser.js'
|
|
5
|
-
import { dump } from './dump.js'
|
|
6
|
-
|
|
7
|
-
export async function transform(options) {
|
|
8
|
-
const now = Date.now()
|
|
9
|
-
const configurations = await load(options)
|
|
10
|
-
for (const config of configurations) await task(config)
|
|
11
|
-
console.info(`Transformed in ${Date.now() - now}ms`)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function task({ files, dest, cwd, type, space, addition }) {
|
|
15
|
-
console.info('Transform task config:', { files, dest, cwd, type, space })
|
|
16
|
-
const m = new Map()
|
|
17
|
-
for (const file of files) {
|
|
18
|
-
const dir = path.resolve(dest, path.dirname(file))
|
|
19
|
-
const prepared = await prepare(path.resolve(cwd, file))
|
|
20
|
-
processPrepared(prepared, dir, m)
|
|
21
|
-
}
|
|
22
|
-
for (const [sheet, job] of m) {
|
|
23
|
-
const data = job.result()
|
|
24
|
-
if (addition) await dump(sheet, { data, ...addition }, type, space)
|
|
25
|
-
else await dump(sheet, data, type, space)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function processPrepared(prepared, dir, m) {
|
|
30
|
-
for (const { name, data } of prepared) {
|
|
31
|
-
if (name.startsWith('#')) continue
|
|
32
|
-
const { sheet, keys } = parseSheetAndKeys(name, dir)
|
|
33
|
-
if (!m.has(sheet)) m.set(sheet, new JobData())
|
|
34
|
-
m.get(sheet).append({ keys, data: parser(data) })
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function parseSheetAndKeys(name, dir) {
|
|
39
|
-
let sheet = name.split('#')[0]
|
|
40
|
-
sheet = sheet.replace('<arr>', '')
|
|
41
|
-
if (sheet.startsWith('>')) sheet = sheet.substring(1)
|
|
42
|
-
const keys = sheet.split('.')
|
|
43
|
-
sheet = path.resolve(dir, keys.shift())
|
|
44
|
-
return { sheet, keys }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
class JobData {
|
|
48
|
-
constructor(data) {
|
|
49
|
-
if (data) this.append(data)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
#data = []
|
|
53
|
-
|
|
54
|
-
append(data) {
|
|
55
|
-
this.#data.push(data)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
result() {
|
|
59
|
-
if (!this.#data.length) return {}
|
|
60
|
-
let result
|
|
61
|
-
for (const { keys, data } of this.#data) {
|
|
62
|
-
if (!keys.length) {
|
|
63
|
-
result = this.#combine(result, data)
|
|
64
|
-
continue
|
|
65
|
-
}
|
|
66
|
-
if (!result) result = {}
|
|
67
|
-
let r = result
|
|
68
|
-
let last = keys.pop()
|
|
69
|
-
for (const key of keys) {
|
|
70
|
-
if (!r[key]) r[key] = {}
|
|
71
|
-
r = r[key]
|
|
72
|
-
}
|
|
73
|
-
r[last] = this.#combine(r[last], data)
|
|
74
|
-
}
|
|
75
|
-
return result
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
#combine(a, b) {
|
|
79
|
-
if (a == null) return b
|
|
80
|
-
if (b == null) return a
|
|
81
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
82
|
-
if (Array.isArray(b)) return a.concat(b)
|
|
83
|
-
a.push(b)
|
|
84
|
-
return a
|
|
85
|
-
}
|
|
86
|
-
if (Array.isArray(a)) return this.#combine(a, Object.values(b))
|
|
87
|
-
if (Array.isArray(b)) return this.#combine(Object.values(a), b)
|
|
88
|
-
const result = {}
|
|
89
|
-
for (const key in a) result[key] = this.#combine(a[key], b[key])
|
|
90
|
-
for (const key in b) if (!result[key]) result[key] = b[key]
|
|
91
|
-
return result
|
|
92
|
-
}
|
|
93
|
-
}
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { load } from './loader.js'
|
|
3
|
+
import { prepare } from './prepare.js'
|
|
4
|
+
import { parser } from './parser.js'
|
|
5
|
+
import { dump } from './dump.js'
|
|
6
|
+
|
|
7
|
+
export async function transform(options) {
|
|
8
|
+
const now = Date.now()
|
|
9
|
+
const configurations = await load(options)
|
|
10
|
+
for (const config of configurations) await task(config)
|
|
11
|
+
console.info(`Transformed in ${Date.now() - now}ms`)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function task({ files, dest, cwd, type, space, addition }) {
|
|
15
|
+
console.info('Transform task config:', { files, dest, cwd, type, space })
|
|
16
|
+
const m = new Map()
|
|
17
|
+
for (const file of files) {
|
|
18
|
+
const dir = path.resolve(dest, path.dirname(file))
|
|
19
|
+
const prepared = await prepare(path.resolve(cwd, file))
|
|
20
|
+
processPrepared(prepared, dir, m)
|
|
21
|
+
}
|
|
22
|
+
for (const [sheet, job] of m) {
|
|
23
|
+
const data = job.result()
|
|
24
|
+
if (addition) await dump(sheet, { data, ...addition }, type, space)
|
|
25
|
+
else await dump(sheet, data, type, space)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function processPrepared(prepared, dir, m) {
|
|
30
|
+
for (const { name, data } of prepared) {
|
|
31
|
+
if (name.startsWith('#')) continue
|
|
32
|
+
const { sheet, keys } = parseSheetAndKeys(name, dir)
|
|
33
|
+
if (!m.has(sheet)) m.set(sheet, new JobData())
|
|
34
|
+
m.get(sheet).append({ keys, data: parser(data) })
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseSheetAndKeys(name, dir) {
|
|
39
|
+
let sheet = name.split('#')[0]
|
|
40
|
+
sheet = sheet.replace('<arr>', '')
|
|
41
|
+
if (sheet.startsWith('>')) sheet = sheet.substring(1)
|
|
42
|
+
const keys = sheet.split('.')
|
|
43
|
+
sheet = path.resolve(dir, keys.shift())
|
|
44
|
+
return { sheet, keys }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class JobData {
|
|
48
|
+
constructor(data) {
|
|
49
|
+
if (data) this.append(data)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
#data = []
|
|
53
|
+
|
|
54
|
+
append(data) {
|
|
55
|
+
this.#data.push(data)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
result() {
|
|
59
|
+
if (!this.#data.length) return {}
|
|
60
|
+
let result
|
|
61
|
+
for (const { keys, data } of this.#data) {
|
|
62
|
+
if (!keys.length) {
|
|
63
|
+
result = this.#combine(result, data)
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
if (!result) result = {}
|
|
67
|
+
let r = result
|
|
68
|
+
let last = keys.pop()
|
|
69
|
+
for (const key of keys) {
|
|
70
|
+
if (!r[key]) r[key] = {}
|
|
71
|
+
r = r[key]
|
|
72
|
+
}
|
|
73
|
+
r[last] = this.#combine(r[last], data)
|
|
74
|
+
}
|
|
75
|
+
return result
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
#combine(a, b) {
|
|
79
|
+
if (a == null) return b
|
|
80
|
+
if (b == null) return a
|
|
81
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
82
|
+
if (Array.isArray(b)) return a.concat(b)
|
|
83
|
+
a.push(b)
|
|
84
|
+
return a
|
|
85
|
+
}
|
|
86
|
+
if (Array.isArray(a)) return this.#combine(a, Object.values(b))
|
|
87
|
+
if (Array.isArray(b)) return this.#combine(Object.values(a), b)
|
|
88
|
+
const result = {}
|
|
89
|
+
for (const key in a) result[key] = this.#combine(a[key], b[key])
|
|
90
|
+
for (const key in b) if (!result[key]) result[key] = b[key]
|
|
91
|
+
return result
|
|
92
|
+
}
|
|
93
|
+
}
|
package/.trunk/trunk.yaml
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"sex": {
|
|
3
|
-
"1": {
|
|
4
|
-
"id": 1,
|
|
5
|
-
"description": "男",
|
|
6
|
-
"weight": 1,
|
|
7
|
-
"value": 1
|
|
8
|
-
},
|
|
9
|
-
"2": {
|
|
10
|
-
"id": 2,
|
|
11
|
-
"description": "女",
|
|
12
|
-
"weight": 1,
|
|
13
|
-
"value": 1
|
|
14
|
-
},
|
|
15
|
-
"3": {
|
|
16
|
-
"id": 3,
|
|
17
|
-
"description": "mtf",
|
|
18
|
-
"weight": 0.1,
|
|
19
|
-
"value": 10
|
|
20
|
-
},
|
|
21
|
-
"4": {
|
|
22
|
-
"id": 4,
|
|
23
|
-
"description": "ftm",
|
|
24
|
-
"weight": 0.1,
|
|
25
|
-
"value": 10
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"age": {
|
|
29
|
-
"1": {
|
|
30
|
-
"id": 1,
|
|
31
|
-
"description": "18岁",
|
|
32
|
-
"weight": 0.1,
|
|
33
|
-
"value": 10
|
|
34
|
-
},
|
|
35
|
-
"2": {
|
|
36
|
-
"id": 2,
|
|
37
|
-
"description": "19岁",
|
|
38
|
-
"weight": 0.2,
|
|
39
|
-
"value": 9
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
"backing": {
|
|
43
|
-
"1": {
|
|
44
|
-
"id": 1,
|
|
45
|
-
"description": "当官的",
|
|
46
|
-
"weight": 1,
|
|
47
|
-
"value": 1
|
|
48
|
-
},
|
|
49
|
-
"2": {
|
|
50
|
-
"id": 2,
|
|
51
|
-
"description": "老农民",
|
|
52
|
-
"weight": 1,
|
|
53
|
-
"value": 1
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
"education": {
|
|
57
|
-
"1": {
|
|
58
|
-
"id": 1,
|
|
59
|
-
"description": "小学",
|
|
60
|
-
"weight": 1,
|
|
61
|
-
"value": 1
|
|
62
|
-
},
|
|
63
|
-
"2": {
|
|
64
|
-
"id": 2,
|
|
65
|
-
"description": "初中",
|
|
66
|
-
"weight": 1,
|
|
67
|
-
"value": 1
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
"figure": {
|
|
71
|
-
"1": {
|
|
72
|
-
"id": 1,
|
|
73
|
-
"description": "健康美",
|
|
74
|
-
"weight": 1,
|
|
75
|
-
"value": 10
|
|
76
|
-
},
|
|
77
|
-
"2": {
|
|
78
|
-
"id": 2,
|
|
79
|
-
"description": "病弱美",
|
|
80
|
-
"weight": 1,
|
|
81
|
-
"value": 5
|
|
82
|
-
},
|
|
83
|
-
"3": {
|
|
84
|
-
"id": 3,
|
|
85
|
-
"description": "病态丑",
|
|
86
|
-
"weight": 1,
|
|
87
|
-
"value": 1
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
"height": {
|
|
91
|
-
"1": {
|
|
92
|
-
"id": 1,
|
|
93
|
-
"description": "250cm",
|
|
94
|
-
"weight": 1,
|
|
95
|
-
"value": 25
|
|
96
|
-
},
|
|
97
|
-
"2": {
|
|
98
|
-
"id": 2,
|
|
99
|
-
"description": "180cm",
|
|
100
|
-
"weight": 5,
|
|
101
|
-
"value": 18
|
|
102
|
-
},
|
|
103
|
-
"3": {
|
|
104
|
-
"id": 3,
|
|
105
|
-
"description": "170cm",
|
|
106
|
-
"weight": 10,
|
|
107
|
-
"value": 17
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
"income": {
|
|
111
|
-
"1": {
|
|
112
|
-
"id": 1,
|
|
113
|
-
"description": 0,
|
|
114
|
-
"weight": 1,
|
|
115
|
-
"value": 1
|
|
116
|
-
},
|
|
117
|
-
"2": {
|
|
118
|
-
"id": 2,
|
|
119
|
-
"description": "1-3000",
|
|
120
|
-
"weight": 1,
|
|
121
|
-
"value": 1
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
"profession": {
|
|
125
|
-
"1": {
|
|
126
|
-
"id": 1,
|
|
127
|
-
"description": "程序员",
|
|
128
|
-
"weight": 1,
|
|
129
|
-
"value": 1
|
|
130
|
-
},
|
|
131
|
-
"2": {
|
|
132
|
-
"id": 2,
|
|
133
|
-
"description": "游戏策划",
|
|
134
|
-
"weight": 1,
|
|
135
|
-
"value": 1
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|