@dittowords/cli 4.3.0 → 4.4.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/.github/actions/install-node-dependencies/action.yml +24 -0
- package/.github/workflows/required-checks.yml +24 -0
- package/.sentryclirc +3 -0
- package/__mocks__/fs.js +2 -0
- package/bin/__mocks__/api.js +48 -0
- package/bin/__mocks__/api.js.map +1 -0
- package/bin/config.test.js +4 -3
- package/bin/config.test.js.map +1 -1
- package/bin/consts.js +19 -29
- package/bin/consts.js.map +1 -1
- package/bin/ditto.js +12 -4
- package/bin/ditto.js.map +1 -1
- package/bin/generate-suggestions.js +68 -58
- package/bin/generate-suggestions.js.map +1 -1
- package/bin/generate-suggestions.test.js +24 -13
- package/bin/generate-suggestions.test.js.map +1 -1
- package/bin/http/__mocks__/fetchComponentFolders.js +71 -0
- package/bin/http/__mocks__/fetchComponentFolders.js.map +1 -0
- package/bin/http/__mocks__/fetchComponents.js +73 -0
- package/bin/http/__mocks__/fetchComponents.js.map +1 -0
- package/bin/http/__mocks__/fetchVariants.js +71 -0
- package/bin/http/__mocks__/fetchVariants.js.map +1 -0
- package/bin/http/fetchComponentFolders.js +4 -4
- package/bin/http/fetchComponentFolders.js.map +1 -1
- package/bin/http/fetchComponents.js +4 -4
- package/bin/http/fetchComponents.js.map +1 -1
- package/bin/http/fetchVariants.js +6 -3
- package/bin/http/fetchVariants.js.map +1 -1
- package/bin/http/http.test.js +159 -0
- package/bin/http/http.test.js.map +1 -0
- package/bin/http/importComponents.js +9 -2
- package/bin/http/importComponents.js.map +1 -1
- package/bin/init/project.test.js +5 -28
- package/bin/init/project.test.js.map +1 -1
- package/bin/init/token.js +72 -27
- package/bin/init/token.js.map +1 -1
- package/bin/init/token.test.js +87 -9
- package/bin/init/token.test.js.map +1 -1
- package/bin/pull-lib.test.js +379 -0
- package/bin/pull-lib.test.js.map +1 -0
- package/bin/pull.js +15 -4
- package/bin/pull.js.map +1 -1
- package/bin/pull.test.js +73 -290
- package/bin/pull.test.js.map +1 -1
- package/bin/replace.js +22 -6
- package/bin/replace.js.map +1 -1
- package/bin/replace.test.js +53 -11
- package/bin/replace.test.js.map +1 -1
- package/bin/utils/determineModuleType.js +6 -7
- package/bin/utils/determineModuleType.js.map +1 -1
- package/bin/utils/determineModuleType.test.js +60 -0
- package/bin/utils/determineModuleType.test.js.map +1 -0
- package/bin/utils/getSelectedProjects.js +5 -5
- package/bin/utils/getSelectedProjects.js.map +1 -1
- package/bin/utils/quit.js +3 -3
- package/bin/utils/quit.js.map +1 -1
- package/jest.config.ts +16 -0
- package/lib/__mocks__/api.ts +12 -0
- package/lib/config.test.ts +3 -1
- package/lib/consts.ts +19 -17
- package/lib/ditto.ts +9 -1
- package/lib/generate-suggestions.test.ts +23 -11
- package/lib/generate-suggestions.ts +89 -79
- package/lib/http/__mocks__/fetchComponentFolders.ts +23 -0
- package/lib/http/__mocks__/fetchComponents.ts +24 -0
- package/lib/http/__mocks__/fetchVariants.ts +21 -0
- package/lib/http/fetchComponentFolders.ts +6 -4
- package/lib/http/fetchComponents.ts +5 -3
- package/lib/http/fetchVariants.ts +15 -4
- package/lib/http/http.test.ts +122 -0
- package/lib/http/importComponents.ts +8 -0
- package/lib/init/project.test.ts +4 -27
- package/lib/init/token.test.ts +55 -7
- package/lib/init/token.ts +76 -27
- package/lib/pull-lib.test.ts +367 -0
- package/lib/pull.test.ts +63 -316
- package/lib/pull.ts +13 -2
- package/lib/replace.test.ts +46 -10
- package/lib/replace.ts +20 -3
- package/lib/utils/determineModuleType.test.ts +48 -0
- package/lib/utils/determineModuleType.ts +4 -6
- package/lib/utils/getSelectedProjects.ts +3 -3
- package/lib/utils/quit.ts +1 -1
- package/package.json +4 -3
- package/jest.config.js +0 -6
package/bin/replace.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../lib/replace.test.ts"],"sourcesContent":["import fs from \"fs
|
|
1
|
+
{"version":3,"sources":["../lib/replace.test.ts"],"sourcesContent":["import fs from \"fs\";\nimport { parseOptions, replaceJSXTextInFile } from \"./replace\"; // Assuming the function is exported in a separate file\n\njest.mock(\"fs\");\n\n// Helper function to create a temporary file\nasync function createTempJSXFile(content: string): Promise<string> {\n const tempFile = \"/tempFile.jsx\";\n await new Promise((resolve, reject) => {\n try {\n fs.writeFile(tempFile, content, resolve);\n } catch (e) {\n reject(e);\n }\n });\n return tempFile;\n}\n\n// Helper function to delete the temporary file\nasync function deleteTempFile(filePath: string): Promise<void> {\n await new Promise((resolve, reject) => {\n try {\n fs.unlink(filePath, resolve);\n } catch (e) {\n reject(e);\n }\n });\n}\n\ndescribe(\"parseOptions\", () => {\n test(\"should pass with valid input\", async () => {\n const tempFile = await createTempJSXFile(\"<div>Hello, world!</div>\");\n expect(() =>\n parseOptions([tempFile, \"secondString\", \"thirdString\"])\n ).not.toThrow();\n\n const result = parseOptions([tempFile, \"secondString\", \"thirdString\"]);\n expect(result).toEqual({\n filePath: tempFile,\n searchString: \"secondString\",\n replaceWith: \"thirdString\",\n });\n\n deleteTempFile(tempFile);\n });\n\n test(\"should throw error when options array does not have exactly three strings\", () => {\n expect(() => parseOptions([\"oneString\"])).toThrow(\n \"The options array must contain <file path> <search string> <replace with>.\"\n );\n expect(() => parseOptions([\"one\", \"two\"])).toThrow(\n \"The options array must contain <file path> <search string> <replace with>.\"\n );\n expect(() => parseOptions([\"one\", \"two\", \"three\", \"four\"])).toThrow(\n \"The options array must contain <file path> <search string> <replace with>.\"\n );\n });\n\n test(\"should throw error when the first string is not a valid file path\", () => {\n const invalidFilePath = \"/path/to/invalid/file.txt\";\n expect(() =>\n parseOptions([invalidFilePath, \"secondString\", \"thirdString\"])\n ).toThrow(`${invalidFilePath} is not a valid file path.`);\n });\n\n test(\"should throw error when the first string is a directory\", () => {\n const directoryPath = \".\";\n expect(() =>\n parseOptions([directoryPath, \"secondString\", \"thirdString\"])\n ).toThrow(`${directoryPath} is not a valid file path.`);\n });\n});\n\ndescribe(\"replaceJSXTextInFile\", () => {\n afterEach(async () => {\n await deleteTempFile(\"/tempFile.jsx\");\n });\n\n test(\"should replace JSX text with a DittoComponent\", async () => {\n const tempFile = await createTempJSXFile(\"<div>Hello, world</div>\");\n const searchString = \"world\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});\n\n const transformedCode = await new Promise((resolve, reject) => {\n fs.readFile(tempFile, \"utf-8\", (error, data) => {\n if (error) {\n reject(error);\n } else {\n resolve(data);\n }\n });\n });\n expect(transformedCode).toContain(\n `<div>Hello, <DittoComponent componentId=\"${replaceWith}\" /></div>`\n );\n });\n\n test(\"should replace JSX text with a DittoComponent with a flag\", async () => {\n const tempFile = await createTempJSXFile(\n `<>\\n<div>Hello, world</div>\\n<div>Hello, world</div>\\n</>`\n );\n const searchString = \"world\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(\n tempFile,\n { searchString, replaceWith },\n { lineNumbers: [3] }\n );\n\n const transformedCode = await new Promise((resolve, reject) =>\n fs.readFile(tempFile, \"utf-8\", (error, data) => {\n if (error) reject(error);\n else resolve(data);\n })\n );\n expect(transformedCode).toContain(\n `<>\\n <div>Hello, world</div>\\n <div>Hello, <DittoComponent componentId=\\\"some-id\\\" /></div>\\n</>;`\n );\n });\n\n test(\"should handle case-insensitive search\", async () => {\n const tempFile = await createTempJSXFile(\"<div>HeLLo, WoRlD</div>\");\n const searchString = \"world\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});\n\n const transformedCode = await new Promise((resolve, reject) =>\n fs.readFile(tempFile, \"utf-8\", (error, data) => {\n if (error) reject(error);\n else resolve(data);\n })\n );\n expect(transformedCode).toContain(\n `<div>HeLLo, <DittoComponent componentId=\"${replaceWith}\" /></div>`\n );\n });\n\n test(\"should not replace JSX text if searchString is not found\", async () => {\n const tempFile = await createTempJSXFile(\"<div>Hello, world!</div>\");\n const searchString = \"foobar\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});\n\n const transformedCode = await new Promise((resolve, reject) =>\n fs.readFile(tempFile, \"utf-8\", (error, data) => {\n if (error) reject(error);\n else resolve(data);\n })\n );\n expect(transformedCode).toContain(\"<div>Hello, world!</div>\");\n });\n});\n"],"names":["fs"],"mappings":"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","debug_id":"8d2eb72b-d2d6-5847-b480-cd39f4da1f7e"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6334441d-042a-5df3-9f37-7bd9fd9adae4")}catch(e){}}();
|
|
3
3
|
|
|
4
4
|
var __create = Object.create;
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -35,15 +35,14 @@ __export(determineModuleType_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(determineModuleType_exports);
|
|
36
36
|
var fs = __toESM(require("fs"));
|
|
37
37
|
var path = __toESM(require("path"));
|
|
38
|
-
function determineModuleType() {
|
|
39
|
-
const value = getRawTypeFromPackageJson();
|
|
38
|
+
function determineModuleType(currentDir = process.cwd()) {
|
|
39
|
+
const value = getRawTypeFromPackageJson(currentDir);
|
|
40
40
|
return getTypeOrDefault(value);
|
|
41
41
|
}
|
|
42
|
-
function getRawTypeFromPackageJson() {
|
|
42
|
+
function getRawTypeFromPackageJson(currentDir) {
|
|
43
43
|
if (process.env.DITTO_MODULE_TYPE) {
|
|
44
44
|
return process.env.DITTO_MODULE_TYPE;
|
|
45
45
|
}
|
|
46
|
-
let currentDir = process.cwd();
|
|
47
46
|
while (currentDir) {
|
|
48
47
|
const packageJsonPath = path.join(currentDir, "package.json");
|
|
49
48
|
if (fs.existsSync(packageJsonPath)) {
|
|
@@ -58,7 +57,7 @@ function getRawTypeFromPackageJson() {
|
|
|
58
57
|
return null;
|
|
59
58
|
}
|
|
60
59
|
if (currentDir === "/") {
|
|
61
|
-
|
|
60
|
+
break;
|
|
62
61
|
}
|
|
63
62
|
currentDir = path.dirname(currentDir);
|
|
64
63
|
}
|
|
@@ -77,4 +76,4 @@ function getTypeOrDefault(value) {
|
|
|
77
76
|
});
|
|
78
77
|
//# sourceMappingURL=determineModuleType.js.map
|
|
79
78
|
|
|
80
|
-
//# debugId=
|
|
79
|
+
//# debugId=6334441d-042a-5df3-9f37-7bd9fd9adae4
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../lib/utils/determineModuleType.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\nexport type ModuleType = \"commonjs\" | \"module\";\n\n/**\n * Looks for a `package.json` file starting in the current working directory and traversing upwards\n * until it finds one or reaches root.\n * @returns \"commonjs\" or \"module\", defaulting to \"module\" if no `package.json` is found or if the found\n * file does not include a `type` property.\n */\nexport function determineModuleType() {\n const value = getRawTypeFromPackageJson();\n return getTypeOrDefault(value);\n}\n\nfunction getRawTypeFromPackageJson() {\n if (process.env.DITTO_MODULE_TYPE) {\n return process.env.DITTO_MODULE_TYPE;\n }\n\n
|
|
1
|
+
{"version":3,"sources":["../../lib/utils/determineModuleType.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\nexport type ModuleType = \"commonjs\" | \"module\";\n\n/**\n * Looks for a `package.json` file starting in the current working directory and traversing upwards\n * until it finds one or reaches root.\n * @returns \"commonjs\" or \"module\", defaulting to \"module\" if no `package.json` is found or if the found\n * file does not include a `type` property.\n */\nexport function determineModuleType(currentDir: string | null = process.cwd()) {\n const value = getRawTypeFromPackageJson(currentDir);\n return getTypeOrDefault(value);\n}\n\nfunction getRawTypeFromPackageJson(currentDir: string | null) {\n if (process.env.DITTO_MODULE_TYPE) {\n return process.env.DITTO_MODULE_TYPE;\n }\n\n while (currentDir) {\n const packageJsonPath = path.join(currentDir, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n const packageJsonContents = fs.readFileSync(packageJsonPath, \"utf8\");\n try {\n const packageData: { type?: string } = JSON.parse(packageJsonContents);\n if (packageData?.type) {\n return packageData.type;\n }\n } catch {}\n\n return null;\n }\n\n if (currentDir === \"/\") {\n break;\n }\n\n // Move up a directory and continue the search\n currentDir = path.dirname(currentDir);\n }\n\n // No package.json\n return null;\n}\n\nfunction getTypeOrDefault(value: string | null): ModuleType {\n const valueLower = value?.toLowerCase() || \"\";\n if (valueLower === \"commonjs\" || valueLower === \"module\") {\n return valueLower;\n }\n\n return \"commonjs\";\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAoB;AACpB,WAAsB;AAUf,SAAS,oBAAoB,aAA4B,QAAQ,IAAI,GAAG;AAC7E,QAAM,QAAQ,0BAA0B,UAAU;AAClD,SAAO,iBAAiB,KAAK;AAC/B;AAEA,SAAS,0BAA0B,YAA2B;AAC5D,MAAI,QAAQ,IAAI,mBAAmB;AACjC,WAAO,QAAQ,IAAI;AAAA,EACrB;AAEA,SAAO,YAAY;AACjB,UAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAC5D,QAAI,GAAG,WAAW,eAAe,GAAG;AAClC,YAAM,sBAAsB,GAAG,aAAa,iBAAiB,MAAM;AACnE,UAAI;AACF,cAAM,cAAiC,KAAK,MAAM,mBAAmB;AACrE,YAAI,2CAAa,MAAM;AACrB,iBAAO,YAAY;AAAA,QACrB;AAAA,MACF,SAAQ;AAAA,MAAC;AAET,aAAO;AAAA,IACT;AAEA,QAAI,eAAe,KAAK;AACtB;AAAA,IACF;AAGA,iBAAa,KAAK,QAAQ,UAAU;AAAA,EACtC;AAGA,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAkC;AAC1D,QAAM,cAAa,+BAAO,kBAAiB;AAC3C,MAAI,eAAe,cAAc,eAAe,UAAU;AACxD,WAAO;AAAA,EACT;AAEA,SAAO;AACT","debug_id":"6334441d-042a-5df3-9f37-7bd9fd9adae4"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="31410f07-eaa0-59b5-a32b-1c709affaf87")}catch(e){}}();
|
|
3
|
+
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var import_determineModuleType = require("./determineModuleType");
|
|
21
|
+
var import_memfs = require("memfs");
|
|
22
|
+
const defaultEnv = process.env;
|
|
23
|
+
jest.mock("fs");
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
import_memfs.vol.reset();
|
|
26
|
+
process.env = __spreadValues({}, defaultEnv);
|
|
27
|
+
});
|
|
28
|
+
test("'commonjs' if no package.json found", () => {
|
|
29
|
+
expect((0, import_determineModuleType.determineModuleType)()).toBe("commonjs");
|
|
30
|
+
});
|
|
31
|
+
test("'commonjs' if package.json found but no `type` property", () => {
|
|
32
|
+
import_memfs.vol.fromJSON({ "package.json": JSON.stringify({}) }, process.cwd());
|
|
33
|
+
expect((0, import_determineModuleType.determineModuleType)()).toBe("commonjs");
|
|
34
|
+
});
|
|
35
|
+
test("'commonjs' if package.json found and `type` property is 'commonjs'", () => {
|
|
36
|
+
import_memfs.vol.fromJSON({ "package.json": JSON.stringify({ type: "commonjs" }) });
|
|
37
|
+
expect((0, import_determineModuleType.determineModuleType)()).toBe("commonjs");
|
|
38
|
+
});
|
|
39
|
+
test("'commonjs' if package.json found and `type` property is invalid", () => {
|
|
40
|
+
import_memfs.vol.fromJSON({ "package.json": JSON.stringify({ type: "invalid-type" }) });
|
|
41
|
+
expect((0, import_determineModuleType.determineModuleType)()).toBe("commonjs");
|
|
42
|
+
});
|
|
43
|
+
test("'module' if package.json found and `type` property is 'module'", () => {
|
|
44
|
+
import_memfs.vol.fromJSON({ "package.json": JSON.stringify({ type: "module" }) });
|
|
45
|
+
expect((0, import_determineModuleType.determineModuleType)()).toBe("module");
|
|
46
|
+
});
|
|
47
|
+
test("finds package.json in parent directories", () => {
|
|
48
|
+
import_memfs.vol.fromJSON({
|
|
49
|
+
"/some/nested/dir/test.txt": "",
|
|
50
|
+
"/package.json": JSON.stringify({ type: "module" })
|
|
51
|
+
});
|
|
52
|
+
expect((0, import_determineModuleType.determineModuleType)("/some/nested/dir")).toBe("module");
|
|
53
|
+
});
|
|
54
|
+
test("supports explicit specification of module type via environment variable", () => {
|
|
55
|
+
process.env.DITTO_MODULE_TYPE = "module";
|
|
56
|
+
expect((0, import_determineModuleType.determineModuleType)()).toBe("module");
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=determineModuleType.test.js.map
|
|
59
|
+
|
|
60
|
+
//# debugId=31410f07-eaa0-59b5-a32b-1c709affaf87
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../lib/utils/determineModuleType.test.ts"],"sourcesContent":["import { determineModuleType } from \"./determineModuleType\";\nimport { vol } from \"memfs\";\n\nconst defaultEnv = process.env;\n\njest.mock(\"fs\");\n\nbeforeEach(() => {\n vol.reset();\n process.env = { ...defaultEnv };\n});\n\ntest(\"'commonjs' if no package.json found\", () => {\n expect(determineModuleType()).toBe(\"commonjs\");\n});\n\ntest(\"'commonjs' if package.json found but no `type` property\", () => {\n vol.fromJSON({ \"package.json\": JSON.stringify({}) }, process.cwd());\n expect(determineModuleType()).toBe(\"commonjs\");\n});\n\ntest(\"'commonjs' if package.json found and `type` property is 'commonjs'\", () => {\n vol.fromJSON({ \"package.json\": JSON.stringify({ type: \"commonjs\" }) });\n expect(determineModuleType()).toBe(\"commonjs\");\n});\n\ntest(\"'commonjs' if package.json found and `type` property is invalid\", () => {\n vol.fromJSON({ \"package.json\": JSON.stringify({ type: \"invalid-type\" }) });\n expect(determineModuleType()).toBe(\"commonjs\");\n});\n\ntest(\"'module' if package.json found and `type` property is 'module'\", () => {\n vol.fromJSON({ \"package.json\": JSON.stringify({ type: \"module\" }) });\n expect(determineModuleType()).toBe(\"module\");\n});\n\ntest(\"finds package.json in parent directories\", () => {\n vol.fromJSON({\n \"/some/nested/dir/test.txt\": \"\",\n \"/package.json\": JSON.stringify({ type: \"module\" }),\n });\n expect(determineModuleType(\"/some/nested/dir\")).toBe(\"module\");\n});\n\ntest(\"supports explicit specification of module type via environment variable\", () => {\n process.env.DITTO_MODULE_TYPE = \"module\";\n expect(determineModuleType()).toBe(\"module\");\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,iCAAoC;AACpC,mBAAoB;AAEpB,MAAM,aAAa,QAAQ;AAE3B,KAAK,KAAK,IAAI;AAEd,WAAW,MAAM;AACf,mBAAI,MAAM;AACV,UAAQ,MAAM,mBAAK;AACrB,CAAC;AAED,KAAK,uCAAuC,MAAM;AAChD,aAAO,gDAAoB,CAAC,EAAE,KAAK,UAAU;AAC/C,CAAC;AAED,KAAK,2DAA2D,MAAM;AACpE,mBAAI,SAAS,EAAE,gBAAgB,KAAK,UAAU,CAAC,CAAC,EAAE,GAAG,QAAQ,IAAI,CAAC;AAClE,aAAO,gDAAoB,CAAC,EAAE,KAAK,UAAU;AAC/C,CAAC;AAED,KAAK,sEAAsE,MAAM;AAC/E,mBAAI,SAAS,EAAE,gBAAgB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC,EAAE,CAAC;AACrE,aAAO,gDAAoB,CAAC,EAAE,KAAK,UAAU;AAC/C,CAAC;AAED,KAAK,mEAAmE,MAAM;AAC5E,mBAAI,SAAS,EAAE,gBAAgB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC,EAAE,CAAC;AACzE,aAAO,gDAAoB,CAAC,EAAE,KAAK,UAAU;AAC/C,CAAC;AAED,KAAK,kEAAkE,MAAM;AAC3E,mBAAI,SAAS,EAAE,gBAAgB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC,EAAE,CAAC;AACnE,aAAO,gDAAoB,CAAC,EAAE,KAAK,QAAQ;AAC7C,CAAC;AAED,KAAK,4CAA4C,MAAM;AACrD,mBAAI,SAAS;AAAA,IACX,6BAA6B;AAAA,IAC7B,iBAAiB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAAA,EACpD,CAAC;AACD,aAAO,gDAAoB,kBAAkB,CAAC,EAAE,KAAK,QAAQ;AAC/D,CAAC;AAED,KAAK,2EAA2E,MAAM;AACpF,UAAQ,IAAI,oBAAoB;AAChC,aAAO,gDAAoB,CAAC,EAAE,KAAK,QAAQ;AAC7C,CAAC","debug_id":"31410f07-eaa0-59b5-a32b-1c709affaf87"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ca926dda-44e3-512a-b95e-05b445329a2e")}catch(e){}}();
|
|
3
3
|
|
|
4
4
|
var __create = Object.create;
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -35,7 +35,7 @@ __export(getSelectedProjects_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(getSelectedProjects_exports);
|
|
37
37
|
var import_js_yaml = __toESM(require("js-yaml"));
|
|
38
|
-
var import_consts = require("../consts");
|
|
38
|
+
var import_consts = __toESM(require("../consts"));
|
|
39
39
|
var import_config = __toESM(require("../config"));
|
|
40
40
|
function jsonIsConfigYAML(json) {
|
|
41
41
|
return typeof json === "object";
|
|
@@ -55,8 +55,8 @@ function yamlToJson(_yaml) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
const getSelectedProjects = (configFile = import_consts.PROJECT_CONFIG_FILE) => import_config.default.parseSourceInformation(configFile).validProjects;
|
|
59
|
-
const getIsUsingComponents = (configFile = import_consts.PROJECT_CONFIG_FILE) => import_config.default.parseSourceInformation(configFile).shouldFetchComponentLibrary;
|
|
58
|
+
const getSelectedProjects = (configFile = import_consts.default.PROJECT_CONFIG_FILE) => import_config.default.parseSourceInformation(configFile).validProjects;
|
|
59
|
+
const getIsUsingComponents = (configFile = import_consts.default.PROJECT_CONFIG_FILE) => import_config.default.parseSourceInformation(configFile).shouldFetchComponentLibrary;
|
|
60
60
|
// Annotate the CommonJS export names for ESM import in node:
|
|
61
61
|
0 && (module.exports = {
|
|
62
62
|
getIsUsingComponents,
|
|
@@ -64,4 +64,4 @@ const getIsUsingComponents = (configFile = import_consts.PROJECT_CONFIG_FILE) =>
|
|
|
64
64
|
});
|
|
65
65
|
//# sourceMappingURL=getSelectedProjects.js.map
|
|
66
66
|
|
|
67
|
-
//# debugId=
|
|
67
|
+
//# debugId=ca926dda-44e3-512a-b95e-05b445329a2e
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../lib/utils/getSelectedProjects.ts"],"sourcesContent":["import fs from \"fs\";\nimport yaml, { YAMLException } from \"js-yaml\";\n\nimport
|
|
1
|
+
{"version":3,"sources":["../../lib/utils/getSelectedProjects.ts"],"sourcesContent":["import fs from \"fs\";\nimport yaml, { YAMLException } from \"js-yaml\";\n\nimport consts from \"../consts\";\nimport { ConfigYAML, Project } from \"../types\";\nimport Config, { DEFAULT_CONFIG_JSON } from \"../config\";\n\nfunction jsonIsConfigYAML(json: unknown): json is ConfigYAML {\n return typeof json === \"object\";\n}\n\nfunction yamlToJson(_yaml: string): ConfigYAML | null {\n try {\n let configYaml = yaml.load(_yaml);\n if (!jsonIsConfigYAML(configYaml)) {\n return {};\n }\n return configYaml;\n } catch (e) {\n if (e instanceof YAMLException) {\n return null;\n } else {\n throw e;\n }\n }\n}\n\n/**\n * Returns an array containing all valid projects ({ id, name })\n * currently contained in the project config file.\n */\nexport const getSelectedProjects = (configFile = consts.PROJECT_CONFIG_FILE) =>\n Config.parseSourceInformation(configFile).validProjects;\n\nexport const getIsUsingComponents = (configFile = consts.PROJECT_CONFIG_FILE) =>\n Config.parseSourceInformation(configFile).shouldFetchComponentLibrary;\n"],"names":["yaml","consts","Config"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,qBAAoC;AAEpC,oBAAmB;AAEnB,oBAA4C;AAE5C,SAAS,iBAAiB,MAAmC;AAC3D,SAAO,OAAO,SAAS;AACzB;AAEA,SAAS,WAAW,OAAkC;AACpD,MAAI;AACF,QAAI,aAAa,eAAAA,QAAK,KAAK,KAAK;AAChC,QAAI,CAAC,iBAAiB,UAAU,GAAG;AACjC,aAAO,CAAC;AAAA,IACV;AACA,WAAO;AAAA,EACT,SAAS,GAAG;AACV,QAAI,aAAa,8BAAe;AAC9B,aAAO;AAAA,IACT,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAMO,MAAM,sBAAsB,CAAC,aAAa,cAAAC,QAAO,wBACtD,cAAAC,QAAO,uBAAuB,UAAU,EAAE;AAErC,MAAM,uBAAuB,CAAC,aAAa,cAAAD,QAAO,wBACvD,cAAAC,QAAO,uBAAuB,UAAU,EAAE","debug_id":"ca926dda-44e3-512a-b95e-05b445329a2e"}
|
package/bin/utils/quit.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="79239749-0258-5746-9b26-d5a38d1e3f33")}catch(e){}}();
|
|
3
3
|
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -28,7 +28,7 @@ function quit(message, exitCode = 2) {
|
|
|
28
28
|
console.log(`
|
|
29
29
|
${message}
|
|
30
30
|
`);
|
|
31
|
-
process.exitCode
|
|
31
|
+
process.exit(exitCode);
|
|
32
32
|
}
|
|
33
33
|
// Annotate the CommonJS export names for ESM import in node:
|
|
34
34
|
0 && (module.exports = {
|
|
@@ -36,4 +36,4 @@ ${message}
|
|
|
36
36
|
});
|
|
37
37
|
//# sourceMappingURL=quit.js.map
|
|
38
38
|
|
|
39
|
-
//# debugId=
|
|
39
|
+
//# debugId=79239749-0258-5746-9b26-d5a38d1e3f33
|
package/bin/utils/quit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../lib/utils/quit.ts"],"sourcesContent":["export function quit(message: string | null, exitCode = 2) {\n if (message) console.log(`\\n${message}\\n`);\n process.exitCode
|
|
1
|
+
{"version":3,"sources":["../../lib/utils/quit.ts"],"sourcesContent":["export function quit(message: string | null, exitCode = 2) {\n if (message) console.log(`\\n${message}\\n`);\n process.exit(exitCode);\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,KAAK,SAAwB,WAAW,GAAG;AACzD,MAAI;AAAS,YAAQ,IAAI;AAAA,EAAK,OAAO;AAAA,CAAI;AACzC,UAAQ,KAAK,QAAQ;AACvB","debug_id":"79239749-0258-5746-9b26-d5a38d1e3f33"}
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Config } from "jest";
|
|
2
|
+
|
|
3
|
+
const config: Config = {
|
|
4
|
+
transformIgnorePatterns: [],
|
|
5
|
+
maxWorkers: 1,
|
|
6
|
+
verbose: true,
|
|
7
|
+
testPathIgnorePatterns: [
|
|
8
|
+
"<rootDir>/node_modules/",
|
|
9
|
+
"<rootDir>/dist/",
|
|
10
|
+
"<rootDir>/bin/",
|
|
11
|
+
],
|
|
12
|
+
watchPathIgnorePatterns: ["<rootDir>/.testing/", "<rootDir>/testing/"],
|
|
13
|
+
collectCoverageFrom: ["lib/**/*.{js,jsx,ts,tsx}"],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default config;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { jest } from "@jest/globals";
|
|
3
|
+
|
|
4
|
+
jest.mock("axios");
|
|
5
|
+
|
|
6
|
+
// by returning the mocked module directly, we can mock responses in tests
|
|
7
|
+
// like `axios.get.mockResolvedValue()`; otherwise, we'd be unable to mock
|
|
8
|
+
// responses because `createApiClient` would be returning an axios instance
|
|
9
|
+
// unaffected by mocks applied to the `axios` module itself.
|
|
10
|
+
export function createApiClient(_token?: string) {
|
|
11
|
+
return axios;
|
|
12
|
+
}
|
package/lib/config.test.ts
CHANGED
|
@@ -5,7 +5,9 @@ import tempy from "tempy";
|
|
|
5
5
|
import yaml from "js-yaml";
|
|
6
6
|
import config from "./config";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
jest.mock("fs");
|
|
9
|
+
|
|
10
|
+
const fakeHomedir = fs.mkdtempSync("/config-testing");
|
|
9
11
|
|
|
10
12
|
describe("Config File", () => {
|
|
11
13
|
const expectedConfigDir = path.join(fakeHomedir, ".config");
|
package/lib/consts.ts
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { homedir } from "os";
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
TEXT_FILE
|
|
20
|
-
|
|
4
|
+
export default new (class {
|
|
5
|
+
get API_HOST() {
|
|
6
|
+
return process.env.DITTO_API_HOST || "https://api.dittowords.com";
|
|
7
|
+
}
|
|
8
|
+
get CONFIG_FILE() {
|
|
9
|
+
return (
|
|
10
|
+
process.env.DITTO_CONFIG_FILE || path.join(homedir(), ".config", "ditto")
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
get PROJECT_CONFIG_FILE() {
|
|
14
|
+
return path.normalize(path.join("ditto", "config.yml"));
|
|
15
|
+
}
|
|
16
|
+
get TEXT_DIR() {
|
|
17
|
+
return process.env.DITTO_TEXT_DIR || "ditto";
|
|
18
|
+
}
|
|
19
|
+
get TEXT_FILE() {
|
|
20
|
+
return path.normalize(path.join(this.TEXT_DIR, "text.json"));
|
|
21
|
+
}
|
|
22
|
+
})();
|
package/lib/ditto.ts
CHANGED
|
@@ -63,6 +63,11 @@ const COMMANDS: CommandConfig<Command>[] = [
|
|
|
63
63
|
{
|
|
64
64
|
name: "pull",
|
|
65
65
|
description: "Sync copy from Ditto into the current working directory",
|
|
66
|
+
flags: {
|
|
67
|
+
"--sample-data": {
|
|
68
|
+
description: "Include sample data. Currently only supports variants.",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
66
71
|
},
|
|
67
72
|
{
|
|
68
73
|
name: "project",
|
|
@@ -210,7 +215,10 @@ const executeCommand = async (
|
|
|
210
215
|
switch (command) {
|
|
211
216
|
case "none":
|
|
212
217
|
case "pull": {
|
|
213
|
-
return pull({
|
|
218
|
+
return pull({
|
|
219
|
+
meta: processMetaOption(meta),
|
|
220
|
+
includeSampleData: options.sampleData || false,
|
|
221
|
+
});
|
|
214
222
|
}
|
|
215
223
|
case "project":
|
|
216
224
|
case "project add": {
|
|
@@ -1,17 +1,31 @@
|
|
|
1
|
-
import fs from "fs
|
|
1
|
+
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { findComponentsInJSXFiles } from "./generate-suggestions";
|
|
4
4
|
|
|
5
|
+
jest.mock("fs");
|
|
6
|
+
|
|
5
7
|
describe("findTextInJSXFiles", () => {
|
|
6
8
|
async function createTempFile(filename: string, content: string) {
|
|
7
|
-
const filePath = path.join("
|
|
8
|
-
await
|
|
9
|
+
const filePath = path.join("/", filename);
|
|
10
|
+
await new Promise((resolve, reject) => {
|
|
11
|
+
try {
|
|
12
|
+
fs.writeFile(filePath, content, () => resolve(null));
|
|
13
|
+
} catch (e) {
|
|
14
|
+
reject(e);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
9
17
|
return filePath;
|
|
10
18
|
}
|
|
11
19
|
|
|
12
20
|
async function deleteTempFile(filename: string) {
|
|
13
|
-
const filePath = path.join("
|
|
14
|
-
await
|
|
21
|
+
const filePath = path.join("/", filename);
|
|
22
|
+
await new Promise((resolve, reject) => {
|
|
23
|
+
try {
|
|
24
|
+
fs.unlink(filePath, resolve);
|
|
25
|
+
} catch (e) {
|
|
26
|
+
reject(e);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
15
29
|
}
|
|
16
30
|
|
|
17
31
|
it("should return an empty obj when no files are found", async () => {
|
|
@@ -74,7 +88,7 @@ describe("findTextInJSXFiles", () => {
|
|
|
74
88
|
};
|
|
75
89
|
|
|
76
90
|
const result = await findComponentsInJSXFiles({
|
|
77
|
-
directory: "
|
|
91
|
+
directory: "/",
|
|
78
92
|
components: {
|
|
79
93
|
"search-string": {
|
|
80
94
|
name: "Search String",
|
|
@@ -119,8 +133,7 @@ describe("findTextInJSXFiles", () => {
|
|
|
119
133
|
};
|
|
120
134
|
|
|
121
135
|
const result = await findComponentsInJSXFiles({
|
|
122
|
-
|
|
123
|
-
files: ["file1.jsx"],
|
|
136
|
+
files: ["/file1.jsx"],
|
|
124
137
|
components: {
|
|
125
138
|
"search-string": {
|
|
126
139
|
name: "Search String",
|
|
@@ -134,9 +147,8 @@ describe("findTextInJSXFiles", () => {
|
|
|
134
147
|
expect(result).toEqual(expectedResult);
|
|
135
148
|
|
|
136
149
|
try {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
files: ["file2.jsx"],
|
|
150
|
+
await findComponentsInJSXFiles({
|
|
151
|
+
files: ["/file2.jsx"],
|
|
140
152
|
components: {
|
|
141
153
|
"search-string": {
|
|
142
154
|
name: "Search String",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs from "fs
|
|
1
|
+
import fs from "fs";
|
|
2
2
|
import glob from "glob";
|
|
3
3
|
import { parse } from "@babel/parser";
|
|
4
4
|
import traverse from "@babel/traverse";
|
|
@@ -43,11 +43,14 @@ async function generateSuggestions(flags: {
|
|
|
43
43
|
console.log(JSON.stringify(results, null, 2));
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
async function findComponentsInJSXFiles(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
async function findComponentsInJSXFiles(
|
|
47
|
+
params: (
|
|
48
|
+
| { directory: string; files?: string[] }
|
|
49
|
+
| { files: string[]; directory?: string }
|
|
50
|
+
) & {
|
|
51
|
+
components: FetchComponentResponse;
|
|
52
|
+
}
|
|
53
|
+
): Promise<{ [apiId: string]: Result }> {
|
|
51
54
|
const result: { [apiId: string]: Result } = {};
|
|
52
55
|
const files =
|
|
53
56
|
params.files ||
|
|
@@ -57,83 +60,90 @@ async function findComponentsInJSXFiles(params: {
|
|
|
57
60
|
|
|
58
61
|
const promises: Promise<any>[] = [];
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
fs.readFile(file, "utf-8"
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
result[compApiId] = {
|
|
76
|
-
apiId: compApiId,
|
|
77
|
-
...component,
|
|
78
|
-
occurrences: {},
|
|
79
|
-
};
|
|
80
|
-
}
|
|
63
|
+
async function handleFile(file: string) {
|
|
64
|
+
const code = await new Promise<string>((resolve, reject) =>
|
|
65
|
+
fs.readFile(file, "utf-8", (err, data) => {
|
|
66
|
+
if (err) {
|
|
67
|
+
reject(err);
|
|
68
|
+
} else {
|
|
69
|
+
resolve(data);
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const ast = parse(code, {
|
|
75
|
+
sourceType: "module",
|
|
76
|
+
plugins: ["jsx", "typescript"],
|
|
77
|
+
});
|
|
81
78
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
// Initialize the occurrences array if it doesn't exist
|
|
117
|
-
if (!result[compApiId]["occurrences"][file]) {
|
|
118
|
-
result[compApiId]["occurrences"][file] = [];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
result[compApiId]["occurrences"][file].push({
|
|
122
|
-
lineNumber,
|
|
123
|
-
preview,
|
|
124
|
-
});
|
|
125
|
-
}
|
|
79
|
+
traverse(ast, {
|
|
80
|
+
JSXText(path) {
|
|
81
|
+
for (const [compApiId, component] of Object.entries(
|
|
82
|
+
params.components
|
|
83
|
+
)) {
|
|
84
|
+
// If we haven't seen this component before, add it to the result
|
|
85
|
+
if (!result[compApiId]) {
|
|
86
|
+
result[compApiId] = {
|
|
87
|
+
apiId: compApiId,
|
|
88
|
+
...component,
|
|
89
|
+
occurrences: {},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (
|
|
94
|
+
// Skip white space lines
|
|
95
|
+
!/^\s*$/.test(path.node.value) &&
|
|
96
|
+
!/^\s*$/.test(component.text) &&
|
|
97
|
+
path.node.value.includes(component.text)
|
|
98
|
+
) {
|
|
99
|
+
// Escape all special characters from the text so we can use it in a regex
|
|
100
|
+
const escapedText = component.text.replace(
|
|
101
|
+
/[.*+?^${}()|[\]\\]/g,
|
|
102
|
+
"\\$&"
|
|
103
|
+
);
|
|
104
|
+
const regex = new RegExp(escapedText, "g");
|
|
105
|
+
let match;
|
|
106
|
+
while ((match = regex.exec(path.node.value)) !== null) {
|
|
107
|
+
const lines = path.node.value.slice(0, match.index).split("\n");
|
|
108
|
+
|
|
109
|
+
if (!path.node.loc) {
|
|
110
|
+
continue;
|
|
126
111
|
}
|
|
127
112
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
113
|
+
const lineNumber = path.node.loc.start.line + lines.length - 1;
|
|
114
|
+
|
|
115
|
+
const codeLines = code.split("\n");
|
|
116
|
+
const line = codeLines[lineNumber - 1];
|
|
117
|
+
const preview = replaceAt(
|
|
118
|
+
line,
|
|
119
|
+
match.index,
|
|
120
|
+
component.text,
|
|
121
|
+
`${component.text}`
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// Initialize the occurrences array if it doesn't exist
|
|
125
|
+
if (!result[compApiId]["occurrences"][file]) {
|
|
126
|
+
result[compApiId]["occurrences"][file] = [];
|
|
131
127
|
}
|
|
128
|
+
|
|
129
|
+
result[compApiId]["occurrences"][file].push({
|
|
130
|
+
lineNumber,
|
|
131
|
+
preview,
|
|
132
|
+
});
|
|
132
133
|
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Remove from result if no occurrences were found
|
|
137
|
+
if (Object.keys(result[compApiId]["occurrences"]).length === 0) {
|
|
138
|
+
delete result[compApiId];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
for (const file of files) {
|
|
146
|
+
promises.push(handleFile(file));
|
|
137
147
|
}
|
|
138
148
|
|
|
139
149
|
await Promise.all(promises);
|
|
@@ -145,7 +155,7 @@ function replaceAt(
|
|
|
145
155
|
str: string,
|
|
146
156
|
index: number,
|
|
147
157
|
searchString: string,
|
|
148
|
-
replacement: string
|
|
158
|
+
replacement: string
|
|
149
159
|
) {
|
|
150
160
|
return (
|
|
151
161
|
str.substring(0, index) +
|