echogarden 3.2.0 → 3.4.0
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/README.md +5 -0
- package/dist/api/Synthesis.d.ts.map +1 -1
- package/dist/api/Synthesis.js +31 -21
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/nlp/TextNormalizer.js +1 -1
- package/dist/nlp/TextNormalizer.js.map +1 -1
- package/dist/synthesis/EspeakTTS.d.ts.map +1 -1
- package/dist/synthesis/EspeakTTS.js +20 -5
- package/dist/synthesis/EspeakTTS.js.map +1 -1
- package/dist/utilities/Timer.d.ts +7 -3
- package/dist/utilities/Timer.d.ts.map +1 -1
- package/dist/utilities/Timer.js +42 -30
- package/dist/utilities/Timer.js.map +1 -1
- package/docs/API.md +51 -34
- package/docs/CLI.md +41 -6
- package/docs/Contributing.md +1 -1
- package/docs/Development.md +22 -18
- package/docs/Engines.md +0 -1
- package/docs/Licenses.md +2 -0
- package/docs/Options.md +56 -4
- package/docs/Releases.md +45 -14
- package/docs/Server.md +14 -5
- package/docs/Tasklist.md +37 -1
- package/docs/Technical.md +1 -0
- package/package.json +16 -14
- package/src/api/Synthesis.ts +39 -27
- package/src/nlp/TextNormalizer.ts +1 -2
- package/src/synthesis/EspeakTTS.ts +21 -6
- package/src/utilities/Timer.ts +57 -37
- package/tsconfig.json +51 -53
- package/dist/encodings/HtmlEscape.d.ts +0 -2
- package/dist/encodings/HtmlEscape.d.ts.map +0 -1
- package/dist/encodings/HtmlEscape.js +0 -30
- package/dist/encodings/HtmlEscape.js.map +0 -1
- package/dist/encodings/LEB128.d.ts +0 -2
- package/dist/encodings/LEB128.d.ts.map +0 -1
- package/dist/encodings/LEB128.js +0 -2
- package/dist/encodings/LEB128.js.map +0 -1
- package/dist/utilities/StringBuilder.d.ts +0 -11
- package/dist/utilities/StringBuilder.d.ts.map +0 -1
- package/dist/utilities/StringBuilder.js +0 -39
- package/dist/utilities/StringBuilder.js.map +0 -1
package/src/api/Synthesis.ts
CHANGED
|
@@ -353,7 +353,11 @@ async function synthesizeSegment(text: string, options: SynthesisOptions, callba
|
|
|
353
353
|
let language: string
|
|
354
354
|
|
|
355
355
|
if (options.language) {
|
|
356
|
-
|
|
356
|
+
try {
|
|
357
|
+
language = await normalizeIdentifierToLanguageCode(options.language)
|
|
358
|
+
} catch {
|
|
359
|
+
language = selectedVoice.languages[0]
|
|
360
|
+
}
|
|
357
361
|
} else {
|
|
358
362
|
language = selectedVoice.languages[0]
|
|
359
363
|
}
|
|
@@ -1814,24 +1818,7 @@ export async function requestVoiceList(options: VoiceListRequestOptions, callbac
|
|
|
1814
1818
|
voiceList = await loadVoiceList()
|
|
1815
1819
|
}
|
|
1816
1820
|
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
if (languageCode) {
|
|
1820
|
-
let filteredVoiceList = voiceList.filter(voice => voice.languages.includes(languageCode))
|
|
1821
|
-
|
|
1822
|
-
if (filteredVoiceList.length == 0 && languageCode.includes('-')) {
|
|
1823
|
-
const shortLanguageCode = getShortLanguageCode(languageCode)
|
|
1824
|
-
|
|
1825
|
-
filteredVoiceList = voiceList.filter(voice => voice.languages.includes(shortLanguageCode))
|
|
1826
|
-
}
|
|
1827
|
-
|
|
1828
|
-
voiceList = filteredVoiceList
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
if (options.voiceGender) {
|
|
1832
|
-
const genderLowercase = options.voiceGender.toLowerCase()
|
|
1833
|
-
voiceList = voiceList.filter(voice => voice.gender == genderLowercase || voice.gender == 'unknown')
|
|
1834
|
-
}
|
|
1821
|
+
let bestMatchingVoice: SynthesisVoice
|
|
1835
1822
|
|
|
1836
1823
|
if (options.voice) {
|
|
1837
1824
|
const namePatternLowerCase = options.voice.toLocaleLowerCase()
|
|
@@ -1853,17 +1840,42 @@ export async function requestVoiceList(options: VoiceListRequestOptions, callbac
|
|
|
1853
1840
|
return false
|
|
1854
1841
|
})
|
|
1855
1842
|
}
|
|
1856
|
-
}
|
|
1857
1843
|
|
|
1858
|
-
|
|
1844
|
+
bestMatchingVoice = voiceList[0]
|
|
1845
|
+
} else {
|
|
1846
|
+
let languageCode = ''
|
|
1859
1847
|
|
|
1860
|
-
|
|
1861
|
-
|
|
1848
|
+
if (options.language) {
|
|
1849
|
+
languageCode = await normalizeIdentifierToLanguageCode(options.language || '')
|
|
1862
1850
|
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1851
|
+
let filteredVoiceList = voiceList.filter(voice => voice.languages.includes(languageCode))
|
|
1852
|
+
|
|
1853
|
+
if (filteredVoiceList.length == 0 && languageCode.includes('-')) {
|
|
1854
|
+
const shortLanguageCode = getShortLanguageCode(languageCode)
|
|
1855
|
+
|
|
1856
|
+
filteredVoiceList = voiceList.filter(voice => voice.languages.includes(shortLanguageCode))
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
voiceList = filteredVoiceList
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
if (options.voiceGender) {
|
|
1863
|
+
const genderLowercase = options.voiceGender.toLowerCase()
|
|
1864
|
+
|
|
1865
|
+
voiceList = voiceList.filter(voice => voice.gender == genderLowercase || voice.gender == 'unknown')
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
bestMatchingVoice = voiceList[0]
|
|
1869
|
+
|
|
1870
|
+
if (bestMatchingVoice && voiceList.length > 1 && defaultDialectForLanguageCode[languageCode]) {
|
|
1871
|
+
const expandedLanguageCode = defaultDialectForLanguageCode[languageCode]
|
|
1872
|
+
|
|
1873
|
+
for (const voice of voiceList) {
|
|
1874
|
+
if (voice.languages.includes(expandedLanguageCode)) {
|
|
1875
|
+
bestMatchingVoice = voice
|
|
1876
|
+
|
|
1877
|
+
break
|
|
1878
|
+
}
|
|
1867
1879
|
}
|
|
1868
1880
|
}
|
|
1869
1881
|
}
|
|
@@ -257,12 +257,29 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
const
|
|
260
|
+
const separatorString = ` | `
|
|
261
|
+
|
|
262
|
+
const canInsertSeparators = ![
|
|
263
|
+
'roa/an',
|
|
264
|
+
'an',
|
|
265
|
+
'art/eo',
|
|
266
|
+
'eo',
|
|
267
|
+
'trk/ky',
|
|
268
|
+
'ky',
|
|
269
|
+
'zlw/pl',
|
|
270
|
+
'pl',
|
|
271
|
+
'zle/uk',
|
|
272
|
+
'uk',
|
|
273
|
+
'gmw/nl',
|
|
274
|
+
'nl'
|
|
275
|
+
].includes(voice)
|
|
261
276
|
|
|
262
277
|
let textWithMarkers: string
|
|
263
278
|
|
|
264
|
-
if
|
|
265
|
-
|
|
279
|
+
// Added `espeakOptions.insertSeparators` here because I'm not sure if adding the separator
|
|
280
|
+
// here is completely necessary, and it is causing issues with some languages.
|
|
281
|
+
if (espeakOptions.insertSeparators && canInsertSeparators) {
|
|
282
|
+
textWithMarkers = `()${separatorString}`
|
|
266
283
|
} else {
|
|
267
284
|
textWithMarkers = `() `
|
|
268
285
|
}
|
|
@@ -280,9 +297,7 @@ export async function synthesizeFragments(fragments: string[], espeakOptions: Es
|
|
|
280
297
|
}
|
|
281
298
|
|
|
282
299
|
if (espeakOptions.insertSeparators && canInsertSeparators) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
textWithMarkers += `<mark name="s-${i}"/>${separator}${fragment}${separator}<mark name="e-${i}"/>`
|
|
300
|
+
textWithMarkers += `<mark name="s-${i}"/>${separatorString}${fragment}${separatorString}<mark name="e-${i}"/>`
|
|
286
301
|
} else {
|
|
287
302
|
if (fragment.endsWith('.')) {
|
|
288
303
|
fragment += ' ()'
|
package/src/utilities/Timer.ts
CHANGED
|
@@ -1,79 +1,99 @@
|
|
|
1
|
-
import { logToStderr
|
|
1
|
+
import { logToStderr } from './Utilities.js'
|
|
2
2
|
|
|
3
3
|
export class Timer {
|
|
4
|
-
|
|
4
|
+
private readonly logger: TimerLogger
|
|
5
|
+
|
|
6
|
+
private startTime = 0
|
|
7
|
+
|
|
8
|
+
constructor(logger?: TimerLogger) {
|
|
9
|
+
if (logger) {
|
|
10
|
+
this.logger = logger
|
|
11
|
+
} else {
|
|
12
|
+
this.logger = logToStderr
|
|
13
|
+
}
|
|
5
14
|
|
|
6
|
-
constructor() {
|
|
7
15
|
this.restart()
|
|
8
16
|
}
|
|
9
17
|
|
|
10
|
-
|
|
18
|
+
// Resets the timer to the current time.
|
|
19
|
+
restart(): void {
|
|
11
20
|
this.startTime = Timer.currentTime
|
|
12
21
|
}
|
|
13
22
|
|
|
23
|
+
// Elapsed time in milliseconds (monotonic where supported).
|
|
14
24
|
get elapsedTime(): number {
|
|
15
|
-
// Elapsed time (milliseconds)
|
|
16
25
|
return Timer.currentTime - this.startTime
|
|
17
26
|
}
|
|
18
27
|
|
|
28
|
+
// Elapsed time in seconds.
|
|
19
29
|
get elapsedTimeSeconds(): number {
|
|
20
|
-
// Elapsed time (seconds)
|
|
21
30
|
return this.elapsedTime / 1000
|
|
22
31
|
}
|
|
23
32
|
|
|
33
|
+
// Returns elapsed ms and restarts the timer.
|
|
24
34
|
getElapsedTimeAndRestart(): number {
|
|
25
|
-
const
|
|
35
|
+
const elapsed = this.elapsedTime
|
|
26
36
|
this.restart()
|
|
27
37
|
|
|
28
|
-
return
|
|
38
|
+
return elapsed
|
|
29
39
|
}
|
|
30
40
|
|
|
41
|
+
// Logs elapsed time (in ms) and restarts the timer.
|
|
31
42
|
logAndRestart(title: string, timePrecision = 3): number {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
//
|
|
35
|
-
const message = `${title}: ${roundToDigits(elapsedTime, timePrecision)}ms`
|
|
36
|
-
|
|
37
|
-
logToStderr(message)
|
|
38
|
-
//
|
|
39
|
-
|
|
43
|
+
const elapsedMs = this.elapsedTime
|
|
44
|
+
this.logger(`${title}: ${roundToDigits(elapsedMs, timePrecision)}ms`)
|
|
40
45
|
this.restart()
|
|
41
46
|
|
|
42
|
-
return
|
|
47
|
+
return elapsedMs
|
|
43
48
|
}
|
|
44
49
|
|
|
50
|
+
// Current high-resolution timestamp in milliseconds since Unix epoch.
|
|
45
51
|
static get currentTime(): number {
|
|
46
|
-
|
|
47
|
-
this.createTimestampFunction()
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return this.getTimestamp()
|
|
52
|
+
return this.timestampFunc()
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
// Current timestamp in microseconds (integer).
|
|
53
56
|
static get microsecondTimestamp(): number {
|
|
54
57
|
return Math.floor(Timer.currentTime * 1000)
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let baseTimestamp = 0
|
|
60
|
+
// Clock setup
|
|
61
|
+
private static timestampFunc: () => number = Timer.createTimestampFunction()
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const nodeTimeMilliseconds = Number(nodeTimeNanoSeconds) / 1_000_000
|
|
63
|
+
private static createTimestampFunction(): () => number {
|
|
64
|
+
const g = globalThis as any
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
// 1. Modern standard: performance.now() (Browsers & Node 16+)
|
|
67
|
+
if (typeof g.performance === 'object' && typeof g.performance.now === 'function') {
|
|
68
|
+
const timeOrigin =
|
|
69
|
+
g.performance.timeOrigin ?? (Date.now() - g.performance.now())
|
|
67
70
|
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
const baseTimestamp = Date.now() - performance.now()
|
|
71
|
+
return () => timeOrigin + g.performance.now()
|
|
72
|
+
}
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
// 2. Node.js high resolution timer (BigInt variant, Node 10.4+)
|
|
75
|
+
if (typeof g.process === 'object' && typeof g.process.hrtime === 'function') {
|
|
76
|
+
const startNs = g.process.hrtime.bigint()
|
|
77
|
+
|
|
78
|
+
const epochBaseMs = Date.now() - (Number(startNs) / 1e6)
|
|
79
|
+
|
|
80
|
+
return () =>
|
|
81
|
+
epochBaseMs + Number(g.process.hrtime.bigint()) / 1e6
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 3. Last-resort fallback (non-monotonic)
|
|
85
|
+
if (typeof Date.now === 'function') {
|
|
86
|
+
return () => Date.now()
|
|
75
87
|
}
|
|
88
|
+
|
|
89
|
+
return () => new Date().getTime()
|
|
76
90
|
}
|
|
91
|
+
}
|
|
77
92
|
|
|
78
|
-
|
|
93
|
+
export function roundToDigits(value: number, digits: number): number {
|
|
94
|
+
const factor = 10 ** digits
|
|
95
|
+
|
|
96
|
+
return Math.round(value * factor) / factor
|
|
79
97
|
}
|
|
98
|
+
|
|
99
|
+
type TimerLogger = (msg: string) => void
|
package/tsconfig.json
CHANGED
|
@@ -1,55 +1,53 @@
|
|
|
1
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
|
-
"noErrorTruncation": true,
|
|
54
|
-
}
|
|
2
|
+
// Visit https://aka.ms/tsconfig to read more about this file
|
|
3
|
+
// Only compile library sources; tests under /tests are run by vitest and typechecked separately (tsconfig.tests.json)
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
// File Layout
|
|
6
|
+
"rootDir": "./src",
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
// Environment Settings
|
|
9
|
+
// See also https://aka.ms/tsconfig/module
|
|
10
|
+
"module": "nodenext",
|
|
11
|
+
"target": "esnext",
|
|
12
|
+
"types": [
|
|
13
|
+
"node"
|
|
14
|
+
],
|
|
15
|
+
// For nodejs:
|
|
16
|
+
// "lib": ["esnext"],
|
|
17
|
+
// "types": ["node"],
|
|
18
|
+
// and npm install -D @types/node
|
|
19
|
+
// Other Outputs
|
|
20
|
+
"sourceMap": true,
|
|
21
|
+
"declaration": true,
|
|
22
|
+
"declarationMap": true,
|
|
23
|
+
// Stricter Typechecking Options
|
|
24
|
+
// "noUncheckedIndexedAccess": true,
|
|
25
|
+
// "exactOptionalPropertyTypes": true,
|
|
26
|
+
// Style Options
|
|
27
|
+
"noImplicitReturns": true,
|
|
28
|
+
// "noImplicitOverride": true,
|
|
29
|
+
// "noUnusedLocals": true,
|
|
30
|
+
// "noUnusedParameters": true,
|
|
31
|
+
// "noFallthroughCasesInSwitch": true,
|
|
32
|
+
// "noPropertyAccessFromIndexSignature": true,
|
|
33
|
+
// Recommended Options
|
|
34
|
+
"strict": true,
|
|
35
|
+
"jsx": "react-jsx",
|
|
36
|
+
// "verbatimModuleSyntax": true,
|
|
37
|
+
"isolatedModules": true,
|
|
38
|
+
"noUncheckedSideEffectImports": true,
|
|
39
|
+
"moduleDetection": "force",
|
|
40
|
+
"skipLibCheck": true,
|
|
41
|
+
// Extended options not in generated tsconfig.json
|
|
42
|
+
"newLine": "lf",
|
|
43
|
+
"forceConsistentCasingInFileNames": true,
|
|
44
|
+
"alwaysStrict": true,
|
|
45
|
+
"noImplicitThis": true,
|
|
46
|
+
"strictBindCallApply": true,
|
|
47
|
+
"strictFunctionTypes": true,
|
|
48
|
+
"noErrorTruncation": true,
|
|
49
|
+
},
|
|
50
|
+
"include": [
|
|
51
|
+
"src"
|
|
52
|
+
]
|
|
55
53
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"HtmlEscape.d.ts","sourceRoot":"","sources":["../../src/encodings/HtmlEscape.ts"],"names":[],"mappings":"AACA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,UAKtC"}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export function escapeHtml(text) {
|
|
2
|
-
return text.replaceAll(/[&<>"']/g, (char) => htmlEscapeLookup[char]);
|
|
3
|
-
}
|
|
4
|
-
const htmlEscapeLookup = {
|
|
5
|
-
'&': '&',
|
|
6
|
-
'<': '<',
|
|
7
|
-
'>': '>',
|
|
8
|
-
"'": ''',
|
|
9
|
-
'"': '"'
|
|
10
|
-
};
|
|
11
|
-
// This HTML unescape method is not fully standard compliant
|
|
12
|
-
// I implemented a fully compliant one in the package html-escape-compliant
|
|
13
|
-
function unescapeHtml(text) {
|
|
14
|
-
return text.replaceAll(/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160);/g, (str) => htmlUnescapeLookup[str]);
|
|
15
|
-
}
|
|
16
|
-
const htmlUnescapeLookup = {
|
|
17
|
-
'&': '&',
|
|
18
|
-
'&': '&',
|
|
19
|
-
'<': '<',
|
|
20
|
-
'<': '<',
|
|
21
|
-
'>': '>',
|
|
22
|
-
'>': '>',
|
|
23
|
-
''': "'",
|
|
24
|
-
''': "'",
|
|
25
|
-
'"': '"',
|
|
26
|
-
'"': '"',
|
|
27
|
-
' ': '\u00A0',
|
|
28
|
-
' ': '\u00A0'
|
|
29
|
-
};
|
|
30
|
-
//# sourceMappingURL=HtmlEscape.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"HtmlEscape.js","sourceRoot":"","sources":["../../src/encodings/HtmlEscape.ts"],"names":[],"mappings":"AACA,MAAM,UAAU,UAAU,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,UAAU,CACrB,UAAU,EACV,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAChC,CAAA;AACF,CAAC;AAED,MAAM,gBAAgB,GAA2B;IAChD,GAAG,EAAE,OAAO;IACZ,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,OAAO;IACZ,GAAG,EAAE,QAAQ;CACb,CAAA;AAED,4DAA4D;AAC5D,2EAA2E;AAC3E,SAAS,YAAY,CAAC,IAAY;IACjC,OAAO,IAAI,CAAC,UAAU,CACrB,0DAA0D,EAC1D,CAAC,GAAG,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAChC,CAAA;AACF,CAAC;AAED,MAAM,kBAAkB,GAA2B;IAClD,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,GAAG;IACZ,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,GAAG;IACZ,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE,GAAG;IACb,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE,GAAG;IACb,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,QAAQ;CAClB,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LEB128.d.ts","sourceRoot":"","sources":["../../src/encodings/LEB128.ts"],"names":[],"mappings":""}
|
package/dist/encodings/LEB128.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LEB128.js","sourceRoot":"","sources":["../../src/encodings/LEB128.ts"],"names":[],"mappings":""}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export declare class StringBuilder {
|
|
2
|
-
private outputBuffer;
|
|
3
|
-
constructor(initialCapacity?: number);
|
|
4
|
-
appendCharCode(charCode: number): void;
|
|
5
|
-
appendCharCodes(...charCodes: number[]): void;
|
|
6
|
-
appendCharCodeArray(charCodes: ArrayLike<number>): void;
|
|
7
|
-
appendString(str: string): void;
|
|
8
|
-
appendCodePoint(codePoint: number): void;
|
|
9
|
-
toString(): string;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=StringBuilder.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"StringBuilder.d.ts","sourceRoot":"","sources":["../../src/utilities/StringBuilder.ts"],"names":[],"mappings":"AAGA,qBAAa,aAAa;IACzB,OAAO,CAAC,YAAY,CAAoB;IAExC,YAAY,eAAe,SAAI,EAE9B;IAED,cAAc,CAAC,QAAQ,EAAE,MAAM,QAE9B;IAED,eAAe,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,QAErC;IAED,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,QAE/C;IAED,YAAY,CAAC,GAAG,EAAE,MAAM,QAMvB;IAED,eAAe,CAAC,SAAS,EAAE,MAAM,QAShC;IAED,QAAQ,WAEP;CACD"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { createDynamicUint16Array } from '../data-structures/DynamicTypedArray.js';
|
|
2
|
-
import { decodeUtf16 } from '../encodings/Utf16.js';
|
|
3
|
-
export class StringBuilder {
|
|
4
|
-
outputBuffer;
|
|
5
|
-
constructor(initialCapacity = 8) {
|
|
6
|
-
this.outputBuffer = createDynamicUint16Array(initialCapacity);
|
|
7
|
-
}
|
|
8
|
-
appendCharCode(charCode) {
|
|
9
|
-
this.outputBuffer.add(charCode);
|
|
10
|
-
}
|
|
11
|
-
appendCharCodes(...charCodes) {
|
|
12
|
-
this.outputBuffer.addArray(charCodes);
|
|
13
|
-
}
|
|
14
|
-
appendCharCodeArray(charCodes) {
|
|
15
|
-
this.outputBuffer.addArray(charCodes);
|
|
16
|
-
}
|
|
17
|
-
appendString(str) {
|
|
18
|
-
const length = str.length;
|
|
19
|
-
for (let i = 0; i < length; i++) {
|
|
20
|
-
this.appendCharCode(str.charCodeAt(i));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
appendCodePoint(codePoint) {
|
|
24
|
-
if (codePoint <= 0xffff) {
|
|
25
|
-
this.appendCharCode(codePoint);
|
|
26
|
-
}
|
|
27
|
-
else if (codePoint <= 0x10ffff) {
|
|
28
|
-
this.appendCharCode(0xd800 + ((codePoint - 0x10000) >>> 10));
|
|
29
|
-
this.appendCharCode(0xdc00 + ((codePoint - 0x10000) & 1023));
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
throw new Error(`appendCodePoint: A code point of ${codePoint} cannot be encoded in UTF-16`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
toString() {
|
|
36
|
-
return decodeUtf16(this.outputBuffer.toTypedArray());
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
//# sourceMappingURL=StringBuilder.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"StringBuilder.js","sourceRoot":"","sources":["../../src/utilities/StringBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,wBAAwB,EAAE,MAAM,yCAAyC,CAAA;AACtG,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAEnD,MAAM,OAAO,aAAa;IACjB,YAAY,CAAoB;IAExC,YAAY,eAAe,GAAG,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,wBAAwB,CAAC,eAAe,CAAC,CAAA;IAC9D,CAAC;IAED,cAAc,CAAC,QAAgB;QAC9B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAChC,CAAC;IAED,eAAe,CAAC,GAAG,SAAmB;QACrC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;IACtC,CAAC;IAED,mBAAmB,CAAC,SAA4B;QAC/C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;IACtC,CAAC;IAED,YAAY,CAAC,GAAW;QACvB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAA;QAEzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACjC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;QACvC,CAAC;IACF,CAAC;IAED,eAAe,CAAC,SAAiB;QAChC,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAA;QAC/B,CAAC;aAAM,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;YAClC,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,SAAS,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YAC5D,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;QAC7D,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,oCAAoC,SAAS,8BAA8B,CAAC,CAAA;QAC7F,CAAC;IACF,CAAC;IAED,QAAQ;QACP,OAAO,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,CAAA;IACrD,CAAC;CACD"}
|