miniread 1.82.0 → 1.84.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.
Files changed (23) hide show
  1. package/dist/core/stable-naming.d.ts +4 -0
  2. package/dist/core/stable-naming.js +1 -0
  3. package/dist/transforms/_generated/manifest.js +10 -0
  4. package/dist/transforms/_generated/registry.js +4 -0
  5. package/dist/transforms/recommended-transform-order.d.ts +1 -1
  6. package/dist/transforms/recommended-transform-order.js +2 -0
  7. package/dist/transforms/rename-add-event-listener-parameters/has-event-handler-usage.d.ts +2 -0
  8. package/dist/transforms/rename-add-event-listener-parameters/has-event-handler-usage.js +42 -0
  9. package/dist/transforms/rename-add-event-listener-parameters/has-event-name-comparison.d.ts +2 -0
  10. package/dist/transforms/rename-add-event-listener-parameters/has-event-name-comparison.js +21 -0
  11. package/dist/transforms/rename-add-event-listener-parameters/is-add-event-listener-key.d.ts +3 -0
  12. package/dist/transforms/rename-add-event-listener-parameters/is-add-event-listener-key.js +8 -0
  13. package/dist/transforms/rename-add-event-listener-parameters/manifest.json +12 -0
  14. package/dist/transforms/rename-add-event-listener-parameters/rename-add-event-listener-parameters-transform.d.ts +2 -0
  15. package/dist/transforms/rename-add-event-listener-parameters/rename-add-event-listener-parameters-transform.js +91 -0
  16. package/dist/transforms/rename-platform-win32-flags/apply-hash-stable-win32-renames.d.ts +8 -0
  17. package/dist/transforms/rename-platform-win32-flags/apply-hash-stable-win32-renames.js +37 -0
  18. package/dist/transforms/rename-platform-win32-flags/is-safe-process-binding.d.ts +3 -0
  19. package/dist/transforms/rename-platform-win32-flags/is-safe-process-binding.js +48 -0
  20. package/dist/transforms/rename-platform-win32-flags/manifest.json +12 -0
  21. package/dist/transforms/rename-platform-win32-flags/rename-platform-win32-flags-transform.d.ts +2 -0
  22. package/dist/transforms/rename-platform-win32-flags/rename-platform-win32-flags-transform.js +112 -0
  23. package/package.json +1 -1
@@ -41,6 +41,10 @@ type RenameEntry = {
41
41
  /** Desired semantic base name (e.g., "timeoutId", "error") */
42
42
  baseName: string;
43
43
  };
