fix: faulty multiline comments
Massimo Melina committed
Mar 28, 2024 at 21:06 UTC
72ada4b74eb3895a155580908532f72296cf8652
1 file changed
+25
-14
src/comments.ts
+25
-14
@@ -2,7 +2,7 @@ import { defineConfig } from './config'
2
import { dirname, join } from 'path'
3
import { basename } from './cross'
4
import { parseFile, parseFileCache } from './util-files'
5
-import { writeFile } from 'fs/promises'
5
+import { createWriteStream } from 'fs'
6
import { singleWorkerFromBatchWorker } from './misc'
7
import _ from 'lodash'
8
import iconv from 'iconv-lite'
@@ -28,11 +28,16 @@ export const setCommentFor = singleWorkerFromBatchWorker(async (jobs: [path: str
28
comments.set(file, comment)
29
}
30
// encode comments in descript.ion format
31
- let txt = ''
32
- comments.forEach((c, f) =>
33
- txt += (f.includes(' ') ? `"${f}"` : f) + ' ' + (c.includes('\n') ? c.replaceAll('\n', '\\n') + MULTILINE_SUFFIX : c) + '\n')
34
- const buffer = iconv.encode(txt, descriptIonEncoding.get())
35
- await writeFile(join(folder, DESCRIPT_ION), buffer)
31
+ const ws = createWriteStream(join(folder, DESCRIPT_ION))
32
+ comments.forEach((comment, filename) => {
33
+ const multiline = comment.includes('\n')
34
+ const line = (filename.includes(' ') ? `"${filename}"` : filename)
35
+ + ' ' + (multiline ? comment.replaceAll('\n', '\\n') : comment)
36
+ ws.write( iconv.encode(line, descriptIonEncoding.get()) )
37
+ if (multiline)
38
+ ws.write(MULTILINE_SUFFIX, 'binary')
39
+ ws.write('\n')
40
+ })
41
}))
42
})
43
@@ -40,19 +45,25 @@ export function areCommentsEnabled() {
45
return descriptIon.get()
46
}
47
43
-const MULTILINE_SUFFIX = '\x04\xc2'
48
+const MULTILINE_SUFFIX = Buffer.from([4, 0xC2])
49
function readDescription(path: string) {
45
- return parseFile(join(path, DESCRIPT_ION), raw =>
46
- // decoding could also be done with native TextDecoder.decode, but we need iconv for the encoding anyway
47
- new Map(iconv.decode(raw, descriptIonEncoding.get()).split('\n').map(line => {
50
+ // decoding could also be done with native TextDecoder.decode, but we need iconv for the encoding anyway
51
+ return parseFile(join(path, DESCRIPT_ION), raw => {
52
+ // for simplicity we "remove" the sequence MULTILINE_SUFFIX before iconv.decode messes it up
53
+ for (let i=0; i<raw.length; i++)
54
+ if (raw[i] === MULTILINE_SUFFIX[0] && raw[i+1] === MULTILINE_SUFFIX[1] && [undefined,13,10].includes(raw[i+2]))
55
+ raw[i] = raw[i+1] = 10
56
+ const decoded = iconv.decode(raw, descriptIonEncoding.get())
57
+ const ret = new Map(decoded.split('\n').map(line => {
58
const quoted = line[0] === '"' ? 1 : 0
59
const i = quoted ? line.indexOf('"', 2) + 1 : line.indexOf(' ')
60
const fn = line.slice(quoted, i - quoted)
51
- let comment = line.slice(i + 1)
52
- if (comment.endsWith(MULTILINE_SUFFIX))
53
- comment = comment.slice(0, -2).replaceAll('\\n', '\n')
61
+ const comment = line.slice(i + 1).replaceAll('\\n', '\n')
62
return [fn, comment]
55
- })))
63
+ }))
64
+ ret.delete('')
65
+ return ret
66
+ })
67
}
68
69
descriptIonEncoding.sub(() => { // invalidate cache at encoding change