sfdx-hardis 5.10.2-beta202412231619.0 → 5.10.2-beta202412292224.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/defaults/mkdocs/docs/stylesheets/extra.css +25 -0
- package/defaults/mkdocs/mkdocs.yml +10 -2
- package/defaults/mkdocs-project-doc/docs/javascripts/gtag.js +27 -0
- package/defaults/mkdocs-project-doc/docs/javascripts/tables.js +6 -0
- package/defaults/mkdocs-project-doc/docs/overrides/main.html +4 -0
- package/defaults/mkdocs-project-doc/docs/stylesheets/extra.css +33 -0
- package/defaults/mkdocs-project-doc/mkdocs.yml +49 -0
- package/lib/commands/hardis/doc/flow2markdown.d.ts +1 -0
- package/lib/commands/hardis/doc/flow2markdown.js +18 -3
- package/lib/commands/hardis/doc/flow2markdown.js.map +1 -1
- package/lib/commands/hardis/doc/project2markdown.d.ts +7 -2
- package/lib/commands/hardis/doc/project2markdown.js +173 -45
- package/lib/commands/hardis/doc/project2markdown.js.map +1 -1
- package/lib/commands/hardis/project/generate/flow-git-diff.js +28 -16
- package/lib/commands/hardis/project/generate/flow-git-diff.js.map +1 -1
- package/lib/common/gitProvider/utilsMarkdown.js +5 -5
- package/lib/common/gitProvider/utilsMarkdown.js.map +1 -1
- package/lib/common/metadata-utils/index.js +3 -2
- package/lib/common/metadata-utils/index.js.map +1 -1
- package/lib/common/utils/flowVisualiser/flowParser.d.ts +0 -7
- package/lib/common/utils/flowVisualiser/flowParser.js +150 -167
- package/lib/common/utils/flowVisualiser/flowParser.js.map +1 -1
- package/lib/common/utils/flowVisualiser/nodeFormatUtils.d.ts +14 -0
- package/lib/common/utils/flowVisualiser/nodeFormatUtils.js +341 -0
- package/lib/common/utils/flowVisualiser/nodeFormatUtils.js.map +1 -0
- package/lib/common/utils/flowVisualiser/renderConfig.d.ts +9 -3
- package/lib/common/utils/flowVisualiser/renderConfig.js +62 -56
- package/lib/common/utils/flowVisualiser/renderConfig.js.map +1 -1
- package/lib/common/utils/index.d.ts +1 -0
- package/lib/common/utils/index.js +10 -0
- package/lib/common/utils/index.js.map +1 -1
- package/lib/common/utils/mermaidUtils.d.ts +5 -2
- package/lib/common/utils/mermaidUtils.js +278 -92
- package/lib/common/utils/mermaidUtils.js.map +1 -1
- package/lib/common/utils/projectUtils.js +1 -1
- package/lib/common/utils/projectUtils.js.map +1 -1
- package/oclif.lock +938 -1263
- package/oclif.manifest.json +373 -358
- package/package.json +6 -5
|
@@ -3,7 +3,7 @@ import fs from 'fs-extra';
|
|
|
3
3
|
import * as Diff from "diff";
|
|
4
4
|
import * as path from "path";
|
|
5
5
|
import which from "which";
|
|
6
|
-
import { execCommand, git, uxLog } from "./index.js";
|
|
6
|
+
import { execCommand, git, isDockerRunning, uxLog } from "./index.js";
|
|
7
7
|
import { parseFlow } from "./flowVisualiser/flowParser.js";
|
|
8
8
|
import { getReportDirectory } from "../../config/index.js";
|
|
9
9
|
import moment from "moment";
|
|
@@ -26,13 +26,15 @@ export async function isDockerAvailable() {
|
|
|
26
26
|
if (IS_DOCKER_AVAILABLE !== null) {
|
|
27
27
|
return IS_DOCKER_AVAILABLE;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
IS_DOCKER_AVAILABLE
|
|
29
|
+
IS_DOCKER_AVAILABLE = await isDockerRunning();
|
|
30
|
+
if (!IS_DOCKER_AVAILABLE) {
|
|
31
|
+
uxLog(this, c.yellow("Docker daemon is not available. If you have issues running npm package @mermaid-js/mermaid-cli, please install Docker and start it"));
|
|
32
|
+
}
|
|
31
33
|
return IS_DOCKER_AVAILABLE;
|
|
32
34
|
}
|
|
33
|
-
export async function generateFlowMarkdownFile(flowName, flowXml, outputFlowMdFile) {
|
|
35
|
+
export async function generateFlowMarkdownFile(flowName, flowXml, outputFlowMdFile, options = { collapsedDetails: true }) {
|
|
34
36
|
try {
|
|
35
|
-
const flowDocGenResult = await parseFlow(flowXml, 'mermaid', { outputAsMarkdown: true });
|
|
37
|
+
const flowDocGenResult = await parseFlow(flowXml, 'mermaid', { outputAsMarkdown: true, collapsedDetails: options.collapsedDetails });
|
|
36
38
|
const flowMarkdownDoc = flowDocGenResult.uml;
|
|
37
39
|
await fs.writeFile(outputFlowMdFile, flowMarkdownDoc);
|
|
38
40
|
uxLog(this, c.grey(`Written ${flowName} documentation in ${outputFlowMdFile}`));
|
|
@@ -99,59 +101,80 @@ export async function generateMarkdownFileWithMermaidCli(outputFlowMdFile) {
|
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
103
|
export function getMermaidExtraClasses() {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
104
|
+
const added = 'fill:green,color:white,stroke-width:4px,max-height:100px';
|
|
105
|
+
const removed = 'fill:red,color:white,stroke-width:4px,max-height:100px';
|
|
106
|
+
const changed = 'fill:orange,color:white,stroke-width:4px,max-height:100px';
|
|
107
|
+
const addedClasses = [
|
|
108
|
+
'actionCallsAdded',
|
|
109
|
+
'assignmentsAdded',
|
|
110
|
+
'collectionProcessorsAdded',
|
|
111
|
+
'customErrorsAdded',
|
|
112
|
+
'decisionsAdded',
|
|
113
|
+
'loopsAdded',
|
|
114
|
+
'recordCreatesAdded',
|
|
115
|
+
'recordDeletesAdded',
|
|
116
|
+
'recordLookupsAdded',
|
|
117
|
+
'recordUpdatesAdded',
|
|
118
|
+
'screensAdded',
|
|
119
|
+
'subflowsAdded',
|
|
120
|
+
'startClassAdded'
|
|
121
|
+
];
|
|
122
|
+
const removedClasses = [
|
|
123
|
+
'actionCallsRemoved',
|
|
124
|
+
'assignmentsRemoved',
|
|
125
|
+
'collectionProcessorsRemoved',
|
|
126
|
+
'customErrorsRemoved',
|
|
127
|
+
'decisionsRemoved',
|
|
128
|
+
'loopsRemoved',
|
|
129
|
+
'recordCreatesRemoved',
|
|
130
|
+
'recordDeletesRemoved',
|
|
131
|
+
'recordLookupsRemoved',
|
|
132
|
+
'recordUpdatesRemoved',
|
|
133
|
+
'screensRemoved',
|
|
134
|
+
'subflowsRemoved',
|
|
135
|
+
'startClassRemoved'
|
|
136
|
+
];
|
|
137
|
+
const changedClasses = [
|
|
138
|
+
'actionCallsChanged',
|
|
139
|
+
'assignmentsChanged',
|
|
140
|
+
'collectionProcessorsChanged',
|
|
141
|
+
'customErrorsChanged',
|
|
142
|
+
'decisionsChanged',
|
|
143
|
+
'loopsChanged',
|
|
144
|
+
'recordCreatesChanged',
|
|
145
|
+
'recordDeletesChanged',
|
|
146
|
+
'recordLookupsChanged',
|
|
147
|
+
'recordUpdatesChanged',
|
|
148
|
+
'screensChanged',
|
|
149
|
+
'subflowsChanged',
|
|
150
|
+
'startClassChanged'
|
|
151
|
+
];
|
|
152
|
+
const formatClasses = (classList, style) => classList.map(className => `classDef ${className} ${style}`).join('\n');
|
|
153
|
+
return `
|
|
154
|
+
${formatClasses(addedClasses, added)}
|
|
127
155
|
|
|
128
|
-
|
|
129
|
-
classDef assignmentsChanged fill:#F97924,color:white,stroke:#edaa18,stroke-width:12px;
|
|
130
|
-
classDef collectionProcessorsChanged fill:#DD7A00,color:white,stroke:#edaa18,stroke-width:12px;
|
|
131
|
-
classDef customErrorsChanged fill:#032D60,color:white,stroke:#edaa18,stroke-width:12px;
|
|
132
|
-
classDef decisionsChanged fill:#DD7A00,color:white,stroke:#edaa18,stroke-width:12px;
|
|
133
|
-
classDef loopsChanged fill:#E07D1C,color:undefined,stroke:#edaa18,stroke-width:12px;
|
|
134
|
-
classDef recordCreatesChanged fill:#F9548A,color:white,stroke:#edaa18,stroke-width:12px;
|
|
135
|
-
classDef recordDeletesChanged fill:#F9548A,color:white,stroke:#edaa18,stroke-width:12px;
|
|
136
|
-
classDef recordLookupsChanged fill:#F9548A,color:white,stroke:#edaa18,stroke-width:12px;
|
|
137
|
-
classDef recordUpdatesChanged fill:#F9548A,color:white,stroke:#edaa18,stroke-width:12px;
|
|
138
|
-
classDef screensChanged fill:#1B96FF,color:white,stroke:#edaa18,stroke-width:12px;
|
|
139
|
-
classDef subflowsChanged fill:#032D60,color:white,stroke:#edaa18,stroke-width:12px;
|
|
156
|
+
${formatClasses(removedClasses, removed)}
|
|
140
157
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
`;
|
|
158
|
+
${formatClasses(changedClasses, changed)}
|
|
159
|
+
`;
|
|
144
160
|
}
|
|
145
161
|
export async function generateFlowVisualGitDiff(flowFile, commitBefore, commitAfter, options = { mermaidMd: false, svgMd: true, debug: false }) {
|
|
162
|
+
const result = { outputDiffMdFile: "", hasFlowDiffs: false };
|
|
146
163
|
const mermaidMdBefore = await buildMermaidMarkdown(commitBefore, flowFile);
|
|
147
164
|
const mermaidMdAfter = await buildMermaidMarkdown(commitAfter, flowFile);
|
|
148
165
|
const flowLabel = path.basename(flowFile, ".flow-meta.xml");
|
|
166
|
+
const reportDir = await getReportDirectory();
|
|
167
|
+
await fs.ensureDir(path.join(reportDir, "flow-diff"));
|
|
168
|
+
const diffMdFile = path.join(reportDir, 'flow-diff', `${flowLabel}_${moment().format("YYYYMMDD-hhmmss")}.md`);
|
|
149
169
|
if (options.debug) {
|
|
150
170
|
uxLog(this, c.grey("FLOW DOC BEFORE:\n" + mermaidMdBefore) + "\n");
|
|
171
|
+
await fs.writeFile(diffMdFile.replace(".md", ".mermaid-before.md"), mermaidMdBefore);
|
|
151
172
|
uxLog(this, c.grey("FLOW DOC AFTER:\n" + mermaidMdAfter) + "\n");
|
|
173
|
+
await fs.writeFile(diffMdFile.replace(".md", ".mermaid-after.md"), mermaidMdAfter);
|
|
152
174
|
}
|
|
153
175
|
const flowDiffs = Diff.diffLines(mermaidMdBefore, mermaidMdAfter);
|
|
154
|
-
|
|
176
|
+
result.hasFlowDiffs = flowDiffs.some(line => line.added || line.removed);
|
|
177
|
+
result.diffLines = flowDiffs.filter(line => line.added || line.removed);
|
|
155
178
|
const mixedLines = [];
|
|
156
179
|
for (const line of flowDiffs) {
|
|
157
180
|
if (line.added) {
|
|
@@ -166,26 +189,26 @@ export async function generateFlowVisualGitDiff(flowFile, commitBefore, commitAf
|
|
|
166
189
|
}
|
|
167
190
|
// uxLog(this, JSON.stringify(mixedLines, null, 2));
|
|
168
191
|
const compareMdLines = [];
|
|
169
|
-
|
|
192
|
+
const linkLines = [];
|
|
193
|
+
buildFinalCompareMarkdown(mixedLines, compareMdLines, false, false, linkLines);
|
|
170
194
|
// Write markdown with diff in a file
|
|
171
|
-
const reportDir = await getReportDirectory();
|
|
172
|
-
await fs.ensureDir(path.join(reportDir, "flow-diff"));
|
|
173
|
-
const diffMdFile = path.join(reportDir, 'flow-diff', `${flowLabel}_${moment().format("YYYYMMDD-hhmmss")}.md`);
|
|
174
195
|
await fs.writeFile(diffMdFile, compareMdLines.join("\n"));
|
|
175
196
|
if (options.mermaidMd) {
|
|
176
|
-
await fs.copyFile(diffMdFile, diffMdFile
|
|
197
|
+
await fs.copyFile(diffMdFile, diffMdFile.replace(".md", ".mermaid.md"));
|
|
177
198
|
}
|
|
178
199
|
if (!options.svgMd) {
|
|
179
|
-
|
|
200
|
+
result.outputDiffMdFile = diffMdFile;
|
|
201
|
+
return result;
|
|
180
202
|
}
|
|
181
203
|
// Generate final markdown with mermaid SVG
|
|
182
204
|
const finalRes = await generateMarkdownFileWithMermaid(diffMdFile);
|
|
183
205
|
if (finalRes) {
|
|
184
206
|
uxLog(this, c.green(`Successfully generated visual git diff for flow: ${diffMdFile}`));
|
|
185
207
|
}
|
|
186
|
-
|
|
208
|
+
result.outputDiffMdFile = diffMdFile;
|
|
209
|
+
return result;
|
|
187
210
|
}
|
|
188
|
-
function buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, isTableStarted) {
|
|
211
|
+
function buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, isTableStarted, linkLines) {
|
|
189
212
|
if (mixedLines.length === 0) {
|
|
190
213
|
return;
|
|
191
214
|
}
|
|
@@ -197,19 +220,37 @@ function buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, isTabl
|
|
|
197
220
|
}
|
|
198
221
|
else if (isMermaid === true && currentLine.includes("```")) {
|
|
199
222
|
compareMdLines.push(...getMermaidExtraClasses().split("\n"));
|
|
223
|
+
// Build link positions
|
|
224
|
+
let pos = 0;
|
|
225
|
+
const positions = {
|
|
226
|
+
added: [],
|
|
227
|
+
removed: [],
|
|
228
|
+
unchanged: []
|
|
229
|
+
};
|
|
230
|
+
for (const linkType of linkLines) {
|
|
231
|
+
positions[linkType].push(pos);
|
|
232
|
+
pos++;
|
|
233
|
+
}
|
|
234
|
+
// Build added and removed links styles
|
|
235
|
+
if (positions.added.length > 0) {
|
|
236
|
+
compareMdLines.push("linkStyle " + positions.added.join(",") + " stroke:#00ff00,stroke-width:4px,color:green;");
|
|
237
|
+
}
|
|
238
|
+
if (positions.removed.length > 0) {
|
|
239
|
+
compareMdLines.push("linkStyle " + positions.removed.join(",") + " stroke:#ff0000,stroke-width:4px,color:red;");
|
|
240
|
+
}
|
|
200
241
|
isMermaid = false;
|
|
201
242
|
}
|
|
202
243
|
let styledLine = currentLine;
|
|
203
244
|
// Remove next diff line if not relevant
|
|
204
|
-
if (styledLine.startsWith("|") && mixedLines.length > 1 && mixedLines[0][1] === '' && mixedLines[1][1].startsWith("|")) {
|
|
245
|
+
if (styledLine.startsWith("|") && mixedLines.length > 1 && mixedLines[0][1] === '' && mixedLines[1][1].startsWith("|") && !mixedLines[1][1].startsWith("|Condition Id|") && !mixedLines[1][1].startsWith("|Filter Id|")) {
|
|
205
246
|
mixedLines.shift();
|
|
206
247
|
}
|
|
207
248
|
// Skip table block if there are no updated lines within
|
|
208
|
-
if (styledLine.startsWith("## ") && !styledLine.startsWith("## Flow")) {
|
|
249
|
+
if (styledLine.startsWith("## ") && !styledLine.startsWith("## Flow Diagram")) {
|
|
209
250
|
let updatedInBlock = false;
|
|
210
251
|
let nextBlockPos = 0;
|
|
211
252
|
for (const nextLine of mixedLines) {
|
|
212
|
-
if (nextLine[1].startsWith("## ") || nextLine[1].
|
|
253
|
+
if (nextLine[1].startsWith("## ") || nextLine[1].includes("_Documentation") || nextLine[1].startsWith("___")) {
|
|
213
254
|
break;
|
|
214
255
|
}
|
|
215
256
|
if (nextLine[0] === "removed" || nextLine[0] === "added") {
|
|
@@ -220,7 +261,7 @@ function buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, isTabl
|
|
|
220
261
|
if (!updatedInBlock) {
|
|
221
262
|
const mixedLinesStartingFromNextBlock = mixedLines.slice(nextBlockPos);
|
|
222
263
|
// Continue processing next lines
|
|
223
|
-
buildFinalCompareMarkdown(mixedLinesStartingFromNextBlock, compareMdLines, isMermaid,
|
|
264
|
+
buildFinalCompareMarkdown(mixedLinesStartingFromNextBlock, compareMdLines, isMermaid, false, linkLines);
|
|
224
265
|
return;
|
|
225
266
|
}
|
|
226
267
|
}
|
|
@@ -230,7 +271,26 @@ function buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, isTabl
|
|
|
230
271
|
let updatedInBlock = false;
|
|
231
272
|
let nextBlockPos = 0;
|
|
232
273
|
for (const nextLine of mixedLines) {
|
|
233
|
-
if (nextLine[1].startsWith("### ") || nextLine[1].startsWith("_Documentation")) {
|
|
274
|
+
if (nextLine[1].startsWith("### ") || nextLine[1].startsWith("## ") || nextLine[1].includes("_Documentation") || nextLine[1].startsWith("___")) {
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
if (nextLine[0] === "removed" || nextLine[0] === "added") {
|
|
278
|
+
updatedInBlock = true;
|
|
279
|
+
}
|
|
280
|
+
nextBlockPos++;
|
|
281
|
+
}
|
|
282
|
+
if (!updatedInBlock) {
|
|
283
|
+
const mixedLinesStartingFromNextBlock = mixedLines.slice(nextBlockPos);
|
|
284
|
+
// Continue processing next lines
|
|
285
|
+
buildFinalCompareMarkdown(mixedLinesStartingFromNextBlock, compareMdLines, isMermaid, false, linkLines);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else if (styledLine.startsWith("#### ")) {
|
|
290
|
+
let updatedInBlock = false;
|
|
291
|
+
let nextBlockPos = 0;
|
|
292
|
+
for (const nextLine of mixedLines) {
|
|
293
|
+
if (nextLine[1].startsWith("#### ") || nextLine[1].startsWith("### ") || nextLine[1].startsWith("## ") || nextLine[1].includes("_Documentation") || nextLine[1].startsWith("___")) {
|
|
234
294
|
break;
|
|
235
295
|
}
|
|
236
296
|
if (nextLine[0] === "removed" || nextLine[0] === "added") {
|
|
@@ -241,7 +301,7 @@ function buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, isTabl
|
|
|
241
301
|
if (!updatedInBlock) {
|
|
242
302
|
const mixedLinesStartingFromNextBlock = mixedLines.slice(nextBlockPos);
|
|
243
303
|
// Continue processing next lines
|
|
244
|
-
buildFinalCompareMarkdown(mixedLinesStartingFromNextBlock, compareMdLines, isMermaid,
|
|
304
|
+
buildFinalCompareMarkdown(mixedLinesStartingFromNextBlock, compareMdLines, isMermaid, false, linkLines);
|
|
245
305
|
return;
|
|
246
306
|
}
|
|
247
307
|
}
|
|
@@ -252,62 +312,76 @@ function buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, isTabl
|
|
|
252
312
|
const tableFilteredLines = [];
|
|
253
313
|
let endTablePos = 0;
|
|
254
314
|
for (const nextLine of mixedLines) {
|
|
255
|
-
if (!nextLine[1].startsWith("|") && nextLine[1] !== "") {
|
|
315
|
+
if ((!nextLine[1].startsWith("|") || nextLine[1].includes("Condition Id") || nextLine[1].includes("Filter Id")) && nextLine[1] !== "") {
|
|
256
316
|
break;
|
|
257
317
|
}
|
|
258
|
-
if (nextLine[0] === "removed" || nextLine[0] === "added" || endTablePos === 0) {
|
|
318
|
+
if ((nextLine[0] === "removed" || nextLine[0] === "added" || endTablePos === 0) && nextLine[1] !== "") {
|
|
259
319
|
tableFilteredLines.push(nextLine);
|
|
260
320
|
}
|
|
261
321
|
endTablePos++;
|
|
262
322
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
323
|
+
if (tableFilteredLines.length < 2) {
|
|
324
|
+
// Empty table
|
|
325
|
+
const mixedLinesStartingFromEndOfTable = mixedLines.slice(endTablePos);
|
|
326
|
+
buildFinalCompareMarkdown(mixedLinesStartingFromEndOfTable, compareMdLines, isMermaid, false, linkLines);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
compareMdLines.push(styledLine);
|
|
330
|
+
const mixedLinesStartingFromEndOfTable = mixedLines.slice(endTablePos);
|
|
331
|
+
const newMixedLines = [...tableFilteredLines, ...[["unchanged", ""]], ...mixedLinesStartingFromEndOfTable];
|
|
332
|
+
// Continue processing next lines
|
|
333
|
+
buildFinalCompareMarkdown(newMixedLines, compareMdLines, isMermaid, true, linkLines);
|
|
334
|
+
}
|
|
268
335
|
return;
|
|
269
336
|
}
|
|
270
337
|
// Tables lines
|
|
271
338
|
if (!isMermaid && status === "removed" && styledLine.startsWith("|") && !styledLine.startsWith("|:-")) {
|
|
272
|
-
styledLine = "|🟥" + styledLine.split("|").filter(e => e !== "").map((col) => `<span style="background-color:
|
|
339
|
+
styledLine = "|🟥" + styledLine.split("|").filter(e => e !== "").map((col) => `<span style="background-color: #ff7f7f;"><i>${col}</i></span>`).join("|") + "|";
|
|
273
340
|
}
|
|
274
341
|
else if (!isMermaid && status === "added" && styledLine.startsWith("|") && !styledLine.startsWith("|:-")) {
|
|
275
|
-
styledLine = "|🟩" + styledLine.split("|").filter(e => e !== "").map((col) => `<span style="background-color:
|
|
342
|
+
styledLine = "|🟩" + styledLine.split("|").filter(e => e !== "").map((col) => `<span style="background-color: #a6e22e;"><b>${col}</b></span>`).join("|") + "|";
|
|
343
|
+
}
|
|
344
|
+
// Normal lines header 3
|
|
345
|
+
else if (!isMermaid && status === "removed" && styledLine.startsWith("#### ")) {
|
|
346
|
+
styledLine = `#### 🟥${styledLine.replace("#### ", "")}`;
|
|
347
|
+
}
|
|
348
|
+
else if (!isMermaid && status === "added" && styledLine.startsWith("#### ")) {
|
|
349
|
+
styledLine = `#### 🟩${styledLine.replace("#### ", "")}`;
|
|
276
350
|
}
|
|
277
351
|
// Normal lines header 2
|
|
278
|
-
else if (!isMermaid && status === "removed" && styledLine.startsWith("###")) {
|
|
352
|
+
else if (!isMermaid && status === "removed" && styledLine.startsWith("### ")) {
|
|
279
353
|
styledLine = `### 🟥${styledLine.replace("### ", "")}`;
|
|
280
354
|
}
|
|
281
|
-
else if (!isMermaid && status === "added" && styledLine.startsWith("###")) {
|
|
355
|
+
else if (!isMermaid && status === "added" && styledLine.startsWith("### ")) {
|
|
282
356
|
styledLine = `### 🟩${styledLine.replace("### ", "")}`;
|
|
283
357
|
}
|
|
284
358
|
// Normal lines header 3
|
|
285
|
-
else if (!isMermaid && status === "removed" && styledLine.startsWith("##")) {
|
|
359
|
+
else if (!isMermaid && status === "removed" && styledLine.startsWith("## ")) {
|
|
286
360
|
styledLine = `## 🟥${styledLine.replace("## ", "")}`;
|
|
287
361
|
}
|
|
288
|
-
else if (!isMermaid && status === "added" && styledLine.startsWith("##")) {
|
|
362
|
+
else if (!isMermaid && status === "added" && styledLine.startsWith("## ")) {
|
|
289
363
|
styledLine = `## 🟩${styledLine.replace("## ", "")}`;
|
|
290
364
|
}
|
|
291
365
|
// Normal lines
|
|
292
|
-
else if (!isMermaid && status === "removed" && styledLine !== "" && !styledLine.startsWith("|:-")) {
|
|
293
|
-
styledLine = `<span style="background-color:
|
|
366
|
+
else if (!isMermaid && status === "removed" && styledLine !== "" && !styledLine.startsWith("|:-") && !styledLine.startsWith("___")) {
|
|
367
|
+
styledLine = `<span style="background-color: #ff7f7f;"><i>🟥${styledLine}</i></span>`;
|
|
294
368
|
}
|
|
295
|
-
else if (!isMermaid && status === "added" && styledLine !== "" && !styledLine.startsWith("|:-")) {
|
|
296
|
-
styledLine = `<span style="background-color:
|
|
369
|
+
else if (!isMermaid && status === "added" && styledLine !== "" && !styledLine.startsWith("|:-") && !styledLine.startsWith("___")) {
|
|
370
|
+
styledLine = `<span style="background-color: #a6e22e;"><b>🟩${styledLine}</b></span>`;
|
|
297
371
|
}
|
|
298
372
|
// Boxes lines
|
|
299
373
|
else if (isMermaid === true && status === "removed" && currentLine.split(":::").length === 2) {
|
|
300
374
|
styledLine = styledLine + "Removed";
|
|
301
375
|
if (styledLine.split('"').length === 3) {
|
|
302
376
|
const splits = styledLine.split('"');
|
|
303
|
-
styledLine = splits[0] + '"
|
|
377
|
+
styledLine = splits[0] + '"<i>' + splits[1] + '</i>"' + splits[2];
|
|
304
378
|
}
|
|
305
379
|
}
|
|
306
380
|
else if (isMermaid === true && status === "added" && currentLine.split(":::").length === 2) {
|
|
307
381
|
styledLine = styledLine + "Added";
|
|
308
382
|
if (styledLine.split('"').length === 3) {
|
|
309
383
|
const splits = styledLine.split('"');
|
|
310
|
-
styledLine = splits[0] + '"
|
|
384
|
+
styledLine = splits[0] + '"<b>' + splits[1] + '</b>"' + splits[2];
|
|
311
385
|
}
|
|
312
386
|
}
|
|
313
387
|
else if (isMermaid === true && currentLine.includes(":::")) {
|
|
@@ -315,58 +389,73 @@ function buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, isTabl
|
|
|
315
389
|
const splits = currentLine.split(/[[({]/);
|
|
316
390
|
if (splits.length > 1) {
|
|
317
391
|
const boxName = splits[0];
|
|
318
|
-
const changed = mixedLines.filter(([lineStatus, line]) => { return line.startsWith(`click ${boxName}`) && ["added", "
|
|
392
|
+
const changed = mixedLines.filter(([lineStatus, line]) => { return line.startsWith(`click ${boxName}`) && ["added", "removed"].includes(lineStatus); }).length;
|
|
319
393
|
if (changed > 0) {
|
|
320
394
|
styledLine = styledLine + "Changed";
|
|
321
395
|
if (styledLine.split('"').length === 3) {
|
|
322
396
|
const splits = styledLine.split('"');
|
|
323
|
-
styledLine = splits[0] + '"
|
|
397
|
+
styledLine = splits[0] + '"<b>' + splits[1] + '</b>"' + splits[2];
|
|
398
|
+
}
|
|
399
|
+
// Remove "removed" line from mixedLines
|
|
400
|
+
const removedNodePos = mixedLines.findIndex(([lineStatus, line]) => { return line.startsWith(`click ${boxName}`) && lineStatus === "removed"; });
|
|
401
|
+
if (removedNodePos !== -1) {
|
|
402
|
+
mixedLines.splice(removedNodePos, 1);
|
|
324
403
|
}
|
|
325
404
|
}
|
|
326
405
|
}
|
|
327
406
|
}
|
|
328
407
|
// Long Link lines
|
|
329
408
|
else if (isMermaid === true && status === "removed" && currentLine.includes('-. Fault .->')) {
|
|
330
|
-
styledLine = styledLine.replace('-. Fault .->', '-. 🟥Fault .->')
|
|
409
|
+
styledLine = styledLine.replace('-. Fault .->', '-. 🟥Fault .->'); //+ ":::removedLink"
|
|
410
|
+
linkLines.push("removed");
|
|
331
411
|
}
|
|
332
412
|
else if (isMermaid === true && status === "added" && currentLine.includes('-. Fault .->')) {
|
|
333
|
-
styledLine = styledLine.replace('-. Fault .->', '-. 🟩Fault .->') + ":::addedLink"
|
|
413
|
+
styledLine = styledLine.replace('-. Fault .->', '-. 🟩Fault .->'); // + ":::addedLink"
|
|
414
|
+
linkLines.push("added");
|
|
334
415
|
}
|
|
335
416
|
/* jscpd:ignore-start */
|
|
336
417
|
// Long Link lines
|
|
337
418
|
else if (isMermaid === true && status === "removed" && currentLine.includes('--->')) {
|
|
338
|
-
styledLine = styledLine.replace("--->", "--.->")
|
|
419
|
+
styledLine = styledLine.replace("--->", "--.->"); //+ ":::removedLink"
|
|
420
|
+
linkLines.push("removed");
|
|
339
421
|
if (styledLine.split("|").length === 3) {
|
|
340
422
|
const splits = styledLine.split("|");
|
|
341
|
-
styledLine = splits[0] + "
|
|
423
|
+
styledLine = splits[0] + '|"🟥<i>' + removeQuotes(splits[1]) + '</i>"|' + splits[2];
|
|
342
424
|
}
|
|
343
425
|
}
|
|
344
426
|
else if (isMermaid === true && status === "added" && currentLine.includes('--->')) {
|
|
345
|
-
styledLine = styledLine.replace("--->", "===>") + ":::addedLink"
|
|
427
|
+
styledLine = styledLine.replace("--->", "===>"); // + ":::addedLink"
|
|
428
|
+
linkLines.push("added");
|
|
346
429
|
if (styledLine.split("|").length === 3) {
|
|
347
430
|
const splits = styledLine.split("|");
|
|
348
|
-
styledLine = splits[0] + "
|
|
431
|
+
styledLine = splits[0] + '|"🟩<b>' + removeQuotes(splits[1]) + '</b>"|' + splits[2];
|
|
349
432
|
}
|
|
350
433
|
}
|
|
351
434
|
// Link lines
|
|
352
435
|
else if (isMermaid === true && status === "removed" && currentLine.includes('-->')) {
|
|
353
|
-
styledLine = styledLine.replace("-->", "-.->") + ":::removedLink"
|
|
436
|
+
styledLine = styledLine.replace("-->", "-.->"); // + ":::removedLink"
|
|
437
|
+
linkLines.push("removed");
|
|
354
438
|
if (styledLine.split("|").length === 3) {
|
|
355
439
|
const splits = styledLine.split("|");
|
|
356
|
-
styledLine = splits[0] + "
|
|
440
|
+
styledLine = splits[0] + '|"🟥<i>' + removeQuotes(splits[1]) + '</i>"|' + splits[2];
|
|
357
441
|
}
|
|
358
442
|
}
|
|
359
443
|
else if (isMermaid === true && status === "added" && currentLine.includes('-->')) {
|
|
360
|
-
styledLine = styledLine.replace("-->", "==>") + ":::addedLink"
|
|
444
|
+
styledLine = styledLine.replace("-->", "==>"); // + ":::addedLink"
|
|
445
|
+
linkLines.push("added");
|
|
361
446
|
if (styledLine.split("|").length === 3) {
|
|
362
447
|
const splits = styledLine.split("|");
|
|
363
|
-
styledLine = splits[0] + "
|
|
448
|
+
styledLine = splits[0] + '|"🟩<b>' + removeQuotes(splits[1]) + '</b>"|' + splits[2];
|
|
364
449
|
}
|
|
365
450
|
}
|
|
451
|
+
else if (isMermaid === true && !["added", "removed"].includes(status) &&
|
|
452
|
+
(currentLine.includes('-->') || currentLine.includes('-. Fault .->'))) {
|
|
453
|
+
linkLines.push("unchanged");
|
|
454
|
+
}
|
|
366
455
|
/* jscpd:ignore-end */
|
|
367
456
|
compareMdLines.push(styledLine);
|
|
368
457
|
// Continue processing next lines
|
|
369
|
-
buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, (styledLine.startsWith("|") && isTableStarted));
|
|
458
|
+
buildFinalCompareMarkdown(mixedLines, compareMdLines, isMermaid, (styledLine.startsWith("|") && isTableStarted), linkLines);
|
|
370
459
|
}
|
|
371
460
|
async function buildMermaidMarkdown(commit, flowFile) {
|
|
372
461
|
const flowXml = await git().show([`${commit}:${flowFile}`]);
|
|
@@ -378,4 +467,101 @@ async function buildMermaidMarkdown(commit, flowFile) {
|
|
|
378
467
|
throw new SfError(`Unable to build Graph for flow ${flowFile}: ${err.message}`);
|
|
379
468
|
}
|
|
380
469
|
}
|
|
470
|
+
function removeQuotes(str) {
|
|
471
|
+
if (str.startsWith('"')) {
|
|
472
|
+
str = str.slice(1);
|
|
473
|
+
}
|
|
474
|
+
if (str.endsWith('"')) {
|
|
475
|
+
str = str.slice(0, -1);
|
|
476
|
+
}
|
|
477
|
+
return str;
|
|
478
|
+
}
|
|
479
|
+
export async function generateHistoryDiffMarkdown(flowFile, debugMode) {
|
|
480
|
+
await fs.ensureDir(path.join("docs", "flows"));
|
|
481
|
+
const diffMdFile = path.join("docs", "flows", path.basename(flowFile).replace(".flow-meta.xml", "-history.md"));
|
|
482
|
+
// Compute for all states
|
|
483
|
+
const fileHistory = await git().log({ file: flowFile });
|
|
484
|
+
const flowLabel = path.basename(flowFile, ".flow-meta.xml");
|
|
485
|
+
uxLog(this, c.cyan(`Generating ${flowLabel} markdown diff between ${fileHistory.all.length} Flow states...`));
|
|
486
|
+
const diffMdFiles = [];
|
|
487
|
+
for (let i = 0; i < fileHistory.all.length; i++) {
|
|
488
|
+
const commitAfter = fileHistory.all[i];
|
|
489
|
+
// Initial state
|
|
490
|
+
if (i === fileHistory.all.length - 1) {
|
|
491
|
+
const flowXml = await git().show([`${fileHistory.all[i].hash}:${flowFile}`]);
|
|
492
|
+
const reportDir = await getReportDirectory();
|
|
493
|
+
await fs.ensureDir(path.join(reportDir, "flow-diff"));
|
|
494
|
+
const diffMdFileTmp = path.join(reportDir, 'flow-diff', `${flowLabel}_${moment().format("YYYYMMDD-hhmmss")}.md`);
|
|
495
|
+
const genRes = await generateFlowMarkdownFile(flowFile, flowXml, diffMdFileTmp, { collapsedDetails: false });
|
|
496
|
+
if (!genRes) {
|
|
497
|
+
throw new Error(`Error generating markdown file for flow ${flowFile}`);
|
|
498
|
+
}
|
|
499
|
+
diffMdFiles.push({
|
|
500
|
+
initialVersion: true,
|
|
501
|
+
commitAfter: commitAfter,
|
|
502
|
+
markdown: fs.readFileSync(diffMdFileTmp, "utf8")
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
const commitBefore = fileHistory.all[i + 1];
|
|
507
|
+
const genDiffRes = await generateFlowVisualGitDiff(flowFile, commitBefore.hash, commitAfter.hash, { svgMd: false, mermaidMd: true, debug: debugMode });
|
|
508
|
+
if (genDiffRes.hasFlowDiffs && fs.existsSync(genDiffRes.outputDiffMdFile)) {
|
|
509
|
+
diffMdFiles.push({
|
|
510
|
+
commitBefore: commitBefore,
|
|
511
|
+
commitAfter: commitAfter,
|
|
512
|
+
markdown: fs.readFileSync(genDiffRes.outputDiffMdFile, "utf8")
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
else {
|
|
516
|
+
uxLog(this, c.yellow(`No real flow diff has been found between ${commitBefore.hash} and ${commitAfter.hash}`));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
// Set all the results in a single tabbed markdown
|
|
521
|
+
uxLog(this, c.cyan(`Aggregating results in summary tabbed file ${diffMdFile}...`));
|
|
522
|
+
let finalMd = `# ${flowLabel} history\n\n`;
|
|
523
|
+
for (const diffMdFile of diffMdFiles) {
|
|
524
|
+
finalMd += `=== "${moment(diffMdFile.commitAfter.date).format("ll")}` + (diffMdFile.initialVersion ? " (Initial)" : "") + `"\n\n`;
|
|
525
|
+
finalMd += ` _${moment(diffMdFile.commitAfter.date).format("ll")}, by ${diffMdFile.commitAfter.author_name} in commit ${diffMdFile.commitAfter.message}_\n\n`;
|
|
526
|
+
// Remove title and add indentation for tabs to be displayed
|
|
527
|
+
finalMd += diffMdFile.markdown.split("\n").filter(line => !line.startsWith("# ")).map(line => ` ${line}`).join("\n");
|
|
528
|
+
finalMd += "\n\n";
|
|
529
|
+
}
|
|
530
|
+
await fs.writeFile(diffMdFile, finalMd);
|
|
531
|
+
if (debugMode) {
|
|
532
|
+
await fs.copyFile(diffMdFile, diffMdFile.replace(".md", ".mermaid.md"));
|
|
533
|
+
}
|
|
534
|
+
const genSvgRes = await generateMarkdownFileWithMermaid(diffMdFile);
|
|
535
|
+
if (!genSvgRes) {
|
|
536
|
+
throw new Error("Error generating mermaid markdown file");
|
|
537
|
+
}
|
|
538
|
+
// Fix indentation for mermaid SVG links
|
|
539
|
+
const diffMarkdown = await fs.readFile(diffMdFile, "utf8");
|
|
540
|
+
const diffMarkdownFixed = diffMarkdown.split("\n").map(line => {
|
|
541
|
+
if (line.startsWith("![diagram]")) {
|
|
542
|
+
return ` ${line}`;
|
|
543
|
+
}
|
|
544
|
+
return line;
|
|
545
|
+
}).join("\n");
|
|
546
|
+
await fs.writeFile(diffMdFile, diffMarkdownFixed);
|
|
547
|
+
// Add link to main flow doc
|
|
548
|
+
const mainFlowDoc = path.join("docs", "flows", path.basename(flowFile).replace(".flow-meta.xml", ".md"));
|
|
549
|
+
if (fs.existsSync(mainFlowDoc)) {
|
|
550
|
+
const mainFlowDocContent = await fs.readFile(mainFlowDoc, "utf8");
|
|
551
|
+
const mainFlowDocLink = `[_View History_](${path.basename(flowFile).replace(".flow-meta.xml", "-history.md")})`;
|
|
552
|
+
if (!mainFlowDocContent.includes(mainFlowDocLink)) {
|
|
553
|
+
let replaced = false;
|
|
554
|
+
const updatedFlowDocContent = mainFlowDocContent.split("\n").map(line => {
|
|
555
|
+
if (line.startsWith("![") && replaced === false) {
|
|
556
|
+
replaced = true;
|
|
557
|
+
return `${line}\n\n ${mainFlowDocLink}\n`;
|
|
558
|
+
}
|
|
559
|
+
return line;
|
|
560
|
+
}).join("\n");
|
|
561
|
+
await fs.writeFile(mainFlowDoc, updatedFlowDocContent);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
uxLog(this, c.green(`Markdown diff between ${fileHistory.all.length} Flow states generated in ${diffMdFile}`));
|
|
565
|
+
return diffMdFile;
|
|
566
|
+
}
|
|
381
567
|
//# sourceMappingURL=mermaidUtils.js.map
|