diffintel 0.2.2 → 0.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/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/explain.d.ts +1 -0
- package/dist/commands/explain.js +7 -0
- package/dist/commands/explain.js.map +1 -1
- package/dist/explain/ast-diff.d.ts +2 -9
- package/dist/explain/ast-diff.js +8 -74
- package/dist/explain/ast-diff.js.map +1 -1
- package/dist/explain/generic-extractor.d.ts +13 -0
- package/dist/explain/generic-extractor.js +85 -0
- package/dist/explain/generic-extractor.js.map +1 -0
- package/dist/explain/html-report.js +116 -5
- package/dist/explain/html-report.js.map +1 -1
- package/dist/explain/language-configs.d.ts +31 -0
- package/dist/explain/language-configs.js +514 -0
- package/dist/explain/language-configs.js.map +1 -0
- package/dist/explain/llm-explain.js +5 -1
- package/dist/explain/llm-explain.js.map +1 -1
- package/dist/explain/markdown-summary.d.ts +5 -0
- package/dist/explain/markdown-summary.js +98 -0
- package/dist/explain/markdown-summary.js.map +1 -0
- package/dist/explain/types.d.ts +1 -0
- package/dist/parsing/index.d.ts +1 -1
- package/dist/parsing/index.js +3 -1
- package/dist/parsing/index.js.map +1 -1
- package/dist/parsing/parser.d.ts +4 -0
- package/dist/parsing/parser.js +69 -2
- package/dist/parsing/parser.js.map +1 -1
- package/package.json +12 -1
package/dist/cli.js
CHANGED
|
@@ -16,6 +16,7 @@ commander_1.program
|
|
|
16
16
|
.option("--base <ref>", "Base ref to diff from (default: origin/main)")
|
|
17
17
|
.option("--head <ref>", "Head ref to diff to (default: HEAD)")
|
|
18
18
|
.option("--out <file>", "Output HTML file path (default: explain-report.html)")
|
|
19
|
+
.option("--summary <file>", "Output markdown summary file path (default: <out>.md)")
|
|
19
20
|
.action(async (opts) => {
|
|
20
21
|
require("dotenv").config();
|
|
21
22
|
const { run } = require("./commands/explain");
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,mEAAkC;AAElC,mBAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,sBAAG,CAAC,OAAO,CAAC,CAAC;AAExB,mBAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,cAAc,EAAE,8CAA8C,CAAC;KACtE,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC;KAC7D,MAAM,CAAC,cAAc,EAAE,sDAAsD,CAAC;KAC9E,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEL,mBAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,mEAAkC;AAElC,mBAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,sBAAG,CAAC,OAAO,CAAC,CAAC;AAExB,mBAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,cAAc,EAAE,8CAA8C,CAAC;KACtE,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC;KAC7D,MAAM,CAAC,cAAc,EAAE,sDAAsD,CAAC;KAC9E,MAAM,CAAC,kBAAkB,EAAE,uDAAuD,CAAC;KACnF,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3B,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEL,mBAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/dist/commands/explain.js
CHANGED
|
@@ -9,6 +9,7 @@ const git_diff_1 = require("../explain/git-diff");
|
|
|
9
9
|
const ast_diff_1 = require("../explain/ast-diff");
|
|
10
10
|
const llm_explain_1 = require("../explain/llm-explain");
|
|
11
11
|
const html_report_1 = require("../explain/html-report");
|
|
12
|
+
const markdown_summary_1 = require("../explain/markdown-summary");
|
|
12
13
|
async function run(opts) {
|
|
13
14
|
const baseRef = opts.base || "origin/main";
|
|
14
15
|
const headRef = opts.head || "HEAD";
|
|
@@ -40,6 +41,7 @@ async function run(opts) {
|
|
|
40
41
|
explanation = {
|
|
41
42
|
title: buildAutoTitle(fileDiffs.length, totalAdditions, totalDeletions),
|
|
42
43
|
description: "",
|
|
44
|
+
impact: [],
|
|
43
45
|
fixes: [],
|
|
44
46
|
risks: [],
|
|
45
47
|
fileExplanations: [],
|
|
@@ -60,6 +62,10 @@ async function run(opts) {
|
|
|
60
62
|
};
|
|
61
63
|
const html = (0, html_report_1.renderReport)(report);
|
|
62
64
|
fs_1.default.writeFileSync(outFile, html, "utf-8");
|
|
65
|
+
// Generate markdown summary alongside HTML
|
|
66
|
+
const summaryFile = opts.summary || outFile.replace(/\.html$/, ".md");
|
|
67
|
+
const markdown = (0, markdown_summary_1.renderMarkdownSummary)(report);
|
|
68
|
+
fs_1.default.writeFileSync(summaryFile, markdown, "utf-8");
|
|
63
69
|
console.error(`\n${explanation.title}`);
|
|
64
70
|
console.error(`${fileDiffs.length} files | +${totalAdditions} -${totalDeletions}`);
|
|
65
71
|
if (explanation.fixes.length > 0) {
|
|
@@ -69,6 +75,7 @@ async function run(opts) {
|
|
|
69
75
|
console.error(`Risks: ${explanation.risks.map((r) => `[${r.level}] ${r.description}`).join("; ")}`);
|
|
70
76
|
}
|
|
71
77
|
console.error(`\nReport: ${outFile}`);
|
|
78
|
+
console.error(`Summary: ${summaryFile}`);
|
|
72
79
|
return 0;
|
|
73
80
|
}
|
|
74
81
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import { FileDiff, FileAnalysis
|
|
2
|
-
interface Declaration {
|
|
3
|
-
name: string;
|
|
4
|
-
type: ChangeType;
|
|
5
|
-
text: string;
|
|
6
|
-
startLine: number;
|
|
7
|
-
}
|
|
1
|
+
import { FileDiff, FileAnalysis } from "./types";
|
|
8
2
|
export declare function analyzeFile(diff: FileDiff): FileAnalysis;
|
|
9
|
-
export declare function extractDeclarations(source: string, ext: string): Declaration[];
|
|
10
|
-
export {};
|
|
3
|
+
export declare function extractDeclarations(source: string, ext: string): import("./generic-extractor").Declaration[];
|
package/dist/explain/ast-diff.js
CHANGED
|
@@ -6,11 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.analyzeFile = analyzeFile;
|
|
7
7
|
exports.extractDeclarations = extractDeclarations;
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const generic_extractor_1 = require("./generic-extractor");
|
|
10
|
+
const language_configs_1 = require("./language-configs");
|
|
9
11
|
const parser_1 = require("../parsing/parser");
|
|
10
|
-
const SUPPORTED_EXTS = new Set([".js", ".ts", ".tsx", ".jsx"]);
|
|
11
12
|
function analyzeFile(diff) {
|
|
12
13
|
const ext = path_1.default.extname(diff.path);
|
|
13
|
-
|
|
14
|
+
const config = (0, language_configs_1.getConfigForExtension)(ext);
|
|
15
|
+
const parseable = (0, parser_1.hasLanguageForExt)(ext);
|
|
16
|
+
// If no config and not parseable, return without structural analysis
|
|
17
|
+
if (!config && !parseable) {
|
|
14
18
|
return {
|
|
15
19
|
path: diff.path,
|
|
16
20
|
status: diff.status,
|
|
@@ -21,7 +25,7 @@ function analyzeFile(diff) {
|
|
|
21
25
|
rawDiff: diff.hunks,
|
|
22
26
|
};
|
|
23
27
|
}
|
|
24
|
-
const language = ext.replace(".", "");
|
|
28
|
+
const language = config?.id || ext.replace(".", "");
|
|
25
29
|
const structuralChanges = [];
|
|
26
30
|
// Extract base declarations for context (what existed before this change)
|
|
27
31
|
const baseDecls = diff.oldContent ? extractDeclarations(diff.oldContent, ext) : [];
|
|
@@ -99,76 +103,6 @@ function analyzeFile(diff) {
|
|
|
99
103
|
};
|
|
100
104
|
}
|
|
101
105
|
function extractDeclarations(source, ext) {
|
|
102
|
-
|
|
103
|
-
return [];
|
|
104
|
-
const { tree } = (0, parser_1.parseSource)(source, ext);
|
|
105
|
-
const decls = [];
|
|
106
|
-
const root = tree.rootNode;
|
|
107
|
-
for (let i = 0; i < root.childCount; i++) {
|
|
108
|
-
const node = root.child(i);
|
|
109
|
-
const extracted = extractFromNode(node);
|
|
110
|
-
if (extracted) {
|
|
111
|
-
decls.push(...extracted);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return decls;
|
|
115
|
-
}
|
|
116
|
-
function extractFromNode(node) {
|
|
117
|
-
const type = node.type;
|
|
118
|
-
if (type === "function_declaration") {
|
|
119
|
-
const name = node.childForFieldName("name")?.text || "<anonymous>";
|
|
120
|
-
return [{ name, type: "function", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
121
|
-
}
|
|
122
|
-
if (type === "class_declaration") {
|
|
123
|
-
const name = node.childForFieldName("name")?.text || "<anonymous>";
|
|
124
|
-
return [{ name, type: "class", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
125
|
-
}
|
|
126
|
-
if (type === "import_statement") {
|
|
127
|
-
const source = node.childForFieldName("source")?.text || node.text;
|
|
128
|
-
return [{ name: source, type: "import", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
129
|
-
}
|
|
130
|
-
if (type === "export_statement") {
|
|
131
|
-
// Named export with declaration inside
|
|
132
|
-
const decl = node.childForFieldName("declaration");
|
|
133
|
-
if (decl) {
|
|
134
|
-
const inner = extractFromNode(decl);
|
|
135
|
-
if (inner) {
|
|
136
|
-
return inner.map((d) => ({ ...d, type: "export" }));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const name = node.text.slice(0, 60);
|
|
140
|
-
return [{ name, type: "export", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
141
|
-
}
|
|
142
|
-
if (type === "variable_declaration" || type === "lexical_declaration") {
|
|
143
|
-
const results = [];
|
|
144
|
-
for (let i = 0; i < node.childCount; i++) {
|
|
145
|
-
const child = node.child(i);
|
|
146
|
-
if (child.type === "variable_declarator") {
|
|
147
|
-
const name = child.childForFieldName("name")?.text || "<unknown>";
|
|
148
|
-
// Check if value is an arrow function or function expression
|
|
149
|
-
const value = child.childForFieldName("value");
|
|
150
|
-
const isFn = value && (value.type === "arrow_function" || value.type === "function");
|
|
151
|
-
results.push({
|
|
152
|
-
name,
|
|
153
|
-
type: isFn ? "function" : "variable",
|
|
154
|
-
text: node.text,
|
|
155
|
-
startLine: node.startPosition.row + 1,
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (results.length)
|
|
160
|
-
return results;
|
|
161
|
-
}
|
|
162
|
-
// Expression statements like module.exports = ...
|
|
163
|
-
if (type === "expression_statement") {
|
|
164
|
-
const expr = node.child(0);
|
|
165
|
-
if (expr?.type === "assignment_expression") {
|
|
166
|
-
const left = expr.childForFieldName("left");
|
|
167
|
-
if (left?.text?.startsWith("module.exports")) {
|
|
168
|
-
return [{ name: "module.exports", type: "export", text: node.text, startLine: node.startPosition.row + 1 }];
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return null;
|
|
106
|
+
return (0, generic_extractor_1.extractDeclarationsGeneric)(source, ext);
|
|
173
107
|
}
|
|
174
108
|
//# sourceMappingURL=ast-diff.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-diff.js","sourceRoot":"","sources":["../../src/explain/ast-diff.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"ast-diff.js","sourceRoot":"","sources":["../../src/explain/ast-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ChangeType } from "./types";
|
|
2
|
+
export interface Declaration {
|
|
3
|
+
name: string;
|
|
4
|
+
type: ChangeType;
|
|
5
|
+
text: string;
|
|
6
|
+
startLine: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Extract declarations from source code using the config-driven system.
|
|
10
|
+
* Falls back to extracting named top-level nodes as "other" when no config exists
|
|
11
|
+
* but the language is parseable.
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractDeclarationsGeneric(source: string, ext: string): Declaration[];
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractDeclarationsGeneric = extractDeclarationsGeneric;
|
|
4
|
+
const language_configs_1 = require("./language-configs");
|
|
5
|
+
const parser_1 = require("../parsing/parser");
|
|
6
|
+
/**
|
|
7
|
+
* Extract declarations from source code using the config-driven system.
|
|
8
|
+
* Falls back to extracting named top-level nodes as "other" when no config exists
|
|
9
|
+
* but the language is parseable.
|
|
10
|
+
*/
|
|
11
|
+
function extractDeclarationsGeneric(source, ext) {
|
|
12
|
+
if (!source.trim())
|
|
13
|
+
return [];
|
|
14
|
+
const config = (0, language_configs_1.getConfigForExtension)(ext);
|
|
15
|
+
// Try to parse — if we can't, return empty
|
|
16
|
+
let tree;
|
|
17
|
+
try {
|
|
18
|
+
const result = (0, parser_1.parseSource)(source, ext);
|
|
19
|
+
tree = result.tree;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const root = tree.rootNode;
|
|
25
|
+
const decls = [];
|
|
26
|
+
for (let i = 0; i < root.childCount; i++) {
|
|
27
|
+
const node = root.child(i);
|
|
28
|
+
const extracted = config
|
|
29
|
+
? extractWithConfig(node, config)
|
|
30
|
+
: extractFallback(node);
|
|
31
|
+
if (extracted) {
|
|
32
|
+
decls.push(...extracted);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return decls;
|
|
36
|
+
}
|
|
37
|
+
function extractWithConfig(node, config) {
|
|
38
|
+
// Check for wrapper types (e.g. Python decorated_definition)
|
|
39
|
+
let targetNode = node;
|
|
40
|
+
if (config.wrapperTypes && node.type in config.wrapperTypes) {
|
|
41
|
+
const fieldName = config.wrapperTypes[node.type];
|
|
42
|
+
const inner = node.childForFieldName(fieldName);
|
|
43
|
+
if (inner) {
|
|
44
|
+
targetNode = inner;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const nodeConfig = config.nodeTypeMap[targetNode.type];
|
|
48
|
+
if (!nodeConfig)
|
|
49
|
+
return null;
|
|
50
|
+
if (nodeConfig.extractor) {
|
|
51
|
+
const results = nodeConfig.extractor(targetNode);
|
|
52
|
+
if (!results)
|
|
53
|
+
return null;
|
|
54
|
+
return results.map((r) => ({
|
|
55
|
+
name: r.name,
|
|
56
|
+
type: r.changeType || nodeConfig.changeType,
|
|
57
|
+
text: node.text,
|
|
58
|
+
startLine: node.startPosition.row + 1,
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
// Default: extract name via childForFieldName("name")
|
|
62
|
+
const name = targetNode.childForFieldName("name")?.text || "<anonymous>";
|
|
63
|
+
return [{
|
|
64
|
+
name,
|
|
65
|
+
type: nodeConfig.changeType,
|
|
66
|
+
text: node.text,
|
|
67
|
+
startLine: node.startPosition.row + 1,
|
|
68
|
+
}];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Fallback for languages without a config.
|
|
72
|
+
* Extracts any top-level node that has a "name" field.
|
|
73
|
+
*/
|
|
74
|
+
function extractFallback(node) {
|
|
75
|
+
const name = node.childForFieldName("name")?.text;
|
|
76
|
+
if (!name)
|
|
77
|
+
return null;
|
|
78
|
+
return [{
|
|
79
|
+
name,
|
|
80
|
+
type: "other",
|
|
81
|
+
text: node.text,
|
|
82
|
+
startLine: node.startPosition.row + 1,
|
|
83
|
+
}];
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=generic-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generic-extractor.js","sourceRoot":"","sources":["../../src/explain/generic-extractor.ts"],"names":[],"mappings":";;AAiBA,gEA+BC;AA9CD,yDAA2E;AAC3E,8CAAgD;AAShD;;;;GAIG;AACH,SAAgB,0BAA0B,CACxC,MAAc,EACd,GAAW;IAEX,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAC;IAE9B,MAAM,MAAM,GAAG,IAAA,wCAAqB,EAAC,GAAG,CAAC,CAAC;IAE1C,2CAA2C;IAC3C,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,oBAAW,EAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACxC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC3B,MAAM,KAAK,GAAkB,EAAE,CAAC;IAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,MAAM;YACtB,CAAC,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC;YACjC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAgB,EAAE,MAAsB;IACjE,6DAA6D;IAC7D,IAAI,UAAU,GAAG,IAAI,CAAC;IACtB,IAAI,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QAC5D,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,KAAK,EAAE,CAAC;YACV,UAAU,GAAG,KAAK,CAAC;QACrB,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAE7B,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACzB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC,UAAU;YAC3C,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC;SACtC,CAAC,CAAC,CAAC;IACN,CAAC;IAED,sDAAsD;IACtD,MAAM,IAAI,GAAG,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,IAAI,IAAI,aAAa,CAAC;IACzE,OAAO,CAAC;YACN,IAAI;YACJ,IAAI,EAAE,UAAU,CAAC,UAAU;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC;SACtC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,IAAgB;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;IAClD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,OAAO,CAAC;YACN,IAAI;YACJ,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC;SACtC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -8,8 +8,15 @@ function escapeHtml(str) {
|
|
|
8
8
|
.replace(/>/g, ">")
|
|
9
9
|
.replace(/"/g, """);
|
|
10
10
|
}
|
|
11
|
+
const MAX_DIFF_LINES = 80;
|
|
11
12
|
function renderReport(report) {
|
|
12
13
|
const { explanation, summary, files } = report;
|
|
14
|
+
// --- Structural summary ---
|
|
15
|
+
const structuralSummaryHtml = buildStructuralSummary(files);
|
|
16
|
+
// --- Impact section ---
|
|
17
|
+
const impactHtml = explanation.impact.length > 0
|
|
18
|
+
? `<div class="impact-section">${explanation.impact.map((item) => `<span>${escapeHtml(item)}</span>`).join("")}</div>`
|
|
19
|
+
: "";
|
|
13
20
|
// --- Fixes section ---
|
|
14
21
|
const fixesHtml = explanation.fixes.length > 0
|
|
15
22
|
? explanation.fixes.map((f) => `<div class="fix-item"><span class="fix-icon">✓</span> ${escapeHtml(f.description)}</div>`).join("\n")
|
|
@@ -21,6 +28,8 @@ function renderReport(report) {
|
|
|
21
28
|
return `<div class="risk-item ${cls}"><span class="risk-label">${r.level}</span> ${escapeHtml(r.description)}</div>`;
|
|
22
29
|
}).join("\n")
|
|
23
30
|
: "";
|
|
31
|
+
// --- Common changes ---
|
|
32
|
+
const commonChangesHtml = buildCommonChanges(files);
|
|
24
33
|
// --- Per-file detail cards ---
|
|
25
34
|
// Build a map for both summary and notes
|
|
26
35
|
const fileExplanationData = new Map(explanation.fileExplanations.map((fe) => [fe.path, fe]));
|
|
@@ -35,9 +44,7 @@ function renderReport(report) {
|
|
|
35
44
|
const notesHtml = feData?.notes && feData.notes.length > 0
|
|
36
45
|
? `<div class="file-notes"><div class="file-notes-label">Things to note</div><ul>${feData.notes.map((n) => `<li>${escapeHtml(n)}</li>`).join("")}</ul></div>`
|
|
37
46
|
: "";
|
|
38
|
-
const diffHtml = f.rawDiff
|
|
39
|
-
? `<details class="diff-toggle"><summary>View diff</summary><pre class="diff-block">${colorDiff(f.rawDiff)}</pre></details>`
|
|
40
|
-
: "";
|
|
47
|
+
const diffHtml = f.rawDiff ? renderDiff(f.rawDiff) : "";
|
|
41
48
|
return `<div class="file-card">
|
|
42
49
|
<div class="file-header">
|
|
43
50
|
<span class="file-status status-${f.status}">${f.status}</span>
|
|
@@ -88,7 +95,7 @@ function renderReport(report) {
|
|
|
88
95
|
|
|
89
96
|
/* Stats */
|
|
90
97
|
.stats {
|
|
91
|
-
display: flex; gap: 20px; margin-bottom:
|
|
98
|
+
display: flex; gap: 20px; margin-bottom: 16px;
|
|
92
99
|
}
|
|
93
100
|
.stat {
|
|
94
101
|
font-size: 13px; color: #777; font-weight: 500;
|
|
@@ -97,6 +104,24 @@ function renderReport(report) {
|
|
|
97
104
|
.stat.additions b { color: #16a34a; }
|
|
98
105
|
.stat.deletions b { color: #dc2626; }
|
|
99
106
|
|
|
107
|
+
/* Structural summary */
|
|
108
|
+
.structural-summary {
|
|
109
|
+
font-size: 14px; color: #555; margin-bottom: 8px;
|
|
110
|
+
padding: 10px 14px; background: #f8fafc; border-radius: 6px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Impact */
|
|
114
|
+
.impact-section {
|
|
115
|
+
font-size: 14px; color: #555; margin-bottom: 28px;
|
|
116
|
+
padding: 10px 14px; background: #f8fafc; border-radius: 6px;
|
|
117
|
+
}
|
|
118
|
+
.impact-section span {
|
|
119
|
+
display: inline-block; margin-right: 12px;
|
|
120
|
+
}
|
|
121
|
+
.impact-section span::before {
|
|
122
|
+
content: "\\2022"; margin-right: 5px; color: #94a3b8;
|
|
123
|
+
}
|
|
124
|
+
|
|
100
125
|
/* Description — article lede */
|
|
101
126
|
.description {
|
|
102
127
|
font-size: 18px; line-height: 1.85; margin-bottom: 36px;
|
|
@@ -141,6 +166,15 @@ function renderReport(report) {
|
|
|
141
166
|
font-size: 14px; color: #64748b;
|
|
142
167
|
}
|
|
143
168
|
|
|
169
|
+
/* Common changes */
|
|
170
|
+
.common-changes { margin-bottom: 24px; }
|
|
171
|
+
.common-change-item {
|
|
172
|
+
padding: 6px 14px; font-size: 13px; color: #555;
|
|
173
|
+
border-left: 2px solid #cbd5e1; margin-bottom: 4px;
|
|
174
|
+
}
|
|
175
|
+
.common-change-item code { font-size: 12px; }
|
|
176
|
+
.common-change-files { font-size: 12px; color: #888; margin-left: 4px; }
|
|
177
|
+
|
|
144
178
|
/* File cards */
|
|
145
179
|
.file-card {
|
|
146
180
|
border: 1px solid #e5e7eb; border-radius: 8px;
|
|
@@ -163,7 +197,7 @@ function renderReport(report) {
|
|
|
163
197
|
|
|
164
198
|
.file-summary {
|
|
165
199
|
padding: 12px 14px; font-size: 14px; color: #444;
|
|
166
|
-
border-bottom: 1px solid #f5f5f5;
|
|
200
|
+
border-bottom: 1px solid #f5f5f5; font-weight: bold
|
|
167
201
|
}
|
|
168
202
|
.file-notes {
|
|
169
203
|
padding: 10px 14px; background: #fafbff;
|
|
@@ -206,6 +240,11 @@ function renderReport(report) {
|
|
|
206
240
|
font-family: "SF Mono", Menlo, monospace;
|
|
207
241
|
margin: 0; border-radius: 0;
|
|
208
242
|
}
|
|
243
|
+
.diff-truncation {
|
|
244
|
+
padding: 6px 14px; font-size: 12px; color: #888;
|
|
245
|
+
border-top: 1px solid #333; background: #252525;
|
|
246
|
+
}
|
|
247
|
+
.diff-show-full { cursor: pointer; color: #60a5fa; text-decoration: underline; background: none; border: none; font-size: 12px; }
|
|
209
248
|
|
|
210
249
|
/* Footer */
|
|
211
250
|
.footer {
|
|
@@ -230,6 +269,10 @@ function renderReport(report) {
|
|
|
230
269
|
<div class="stat deletions"><b>-${summary.deletions}</b> removed</div>
|
|
231
270
|
</div>
|
|
232
271
|
|
|
272
|
+
${structuralSummaryHtml}
|
|
273
|
+
|
|
274
|
+
${impactHtml}
|
|
275
|
+
|
|
233
276
|
${explanation.description
|
|
234
277
|
? `<div class="description">${escapeHtml(explanation.description)}</div>`
|
|
235
278
|
: `<div class="ast-only-notice">Structural analysis only — set ANTHROPIC_API_KEY for AI-powered explanations.</div>`}
|
|
@@ -238,6 +281,8 @@ function renderReport(report) {
|
|
|
238
281
|
|
|
239
282
|
${risksHtml ? `<h2>Things to watch</h2>\n${risksHtml}` : ""}
|
|
240
283
|
|
|
284
|
+
${commonChangesHtml}
|
|
285
|
+
|
|
241
286
|
<h2>Changed files</h2>
|
|
242
287
|
${fileCards}
|
|
243
288
|
|
|
@@ -247,6 +292,72 @@ function renderReport(report) {
|
|
|
247
292
|
</body>
|
|
248
293
|
</html>`;
|
|
249
294
|
}
|
|
295
|
+
function renderDiff(rawDiff) {
|
|
296
|
+
const lines = rawDiff.split("\n");
|
|
297
|
+
const totalLines = lines.length;
|
|
298
|
+
if (totalLines <= MAX_DIFF_LINES) {
|
|
299
|
+
return `<details class="diff-toggle"><summary>View diff</summary><pre class="diff-block">${colorDiff(rawDiff)}</pre></details>`;
|
|
300
|
+
}
|
|
301
|
+
const truncated = lines.slice(0, MAX_DIFF_LINES).join("\n");
|
|
302
|
+
const id = `diff-${Math.random().toString(36).slice(2, 8)}`;
|
|
303
|
+
return `<details class="diff-toggle"><summary>View diff</summary><pre class="diff-block" id="${id}-short">${colorDiff(truncated)}</pre><div class="diff-truncation" id="${id}-notice">Showing ${MAX_DIFF_LINES} of ${totalLines} lines <button class="diff-show-full" onclick="document.getElementById('${id}-short').style.display='none';document.getElementById('${id}-full').style.display='block';this.parentElement.style.display='none';">Show all</button></div><pre class="diff-block" id="${id}-full" style="display:none">${colorDiff(rawDiff)}</pre></details>`;
|
|
304
|
+
}
|
|
305
|
+
function buildStructuralSummary(files) {
|
|
306
|
+
const counts = new Map();
|
|
307
|
+
for (const f of files) {
|
|
308
|
+
for (const c of f.structuralChanges) {
|
|
309
|
+
const key = `${c.action}:${c.type}`;
|
|
310
|
+
counts.set(key, (counts.get(key) || 0) + 1);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (counts.size === 0)
|
|
314
|
+
return "";
|
|
315
|
+
const actionOrder = ["added", "modified", "removed"];
|
|
316
|
+
const parts = [];
|
|
317
|
+
for (const action of actionOrder) {
|
|
318
|
+
const items = [];
|
|
319
|
+
for (const [key, count] of counts) {
|
|
320
|
+
if (key.startsWith(action + ":")) {
|
|
321
|
+
const type = key.split(":")[1];
|
|
322
|
+
items.push(`${count} ${type}${count !== 1 ? "s" : ""}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (items.length > 0) {
|
|
326
|
+
parts.push(`${items.join(", ")} ${action}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (parts.length === 0)
|
|
330
|
+
return "";
|
|
331
|
+
const filesWithChanges = files.filter((f) => f.structuralChanges.length > 0).length;
|
|
332
|
+
return `<div class="structural-summary">${parts.join(" · ")} across ${filesWithChanges} file${filesWithChanges !== 1 ? "s" : ""}</div>`;
|
|
333
|
+
}
|
|
334
|
+
function buildCommonChanges(files) {
|
|
335
|
+
// Group changes by signature
|
|
336
|
+
const groups = new Map();
|
|
337
|
+
for (const f of files) {
|
|
338
|
+
for (const c of f.structuralChanges) {
|
|
339
|
+
const sig = `${c.action}:${c.type}:${c.name}`;
|
|
340
|
+
const group = groups.get(sig);
|
|
341
|
+
if (group) {
|
|
342
|
+
group.filePaths.push(f.path);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
groups.set(sig, { change: c, filePaths: [f.path] });
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Filter to changes appearing in 2+ files
|
|
350
|
+
const common = [...groups.values()].filter((g) => g.filePaths.length >= 2);
|
|
351
|
+
if (common.length === 0)
|
|
352
|
+
return "";
|
|
353
|
+
const items = common.map((g) => {
|
|
354
|
+
const { change, filePaths } = g;
|
|
355
|
+
const actionSymbol = change.action === "added" ? "+" : change.action === "removed" ? "-" : "~";
|
|
356
|
+
const fileList = filePaths.map((p) => `<code>${escapeHtml(p)}</code>`).join(", ");
|
|
357
|
+
return `<div class="common-change-item">${actionSymbol} <code>${escapeHtml(change.name)}</code> (${change.type})<span class="common-change-files"> in ${fileList}</span></div>`;
|
|
358
|
+
}).join("\n");
|
|
359
|
+
return `<h2>Common changes</h2>\n${items}`;
|
|
360
|
+
}
|
|
250
361
|
function colorDiff(diff) {
|
|
251
362
|
return escapeHtml(diff)
|
|
252
363
|
.split("\n")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-report.js","sourceRoot":"","sources":["../../src/explain/html-report.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"html-report.js","sourceRoot":"","sources":["../../src/explain/html-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SyntaxNode } from "../parsing/parser";
|
|
2
|
+
import { ChangeType } from "./types";
|
|
3
|
+
export interface ExtractedDecl {
|
|
4
|
+
name: string;
|
|
5
|
+
changeType?: ChangeType;
|
|
6
|
+
}
|
|
7
|
+
export interface NodeTypeConfig {
|
|
8
|
+
changeType: ChangeType;
|
|
9
|
+
/**
|
|
10
|
+
* Custom extractor for nodes needing special name/type logic.
|
|
11
|
+
* Return null to skip the node entirely.
|
|
12
|
+
* Return array for nodes containing multiple declarations.
|
|
13
|
+
* If omitted, default: [{ name: node.childForFieldName("name")?.text }]
|
|
14
|
+
*/
|
|
15
|
+
extractor?: (node: SyntaxNode) => ExtractedDecl[] | null;
|
|
16
|
+
}
|
|
17
|
+
export interface LanguageConfig {
|
|
18
|
+
id: string;
|
|
19
|
+
extensions: string[];
|
|
20
|
+
treeSitterPackage: string;
|
|
21
|
+
/** Sub-property to access on the module (e.g. "php" for tree-sitter-php which exports { php, php_only }) */
|
|
22
|
+
treeSitterSubProperty?: string;
|
|
23
|
+
nodeTypeMap: Record<string, NodeTypeConfig>;
|
|
24
|
+
/** Wrapper nodes that contain the real declaration (e.g. Python decorated_definition) */
|
|
25
|
+
wrapperTypes?: Record<string, string>;
|
|
26
|
+
}
|
|
27
|
+
export declare const languageConfigs: LanguageConfig[];
|
|
28
|
+
/** Look up a language config by file extension */
|
|
29
|
+
export declare function getConfigForExtension(ext: string): LanguageConfig | null;
|
|
30
|
+
/** Get all supported file extensions across all configs */
|
|
31
|
+
export declare function getAllSupportedExtensions(): Set<string>;
|