comment-variables 0.0.3 → 0.0.5
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/find-all-imports.js +9 -139
- package/index.js +15 -9
- package/package.json +3 -1
package/find-all-imports.js
CHANGED
|
@@ -1,128 +1,8 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import { loadConfig, createMatchPath } from "tsconfig-paths";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {readonly [typeof TSX, typeof TS, typeof JSX, typeof JS, typeof MJS, typeof CJS]} Extensions
|
|
10
|
-
* @typedef {import('eslint').Linter.LanguageOptions} LanguageOptions
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
// JavaScript/TypeScript extensions
|
|
14
|
-
export const TSX = ".tsx";
|
|
15
|
-
export const TS = ".ts";
|
|
16
|
-
export const JSX = ".jsx";
|
|
17
|
-
export const JS = ".js";
|
|
18
|
-
export const MJS = ".mjs";
|
|
19
|
-
export const CJS = ".cjs";
|
|
20
|
-
|
|
21
|
-
// JavaScript/TypeScript extensions array
|
|
22
|
-
/** @type {Extensions} */
|
|
23
|
-
const EXTENSIONS = Object.freeze([TSX, TS, JSX, JS, MJS, CJS]); // In priority order
|
|
24
|
-
|
|
25
|
-
/* resolveImportPath */
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Finds the existing path of an import that does not have an extension specified.
|
|
29
|
-
* @param {string} basePath The absolute import path with extension yet resolved.
|
|
30
|
-
* @returns The absolute path with its extension or `null` if no path is found.
|
|
31
|
-
*/
|
|
32
|
-
const findExistingPath = (basePath) => {
|
|
33
|
-
for (const ext of EXTENSIONS) {
|
|
34
|
-
const fullPath = `${basePath}${ext}`;
|
|
35
|
-
if (fs.existsSync(fullPath)) return fullPath;
|
|
36
|
-
}
|
|
37
|
-
return null;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Resolves an import path to a filesystem path, handling:
|
|
42
|
-
* - Base url and aliases (via tsconfig.json `baseUrl` and `paths` compiler options)
|
|
43
|
-
* - Missing extensions (appends `.ts`, `.tsx`, etc.)
|
|
44
|
-
* - Directory imports (e.g., `./components` → `./components/index.ts`)
|
|
45
|
-
* @param {string} currentDir The directory of the file containing the import (such as from `path.dirname(context.filename)`).
|
|
46
|
-
* @param {string} importPath The import specifier (e.g., `@/components/Button` or `./utils`), from the current node.
|
|
47
|
-
* @param {string} cwd The project root (such as from `context.cwd`).
|
|
48
|
-
* @returns The absolute resolved path or `null` if no path is found.
|
|
49
|
-
*/
|
|
50
|
-
export const resolveImportPath = (
|
|
51
|
-
currentDir,
|
|
52
|
-
importPath,
|
|
53
|
-
cwd = process.cwd()
|
|
54
|
-
) => {
|
|
55
|
-
// Step 1: Resolves baseUrl and aliases
|
|
56
|
-
const config = loadConfig(cwd);
|
|
57
|
-
|
|
58
|
-
// creates a function that can resolve paths according to tsconfig's paths property if the config result type is success
|
|
59
|
-
const resolveTSConfig =
|
|
60
|
-
config.resultType === "success"
|
|
61
|
-
? createMatchPath(config.absoluteBaseUrl, config.paths)
|
|
62
|
-
: null;
|
|
63
|
-
|
|
64
|
-
// resolves a path that relies on tsconfig's baseUrl or aliases if any of the aforementioned are present in the import path
|
|
65
|
-
const baseUrlOrAliasedPath = resolveTSConfig
|
|
66
|
-
? resolveTSConfig(importPath, undefined, undefined, EXTENSIONS)
|
|
67
|
-
: null;
|
|
68
|
-
|
|
69
|
-
// Step 2: Resolves relative/absolute paths
|
|
70
|
-
const basePath = baseUrlOrAliasedPath || path.resolve(currentDir, importPath);
|
|
71
|
-
|
|
72
|
-
// does not resolve on node_modules
|
|
73
|
-
if (basePath.includes("node_modules")) return null;
|
|
74
|
-
|
|
75
|
-
// Case 1: File with extension exists
|
|
76
|
-
if (path.extname(importPath) && fs.existsSync(basePath)) return basePath;
|
|
77
|
-
|
|
78
|
-
// Case 2: Tries appending extensions
|
|
79
|
-
const extensionlessImportPath = findExistingPath(basePath);
|
|
80
|
-
if (extensionlessImportPath) return extensionlessImportPath;
|
|
81
|
-
|
|
82
|
-
// Case 3: Directory import (e.g., `./components` → `./components/index.ts`)
|
|
83
|
-
const indexPath = path.join(basePath, "index");
|
|
84
|
-
const directoryImportPath = findExistingPath(indexPath);
|
|
85
|
-
if (directoryImportPath) return directoryImportPath;
|
|
86
|
-
|
|
87
|
-
return null; // not found
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/* getSourceCodeFromFilePath */
|
|
91
|
-
|
|
92
|
-
// ESLint configs language options
|
|
93
|
-
const typeScriptAndJSXCompatible = {
|
|
94
|
-
// for compatibility with .ts and .tsx
|
|
95
|
-
parser: tseslint.parser,
|
|
96
|
-
// for compatibility with JSX
|
|
97
|
-
parserOptions: {
|
|
98
|
-
ecmaFeatures: {
|
|
99
|
-
jsx: true,
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Gets the ESLint-generated SourceCode object of a file from its resolved path.
|
|
106
|
-
* @param {string} resolvedPath The resolved path of the file.
|
|
107
|
-
* @param {LanguageOptions} languageOptions The languageOptions object used by `linter.verify()` defaulting to a version that is TypeScript- and JSX-compatible.
|
|
108
|
-
* @returns The ESLint-generated SourceCode object of the file.
|
|
109
|
-
*/
|
|
110
|
-
export const getSourceCodeFromFilePath = (
|
|
111
|
-
resolvedPath,
|
|
112
|
-
languageOptions = typeScriptAndJSXCompatible
|
|
113
|
-
) => {
|
|
114
|
-
// ensures each instance of the function is based on its own linter
|
|
115
|
-
// (just in case somehow some linters were running concurrently)
|
|
116
|
-
const linter = new Linter();
|
|
117
|
-
// the raw code of the file at the end of the resolved path
|
|
118
|
-
const text = fs.readFileSync(resolvedPath, "utf8");
|
|
119
|
-
// utilizes linter.verify ...
|
|
120
|
-
linter.verify(text, { languageOptions });
|
|
121
|
-
// ... to retrieve the raw code as a SourceCode object
|
|
122
|
-
const code = linter.getSourceCode();
|
|
123
|
-
|
|
124
|
-
return code;
|
|
125
|
-
};
|
|
4
|
+
import { resolveImportingPath } from "resolve-importing-path";
|
|
5
|
+
import { getSourceCodeFromFilePath } from "get-sourcecode-from-file-path";
|
|
126
6
|
|
|
127
7
|
/* findAllImports */
|
|
128
8
|
|
|
@@ -138,8 +18,8 @@ const processImport = (
|
|
|
138
18
|
depth,
|
|
139
19
|
maxDepth
|
|
140
20
|
) => {
|
|
141
|
-
const resolvedPath =
|
|
142
|
-
if (!resolvedPath) return true; //
|
|
21
|
+
const resolvedPath = resolveImportingPath(currentDir, importPath, cwd);
|
|
22
|
+
if (!resolvedPath) return true; // Skips unresolved paths (not an error).
|
|
143
23
|
|
|
144
24
|
const result = findAllImports(
|
|
145
25
|
resolvedPath,
|
|
@@ -148,7 +28,7 @@ const processImport = (
|
|
|
148
28
|
depth + 1,
|
|
149
29
|
maxDepth
|
|
150
30
|
);
|
|
151
|
-
return result !== null; // Returns false if child failed
|
|
31
|
+
return result !== null; // Returns false if child failed.
|
|
152
32
|
};
|
|
153
33
|
|
|
154
34
|
export const findAllImports = (
|
|
@@ -158,7 +38,7 @@ export const findAllImports = (
|
|
|
158
38
|
depth = 0,
|
|
159
39
|
maxDepth = 100
|
|
160
40
|
) => {
|
|
161
|
-
// Early failure checks (with logging)
|
|
41
|
+
// Early failure checks (with logging).
|
|
162
42
|
if (depth > maxDepth) {
|
|
163
43
|
console.error(`ERROR. Max depth ${maxDepth} reached at ${filePath}.`);
|
|
164
44
|
return null;
|
|
@@ -169,7 +49,7 @@ export const findAllImports = (
|
|
|
169
49
|
}
|
|
170
50
|
if (visited.has(filePath)) return visited;
|
|
171
51
|
|
|
172
|
-
//
|
|
52
|
+
// Parses AST.
|
|
173
53
|
visited.add(filePath);
|
|
174
54
|
const sourceCode = getSourceCodeFromFilePath(filePath);
|
|
175
55
|
if (!sourceCode?.ast) {
|
|
@@ -177,7 +57,7 @@ export const findAllImports = (
|
|
|
177
57
|
return null;
|
|
178
58
|
}
|
|
179
59
|
|
|
180
|
-
//
|
|
60
|
+
// Processes all imports.
|
|
181
61
|
const currentDir = path.dirname(filePath);
|
|
182
62
|
for (const node of sourceCode.ast.body) {
|
|
183
63
|
// ES Modules (import x from 'y')
|
|
@@ -218,15 +98,5 @@ export const findAllImports = (
|
|
|
218
98
|
}
|
|
219
99
|
}
|
|
220
100
|
|
|
221
|
-
return visited; //
|
|
101
|
+
return visited; // success
|
|
222
102
|
};
|
|
223
|
-
|
|
224
|
-
/* Notes
|
|
225
|
-
So here I want to make
|
|
226
|
-
- resolveImportPath
|
|
227
|
-
- getSourceCodeFromFilePath (remember the reason I favored the sourceCode is because it grants access to the AST and to the comments.)
|
|
228
|
-
|
|
229
|
-
js-comments is taken on npm.
|
|
230
|
-
JSComments, jscomments is free.
|
|
231
|
-
comment-variables in the end.
|
|
232
|
-
*/
|
package/index.js
CHANGED
|
@@ -5,13 +5,14 @@ import path from "path";
|
|
|
5
5
|
import fs from "fs";
|
|
6
6
|
|
|
7
7
|
import { ESLint } from "eslint";
|
|
8
|
+
import tseslint from "typescript-eslint";
|
|
8
9
|
|
|
9
10
|
import { runWithConfig } from "./run-with-config.js";
|
|
10
11
|
import { findAllImports } from "./find-all-imports.js";
|
|
11
12
|
|
|
12
13
|
const cwd = process.cwd();
|
|
13
14
|
|
|
14
|
-
// ENSURES THE CLI TOOL ONLY RUN IN
|
|
15
|
+
// ENSURES THE CLI TOOL ONLY RUN IN FOLDERS THAT POSSESS A package.json FILE AND A .git FOLDER.
|
|
15
16
|
|
|
16
17
|
const hasPackageJson = fs.existsSync(path.join(cwd, "package.json"));
|
|
17
18
|
if (!hasPackageJson) {
|
|
@@ -97,6 +98,17 @@ const allJSTSFileGlobs = [
|
|
|
97
98
|
|
|
98
99
|
// MAKES THE FLOW FOR resolveCommentsInProject.
|
|
99
100
|
|
|
101
|
+
const typeScriptAndJSXCompatible = {
|
|
102
|
+
// for compatibility with TypeScript (.ts and .tsx)
|
|
103
|
+
parser: tseslint.parser,
|
|
104
|
+
// for compatibility with JSX (React, etc.)
|
|
105
|
+
parserOptions: {
|
|
106
|
+
ecmaFeatures: {
|
|
107
|
+
jsx: true,
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
|
|
100
112
|
/** @type {import('@typescript-eslint/utils').TSESLint.RuleModule<string, []>} */
|
|
101
113
|
const jsCommentsRule = {
|
|
102
114
|
meta: {
|
|
@@ -166,10 +178,7 @@ async function resolveCommentsInProject(fileGlobs = allJSTSFileGlobs) {
|
|
|
166
178
|
{
|
|
167
179
|
files: fileGlobs,
|
|
168
180
|
ignores: [...configIgnores, ...knownIgnores], // 🚫 Ensure config isn't linted
|
|
169
|
-
languageOptions:
|
|
170
|
-
ecmaVersion: "latest",
|
|
171
|
-
sourceType: "module",
|
|
172
|
-
},
|
|
181
|
+
languageOptions: typeScriptAndJSXCompatible,
|
|
173
182
|
plugins: {
|
|
174
183
|
"js-comments": {
|
|
175
184
|
rules: {
|
|
@@ -277,10 +286,7 @@ async function compressCommentsInProject(fileGlobs = allJSTSFileGlobs) {
|
|
|
277
286
|
{
|
|
278
287
|
files: fileGlobs,
|
|
279
288
|
ignores: [...configIgnores, ...knownIgnores], // 🚫 Ensure config isn't linted
|
|
280
|
-
languageOptions:
|
|
281
|
-
ecmaVersion: "latest",
|
|
282
|
-
sourceType: "module",
|
|
283
|
-
},
|
|
289
|
+
languageOptions: typeScriptAndJSXCompatible,
|
|
284
290
|
plugins: {
|
|
285
291
|
"js-comments": {
|
|
286
292
|
rules: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comment-variables",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"bin": {
|
|
6
6
|
"jscomments": "./index.js",
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"type": "module",
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"eslint": "^9.29.0",
|
|
23
|
+
"get-sourcecode-from-file-path": "^1.0.0",
|
|
24
|
+
"resolve-importing-path": "^1.0.2",
|
|
23
25
|
"tsconfig-paths": "^4.2.0",
|
|
24
26
|
"typescript-eslint": "^8.34.1",
|
|
25
27
|
"zod": "^3.25.67"
|