glassbox 0.4.2 → 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 +368 -174
- package/dist/client/app.global.js +8 -14
- package/dist/client/history.global.js +1 -0
- package/dist/client/styles.css +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1403,9 +1403,9 @@ function createNewFileDiff(filePath, repoRoot) {
|
|
|
1403
1403
|
isBinary: false
|
|
1404
1404
|
};
|
|
1405
1405
|
}
|
|
1406
|
-
function parseDiff(
|
|
1406
|
+
function parseDiff(raw) {
|
|
1407
1407
|
const files = [];
|
|
1408
|
-
const fileChunks =
|
|
1408
|
+
const fileChunks = raw.split(/^diff --git /m).filter(Boolean);
|
|
1409
1409
|
for (const chunk of fileChunks) {
|
|
1410
1410
|
const headerEnd = chunk.indexOf("@@");
|
|
1411
1411
|
const header = headerEnd === -1 ? chunk : chunk.slice(0, headerEnd);
|
|
@@ -1441,12 +1441,12 @@ function parseDiff(raw2) {
|
|
|
1441
1441
|
}
|
|
1442
1442
|
return files;
|
|
1443
1443
|
}
|
|
1444
|
-
function parseHunks(
|
|
1444
|
+
function parseHunks(raw) {
|
|
1445
1445
|
const hunks = [];
|
|
1446
1446
|
const hunkRegex = /^@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@(.*)/gm;
|
|
1447
1447
|
let match;
|
|
1448
1448
|
const hunkStarts = [];
|
|
1449
|
-
while ((match = hunkRegex.exec(
|
|
1449
|
+
while ((match = hunkRegex.exec(raw)) !== null) {
|
|
1450
1450
|
const groups = match;
|
|
1451
1451
|
hunkStarts.push({
|
|
1452
1452
|
index: match.index + match[0].length,
|
|
@@ -1458,8 +1458,8 @@ function parseHunks(raw2) {
|
|
|
1458
1458
|
}
|
|
1459
1459
|
for (let i = 0; i < hunkStarts.length; i++) {
|
|
1460
1460
|
const start = hunkStarts[i];
|
|
1461
|
-
const end = i + 1 < hunkStarts.length ?
|
|
1462
|
-
const body =
|
|
1461
|
+
const end = i + 1 < hunkStarts.length ? raw.lastIndexOf("\n@@", hunkStarts[i + 1].index) : raw.length;
|
|
1462
|
+
const body = raw.slice(start.index, end);
|
|
1463
1463
|
const lines = [];
|
|
1464
1464
|
let oldNum = start.oldStart;
|
|
1465
1465
|
let newNum = start.newStart;
|
|
@@ -4175,24 +4175,7 @@ var SafeHtml = class {
|
|
|
4175
4175
|
return this.__html;
|
|
4176
4176
|
}
|
|
4177
4177
|
};
|
|
4178
|
-
|
|
4179
|
-
return new SafeHtml(html);
|
|
4180
|
-
}
|
|
4181
|
-
var VOID_TAGS = /* @__PURE__ */ new Set([
|
|
4182
|
-
"area",
|
|
4183
|
-
"base",
|
|
4184
|
-
"br",
|
|
4185
|
-
"col",
|
|
4186
|
-
"embed",
|
|
4187
|
-
"hr",
|
|
4188
|
-
"img",
|
|
4189
|
-
"input",
|
|
4190
|
-
"link",
|
|
4191
|
-
"meta",
|
|
4192
|
-
"source",
|
|
4193
|
-
"track",
|
|
4194
|
-
"wbr"
|
|
4195
|
-
]);
|
|
4178
|
+
var VOID_TAGS = /* @__PURE__ */ new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "source", "track", "wbr"]);
|
|
4196
4179
|
function renderChildren(children) {
|
|
4197
4180
|
if (children == null || typeof children === "boolean") return "";
|
|
4198
4181
|
if (children instanceof SafeHtml) return children.__html;
|
|
@@ -4201,10 +4184,134 @@ function renderChildren(children) {
|
|
|
4201
4184
|
if (Array.isArray(children)) return children.map(renderChildren).join("");
|
|
4202
4185
|
return "";
|
|
4203
4186
|
}
|
|
4187
|
+
var ATTR_ALIASES = {
|
|
4188
|
+
// HTML attributes
|
|
4189
|
+
className: "class",
|
|
4190
|
+
htmlFor: "for",
|
|
4191
|
+
httpEquiv: "http-equiv",
|
|
4192
|
+
acceptCharset: "accept-charset",
|
|
4193
|
+
accessKey: "accesskey",
|
|
4194
|
+
autoCapitalize: "autocapitalize",
|
|
4195
|
+
autoComplete: "autocomplete",
|
|
4196
|
+
autoFocus: "autofocus",
|
|
4197
|
+
autoPlay: "autoplay",
|
|
4198
|
+
colSpan: "colspan",
|
|
4199
|
+
contentEditable: "contenteditable",
|
|
4200
|
+
crossOrigin: "crossorigin",
|
|
4201
|
+
dateTime: "datetime",
|
|
4202
|
+
defaultChecked: "checked",
|
|
4203
|
+
defaultValue: "value",
|
|
4204
|
+
encType: "enctype",
|
|
4205
|
+
formAction: "formaction",
|
|
4206
|
+
formEncType: "formenctype",
|
|
4207
|
+
formMethod: "formmethod",
|
|
4208
|
+
formNoValidate: "formnovalidate",
|
|
4209
|
+
formTarget: "formtarget",
|
|
4210
|
+
hrefLang: "hreflang",
|
|
4211
|
+
inputMode: "inputmode",
|
|
4212
|
+
maxLength: "maxlength",
|
|
4213
|
+
minLength: "minlength",
|
|
4214
|
+
noModule: "nomodule",
|
|
4215
|
+
noValidate: "novalidate",
|
|
4216
|
+
readOnly: "readonly",
|
|
4217
|
+
referrerPolicy: "referrerpolicy",
|
|
4218
|
+
rowSpan: "rowspan",
|
|
4219
|
+
spellCheck: "spellcheck",
|
|
4220
|
+
srcDoc: "srcdoc",
|
|
4221
|
+
srcLang: "srclang",
|
|
4222
|
+
srcSet: "srcset",
|
|
4223
|
+
tabIndex: "tabindex",
|
|
4224
|
+
useMap: "usemap",
|
|
4225
|
+
// SVG presentation attributes (camelCase → kebab-case)
|
|
4226
|
+
strokeWidth: "stroke-width",
|
|
4227
|
+
strokeLinecap: "stroke-linecap",
|
|
4228
|
+
strokeLinejoin: "stroke-linejoin",
|
|
4229
|
+
strokeDasharray: "stroke-dasharray",
|
|
4230
|
+
strokeDashoffset: "stroke-dashoffset",
|
|
4231
|
+
strokeMiterlimit: "stroke-miterlimit",
|
|
4232
|
+
strokeOpacity: "stroke-opacity",
|
|
4233
|
+
fillOpacity: "fill-opacity",
|
|
4234
|
+
fillRule: "fill-rule",
|
|
4235
|
+
clipPath: "clip-path",
|
|
4236
|
+
clipRule: "clip-rule",
|
|
4237
|
+
colorInterpolation: "color-interpolation",
|
|
4238
|
+
colorInterpolationFilters: "color-interpolation-filters",
|
|
4239
|
+
floodColor: "flood-color",
|
|
4240
|
+
floodOpacity: "flood-opacity",
|
|
4241
|
+
lightingColor: "lighting-color",
|
|
4242
|
+
stopColor: "stop-color",
|
|
4243
|
+
stopOpacity: "stop-opacity",
|
|
4244
|
+
shapeRendering: "shape-rendering",
|
|
4245
|
+
imageRendering: "image-rendering",
|
|
4246
|
+
textRendering: "text-rendering",
|
|
4247
|
+
pointerEvents: "pointer-events",
|
|
4248
|
+
vectorEffect: "vector-effect",
|
|
4249
|
+
paintOrder: "paint-order",
|
|
4250
|
+
// SVG text/font attributes
|
|
4251
|
+
fontFamily: "font-family",
|
|
4252
|
+
fontSize: "font-size",
|
|
4253
|
+
fontStyle: "font-style",
|
|
4254
|
+
fontVariant: "font-variant",
|
|
4255
|
+
fontWeight: "font-weight",
|
|
4256
|
+
fontStretch: "font-stretch",
|
|
4257
|
+
textAnchor: "text-anchor",
|
|
4258
|
+
textDecoration: "text-decoration",
|
|
4259
|
+
dominantBaseline: "dominant-baseline",
|
|
4260
|
+
alignmentBaseline: "alignment-baseline",
|
|
4261
|
+
baselineShift: "baseline-shift",
|
|
4262
|
+
letterSpacing: "letter-spacing",
|
|
4263
|
+
wordSpacing: "word-spacing",
|
|
4264
|
+
writingMode: "writing-mode",
|
|
4265
|
+
glyphOrientationHorizontal: "glyph-orientation-horizontal",
|
|
4266
|
+
glyphOrientationVertical: "glyph-orientation-vertical",
|
|
4267
|
+
// SVG marker/gradient/filter attributes
|
|
4268
|
+
markerStart: "marker-start",
|
|
4269
|
+
markerMid: "marker-mid",
|
|
4270
|
+
markerEnd: "marker-end",
|
|
4271
|
+
gradientUnits: "gradientUnits",
|
|
4272
|
+
gradientTransform: "gradientTransform",
|
|
4273
|
+
spreadMethod: "spreadMethod",
|
|
4274
|
+
patternUnits: "patternUnits",
|
|
4275
|
+
patternContentUnits: "patternContentUnits",
|
|
4276
|
+
patternTransform: "patternTransform",
|
|
4277
|
+
maskUnits: "maskUnits",
|
|
4278
|
+
maskContentUnits: "maskContentUnits",
|
|
4279
|
+
filterUnits: "filterUnits",
|
|
4280
|
+
primitiveUnits: "primitiveUnits",
|
|
4281
|
+
clipPathUnits: "clipPathUnits",
|
|
4282
|
+
// SVG xlink (legacy but still used)
|
|
4283
|
+
xlinkHref: "xlink:href",
|
|
4284
|
+
xlinkShow: "xlink:show",
|
|
4285
|
+
xlinkActuate: "xlink:actuate",
|
|
4286
|
+
xlinkType: "xlink:type",
|
|
4287
|
+
xlinkRole: "xlink:role",
|
|
4288
|
+
xlinkTitle: "xlink:title",
|
|
4289
|
+
xlinkArcrole: "xlink:arcrole",
|
|
4290
|
+
xmlBase: "xml:base",
|
|
4291
|
+
xmlLang: "xml:lang",
|
|
4292
|
+
xmlSpace: "xml:space",
|
|
4293
|
+
xmlns: "xmlns",
|
|
4294
|
+
xmlnsXlink: "xmlns:xlink",
|
|
4295
|
+
// SVG filter primitive attributes
|
|
4296
|
+
stdDeviation: "stdDeviation",
|
|
4297
|
+
baseFrequency: "baseFrequency",
|
|
4298
|
+
numOctaves: "numOctaves",
|
|
4299
|
+
kernelMatrix: "kernelMatrix",
|
|
4300
|
+
surfaceScale: "surfaceScale",
|
|
4301
|
+
specularConstant: "specularConstant",
|
|
4302
|
+
specularExponent: "specularExponent",
|
|
4303
|
+
diffuseConstant: "diffuseConstant",
|
|
4304
|
+
pointsAtX: "pointsAtX",
|
|
4305
|
+
pointsAtY: "pointsAtY",
|
|
4306
|
+
pointsAtZ: "pointsAtZ",
|
|
4307
|
+
limitingConeAngle: "limitingConeAngle",
|
|
4308
|
+
tableValues: "tableValues"
|
|
4309
|
+
// viewBox, preserveAspectRatio stay as-is (already correct casing)
|
|
4310
|
+
};
|
|
4204
4311
|
function renderAttr(key, value) {
|
|
4312
|
+
const name = ATTR_ALIASES[key] ?? key;
|
|
4205
4313
|
if (value == null || value === false) return "";
|
|
4206
|
-
if (value === true) return ` ${
|
|
4207
|
-
const name = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
|
|
4314
|
+
if (value === true) return ` ${name}`;
|
|
4208
4315
|
let strValue;
|
|
4209
4316
|
if (value instanceof SafeHtml) {
|
|
4210
4317
|
strValue = value.__html;
|
|
@@ -4225,6 +4332,126 @@ function jsx(tag, props) {
|
|
|
4225
4332
|
const childStr = children != null ? renderChildren(children) : "";
|
|
4226
4333
|
return new SafeHtml(`<${tag}${attrStr}>${childStr}</${tag}>`);
|
|
4227
4334
|
}
|
|
4335
|
+
function Fragment({ children }) {
|
|
4336
|
+
return new SafeHtml(children != null ? renderChildren(children) : "");
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4339
|
+
// src/icons.tsx
|
|
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" };
|
|
4341
|
+
var S12 = { ...S14, width: "12", height: "12" };
|
|
4342
|
+
var S16 = { ...S14, width: "16", height: "16" };
|
|
4343
|
+
function IconEdit() {
|
|
4344
|
+
return /* @__PURE__ */ jsx("svg", { ...S14, children: [
|
|
4345
|
+
/* @__PURE__ */ jsx("path", { d: "M17 3a2.85 2.85 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" }),
|
|
4346
|
+
/* @__PURE__ */ jsx("path", { d: "m15 5 4 4" })
|
|
4347
|
+
] });
|
|
4348
|
+
}
|
|
4349
|
+
function IconTrash() {
|
|
4350
|
+
return /* @__PURE__ */ jsx("svg", { ...S14, children: [
|
|
4351
|
+
/* @__PURE__ */ jsx("path", { d: "M3 6h18" }),
|
|
4352
|
+
/* @__PURE__ */ jsx("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }),
|
|
4353
|
+
/* @__PURE__ */ jsx("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" }),
|
|
4354
|
+
/* @__PURE__ */ jsx("line", { x1: "10", y1: "11", x2: "10", y2: "17" }),
|
|
4355
|
+
/* @__PURE__ */ jsx("line", { x1: "14", y1: "11", x2: "14", y2: "17" })
|
|
4356
|
+
] });
|
|
4357
|
+
}
|
|
4358
|
+
function IconTrash16() {
|
|
4359
|
+
return /* @__PURE__ */ jsx("svg", { ...S16, children: [
|
|
4360
|
+
/* @__PURE__ */ jsx("path", { d: "M3 6h18" }),
|
|
4361
|
+
/* @__PURE__ */ jsx("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }),
|
|
4362
|
+
/* @__PURE__ */ jsx("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" }),
|
|
4363
|
+
/* @__PURE__ */ jsx("line", { x1: "10", y1: "11", x2: "10", y2: "17" }),
|
|
4364
|
+
/* @__PURE__ */ jsx("line", { x1: "14", y1: "11", x2: "14", y2: "17" })
|
|
4365
|
+
] });
|
|
4366
|
+
}
|
|
4367
|
+
function IconReveal() {
|
|
4368
|
+
return /* @__PURE__ */ jsx("svg", { ...S12, children: [
|
|
4369
|
+
/* @__PURE__ */ jsx("path", { d: "M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" }),
|
|
4370
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "11", x2: "12", y2: "17" }),
|
|
4371
|
+
/* @__PURE__ */ jsx("polyline", { points: "9 14 12 11 15 14" })
|
|
4372
|
+
] });
|
|
4373
|
+
}
|
|
4374
|
+
function IconZoomOut() {
|
|
4375
|
+
return /* @__PURE__ */ jsx("svg", { ...S14, children: /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) });
|
|
4376
|
+
}
|
|
4377
|
+
function IconZoomIn() {
|
|
4378
|
+
return /* @__PURE__ */ jsx("svg", { ...S14, children: [
|
|
4379
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
4380
|
+
/* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
4381
|
+
] });
|
|
4382
|
+
}
|
|
4383
|
+
function IconFit() {
|
|
4384
|
+
return /* @__PURE__ */ jsx("svg", { ...S14, children: [
|
|
4385
|
+
/* @__PURE__ */ jsx("path", { d: "M15 3h6v6" }),
|
|
4386
|
+
/* @__PURE__ */ jsx("path", { d: "M9 21H3v-6" }),
|
|
4387
|
+
/* @__PURE__ */ jsx("path", { d: "M21 3l-7 7" }),
|
|
4388
|
+
/* @__PURE__ */ jsx("path", { d: "M3 21l7-7" })
|
|
4389
|
+
] });
|
|
4390
|
+
}
|
|
4391
|
+
function IconActualSize() {
|
|
4392
|
+
return /* @__PURE__ */ jsx("svg", { ...S14, children: [
|
|
4393
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
|
|
4394
|
+
/* @__PURE__ */ jsx("text", { x: "12", y: "15.5", textAnchor: "middle", fontSize: "9", fontWeight: "bold", fill: "currentColor", stroke: "none", children: "1:1" })
|
|
4395
|
+
] });
|
|
4396
|
+
}
|
|
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
|
+
}
|
|
4228
4455
|
|
|
4229
4456
|
// src/components/imageDiff.tsx
|
|
4230
4457
|
function ImageDiff({ file, diff, fontWarning, baseWidth, baseHeight }) {
|
|
@@ -4274,7 +4501,6 @@ function ImageDiff({ file, diff, fontWarning, baseWidth, baseHeight }) {
|
|
|
4274
4501
|
}
|
|
4275
4502
|
|
|
4276
4503
|
// src/components/diffView.tsx
|
|
4277
|
-
var revealSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/><line x1="12" y1="11" x2="12" y2="17"/><polyline points="9 14 12 11 15 14"/></svg>';
|
|
4278
4504
|
function DiffView({ file, diff, annotations, mode }) {
|
|
4279
4505
|
const annotationsByLine = {};
|
|
4280
4506
|
for (const a of annotations) {
|
|
@@ -4293,7 +4519,7 @@ function DiffView({ file, diff, annotations, mode }) {
|
|
|
4293
4519
|
/* @__PURE__ */ jsx("div", { className: "diff-header", children: [
|
|
4294
4520
|
/* @__PURE__ */ jsx("div", { className: "diff-header-file", children: [
|
|
4295
4521
|
/* @__PURE__ */ jsx("span", { className: "file-path", children: diff.filePath }),
|
|
4296
|
-
/* @__PURE__ */ jsx("button", { className: "reveal-btn", "data-file-id": file.id, title: "Reveal in file manager", children:
|
|
4522
|
+
/* @__PURE__ */ jsx("button", { className: "reveal-btn", "data-file-id": file.id, title: "Reveal in file manager", children: /* @__PURE__ */ jsx(IconReveal, {}) })
|
|
4297
4523
|
] }),
|
|
4298
4524
|
/* @__PURE__ */ jsx("div", { className: "diff-header-actions", children: /* @__PURE__ */ jsx("span", { className: `file-status ${diff.status}`, children: diff.status }) })
|
|
4299
4525
|
] }),
|
|
@@ -4354,7 +4580,7 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4354
4580
|
"data-new-line": group.pair.left?.newNum ?? group.pair.right?.newNum ?? "",
|
|
4355
4581
|
children: [
|
|
4356
4582
|
/* @__PURE__ */ jsx("span", { className: "gutter", "data-line-number": group.pair.left?.oldNum ?? "" }),
|
|
4357
|
-
/* @__PURE__ */ jsx("span", { className: "code", children:
|
|
4583
|
+
/* @__PURE__ */ jsx("span", { className: "code", children: renderPairContent(group.pair, "left") })
|
|
4358
4584
|
]
|
|
4359
4585
|
}
|
|
4360
4586
|
),
|
|
@@ -4366,7 +4592,7 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4366
4592
|
"data-side": "new",
|
|
4367
4593
|
children: [
|
|
4368
4594
|
/* @__PURE__ */ jsx("span", { className: "gutter", "data-line-number": group.pair.right?.newNum ?? "" }),
|
|
4369
|
-
/* @__PURE__ */ jsx("span", { className: "code", children:
|
|
4595
|
+
/* @__PURE__ */ jsx("span", { className: "code", children: renderPairContent(group.pair, "right") })
|
|
4370
4596
|
]
|
|
4371
4597
|
}
|
|
4372
4598
|
)
|
|
@@ -4416,7 +4642,7 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4416
4642
|
"data-new-line": pair.left?.newNum ?? pair.right?.newNum ?? "",
|
|
4417
4643
|
children: [
|
|
4418
4644
|
/* @__PURE__ */ jsx("span", { className: "gutter", "data-line-number": pair.left?.oldNum ?? "" }),
|
|
4419
|
-
/* @__PURE__ */ jsx("span", { className: "code", children:
|
|
4645
|
+
/* @__PURE__ */ jsx("span", { className: "code", children: renderPairContent(pair, "left") })
|
|
4420
4646
|
]
|
|
4421
4647
|
}
|
|
4422
4648
|
);
|
|
@@ -4461,7 +4687,7 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4461
4687
|
"data-side": "new",
|
|
4462
4688
|
children: [
|
|
4463
4689
|
/* @__PURE__ */ jsx("span", { className: "gutter", "data-line-number": pair.right?.newNum ?? "" }),
|
|
4464
|
-
/* @__PURE__ */ jsx("span", { className: "code", children:
|
|
4690
|
+
/* @__PURE__ */ jsx("span", { className: "code", children: renderPairContent(pair, "right") })
|
|
4465
4691
|
]
|
|
4466
4692
|
}
|
|
4467
4693
|
);
|
|
@@ -4469,6 +4695,20 @@ function SplitDiff({ hunks, annotationsByLine }) {
|
|
|
4469
4695
|
] });
|
|
4470
4696
|
}) });
|
|
4471
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
|
+
}
|
|
4472
4712
|
function pairLines(lines) {
|
|
4473
4713
|
const pairs = [];
|
|
4474
4714
|
let i = 0;
|
|
@@ -4502,55 +4742,88 @@ function pairLines(lines) {
|
|
|
4502
4742
|
}
|
|
4503
4743
|
return pairs;
|
|
4504
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
|
+
}
|
|
4505
4774
|
function UnifiedDiff({ hunks, annotationsByLine }) {
|
|
4506
4775
|
const lastHunk = hunks[hunks.length - 1];
|
|
4507
4776
|
const tailStart = lastHunk ? lastHunk.newStart + lastHunk.newCount : 1;
|
|
4508
4777
|
return /* @__PURE__ */ jsx("div", { className: "diff-table-unified", children: [
|
|
4509
|
-
hunks.map((hunk, hunkIdx) =>
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
"
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
"
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
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
|
+
}),
|
|
4554
4827
|
/* @__PURE__ */ jsx("div", { className: "hunk-separator hunk-expander-tail", "data-start": tailStart, children: "\u2195 Show remaining lines" })
|
|
4555
4828
|
] });
|
|
4556
4829
|
}
|
|
@@ -4567,8 +4840,8 @@ function AnnotationRows({ annotations }) {
|
|
|
4567
4840
|
/* @__PURE__ */ jsx("span", { className: "annotation-text", children: a.content }),
|
|
4568
4841
|
/* @__PURE__ */ jsx("div", { className: "annotation-actions", children: [
|
|
4569
4842
|
a.is_stale ? /* @__PURE__ */ jsx("button", { className: "btn btn-xs btn-keep", "data-action": "keep", children: "Keep" }) : null,
|
|
4570
|
-
/* @__PURE__ */ jsx("button", { className: "btn btn-xs btn-icon", "data-action": "edit", title: "Edit", children:
|
|
4571
|
-
/* @__PURE__ */ jsx("button", { className: "btn btn-xs btn-icon btn-danger", "data-action": "delete", title: "Delete", children:
|
|
4843
|
+
/* @__PURE__ */ jsx("button", { className: "btn btn-xs btn-icon", "data-action": "edit", title: "Edit", children: /* @__PURE__ */ jsx(IconEdit, {}) }),
|
|
4844
|
+
/* @__PURE__ */ jsx("button", { className: "btn btn-xs btn-icon btn-danger", "data-action": "delete", title: "Delete", children: /* @__PURE__ */ jsx(IconTrash, {}) })
|
|
4572
4845
|
] })
|
|
4573
4846
|
]
|
|
4574
4847
|
}
|
|
@@ -4678,7 +4951,6 @@ function Layout({ title, reviewId, children }) {
|
|
|
4678
4951
|
function titleCase(s) {
|
|
4679
4952
|
return s.replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
4680
4953
|
}
|
|
4681
|
-
var trashIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>';
|
|
4682
4954
|
function shortenArgs(args) {
|
|
4683
4955
|
const shaPattern = /\b([0-9a-f]{7,40})\b/gi;
|
|
4684
4956
|
const result = { hasLong: false };
|
|
@@ -4726,7 +4998,7 @@ function ReviewHistory({ reviews, currentReviewId }) {
|
|
|
4726
4998
|
" | Created: ",
|
|
4727
4999
|
r.created_at
|
|
4728
5000
|
] }),
|
|
4729
|
-
!isCurrent ? /* @__PURE__ */ jsx("button", { className: "delete-review-btn", "data-delete-id": r.id, title: "Delete review", children:
|
|
5001
|
+
!isCurrent ? /* @__PURE__ */ jsx("button", { className: "delete-review-btn", "data-delete-id": r.id, title: "Delete review", children: /* @__PURE__ */ jsx(IconTrash16, {}) }) : null
|
|
4730
5002
|
] }) }),
|
|
4731
5003
|
isCurrent && hasOtherReviews ? /* @__PURE__ */ jsx("div", { className: "bulk-actions", children: [
|
|
4732
5004
|
/* @__PURE__ */ jsx("span", { children: "Bulk actions:" }),
|
|
@@ -4736,94 +5008,12 @@ function ReviewHistory({ reviews, currentReviewId }) {
|
|
|
4736
5008
|
] });
|
|
4737
5009
|
}) }),
|
|
4738
5010
|
/* @__PURE__ */ jsx("a", { href: "/", className: "btn btn-link", style: "margin-top:16px;display:inline-block", children: "Back to current review" }),
|
|
4739
|
-
/* @__PURE__ */ jsx("script", {
|
|
5011
|
+
/* @__PURE__ */ jsx("script", { src: "/static/history.js" })
|
|
4740
5012
|
] });
|
|
4741
5013
|
}
|
|
4742
|
-
function getHistoryScript() {
|
|
4743
|
-
return `
|
|
4744
|
-
(function() {
|
|
4745
|
-
function esc(s) {
|
|
4746
|
-
var d = document.createElement('div');
|
|
4747
|
-
d.textContent = s;
|
|
4748
|
-
return d.innerHTML;
|
|
4749
|
-
}
|
|
4750
|
-
|
|
4751
|
-
function updateBulkVisibility() {
|
|
4752
|
-
var bulk = document.querySelector('.bulk-actions');
|
|
4753
|
-
if (bulk && !document.querySelector('.delete-review-btn')) {
|
|
4754
|
-
bulk.remove();
|
|
4755
|
-
}
|
|
4756
|
-
}
|
|
4757
|
-
|
|
4758
|
-
// Single review delete
|
|
4759
|
-
document.querySelectorAll('.delete-review-btn').forEach(function(btn) {
|
|
4760
|
-
btn.addEventListener('click', function(e) {
|
|
4761
|
-
e.preventDefault();
|
|
4762
|
-
e.stopPropagation();
|
|
4763
|
-
var id = btn.dataset.deleteId;
|
|
4764
|
-
showConfirm('Delete this review? This cannot be undone.', function() {
|
|
4765
|
-
fetch('/api/review/' + encodeURIComponent(id), { method: 'DELETE' })
|
|
4766
|
-
.then(function(r) { return r.json(); })
|
|
4767
|
-
.then(function() {
|
|
4768
|
-
btn.closest('.history-item-link').parentElement.remove();
|
|
4769
|
-
updateBulkVisibility();
|
|
4770
|
-
});
|
|
4771
|
-
});
|
|
4772
|
-
});
|
|
4773
|
-
});
|
|
4774
|
-
|
|
4775
|
-
// Bulk delete completed
|
|
4776
|
-
var delCompletedBtn = document.getElementById('delete-completed-btn');
|
|
4777
|
-
if (delCompletedBtn) {
|
|
4778
|
-
delCompletedBtn.addEventListener('click', function() {
|
|
4779
|
-
showConfirm('Delete all completed reviews (except current)? This cannot be undone.', function() {
|
|
4780
|
-
fetch('/api/reviews/delete-completed', { method: 'POST', headers: { 'Content-Type': 'application/json' } })
|
|
4781
|
-
.then(function(r) { return r.json(); })
|
|
4782
|
-
.then(function() { location.reload(); });
|
|
4783
|
-
});
|
|
4784
|
-
});
|
|
4785
|
-
}
|
|
4786
|
-
|
|
4787
|
-
// Bulk delete all
|
|
4788
|
-
var delAllBtn = document.getElementById('delete-all-btn');
|
|
4789
|
-
if (delAllBtn) {
|
|
4790
|
-
delAllBtn.addEventListener('click', function() {
|
|
4791
|
-
showConfirm('Delete ALL reviews except the current one? This cannot be undone.', function() {
|
|
4792
|
-
fetch('/api/reviews/delete-all', { method: 'POST', headers: { 'Content-Type': 'application/json' } })
|
|
4793
|
-
.then(function(r) { return r.json(); })
|
|
4794
|
-
.then(function() { location.reload(); });
|
|
4795
|
-
});
|
|
4796
|
-
});
|
|
4797
|
-
}
|
|
4798
|
-
|
|
4799
|
-
function showConfirm(message, onConfirm) {
|
|
4800
|
-
var overlay = document.createElement('div');
|
|
4801
|
-
overlay.className = 'modal-overlay';
|
|
4802
|
-
overlay.innerHTML =
|
|
4803
|
-
'<div class="modal">' +
|
|
4804
|
-
'<h3>Confirm</h3>' +
|
|
4805
|
-
'<p>' + esc(message) + '</p>' +
|
|
4806
|
-
'<div class="modal-actions">' +
|
|
4807
|
-
'<button class="btn btn-sm modal-cancel">Cancel</button>' +
|
|
4808
|
-
'<button class="btn btn-sm btn-danger modal-confirm">Delete</button>' +
|
|
4809
|
-
'</div>' +
|
|
4810
|
-
'</div>';
|
|
4811
|
-
overlay.querySelector('.modal-cancel').addEventListener('click', function() { overlay.remove(); });
|
|
4812
|
-
overlay.querySelector('.modal-confirm').addEventListener('click', function() { overlay.remove(); onConfirm(); });
|
|
4813
|
-
overlay.addEventListener('click', function(e) { if (e.target === overlay) overlay.remove(); });
|
|
4814
|
-
document.body.appendChild(overlay);
|
|
4815
|
-
}
|
|
4816
|
-
})();
|
|
4817
|
-
`;
|
|
4818
|
-
}
|
|
4819
5014
|
|
|
4820
5015
|
// src/routes/pages.tsx
|
|
4821
5016
|
init_queries();
|
|
4822
|
-
var zoomOutSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/></svg>';
|
|
4823
|
-
var zoomInSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>';
|
|
4824
|
-
var actualSizeSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><text x="12" y="15.5" text-anchor="middle" font-size="9" font-weight="bold" fill="currentColor" stroke="none">1:1</text></svg>';
|
|
4825
|
-
var fitSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"/><path d="M9 21H3v-6"/><path d="M21 3l-7 7"/><path d="M3 21l7-7"/></svg>';
|
|
4826
|
-
var revealSvgIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/><line x1="12" y1="11" x2="12" y2="17"/><polyline points="9 14 12 11 15 14"/></svg>';
|
|
4827
5017
|
var pageRoutes = new Hono3();
|
|
4828
5018
|
pageRoutes.get("/", async (c) => {
|
|
4829
5019
|
const reviewId = c.get("reviewId");
|
|
@@ -4894,10 +5084,10 @@ pageRoutes.get("/", async (c) => {
|
|
|
4894
5084
|
/* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "image", style: "display:none", children: "Image" })
|
|
4895
5085
|
] }) }),
|
|
4896
5086
|
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: [
|
|
4897
|
-
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children:
|
|
4898
|
-
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children:
|
|
4899
|
-
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children:
|
|
4900
|
-
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children:
|
|
5087
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children: /* @__PURE__ */ jsx(IconZoomOut, {}) }),
|
|
5088
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children: /* @__PURE__ */ jsx(IconFit, {}) }),
|
|
5089
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children: /* @__PURE__ */ jsx(IconActualSize, {}) }),
|
|
5090
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children: /* @__PURE__ */ jsx(IconZoomIn, {}) })
|
|
4901
5091
|
] })
|
|
4902
5092
|
] })
|
|
4903
5093
|
] })
|
|
@@ -4938,7 +5128,7 @@ pageRoutes.get("/file/:fileId", async (c) => {
|
|
|
4938
5128
|
/* @__PURE__ */ jsx("div", { className: "diff-header", children: [
|
|
4939
5129
|
/* @__PURE__ */ jsx("div", { className: "diff-header-file", children: [
|
|
4940
5130
|
/* @__PURE__ */ jsx("span", { className: "file-path", children: diff.filePath }),
|
|
4941
|
-
/* @__PURE__ */ jsx("button", { className: "reveal-btn", "data-file-id": file.id, title: "Reveal in file manager", children:
|
|
5131
|
+
/* @__PURE__ */ jsx("button", { className: "reveal-btn", "data-file-id": file.id, title: "Reveal in file manager", children: /* @__PURE__ */ jsx(IconReveal, {}) })
|
|
4942
5132
|
] }),
|
|
4943
5133
|
/* @__PURE__ */ jsx("div", { className: "diff-header-actions", children: /* @__PURE__ */ jsx("span", { className: `file-status ${diff.status}`, children: diff.status }) })
|
|
4944
5134
|
] }),
|
|
@@ -5045,10 +5235,10 @@ pageRoutes.get("/review/:reviewId", async (c) => {
|
|
|
5045
5235
|
/* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "image", style: "display:none", children: "Image" })
|
|
5046
5236
|
] }) }),
|
|
5047
5237
|
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: [
|
|
5048
|
-
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children:
|
|
5049
|
-
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children:
|
|
5050
|
-
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children:
|
|
5051
|
-
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children:
|
|
5238
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children: /* @__PURE__ */ jsx(IconZoomOut, {}) }),
|
|
5239
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children: /* @__PURE__ */ jsx(IconFit, {}) }),
|
|
5240
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children: /* @__PURE__ */ jsx(IconActualSize, {}) }),
|
|
5241
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children: /* @__PURE__ */ jsx(IconZoomIn, {}) })
|
|
5052
5242
|
] })
|
|
5053
5243
|
] })
|
|
5054
5244
|
] })
|
|
@@ -5099,6 +5289,10 @@ async function startServer(port, reviewId, repoRoot, options) {
|
|
|
5099
5289
|
const js = readFileSync8(join7(distDir, "app.global.js"), "utf-8");
|
|
5100
5290
|
return c.text(js, 200, { "Content-Type": "application/javascript", "Cache-Control": "no-cache" });
|
|
5101
5291
|
});
|
|
5292
|
+
app.get("/static/history.js", (c) => {
|
|
5293
|
+
const js = readFileSync8(join7(distDir, "history.global.js"), "utf-8");
|
|
5294
|
+
return c.text(js, 200, { "Content-Type": "application/javascript", "Cache-Control": "no-cache" });
|
|
5295
|
+
});
|
|
5102
5296
|
app.route("/api", apiRoutes);
|
|
5103
5297
|
app.route("/api/ai", aiApiRoutes);
|
|
5104
5298
|
app.route("/", pageRoutes);
|
|
@@ -5503,7 +5697,7 @@ async function main() {
|
|
|
5503
5697
|
console.log("AI service test mode enabled \u2014 using mock AI responses");
|
|
5504
5698
|
}
|
|
5505
5699
|
if (debug) {
|
|
5506
|
-
console.log(`[debug] Build timestamp: ${"2026-03-
|
|
5700
|
+
console.log(`[debug] Build timestamp: ${"2026-03-21T23:17:12.455Z"}`);
|
|
5507
5701
|
}
|
|
5508
5702
|
if (projectDir) {
|
|
5509
5703
|
process.chdir(projectDir);
|