-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsetOfBlocks.ts
127 lines (114 loc) · 3.19 KB
/
setOfBlocks.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
120
121
122
123
124
125
126
127
import { Block } from './block.js'
import { hashCompare } from './utils.js'
import { GetTextTranslation, GetTextTranslations } from 'gettext-parser'
export class SetOfBlocks {
/** An array of Block objects */
blocks: Block[]
path?: string
/**
* Constructor for the Block class.
*
* @param {Block[]} arr - optional array of Block objects
* @param path - optional path to the file
*/
constructor(arr?: Block[], path?: string) {
this.blocks = (arr as Block[]) || []
this.path = path || undefined
}
/**
* Add a block to the collection, merging if a duplicate exists.
*
* @param {Block} block - the block to add
* @return {void}
*/
add(block: Block): void {
const duplicate = this.getDuplicate(block.hash())
if (duplicate) {
duplicate.merge(block)
} else {
this.blocks.push(block)
}
}
/**
* Find and return a duplicate block based on the given hash.
*
* @param {number} hash - the hash to search for
* @return {Block | undefined} the duplicate block, if found
*/
getDuplicate(hash: number): Block | undefined {
for (let i = 0; i < this.blocks.length; i++) {
if (this.blocks[i].hash() === hash) {
return this.blocks[i]
}
}
return undefined
}
/**
* Chainable sort function
*
* @param type - sorting type ('alphabetically', 'numerically', etc.)
* @returns {SetOfBlocks} the instance of SetOfBlocks
*/
sortBlocks(type: string = 'alphabetically'): SetOfBlocks {
switch (type) {
case 'alphabetically':
this.blocks.sort((a, b) => a.msgid.localeCompare(b.msgid))
break
case 'hash':
this.blocks.sort(hashCompare)
break
}
return this
}
/**
* Chainable filter function used to remove blocks without mandatory fields
* Usually you want to fire this function to clean up the blocks without the msgid
*
* @returns {SetOfBlocks} the instance of SetOfBlocks
*/
cleanup(
mandatoryField: keyof Pick<
GetTextTranslation,
'msgid' | 'msgstr' | 'msgid_plural' | 'msgctxt'
> = 'msgid'
): SetOfBlocks {
this.blocks = this.blocks.filter((b) => !!b[mandatoryField])
return this
}
/**
* Convert the blocks to a string representation.
*
* @return {string} the string representation of the blocks
*/
toStr(): string {
return this.blocks.reduce((prev, curr) => prev + curr.toStr() + '\n\n', '')
}
/**
* Convert the blocks to a JSON representation using a compatible format for gettext-parser module
*
* @return {Map<string, Map<string, GetTextTranslation>>} the JSON representation of the blocks
*/
toJson(): { [key: string]: { [key: string]: GetTextTranslation } } {
const jsonObject: GetTextTranslations['translations'] = {}
this.blocks.forEach((block) => {
const index = block.msgctxt || ''
if (!jsonObject[index]) {
jsonObject[index] = {}
}
jsonObject[index][block.msgid] = block.toJson()
})
return jsonObject
}
/**
* Adds an array of Block objects to the current instance.
*
* @param {Block[]} arr - The array of Block objects to add
* @return {void}
*/
addArray(arr: Block[]): void {
// for each item in the array call add on the current instance
for (const item of arr) this.add(item)
// filter out any items that don't have a msgid
this.blocks.filter((b) => b.msgid)
}
}