44
+ export declare const findAvailableStableRenameName: (scope: Scope, binding: Binding | undefined, baseName: string, startIndex: number, currentName: string) => {
45
+ name: string;
46
+ nextIndex: number;
47
+ };
44
48
  /**
45
49
  * Collects rename operations and applies them with automatic stability logic.
46
50
  *
@@ -154,6 +154,7 @@ const findAvailableName = (scope, binding, baseName, startIndex, canBeStable, cu
154
154
  return { name: candidateReadable, nextIndex: index + 1 };
155
155
  }
156
156
  };
157
+ export const findAvailableStableRenameName = (scope, binding, baseName, startIndex, currentName) => findAvailableName(scope, binding, baseName, startIndex, true, currentName);
157
158
  /**
158
159
  * Collects rename operations and applies them with automatic stability logic.
159
160
  *
@@ -38,6 +38,10 @@ const manifestData = {
38
38
  notes: "Added manually; improves readability by reducing nesting.",
39
39
  evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-01-25T23:01:41.815Z", "changedLines": 5208, "durationSeconds": 58.302647375, "stableNames": 1357 } },
40
40
  },
41
+ "rename-add-event-listener-parameters": {
42
+ recommended: true,
43
+ evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-06T17:38:36.844Z", "changedLines": 8, "durationSeconds": 179.627881234, "stableNames": 1359 } },
44
+ },
41
45
  "rename-arguments-length-flags": {
42
46
  recommended: true,
43
47
  notes: "Measured with baseline none: 0.00%. Added to recommended for readability.",
@@ -232,6 +236,10 @@ const manifestData = {
232
236
  notes: "Extends v1 to also handle this.property = param assignments.",
233
237
  evaluations: { "legacy:evaluation": { "evaluatedAt": "2026-01-25T20:07:10.063Z", "changedLines": 20493, "durationSeconds": 0, "stableNames": 0, "diffSizePercent": 99.99244056393393 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 99.99244056393393, "evaluatedAt": "2026-01-25T23:24:32.608Z", "changedLines": 20493, "durationSeconds": 56.743425875, "stableNames": 1357 } },
234
238
  },
239
+ "rename-platform-win32-flags": {
240
+ recommended: true,
241
+ evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 99.99623032701913, "evaluatedAt": "2026-02-06T14:58:00.533Z", "changedLines": 42, "durationSeconds": 224.696743585, "stableNames": 1358 } },
242
+ },
235
243
  "rename-process-stdout-handlers": {
236
244
  recommended: false,
237
245
  notes: "Measured with baseline none: -0.0019%. Kept out of recommended due to slight negative diff impact, but useful for readability in stdout hook handlers.",
@@ -462,6 +470,7 @@ export const recommendedTransformIds = [
462
470
  "rename-charcode-variables-v2",
463
471
  "rename-client-aliases",
464
472
  "rename-comparison-flags",
473
+ "rename-platform-win32-flags",
465
474
  "rename-date-now-start-times",
466
475
  "rename-default-options-parameters-v2",
467
476
  "rename-deferred-resolve-parameters",
@@ -475,6 +484,7 @@ export const recommendedTransformIds = [
475
484
  "rename-error-first-callback-parameters-v2",
476
485
  "rename-error-variables",
477
486
  "rename-event-parameters",
487
+ "rename-add-event-listener-parameters",
478
488
  "rename-http-server-parameters",
479
489
  "rename-fs-sync-variables",
480
490
  "rename-http-method-parameters",
@@ -7,6 +7,7 @@ import { expandSpecialNumberLiteralsTransform } from "../expand-special-number-l
7
7
  import { expandTypeofUndefinedComparisonsTransform } from "../expand-typeof-undefined-comparisons/expand-typeof-undefined-comparisons-transform.js";
8
8
  import { expandUndefinedLiteralsTransform } from "../expand-undefined-literals/expand-undefined-literals-transform.js";
9
9
  import { removeRedundantElseTransform } from "../remove-redundant-else/remove-redundant-else-transform.js";
10
+ import { renameAddEventListenerParametersTransform } from "../rename-add-event-listener-parameters/rename-add-event-listener-parameters-transform.js";
10
11
  import { renameArgumentsLengthFlagsTransform } from "../rename-arguments-length-flags/rename-arguments-length-flags-transform.js";
11
12
  import { renameAsapWrappersTransform } from "../rename-asap-wrappers/rename-asap-wrappers-transform.js";
12
13
  import { renameAwaiterHelperFunctionsTransform } from "../rename-awaiter-helper-functions/rename-awaiter-helper-functions-transform.js";
@@ -47,6 +48,7 @@ import { renameObjectKeysReducerParametersTransform } from "../rename-object-key
47
48
  import { renameObjectKeysVariablesTransform } from "../rename-object-keys-variables/rename-object-keys-variables-transform.js";
48
49
  import { renameParametersToMatchPropertiesTransform } from "../rename-parameters-to-match-properties/rename-parameters-to-match-properties-transform.js";
49
50
  import { renameParametersToMatchPropertiesV2Transform } from "../rename-parameters-to-match-properties-v2/rename-parameters-to-match-properties-v2-transform.js";
51
+ import { renamePlatformWin32FlagsTransform } from "../rename-platform-win32-flags/rename-platform-win32-flags-transform.js";
50
52
  import { renameProcessStdoutHandlersTransform } from "../rename-process-stdout-handlers/rename-process-stdout-handlers-transform.js";
51
53
  import { renamePromiseCatchParametersTransform } from "../rename-promise-catch-parameters/rename-promise-catch-parameters-transform.js";
52
54
  import { renamePromiseExecutorParametersTransform } from "../rename-promise-executor-parameters/rename-promise-executor-parameters-transform.js";
@@ -95,6 +97,7 @@ export const transformRegistry = {
95
97
  [expandTypeofUndefinedComparisonsTransform.id]: expandTypeofUndefinedComparisonsTransform,
96
98
  [expandUndefinedLiteralsTransform.id]: expandUndefinedLiteralsTransform,
97
99
  [removeRedundantElseTransform.id]: removeRedundantElseTransform,
100
+ [renameAddEventListenerParametersTransform.id]: renameAddEventListenerParametersTransform,
98
101
  [renameArgumentsLengthFlagsTransform.id]: renameArgumentsLengthFlagsTransform,
99
102
  [renameAsapWrappersTransform.id]: renameAsapWrappersTransform,
100
103
  [renameAwaiterHelperFunctionsTransform.id]: renameAwaiterHelperFunctionsTransform,
@@ -135,6 +138,7 @@ export const transformRegistry = {
135
138
  [renameObjectKeysVariablesTransform.id]: renameObjectKeysVariablesTransform,
136
139
  [renameParametersToMatchPropertiesTransform.id]: renameParametersToMatchPropertiesTransform,
137
140
  [renameParametersToMatchPropertiesV2Transform.id]: renameParametersToMatchPropertiesV2Transform,
141
+ [renamePlatformWin32FlagsTransform.id]: renamePlatformWin32FlagsTransform,
138
142
  [renameProcessStdoutHandlersTransform.id]: renameProcessStdoutHandlersTransform,
139
143
  [renamePromiseCatchParametersTransform.id]: renamePromiseCatchParametersTransform,
140
144
  [renamePromiseExecutorParametersTransform.id]: renamePromiseExecutorParametersTransform,
@@ -4,4 +4,4 @@
4
4
  * This lets us tune transform interactions intentionally instead of relying on
5
5
  * alphabetical ID sorting.
6
6
  */
