@dittowords/cli 3.2.2-alpha → 3.3.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.
- package/bin/ditto.js +31 -15
- package/bin/ditto.js.map +1 -1
- package/bin/generate-suggestions.js +19 -10
- package/bin/generate-suggestions.js.map +1 -1
- package/bin/http/fetchComponents.js.map +1 -1
- package/bin/replace.js +9 -3
- package/bin/replace.js.map +1 -1
- package/lib/ditto.ts +48 -13
- package/lib/generate-suggestions.test.ts +25 -24
- package/lib/generate-suggestions.ts +41 -24
- package/lib/http/fetchComponents.ts +12 -1
- package/lib/replace.test.ts +22 -3
- package/lib/replace.ts +15 -3
- package/package.json +1 -1
- package/testfiles/test1.jsx +18 -0
- package/testfiles/test2.jsx +9 -0
- package/bin/lib/add-project.js +0 -36
- package/bin/lib/add-project.js.map +0 -1
- package/bin/lib/api.js +0 -20
- package/bin/lib/api.js.map +0 -1
- package/bin/lib/config.js +0 -202
- package/bin/lib/config.js.map +0 -1
- package/bin/lib/consts.js +0 -21
- package/bin/lib/consts.js.map +0 -1
- package/bin/lib/ditto.js +0 -121
- package/bin/lib/ditto.js.map +0 -1
- package/bin/lib/generate-suggestions.js +0 -71
- package/bin/lib/generate-suggestions.js.map +0 -1
- package/bin/lib/http/fetchComponents.js +0 -13
- package/bin/lib/http/fetchComponents.js.map +0 -1
- package/bin/lib/http/fetchVariants.js +0 -26
- package/bin/lib/http/fetchVariants.js.map +0 -1
- package/bin/lib/init/init.js +0 -50
- package/bin/lib/init/init.js.map +0 -1
- package/bin/lib/init/project.js +0 -108
- package/bin/lib/init/project.js.map +0 -1
- package/bin/lib/init/token.js +0 -91
- package/bin/lib/init/token.js.map +0 -1
- package/bin/lib/output.js +0 -34
- package/bin/lib/output.js.map +0 -1
- package/bin/lib/pull.js +0 -264
- package/bin/lib/pull.js.map +0 -1
- package/bin/lib/remove-project.js +0 -35
- package/bin/lib/remove-project.js.map +0 -1
- package/bin/lib/replace.js +0 -107
- package/bin/lib/replace.js.map +0 -1
- package/bin/lib/types.js +0 -3
- package/bin/lib/types.js.map +0 -1
- package/bin/lib/utils/cleanFileName.js +0 -11
- package/bin/lib/utils/cleanFileName.js.map +0 -1
- package/bin/lib/utils/generateJsDriver.js +0 -56
- package/bin/lib/utils/generateJsDriver.js.map +0 -1
- package/bin/lib/utils/getSelectedProjects.js +0 -61
- package/bin/lib/utils/getSelectedProjects.js.map +0 -1
- package/bin/lib/utils/processMetaOption.js +0 -15
- package/bin/lib/utils/processMetaOption.js.map +0 -1
- package/bin/lib/utils/projectsToText.js +0 -25
- package/bin/lib/utils/projectsToText.js.map +0 -1
- package/bin/lib/utils/promptForProject.js +0 -43
- package/bin/lib/utils/promptForProject.js.map +0 -1
- package/bin/lib/utils/quit.js +0 -10
- package/bin/lib/utils/quit.js.map +0 -1
- package/bin/lib/utils/sourcesToText.js +0 -25
- package/bin/lib/utils/sourcesToText.js.map +0 -1
- package/bin/package.json +0 -76
package/bin/ditto.js
CHANGED
|
@@ -8,8 +8,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
8
8
|
const commander_1 = require("commander");
|
|
9
9
|
// to use V8's code cache to speed up instantiation time
|
|
10
10
|
require("v8-compile-cache");
|
|
11
|
-
const fs_1 = __importDefault(require("fs"));
|
|
12
|
-
const path_1 = __importDefault(require("path"));
|
|
13
11
|
const init_1 = require("./init/init");
|
|
14
12
|
const pull_1 = require("./pull");
|
|
15
13
|
const quit_1 = require("./utils/quit");
|
|
@@ -18,14 +16,6 @@ const remove_project_1 = __importDefault(require("./remove-project"));
|
|
|
18
16
|
const replace_1 = require("./replace");
|
|
19
17
|
const generate_suggestions_1 = require("./generate-suggestions");
|
|
20
18
|
const processMetaOption_1 = __importDefault(require("./utils/processMetaOption"));
|
|
21
|
-
function getVersion() {
|
|
22
|
-
const packageJsonPath = path_1.default.join(__dirname, "..", "package.json");
|
|
23
|
-
const packageJsonContent = fs_1.default.readFileSync(packageJsonPath, "utf8");
|
|
24
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
25
|
-
const version = packageJson.version;
|
|
26
|
-
return version;
|
|
27
|
-
}
|
|
28
|
-
const VERSION = getVersion();
|
|
29
19
|
const COMMANDS = [
|
|
30
20
|
{
|
|
31
21
|
name: "pull",
|
|
@@ -48,10 +38,21 @@ const COMMANDS = [
|
|
|
48
38
|
{
|
|
49
39
|
name: "generate-suggestions",
|
|
50
40
|
description: "Find text that can be potentially replaced with Ditto text",
|
|
41
|
+
flags: {
|
|
42
|
+
"-d, --directory [value]": {
|
|
43
|
+
description: "Directory to search for text",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
51
46
|
},
|
|
52
47
|
{
|
|
53
48
|
name: "replace",
|
|
54
49
|
description: "Find and replace Ditto text with code",
|
|
50
|
+
flags: {
|
|
51
|
+
"-ln, --line-numbers [value]": {
|
|
52
|
+
description: "Only replace text on a specific line number",
|
|
53
|
+
processor: (value) => value.split(",").map(Number),
|
|
54
|
+
},
|
|
55
|
+
},
|
|
55
56
|
},
|
|
56
57
|
];
|
|
57
58
|
const setupCommands = () => {
|
|
@@ -60,8 +61,20 @@ const setupCommands = () => {
|
|
|
60
61
|
const cmd = commander_1.program
|
|
61
62
|
.command(commandConfig.name)
|
|
62
63
|
.description(commandConfig.description)
|
|
63
|
-
.action((
|
|
64
|
-
|
|
64
|
+
.action((options) => {
|
|
65
|
+
return executeCommand(commandConfig.name, options);
|
|
66
|
+
});
|
|
67
|
+
if (commandConfig.flags) {
|
|
68
|
+
Object.entries(commandConfig.flags).forEach(([flags, { description, processor }]) => {
|
|
69
|
+
if (processor) {
|
|
70
|
+
cmd.option(flags, description, processor);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
cmd.option(flags, description);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if ("commands" in commandConfig && commandConfig.commands) {
|
|
65
78
|
commandConfig.commands.forEach((nestedCommand) => {
|
|
66
79
|
cmd
|
|
67
80
|
.command(nestedCommand.name)
|
|
@@ -73,7 +86,6 @@ const setupCommands = () => {
|
|
|
73
86
|
};
|
|
74
87
|
const setupOptions = () => {
|
|
75
88
|
commander_1.program.option("-m, --meta <data...>", "Include arbitrary data in requests to the Ditto API. Ex: -m githubActionRequest:true trigger:manual");
|
|
76
|
-
commander_1.program.version(VERSION, "-v, --version", "Output the current version");
|
|
77
89
|
};
|
|
78
90
|
const executeCommand = async (command, options) => {
|
|
79
91
|
const needsInitialization = (0, init_1.needsTokenOrSource)();
|
|
@@ -105,10 +117,14 @@ const executeCommand = async (command, options) => {
|
|
|
105
117
|
return (0, remove_project_1.default)();
|
|
106
118
|
}
|
|
107
119
|
case "generate-suggestions": {
|
|
108
|
-
return (0, generate_suggestions_1.generateSuggestions)(
|
|
120
|
+
return (0, generate_suggestions_1.generateSuggestions)({
|
|
121
|
+
...(options.directory ? { directory: options.directory } : {}),
|
|
122
|
+
});
|
|
109
123
|
}
|
|
110
124
|
case "replace": {
|
|
111
|
-
return (0, replace_1.replace)(options
|
|
125
|
+
return (0, replace_1.replace)(options.args, {
|
|
126
|
+
...(options.lineNumbers ? { lineNumbers: options.lineNumbers } : {}),
|
|
127
|
+
});
|
|
112
128
|
}
|
|
113
129
|
default: {
|
|
114
130
|
(0, quit_1.quit)("Exiting Ditto CLI...");
|
package/bin/ditto.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ditto.js","sourceRoot":"","sources":["../lib/ditto.ts"],"names":[],"mappings":";;;;;;AACA,0DAA0D;AAC1D,yCAAoC;AACpC,wDAAwD;AACxD,4BAA0B;
|
|
1
|
+
{"version":3,"file":"ditto.js","sourceRoot":"","sources":["../lib/ditto.ts"],"names":[],"mappings":";;;;;;AACA,0DAA0D;AAC1D,yCAAoC;AACpC,wDAAwD;AACxD,4BAA0B;AAE1B,sCAAuD;AACvD,iCAA8B;AAC9B,uCAAoC;AACpC,gEAAuC;AACvC,sEAA6C;AAC7C,uCAAoC;AACpC,iEAA6D;AAE7D,kFAA0D;AAsB1D,MAAM,QAAQ,GAA6B;IACzC;QACE,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,yDAAyD;KACvE;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,uCAAuC;QACpD,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,KAAK;gBACX,WAAW,EAAE,uCAAuC;aACrD;YACD;gBACE,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,wCAAwC;aACtD;SACF;KACF;IACD;QACE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,4DAA4D;QACzE,KAAK,EAAE;YACL,yBAAyB,EAAE;gBACzB,WAAW,EAAE,8BAA8B;aAC5C;SACF;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,uCAAuC;QACpD,KAAK,EAAE;YACL,6BAA6B,EAAE;gBAC7B,WAAW,EAAE,6CAA6C;gBAC1D,SAAS,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;aAC3D;SACF;KACF;CACF,CAAC;AAEF,MAAM,aAAa,GAAG,GAAG,EAAE;IACzB,mBAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAE1B,QAAQ,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE;QACjC,MAAM,GAAG,GAAG,mBAAO;aAChB,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC;aAC3B,WAAW,CAAC,aAAa,CAAC,WAAW,CAAC;aACtC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;YAClB,OAAO,cAAc,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEL,IAAI,aAAa,CAAC,KAAK,EAAE;YACvB,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,OAAO,CACzC,CAAC,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE;gBACtC,IAAI,SAAS,EAAE;oBACb,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;iBAC3C;qBAAM;oBACL,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;iBAChC;YACH,CAAC,CACF,CAAC;SACH;QAED,IAAI,UAAU,IAAI,aAAa,IAAI,aAAa,CAAC,QAAQ,EAAE;YACzD,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE;gBAC/C,GAAG;qBACA,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC;qBAC3B,WAAW,CAAC,aAAa,CAAC,WAAW,CAAC;qBACtC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CACvB,cAAc,CACZ,GAAG,aAAa,CAAC,IAAI,IAAI,aAAa,CAAC,IAAI,EAAE,EAC7C,OAAO,CACR,CACF,CAAC;YACN,CAAC,CAAC,CAAC;SACJ;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,GAAG,EAAE;IACxB,mBAAO,CAAC,MAAM,CACZ,sBAAsB,EACtB,qGAAqG,CACtG,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,KAAK,EAC1B,OAAyB,EACzB,OAAY,EACG,EAAE;IACjB,MAAM,mBAAmB,GAAG,IAAA,yBAAkB,GAAE,CAAC;IACjD,IAAI,mBAAmB,EAAE;QACvB,IAAI;YACF,MAAM,IAAA,WAAI,GAAE,CAAC;SACd;QAAC,OAAO,KAAK,EAAE;YACd,IAAA,WAAI,EAAC,sBAAsB,CAAC,CAAC;YAC7B,OAAO;SACR;KACF;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,mBAAO,CAAC,IAAI,EAAE,CAAC;IAChC,QAAQ,OAAO,EAAE;QACf,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC,CAAC;YACX,OAAO,IAAA,WAAI,EAAC,EAAE,IAAI,EAAE,IAAA,2BAAiB,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SAChD;QACD,KAAK,SAAS,CAAC;QACf,KAAK,aAAa,CAAC,CAAC;YAClB,6DAA6D;YAC7D,6DAA6D;YAC7D,2CAA2C;YAC3C,IAAI,mBAAmB;gBAAE,OAAO;YAEhC,OAAO,IAAA,qBAAU,GAAE,CAAC;SACrB;QACD,KAAK,gBAAgB,CAAC,CAAC;YACrB,OAAO,IAAA,wBAAa,GAAE,CAAC;SACxB;QACD,KAAK,sBAAsB,CAAC,CAAC;YAC3B,OAAO,IAAA,0CAAmB,EAAC;gBACzB,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/D,CAAC,CAAC;SACJ;QACD,KAAK,SAAS,CAAC,CAAC;YACd,OAAO,IAAA,iBAAO,EAAC,OAAO,CAAC,IAAI,EAAE;gBAC3B,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACrE,CAAC,CAAC;SACJ;QACD,OAAO,CAAC,CAAC;YACP,IAAA,WAAI,EAAC,sBAAsB,CAAC,CAAC;YAC7B,OAAO;SACR;KACF;AACH,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;IACtB,aAAa,EAAE,CAAC;IAChB,YAAY,EAAE,CAAC;IAEf,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrE,MAAM,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACjC,OAAO;KACR;IAED,mBAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC"}
|
|
@@ -9,27 +9,33 @@ const glob_1 = __importDefault(require("glob"));
|
|
|
9
9
|
const parser_1 = require("@babel/parser");
|
|
10
10
|
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
11
11
|
const fetchComponents_1 = require("./http/fetchComponents");
|
|
12
|
-
async function generateSuggestions() {
|
|
12
|
+
async function generateSuggestions(flags) {
|
|
13
13
|
const components = await (0, fetchComponents_1.fetchComponents)();
|
|
14
14
|
const results = {};
|
|
15
15
|
for (const [compApiId, component] of Object.entries(components)) {
|
|
16
16
|
if (!results[compApiId]) {
|
|
17
|
-
results[compApiId] =
|
|
17
|
+
results[compApiId] = { apiId: compApiId, ...component, occurrences: {} };
|
|
18
|
+
}
|
|
19
|
+
const directory = flags.directory || ".";
|
|
20
|
+
const result = await findTextInJSXFiles(directory, component);
|
|
21
|
+
results[compApiId].occurrences = result;
|
|
22
|
+
// Remove if there the length is zero
|
|
23
|
+
if (Object.keys(results[compApiId].occurrences).length === 0) {
|
|
24
|
+
delete results[compApiId];
|
|
18
25
|
}
|
|
19
|
-
const result = await findTextInJSXFiles(".", component.text);
|
|
20
|
-
results[compApiId] = [...results[compApiId], ...result];
|
|
21
26
|
}
|
|
22
27
|
// Display results to user
|
|
23
28
|
console.log(JSON.stringify(results, null, 2));
|
|
24
29
|
}
|
|
25
30
|
exports.generateSuggestions = generateSuggestions;
|
|
26
|
-
async function findTextInJSXFiles(path,
|
|
27
|
-
const result =
|
|
31
|
+
async function findTextInJSXFiles(path, component) {
|
|
32
|
+
const result = {};
|
|
28
33
|
const files = glob_1.default.sync(`${path}/**/*.+(jsx|tsx)`, {
|
|
29
34
|
ignore: "**/node_modules/**",
|
|
30
35
|
});
|
|
31
36
|
const promises = [];
|
|
32
37
|
for (const file of files) {
|
|
38
|
+
result[file] = [];
|
|
33
39
|
promises.push(fs_extra_1.default.readFile(file, "utf-8").then((code) => {
|
|
34
40
|
const ast = (0, parser_1.parse)(code, {
|
|
35
41
|
sourceType: "module",
|
|
@@ -38,8 +44,8 @@ async function findTextInJSXFiles(path, searchString) {
|
|
|
38
44
|
const occurrences = [];
|
|
39
45
|
(0, traverse_1.default)(ast, {
|
|
40
46
|
JSXText(path) {
|
|
41
|
-
if (path.node.value.includes(
|
|
42
|
-
const regex = new RegExp(
|
|
47
|
+
if (path.node.value.includes(component.text)) {
|
|
48
|
+
const regex = new RegExp(component.text, "g");
|
|
43
49
|
let match;
|
|
44
50
|
while ((match = regex.exec(path.node.value)) !== null) {
|
|
45
51
|
const lines = path.node.value.slice(0, match.index).split("\n");
|
|
@@ -49,14 +55,17 @@ async function findTextInJSXFiles(path, searchString) {
|
|
|
49
55
|
const lineNumber = path.node.loc.start.line + lines.length - 1;
|
|
50
56
|
const codeLines = code.split("\n");
|
|
51
57
|
const line = codeLines[lineNumber - 1];
|
|
52
|
-
const preview = replaceAt(line, match.index,
|
|
58
|
+
const preview = replaceAt(line, match.index, component.text, `${component.text}`);
|
|
53
59
|
occurrences.push({ lineNumber, preview });
|
|
54
60
|
}
|
|
55
61
|
}
|
|
56
62
|
},
|
|
57
63
|
});
|
|
58
64
|
if (occurrences.length > 0) {
|
|
59
|
-
result
|
|
65
|
+
result[file] = occurrences;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
delete result[file];
|
|
60
69
|
}
|
|
61
70
|
}));
|
|
62
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-suggestions.js","sourceRoot":"","sources":["../lib/generate-suggestions.ts"],"names":[],"mappings":";;;;;;AAAA,wDAA0B;AAC1B,gDAAwB;AACxB,0CAAsC;AACtC,+DAAuC;AAEvC,
|
|
1
|
+
{"version":3,"file":"generate-suggestions.js","sourceRoot":"","sources":["../lib/generate-suggestions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetchComponents.js","sourceRoot":"","sources":["../../lib/http/fetchComponents.ts"],"names":[],"mappings":";;;;;;AAAA,iDAAyB;
|
|
1
|
+
{"version":3,"file":"fetchComponents.js","sourceRoot":"","sources":["../../lib/http/fetchComponents.ts"],"names":[],"mappings":";;;;;;AAAA,iDAAyB;AAalB,KAAK,UAAU,eAAe;IACnC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,aAAG,CAAC,GAAG,CAO3B,aAAa,EAAE,EAAE,CAAC,CAAC;IAEtB,OAAO,IAAI,CAAC;AACd,CAAC;AAXD,0CAWC"}
|
package/bin/replace.js
CHANGED
|
@@ -32,7 +32,7 @@ const parser_1 = require("@babel/parser");
|
|
|
32
32
|
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
33
33
|
const t = __importStar(require("@babel/types"));
|
|
34
34
|
const core_1 = require("@babel/core");
|
|
35
|
-
async function replaceJSXTextInFile(filePath, replacement) {
|
|
35
|
+
async function replaceJSXTextInFile(filePath, replacement, flags) {
|
|
36
36
|
const code = await fs_extra_1.default.readFile(filePath, "utf-8");
|
|
37
37
|
const ast = (0, parser_1.parse)(code, {
|
|
38
38
|
sourceType: "module",
|
|
@@ -43,6 +43,12 @@ async function replaceJSXTextInFile(filePath, replacement) {
|
|
|
43
43
|
const { searchString, replaceWith } = replacement;
|
|
44
44
|
const regex = new RegExp(searchString, "gi");
|
|
45
45
|
if (regex.test(path.node.value)) {
|
|
46
|
+
// Ignore if not on a line number that we want to replace.
|
|
47
|
+
if (flags.lineNumbers &&
|
|
48
|
+
path.node.loc &&
|
|
49
|
+
!flags.lineNumbers.includes(path.node.loc.start.line)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
46
52
|
const splitValues = splitByCaseInsensitive(path.node.value, searchString);
|
|
47
53
|
const nodes = [];
|
|
48
54
|
splitValues.forEach((splitValue) => {
|
|
@@ -73,7 +79,7 @@ exports.replaceJSXTextInFile = replaceJSXTextInFile;
|
|
|
73
79
|
function splitByCaseInsensitive(str, delimiter) {
|
|
74
80
|
return str.split(new RegExp(`(${delimiter})`, "gi")).filter((s) => s !== "");
|
|
75
81
|
}
|
|
76
|
-
function replace(options) {
|
|
82
|
+
function replace(options, flags) {
|
|
77
83
|
let filePath;
|
|
78
84
|
let searchString;
|
|
79
85
|
let replaceWith;
|
|
@@ -88,7 +94,7 @@ function replace(options) {
|
|
|
88
94
|
console.error("Usage for replace: ditto-cli replace <file path> <search string> <replace with>");
|
|
89
95
|
return;
|
|
90
96
|
}
|
|
91
|
-
replaceJSXTextInFile(filePath, { searchString, replaceWith });
|
|
97
|
+
replaceJSXTextInFile(filePath, { searchString, replaceWith }, flags);
|
|
92
98
|
}
|
|
93
99
|
exports.replace = replace;
|
|
94
100
|
function parseOptions(options) {
|
package/bin/replace.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace.js","sourceRoot":"","sources":["../lib/replace.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wDAA0B;AAC1B,0CAAsC;AACtC,+DAAuC;AACvC,gDAAkC;AAClC,sCAA+C;AAE/C,KAAK,UAAU,oBAAoB,CACjC,QAAgB,EAChB,WAA0D;
|
|
1
|
+
{"version":3,"file":"replace.js","sourceRoot":"","sources":["../lib/replace.ts"],"names":[],"mappings":"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"}
|
package/lib/ditto.ts
CHANGED
|
@@ -35,7 +35,16 @@ type Command =
|
|
|
35
35
|
| "generate-suggestions"
|
|
36
36
|
| "replace";
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
interface CommandConfig<T extends Command | "add" | "remove"> {
|
|
39
|
+
name: T;
|
|
40
|
+
description: string;
|
|
41
|
+
commands?: CommandConfig<"add" | "remove">[];
|
|
42
|
+
flags?: {
|
|
43
|
+
[flag: string]: { description: string; processor?: (value: string) => any };
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const COMMANDS: CommandConfig<Command>[] = [
|
|
39
48
|
{
|
|
40
49
|
name: "pull",
|
|
41
50
|
description: "Sync copy from Ditto into the current working directory",
|
|
@@ -57,12 +66,23 @@ const COMMANDS = [
|
|
|
57
66
|
{
|
|
58
67
|
name: "generate-suggestions",
|
|
59
68
|
description: "Find text that can be potentially replaced with Ditto text",
|
|
69
|
+
flags: {
|
|
70
|
+
"-d, --directory [value]": {
|
|
71
|
+
description: "Directory to search for text",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
60
74
|
},
|
|
61
75
|
{
|
|
62
76
|
name: "replace",
|
|
63
77
|
description: "Find and replace Ditto text with code",
|
|
78
|
+
flags: {
|
|
79
|
+
"-ln, --line-numbers [value]": {
|
|
80
|
+
description: "Only replace text on a specific line number",
|
|
81
|
+
processor: (value: string) => value.split(",").map(Number),
|
|
82
|
+
},
|
|
83
|
+
},
|
|
64
84
|
},
|
|
65
|
-
]
|
|
85
|
+
];
|
|
66
86
|
|
|
67
87
|
const setupCommands = () => {
|
|
68
88
|
program.name("ditto-cli");
|
|
@@ -71,19 +91,30 @@ const setupCommands = () => {
|
|
|
71
91
|
const cmd = program
|
|
72
92
|
.command(commandConfig.name)
|
|
73
93
|
.description(commandConfig.description)
|
|
74
|
-
.action((
|
|
94
|
+
.action((options) => {
|
|
95
|
+
return executeCommand(commandConfig.name, options);
|
|
96
|
+
});
|
|
75
97
|
|
|
76
|
-
if (
|
|
98
|
+
if (commandConfig.flags) {
|
|
99
|
+
Object.entries(commandConfig.flags).forEach(
|
|
100
|
+
([flags, { description, processor }]) => {
|
|
101
|
+
cmd.option(flags, description, processor);
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if ("commands" in commandConfig && commandConfig.commands) {
|
|
77
107
|
commandConfig.commands.forEach((nestedCommand) => {
|
|
78
108
|
cmd
|
|
79
109
|
.command(nestedCommand.name)
|
|
80
110
|
.description(nestedCommand.description)
|
|
81
|
-
.action((str, options) =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
111
|
+
.action((str, options) => {
|
|
112
|
+
if (commandConfig.name === "project") {
|
|
113
|
+
const command =
|
|
114
|
+
`${commandConfig.name} ${nestedCommand.name}` as Command;
|
|
115
|
+
return executeCommand(command, options);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
87
118
|
});
|
|
88
119
|
}
|
|
89
120
|
});
|
|
@@ -99,7 +130,7 @@ const setupOptions = () => {
|
|
|
99
130
|
|
|
100
131
|
const executeCommand = async (
|
|
101
132
|
command: Command | "none",
|
|
102
|
-
options:
|
|
133
|
+
options: any
|
|
103
134
|
): Promise<void> => {
|
|
104
135
|
const needsInitialization = needsTokenOrSource();
|
|
105
136
|
if (needsInitialization) {
|
|
@@ -130,10 +161,14 @@ const executeCommand = async (
|
|
|
130
161
|
return removeProject();
|
|
131
162
|
}
|
|
132
163
|
case "generate-suggestions": {
|
|
133
|
-
return generateSuggestions(
|
|
164
|
+
return generateSuggestions({
|
|
165
|
+
...(options.directory ? { directory: options.directory } : {}),
|
|
166
|
+
});
|
|
134
167
|
}
|
|
135
168
|
case "replace": {
|
|
136
|
-
return replace(options
|
|
169
|
+
return replace(options.args, {
|
|
170
|
+
...(options?.lineNumbers ? { lineNumbers: options.lineNumbers } : {}),
|
|
171
|
+
});
|
|
137
172
|
}
|
|
138
173
|
default: {
|
|
139
174
|
quit("Exiting Ditto CLI...");
|
|
@@ -14,19 +14,23 @@ describe("findTextInJSXFiles", () => {
|
|
|
14
14
|
await fs.unlink(filePath);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
it("should return an empty
|
|
18
|
-
const result = await findTextInJSXFiles(".",
|
|
17
|
+
it("should return an empty obj when no files are found", async () => {
|
|
18
|
+
const result = await findTextInJSXFiles(".", {
|
|
19
|
+
text: "searchString",
|
|
20
|
+
} as any);
|
|
19
21
|
|
|
20
|
-
expect(result).toEqual(
|
|
22
|
+
expect(result).toEqual({});
|
|
21
23
|
});
|
|
22
24
|
|
|
23
|
-
it("should return an empty
|
|
25
|
+
it("should return an empty obj when searchString is not found in any file", async () => {
|
|
24
26
|
const file1 = await createTempFile("file1.jsx", "<div>No match</div>");
|
|
25
27
|
const file2 = await createTempFile("file2.tsx", "<div>No match</div>");
|
|
26
28
|
|
|
27
|
-
const result = await findTextInJSXFiles(".",
|
|
29
|
+
const result = await findTextInJSXFiles(".", {
|
|
30
|
+
text: "searchString",
|
|
31
|
+
} as any);
|
|
28
32
|
|
|
29
|
-
expect(result).toEqual(
|
|
33
|
+
expect(result).toEqual({});
|
|
30
34
|
|
|
31
35
|
await deleteTempFile(file1);
|
|
32
36
|
await deleteTempFile(file2);
|
|
@@ -38,25 +42,22 @@ describe("findTextInJSXFiles", () => {
|
|
|
38
42
|
`<div>Test searchString and another searchString</div>`
|
|
39
43
|
);
|
|
40
44
|
|
|
41
|
-
const expectedResult =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"<div>Test searchString and another {{searchString}}</div>",
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
},
|
|
57
|
-
];
|
|
45
|
+
const expectedResult = {
|
|
46
|
+
[file1]: [
|
|
47
|
+
{
|
|
48
|
+
lineNumber: 1,
|
|
49
|
+
preview: "<div>Test searchString and another searchString</div>",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
lineNumber: 1,
|
|
53
|
+
preview: "<div>Test searchString and another searchString</div>",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
|
58
57
|
|
|
59
|
-
const result = await findTextInJSXFiles(".",
|
|
58
|
+
const result = await findTextInJSXFiles(".", {
|
|
59
|
+
text: "searchString",
|
|
60
|
+
} as any);
|
|
60
61
|
|
|
61
62
|
expect(result).toEqual(expectedResult);
|
|
62
63
|
|
|
@@ -3,38 +3,51 @@ import glob from "glob";
|
|
|
3
3
|
import { parse } from "@babel/parser";
|
|
4
4
|
import traverse from "@babel/traverse";
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
FetchComponentResponseComponent,
|
|
8
|
+
fetchComponents,
|
|
9
|
+
} from "./http/fetchComponents";
|
|
10
|
+
|
|
11
|
+
interface Result extends FetchComponentResponseComponent {
|
|
12
|
+
apiId: string;
|
|
13
|
+
occurrences: {
|
|
14
|
+
[file: string]: Occurrence[];
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface Occurrence {
|
|
19
|
+
lineNumber: number;
|
|
20
|
+
preview: string;
|
|
21
|
+
}
|
|
7
22
|
|
|
8
|
-
async function generateSuggestions() {
|
|
23
|
+
async function generateSuggestions(flags: { directory?: string }) {
|
|
9
24
|
const components = await fetchComponents();
|
|
10
|
-
const results: {
|
|
11
|
-
[compApiId: string]: FindResults;
|
|
12
|
-
} = {};
|
|
25
|
+
const results: { [apiId: string]: Result } = {};
|
|
13
26
|
|
|
14
27
|
for (const [compApiId, component] of Object.entries(components)) {
|
|
15
28
|
if (!results[compApiId]) {
|
|
16
|
-
results[compApiId] =
|
|
29
|
+
results[compApiId] = { apiId: compApiId, ...component, occurrences: {} };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const directory = flags.directory || ".";
|
|
33
|
+
const result = await findTextInJSXFiles(directory, component);
|
|
34
|
+
results[compApiId].occurrences = result;
|
|
35
|
+
|
|
36
|
+
// Remove if there the length is zero
|
|
37
|
+
if (Object.keys(results[compApiId].occurrences).length === 0) {
|
|
38
|
+
delete results[compApiId];
|
|
17
39
|
}
|
|
18
|
-
const result = await findTextInJSXFiles(".", component.text);
|
|
19
|
-
results[compApiId] = [...results[compApiId], ...result];
|
|
20
40
|
}
|
|
21
41
|
|
|
22
42
|
// Display results to user
|
|
23
43
|
console.log(JSON.stringify(results, null, 2));
|
|
24
44
|
}
|
|
25
45
|
|
|
26
|
-
interface Occurence {
|
|
27
|
-
lineNumber: number;
|
|
28
|
-
preview: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
type FindResults = { file: string; occurrences: Occurence[] }[];
|
|
32
|
-
|
|
33
46
|
async function findTextInJSXFiles(
|
|
34
47
|
path: string,
|
|
35
|
-
|
|
36
|
-
)
|
|
37
|
-
const result:
|
|
48
|
+
component: FetchComponentResponseComponent
|
|
49
|
+
) {
|
|
50
|
+
const result: Result["occurrences"] = {};
|
|
38
51
|
const files = glob.sync(`${path}/**/*.+(jsx|tsx)`, {
|
|
39
52
|
ignore: "**/node_modules/**",
|
|
40
53
|
});
|
|
@@ -42,6 +55,8 @@ async function findTextInJSXFiles(
|
|
|
42
55
|
const promises: Promise<any>[] = [];
|
|
43
56
|
|
|
44
57
|
for (const file of files) {
|
|
58
|
+
result[file] = [];
|
|
59
|
+
|
|
45
60
|
promises.push(
|
|
46
61
|
fs.readFile(file, "utf-8").then((code) => {
|
|
47
62
|
const ast = parse(code, {
|
|
@@ -49,12 +64,12 @@ async function findTextInJSXFiles(
|
|
|
49
64
|
plugins: ["jsx", "typescript"],
|
|
50
65
|
});
|
|
51
66
|
|
|
52
|
-
const occurrences:
|
|
67
|
+
const occurrences: Occurrence[] = [];
|
|
53
68
|
|
|
54
69
|
traverse(ast, {
|
|
55
70
|
JSXText(path) {
|
|
56
|
-
if (path.node.value.includes(
|
|
57
|
-
const regex = new RegExp(
|
|
71
|
+
if (path.node.value.includes(component.text)) {
|
|
72
|
+
const regex = new RegExp(component.text, "g");
|
|
58
73
|
let match;
|
|
59
74
|
while ((match = regex.exec(path.node.value)) !== null) {
|
|
60
75
|
const lines = path.node.value.slice(0, match.index).split("\n");
|
|
@@ -70,8 +85,8 @@ async function findTextInJSXFiles(
|
|
|
70
85
|
const preview = replaceAt(
|
|
71
86
|
line,
|
|
72
87
|
match.index,
|
|
73
|
-
|
|
74
|
-
|
|
88
|
+
component.text,
|
|
89
|
+
`${component.text}`
|
|
75
90
|
);
|
|
76
91
|
|
|
77
92
|
occurrences.push({ lineNumber, preview });
|
|
@@ -81,7 +96,9 @@ async function findTextInJSXFiles(
|
|
|
81
96
|
});
|
|
82
97
|
|
|
83
98
|
if (occurrences.length > 0) {
|
|
84
|
-
result
|
|
99
|
+
result[file] = occurrences;
|
|
100
|
+
} else {
|
|
101
|
+
delete result[file];
|
|
85
102
|
}
|
|
86
103
|
})
|
|
87
104
|
);
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import api from "../api";
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export interface FetchComponentResponseComponent {
|
|
4
|
+
name: string;
|
|
5
|
+
text: string;
|
|
6
|
+
status: "NONE" | "WIP" | "REVIEW" | "FINAL";
|
|
7
|
+
folder: "string" | null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface FetchComponentResponse {
|
|
11
|
+
[compApiId: string]: FetchComponentResponseComponent;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function fetchComponents(): Promise<FetchComponentResponse> {
|
|
4
15
|
const { data } = await api.get<{
|
|
5
16
|
[compApiId: string]: {
|
|
6
17
|
name: string;
|
package/lib/replace.test.ts
CHANGED
|
@@ -67,7 +67,7 @@ describe("replaceJSXTextInFile", () => {
|
|
|
67
67
|
const searchString = "world";
|
|
68
68
|
const replaceWith = "some-id";
|
|
69
69
|
|
|
70
|
-
await replaceJSXTextInFile(tempFile, { searchString, replaceWith });
|
|
70
|
+
await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});
|
|
71
71
|
|
|
72
72
|
const transformedCode = await fs.readFile(tempFile, "utf-8");
|
|
73
73
|
expect(transformedCode).toContain(
|
|
@@ -75,12 +75,31 @@ describe("replaceJSXTextInFile", () => {
|
|
|
75
75
|
);
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
+
test("should replace JSX text with a DittoComponent with a flag", async () => {
|
|
79
|
+
const tempFile = await createTempJSXFile(
|
|
80
|
+
`<>\n<div>Hello, world</div>\n<div>Hello, world</div>\n</>`
|
|
81
|
+
);
|
|
82
|
+
const searchString = "world";
|
|
83
|
+
const replaceWith = "some-id";
|
|
84
|
+
|
|
85
|
+
await replaceJSXTextInFile(
|
|
86
|
+
tempFile,
|
|
87
|
+
{ searchString, replaceWith },
|
|
88
|
+
{ lineNumbers: [3] }
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const transformedCode = await fs.readFile(tempFile, "utf-8");
|
|
92
|
+
expect(transformedCode).toContain(
|
|
93
|
+
`<>\n <div>Hello, world</div>\n <div>Hello, <DittoComponent componentId=\"some-id\" /></div>\n</>;`
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
78
97
|
test("should handle case-insensitive search", async () => {
|
|
79
98
|
const tempFile = await createTempJSXFile("<div>HeLLo, WoRlD</div>");
|
|
80
99
|
const searchString = "world";
|
|
81
100
|
const replaceWith = "some-id";
|
|
82
101
|
|
|
83
|
-
await replaceJSXTextInFile(tempFile, { searchString, replaceWith });
|
|
102
|
+
await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});
|
|
84
103
|
|
|
85
104
|
const transformedCode = await fs.readFile(tempFile, "utf-8");
|
|
86
105
|
expect(transformedCode).toContain(
|
|
@@ -93,7 +112,7 @@ describe("replaceJSXTextInFile", () => {
|
|
|
93
112
|
const searchString = "foobar";
|
|
94
113
|
const replaceWith = "some-id";
|
|
95
114
|
|
|
96
|
-
await replaceJSXTextInFile(tempFile, { searchString, replaceWith });
|
|
115
|
+
await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});
|
|
97
116
|
|
|
98
117
|
const transformedCode = await fs.readFile(tempFile, "utf-8");
|
|
99
118
|
expect(transformedCode).toContain("<div>Hello, world!</div>");
|