88 lines
2.4 KiB
JavaScript
88 lines
2.4 KiB
JavaScript
import { createHash } from 'node:crypto'
|
||
import { createWriteStream } from 'node:fs'
|
||
import { mkdir, readFile, stat, writeFile } from 'node:fs/promises'
|
||
import path from 'node:path'
|
||
|
||
export async function readJson(filePath) {
|
||
return JSON.parse(await readFile(filePath, 'utf8'))
|
||
}
|
||
|
||
export async function writeJson(filePath, value) {
|
||
await mkdir(path.dirname(filePath), { recursive: true })
|
||
await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8')
|
||
}
|
||
|
||
export async function exists(filePath) {
|
||
try {
|
||
await stat(filePath)
|
||
return true
|
||
} catch {
|
||
return false
|
||
}
|
||
}
|
||
|
||
export async function downloadFile(url, filePath) {
|
||
await mkdir(path.dirname(filePath), { recursive: true })
|
||
const response = await fetch(url)
|
||
if (!response.ok || !response.body) {
|
||
throw new Error(`Download failed ${response.status} ${response.statusText}: ${url}`)
|
||
}
|
||
|
||
const output = createWriteStream(filePath)
|
||
await new Promise((resolve, reject) => {
|
||
response.body.pipeTo(
|
||
new WritableStream({
|
||
write(chunk) {
|
||
output.write(Buffer.from(chunk))
|
||
},
|
||
close() {
|
||
output.end(resolve)
|
||
},
|
||
abort(reason) {
|
||
output.destroy(reason)
|
||
reject(reason)
|
||
},
|
||
}),
|
||
).catch(reject)
|
||
})
|
||
}
|
||
|
||
export async function sha256File(filePath) {
|
||
const data = await readFile(filePath)
|
||
return createHash('sha256').update(data).digest('hex')
|
||
}
|
||
|
||
export function normalizeStrong(value) {
|
||
const match = /^([GH])0*([0-9]+)$/i.exec(value)
|
||
return match ? `${match[1].toUpperCase()}${Number(match[2])}` : value.toUpperCase()
|
||
}
|
||
|
||
export function cleanUsfmText(input) {
|
||
return input
|
||
.replace(/…/g, '...')
|
||
.replace(/…/g, '...')
|
||
.replace(/’/g, "'")
|
||
.replace(/’/g, "'")
|
||
.replace(/’/g, "'")
|
||
.replace(/‘/g, "'")
|
||
.replace(/“/g, '"')
|
||
.replace(/â€Â/g, '"')
|
||
.replace(/“/g, '"')
|
||
.replace(/â€/g, '"')
|
||
.replace(/“/g, '"')
|
||
.replace(/”/g, '"')
|
||
.replace(/—/g, '-')
|
||
.replace(/–/g, '-')
|
||
.replace(/—/g, '-')
|
||
.replace(/–/g, '-')
|
||
.replace(/\\f [\s\S]*?\\f\*/g, '')
|
||
.replace(/\\x [\s\S]*?\\x\*/g, '')
|
||
.replace(/\\add\s+([^\\]+)\\add\*/g, '$1')
|
||
.replace(/\\nd\s+([\s\S]*?)\\nd\*/g, '$1')
|
||
.replace(/\\[+\w]+\*/g, '')
|
||
.replace(/\\[a-z0-9+]+(?:\s+)?/gi, '')
|
||
.replace(/\s+/g, ' ')
|
||
.replace(/\s+([,.;:?!])/g, '$1')
|
||
.trim()
|
||
}
|