miniread 1.35.0 → 1.36.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.
@@ -0,0 +1,2 @@
1
+ import type { Program } from "@babel/types";
2
+ export declare const collectExportedNames: (program: Program) => Set<string>;
@@ -0,0 +1,68 @@
1
+ import { isArrayPattern, isAssignmentPattern, isClassDeclaration, isExportNamedDeclaration, isExportSpecifier, isFunctionDeclaration, isIdentifier, isObjectPattern, isObjectProperty, isRestElement, isVariableDeclaration, } from "@babel/types";
2
+ const addBindingNamesFromNode = (node, out) => {
3
+ const babelNode = node;
4
+ if (!babelNode)
5
+ return;
6
+ if (babelNode.type === "VoidPattern")
7
+ return;
8
+ if (isIdentifier(babelNode)) {
9
+ out.add(babelNode.name);
10
+ return;
11
+ }
12
+ if (isObjectPattern(babelNode)) {
13
+ for (const property of babelNode.properties) {
14
+ if (isRestElement(property)) {
15
+ addBindingNamesFromNode(property.argument, out);
16
+ continue;
17
+ }
18
+ if (!isObjectProperty(property))
19
+ continue;
20
+ addBindingNamesFromNode(property.value, out);
21
+ }
22
+ return;
23
+ }
24
+ if (isArrayPattern(babelNode)) {
25
+ for (const element of babelNode.elements) {
26
+ addBindingNamesFromNode(element, out);
27
+ }
28
+ return;
29
+ }
30
+ if (isRestElement(babelNode)) {
31
+ addBindingNamesFromNode(babelNode.argument, out);
32
+ return;
33
+ }
34
+ if (isAssignmentPattern(babelNode)) {
35
+ addBindingNamesFromNode(babelNode.left, out);
36
+ }
37
+ };
38
+ export const collectExportedNames = (program) => {
39
+ const exportedNames = new Set();
40
+ for (const statement of program.body) {
41
+ if (!isExportNamedDeclaration(statement))
42
+ continue;
43
+ const declaration = statement.declaration;
44
+ if (declaration) {
45
+ if (isVariableDeclaration(declaration)) {
46
+ for (const declarator of declaration.declarations) {
47
+ addBindingNamesFromNode(declarator.id, exportedNames);
48
+ }
49
+ }
50
+ else if (isFunctionDeclaration(declaration) ||
51
+ isClassDeclaration(declaration)) {
52
+ const id = declaration.id;
53
+ if (!id)
54
+ continue;
55
+ exportedNames.add(id.name);
56
+ }
57
+ }
58
+ for (const specifier of statement.specifiers) {
59
+ if (!isExportSpecifier(specifier))
60
+ continue;
61
+ const local = specifier.local;
62
+ if (!isIdentifier(local))
63
+ continue;
64
+ exportedNames.add(local.name);
65
+ }
66
+ }
67
+ return exportedNames;
68
+ };
@@ -38,7 +38,7 @@ const hasShadowingRisk = (binding, bindingScope, targetName) => binding.referenc
38
38
  /**
39
39
  * Finds the next available name slot in a scope.
40
40
  */