7
- export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "stabilize-deferred-top-level-bindings", "stabilize-deferred-stable-rhs", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-comparison-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-deferred-resolve-parameters", "rename-deferred-resolve-parameters-v2", "rename-destructured-aliases", "rename-rest-parameters", "rename-rest-pop-callbacks", "rename-execfile-arguments", "rename-file-reader-variables", "rename-error-first-callback-parameters", "rename-error-first-callback-parameters-v2", "rename-error-variables", "rename-event-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-indexeddb-request-variables", "rename-loop-index-variables-v3", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-object-keys-reducer-parameters", "rename-parameters-to-match-properties-v2", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-file-extension-variables", "rename-string-split-variables", "rename-this-aliases", "rename-timeout-promises", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "rename-zod-check-parameters", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
7
+ export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "stabilize-deferred-top-level-bindings", "stabilize-deferred-stable-rhs", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-comparison-flags", "rename-platform-win32-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-deferred-resolve-parameters", "rename-deferred-resolve-parameters-v2", "rename-destructured-aliases", "rename-rest-parameters", "rename-rest-pop-callbacks", "rename-execfile-arguments", "rename-file-reader-variables", "rename-error-first-callback-parameters", "rename-error-first-callback-parameters-v2", "rename-error-variables", "rename-event-parameters", "rename-add-event-listener-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-indexeddb-request-variables", "rename-loop-index-variables-v3", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-object-keys-reducer-parameters", "rename-parameters-to-match-properties-v2", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-file-extension-variables", "rename-string-split-variables", "rename-this-aliases", "rename-timeout-promises", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "rename-zod-check-parameters", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
@@ -36,6 +36,7 @@ export const recommendedTransformOrder = [
36
36
  "rename-charcode-variables-v2",
37
37
  "rename-client-aliases",
38
38
  "rename-comparison-flags",
39
+ "rename-platform-win32-flags",
39
40
  "rename-date-now-start-times",
40
41
  "rename-default-options-parameters-v2",
41
42
  "rename-deferred-resolve-parameters",
@@ -49,6 +50,7 @@ export const recommendedTransformOrder = [
49
50
  "rename-error-first-callback-parameters-v2",
50
51
  "rename-error-variables",
51
52
  "rename-event-parameters",
53
+ "rename-add-event-listener-parameters",
52
54
  "rename-http-server-parameters",
53
55
  // Runs after stabilize-top-level-bindings: in the recommended preset, top-level `fs` bindings
54
56
  // are already stable-hashed. This transform gives remaining non-stable `fs` helpers stable
@@ -0,0 +1,2 @@
1
+ import type { Binding } from "@babel/traverse";
2
+ export declare const hasEventHandlerUsage: (binding: Binding) => boolean;
@@ -0,0 +1,42 @@
1
+ const isHandleEventAccess = (node) => {
2
+ if (!node.computed && node.property.type === "Identifier") {
3
+ return node.property.name === "handleEvent";
4
+ }
5
+ if (node.computed && node.property.type === "StringLiteral") {
6
+ return node.property.value === "handleEvent";
7
+ }
8
+ return false;
9
+ };
10
+ const isWriteSideHandleEventAccess = (memberPath) => {
11
+ const parent = memberPath.parentPath;
12
+ if (parent.isAssignmentExpression()) {
13
+ return parent.node.left === memberPath.node;
14
+ }
15
+ if (parent.isUpdateExpression()) {
16
+ return parent.node.argument === memberPath.node;
17
+ }
18
+ return false;
19
+ };
20
+ export const hasEventHandlerUsage = (binding) => {
21
+ return binding.referencePaths.some((referencePath) => {
22
+ const parent = referencePath.parentPath;
23
+ if (!parent)
24
+ return false;
25
+ if ((parent.isCallExpression() || parent.isOptionalCallExpression()) &&
26
+ referencePath.key === "callee")
27
+ return true;
28
+ if ((parent.isMemberExpression() || parent.isOptionalMemberExpression()) &&
29
+ referencePath.key === "object") {
30
+ if (isWriteSideHandleEventAccess(parent))
31
+ return false;
32
+ const property = parent.node.property;
33
+ if (property.type !== "Identifier" && property.type !== "StringLiteral")
34
+ return false;
35
+ return isHandleEventAccess({
36
+ property,
37
+ computed: parent.node.computed,
38
+ });
39
+ }
40
+ return false;
41
+ });
42
+ };
@@ -0,0 +1,2 @@
1
+ import type { Binding } from "@babel/traverse";
2
+ export declare const hasEventNameComparison: (binding: Binding) => boolean;
@@ -0,0 +1,21 @@
1
+ export const hasEventNameComparison = (binding) => {
2
+ return binding.referencePaths.some((referencePath) => {
3
+ const parent = referencePath.parentPath;
4
+ if (!parent)
5
+ return false;
6
+ if (parent.isBinaryExpression()) {
7
+ const { left, right, operator } = parent.node;
8
+ if (operator !== "===" && operator !== "==")
9
+ return false;
10
+ if (left === referencePath.node)
11
+ return right.type === "StringLiteral";
12
+ if (right === referencePath.node)
13
+ return left.type === "StringLiteral";
14
+ return false;
15
+ }
16
+ if (parent.isSwitchStatement() && referencePath.key === "discriminant") {
17
+ return parent.node.cases.some((caseClause) => caseClause.test?.type === "StringLiteral");
18
+ }
19
+ return false;
20
+ });
21
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type { ObjectMethod, ObjectProperty } from "@babel/types";
3
+ export declare const isAddEventListenerKey: (path: NodePath<ObjectMethod | ObjectProperty>) => boolean;
@@ -0,0 +1,8 @@
1
+ export const isAddEventListenerKey = (path) => {
2
+ const { key, computed } = path.node;
3
+ if (key.type === "Identifier")
4
+ return !computed && key.name === "addEventListener";
5
+ if (key.type === "StringLiteral")
6
+ return key.value === "addEventListener";
7
+ return false;
8
+ };
@@ -0,0 +1,12 @@
1
+ {
2
+ "recommended": true,
3
+ "evaluations": {
4
+ "claude-code-2.1.10:claude-code-2.1.11": {
5
+ "diffSizePercent": 100,
6
+ "evaluatedAt": "2026-02-06T17:38:36.844Z",
7
+ "changedLines": 8,
8
+ "durationSeconds": 179.627881234,
9
+ "stableNames": 1359
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,2 @@
1
+ import { type Transform } from "../../core/types.js";
2
+ export declare const renameAddEventListenerParametersTransform: Transform;
@@ -0,0 +1,91 @@
1
+ import { createRequire } from "node:module";
2
+ import { RenameGroup, isStableRenamed } from "../../core/stable-naming.js";
3
+ import { getFilesToProcess, } from "../../core/types.js";
4
+ import { hasEventHandlerUsage } from "./has-event-handler-usage.js";
5
+ import { hasEventNameComparison } from "./has-event-name-comparison.js";
6
+ import { isAddEventListenerKey } from "./is-add-event-listener-key.js";
7
+ const require = createRequire(import.meta.url);
8
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
9
+ const traverse = require("@babel/traverse").default;
10
+ const EVENT_NAME_BASE = "eventName";
11
+ const EVENT_HANDLER_BASE = "eventHandler";
12
+ const collectAddEventListenerRename = (path, group) => {
13
+ if (path.node.params.length !== 2)
14
+ return;
15
+ const [eventNameParameter, handlerParameter] = path.node.params;
16
+ if (eventNameParameter?.type !== "Identifier")
17
+ return;
18
+ if (handlerParameter?.type !== "Identifier")
19
+ return;
20
+ const eventName = eventNameParameter.name;
21
+ const handlerName = handlerParameter.name;
22
+ if (eventName === handlerName)
23
+ return;
24
+ const shouldRenameEventName = !isStableRenamed(eventName);
25
+ const shouldRenameHandlerName = !isStableRenamed(handlerName);
26
+ if (!shouldRenameEventName && !shouldRenameHandlerName)
27
+ return;
28
+ const eventBinding = path.scope.getBinding(eventName);
29
+ if (!eventBinding)
30
+ return;
31
+ if (!eventBinding.constant)
32
+ return;
33
+ const handlerBinding = path.scope.getBinding(handlerName);
34
+ if (!handlerBinding)
35
+ return;
36
+ if (!handlerBinding.constant)
37
+ return;
38
+ if (!hasEventNameComparison(eventBinding))
39
+ return;
40
+ if (!hasEventHandlerUsage(handlerBinding))
41
+ return;
42
+ if (shouldRenameEventName) {
43
+ group.add({
44
+ scope: path.scope,
45
+ currentName: eventName,
46
+ baseName: EVENT_NAME_BASE,
47
+ });
48
+ }
49
+ if (shouldRenameHandlerName) {
50
+ group.add({
51
+ scope: path.scope,
52
+ currentName: handlerName,
53
+ baseName: EVENT_HANDLER_BASE,
54
+ });
55
+ }
56
+ };
57
+ export const renameAddEventListenerParametersTransform = {
58
+ id: "rename-add-event-listener-parameters",
59
+ description: "Renames addEventListener parameters to eventName/eventHandler when usage is high-confidence",
60
+ scope: "file",
61
+ parallelizable: true,
62
+ transform(context) {
63
+ let nodesVisited = 0;
64
+ let transformationsApplied = 0;
65
+ for (const fileInfo of getFilesToProcess(context)) {
66
+ const group = new RenameGroup();
67
+ traverse(fileInfo.ast, {
68
+ ObjectMethod(path) {
69
+ nodesVisited++;
70
+ if (!isAddEventListenerKey(path))
71
+ return;
72
+ collectAddEventListenerRename(path, group);
73
+ },
74
+ ObjectProperty(path) {
75
+ nodesVisited++;
76
+ if (!isAddEventListenerKey(path))
77
+ return;
78
+ const valuePath = path.get("value");
79
+ if (valuePath.isFunctionExpression()) {
80
+ collectAddEventListenerRename(valuePath, group);
81
+ }
82
+ else if (valuePath.isArrowFunctionExpression()) {
83
+ collectAddEventListenerRename(valuePath, group);
84
+ }
85
+ },
86
+ });
87
+ transformationsApplied += group.apply();
88
+ }
89
+ return Promise.resolve({ nodesVisited, transformationsApplied });
90
+ },
91
+ };
@@ -0,0 +1,8 @@
1
+ import type { Binding, Scope } from "@babel/traverse";
2
+ export type HashRenameEntry = {
3
+ baseName: string;
4
+ binding: Binding;
5
+ currentName: string;
6
+ scope: Scope;
7
+ };
8
+ export declare const applyHashStableWin32Renames: (hashEntries: HashRenameEntry[]) => number;
@@ -0,0 +1,37 @@
1
+ import { findAvailableStableRenameName } from "../../core/stable-naming.js";
2
+ export const applyHashStableWin32Renames = (hashEntries) => {
3
+ let transformationsApplied = 0;
4
+ const hashScopeGroups = new Map();
5
+ for (const entry of hashEntries) {
6
+ let baseNameMap = hashScopeGroups.get(entry.scope);
7
+ if (!baseNameMap) {
8
+ baseNameMap = new Map();
9
+ hashScopeGroups.set(entry.scope, baseNameMap);
10
+ }
11
+ let baseGroup = baseNameMap.get(entry.baseName);
12
+ if (!baseGroup) {
13
+ baseGroup = [];
14
+ baseNameMap.set(entry.baseName, baseGroup);
15
+ }
16
+ baseGroup.push(entry);
17
+ }
18
+ for (const [scope, baseNameMap] of hashScopeGroups) {
19
+ for (const [baseName, baseGroup] of baseNameMap) {
20
+ const sortedGroup = baseGroup.toSorted((a, b) => a.currentName < b.currentName
21
+ ? -1
22
+ : a.currentName > b.currentName
23
+ ? 1
24
+ : 0);
25
+ let index = 1;
26
+ for (const entry of sortedGroup) {
27
+ const target = findAvailableStableRenameName(scope, entry.binding, baseName, index, entry.currentName);
28
+ index = target.nextIndex;
29
+ if (target.name === entry.currentName)
30
+ continue;
31
+ scope.rename(entry.currentName, target.name);
32
+ transformationsApplied++;
33
+ }
34
+ }
35
+ }
36
+ return transformationsApplied;
37
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type { VariableDeclarator } from "@babel/types";
3
+ export declare const isSafeProcessBinding: (path: NodePath<VariableDeclarator>, identifierName: string) => boolean;
@@ -0,0 +1,48 @@
1
+ import { isNodeRequireInScope } from "../is-require-from-url-module.js";
2
+ const isProcessSpecifier = (value) => value === "process" ||
3
+ value === "node:process" ||
4
+ value === "process/browser" ||
5
+ value === "node:process/browser";
6
+ export const isSafeProcessBinding = (path, identifierName) => {
7
+ const processBinding = path.scope.getBinding(identifierName);
8
+ if (!processBinding)
9
+ return identifierName === "process";
10
+ const bindingPath = processBinding.path;
11
+ if (bindingPath.isImportDefaultSpecifier() ||
12
+ bindingPath.isImportNamespaceSpecifier() ||
13
+ bindingPath.isImportSpecifier()) {
14
+ const parent = bindingPath.parent;
15
+ if (parent.type !== "ImportDeclaration")
16
+ return false;
17
+ if (!isProcessSpecifier(parent.source.value))
18
+ return false;
19
+ if (bindingPath.isImportSpecifier()) {
20
+ const imported = bindingPath.node.imported;
21
+ if (imported.type !== "Identifier")
22
+ return false;
23
+ return imported.name === "default";
24
+ }
25
+ return true;
26
+ }
27
+ if (!bindingPath.isVariableDeclarator())
28
+ return false;
29
+ const init = bindingPath.node.init;
30
+ if (!init)
31
+ return false;
32
+ if (init.type !== "CallExpression")
33
+ return false;
34
+ if (init.callee.type !== "Identifier")
35
+ return false;
36
+ if (init.callee.name !== "require")
37
+ return false;
38
+ if (!isNodeRequireInScope(bindingPath.scope))
39
+ return false;
40
+ if (init.arguments.length !== 1)
41
+ return false;
42
+ const argument0 = init.arguments[0];
43
+ if (!argument0)
44
+ return false;
45
+ if (argument0.type !== "StringLiteral")
46
+ return false;
47
+ return isProcessSpecifier(argument0.value);
48
+ };
@@ -0,0 +1,12 @@
1
+ {
2
+ "recommended": true,
3
+ "evaluations": {
4
+ "claude-code-2.1.10:claude-code-2.1.11": {
5
+ "diffSizePercent": 99.99623032701913,
6
+ "evaluatedAt": "2026-02-06T14:58:00.533Z",
7
+ "changedLines": 42,
8
+ "durationSeconds": 224.696743585,
9
+ "stableNames": 1358
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,2 @@
1
+ import { type Transform } from "../../core/types.js";
2
+ export declare const renamePlatformWin32FlagsTransform: Transform;
@@ -0,0 +1,112 @@
1
+ import { createRequire } from "node:module";
2
+ import { collectExportedNames } from "../../core/collect-exported-names.js";
3
+ import { isHashBasedStableName, RenameGroup, } from "../../core/stable-naming.js";
4
+ import { getFilesToProcess, } from "../../core/types.js";
5
+ import { applyHashStableWin32Renames, } from "./apply-hash-stable-win32-renames.js";
6
+ import { isSafeProcessBinding } from "./is-safe-process-binding.js";
7
+ const require = createRequire(import.meta.url);
8
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
9
+ const traverse = require("@babel/traverse").default;
10
+ const WIN32_LITERAL = "win32";
11
+ const isProcessPlatformExpression = (node) => {
12
+ if (node.type !== "MemberExpression")
13
+ return false;
14
+ if (node.computed)
15
+ return false;
16
+ if (node.object.type !== "Identifier")
17
+ return false;
18
+ // We intentionally keep this structural and verify process identity separately.
19
+ if (node.property.type !== "Identifier")
20
+ return false;
21
+ if (node.property.name !== "platform")
22
+ return false;
23
+ return true;
24
+ };
25
+ const isWin32Literal = (node) => {
26
+ if (node.type !== "StringLiteral")
27
+ return false;
28
+ return node.value === WIN32_LITERAL;
29
+ };
30
+ const getWin32BaseName = (node) => {
31
+ if (node.operator !== "===" && node.operator !== "!==")
32
+ return undefined;
33
+ const matchesLeft = isProcessPlatformExpression(node.left) && isWin32Literal(node.right);
34
+ const matchesRight = isProcessPlatformExpression(node.right) && isWin32Literal(node.left);
35
+ if (!matchesLeft && !matchesRight)
36
+ return undefined;
37
+ return node.operator === "===" ? "isWindows" : "isNotWindows";
38
+ };
39
+ const getPlatformIdentifierName = (node) => {
40
+ if (isProcessPlatformExpression(node.left)) {
41
+ return node.left.object.name;
42
+ }
43
+ if (isProcessPlatformExpression(node.right)) {
44
+ return node.right.object.name;
45
+ }
46
+ return undefined;
47
+ };
48
+ export const renamePlatformWin32FlagsTransform = {
49
+ id: "rename-platform-win32-flags",
50
+ description: 'Renames process.platform ===/!== "win32" variables to readable Windows flag names',
51
+ scope: "file",
52
+ parallelizable: true,
53
+ transform(context) {
54
+ let nodesVisited = 0;
55
+ let transformationsApplied = 0;
56
+ for (const fileInfo of getFilesToProcess(context)) {
57
+ const group = new RenameGroup();
58
+ const hashEntries = [];
59
+ const exportedNames = collectExportedNames(fileInfo.ast.program);
60
+ traverse(fileInfo.ast, {
61
+ VariableDeclarator(path) {
62
+ nodesVisited++;
63
+ const id = path.node.id;
64
+ if (id.type !== "Identifier")
65
+ return;
66
+ const init = path.node.init;
67
+ if (init?.type !== "BinaryExpression")
68
+ return;
69
+ const platformIdentifierName = getPlatformIdentifierName(init);
70
+ if (!platformIdentifierName)
71
+ return;
72
+ if (!isSafeProcessBinding(path, platformIdentifierName))
73
+ return;
74
+ const baseName = getWin32BaseName(init);
75
+ if (!baseName)
76
+ return;
77
+ const binding = path.scope.getBinding(id.name);
78
+ if (!binding)
79
+ return;
80
+ if (!binding.constant)
81
+ return;
82
+ // Intentionally skip single-declaration dead flags to avoid churn;
83
+ // unlike generic comparison-flags, this transform targets a narrow,
84
+ // semantically named pattern where dead-code renames add little value.
85
+ if (binding.referencePaths.length === 0)
86
+ return;
87
+ if (binding.scope.block.type === "Program" &&
88
+ exportedNames.has(id.name)) {
89
+ return;
90
+ }
91
+ if (isHashBasedStableName(id.name)) {
92
+ hashEntries.push({
93
+ baseName,
94
+ binding,
95
+ currentName: id.name,
96
+ scope: path.scope,
97
+ });
98
+ return;
99
+ }
100
+ group.add({
101
+ scope: path.scope,
102
+ currentName: id.name,
103
+ baseName,
104
+ });
105
+ },
106
+ });
107
+ transformationsApplied += applyHashStableWin32Renames(hashEntries);
108
+ transformationsApplied += group.apply();
109
+ }
110
+ return Promise.resolve({ nodesVisited, transformationsApplied });
111
+ },
112
+ };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "miniread",
3
3
  "author": "Łukasz Jerciński",
4
4
  "license": "MIT",
5
- "version": "1.82.0",
5
+ "version": "1.84.0",
6
6
  "description": "Transform minified JavaScript/TypeScript into a more readable form using deterministic AST-based transforms.",
7
7
  "repository": {
8
8
  "type": "git",