glassbox 0.4.3 → 0.4.4
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 +158 -50
- package/dist/client/app.global.js +8 -8
- package/dist/client/styles.css +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4332,6 +4332,9 @@ function jsx(tag, props) {
|
|
|
4332
4332
|
const childStr = children != null ? renderChildren(children) : "";
|
|
4333
4333
|
return new SafeHtml(`<${tag}${attrStr}>${childStr}</${tag}>`);
|
|
4334
4334
|
}
|
|
4335
|
+
function Fragment({ children }) {
|
|
4336
|
+
return new SafeHtml(children != null ? renderChildren(children) : "");
|
|
4337
|
+
}
|
|
4335
4338
|
|
|
4336
4339
|
// src/icons.tsx
|
|
4337
4340
|
var S14 = { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" };
|
|
@@ -4392,6 +4395,64 @@ function IconActualSize() {
|
|
|
4392
4395
|
] });
|
|
4393
4396
|
}
|
|
4394
4397
|
|
|
4398
|
+
// src/utils/charDiff.ts
|
|
4399
|
+
function charDiff(oldStr, newStr) {
|
|
4400
|
+
if (!oldStr && !newStr) return null;
|
|
4401
|
+
if (oldStr === newStr) return null;
|
|
4402
|
+
const lcs = lcsTable(oldStr, newStr);
|
|
4403
|
+
const lcsLen = lcs[oldStr.length][newStr.length];
|
|
4404
|
+
const maxLen = Math.max(oldStr.length, newStr.length);
|
|
4405
|
+
if (maxLen === 0) return null;
|
|
4406
|
+
if (lcsLen / maxLen < 0.2) return null;
|
|
4407
|
+
const oldCommon = /* @__PURE__ */ new Set();
|
|
4408
|
+
const newCommon = /* @__PURE__ */ new Set();
|
|
4409
|
+
let i = oldStr.length, j = newStr.length;
|
|
4410
|
+
while (i > 0 && j > 0) {
|
|
4411
|
+
if (oldStr[i - 1] === newStr[j - 1]) {
|
|
4412
|
+
oldCommon.add(i - 1);
|
|
4413
|
+
newCommon.add(j - 1);
|
|
4414
|
+
i--;
|
|
4415
|
+
j--;
|
|
4416
|
+
} else if (lcs[i - 1][j] > lcs[i][j - 1]) {
|
|
4417
|
+
i--;
|
|
4418
|
+
} else {
|
|
4419
|
+
j--;
|
|
4420
|
+
}
|
|
4421
|
+
}
|
|
4422
|
+
return {
|
|
4423
|
+
oldSegments: buildSegments(oldStr, oldCommon),
|
|
4424
|
+
newSegments: buildSegments(newStr, newCommon)
|
|
4425
|
+
};
|
|
4426
|
+
}
|
|
4427
|
+
function lcsTable(a, b) {
|
|
4428
|
+
const m = a.length, n = b.length;
|
|
4429
|
+
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
|
|
4430
|
+
for (let i = 1; i <= m; i++) {
|
|
4431
|
+
for (let j = 1; j <= n; j++) {
|
|
4432
|
+
dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] + 1 : Math.max(dp[i - 1][j], dp[i][j - 1]);
|
|
4433
|
+
}
|
|
4434
|
+
}
|
|
4435
|
+
return dp;
|
|
4436
|
+
}
|
|
4437
|
+
function buildSegments(str, commonPositions) {
|
|
4438
|
+
const segments = [];
|
|
4439
|
+
let current = "";
|
|
4440
|
+
let currentChanged = false;
|
|
4441
|
+
for (let i = 0; i < str.length; i++) {
|
|
4442
|
+
const changed = !commonPositions.has(i);
|
|
4443
|
+
if (changed !== currentChanged && current.length > 0) {
|
|
4444
|
+
segments.push({ text: current, changed: currentChanged });
|
|
4445
|
+
current = "";
|
|
4446
|
+
}
|
|
4447
|
+
currentChanged = changed;
|
|
4448
|
+
current += str[i];
|
|
4449
|
+
}
|
|
4450
|
+
if (current.length > 0) {
|
|
4451
|
+
segments.push({ text: current, changed: currentChanged });
|
|
4452
|
+
}
|
|
4453
|
+
return segments;
|
|
4454
|
+
}
|
|
4455
|
+
|
|
4395
4456
|
// src/components/imageDiff.tsx
|
|
4396
4457
|
function ImageDiff({ file, diff, fontWarning, baseWidth, baseHeight }) {
|
|
4397
4458
|
const fileId = file.id;
|
|
@@ -4519,7 +4580,7 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4519
4580
|
"data-new-line": group.pair.left?.newNum ?? group.pair.right?.newNum ?? "",
|
|
4520
4581
|
children: [
|
|
4521
4582
|
/* @__PURE__ */ jsx("span", { className: "gutter", "data-line-number": group.pair.left?.oldNum ?? "" }),
|
|
4522
|
-
/* @__PURE__ */ jsx("span", { className: "code", children: group.pair
|
|
4583
|
+
/* @__PURE__ */ jsx("span", { className: "code", children: renderPairContent(group.pair, "left") })
|
|
4523
4584
|
]
|
|
4524
4585
|
}
|
|
4525
4586
|
),
|
|
@@ -4531,7 +4592,7 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4531
4592
|
"data-side": "new",
|
|
4532
4593
|
children: [
|
|
4533
4594
|
/* @__PURE__ */ jsx("span", { className: "gutter", "data-line-number": group.pair.right?.newNum ?? "" }),
|
|
4534
|
-
/* @__PURE__ */ jsx("span", { className: "code", children: group.pair
|
|
4595
|
+
/* @__PURE__ */ jsx("span", { className: "code", children: renderPairContent(group.pair, "right") })
|
|
4535
4596
|
]
|
|
4536
4597
|
}
|
|
4537
4598
|
)
|
|
@@ -4581,7 +4642,7 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4581
4642
|
"data-new-line": pair.left?.newNum ?? pair.right?.newNum ?? "",
|
|
4582
4643
|
children: [
|
|
4583
4644
|
/* @__PURE__ */ jsx("span", { className: "gutter", "data-line-number": pair.left?.oldNum ?? "" }),
|
|
4584
|
-
/* @__PURE__ */ jsx("span", { className: "code", children: pair
|
|
4645
|
+
/* @__PURE__ */ jsx("span", { className: "code", children: renderPairContent(pair, "left") })
|
|
4585
4646
|
]
|
|
4586
4647
|
}
|
|
4587
4648
|
);
|
|
@@ -4626,7 +4687,7 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4626
4687
|
"data-side": "new",
|
|
4627
4688
|
children: [
|
|
4628
4689
|
/* @__PURE__ */ jsx("span", { className: "gutter", "data-line-number": pair.right?.newNum ?? "" }),
|
|
4629
|
-
/* @__PURE__ */ jsx("span", { className: "code", children: pair
|
|
4690
|
+
/* @__PURE__ */ jsx("span", { className: "code", children: renderPairContent(pair, "right") })
|
|
4630
4691
|
]
|
|
4631
4692
|
}
|
|
4632
4693
|
);
|
|
@@ -4634,6 +4695,20 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4634
4695
|
] });
|
|
4635
4696
|
}) });
|
|
4636
4697
|
}
|
|
4698
|
+
function renderSegments(segments) {
|
|
4699
|
+
return /* @__PURE__ */ jsx(Fragment, { children: segments.map((s) => s.changed ? /* @__PURE__ */ jsx("span", { className: "char-change", children: s.text }) : /* @__PURE__ */ jsx(Fragment, { children: s.text })) });
|
|
4700
|
+
}
|
|
4701
|
+
function renderPairContent(pair, side) {
|
|
4702
|
+
const line = side === "left" ? pair.left : pair.right;
|
|
4703
|
+
if (!line) return "";
|
|
4704
|
+
if (pair.left && pair.right && pair.left.type === "remove" && pair.right.type === "add") {
|
|
4705
|
+
const diff = charDiff(pair.left.content, pair.right.content);
|
|
4706
|
+
if (diff) {
|
|
4707
|
+
return renderSegments(side === "left" ? diff.oldSegments : diff.newSegments);
|
|
4708
|
+
}
|
|
4709
|
+
}
|
|
4710
|
+
return line.content;
|
|
4711
|
+
}
|
|
4637
4712
|
function pairLines(lines) {
|
|
4638
4713
|
const pairs = [];
|
|
4639
4714
|
let i = 0;
|
|
@@ -4667,55 +4742,88 @@ function pairLines(lines) {
|
|
|
4667
4742
|
}
|
|
4668
4743
|
return pairs;
|
|
4669
4744
|
}
|
|
4745
|
+
function buildUnifiedCharDiffs(lines) {
|
|
4746
|
+
const result = /* @__PURE__ */ new Map();
|
|
4747
|
+
let i = 0;
|
|
4748
|
+
while (i < lines.length) {
|
|
4749
|
+
if (lines[i].type === "remove") {
|
|
4750
|
+
const removes = [];
|
|
4751
|
+
while (i < lines.length && lines[i].type === "remove") {
|
|
4752
|
+
removes.push(lines[i]);
|
|
4753
|
+
i++;
|
|
4754
|
+
}
|
|
4755
|
+
const adds = [];
|
|
4756
|
+
while (i < lines.length && lines[i].type === "add") {
|
|
4757
|
+
adds.push(lines[i]);
|
|
4758
|
+
i++;
|
|
4759
|
+
}
|
|
4760
|
+
const pairCount = Math.min(removes.length, adds.length);
|
|
4761
|
+
for (let j = 0; j < pairCount; j++) {
|
|
4762
|
+
const diff = charDiff(removes[j].content, adds[j].content);
|
|
4763
|
+
if (diff) {
|
|
4764
|
+
result.set(removes[j], diff.oldSegments);
|
|
4765
|
+
result.set(adds[j], diff.newSegments);
|
|
4766
|
+
}
|
|
4767
|
+
}
|
|
4768
|
+
} else {
|
|
4769
|
+
i++;
|
|
4770
|
+
}
|
|
4771
|
+
}
|
|
4772
|
+
return result;
|
|
4773
|
+
}
|
|
4670
4774
|
function UnifiedDiff({ hunks, annotationsByLine }) {
|
|
4671
4775
|
const lastHunk = hunks[hunks.length - 1];
|
|
4672
4776
|
const tailStart = lastHunk ? lastHunk.newStart + lastHunk.newCount : 1;
|
|
4673
4777
|
return /* @__PURE__ */ jsx("div", { className: "diff-table-unified", children: [
|
|
4674
|
-
hunks.map((hunk, hunkIdx) =>
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
"
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
"
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4778
|
+
hunks.map((hunk, hunkIdx) => {
|
|
4779
|
+
const charDiffs = buildUnifiedCharDiffs(hunk.lines);
|
|
4780
|
+
return /* @__PURE__ */ jsx("div", { className: "hunk-block", children: [
|
|
4781
|
+
/* @__PURE__ */ jsx(
|
|
4782
|
+
"div",
|
|
4783
|
+
{
|
|
4784
|
+
className: "hunk-separator",
|
|
4785
|
+
"data-hunk-idx": hunkIdx,
|
|
4786
|
+
"data-old-start": hunk.oldStart,
|
|
4787
|
+
"data-old-count": hunk.oldCount,
|
|
4788
|
+
"data-new-start": hunk.newStart,
|
|
4789
|
+
"data-new-count": hunk.newCount,
|
|
4790
|
+
children: [
|
|
4791
|
+
"@@ -",
|
|
4792
|
+
hunk.oldStart,
|
|
4793
|
+
",",
|
|
4794
|
+
hunk.oldCount,
|
|
4795
|
+
" +",
|
|
4796
|
+
hunk.newStart,
|
|
4797
|
+
",",
|
|
4798
|
+
hunk.newCount,
|
|
4799
|
+
" @@"
|
|
4800
|
+
]
|
|
4801
|
+
}
|
|
4802
|
+
),
|
|
4803
|
+
hunk.lines.map((line) => {
|
|
4804
|
+
const lineNum = line.type === "remove" ? line.oldNum : line.newNum;
|
|
4805
|
+
const side = line.type === "remove" ? "old" : "new";
|
|
4806
|
+
const anns = annotationsByLine[`${lineNum}:${side}`] ?? [];
|
|
4807
|
+
const segments = charDiffs.get(line);
|
|
4808
|
+
return /* @__PURE__ */ jsx("div", { children: [
|
|
4809
|
+
/* @__PURE__ */ jsx(
|
|
4810
|
+
"div",
|
|
4811
|
+
{
|
|
4812
|
+
className: `diff-line ${line.type}${anns.length ? " has-annotation" : ""}`,
|
|
4813
|
+
"data-line": lineNum,
|
|
4814
|
+
"data-side": side,
|
|
4815
|
+
children: [
|
|
4816
|
+
/* @__PURE__ */ jsx("span", { className: "gutter-old", "data-line-number": line.oldNum ?? "" }),
|
|
4817
|
+
/* @__PURE__ */ jsx("span", { className: "gutter-new", "data-line-number": line.newNum ?? "" }),
|
|
4818
|
+
/* @__PURE__ */ jsx("span", { className: "code", children: segments ? renderSegments(segments) : line.content })
|
|
4819
|
+
]
|
|
4820
|
+
}
|
|
4821
|
+
),
|
|
4822
|
+
anns.length > 0 ? /* @__PURE__ */ jsx(AnnotationRows, { annotations: anns }) : null
|
|
4823
|
+
] });
|
|
4824
|
+
})
|
|
4825
|
+
] });
|
|
4826
|
+
}),
|
|
4719
4827
|
/* @__PURE__ */ jsx("div", { className: "hunk-separator hunk-expander-tail", "data-start": tailStart, children: "\u2195 Show remaining lines" })
|
|
4720
4828
|
] });
|
|
4721
4829
|
}
|
|
@@ -5589,7 +5697,7 @@ async function main() {
|
|
|
5589
5697
|
console.log("AI service test mode enabled \u2014 using mock AI responses");
|
|
5590
5698
|
}
|
|
5591
5699
|
if (debug) {
|
|
5592
|
-
console.log(`[debug] Build timestamp: ${"2026-03-
|
|
5700
|
+
console.log(`[debug] Build timestamp: ${"2026-03-21T23:17:12.455Z"}`);
|
|
5593
5701
|
}
|
|
5594
5702
|
if (projectDir) {
|
|
5595
5703
|
process.chdir(projectDir);
|