41
- const findAvailableName = (scope, binding, baseName, startIndex, canBeStable) => {
41
+ const findAvailableName = (scope, binding, baseName, startIndex, canBeStable, currentName) => {
42
42
  let index = startIndex;
43
43
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
44
44
  while (true) {
@@ -47,8 +47,12 @@ const findAvailableName = (scope, binding, baseName, startIndex, canBeStable) =>
47
47
  const candidateStable = makeStableName(candidateBase);
48
48
  const candidateReadable = candidateBase;
49
49
  // Check if either form is already taken in this scope
50
- const stableTaken = scope.hasBinding(candidateStable);
51
- const readableTaken = scope.hasBinding(candidateReadable);
50
+ const stableTaken = candidateStable === currentName
51
+ ? false
52
+ : scope.hasBinding(candidateStable);
53
+ const readableTaken = candidateReadable === currentName
54
+ ? false
55
+ : scope.hasBinding(candidateReadable);
52
56
  if (!stableTaken && !readableTaken) {
53
57
  // This slot is available
54
58
  const name = canBeStable ? candidateStable : candidateReadable;
@@ -124,7 +128,7 @@ export class RenameGroup {
124
128
  let index = 1;
125
129
  for (const entry of group) {
126
130
  // Find next available name slot
127
- const targetName = findAvailableName(scope, scope.getBinding(entry.currentName), baseName, index, canBeStable);
131
+ const targetName = findAvailableName(scope, scope.getBinding(entry.currentName), baseName, index, canBeStable, entry.currentName);
128
132
  index = targetName.nextIndex;
129
133
  if (entry.currentName !== targetName.name) {
130
134
  scope.rename(entry.currentName, targetName.name);
@@ -81,6 +81,12 @@ const manifestData = {
81
81
  evaluatedAt: "2026-01-23T18:10:00.000Z",
82
82
  notes: "Derives names from charCodeAt argument for better stability (e.g., $charCodeAtIndex, $charCodeAtIndexPlus1).",
83
83
  },
84
+ "rename-client-aliases": {
85
+ diffReductionImpact: 0,
86
+ recommended: true,
87
+ evaluatedAt: "2026-01-24T15:58:39.356Z",
88
+ notes: "Measured with baseline none: 0.00%. Added to recommended for readability.",
89
+ },
84
90
  "rename-comparison-flags": {
85
91
  diffReductionImpact: 0,
86
92
  recommended: true,
@@ -13,6 +13,7 @@ import { renameCatchParametersTransform } from "../rename-catch-parameters/renam
13
13
  import { renameCharCodeAtTransform } from "../rename-char-code-at/rename-char-code-at-transform.js";
14
14
  import { renameCharcodeVariablesTransform } from "../rename-charcode-variables/rename-charcode-variables-transform.js";
15
15
  import { renameCharcodeVariablesV2Transform } from "../rename-charcode-variables-v2/rename-charcode-variables-v2-transform.js";
16
+ import { renameClientAliasesTransform } from "../rename-client-aliases/rename-client-aliases-transform.js";
16
17
  import { renameComparisonFlagsTransform } from "../rename-comparison-flags/rename-comparison-flags-transform.js";
17
18
  import { renameDateNowStartTimesTransform } from "../rename-date-now-start-times/rename-date-now-start-times-transform.js";
18
19
  import { renameDefaultOptionsParametersTransform } from "../rename-default-options-parameters/rename-default-options-parameters-transform.js";
@@ -55,6 +56,7 @@ export const transformRegistry = {
55
56
  [renameCharCodeAtTransform.id]: renameCharCodeAtTransform,
56
57
  [renameCharcodeVariablesTransform.id]: renameCharcodeVariablesTransform,
57
58
  [renameCharcodeVariablesV2Transform.id]: renameCharcodeVariablesV2Transform,
59
+ [renameClientAliasesTransform.id]: renameClientAliasesTransform,
58
60
  [renameComparisonFlagsTransform.id]: renameComparisonFlagsTransform,
59
61
  [renameDateNowStartTimesTransform.id]: renameDateNowStartTimesTransform,
60
62
  [renameDefaultOptionsParametersTransform.id]: renameDefaultOptionsParametersTransform,
@@ -0,0 +1,6 @@
1
+ {
2
+ "diffReductionImpact": 0,
3
+ "recommended": true,
4
+ "evaluatedAt": "2026-01-24T15:58:39.356Z",
5
+ "notes": "Measured with baseline none: 0.00%. Added to recommended for readability."
6
+ }
@@ -0,0 +1,2 @@
1
+ import { type Transform } from "../../core/types.js";
2
+ export declare const renameClientAliasesTransform: Transform;
@@ -0,0 +1,65 @@
1
+ import { createRequire } from "node:module";
2
+ import { collectExportedNames } from "../../core/collect-exported-names.js";
3
+ import { RenameGroup, isStableRenamed } from "../../core/stable-naming.js";
4
+ import { getFilesToProcess, } from "../../core/types.js";
5
+ const require = createRequire(import.meta.url);
6
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
7
+ const traverse = require("@babel/traverse").default;
8
+ const BASE_NAME = "client";
9
+ const isClientMemberExpression = (node) => {
10
+ if (node.computed) {
11
+ return ((node.property.type === "StringLiteral" &&
12
+ node.property.value === "client") ||
13
+ (node.property.type === "TemplateLiteral" &&
14
+ node.property.expressions.length === 0 &&
15
+ node.property.quasis[0]?.value.cooked === "client"));
16
+ }
17
+ return node.property.type === "Identifier" && node.property.name === "client";
18
+ };
19
+ export const renameClientAliasesTransform = {
20
+ id: "rename-client-aliases",
21
+ description: "Renames aliases of *.client to $client/$client2/...",
22
+ scope: "file",
23
+ parallelizable: true,
24
+ transform(context) {
25
+ let nodesVisited = 0;
26
+ let transformationsApplied = 0;
27
+ for (const fileInfo of getFilesToProcess(context)) {
28
+ const group = new RenameGroup();
29
+ const exportedNames = collectExportedNames(fileInfo.ast.program);
30
+ traverse(fileInfo.ast, {
31
+ VariableDeclarator(path) {
32
+ nodesVisited++;
33
+ const id = path.node.id;
34
+ if (id.type !== "Identifier")
35
+ return;
36
+ if (isStableRenamed(id.name))
37
+ return;
38
+ const init = path.node.init;
39
+ if (init?.type !== "MemberExpression")
40
+ return;
41
+ if (!isClientMemberExpression(init))
42
+ return;
43
+ const binding = path.scope.getBinding(id.name);
44
+ if (!binding)
45
+ return;
46
+ if (!binding.constant)
47
+ return;
48
+ if (binding.referencePaths.length === 0)
49
+ return;
50
+ if (binding.scope.block.type === "Program" &&
51
+ exportedNames.has(id.name)) {
52
+ return;
53
+ }
54
+ group.add({
55
+ scope: binding.scope,
56
+ currentName: id.name,
57
+ baseName: BASE_NAME,
58
+ });
59
+ },
60
+ });
61
+ transformationsApplied += group.apply();
62
+ }
63
+ return Promise.resolve({ nodesVisited, transformationsApplied });
64
+ },
65
+ };
@@ -1,78 +1,11 @@
1
1
  import { createRequire } from "node:module";
2
- import { isArrayPattern, isAssignmentPattern, isClassDeclaration, isExportNamedDeclaration, isExportSpecifier, isFunctionDeclaration, isIdentifier, isObjectPattern, isObjectProperty, isRestElement, isVariableDeclaration, } from "@babel/types";
2
+ import { collectExportedNames } from "../../core/collect-exported-names.js";
3
3
  import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
4
4
  import { getFilesToProcess, } from "../../core/types.js";
5
5
  const require = createRequire(import.meta.url);
6
6
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
7
7
  const traverse = require("@babel/traverse").default;
8
8
  const BASE_NAME = "thisRef";
9
- const addBindingNamesFromNode = (node, out) => {
10
- const babelNode = node;
11
- if (!babelNode)
12
- return;
13
- if (babelNode.type === "VoidPattern")
14
- return;
15
- if (isIdentifier(babelNode)) {
16
- out.add(babelNode.name);
17
- return;
18
- }
19
- if (isObjectPattern(babelNode)) {
20
- for (const property of babelNode.properties) {
21
- if (isRestElement(property)) {
22
- addBindingNamesFromNode(property.argument, out);
23
- continue;
24
- }
25
- if (!isObjectProperty(property))
26
- continue;
27
- addBindingNamesFromNode(property.value, out);
28
- }
29
- return;
30
- }
31
- if (isArrayPattern(babelNode)) {
32
- for (const element of babelNode.elements) {
33
- addBindingNamesFromNode(element, out);
34
- }
35
- return;
36
- }
37
- if (isRestElement(babelNode)) {
38
- addBindingNamesFromNode(babelNode.argument, out);
39
- return;
40
- }
41
- if (isAssignmentPattern(babelNode)) {
42
- addBindingNamesFromNode(babelNode.left, out);
43
- }
44
- };
45
- const collectExportedNames = (program) => {
46
- const exportedNames = new Set();
47
- for (const statement of program.body) {
48
- if (!isExportNamedDeclaration(statement))
49
- continue;
50
- const declaration = statement.declaration;
51
- if (declaration) {
52
- if (isVariableDeclaration(declaration)) {
53
- for (const declarator of declaration.declarations) {
54
- addBindingNamesFromNode(declarator.id, exportedNames);
55
- }
56
- }
57
- else if (isFunctionDeclaration(declaration) ||
58
- isClassDeclaration(declaration)) {
59
- const id = declaration.id;
60
- if (!id)
61
- continue;
62
- exportedNames.add(id.name);
63
- }
64
- }
65
- for (const specifier of statement.specifiers) {
66
- if (!isExportSpecifier(specifier))
67
- continue;
68
- const local = specifier.local;
69
- if (!isIdentifier(local))
70
- continue;
71
- exportedNames.add(local.name);
72
- }
73
- }
74
- return exportedNames;
75
- };
76
9
  export const renameThisAliasesTransform = {
77
10
  id: "rename-this-aliases",
78
11
  description: "Renames `var x = this` aliases to $thisRef (stable when unique) or thisRef/thisRef2/...",
@@ -1,78 +1,11 @@
1
1
  import { createRequire } from "node:module";
2
- import { isArrayPattern, isAssignmentPattern, isClassDeclaration, isExportNamedDeclaration, isExportSpecifier, isFunctionDeclaration, isIdentifier, isObjectPattern, isObjectProperty, isRestElement, isVariableDeclaration, } from "@babel/types";
2
+ import { collectExportedNames } from "../../core/collect-exported-names.js";
3
3
  import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
4
4
  import { getFilesToProcess, } from "../../core/types.js";
5
5
  const require = createRequire(import.meta.url);
6
6
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
7
7
  const traverse = require("@babel/traverse").default;
8
8
  const BASE_NAME = "type";
9
- const addBindingNamesFromNode = (node, out) => {
10
- const babelNode = node;
11
- if (!babelNode)
12
- return;
13
- if (babelNode.type === "VoidPattern")
14
- return;
15
- if (isIdentifier(babelNode)) {
16
- out.add(babelNode.name);
17
- return;
18
- }
19
- if (isObjectPattern(babelNode)) {
20
- for (const property of babelNode.properties) {
21
- if (isRestElement(property)) {
22
- addBindingNamesFromNode(property.argument, out);
23
- continue;
24
- }
25
- if (!isObjectProperty(property))
26
- continue;
27
- addBindingNamesFromNode(property.value, out);
28
- }
29
- return;
30
- }
31
- if (isArrayPattern(babelNode)) {
32
- for (const element of babelNode.elements) {
33
- addBindingNamesFromNode(element, out);
34
- }
35
- return;
36
- }
37
- if (isRestElement(babelNode)) {
38
- addBindingNamesFromNode(babelNode.argument, out);
39
- return;
40
- }
41
- if (isAssignmentPattern(babelNode)) {
42
- addBindingNamesFromNode(babelNode.left, out);
43
- }
44
- };
45
- const collectExportedNames = (program) => {
46
- const exportedNames = new Set();
47
- for (const statement of program.body) {
48
- if (!isExportNamedDeclaration(statement))
49
- continue;
50
- const declaration = statement.declaration;
51
- if (declaration) {
52
- if (isVariableDeclaration(declaration)) {
53
- for (const declarator of declaration.declarations) {
54
- addBindingNamesFromNode(declarator.id, exportedNames);
55
- }
56
- }
57
- else if (isFunctionDeclaration(declaration) ||
58
- isClassDeclaration(declaration)) {
59
- const id = declaration.id;
60
- if (!id)
61
- continue;
62
- exportedNames.add(id.name);
63
- }
64
- }
65
- for (const specifier of statement.specifiers) {
66
- if (!isExportSpecifier(specifier))
67
- continue;
68
- const local = specifier.local;
69
- if (!isIdentifier(local))
70
- continue;
71
- exportedNames.add(local.name);
72
- }
73
- }
74
- return exportedNames;
75
- };
76
9
  export const renameTypeofVariablesTransform = {
77
10
  id: "rename-typeof-variables",
78
11
  description: "Renames variables assigned from typeof expressions to $type (stable when unique) or type/type2/...",
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.35.0",
5
+ "version": "1.36.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",