@oh-my-pi/pi-utils 15.9.0 → 15.9.1
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/package.json +2 -2
- package/src/tab-spacing.ts +34 -4
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-utils",
|
|
4
|
-
"version": "15.9.
|
|
4
|
+
"version": "15.9.1",
|
|
5
5
|
"description": "Shared utilities for pi packages",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"fmt": "biome format --write ."
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@oh-my-pi/pi-natives": "15.9.
|
|
34
|
+
"@oh-my-pi/pi-natives": "15.9.1",
|
|
35
35
|
"beautiful-mermaid": "^1.1.3",
|
|
36
36
|
"handlebars": "^4.7.9",
|
|
37
37
|
"winston": "^3.19.0",
|
package/src/tab-spacing.ts
CHANGED
|
@@ -4,17 +4,25 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
6
|
import * as path from "node:path";
|
|
7
|
-
import {
|
|
7
|
+
import { isFsError } from "./fs-error";
|
|
8
8
|
|
|
9
9
|
export const MIN_TAB_WIDTH = 1;
|
|
10
10
|
export const MAX_TAB_WIDTH = 16;
|
|
11
11
|
export const DEFAULT_TAB_WIDTH = 3;
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Per-component path length cap on common filesystems (`NAME_MAX = 255` on
|
|
15
|
+
* Linux ext4 / macOS APFS / Windows NTFS). Paths with components longer than
|
|
16
|
+
* this cannot be opened at all, so editorconfig discovery short-circuits to
|
|
17
|
+
* the default instead of running into `ENAMETOOLONG` from `readFileSync`.
|
|
18
|
+
*/
|
|
19
|
+
const NAME_MAX_BYTES = 255;
|
|
20
|
+
|
|
13
21
|
const EDITORCONFIG_NAME = ".editorconfig";
|
|
14
22
|
|
|
15
23
|
let defaultTabWidth = DEFAULT_TAB_WIDTH;
|
|
16
24
|
|
|
17
|
-
const editorConfigCache = new Map<string, ParsedEditorConfig>();
|
|
25
|
+
const editorConfigCache = new Map<string, ParsedEditorConfig | null>();
|
|
18
26
|
const editorConfigChainCache = new Map<string, ChainEntry[]>();
|
|
19
27
|
const indentationCache = new Map<string, number>();
|
|
20
28
|
|
|
@@ -145,14 +153,18 @@ function parseCachedEditorConfig(configPath: string): ParsedEditorConfig | undef
|
|
|
145
153
|
const key = path.resolve(configPath);
|
|
146
154
|
const hit = editorConfigCache.get(key);
|
|
147
155
|
if (hit !== undefined) {
|
|
148
|
-
return hit;
|
|
156
|
+
return hit ?? undefined;
|
|
149
157
|
}
|
|
150
158
|
|
|
151
159
|
let content: string;
|
|
152
160
|
try {
|
|
153
161
|
content = fs.readFileSync(key, "utf8");
|
|
154
162
|
} catch (err) {
|
|
155
|
-
|
|
163
|
+
// editorconfig discovery is best-effort. Any filesystem error
|
|
164
|
+
// (`ENOENT`, `ENAMETOOLONG`, `ENOTDIR`, `EACCES`, `ELOOP`, `EINVAL`,
|
|
165
|
+
// …) means "no usable config at this path" — never a fatal condition
|
|
166
|
+
// for callers like the edit renderer that hand us arbitrary strings.
|
|
167
|
+
if (isFsError(err)) return undefined;
|
|
156
168
|
throw err;
|
|
157
169
|
}
|
|
158
170
|
const parsed = parseEditorConfigFile(content);
|
|
@@ -279,6 +291,15 @@ function resolveEditorConfigTabWidth(match: EditorConfigMatch | undefined, fallb
|
|
|
279
291
|
return undefined;
|
|
280
292
|
}
|
|
281
293
|
|
|
294
|
+
function hasOverlongPathComponent(filePath: string): boolean {
|
|
295
|
+
for (const part of filePath.split(/[\\/]/)) {
|
|
296
|
+
if (part.length > 0 && Buffer.byteLength(part) > NAME_MAX_BYTES) {
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
|
|
282
303
|
export function getDefaultTabWidth(): number {
|
|
283
304
|
return defaultTabWidth;
|
|
284
305
|
}
|
|
@@ -298,6 +319,15 @@ export function getIndentation(file?: string | null, projectDir?: string | null)
|
|
|
298
319
|
|
|
299
320
|
const cwd = projectDir ?? process.cwd();
|
|
300
321
|
const absoluteFile = resolveFilePath(cwd, file);
|
|
322
|
+
|
|
323
|
+
// Renderers can hand us arbitrary strings (e.g. a malformed edit tool
|
|
324
|
+
// call whose `file_path` is gibberish). Reject paths whose normalized
|
|
325
|
+
// absolute form still has any component longer than `NAME_MAX_BYTES` —
|
|
326
|
+
// the editorconfig chain would only trip `ENAMETOOLONG` from
|
|
327
|
+
// `readFileSync` and escape.
|
|
328
|
+
if (hasOverlongPathComponent(absoluteFile)) {
|
|
329
|
+
return fallback;
|
|
330
|
+
}
|
|
301
331
|
const absKey = absoluteFile;
|
|
302
332
|
const cached = indentationCache.get(absKey);
|
|
303
333
|
if (cached !== undefined) {
|