@dittowords/cli 3.2.0-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 CHANGED
@@ -38,10 +38,21 @@ const COMMANDS = [
38
38
  {
39
39
  name: "generate-suggestions",
40
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
+ },
41
46
  },
42
47
  {
43
48
  name: "replace",
44
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
+ },
45
56
  },
46
57
  ];
47
58
  const setupCommands = () => {
@@ -50,8 +61,20 @@ const setupCommands = () => {
50
61
  const cmd = commander_1.program
51
62
  .command(commandConfig.name)
52
63
  .description(commandConfig.description)
53
- .action((str, options) => executeCommand(commandConfig.name, options));
54
- if ("commands" in commandConfig) {
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) {
55
78
  commandConfig.commands.forEach((nestedCommand) => {
56
79
  cmd
57
80
  .command(nestedCommand.name)
@@ -94,10 +117,14 @@ const executeCommand = async (command, options) => {
94
117
  return (0, remove_project_1.default)();
95
118
  }
96
119
  case "generate-suggestions": {
97
- return (0, generate_suggestions_1.generateSuggestions)();
120
+ return (0, generate_suggestions_1.generateSuggestions)({
121
+ ...(options.directory ? { directory: options.directory } : {}),
122
+ });
98
123
  }
99
124
  case "replace": {
100
- return (0, replace_1.replace)(options);
125
+ return (0, replace_1.replace)(options.args, {
126
+ ...(options.lineNumbers ? { lineNumbers: options.lineNumbers } : {}),
127
+ });
101
128
  }
102
129
  default: {
103
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":"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"}
1
+ {"version":3,"file":"ditto.js","sourceRoot":"","sources":["../lib/ditto.ts"],"names":[],"mappings":"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"}
@@ -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, searchString) {
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(searchString)) {
42
- const regex = new RegExp(searchString, "g");
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, searchString, `{{${searchString}}}`);
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.push({ file, occurrences });
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":"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"}
1
+ {"version":3,"file":"generate-suggestions.js","sourceRoot":"","sources":["../lib/generate-suggestions.ts"],"names":[],"mappings":";;;;;;AAAA,wDAA0B;AAC1B,gDAAwB;AACxB,0CAAsC;AACtC,+DAAuC;AAEvC,4DAGgC;AAchC,KAAK,UAAU,mBAAmB,CAAC,KAA6B;IAC9D,MAAM,UAAU,GAAG,MAAM,IAAA,iCAAe,GAAE,CAAC;IAC3C,MAAM,OAAO,GAAgC,EAAE,CAAC;IAEhD,KAAK,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;QAC/D,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;YACvB,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;SAC1E;QAED,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,GAAG,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC9D,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,GAAG,MAAM,CAAC;QAExC,qCAAqC;QACrC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;YAC5D,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;SAC3B;KACF;IAED,0BAA0B;IAC1B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAgF4B,kDAAmB;AA9EhD,KAAK,UAAU,kBAAkB,CAC/B,IAAY,EACZ,SAA0C;IAE1C,MAAM,MAAM,GAA0B,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,IAAI,kBAAkB,EAAE;QACjD,MAAM,EAAE,oBAAoB;KAC7B,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAmB,EAAE,CAAC;IAEpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;QACxB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAElB,QAAQ,CAAC,IAAI,CACX,kBAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACvC,MAAM,GAAG,GAAG,IAAA,cAAK,EAAC,IAAI,EAAE;gBACtB,UAAU,EAAE,QAAQ;gBACpB,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC;aAC/B,CAAC,CAAC;YAEH,MAAM,WAAW,GAAiB,EAAE,CAAC;YAErC,IAAA,kBAAQ,EAAC,GAAG,EAAE;gBACZ,OAAO,CAAC,IAAI;oBACV,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;wBAC5C,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;wBAC9C,IAAI,KAAK,CAAC;wBACV,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE;4BACrD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;4BAEhE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;gCAClB,SAAS;6BACV;4BAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;4BAE/D,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;4BACnC,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;4BACvC,MAAM,OAAO,GAAG,SAAS,CACvB,IAAI,EACJ,KAAK,CAAC,KAAK,EACX,SAAS,CAAC,IAAI,EACd,GAAG,SAAS,CAAC,IAAI,EAAE,CACpB,CAAC;4BAEF,WAAW,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;yBAC3C;qBACF;gBACH,CAAC;aACF,CAAC,CAAC;YAEH,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC;aAC5B;iBAAM;gBACL,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;aACrB;QACH,CAAC,CAAC,CACH,CAAC;KACH;IAED,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE5B,OAAO,MAAM,CAAC;AAChB,CAAC;AAcQ,gDAAkB;AAZ3B,SAAS,SAAS,CAChB,GAAW,EACX,KAAa,EACb,YAAoB,EACpB,WAAmB;IAEnB,OAAO,CACL,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC;QACvB,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,WAAW,CAAC,CACpE,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetchComponents.js","sourceRoot":"","sources":["../../lib/http/fetchComponents.ts"],"names":[],"mappings":";;;;;;AAAA,iDAAyB;AAElB,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"}
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) {
@@ -1 +1 @@
1
- {"version":3,"file":"replace.js","sourceRoot":"","sources":["../lib/replace.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"replace.js","sourceRoot":"","sources":["../lib/replace.ts"],"names":[],"mappings":"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"}
package/lib/ditto.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  import { program } from "commander";
4
4
  // to use V8's code cache to speed up instantiation time
5
5
  import "v8-compile-cache";
6
-
7
- import packageJson from "../package.json";
6
+ import fs from "fs";
7
+ import path from "path";
8
8
 
9
9
  import { init, needsTokenOrSource } from "./init/init";
10
10
  import { pull } from "./pull";
@@ -16,7 +16,16 @@ import { generateSuggestions } from "./generate-suggestions";
16
16
 
17
17
  import processMetaOption from "./utils/processMetaOption";
18
18
 
19
- const VERSION = packageJson.version;
19
+ function getVersion(): string {
20
+ const packageJsonPath = path.join(__dirname, "..", "package.json");
21
+ const packageJsonContent = fs.readFileSync(packageJsonPath, "utf8");
22
+ const packageJson = JSON.parse(packageJsonContent) as { version: string };
23
+ const version = packageJson.version;
24
+
25
+ return version;
26
+ }
27
+
28
+ const VERSION = getVersion();
20
29
 
21
30
  type Command =
22
31
  | "pull"
@@ -26,7 +35,16 @@ type Command =
26
35
  | "generate-suggestions"
27
36
  | "replace";
28
37
 
29
- const COMMANDS = [
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>[] = [
30
48
  {
31
49
  name: "pull",
32
50
  description: "Sync copy from Ditto into the current working directory",
@@ -48,12 +66,23 @@ const COMMANDS = [
48
66
  {
49
67
  name: "generate-suggestions",
50
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
+ },
51
74
  },
52
75
  {
53
76
  name: "replace",
54
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
+ },
55
84
  },
56
- ] as const;
85
+ ];
57
86
 
58
87
  const setupCommands = () => {
59
88
  program.name("ditto-cli");
@@ -62,19 +91,30 @@ const setupCommands = () => {
62
91
  const cmd = program
63
92
  .command(commandConfig.name)
64
93
  .description(commandConfig.description)
65
- .action((str, options) => executeCommand(commandConfig.name, options));
94
+ .action((options) => {
95
+ return executeCommand(commandConfig.name, options);
96
+ });
97
+
98
+ if (commandConfig.flags) {
99
+ Object.entries(commandConfig.flags).forEach(
100
+ ([flags, { description, processor }]) => {
101
+ cmd.option(flags, description, processor);
102
+ }
103
+ );
104
+ }
66
105
 
67
- if ("commands" in commandConfig) {
106
+ if ("commands" in commandConfig && commandConfig.commands) {
68
107
  commandConfig.commands.forEach((nestedCommand) => {
69
108
  cmd
70
109
  .command(nestedCommand.name)
71
110
  .description(nestedCommand.description)
72
- .action((str, options) =>
73
- executeCommand(
74
- `${commandConfig.name} ${nestedCommand.name}`,
75
- options
76
- )
77
- );
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
+ });
78
118
  });
79
119
  }
80
120
  });
@@ -90,7 +130,7 @@ const setupOptions = () => {
90
130
 
91
131
  const executeCommand = async (
92
132
  command: Command | "none",
93
- options: string[]
133
+ options: any
94
134
  ): Promise<void> => {
95
135
  const needsInitialization = needsTokenOrSource();
96
136
  if (needsInitialization) {
@@ -121,10 +161,14 @@ const executeCommand = async (
121
161
  return removeProject();
122
162
  }
123
163
  case "generate-suggestions": {
124
- return generateSuggestions();
164
+ return generateSuggestions({
165
+ ...(options.directory ? { directory: options.directory } : {}),
166
+ });
125
167
  }
126
168
  case "replace": {
127
- return replace(options);
169
+ return replace(options.args, {
170
+ ...(options?.lineNumbers ? { lineNumbers: options.lineNumbers } : {}),
171
+ });
128
172
  }
129
173
  default: {
130
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 array when no files are found", async () => {
18
- const result = await findTextInJSXFiles(".", "searchString");
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 array when searchString is not found in any file", async () => {
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(".", "searchString");
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
- file: file1,
44
- occurrences: [
45
- {
46
- lineNumber: 1,
47
- preview:
48
- "<div>Test {{searchString}} and another searchString</div>",
49
- },
50
- {
51
- lineNumber: 1,
52
- preview:
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(".", "searchString");
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 { fetchComponents } from "./http/fetchComponents";
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
- searchString: string
36
- ): Promise<FindResults> {
37
- const result: { file: string; occurrences: Occurence[] }[] = [];
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: Occurence[] = [];
67
+ const occurrences: Occurrence[] = [];
53
68
 
54
69
  traverse(ast, {
55
70
  JSXText(path) {
56
- if (path.node.value.includes(searchString)) {
57
- const regex = new RegExp(searchString, "g");
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
- searchString,
74
- `{{${searchString}}}`
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.push({ file, occurrences });
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 async function fetchComponents() {
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;
@@ -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>");
package/lib/replace.ts CHANGED
@@ -6,7 +6,10 @@ import { transformFromAst } from "@babel/core";
6
6
 
7
7
  async function replaceJSXTextInFile(
8
8
  filePath: string,
9
- replacement: { searchString: string; replaceWith: string }
9
+ replacement: { searchString: string; replaceWith: string },
10
+ flags: {
11
+ lineNumbers?: number[];
12
+ }
10
13
  ) {
11
14
  const code = await fs.readFile(filePath, "utf-8");
12
15
  const ast = parse(code, {
@@ -20,6 +23,15 @@ async function replaceJSXTextInFile(
20
23
 
21
24
  const regex = new RegExp(searchString, "gi");
22
25
  if (regex.test(path.node.value)) {
26
+ // Ignore if not on a line number that we want to replace.
27
+ if (
28
+ flags.lineNumbers &&
29
+ path.node.loc &&
30
+ !flags.lineNumbers.includes(path.node.loc.start.line)
31
+ ) {
32
+ return;
33
+ }
34
+
23
35
  const splitValues = splitByCaseInsensitive(
24
36
  path.node.value,
25
37
  searchString
@@ -59,7 +71,7 @@ function splitByCaseInsensitive(str: string, delimiter: string) {
59
71
  return str.split(new RegExp(`(${delimiter})`, "gi")).filter((s) => s !== "");
60
72
  }
61
73
 
62
- function replace(options: string[]) {
74
+ function replace(options: string[], flags: { lineNumbers?: number[] }) {
63
75
  let filePath: string;
64
76
  let searchString: string;
65
77
  let replaceWith: string;
@@ -77,7 +89,7 @@ function replace(options: string[]) {
77
89
  return;
78
90
  }
79
91
 
80
- replaceJSXTextInFile(filePath, { searchString, replaceWith });
92
+ replaceJSXTextInFile(filePath, { searchString, replaceWith }, flags);
81
93
  }
82
94
 
83
95
  function parseOptions(options: string[]): {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dittowords/cli",
3
- "version": "3.2.0-alpha",
3
+ "version": "3.3.0",
4
4
  "description": "Command Line Interface for Ditto (dittowords.com).",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ function HelloWorld() {
3
+ return (
4
+ <div>
5
+ <p>hello world</p>
6
+ <p>Some additional text.</p>
7
+ <p>hello world</p>
8
+ <p>More additional text.</p>
9
+ <p>ahhh hello world iaewofjaowiejfoiwjfoffj</p>
10
+ <p>Even more additional text.</p>
11
+ <p>hello world</p>
12
+ <p>Final additional text.</p>
13
+ <p>hello world</p>
14
+ <p>good bye</p>
15
+ </div>
16
+ );
17
+ }
18
+ export default HelloWorld;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ function HelloWorld() {
3
+ return (
4
+ <div>
5
+ <p>good bye</p>
6
+ </div>
7
+ );
8
+ }
9
+ export default HelloWorld;