endef 2.0.1 → 2.0.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/README.md +7 -7
- package/package.json +1 -1
- package/src/de.js +29 -4
- package/src/en.js +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`endef` 是一个纯 Node.js 的文件旁路转换工具。
|
|
4
4
|
|
|
5
|
-
它适合这样的场景:某些常见源码或文本后缀的文件在系统读取、复制、粘贴、编辑器打开时出现乱码或异常,但通过 Node.js 脚本读取仍然正常。`endef` 会先把目标文件内容写到同目录的 `.endef`
|
|
5
|
+
它适合这样的场景:某些常见源码或文本后缀的文件在系统读取、复制、粘贴、编辑器打开时出现乱码或异常,但通过 Node.js 脚本读取仍然正常。`endef` 会先把目标文件内容写到同目录的 `.endef` 副本里,再删除原文件,并用 `.endef` 副本内容新建原文件。
|
|
6
6
|
|
|
7
7
|
示例:
|
|
8
8
|
|
|
@@ -20,7 +20,7 @@ README.md -> README.md.endef -> README.md
|
|
|
20
20
|
- 默认旁路后缀为 `.endef`
|
|
21
21
|
- `en` 默认转换所有匹配后缀的文件
|
|
22
22
|
- `en --marker` 可以只转换命中 marker 的文件,marker 支持数组配置,也支持 CLI 手动指定多个
|
|
23
|
-
- `de`
|
|
23
|
+
- `de` 会删除原文件,用 `.endef` 临时副本内容新建原文件,再删除 `.endef`
|
|
24
24
|
- `pack` 会把恢复后的目录打包成 `.tar.gz`
|
|
25
25
|
- 不引入生产依赖
|
|
26
26
|
|
|
@@ -66,7 +66,7 @@ endef en /path/to/project --marker E-SafeNet --marker BadText
|
|
|
66
66
|
endef en /path/to/project --marker E-SafeNet,BadText
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
删除原文件,用 `.endef` 副本内容新建原文件,再删除 `.endef`:
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
72
|
endef de /path/to/project
|
|
@@ -107,11 +107,11 @@ endef all [directory] [options]
|
|
|
107
107
|
|
|
108
108
|
`en` 会扫描目标目录,把匹配后缀的文件读取出来,并写成同目录的 `.endef` 副本。
|
|
109
109
|
|
|
110
|
-
`de` 会扫描目标目录中的 `.endef`
|
|
110
|
+
`de` 会扫描目标目录中的 `.endef` 文件,删除对应的原文件,用 `.endef` 副本内容新建原文件,然后删除 `.endef` 副本。这个命令会直接修改文件,请在执行前确认目录和备份策略。
|
|
111
111
|
|
|
112
112
|
`pack` 会按当前配置扫描当前目录,把没有被 `excludeDirs` 排除的文件打包成 `.tar.gz`。如果输出文件已存在,会直接覆盖。
|
|
113
113
|
|
|
114
|
-
`all` 会按顺序执行 `en`、`de`、`pack
|
|
114
|
+
`all` 会按顺序执行 `en`、`de`、`pack`,适合确认配置后一次性完成旁路转换、新建恢复和打包。
|
|
115
115
|
|
|
116
116
|
## 参数
|
|
117
117
|
|
|
@@ -222,13 +222,13 @@ endef en . --marker E-SafeNet --marker BadText
|
|
|
222
222
|
file.ext.endef
|
|
223
223
|
```
|
|
224
224
|
|
|
225
|
-
|
|
225
|
+
删除原文件后,用 `.endef` 内容新建:
|
|
226
226
|
|
|
227
227
|
```text
|
|
228
228
|
file.ext
|
|
229
229
|
```
|
|
230
230
|
|
|
231
|
-
如果 `file.ext`
|
|
231
|
+
如果 `file.ext` 已经存在,会先被删除,然后用 `.endef` 副本内容创建新的 `file.ext`。创建成功后,`file.ext.endef` 会被删除。这个行为符合工具的核心假设:原文件可能已经被异常内容污染,而 `.endef` 是通过旁路读取保存出来的可恢复内容。
|
|
232
232
|
|
|
233
233
|
## 打包策略
|
|
234
234
|
|
package/package.json
CHANGED
package/src/de.js
CHANGED
|
@@ -30,22 +30,28 @@ async function restoreFiles(directory, options = {}) {
|
|
|
30
30
|
})
|
|
31
31
|
|
|
32
32
|
await Promise.all(tasks)
|
|
33
|
-
console.log(
|
|
33
|
+
console.log(
|
|
34
|
+
`Done. restored=${stats.restored}, removed=${stats.removed}, created=${stats.created}, deleted=${stats.deleted}, failed=${stats.failed}`
|
|
35
|
+
)
|
|
34
36
|
return stats
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
async function restoreOne(filePath, config, stats) {
|
|
38
40
|
const targetPath = filePath.slice(0, -config.suffix.length)
|
|
39
41
|
const targetExists = await exists(targetPath)
|
|
42
|
+
const data = await fs.readFile(filePath)
|
|
40
43
|
|
|
41
44
|
await fs.rm(targetPath, { force: true })
|
|
42
|
-
await
|
|
45
|
+
await waitForMissing(targetPath)
|
|
46
|
+
await fs.writeFile(targetPath, data, { flag: 'wx' })
|
|
47
|
+
await fs.rm(filePath, { force: true })
|
|
43
48
|
|
|
44
49
|
stats.restored += 1
|
|
45
50
|
if (targetExists) {
|
|
46
51
|
stats.removed += 1
|
|
47
52
|
}
|
|
48
|
-
stats.
|
|
53
|
+
stats.created += 1
|
|
54
|
+
stats.deleted += 1
|
|
49
55
|
console.log(`Restored: ${filePath} -> ${targetPath}`)
|
|
50
56
|
}
|
|
51
57
|
|
|
@@ -58,11 +64,30 @@ async function exists(filePath) {
|
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
66
|
|
|
67
|
+
async function waitForMissing(filePath) {
|
|
68
|
+
for (let index = 0; index < 20; index += 1) {
|
|
69
|
+
if (!(await exists(filePath))) {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await delay(25)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
throw new Error(`Target still exists after remove: ${filePath}`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function delay(ms) {
|
|
80
|
+
return new Promise(resolve => {
|
|
81
|
+
setTimeout(resolve, ms)
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
61
85
|
function createStats() {
|
|
62
86
|
return {
|
|
63
87
|
restored: 0,
|
|
64
88
|
removed: 0,
|
|
65
|
-
|
|
89
|
+
created: 0,
|
|
90
|
+
deleted: 0,
|
|
66
91
|
failed: 0
|
|
67
92
|
}
|
|
68
93
|
}
|
package/src/en.js
CHANGED
|
@@ -27,14 +27,14 @@ async function processFiles(directory, options = {}) {
|
|
|
27
27
|
tasks.push(
|
|
28
28
|
limit(async () => {
|
|
29
29
|
const outputPath = `${filePath}${config.suffix}`
|
|
30
|
-
const data = await fs.readFile(filePath
|
|
30
|
+
const data = await fs.readFile(filePath)
|
|
31
31
|
|
|
32
32
|
if (config.markerFilter && !matchesAnyMarker(data, config.markers)) {
|
|
33
33
|
stats.skipped += 1
|
|
34
34
|
return
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
await fs.writeFile(outputPath, data
|
|
37
|
+
await fs.writeFile(outputPath, data)
|
|
38
38
|
console.log(`Written: ${outputPath}`)
|
|
39
39
|
stats.written += 1
|
|
40
40
|
}).catch(error => {
|