@davmash/bygone 0.8.5 → 0.8.6
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/CHANGELOG.md +7 -0
- package/cli/present.js +31 -2
- package/docs/change-tour-format.md +5 -0
- package/out/changeTour.js +8 -3
- package/out/standalone-main.js +333 -21
- package/out/tourCoverage.js +8 -3
- package/out/windowTitle.js +143 -0
- package/package.json +1 -1
- package/schemas/change-tour-source.schema.json +4 -0
- package/skills/pr-tour-guide/SKILL.md +4 -0
- package/web/web-host.js +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.8.6
|
|
6
|
+
|
|
7
|
+
- Added optional authored-tour `windowTitle` labels and context-aware desktop and VS Code window titles
|
|
8
|
+
- Fixed tour presenter windows so authored `windowTitle` values appear in the native title instead of staying on the default `Bygone Tour` label
|
|
9
|
+
|
|
5
10
|
## 0.8.5
|
|
6
11
|
|
|
7
12
|
- Fixed Homebrew cask `bygone` CLI launch on Apple Silicon by routing through a bundle-aware launcher script inside the app
|
|
8
13
|
- Documented the macOS **“app is damaged”** workaround for unsigned desktop downloads (README, releasing docs, PR Tour Guide skill)
|
|
9
14
|
|
|
15
|
+
**macOS install:** Desktop builds are unsigned. If Gatekeeper reports the app is damaged, run `xattr -cr /Applications/Bygone.app` then open the app.
|
|
16
|
+
|
|
10
17
|
## 0.8.4
|
|
11
18
|
|
|
12
19
|
- Clarified PR Tour Guide skill install commands for project scope and agent-specific global installs
|
package/cli/present.js
CHANGED
|
@@ -3,6 +3,7 @@ const { createServer } = require('http');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { spawn } = require('child_process');
|
|
5
5
|
const { buildChangeTourManifest, parseChangeTourStory } = require('../out/changeTour.js');
|
|
6
|
+
const { buildTourWindowTitle } = require('../out/windowTitle.js');
|
|
6
7
|
const { tokenMatches } = require('./commandSpec.js');
|
|
7
8
|
const { loadTourSource } = require('./tourFile.js');
|
|
8
9
|
|
|
@@ -39,6 +40,10 @@ async function startPresentation(args, cwd, packageRoot, options = {}) {
|
|
|
39
40
|
process.stdout.write(`Wrote change-tour manifest to ${resolvedOutput}\n`);
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
const tourWindowTitle = buildTourWindowTitle(manifest, 'Bygone');
|
|
44
|
+
const presenterIndexPath = path.join(packageRoot, 'web', 'index.html');
|
|
45
|
+
let presenterIndexTemplate;
|
|
46
|
+
|
|
42
47
|
const server = createServer((request, response) => {
|
|
43
48
|
const requestUrl = new URL(request.url || '/', 'http://127.0.0.1');
|
|
44
49
|
if (requestUrl.pathname === '/tour.json') {
|
|
@@ -49,6 +54,21 @@ async function startPresentation(args, cwd, packageRoot, options = {}) {
|
|
|
49
54
|
response.end(serializedManifest);
|
|
50
55
|
return;
|
|
51
56
|
}
|
|
57
|
+
if (requestUrl.pathname === '/' || requestUrl.pathname === '/index.html') {
|
|
58
|
+
if (!presenterIndexTemplate) {
|
|
59
|
+
presenterIndexTemplate = readFileSync(presenterIndexPath, 'utf8');
|
|
60
|
+
}
|
|
61
|
+
const html = presenterIndexTemplate.replace(
|
|
62
|
+
/<title>Bygone Tour<\/title>/,
|
|
63
|
+
`<title>${escapeHtml(tourWindowTitle)}</title>`
|
|
64
|
+
);
|
|
65
|
+
response.writeHead(200, {
|
|
66
|
+
'Content-Type': 'text/html; charset=utf-8',
|
|
67
|
+
'Cache-Control': 'no-store'
|
|
68
|
+
});
|
|
69
|
+
response.end(html);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
52
72
|
const targetPath = resolveAssetPath(packageRoot, requestUrl.pathname);
|
|
53
73
|
if (!targetPath) {
|
|
54
74
|
respond(response, 404, 'Not found');
|
|
@@ -120,7 +140,7 @@ function parsePresentArgs(args) {
|
|
|
120
140
|
|
|
121
141
|
function resolveAssetPath(packageRoot, requestPath) {
|
|
122
142
|
if (requestPath === '/' || requestPath === '/index.html') {
|
|
123
|
-
return
|
|
143
|
+
return null;
|
|
124
144
|
}
|
|
125
145
|
if (!requestPath.startsWith('/web/') && !requestPath.startsWith('/media/')) {
|
|
126
146
|
return null;
|
|
@@ -160,7 +180,16 @@ function respond(response, statusCode, message) {
|
|
|
160
180
|
response.end(message);
|
|
161
181
|
}
|
|
162
182
|
|
|
183
|
+
function escapeHtml(text) {
|
|
184
|
+
return text
|
|
185
|
+
.replaceAll('&', '&')
|
|
186
|
+
.replaceAll('<', '<')
|
|
187
|
+
.replaceAll('>', '>')
|
|
188
|
+
.replaceAll('"', '"');
|
|
189
|
+
}
|
|
190
|
+
|
|
163
191
|
module.exports = {
|
|
164
192
|
parsePresentArgs,
|
|
165
|
-
startPresentation
|
|
193
|
+
startPresentation,
|
|
194
|
+
escapeHtml
|
|
166
195
|
};
|
|
@@ -35,11 +35,16 @@ contents, and diffs into the portable JSON manifest served by the presenter.
|
|
|
35
35
|
Compilation fails if an anchor has no match or has multiple matches without an
|
|
36
36
|
explicit `occurrence`.
|
|
37
37
|
|
|
38
|
+
The optional `windowTitle` sets the native window title for the tour presenter.
|
|
39
|
+
Use a short label such as a pull request number when several tours may be open at
|
|
40
|
+
once. When omitted, the presenter falls back to `title`, then a generic tour label.
|
|
41
|
+
|
|
38
42
|
## Structure
|
|
39
43
|
|
|
40
44
|
```yaml
|
|
41
45
|
version: 1
|
|
42
46
|
title: A reviewer-facing title
|
|
47
|
+
windowTitle: PR-1234
|
|
43
48
|
sourceUrl: https://example.test/pull/123
|
|
44
49
|
range:
|
|
45
50
|
base: 0123456789abcdef
|
package/out/changeTour.js
CHANGED
|
@@ -239,6 +239,9 @@ function parseChangeTourManifest(value) {
|
|
|
239
239
|
}
|
|
240
240
|
requireString(value.title, "title");
|
|
241
241
|
requireString(value.generatedAt, "generatedAt");
|
|
242
|
+
if (value.windowTitle !== void 0) {
|
|
243
|
+
requireString(value.windowTitle, "windowTitle");
|
|
244
|
+
}
|
|
242
245
|
if (value.sourceUrl !== void 0) {
|
|
243
246
|
requireString(value.sourceUrl, "sourceUrl");
|
|
244
247
|
}
|
|
@@ -533,8 +536,9 @@ function parseChangeTourSource(value) {
|
|
|
533
536
|
if (!isRecord2(value) || value.version !== CHANGE_TOUR_SOURCE_VERSION) {
|
|
534
537
|
throw new Error("Unsupported or missing change-tour source version.");
|
|
535
538
|
}
|
|
536
|
-
requireOnlyKeys(value, ["version", "title", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
|
|
539
|
+
requireOnlyKeys(value, ["version", "title", "windowTitle", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
|
|
537
540
|
optionalString(value.title, "title");
|
|
541
|
+
optionalString(value.windowTitle, "windowTitle");
|
|
538
542
|
optionalString(value.sourceUrl, "sourceUrl");
|
|
539
543
|
if (value.range !== void 0) {
|
|
540
544
|
if (!isRecord2(value.range)) throw new Error("range must be an object.");
|
|
@@ -1385,7 +1389,7 @@ var CHAPTERS = {
|
|
|
1385
1389
|
packaging: { id: "packaging", title: "Packaging and dependencies", priority: 4 }
|
|
1386
1390
|
};
|
|
1387
1391
|
function buildChangeTourManifest(startPath, options = {}) {
|
|
1388
|
-
var _a, _b, _c, _d;
|
|
1392
|
+
var _a, _b, _c, _d, _e;
|
|
1389
1393
|
const range = resolveBranchReviewRange(startPath, options.headRef, options.baseRef);
|
|
1390
1394
|
const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_TOUR_FILE_BYTES;
|
|
1391
1395
|
const maxLineBytes = options.maxLineBytes ?? DEFAULT_MAX_TOUR_LINE_BYTES;
|
|
@@ -1457,7 +1461,8 @@ function buildChangeTourManifest(startPath, options = {}) {
|
|
|
1457
1461
|
const manifest = {
|
|
1458
1462
|
version: CHANGE_TOUR_MANIFEST_VERSION,
|
|
1459
1463
|
title: ((_a = options.source) == null ? void 0 : _a.title) || ((_b = options.story) == null ? void 0 : _b.title) || options.title || `${range.headRef} against ${range.baseRef}`,
|
|
1460
|
-
|
|
1464
|
+
windowTitle: (_c = options.source) == null ? void 0 : _c.windowTitle,
|
|
1465
|
+
sourceUrl: ((_d = options.source) == null ? void 0 : _d.sourceUrl) || ((_e = options.story) == null ? void 0 : _e.sourceUrl) || options.sourceUrl,
|
|
1461
1466
|
generatedAt: options.generatedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1462
1467
|
range: {
|
|
1463
1468
|
baseRef: range.baseRef,
|
package/out/standalone-main.js
CHANGED
|
@@ -3811,6 +3811,9 @@ var require_changeTour = __commonJS({
|
|
|
3811
3811
|
}
|
|
3812
3812
|
requireString(value.title, "title");
|
|
3813
3813
|
requireString(value.generatedAt, "generatedAt");
|
|
3814
|
+
if (value.windowTitle !== void 0) {
|
|
3815
|
+
requireString(value.windowTitle, "windowTitle");
|
|
3816
|
+
}
|
|
3814
3817
|
if (value.sourceUrl !== void 0) {
|
|
3815
3818
|
requireString(value.sourceUrl, "sourceUrl");
|
|
3816
3819
|
}
|
|
@@ -4103,8 +4106,9 @@ var require_changeTour = __commonJS({
|
|
|
4103
4106
|
if (!isRecord22(value) || value.version !== CHANGE_TOUR_SOURCE_VERSION) {
|
|
4104
4107
|
throw new Error("Unsupported or missing change-tour source version.");
|
|
4105
4108
|
}
|
|
4106
|
-
requireOnlyKeys(value, ["version", "title", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
|
|
4109
|
+
requireOnlyKeys(value, ["version", "title", "windowTitle", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
|
|
4107
4110
|
optionalString(value.title, "title");
|
|
4111
|
+
optionalString(value.windowTitle, "windowTitle");
|
|
4108
4112
|
optionalString(value.sourceUrl, "sourceUrl");
|
|
4109
4113
|
if (value.range !== void 0) {
|
|
4110
4114
|
if (!isRecord22(value.range)) throw new Error("range must be an object.");
|
|
@@ -4947,7 +4951,7 @@ var require_changeTour = __commonJS({
|
|
|
4947
4951
|
packaging: { id: "packaging", title: "Packaging and dependencies", priority: 4 }
|
|
4948
4952
|
};
|
|
4949
4953
|
function buildChangeTourManifest(startPath, options = {}) {
|
|
4950
|
-
var _a, _b, _c, _d;
|
|
4954
|
+
var _a, _b, _c, _d, _e;
|
|
4951
4955
|
const range = resolveBranchReviewRange3(startPath, options.headRef, options.baseRef);
|
|
4952
4956
|
const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_TOUR_FILE_BYTES;
|
|
4953
4957
|
const maxLineBytes = options.maxLineBytes ?? DEFAULT_MAX_TOUR_LINE_BYTES;
|
|
@@ -5019,7 +5023,8 @@ var require_changeTour = __commonJS({
|
|
|
5019
5023
|
const manifest = {
|
|
5020
5024
|
version: CHANGE_TOUR_MANIFEST_VERSION,
|
|
5021
5025
|
title: ((_a = options.source) == null ? void 0 : _a.title) || ((_b = options.story) == null ? void 0 : _b.title) || options.title || `${range.headRef} against ${range.baseRef}`,
|
|
5022
|
-
|
|
5026
|
+
windowTitle: (_c = options.source) == null ? void 0 : _c.windowTitle,
|
|
5027
|
+
sourceUrl: ((_d = options.source) == null ? void 0 : _d.sourceUrl) || ((_e = options.story) == null ? void 0 : _e.sourceUrl) || options.sourceUrl,
|
|
5023
5028
|
generatedAt: options.generatedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
5024
5029
|
range: {
|
|
5025
5030
|
baseRef: range.baseRef,
|
|
@@ -5466,6 +5471,140 @@ var require_changeTour = __commonJS({
|
|
|
5466
5471
|
}
|
|
5467
5472
|
});
|
|
5468
5473
|
|
|
5474
|
+
// out/windowTitle.js
|
|
5475
|
+
var require_windowTitle = __commonJS({
|
|
5476
|
+
"out/windowTitle.js"(exports2, module2) {
|
|
5477
|
+
"use strict";
|
|
5478
|
+
var __defProp2 = Object.defineProperty;
|
|
5479
|
+
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
5480
|
+
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
5481
|
+
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
5482
|
+
var __export2 = (target, all) => {
|
|
5483
|
+
for (var name in all)
|
|
5484
|
+
__defProp2(target, name, { get: all[name], enumerable: true });
|
|
5485
|
+
};
|
|
5486
|
+
var __copyProps2 = (to, from, except, desc) => {
|
|
5487
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
5488
|
+
for (let key of __getOwnPropNames2(from))
|
|
5489
|
+
if (!__hasOwnProp2.call(to, key) && key !== except)
|
|
5490
|
+
__defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
|
|
5491
|
+
}
|
|
5492
|
+
return to;
|
|
5493
|
+
};
|
|
5494
|
+
var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
5495
|
+
var windowTitle_exports2 = {};
|
|
5496
|
+
__export2(windowTitle_exports2, {
|
|
5497
|
+
MAX_WINDOW_TITLE_LENGTH: () => MAX_WINDOW_TITLE_LENGTH2,
|
|
5498
|
+
buildHistoryTitle: () => buildHistoryTitle3,
|
|
5499
|
+
buildHistoryTitleFromViewState: () => buildHistoryTitleFromViewState2,
|
|
5500
|
+
buildMultiPanelTitle: () => buildMultiPanelTitle2,
|
|
5501
|
+
buildStandaloneSessionTitle: () => buildStandaloneSessionTitle3,
|
|
5502
|
+
buildTourWindowTitle: () => buildTourWindowTitle3,
|
|
5503
|
+
buildTwoWayComparisonTitle: () => buildTwoWayComparisonTitle2,
|
|
5504
|
+
formatComparisonPair: () => formatComparisonPair2,
|
|
5505
|
+
truncateTitle: () => truncateTitle2
|
|
5506
|
+
});
|
|
5507
|
+
module2.exports = __toCommonJS2(windowTitle_exports2);
|
|
5508
|
+
var MAX_WINDOW_TITLE_LENGTH2 = 120;
|
|
5509
|
+
function truncateTitle2(text, max = MAX_WINDOW_TITLE_LENGTH2) {
|
|
5510
|
+
if (text.length <= max) {
|
|
5511
|
+
return text;
|
|
5512
|
+
}
|
|
5513
|
+
return `${text.slice(0, max - 1)}\u2026`;
|
|
5514
|
+
}
|
|
5515
|
+
function formatComparisonPair2(left, right) {
|
|
5516
|
+
return `${left} \u2194 ${right}`;
|
|
5517
|
+
}
|
|
5518
|
+
function buildMultiPanelTitle2(input) {
|
|
5519
|
+
const { panels, activePanelId, activePairIndex, panelIds } = input;
|
|
5520
|
+
if (panels.length === 0) {
|
|
5521
|
+
return "Multi-Panel Compare";
|
|
5522
|
+
}
|
|
5523
|
+
if (panels.length === 1) {
|
|
5524
|
+
return truncateTitle2(panels[0].label);
|
|
5525
|
+
}
|
|
5526
|
+
if (panels.length === 2) {
|
|
5527
|
+
return truncateTitle2(formatComparisonPair2(panels[0].label, panels[1].label));
|
|
5528
|
+
}
|
|
5529
|
+
const ids = panelIds ?? panels.map((_panel, index) => String(index));
|
|
5530
|
+
const activeIndex = activePanelId ? ids.findIndex((id) => id === activePanelId) : -1;
|
|
5531
|
+
if (activePairIndex !== null && activePairIndex !== void 0 && activePairIndex >= 0 && activePairIndex < panels.length - 1) {
|
|
5532
|
+
return truncateTitle2(formatComparisonPair2(
|
|
5533
|
+
panels[activePairIndex].label,
|
|
5534
|
+
panels[activePairIndex + 1].label
|
|
5535
|
+
));
|
|
5536
|
+
}
|
|
5537
|
+
if (activeIndex >= 0) {
|
|
5538
|
+
const derivedPairIndex = activeIndex < panels.length - 1 ? activeIndex : Math.max(0, activeIndex - 1);
|
|
5539
|
+
return truncateTitle2(formatComparisonPair2(
|
|
5540
|
+
panels[derivedPairIndex].label,
|
|
5541
|
+
panels[derivedPairIndex + 1].label
|
|
5542
|
+
));
|
|
5543
|
+
}
|
|
5544
|
+
return truncateTitle2(formatComparisonPair2(panels[0].label, panels[panels.length - 1].label));
|
|
5545
|
+
}
|
|
5546
|
+
function buildHistoryTitle3(fileName, options) {
|
|
5547
|
+
const parts = [`${fileName} History`];
|
|
5548
|
+
if (options == null ? void 0 : options.shortCommit) {
|
|
5549
|
+
parts.push(options.shortCommit);
|
|
5550
|
+
}
|
|
5551
|
+
if (options == null ? void 0 : options.positionLabel) {
|
|
5552
|
+
parts.push(`(${options.positionLabel})`);
|
|
5553
|
+
}
|
|
5554
|
+
return truncateTitle2(parts.join(" \u2014 "));
|
|
5555
|
+
}
|
|
5556
|
+
function buildHistoryTitleFromViewState2(fileName, history) {
|
|
5557
|
+
const shortCommit = history.rightCommitLabel.split(/\s+/)[0] || void 0;
|
|
5558
|
+
return buildHistoryTitle3(fileName, {
|
|
5559
|
+
shortCommit,
|
|
5560
|
+
positionLabel: history.positionLabel
|
|
5561
|
+
});
|
|
5562
|
+
}
|
|
5563
|
+
function buildTwoWayComparisonTitle2(left, right) {
|
|
5564
|
+
return truncateTitle2(formatComparisonPair2(left, right));
|
|
5565
|
+
}
|
|
5566
|
+
function buildTourWindowTitle3(manifest, appName = "Bygone") {
|
|
5567
|
+
var _a, _b;
|
|
5568
|
+
const label = ((_a = manifest == null ? void 0 : manifest.windowTitle) == null ? void 0 : _a.trim()) || ((_b = manifest == null ? void 0 : manifest.title) == null ? void 0 : _b.trim());
|
|
5569
|
+
return label ? truncateTitle2(label) : `${appName} Tour`;
|
|
5570
|
+
}
|
|
5571
|
+
function buildStandaloneSessionTitle3(session2) {
|
|
5572
|
+
var _a, _b, _c, _d;
|
|
5573
|
+
if (session2.mode === "multi-diff" && session2.multi) {
|
|
5574
|
+
return buildMultiPanelTitle2({
|
|
5575
|
+
panels: session2.multi.files,
|
|
5576
|
+
activePanelId: session2.multi.activePanelId,
|
|
5577
|
+
activePairIndex: session2.multi.activePairIndex,
|
|
5578
|
+
panelIds: session2.multi.files.map((file) => file.id)
|
|
5579
|
+
});
|
|
5580
|
+
}
|
|
5581
|
+
if (session2.mode === "history" && ((_a = session2.history) == null ? void 0 : _a.filePath)) {
|
|
5582
|
+
const entry = (_b = session2.history.entries) == null ? void 0 : _b[session2.history.index ?? 0];
|
|
5583
|
+
return buildHistoryTitle3(
|
|
5584
|
+
session2.history.filePath.split("/").pop() || "File",
|
|
5585
|
+
{ shortCommit: entry == null ? void 0 : entry.shortCommit }
|
|
5586
|
+
);
|
|
5587
|
+
}
|
|
5588
|
+
if (session2.mode === "directory-history" && session2.dirHistory) {
|
|
5589
|
+
const name = session2.dirHistory.displayName || session2.dirHistory.viewRelativePath || "Directory";
|
|
5590
|
+
return truncateTitle2(`${name} Directory History`);
|
|
5591
|
+
}
|
|
5592
|
+
if (session2.mode === "directory" && session2.directory) {
|
|
5593
|
+
if ((_c = session2.directory.review) == null ? void 0 : _c.headRef) {
|
|
5594
|
+
return truncateTitle2(`${session2.directory.review.headRef} Branch Change`);
|
|
5595
|
+
}
|
|
5596
|
+
if ((_d = session2.directory.labels) == null ? void 0 : _d.length) {
|
|
5597
|
+
return truncateTitle2(session2.directory.labels.join(" \u2194 "));
|
|
5598
|
+
}
|
|
5599
|
+
}
|
|
5600
|
+
if (session2.left && session2.right) {
|
|
5601
|
+
return buildTwoWayComparisonTitle2(session2.left.label, session2.right.label);
|
|
5602
|
+
}
|
|
5603
|
+
return "Compare";
|
|
5604
|
+
}
|
|
5605
|
+
}
|
|
5606
|
+
});
|
|
5607
|
+
|
|
5469
5608
|
// node_modules/js-yaml/lib/common.js
|
|
5470
5609
|
var require_common = __commonJS({
|
|
5471
5610
|
"node_modules/js-yaml/lib/common.js"(exports2, module2) {
|
|
@@ -8594,6 +8733,7 @@ var require_present = __commonJS({
|
|
|
8594
8733
|
var path9 = require("path");
|
|
8595
8734
|
var { spawn: spawn2 } = require("child_process");
|
|
8596
8735
|
var { buildChangeTourManifest, parseChangeTourStory } = require_changeTour();
|
|
8736
|
+
var { buildTourWindowTitle: buildTourWindowTitle3 } = require_windowTitle();
|
|
8597
8737
|
var { tokenMatches: tokenMatches2 } = require_commandSpec();
|
|
8598
8738
|
var { loadTourSource } = require_tourFile();
|
|
8599
8739
|
var MIME_TYPES = /* @__PURE__ */ new Map([
|
|
@@ -8627,6 +8767,9 @@ var require_present = __commonJS({
|
|
|
8627
8767
|
process.stdout.write(`Wrote change-tour manifest to ${resolvedOutput}
|
|
8628
8768
|
`);
|
|
8629
8769
|
}
|
|
8770
|
+
const tourWindowTitle = buildTourWindowTitle3(manifest, "Bygone");
|
|
8771
|
+
const presenterIndexPath = path9.join(packageRoot2, "web", "index.html");
|
|
8772
|
+
let presenterIndexTemplate;
|
|
8630
8773
|
const server = createServer((request, response) => {
|
|
8631
8774
|
const requestUrl = new URL(request.url || "/", "http://127.0.0.1");
|
|
8632
8775
|
if (requestUrl.pathname === "/tour.json") {
|
|
@@ -8637,6 +8780,21 @@ var require_present = __commonJS({
|
|
|
8637
8780
|
response.end(serializedManifest);
|
|
8638
8781
|
return;
|
|
8639
8782
|
}
|
|
8783
|
+
if (requestUrl.pathname === "/" || requestUrl.pathname === "/index.html") {
|
|
8784
|
+
if (!presenterIndexTemplate) {
|
|
8785
|
+
presenterIndexTemplate = readFileSync5(presenterIndexPath, "utf8");
|
|
8786
|
+
}
|
|
8787
|
+
const html = presenterIndexTemplate.replace(
|
|
8788
|
+
/<title>Bygone Tour<\/title>/,
|
|
8789
|
+
`<title>${escapeHtml(tourWindowTitle)}</title>`
|
|
8790
|
+
);
|
|
8791
|
+
response.writeHead(200, {
|
|
8792
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
8793
|
+
"Cache-Control": "no-store"
|
|
8794
|
+
});
|
|
8795
|
+
response.end(html);
|
|
8796
|
+
return;
|
|
8797
|
+
}
|
|
8640
8798
|
const targetPath = resolveAssetPath(packageRoot2, requestUrl.pathname);
|
|
8641
8799
|
if (!targetPath) {
|
|
8642
8800
|
respond(response, 404, "Not found");
|
|
@@ -8707,7 +8865,7 @@ var require_present = __commonJS({
|
|
|
8707
8865
|
}
|
|
8708
8866
|
function resolveAssetPath(packageRoot2, requestPath) {
|
|
8709
8867
|
if (requestPath === "/" || requestPath === "/index.html") {
|
|
8710
|
-
return
|
|
8868
|
+
return null;
|
|
8711
8869
|
}
|
|
8712
8870
|
if (!requestPath.startsWith("/web/") && !requestPath.startsWith("/media/")) {
|
|
8713
8871
|
return null;
|
|
@@ -8739,9 +8897,13 @@ var require_present = __commonJS({
|
|
|
8739
8897
|
}
|
|
8740
8898
|
response.end(message);
|
|
8741
8899
|
}
|
|
8900
|
+
function escapeHtml(text) {
|
|
8901
|
+
return text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
8902
|
+
}
|
|
8742
8903
|
module2.exports = {
|
|
8743
8904
|
parsePresentArgs,
|
|
8744
|
-
startPresentation: startPresentation2
|
|
8905
|
+
startPresentation: startPresentation2,
|
|
8906
|
+
escapeHtml
|
|
8745
8907
|
};
|
|
8746
8908
|
}
|
|
8747
8909
|
});
|
|
@@ -8789,6 +8951,121 @@ var require_launchArgs = __commonJS({
|
|
|
8789
8951
|
}
|
|
8790
8952
|
});
|
|
8791
8953
|
|
|
8954
|
+
// src/windowTitle.ts
|
|
8955
|
+
var windowTitle_exports = {};
|
|
8956
|
+
__export(windowTitle_exports, {
|
|
8957
|
+
MAX_WINDOW_TITLE_LENGTH: () => MAX_WINDOW_TITLE_LENGTH,
|
|
8958
|
+
buildHistoryTitle: () => buildHistoryTitle,
|
|
8959
|
+
buildHistoryTitleFromViewState: () => buildHistoryTitleFromViewState,
|
|
8960
|
+
buildMultiPanelTitle: () => buildMultiPanelTitle,
|
|
8961
|
+
buildStandaloneSessionTitle: () => buildStandaloneSessionTitle,
|
|
8962
|
+
buildTourWindowTitle: () => buildTourWindowTitle,
|
|
8963
|
+
buildTwoWayComparisonTitle: () => buildTwoWayComparisonTitle,
|
|
8964
|
+
formatComparisonPair: () => formatComparisonPair,
|
|
8965
|
+
truncateTitle: () => truncateTitle
|
|
8966
|
+
});
|
|
8967
|
+
function truncateTitle(text, max = MAX_WINDOW_TITLE_LENGTH) {
|
|
8968
|
+
if (text.length <= max) {
|
|
8969
|
+
return text;
|
|
8970
|
+
}
|
|
8971
|
+
return `${text.slice(0, max - 1)}\u2026`;
|
|
8972
|
+
}
|
|
8973
|
+
function formatComparisonPair(left, right) {
|
|
8974
|
+
return `${left} \u2194 ${right}`;
|
|
8975
|
+
}
|
|
8976
|
+
function buildMultiPanelTitle(input) {
|
|
8977
|
+
const { panels, activePanelId, activePairIndex, panelIds } = input;
|
|
8978
|
+
if (panels.length === 0) {
|
|
8979
|
+
return "Multi-Panel Compare";
|
|
8980
|
+
}
|
|
8981
|
+
if (panels.length === 1) {
|
|
8982
|
+
return truncateTitle(panels[0].label);
|
|
8983
|
+
}
|
|
8984
|
+
if (panels.length === 2) {
|
|
8985
|
+
return truncateTitle(formatComparisonPair(panels[0].label, panels[1].label));
|
|
8986
|
+
}
|
|
8987
|
+
const ids = panelIds ?? panels.map((_panel, index) => String(index));
|
|
8988
|
+
const activeIndex = activePanelId ? ids.findIndex((id) => id === activePanelId) : -1;
|
|
8989
|
+
if (activePairIndex !== null && activePairIndex !== void 0 && activePairIndex >= 0 && activePairIndex < panels.length - 1) {
|
|
8990
|
+
return truncateTitle(formatComparisonPair(
|
|
8991
|
+
panels[activePairIndex].label,
|
|
8992
|
+
panels[activePairIndex + 1].label
|
|
8993
|
+
));
|
|
8994
|
+
}
|
|
8995
|
+
if (activeIndex >= 0) {
|
|
8996
|
+
const derivedPairIndex = activeIndex < panels.length - 1 ? activeIndex : Math.max(0, activeIndex - 1);
|
|
8997
|
+
return truncateTitle(formatComparisonPair(
|
|
8998
|
+
panels[derivedPairIndex].label,
|
|
8999
|
+
panels[derivedPairIndex + 1].label
|
|
9000
|
+
));
|
|
9001
|
+
}
|
|
9002
|
+
return truncateTitle(formatComparisonPair(panels[0].label, panels[panels.length - 1].label));
|
|
9003
|
+
}
|
|
9004
|
+
function buildHistoryTitle(fileName, options) {
|
|
9005
|
+
const parts = [`${fileName} History`];
|
|
9006
|
+
if (options?.shortCommit) {
|
|
9007
|
+
parts.push(options.shortCommit);
|
|
9008
|
+
}
|
|
9009
|
+
if (options?.positionLabel) {
|
|
9010
|
+
parts.push(`(${options.positionLabel})`);
|
|
9011
|
+
}
|
|
9012
|
+
return truncateTitle(parts.join(" \u2014 "));
|
|
9013
|
+
}
|
|
9014
|
+
function buildHistoryTitleFromViewState(fileName, history) {
|
|
9015
|
+
const shortCommit = history.rightCommitLabel.split(/\s+/)[0] || void 0;
|
|
9016
|
+
return buildHistoryTitle(fileName, {
|
|
9017
|
+
shortCommit,
|
|
9018
|
+
positionLabel: history.positionLabel
|
|
9019
|
+
});
|
|
9020
|
+
}
|
|
9021
|
+
function buildTwoWayComparisonTitle(left, right) {
|
|
9022
|
+
return truncateTitle(formatComparisonPair(left, right));
|
|
9023
|
+
}
|
|
9024
|
+
function buildTourWindowTitle(manifest, appName = "Bygone") {
|
|
9025
|
+
const label = manifest?.windowTitle?.trim() || manifest?.title?.trim();
|
|
9026
|
+
return label ? truncateTitle(label) : `${appName} Tour`;
|
|
9027
|
+
}
|
|
9028
|
+
function buildStandaloneSessionTitle(session2) {
|
|
9029
|
+
if (session2.mode === "multi-diff" && session2.multi) {
|
|
9030
|
+
return buildMultiPanelTitle({
|
|
9031
|
+
panels: session2.multi.files,
|
|
9032
|
+
activePanelId: session2.multi.activePanelId,
|
|
9033
|
+
activePairIndex: session2.multi.activePairIndex,
|
|
9034
|
+
panelIds: session2.multi.files.map((file) => file.id)
|
|
9035
|
+
});
|
|
9036
|
+
}
|
|
9037
|
+
if (session2.mode === "history" && session2.history?.filePath) {
|
|
9038
|
+
const entry = session2.history.entries?.[session2.history.index ?? 0];
|
|
9039
|
+
return buildHistoryTitle(
|
|
9040
|
+
session2.history.filePath.split("/").pop() || "File",
|
|
9041
|
+
{ shortCommit: entry?.shortCommit }
|
|
9042
|
+
);
|
|
9043
|
+
}
|
|
9044
|
+
if (session2.mode === "directory-history" && session2.dirHistory) {
|
|
9045
|
+
const name = session2.dirHistory.displayName || session2.dirHistory.viewRelativePath || "Directory";
|
|
9046
|
+
return truncateTitle(`${name} Directory History`);
|
|
9047
|
+
}
|
|
9048
|
+
if (session2.mode === "directory" && session2.directory) {
|
|
9049
|
+
if (session2.directory.review?.headRef) {
|
|
9050
|
+
return truncateTitle(`${session2.directory.review.headRef} Branch Change`);
|
|
9051
|
+
}
|
|
9052
|
+
if (session2.directory.labels?.length) {
|
|
9053
|
+
return truncateTitle(session2.directory.labels.join(" \u2194 "));
|
|
9054
|
+
}
|
|
9055
|
+
}
|
|
9056
|
+
if (session2.left && session2.right) {
|
|
9057
|
+
return buildTwoWayComparisonTitle(session2.left.label, session2.right.label);
|
|
9058
|
+
}
|
|
9059
|
+
return "Compare";
|
|
9060
|
+
}
|
|
9061
|
+
var MAX_WINDOW_TITLE_LENGTH;
|
|
9062
|
+
var init_windowTitle = __esm({
|
|
9063
|
+
"src/windowTitle.ts"() {
|
|
9064
|
+
"use strict";
|
|
9065
|
+
MAX_WINDOW_TITLE_LENGTH = 120;
|
|
9066
|
+
}
|
|
9067
|
+
});
|
|
9068
|
+
|
|
8792
9069
|
// package.json
|
|
8793
9070
|
var require_package = __commonJS({
|
|
8794
9071
|
"package.json"(exports2, module2) {
|
|
@@ -8798,7 +9075,7 @@ var require_package = __commonJS({
|
|
|
8798
9075
|
displayName: "Bygone",
|
|
8799
9076
|
desktopName: "com.davidmashburn.bygone.desktop",
|
|
8800
9077
|
description: "See how change happened. Visual diff and file history for VS Code.",
|
|
8801
|
-
version: "0.8.
|
|
9078
|
+
version: "0.8.6",
|
|
8802
9079
|
author: "David Mashburn",
|
|
8803
9080
|
license: "MIT",
|
|
8804
9081
|
private: false,
|
|
@@ -22047,6 +22324,11 @@ var { tokenMatches, tokensFor } = require_commandSpec();
|
|
|
22047
22324
|
var { startPresentation } = require_present();
|
|
22048
22325
|
var { resolveWorkingDirectory } = require_workingDirectory();
|
|
22049
22326
|
var { getCliArgsFromArgv, getForwardedLaunchArgs } = require_launchArgs();
|
|
22327
|
+
var {
|
|
22328
|
+
buildHistoryTitle: buildHistoryTitle2,
|
|
22329
|
+
buildStandaloneSessionTitle: buildStandaloneSessionTitle2,
|
|
22330
|
+
buildTourWindowTitle: buildTourWindowTitle2
|
|
22331
|
+
} = (init_windowTitle(), __toCommonJS(windowTitle_exports));
|
|
22050
22332
|
var APP_NAME = "Bygone";
|
|
22051
22333
|
var APP_VERSION = require_package().version;
|
|
22052
22334
|
var HELP_URL = "https://github.com/davidmashburn/bygone";
|
|
@@ -22281,7 +22563,7 @@ async function openTourPresentation(args, cwd) {
|
|
|
22281
22563
|
});
|
|
22282
22564
|
activeTourServers.add(presentation.server);
|
|
22283
22565
|
try {
|
|
22284
|
-
await showTourWindow(presentation.url, presentation.server);
|
|
22566
|
+
await showTourWindow(presentation.url, presentation.server, presentation.manifest);
|
|
22285
22567
|
} catch (error) {
|
|
22286
22568
|
closeTourServer(presentation.server);
|
|
22287
22569
|
throw error;
|
|
@@ -22291,7 +22573,7 @@ async function openAuthoredTourDocument(sourcePath) {
|
|
|
22291
22573
|
const document2 = discoverAuthoredTourDocument2(sourcePath);
|
|
22292
22574
|
await openTourPresentation(["--tour", document2.documentPath], document2.repoRoot);
|
|
22293
22575
|
}
|
|
22294
|
-
async function showTourWindow(url, server) {
|
|
22576
|
+
async function showTourWindow(url, server, manifest) {
|
|
22295
22577
|
const parsedUrl = new URL(url);
|
|
22296
22578
|
if (parsedUrl.protocol !== "http:" || parsedUrl.hostname !== "127.0.0.1") {
|
|
22297
22579
|
throw new Error("Tour presenter URL must use the local Bygone server.");
|
|
@@ -22303,7 +22585,7 @@ async function showTourWindow(url, server) {
|
|
|
22303
22585
|
minWidth: 960,
|
|
22304
22586
|
minHeight: 640,
|
|
22305
22587
|
show: false,
|
|
22306
|
-
title:
|
|
22588
|
+
title: buildTourWindowTitle2(manifest, APP_NAME),
|
|
22307
22589
|
webPreferences: {
|
|
22308
22590
|
sandbox: true,
|
|
22309
22591
|
contextIsolation: true,
|
|
@@ -22341,12 +22623,24 @@ async function showTourWindow(url, server) {
|
|
|
22341
22623
|
latestTourWindow = getLatestTourWindow();
|
|
22342
22624
|
}
|
|
22343
22625
|
});
|
|
22626
|
+
const tourWindowTitle = buildTourWindowTitle2(manifest, APP_NAME);
|
|
22627
|
+
const applyTourWindowTitle = () => {
|
|
22628
|
+
if (!tourWindow.isDestroyed()) {
|
|
22629
|
+
tourWindow.setTitle(tourWindowTitle);
|
|
22630
|
+
}
|
|
22631
|
+
};
|
|
22632
|
+
tourWindow.webContents.on("page-title-updated", (event) => {
|
|
22633
|
+
event.preventDefault();
|
|
22634
|
+
queueMicrotask(applyTourWindowTitle);
|
|
22635
|
+
});
|
|
22636
|
+
tourWindow.webContents.on("did-finish-load", applyTourWindowTitle);
|
|
22344
22637
|
try {
|
|
22345
22638
|
await tourWindow.loadURL(url);
|
|
22346
22639
|
} catch (error) {
|
|
22347
22640
|
tourWindow.destroy();
|
|
22348
22641
|
throw error;
|
|
22349
22642
|
}
|
|
22643
|
+
applyTourWindowTitle();
|
|
22350
22644
|
tourWindow.show();
|
|
22351
22645
|
tourWindow.focus();
|
|
22352
22646
|
return tourWindow;
|
|
@@ -23435,11 +23729,15 @@ async function handleRendererMessage(message) {
|
|
|
23435
23729
|
return;
|
|
23436
23730
|
}
|
|
23437
23731
|
if (message.type === "multiSetActivePanel" && typeof message.panelId === "string") {
|
|
23438
|
-
setActiveMultiPanel(message.panelId)
|
|
23732
|
+
if (setActiveMultiPanel(message.panelId)) {
|
|
23733
|
+
refreshSessionWindowTitle();
|
|
23734
|
+
}
|
|
23439
23735
|
return;
|
|
23440
23736
|
}
|
|
23441
23737
|
if (message.type === "multiSetActivePair" && Number.isInteger(message.pairIndex)) {
|
|
23442
|
-
setActiveMultiPair(message.pairIndex)
|
|
23738
|
+
if (setActiveMultiPair(message.pairIndex)) {
|
|
23739
|
+
refreshSessionWindowTitle();
|
|
23740
|
+
}
|
|
23443
23741
|
return;
|
|
23444
23742
|
}
|
|
23445
23743
|
if (message.type === "multiAddPanel" && typeof message.anchorPanelId === "string" && (message.side === "left" || message.side === "right")) {
|
|
@@ -23463,7 +23761,7 @@ async function handleRendererMessage(message) {
|
|
|
23463
23761
|
if (panel) {
|
|
23464
23762
|
panel.content = message.content;
|
|
23465
23763
|
panel.dirty = panel.content !== panel.savedContent;
|
|
23466
|
-
|
|
23764
|
+
refreshSessionWindowTitle();
|
|
23467
23765
|
}
|
|
23468
23766
|
return;
|
|
23469
23767
|
}
|
|
@@ -24117,7 +24415,7 @@ async function sendCurrentDirectoryDiff() {
|
|
|
24117
24415
|
canMutate: !review && session.source?.kind === "directories",
|
|
24118
24416
|
review: buildReviewViewState(review)
|
|
24119
24417
|
});
|
|
24120
|
-
|
|
24418
|
+
refreshSessionWindowTitle();
|
|
24121
24419
|
if (launchArguments.kind === "smoke-directory" && mainWindow && !mainWindow.isDestroyed()) {
|
|
24122
24420
|
setTimeout(() => {
|
|
24123
24421
|
void mainWindow.webContents.executeJavaScript(`document.querySelector('.dir-entry[data-is-dir="false"]')?.click()`);
|
|
@@ -24182,7 +24480,7 @@ async function sendCurrentDirectoryHistoryEntry() {
|
|
|
24182
24480
|
fileNavigation: buildDirectoryHistoryFileNavigationState(session.dirHistory, entry),
|
|
24183
24481
|
canReturnToDirectory: true
|
|
24184
24482
|
});
|
|
24185
|
-
|
|
24483
|
+
refreshSessionWindowTitle();
|
|
24186
24484
|
scheduleCaptureIfNeeded();
|
|
24187
24485
|
return;
|
|
24188
24486
|
}
|
|
@@ -24206,7 +24504,7 @@ async function sendCurrentDirectoryHistoryEntry() {
|
|
|
24206
24504
|
history,
|
|
24207
24505
|
canMutate: true
|
|
24208
24506
|
});
|
|
24209
|
-
|
|
24507
|
+
refreshSessionWindowTitle();
|
|
24210
24508
|
scheduleCaptureIfNeeded();
|
|
24211
24509
|
}
|
|
24212
24510
|
function buildDirectoryHistoryViewState(dirHistory, entry) {
|
|
@@ -25377,7 +25675,7 @@ async function sendCurrentMultiDiff() {
|
|
|
25377
25675
|
fileNavigation: buildStandaloneFileNavigationState(),
|
|
25378
25676
|
mutationEnabled: !isDirectoryDrilldown
|
|
25379
25677
|
});
|
|
25380
|
-
|
|
25678
|
+
refreshSessionWindowTitle();
|
|
25381
25679
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
25382
25680
|
setTimeout(() => {
|
|
25383
25681
|
void mainWindow.webContents.executeJavaScript(`(() => ({
|
|
@@ -25495,7 +25793,7 @@ async function sendCurrentDiff() {
|
|
|
25495
25793
|
directoryNavigation: buildDirectoryDrilldownNavigationState(),
|
|
25496
25794
|
canReturnToDirectory: Boolean(session.returnDirectory)
|
|
25497
25795
|
});
|
|
25498
|
-
|
|
25796
|
+
refreshSessionWindowTitle();
|
|
25499
25797
|
scheduleCaptureIfNeeded();
|
|
25500
25798
|
return;
|
|
25501
25799
|
}
|
|
@@ -25523,7 +25821,7 @@ async function sendCurrentDiff() {
|
|
|
25523
25821
|
comparisonSummary: session.returnDirectory?.comparisonSummary
|
|
25524
25822
|
};
|
|
25525
25823
|
postOrQueue(message);
|
|
25526
|
-
|
|
25824
|
+
refreshSessionWindowTitle();
|
|
25527
25825
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
25528
25826
|
setTimeout(() => {
|
|
25529
25827
|
void mainWindow.webContents.executeJavaScript(`(() => ({
|
|
@@ -25611,7 +25909,7 @@ async function sendCurrentHistoryEntry() {
|
|
|
25611
25909
|
rail
|
|
25612
25910
|
}
|
|
25613
25911
|
});
|
|
25614
|
-
|
|
25912
|
+
refreshSessionWindowTitle();
|
|
25615
25913
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
25616
25914
|
setTimeout(() => {
|
|
25617
25915
|
void mainWindow.webContents.executeJavaScript(`(() => ({
|
|
@@ -25931,7 +26229,7 @@ async function saveDirtyMultiPanels() {
|
|
|
25931
26229
|
}
|
|
25932
26230
|
updateWatchers();
|
|
25933
26231
|
await sendCurrentMultiDiff();
|
|
25934
|
-
|
|
26232
|
+
refreshSessionWindowTitle();
|
|
25935
26233
|
return true;
|
|
25936
26234
|
}
|
|
25937
26235
|
async function saveMultiPanel(panel, { dialogTitle, refreshView }) {
|
|
@@ -25957,7 +26255,7 @@ async function saveMultiPanel(panel, { dialogTitle, refreshView }) {
|
|
|
25957
26255
|
if (refreshView) {
|
|
25958
26256
|
updateWatchers();
|
|
25959
26257
|
await sendCurrentMultiDiff();
|
|
25960
|
-
|
|
26258
|
+
refreshSessionWindowTitle();
|
|
25961
26259
|
}
|
|
25962
26260
|
return true;
|
|
25963
26261
|
}
|
|
@@ -26071,6 +26369,20 @@ function updateWindowTitle(title) {
|
|
|
26071
26369
|
const dirtySuffix = hasUnsavedChanges() ? " \u2022 Unsaved" : "";
|
|
26072
26370
|
mainWindow.setTitle(`${APP_NAME} \u2014 ${title}${dirtySuffix}`);
|
|
26073
26371
|
}
|
|
26372
|
+
function refreshSessionWindowTitle() {
|
|
26373
|
+
if (session.mode === "history" && session.history) {
|
|
26374
|
+
const visibleIndices = getVisibleFileHistoryIndices(session.history);
|
|
26375
|
+
const visiblePosition = visibleIndices.indexOf(session.history.index);
|
|
26376
|
+
const entry = session.history.entries[session.history.index];
|
|
26377
|
+
const fileName = path8.basename(session.history.filePath);
|
|
26378
|
+
updateWindowTitle(buildHistoryTitle2(fileName, {
|
|
26379
|
+
shortCommit: entry?.shortCommit,
|
|
26380
|
+
positionLabel: visiblePosition >= 0 ? `${visiblePosition + 1} / ${visibleIndices.length}` : void 0
|
|
26381
|
+
}));
|
|
26382
|
+
return;
|
|
26383
|
+
}
|
|
26384
|
+
updateWindowTitle(buildStandaloneSessionTitle2(session));
|
|
26385
|
+
}
|
|
26074
26386
|
async function confirmSessionReplacement(action) {
|
|
26075
26387
|
if (!hasUnsavedChanges()) {
|
|
26076
26388
|
return true;
|
package/out/tourCoverage.js
CHANGED
|
@@ -481,6 +481,9 @@ function parseChangeTourManifest(value) {
|
|
|
481
481
|
}
|
|
482
482
|
requireString(value.title, "title");
|
|
483
483
|
requireString(value.generatedAt, "generatedAt");
|
|
484
|
+
if (value.windowTitle !== void 0) {
|
|
485
|
+
requireString(value.windowTitle, "windowTitle");
|
|
486
|
+
}
|
|
484
487
|
if (value.sourceUrl !== void 0) {
|
|
485
488
|
requireString(value.sourceUrl, "sourceUrl");
|
|
486
489
|
}
|
|
@@ -744,8 +747,9 @@ function parseChangeTourSource(value) {
|
|
|
744
747
|
if (!isRecord2(value) || value.version !== CHANGE_TOUR_SOURCE_VERSION) {
|
|
745
748
|
throw new Error("Unsupported or missing change-tour source version.");
|
|
746
749
|
}
|
|
747
|
-
requireOnlyKeys(value, ["version", "title", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
|
|
750
|
+
requireOnlyKeys(value, ["version", "title", "windowTitle", "sourceUrl", "range", "anchors", "connections", "chapters", "coverage"], "source");
|
|
748
751
|
optionalString(value.title, "title");
|
|
752
|
+
optionalString(value.windowTitle, "windowTitle");
|
|
749
753
|
optionalString(value.sourceUrl, "sourceUrl");
|
|
750
754
|
if (value.range !== void 0) {
|
|
751
755
|
if (!isRecord2(value.range)) throw new Error("range must be an object.");
|
|
@@ -1162,7 +1166,7 @@ var CHAPTERS = {
|
|
|
1162
1166
|
packaging: { id: "packaging", title: "Packaging and dependencies", priority: 4 }
|
|
1163
1167
|
};
|
|
1164
1168
|
function buildChangeTourManifest(startPath, options = {}) {
|
|
1165
|
-
var _a, _b, _c, _d;
|
|
1169
|
+
var _a, _b, _c, _d, _e;
|
|
1166
1170
|
const range = resolveBranchReviewRange(startPath, options.headRef, options.baseRef);
|
|
1167
1171
|
const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_TOUR_FILE_BYTES;
|
|
1168
1172
|
const maxLineBytes = options.maxLineBytes ?? DEFAULT_MAX_TOUR_LINE_BYTES;
|
|
@@ -1234,7 +1238,8 @@ function buildChangeTourManifest(startPath, options = {}) {
|
|
|
1234
1238
|
const manifest = {
|
|
1235
1239
|
version: CHANGE_TOUR_MANIFEST_VERSION,
|
|
1236
1240
|
title: ((_a = options.source) == null ? void 0 : _a.title) || ((_b = options.story) == null ? void 0 : _b.title) || options.title || `${range.headRef} against ${range.baseRef}`,
|
|
1237
|
-
|
|
1241
|
+
windowTitle: (_c = options.source) == null ? void 0 : _c.windowTitle,
|
|
1242
|
+
sourceUrl: ((_d = options.source) == null ? void 0 : _d.sourceUrl) || ((_e = options.story) == null ? void 0 : _e.sourceUrl) || options.sourceUrl,
|
|
1238
1243
|
generatedAt: options.generatedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1239
1244
|
range: {
|
|
1240
1245
|
baseRef: range.baseRef,
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/windowTitle.ts
|
|
21
|
+
var windowTitle_exports = {};
|
|
22
|
+
__export(windowTitle_exports, {
|
|
23
|
+
MAX_WINDOW_TITLE_LENGTH: () => MAX_WINDOW_TITLE_LENGTH,
|
|
24
|
+
buildHistoryTitle: () => buildHistoryTitle,
|
|
25
|
+
buildHistoryTitleFromViewState: () => buildHistoryTitleFromViewState,
|
|
26
|
+
buildMultiPanelTitle: () => buildMultiPanelTitle,
|
|
27
|
+
buildStandaloneSessionTitle: () => buildStandaloneSessionTitle,
|
|
28
|
+
buildTourWindowTitle: () => buildTourWindowTitle,
|
|
29
|
+
buildTwoWayComparisonTitle: () => buildTwoWayComparisonTitle,
|
|
30
|
+
formatComparisonPair: () => formatComparisonPair,
|
|
31
|
+
truncateTitle: () => truncateTitle
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(windowTitle_exports);
|
|
34
|
+
var MAX_WINDOW_TITLE_LENGTH = 120;
|
|
35
|
+
function truncateTitle(text, max = MAX_WINDOW_TITLE_LENGTH) {
|
|
36
|
+
if (text.length <= max) {
|
|
37
|
+
return text;
|
|
38
|
+
}
|
|
39
|
+
return `${text.slice(0, max - 1)}\u2026`;
|
|
40
|
+
}
|
|
41
|
+
function formatComparisonPair(left, right) {
|
|
42
|
+
return `${left} \u2194 ${right}`;
|
|
43
|
+
}
|
|
44
|
+
function buildMultiPanelTitle(input) {
|
|
45
|
+
const { panels, activePanelId, activePairIndex, panelIds } = input;
|
|
46
|
+
if (panels.length === 0) {
|
|
47
|
+
return "Multi-Panel Compare";
|
|
48
|
+
}
|
|
49
|
+
if (panels.length === 1) {
|
|
50
|
+
return truncateTitle(panels[0].label);
|
|
51
|
+
}
|
|
52
|
+
if (panels.length === 2) {
|
|
53
|
+
return truncateTitle(formatComparisonPair(panels[0].label, panels[1].label));
|
|
54
|
+
}
|
|
55
|
+
const ids = panelIds ?? panels.map((_panel, index) => String(index));
|
|
56
|
+
const activeIndex = activePanelId ? ids.findIndex((id) => id === activePanelId) : -1;
|
|
57
|
+
if (activePairIndex !== null && activePairIndex !== void 0 && activePairIndex >= 0 && activePairIndex < panels.length - 1) {
|
|
58
|
+
return truncateTitle(formatComparisonPair(
|
|
59
|
+
panels[activePairIndex].label,
|
|
60
|
+
panels[activePairIndex + 1].label
|
|
61
|
+
));
|
|
62
|
+
}
|
|
63
|
+
if (activeIndex >= 0) {
|
|
64
|
+
const derivedPairIndex = activeIndex < panels.length - 1 ? activeIndex : Math.max(0, activeIndex - 1);
|
|
65
|
+
return truncateTitle(formatComparisonPair(
|
|
66
|
+
panels[derivedPairIndex].label,
|
|
67
|
+
panels[derivedPairIndex + 1].label
|
|
68
|
+
));
|
|
69
|
+
}
|
|
70
|
+
return truncateTitle(formatComparisonPair(panels[0].label, panels[panels.length - 1].label));
|
|
71
|
+
}
|
|
72
|
+
function buildHistoryTitle(fileName, options) {
|
|
73
|
+
const parts = [`${fileName} History`];
|
|
74
|
+
if (options == null ? void 0 : options.shortCommit) {
|
|
75
|
+
parts.push(options.shortCommit);
|
|
76
|
+
}
|
|
77
|
+
if (options == null ? void 0 : options.positionLabel) {
|
|
78
|
+
parts.push(`(${options.positionLabel})`);
|
|
79
|
+
}
|
|
80
|
+
return truncateTitle(parts.join(" \u2014 "));
|
|
81
|
+
}
|
|
82
|
+
function buildHistoryTitleFromViewState(fileName, history) {
|
|
83
|
+
const shortCommit = history.rightCommitLabel.split(/\s+/)[0] || void 0;
|
|
84
|
+
return buildHistoryTitle(fileName, {
|
|
85
|
+
shortCommit,
|
|
86
|
+
positionLabel: history.positionLabel
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function buildTwoWayComparisonTitle(left, right) {
|
|
90
|
+
return truncateTitle(formatComparisonPair(left, right));
|
|
91
|
+
}
|
|
92
|
+
function buildTourWindowTitle(manifest, appName = "Bygone") {
|
|
93
|
+
var _a, _b;
|
|
94
|
+
const label = ((_a = manifest == null ? void 0 : manifest.windowTitle) == null ? void 0 : _a.trim()) || ((_b = manifest == null ? void 0 : manifest.title) == null ? void 0 : _b.trim());
|
|
95
|
+
return label ? truncateTitle(label) : `${appName} Tour`;
|
|
96
|
+
}
|
|
97
|
+
function buildStandaloneSessionTitle(session) {
|
|
98
|
+
var _a, _b, _c, _d;
|
|
99
|
+
if (session.mode === "multi-diff" && session.multi) {
|
|
100
|
+
return buildMultiPanelTitle({
|
|
101
|
+
panels: session.multi.files,
|
|
102
|
+
activePanelId: session.multi.activePanelId,
|
|
103
|
+
activePairIndex: session.multi.activePairIndex,
|
|
104
|
+
panelIds: session.multi.files.map((file) => file.id)
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (session.mode === "history" && ((_a = session.history) == null ? void 0 : _a.filePath)) {
|
|
108
|
+
const entry = (_b = session.history.entries) == null ? void 0 : _b[session.history.index ?? 0];
|
|
109
|
+
return buildHistoryTitle(
|
|
110
|
+
session.history.filePath.split("/").pop() || "File",
|
|
111
|
+
{ shortCommit: entry == null ? void 0 : entry.shortCommit }
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
if (session.mode === "directory-history" && session.dirHistory) {
|
|
115
|
+
const name = session.dirHistory.displayName || session.dirHistory.viewRelativePath || "Directory";
|
|
116
|
+
return truncateTitle(`${name} Directory History`);
|
|
117
|
+
}
|
|
118
|
+
if (session.mode === "directory" && session.directory) {
|
|
119
|
+
if ((_c = session.directory.review) == null ? void 0 : _c.headRef) {
|
|
120
|
+
return truncateTitle(`${session.directory.review.headRef} Branch Change`);
|
|
121
|
+
}
|
|
122
|
+
if ((_d = session.directory.labels) == null ? void 0 : _d.length) {
|
|
123
|
+
return truncateTitle(session.directory.labels.join(" \u2194 "));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (session.left && session.right) {
|
|
127
|
+
return buildTwoWayComparisonTitle(session.left.label, session.right.label);
|
|
128
|
+
}
|
|
129
|
+
return "Compare";
|
|
130
|
+
}
|
|
131
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
132
|
+
0 && (module.exports = {
|
|
133
|
+
MAX_WINDOW_TITLE_LENGTH,
|
|
134
|
+
buildHistoryTitle,
|
|
135
|
+
buildHistoryTitleFromViewState,
|
|
136
|
+
buildMultiPanelTitle,
|
|
137
|
+
buildStandaloneSessionTitle,
|
|
138
|
+
buildTourWindowTitle,
|
|
139
|
+
buildTwoWayComparisonTitle,
|
|
140
|
+
formatComparisonPair,
|
|
141
|
+
truncateTitle
|
|
142
|
+
});
|
|
143
|
+
//# sourceMappingURL=windowTitle.js.map
|
package/package.json
CHANGED
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
"properties": {
|
|
10
10
|
"version": { "const": 1 },
|
|
11
11
|
"title": { "$ref": "#/$defs/nonEmptyString" },
|
|
12
|
+
"windowTitle": {
|
|
13
|
+
"$ref": "#/$defs/nonEmptyString",
|
|
14
|
+
"description": "Optional native window title for the tour presenter. Use a short label such as a pull request number when multiple tours may be open."
|
|
15
|
+
},
|
|
12
16
|
"sourceUrl": { "type": "string", "minLength": 1 },
|
|
13
17
|
"range": {
|
|
14
18
|
"type": "object",
|
|
@@ -171,6 +171,10 @@ context, and keep the file within the corresponding repository so Bygone can
|
|
|
171
171
|
resolve those objects. Use a compiled `.tour.json` only when a portable
|
|
172
172
|
snapshot is required.
|
|
173
173
|
|
|
174
|
+
Set optional `windowTitle` when the tour should appear in the native window
|
|
175
|
+
title — for example a pull request number (`PR-1234`) so multiple open tours
|
|
176
|
+
stay distinguishable. When omitted, the presenter falls back to `title`.
|
|
177
|
+
|
|
174
178
|
For every step:
|
|
175
179
|
|
|
176
180
|
- make one concise explanatory claim;
|
package/web/web-host.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";(()=>{function V(){}V.prototype={diff:function(t,n){var r,s=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},a=s.callback;typeof s=="function"&&(a=s,s={}),this.options=s;var
|
|
2
|
-
`));var t=[],n=e.split(/(\n|\r\n)/);n[n.length-1]||n.pop();for(var r=0;r<n.length;r++){var s=n[r];r%2&&!this.options.newlineIsToken?t[t.length-1]+=s:(this.options.ignoreWhitespace&&(s=s.trim()),t.push(s))}return t};var
|
|
1
|
+
"use strict";(()=>{function V(){}V.prototype={diff:function(t,n){var r,s=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},a=s.callback;typeof s=="function"&&(a=s,s={}),this.options=s;var c=this;function i(N){return a?(setTimeout(function(){a(void 0,N)},0),!0):N}t=this.castInput(t),n=this.castInput(n),t=this.removeEmpty(this.tokenize(t)),n=this.removeEmpty(this.tokenize(n));var u=n.length,d=t.length,g=1,h=u+d;s.maxEditLength&&(h=Math.min(h,s.maxEditLength));var E=(r=s.timeout)!==null&&r!==void 0?r:1/0,L=Date.now()+E,C=[{oldPos:-1,lastComponent:void 0}],I=this.extractCommon(C[0],n,t,0);if(C[0].oldPos+1>=d&&I+1>=u)return i([{value:this.join(n),count:n.length}]);var w=-1/0,b=1/0;function x(){for(var N=Math.max(w,-g);N<=Math.min(b,g);N+=2){var _=void 0,F=C[N-1],O=C[N+1];F&&(C[N-1]=void 0);var B=!1;if(O){var ie=O.oldPos-N;B=O&&0<=ie&&ie<u}var fe=F&&F.oldPos+1<d;if(!B&&!fe){C[N]=void 0;continue}if(!fe||B&&F.oldPos+1<O.oldPos?_=c.addToPath(O,!0,void 0,0):_=c.addToPath(F,void 0,!0,1),I=c.extractCommon(_,n,t,N),_.oldPos+1>=d&&I+1>=u)return i(Xt(c,_.lastComponent,n,t,c.useLongestToken));C[N]=_,_.oldPos+1>=d&&(b=Math.min(b,N-1)),I+1>=u&&(w=Math.max(w,N+1))}g++}if(a)(function N(){setTimeout(function(){if(g>h||Date.now()>L)return a();x()||N()},0)})();else for(;g<=h&&Date.now()<=L;){var k=x();if(k)return k}},addToPath:function(t,n,r,s){var a=t.lastComponent;return a&&a.added===n&&a.removed===r?{oldPos:t.oldPos+s,lastComponent:{count:a.count+1,added:n,removed:r,previousComponent:a.previousComponent}}:{oldPos:t.oldPos+s,lastComponent:{count:1,added:n,removed:r,previousComponent:a}}},extractCommon:function(t,n,r,s){for(var a=n.length,c=r.length,i=t.oldPos,u=i-s,d=0;u+1<a&&i+1<c&&this.equals(n[u+1],r[i+1]);)u++,i++,d++;return d&&(t.lastComponent={count:d,previousComponent:t.lastComponent}),t.oldPos=i,u},equals:function(t,n){return this.options.comparator?this.options.comparator(t,n):t===n||this.options.ignoreCase&&t.toLowerCase()===n.toLowerCase()},removeEmpty:function(t){for(var n=[],r=0;r<t.length;r++)t[r]&&n.push(t[r]);return n},castInput:function(t){return t},tokenize:function(t){return t.split("")},join:function(t){return t.join("")}};function Xt(e,t,n,r,s){for(var a=[],c;t;)a.push(t),c=t.previousComponent,delete t.previousComponent,t=c;a.reverse();for(var i=0,u=a.length,d=0,g=0;i<u;i++){var h=a[i];if(h.removed){if(h.value=e.join(r.slice(g,g+h.count)),g+=h.count,i&&a[i-1].added){var L=a[i-1];a[i-1]=a[i],a[i]=L}}else{if(!h.added&&s){var E=n.slice(d,d+h.count);E=E.map(function(I,w){var b=r[g+w];return b.length>I.length?b:I}),h.value=e.join(E)}else h.value=e.join(n.slice(d,d+h.count));d+=h.count,h.added||(g+=h.count)}}var C=a[u-1];return u>1&&typeof C.value=="string"&&(C.added||C.removed)&&e.equals("",C.value)&&(a[u-2].value+=C.value,a.pop()),a}var Yt=new V;function Ze(e,t,n){return Yt.diff(e,t,n)}var Ye=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/,Je=/\S/,Me=new V;Me.equals=function(e,t){return this.options.ignoreCase&&(e=e.toLowerCase(),t=t.toLowerCase()),e===t||this.options.ignoreWhitespace&&!Je.test(e)&&!Je.test(t)};Me.tokenize=function(e){for(var t=e.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/),n=0;n<t.length-1;n++)!t[n+1]&&t[n+2]&&Ye.test(t[n])&&Ye.test(t[n+2])&&(t[n]+=t[n+2],t.splice(n+1,2),n--);return t};function Qe(e,t,n){return Me.diff(e,t,n)}var et=new V;et.tokenize=function(e){this.options.stripTrailingCr&&(e=e.replace(/\r\n/g,`
|
|
2
|
+
`));var t=[],n=e.split(/(\n|\r\n)/);n[n.length-1]||n.pop();for(var r=0;r<n.length;r++){var s=n[r];r%2&&!this.options.newlineIsToken?t[t.length-1]+=s:(this.options.ignoreWhitespace&&(s=s.trim()),t.push(s))}return t};var Jt=new V;Jt.tokenize=function(e){return e.split(/(\S.+?[.!?])(?=\s+|$)/)};var Zt=new V;Zt.tokenize=function(e){return e.split(/([{}:;,]|\s+)/)};function ye(e){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?ye=function(t){return typeof t}:ye=function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},ye(e)}var Qt=Object.prototype.toString,ce=new V;ce.useLongestToken=!0;ce.tokenize=et.tokenize;ce.castInput=function(e){var t=this.options,n=t.undefinedReplacement,r=t.stringifyReplacer,s=r===void 0?function(a,c){return typeof c>"u"?n:c}:r;return typeof e=="string"?e:JSON.stringify(Re(e,null,null,s),s," ")};ce.equals=function(e,t){return V.prototype.equals.call(ce,e.replace(/,([\r\n])/g,"$1"),t.replace(/,([\r\n])/g,"$1"))};function Re(e,t,n,r,s){t=t||[],n=n||[],r&&(e=r(s,e));var a;for(a=0;a<t.length;a+=1)if(t[a]===e)return n[a];var c;if(Qt.call(e)==="[object Array]"){for(t.push(e),c=new Array(e.length),n.push(c),a=0;a<e.length;a+=1)c[a]=Re(e[a],t,n,r,s);return t.pop(),n.pop(),c}if(e&&e.toJSON&&(e=e.toJSON()),ye(e)==="object"&&e!==null){t.push(e),c={},n.push(c);var i=[],u;for(u in e)e.hasOwnProperty(u)&&i.push(u);for(i.sort(),a=0;a<i.length;a+=1)u=i[a],c[u]=Re(e[u],t,n,r,u);t.pop(),n.pop()}else c=e;return c}var Ie=new V;Ie.tokenize=function(e){return e.slice()};Ie.join=Ie.removeEmpty=function(e){return e};function tt(e,t,n){return Ie.diff(e,t,n)}var tn=500,nn=100,nt=wt("BYGONE_MAX_INLINE_HIGHLIGHT_LINE_LENGTH",tn),rn=wt("BYGONE_DIFF_TIMEOUT_MS",nn);function Q(e,t,n={}){let r=rt(e),s=rt(t),a=tt(r,s,{timeout:n.timeoutMs??rn});if(!a)return on(r,s);let c=[],i=[],u=[],d=[],g=1,h=1;for(let L=0;L<a.length;L++){let C=a[L],I=C.removed?C.value:[],w=C.added?C.value:[];if(!C.added&&!C.removed){for(let b of C.value)i.push(Y("context",b,g)),u.push(Y("context",b,h)),c.push(re(X("context",b,g++),X("context",b,h++)));continue}if(C.removed&&L+1<a.length&&a[L+1].added){let b=a[L+1],x=i.length,k=u.length,N=pt(I,b.value);for(let{left:_,right:F}of N){let O,B;_!==void 0&&(O=Y("removed",_,g),i.push(O)),F!==void 0&&(B=Y("added",F,h),u.push(B)),O&&B&&Sn(O,B),c.push(re(_===void 0?ne():X("removed",_,g++),F===void 0?ne():X("added",F,h++)))}d.push(Se("replace",x,i.length,k,u.length)),L++;continue}if(C.removed){let b=i.length,x=u.length;for(let k of I)i.push(Y("removed",k,g)),c.push(re(X("removed",k,g++),ne()));d.push(Se("delete",b,i.length,x,u.length));continue}if(C.added){let b=i.length,x=u.length;for(let k of w)u.push(Y("added",k,h)),c.push(re(ne(),X("added",k,h++)));d.push(Se("insert",b,i.length,x,u.length))}}let E=c.some(L=>L.left.kind!=="context"||L.right.kind!=="context");return{rows:c,leftLines:i,rightLines:u,blocks:d,hasChanges:E}}function on(e,t){let n=e.map((c,i)=>Y("removed",c,i+1)),r=t.map((c,i)=>Y("added",c,i+1)),s=[...e.map((c,i)=>re(X("removed",c,i+1),ne())),...t.map((c,i)=>re(ne(),X("added",c,i+1)))],a="replace";return e.length===0?a="insert":t.length===0&&(a="delete"),{rows:s,leftLines:n,rightLines:r,blocks:s.length===0?[]:[Se(a,0,e.length,0,t.length)],hasChanges:s.length>0}}function rt(e){if(e.length===0)return[];let t=e.replace(/\r\n/g,`
|
|
3
3
|
`).split(`
|
|
4
|
-
`);return t[t.length-1]===""&&t.pop(),t}var ht=1e4,it=2e3,
|
|
4
|
+
`);return t[t.length-1]===""&&t.pop(),t}var ht=1e4,it=2e3,sn=.52,an=.35,gt=.38,ln=.33,mt=.86,Ee=.08,xe=.05,ve=-.12,ot=5e3,cn=2e3,st=4,un=8,Fe=4;function pt(e,t){if(e.length===0)return t.map(u=>({right:u}));if(t.length===0)return e.map(u=>({left:u}));if(e.length===1&&t.length===1){let u=Oe(e[0],t[0]);return(u.eligible||u.score>=an)&&_e(e[0],t[0])&&ue(J(e[0]))&&ue(J(t[0]))?[{left:e[0],right:t[0]}]:[{left:e[0]},{right:t[0]}]}if(e.length*t.length>ht)return mn(e,t);let n=dn(e,t),r=Array.from({length:e.length+1},()=>new Array(t.length+1).fill(Number.NEGATIVE_INFINITY)),s=Array.from({length:e.length+1},()=>new Array(t.length+1).fill(null));r[0][0]=0;for(let u=1;u<=e.length;u++)r[u][0]=r[u-1][0]+ve,s[u][0]="left";for(let u=1;u<=t.length;u++)r[0][u]=r[0][u-1]+ve,s[0][u]="right";for(let u=1;u<=e.length;u++)for(let d=1;d<=t.length;d++){let g=n[u-1][d-1],E=[{move:"left",score:r[u-1][d]+ve},{move:"right",score:r[u][d-1]+ve},{move:"match",score:g===null?Number.NEGATIVE_INFINITY:r[u-1][d-1]+g}].reduce((L,C)=>C.score>L.score?C:L);r[u][d]=E.score,s[u][d]=E.move}let a=[],c=e.length,i=t.length;for(;c>0||i>0;){let u=s[c][i];u==="match"?a.push({left:e[--c],right:t[--i]}):u==="left"?a.push({left:e[--c]}):a.push({right:t[--i]})}return a.reverse()}function Oe(e,t){let n=J(e),r=J(t),s=ue(n),a=ue(r);if(!s||!a||n.length>it||r.length>it)return{score:0,eligible:!1,characterSimilarity:0,tokenSimilarity:0,lengthSimilarity:0};if(n===r)return{score:1,eligible:!0,characterSimilarity:1,tokenSimilarity:1,lengthSimilarity:1};let c=He(n),i=He(r),u=Tn(n,r),d=xn(c,i),g=Math.min(n.length,r.length)/Math.max(n.length,r.length),h=vn(c,i),E=u*.52+d*.32+g*.1+h*.06,L=u>=.52||d>=.45||u>=.48&&d>=.28;return{score:E,eligible:L&&E>=sn,characterSimilarity:u,tokenSimilarity:d,lengthSimilarity:g}}function dn(e,t){let n=e.map(I=>t.map(w=>Oe(I,w))),r=bt(e,t),s=n.map(I=>De(I)),a=t.map((I,w)=>De(n.map(b=>b[w]))),c=n.map((I,w)=>I.map((b,x)=>{if(r.has(`${w}:${x}`))return Math.max(b.score,1);if(!b.eligible)return null;let k=s[w],N=a[x],_=b.score===k.best&&b.score===N.best,F=b.score>=mt?Ee/2:Ee,O=k.best-k.second>=F,B=N.best-N.second>=F;return _&&O&&B?b.score:null}));if(Math.max(e.length,t.length)>un||Math.abs(e.length-t.length)>Fe)return c;let i=(I,w,b)=>I.score>=gt&&_e(e[w],t[b])&&Math.abs(w-b)<=Fe,u=n.map((I,w)=>Te(I,(b,x)=>i(b,w,x))),d=t.map((I,w)=>Te(n.map(b=>b[w]),(b,x)=>i(b,x,w))),g=(I,w,b)=>I.score>=ln&&_e(e[w],t[b])&&Math.abs(w-b)<=Fe,h=n.map((I,w)=>Te(I,(b,x)=>g(b,w,x))),E=t.map((I,w)=>Te(n.map(b=>b[w]),(b,x)=>g(b,x,w))),L=(I,w)=>{let b=n[I][w];if(!i(b,I,w))return!1;let x=u[I],k=d[w];return b.score===x.best&&b.score===k.best&&x.best-x.second>=xe&&k.best-k.second>=xe},C=(I,w)=>{let b=n[I][w];if(!g(b,I,w))return!1;let x=h[I],k=E[w];return b.score===x.best&&b.score===k.best&&x.best-x.second>=xe&&k.best-k.second>=xe};return c.map((I,w)=>I.map((b,x)=>{if(b!==null)return b;let k=L(w,x)&&(fn(c,w,x)||hn(n,w,x,L)),N=gn(n,w,x,(_,F)=>g(n[_][F],_,F),C);return!k&&!N?null:n[w][x].score}))}function fn(e,t,n){return t>0&&n>0&&e[t-1][n-1]!==null||t+1<e.length&&n+1<e[t+1].length&&e[t+1][n+1]!==null}function hn(e,t,n,r){return t>0&&n>0&&r(t-1,n-1)||t+1<e.length&&n+1<e[t+1].length&&r(t+1,n+1)}function gn(e,t,n,r,s){let a=t,c=n;for(;a>0&&c>0&&r(a-1,c-1);)a--,c--;let i=t,u=n,d=e[t][n].score,g=1;for(;i+1<e.length&&u+1<e[i+1].length&&r(i+1,u+1);)i++,u++,d+=e[i][u].score,g++;for(let h=t-1,E=n-1;h>=a&&E>=c;h--,E--)d+=e[h][E].score,g++;return g>=3&&d/g>=gt&&s(a,c)&&s(i,u)}function Te(e,t){let n=Number.NEGATIVE_INFINITY,r=Number.NEGATIVE_INFINITY;return e.forEach((s,a)=>{t(s,a)&&(s.score>n?(r=n,n=s.score):s.score>r&&(r=s.score))}),{best:n,second:r}}function De(e){let t=Number.NEGATIVE_INFINITY,n=Number.NEGATIVE_INFINITY;for(let r of e)r.eligible&&(r.score>t?(n=t,t=r.score):r.score>n&&(n=r.score));return{best:t,second:n}}function mn(e,t){let n=pn(e,t),r=[],s=0,a=0;for(let c of n)dt(r,e.slice(s,c.leftIndex),t.slice(a,c.rightIndex)),r.push({left:e[c.leftIndex],right:t[c.rightIndex]}),s=c.leftIndex+1,a=c.rightIndex+1;return dt(r,e.slice(s),t.slice(a)),r}function pn(e,t){let n=bn(e,t);if(n===null)return[];let r=bt(e,t),s=n.map(({leftIndex:d,rightIndex:g,exact:h})=>({leftIndex:d,rightIndex:g,exact:h,structural:r.has(`${d}:${g}`),match:Oe(e[d],t[g])})).filter(d=>d.exact||d.structural||d.match.eligible),a=ct(s,"leftIndex"),c=ct(s,"rightIndex"),i=s.filter(d=>{if(d.exact||d.structural)return!0;let g=a.get(d.leftIndex),h=c.get(d.rightIndex);if(!g||!h||d.match.score!==g.best||d.match.score!==h.best)return!1;let E=d.match.score>=mt?Ee/2:Ee;return g.best-g.second>=E&&h.best-h.second>=E}),u=yn(i,t.length);return u.length<=cn?u:[]}function bn(e,t){let n=at(e,J),r=at(t,J),s=new Map;for(let[i,u]of n){let d=r.get(i);if(!ue(i)||u.length!==1||d?.length!==1)continue;let g=u[0],h=d[0];if(s.set(`${g}:${h}`,{leftIndex:g,rightIndex:h,exact:!0}),s.size>ot)return null}let a=lt(e),c=lt(t);for(let[i,u]of a){let d=c.get(i);if(!(!d||u.length>st||d.length>st))for(let g of u)for(let h of d){let E=`${g}:${h}`;if(!s.has(E)&&(s.set(E,{leftIndex:g,rightIndex:h,exact:!1}),s.size>ot))return null}}return[...s.values()]}function at(e,t){let n=new Map;return e.forEach((r,s)=>{let a=t(r),c=n.get(a)??[];c.push(s),n.set(a,c)}),n}function lt(e){let t=new Map;return e.forEach((n,r)=>{let s=new Set(He(J(n)).filter(wn));for(let a of s){let c=t.get(a)??[];c.push(r),t.set(a,c)}}),t}function wn(e){return e.length>=2&&/[\p{L}\p{N}_$]/u.test(e)}function ct(e,t){let n=new Map;for(let r of e){let s=n.get(r[t])??[];s.push(r.match),n.set(r[t],s)}return new Map([...n].map(([r,s])=>[r,De(s)]))}function yn(e,t){let n=[...e].sort((d,g)=>d.leftIndex-g.leftIndex||d.rightIndex-g.rightIndex),r=new Array(t+2).fill(0),s=new Array(t+2).fill(-1),a=new Array(n.length).fill(0),c=new Array(n.length).fill(-1);for(let d=0;d<n.length;){let g=d+1;for(;g<n.length&&n[g].leftIndex===n[d].leftIndex;)g++;for(let h=d;h<g;h++){let E=ut(r,s,n[h].rightIndex),L=n[h].exact||n[h].structural?.5:0;a[h]=E.score+n[h].match.score+L,c[h]=E.candidateIndex}for(let h=d;h<g;h++)In(r,s,n[h].rightIndex+1,a[h],h);d=g}let i=ut(r,s,t+1),u=[];for(let d=i.candidateIndex;d>=0;d=c[d])u.push({leftIndex:n[d].leftIndex,rightIndex:n[d].rightIndex});return u.reverse()}function ut(e,t,n){let r=0,s=-1;for(let a=n;a>0;a-=a&-a)e[a]>r&&(r=e[a],s=t[a]);return{score:r,candidateIndex:s}}function In(e,t,n,r,s){for(let a=n;a<e.length;a+=a&-a)r>e[a]&&(e[a]=r,t[a]=s)}function dt(e,t,n){if(t.length*n.length<=ht){e.push(...pt(t,n));return}e.push(...t.map(r=>({left:r}))),e.push(...n.map(r=>({right:r})))}function J(e){return e.trim().replace(/\s+/g," ")}function bt(e,t){let n=ft(e),r=ft(t),s=new Set;for(let[a,c]of n){let i=r.get(a);c.length===1&&i?.length===1&&s.add(`${c[0]}:${i[0]}`)}return s}function ft(e){let t=new Map;return e.forEach((n,r)=>{let s=Pe(n);if(!s)return;let a=t.get(s)??[];a.push(r),t.set(s,a)}),t}function _e(e,t){let n=Pe(e),r=Pe(t);return!n||!r?n===r:n.split(":",1)[0]===r.split(":",1)[0]}function Pe(e){let t=J(e),n=[["function",/^(?:(?:export|default)\s+)*(?:async\s+)?function\s*\*?\s*([\p{L}_$][\p{L}\p{N}_$]*)\s*\(/u],["function",/^(?:async\s+)?def\s+([\p{L}_][\p{L}\p{N}_]*)\s*\(/u],["function",/^(?:pub(?:\([^)]*\))?\s+)?(?:async\s+)?fn\s+([\p{L}_][\p{L}\p{N}_]*)\s*(?:<[^>]*>)?\s*\(/u],["function",/^func\s+(?:\([^)]*\)\s*)?([\p{L}_][\p{L}\p{N}_]*)\s*\(/u],["class",/^(?:(?:export|default|abstract|public)\s+)*class\s+([\p{L}_$][\p{L}\p{N}_$]*)\b/u]];for(let[r,s]of n){let a=t.match(s);if(a)return`${r}:${a[1]}`}return null}function ue(e){return e.length<3?!1:/[\p{L}\p{N}_$]/u.test(e)&&!/^[\s()[\]{};,.:+\-*/=>|&!?'"`]+$/.test(e)}function He(e){return e.toLowerCase().match(/[\p{L}_$][\p{L}\p{N}_$]*|\p{N}+(?:\.\p{N}+)?|[^\s\p{L}\p{N}_$]/gu)??[]}function xn(e,t){if(e.length+t.length===0)return 1;let n=new Map;e.forEach(s=>n.set(s,(n.get(s)??0)+1));let r=0;for(let s of t){let a=n.get(s)??0;a>0&&(r++,n.set(s,a-1))}return 2*r/(e.length+t.length)}function vn(e,t){if(e.length===0||t.length===0)return 0;let n=e[0]===t[0]?.5:0,r=e[e.length-1]===t[t.length-1]?.5:0;return n+r}function Tn(e,t){let n=e.length+t.length;return n===0?1:2*Ze(e,t).filter(s=>!s.added&&!s.removed).reduce((s,a)=>s+a.value.length,0)/n}function Sn(e,t){if(e.content.length>nt||t.content.length>nt)return;let{leftSegments:n,rightSegments:r,hasInlineChanges:s}=En(e.content,t.content);s&&(e.segments=n,t.segments=r)}function En(e,t){let n=Qe(e,t),r=[],s=[],a=!1;for(let c of n){let i=c.value;if(!c.added&&!c.removed){let d={kind:"context",text:i,emphasis:!1};r.push(d),s.push(d);continue}let u=/[^\s]/.test(i);a=a||u,c.removed&&r.push({kind:"removed",text:i,emphasis:u}),c.added&&s.push({kind:"added",text:i,emphasis:u})}return{leftSegments:r,rightSegments:s,hasInlineChanges:a}}function ne(){return{kind:"placeholder",content:"",lineNumber:null}}function X(e,t,n){return{kind:e,content:t,lineNumber:n}}function Y(e,t,n){return{kind:e,content:t,lineNumber:n}}function re(e,t){return{left:e,right:t}}function Se(e,t,n,r,s){return{kind:e,leftStart:t,leftEnd:n,rightStart:r,rightEnd:s}}function wt(e,t){let n=typeof process<"u"?process.env?.[e]:void 0,r=Number.parseInt(n??"",10);return Number.isFinite(r)&&r>0?r:t}function yt(){return{leftFileName:"test-file-1.js",rightFileName:"test-file-2.js",leftContent:`// Test File 1 - Example JavaScript Code
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const path = require('path');
|
|
7
7
|
|
|
@@ -145,7 +145,7 @@ if (require.main === module) {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
module.exports = FileProcessor;
|
|
148
|
-
`}}function It(e){if(!H(e)||e.version!==1)throw new Error("Unsupported or missing change-tour manifest version.");if(A(e.title,"title"),A(e.generatedAt,"generatedAt"),e.sourceUrl!==void 0&&A(e.sourceUrl,"sourceUrl"),!H(e.range))throw new Error("Change-tour manifest range must be an object.");for(let r of["baseRef","headRef","mergeBaseOid","headOid"])A(e.range[r],`range.${r}`);if(!H(e.summary))throw new Error("Change-tour manifest summary must be an object.");for(let r of["changedFiles","includedScenes","additions","deletions","commitCount"])ee(e.summary[r],`summary.${r}`);if(de(e.summary.omittedFiles,"summary.omittedFiles"),!Array.isArray(e.commits)||!Array.isArray(e.chapters)||!Array.isArray(e.scenes))throw new Error("Change-tour manifest commits, chapters, and scenes must be arrays.");if(e.files!==void 0&&!Array.isArray(e.files))throw new Error("Change-tour manifest files must be an array.");let t=new Set;for(let[r,s]of e.scenes.entries()){if(Ue(s,r),t.has(s.id))throw new Error(`Duplicate change-tour scene id: ${s.id}`);t.add(s.id)}for(let[r,s]of e.chapters.entries()){if(!H(s))throw new Error(`chapters[${r}] must be an object.`);A(s.id,`chapters[${r}].id`),A(s.title,`chapters[${r}].title`),de(s.sceneIds,`chapters[${r}].sceneIds`);for(let a of s.sceneIds)if(!t.has(a))throw new Error(`Chapter references unknown scene id: ${a}`)}if(e.summary.includedScenes!==e.scenes.length)throw new Error("summary.includedScenes must match the number of scenes.");let n=e.files===void 0?kn(e.scenes):e.files.map((r,s)=>(Ln(r,s),r));if(e.files!==void 0&&e.summary.changedFiles!==n.length)throw new Error("summary.changedFiles must match the number of files.");return{...e,files:n}}function Ue(e,t){if(!H(e)||!["text-diff","discussion","walkthrough","stacked-diff","deconstructed-diff"].includes(String(e.kind)))throw new Error(`scenes[${t}] must be a text-diff, discussion, walkthrough, stacked-diff, or deconstructed-diff scene.`);for(let n of["id","title"])A(e[n],`scenes[${t}].${n}`);if(Nn(e,`scenes[${t}]`),e.kind!=="discussion"){if(e.kind==="walkthrough"){if(!Array.isArray(e.steps)||e.steps.length===0)throw new Error(`scenes[${t}].steps must be a non-empty array.`);for(let[n,r]of e.steps.entries()){let s=`scenes[${t}].steps[${n}]`;if(!H(r)||!H(r.focus)||!H(r.diff))throw new Error(`${s} must contain focus and diff objects.`);for(let a of["id","title","body"])A(r[a],`${s}.${a}`);if(r.depth!==void 0&&!["mentioned","explained","contextualized"].includes(String(r.depth)))throw new Error(`${s}.depth must be mentioned, explained, or contextualized.`);if(Be(r.focus,`${s}.focus`),Ue(r.diff,t),r.diff.kind!=="text-diff")throw new Error(`${s}.diff must be a text-diff scene.`);if(r.connection!==void 0){if(!H(r.connection))throw new Error(`${s}.connection must be an object.`);A(r.connection.id,`${s}.connection.id`),A(r.connection.label,`${s}.connection.label`),Be(r.connection.from,`${s}.connection.from`),Be(r.connection.to,`${s}.connection.to`)}}return}if(e.kind==="stacked-diff"){Tn(e,t);return}if(e.kind==="deconstructed-diff"){Cn(e,t);return}for(let n of["path","leftLabel","rightLabel","leftContent","rightContent"])A(e[n],`scenes[${t}].${n}`);e.previousPath!==void 0&&A(e.previousPath,`scenes[${t}].previousPath`),A(e.changeKind,`scenes[${t}].changeKind`),ee(e.additions,`scenes[${t}].additions`),ee(e.deletions,`scenes[${t}].deletions`),e.focusChangeIndex!==void 0&&ee(e.focusChangeIndex,`scenes[${t}].focusChangeIndex`)}}function Tn(e,t){if(!Array.isArray(e.stack)||e.stack.length<3||e.stack.length>6)throw new Error(`scenes[${t}].stack must contain between 3 and 6 revisions.`);for(let[n,r]of e.stack.entries()){if(!H(r))throw new Error(`scenes[${t}].stack[${n}] must be an object.`);for(let s of["id","ref","oid","label"])A(r[s],`scenes[${t}].stack[${n}].${s}`)}xt(e.files,e.stack.length,t),vt(e.steps,e.stack.length,t,!1)}function Cn(e,t){if(e.stageLabel!=="Explanation stages")throw new Error(`scenes[${t}].stageLabel must be Explanation stages.`);if(!H(e.realRange))throw new Error(`scenes[${t}].realRange must be an object.`);for(let r of["baseRef","targetRef","baseOid","targetOid"])A(e.realRange[r],`scenes[${t}].realRange.${r}`);if(!Array.isArray(e.panels)||e.panels.length<2||e.panels.length>13)throw new Error(`scenes[${t}].panels must contain a baseline and between 1 and 12 stages.`);let n=e.panels;for(let[r,s]of n.entries()){if(!H(s))throw new Error(`scenes[${t}].panels[${r}] must be an object.`);for(let l of["id","label","role"])A(s[l],`scenes[${t}].panels[${r}].${l}`);let a=r===0?"baseline":"stage";if(s.role!==a)throw new Error(`scenes[${t}].panels[${r}].role must be ${a}.`);r>0&&A(s.stageId,`scenes[${t}].panels[${r}].stageId`)}if(xt(e.files,n.length,t),vt(e.steps,n.length,t,!0),Array.isArray(e.steps)&&e.steps.length!==n.length-1)throw new Error(`scenes[${t}].steps must match the number of explanation stages.`);Array.isArray(e.steps)&&e.steps.forEach((r,s)=>{let a=n[s+1];if(!H(r)||!H(a)||a.stageId!==r.id)throw new Error(`scenes[${t}].panels must align with explanation stage ids.`)})}function xt(e,t,n){if(!Array.isArray(e)||e.length===0)throw new Error(`scenes[${n}].files must be non-empty.`);for(let[r,s]of e.entries()){if(!H(s))throw new Error(`scenes[${n}].files[${r}] must be an object.`);if(A(s.path,`scenes[${n}].files[${r}].path`),!Array.isArray(s.panels)||s.panels.length!==t)throw new Error(`scenes[${n}].files[${r}].panels must match panel count.`);for(let[a,l]of s.panels.entries()){if(!H(l))throw new Error(`scenes[${n}].files[${r}].panels[${a}] must be an object.`);for(let i of["id","label","content"])A(l[i],`scenes[${n}].files[${r}].panels[${a}].${i}`);if(l.path!==void 0&&A(l.path,`scenes[${n}].files[${r}].panels[${a}].path`),typeof l.exists!="boolean")throw new Error(`scenes[${n}].files[${r}].panels[${a}].exists must be boolean.`)}}}function vt(e,t,n,r){if(!Array.isArray(e)||e.length===0)throw new Error(`scenes[${n}].steps must be non-empty.`);for(let[s,a]of e.entries()){if(!H(a))throw new Error(`scenes[${n}].steps[${s}] must be an object.`);for(let l of["id","title","body","file","side"])A(a[l],`scenes[${n}].steps[${s}].${l}`);if(ee(a.pairIndex,`scenes[${n}].steps[${s}].pairIndex`),Number(a.pairIndex)>=t-1)throw new Error(`scenes[${n}].steps[${s}].pairIndex is outside the panels.`);if(r){if(de(a.introducedHunks,`scenes[${n}].steps[${s}].introducedHunks`),a.introducedHunks.length===0)throw new Error(`scenes[${n}].steps[${s}].introducedHunks must be non-empty.`);if(Number(a.pairIndex)!==s)throw new Error(`scenes[${n}].steps[${s}].pairIndex must match its explanation stage.`)}if(a.side!=="left"&&a.side!=="right")throw new Error(`scenes[${n}].steps[${s}].side must be left or right.`);a.startLine!==void 0&&Ce(a.startLine,`scenes[${n}].steps[${s}].startLine`),a.endLine!==void 0&&Ce(a.endLine,`scenes[${n}].steps[${s}].endLine`)}}function Ln(e,t){if(!H(e))throw new Error(`files[${t}] must be an object.`);if(e.kind==="text-diff"){Ue(e,t);return}if(e.kind!=="omitted")throw new Error(`files[${t}].kind must be text-diff or omitted.`);for(let n of["id","title","path","changeKind","reason"])A(e[n],`files[${t}].${n}`);e.previousPath!==void 0&&A(e.previousPath,`files[${t}].previousPath`),ee(e.additions,`files[${t}].additions`),ee(e.deletions,`files[${t}].deletions`)}function kn(e){let t=new Map;for(let n of e){if(n.kind==="text-diff"){t.has(n.path)||t.set(n.path,n);continue}if(n.kind==="walkthrough")for(let r of n.steps)t.has(r.diff.path)||t.set(r.diff.path,r.diff)}return[...t.values()].sort((n,r)=>n.path.localeCompare(r.path))}function Be(e,t){if(!H(e))throw new Error(`${t} must be an object.`);for(let n of["id","path","revision","excerpt"])A(e[n],`${t}.${n}`);if(e.revision!=="base"&&e.revision!=="head")throw new Error(`${t}.revision must be base or head.`);if(Ce(e.startLine,`${t}.startLine`),Ce(e.endLine,`${t}.endLine`),Number(e.endLine)<Number(e.startLine))throw new Error(`${t}.endLine must not precede startLine.`)}function Nn(e,t){A(e.summary,`${t}.summary`),de(e.bullets,`${t}.bullets`),de(e.tags,`${t}.tags`),A(e.takeaway,`${t}.takeaway`)}function H(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function A(e,t){if(typeof e!="string")throw new Error(`${t} must be a string.`)}function de(e,t){if(!Array.isArray(e)||e.some(n=>typeof n!="string"))throw new Error(`${t} must be an array of strings.`)}function ee(e,t){if(!Number.isInteger(e)||Number(e)<0)throw new Error(`${t} must be a non-negative integer.`)}function Ce(e,t){if(!Number.isInteger(e)||Number(e)<1)throw new Error(`${t} must be a positive integer.`)}function St(e,t,n){let r=e.findIndex(i=>i.id===t),s=r>=0?r:0,a=e[s];if(!a||a.kind!=="walkthrough"&&a.kind!=="stacked-diff"&&a.kind!=="deconstructed-diff"||!n)return{sceneIndex:s,stepIndex:0};let l=a.steps.findIndex(i=>i.id===n);return{sceneIndex:s,stepIndex:l>=0?l:0}}function Tt(e,t,n){let r=e[t.sceneIndex];if(!r)return null;if(n>0)return(r.kind==="walkthrough"||r.kind==="stacked-diff"||r.kind==="deconstructed-diff")&&t.stepIndex<r.steps.length-1?{sceneIndex:t.sceneIndex,stepIndex:t.stepIndex+1}:t.sceneIndex<e.length-1?{sceneIndex:t.sceneIndex+1,stepIndex:0}:null;if((r.kind==="walkthrough"||r.kind==="stacked-diff"||r.kind==="deconstructed-diff")&&t.stepIndex>0)return{sceneIndex:t.sceneIndex,stepIndex:t.stepIndex-1};if(t.sceneIndex===0)return null;let s=e[t.sceneIndex-1];return{sceneIndex:t.sceneIndex-1,stepIndex:s.kind==="walkthrough"||s.kind==="stacked-diff"||s.kind==="deconstructed-diff"?s.steps.length-1:0}}function Ct(e,t,n){if(!t)return null;let r=e.map((i,u)=>({file:i,fileIndex:u})).filter(({file:i})=>i.kind==="text-diff"),s=r.findIndex(({file:i})=>i.path===t),a=s+n,l=s>=0?r[a]:null;return l?{fileIndex:l.fileIndex,path:l.file.path}:null}function Lt(e,t,n){let r=e[t.sceneIndex],s=Et(r,t.sceneIndex,t.stepIndex,n);if(s)return s;for(let a=0;a<e.length;a+=1){if(a===t.sceneIndex)continue;let l=Et(e[a],a,0,n);if(l)return l}return null}function Et(e,t,n,r){if(!e||e.kind!=="stacked-diff"&&e.kind!=="deconstructed-diff"||!e.files.some(l=>l.path===r))return null;let a=e.steps[n]?.file===r?n:e.steps.findIndex(l=>l.file===r);return{sceneIndex:t,stepIndex:a>=0?a:Math.max(n,0)}}function Nt(e,t,n="all",r=300){let s=t.trim().toLocaleLowerCase();if(!s||r<=0)return[];let a=[];if(n!=="code"){let l=new Map;e.chapters.forEach(i=>i.sceneIds.forEach(u=>l.set(u,i.title))),e.scenes.forEach((i,u)=>{let d=[l.get(i.id),i.title,i.summary,...i.bullets,...i.tags,i.takeaway],g=kt(d,s);g&&a.push({kind:"narrative",sceneIndex:u,label:i.title,preview:g}),An(i)&&i.steps.forEach((h,T)=>{let L=kt([h.title,h.body,"connection"in h?h.connection?.label:void 0],s);L&&a.push({kind:"narrative",sceneIndex:u,stepIndex:T,label:`${i.title} \xB7 ${h.title}`,preview:L})})})}if(n!=="narrative"&&a.length<r)for(let l=0;l<e.files.length;l+=1){let i=e.files[l];if(i.kind==="text-diff"){for(let[u,d]of[[0,i.leftContent],[1,i.rightContent]])for(let g of $n(d,s))if(a.push({kind:"code",fileIndex:l,sideIndex:u,label:`${i.path} \xB7 ${u===0?"base":"head"}`,...g}),a.length>=r)return a}}return a.slice(0,r)}function kt(e,t){return e.find(n=>n?.toLocaleLowerCase().includes(t))}function $n(e,t){let n=[];return e.replace(/\r\n/g,`
|
|
148
|
+
`}}function It(e){if(!P(e)||e.version!==1)throw new Error("Unsupported or missing change-tour manifest version.");if($(e.title,"title"),$(e.generatedAt,"generatedAt"),e.windowTitle!==void 0&&$(e.windowTitle,"windowTitle"),e.sourceUrl!==void 0&&$(e.sourceUrl,"sourceUrl"),!P(e.range))throw new Error("Change-tour manifest range must be an object.");for(let r of["baseRef","headRef","mergeBaseOid","headOid"])$(e.range[r],`range.${r}`);if(!P(e.summary))throw new Error("Change-tour manifest summary must be an object.");for(let r of["changedFiles","includedScenes","additions","deletions","commitCount"])ee(e.summary[r],`summary.${r}`);if(de(e.summary.omittedFiles,"summary.omittedFiles"),!Array.isArray(e.commits)||!Array.isArray(e.chapters)||!Array.isArray(e.scenes))throw new Error("Change-tour manifest commits, chapters, and scenes must be arrays.");if(e.files!==void 0&&!Array.isArray(e.files))throw new Error("Change-tour manifest files must be an array.");let t=new Set;for(let[r,s]of e.scenes.entries()){if(We(s,r),t.has(s.id))throw new Error(`Duplicate change-tour scene id: ${s.id}`);t.add(s.id)}for(let[r,s]of e.chapters.entries()){if(!P(s))throw new Error(`chapters[${r}] must be an object.`);$(s.id,`chapters[${r}].id`),$(s.title,`chapters[${r}].title`),de(s.sceneIds,`chapters[${r}].sceneIds`);for(let a of s.sceneIds)if(!t.has(a))throw new Error(`Chapter references unknown scene id: ${a}`)}if(e.summary.includedScenes!==e.scenes.length)throw new Error("summary.includedScenes must match the number of scenes.");let n=e.files===void 0?$n(e.scenes):e.files.map((r,s)=>(kn(r,s),r));if(e.files!==void 0&&e.summary.changedFiles!==n.length)throw new Error("summary.changedFiles must match the number of files.");return{...e,files:n}}function We(e,t){if(!P(e)||!["text-diff","discussion","walkthrough","stacked-diff","deconstructed-diff"].includes(String(e.kind)))throw new Error(`scenes[${t}] must be a text-diff, discussion, walkthrough, stacked-diff, or deconstructed-diff scene.`);for(let n of["id","title"])$(e[n],`scenes[${t}].${n}`);if(Nn(e,`scenes[${t}]`),e.kind!=="discussion"){if(e.kind==="walkthrough"){if(!Array.isArray(e.steps)||e.steps.length===0)throw new Error(`scenes[${t}].steps must be a non-empty array.`);for(let[n,r]of e.steps.entries()){let s=`scenes[${t}].steps[${n}]`;if(!P(r)||!P(r.focus)||!P(r.diff))throw new Error(`${s} must contain focus and diff objects.`);for(let a of["id","title","body"])$(r[a],`${s}.${a}`);if(r.depth!==void 0&&!["mentioned","explained","contextualized"].includes(String(r.depth)))throw new Error(`${s}.depth must be mentioned, explained, or contextualized.`);if(Be(r.focus,`${s}.focus`),We(r.diff,t),r.diff.kind!=="text-diff")throw new Error(`${s}.diff must be a text-diff scene.`);if(r.connection!==void 0){if(!P(r.connection))throw new Error(`${s}.connection must be an object.`);$(r.connection.id,`${s}.connection.id`),$(r.connection.label,`${s}.connection.label`),Be(r.connection.from,`${s}.connection.from`),Be(r.connection.to,`${s}.connection.to`)}}return}if(e.kind==="stacked-diff"){Cn(e,t);return}if(e.kind==="deconstructed-diff"){Ln(e,t);return}for(let n of["path","leftLabel","rightLabel","leftContent","rightContent"])$(e[n],`scenes[${t}].${n}`);e.previousPath!==void 0&&$(e.previousPath,`scenes[${t}].previousPath`),$(e.changeKind,`scenes[${t}].changeKind`),ee(e.additions,`scenes[${t}].additions`),ee(e.deletions,`scenes[${t}].deletions`),e.focusChangeIndex!==void 0&&ee(e.focusChangeIndex,`scenes[${t}].focusChangeIndex`)}}function Cn(e,t){if(!Array.isArray(e.stack)||e.stack.length<3||e.stack.length>6)throw new Error(`scenes[${t}].stack must contain between 3 and 6 revisions.`);for(let[n,r]of e.stack.entries()){if(!P(r))throw new Error(`scenes[${t}].stack[${n}] must be an object.`);for(let s of["id","ref","oid","label"])$(r[s],`scenes[${t}].stack[${n}].${s}`)}xt(e.files,e.stack.length,t),vt(e.steps,e.stack.length,t,!1)}function Ln(e,t){if(e.stageLabel!=="Explanation stages")throw new Error(`scenes[${t}].stageLabel must be Explanation stages.`);if(!P(e.realRange))throw new Error(`scenes[${t}].realRange must be an object.`);for(let r of["baseRef","targetRef","baseOid","targetOid"])$(e.realRange[r],`scenes[${t}].realRange.${r}`);if(!Array.isArray(e.panels)||e.panels.length<2||e.panels.length>13)throw new Error(`scenes[${t}].panels must contain a baseline and between 1 and 12 stages.`);let n=e.panels;for(let[r,s]of n.entries()){if(!P(s))throw new Error(`scenes[${t}].panels[${r}] must be an object.`);for(let c of["id","label","role"])$(s[c],`scenes[${t}].panels[${r}].${c}`);let a=r===0?"baseline":"stage";if(s.role!==a)throw new Error(`scenes[${t}].panels[${r}].role must be ${a}.`);r>0&&$(s.stageId,`scenes[${t}].panels[${r}].stageId`)}if(xt(e.files,n.length,t),vt(e.steps,n.length,t,!0),Array.isArray(e.steps)&&e.steps.length!==n.length-1)throw new Error(`scenes[${t}].steps must match the number of explanation stages.`);Array.isArray(e.steps)&&e.steps.forEach((r,s)=>{let a=n[s+1];if(!P(r)||!P(a)||a.stageId!==r.id)throw new Error(`scenes[${t}].panels must align with explanation stage ids.`)})}function xt(e,t,n){if(!Array.isArray(e)||e.length===0)throw new Error(`scenes[${n}].files must be non-empty.`);for(let[r,s]of e.entries()){if(!P(s))throw new Error(`scenes[${n}].files[${r}] must be an object.`);if($(s.path,`scenes[${n}].files[${r}].path`),!Array.isArray(s.panels)||s.panels.length!==t)throw new Error(`scenes[${n}].files[${r}].panels must match panel count.`);for(let[a,c]of s.panels.entries()){if(!P(c))throw new Error(`scenes[${n}].files[${r}].panels[${a}] must be an object.`);for(let i of["id","label","content"])$(c[i],`scenes[${n}].files[${r}].panels[${a}].${i}`);if(c.path!==void 0&&$(c.path,`scenes[${n}].files[${r}].panels[${a}].path`),typeof c.exists!="boolean")throw new Error(`scenes[${n}].files[${r}].panels[${a}].exists must be boolean.`)}}}function vt(e,t,n,r){if(!Array.isArray(e)||e.length===0)throw new Error(`scenes[${n}].steps must be non-empty.`);for(let[s,a]of e.entries()){if(!P(a))throw new Error(`scenes[${n}].steps[${s}] must be an object.`);for(let c of["id","title","body","file","side"])$(a[c],`scenes[${n}].steps[${s}].${c}`);if(ee(a.pairIndex,`scenes[${n}].steps[${s}].pairIndex`),Number(a.pairIndex)>=t-1)throw new Error(`scenes[${n}].steps[${s}].pairIndex is outside the panels.`);if(r){if(de(a.introducedHunks,`scenes[${n}].steps[${s}].introducedHunks`),a.introducedHunks.length===0)throw new Error(`scenes[${n}].steps[${s}].introducedHunks must be non-empty.`);if(Number(a.pairIndex)!==s)throw new Error(`scenes[${n}].steps[${s}].pairIndex must match its explanation stage.`)}if(a.side!=="left"&&a.side!=="right")throw new Error(`scenes[${n}].steps[${s}].side must be left or right.`);a.startLine!==void 0&&Ce(a.startLine,`scenes[${n}].steps[${s}].startLine`),a.endLine!==void 0&&Ce(a.endLine,`scenes[${n}].steps[${s}].endLine`)}}function kn(e,t){if(!P(e))throw new Error(`files[${t}] must be an object.`);if(e.kind==="text-diff"){We(e,t);return}if(e.kind!=="omitted")throw new Error(`files[${t}].kind must be text-diff or omitted.`);for(let n of["id","title","path","changeKind","reason"])$(e[n],`files[${t}].${n}`);e.previousPath!==void 0&&$(e.previousPath,`files[${t}].previousPath`),ee(e.additions,`files[${t}].additions`),ee(e.deletions,`files[${t}].deletions`)}function $n(e){let t=new Map;for(let n of e){if(n.kind==="text-diff"){t.has(n.path)||t.set(n.path,n);continue}if(n.kind==="walkthrough")for(let r of n.steps)t.has(r.diff.path)||t.set(r.diff.path,r.diff)}return[...t.values()].sort((n,r)=>n.path.localeCompare(r.path))}function Be(e,t){if(!P(e))throw new Error(`${t} must be an object.`);for(let n of["id","path","revision","excerpt"])$(e[n],`${t}.${n}`);if(e.revision!=="base"&&e.revision!=="head")throw new Error(`${t}.revision must be base or head.`);if(Ce(e.startLine,`${t}.startLine`),Ce(e.endLine,`${t}.endLine`),Number(e.endLine)<Number(e.startLine))throw new Error(`${t}.endLine must not precede startLine.`)}function Nn(e,t){$(e.summary,`${t}.summary`),de(e.bullets,`${t}.bullets`),de(e.tags,`${t}.tags`),$(e.takeaway,`${t}.takeaway`)}function P(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function $(e,t){if(typeof e!="string")throw new Error(`${t} must be a string.`)}function de(e,t){if(!Array.isArray(e)||e.some(n=>typeof n!="string"))throw new Error(`${t} must be an array of strings.`)}function ee(e,t){if(!Number.isInteger(e)||Number(e)<0)throw new Error(`${t} must be a non-negative integer.`)}function Ce(e,t){if(!Number.isInteger(e)||Number(e)<1)throw new Error(`${t} must be a positive integer.`)}function St(e,t,n){let r=e.findIndex(i=>i.id===t),s=r>=0?r:0,a=e[s];if(!a||a.kind!=="walkthrough"&&a.kind!=="stacked-diff"&&a.kind!=="deconstructed-diff"||!n)return{sceneIndex:s,stepIndex:0};let c=a.steps.findIndex(i=>i.id===n);return{sceneIndex:s,stepIndex:c>=0?c:0}}function Et(e,t,n){let r=e[t.sceneIndex];if(!r)return null;if(n>0)return(r.kind==="walkthrough"||r.kind==="stacked-diff"||r.kind==="deconstructed-diff")&&t.stepIndex<r.steps.length-1?{sceneIndex:t.sceneIndex,stepIndex:t.stepIndex+1}:t.sceneIndex<e.length-1?{sceneIndex:t.sceneIndex+1,stepIndex:0}:null;if((r.kind==="walkthrough"||r.kind==="stacked-diff"||r.kind==="deconstructed-diff")&&t.stepIndex>0)return{sceneIndex:t.sceneIndex,stepIndex:t.stepIndex-1};if(t.sceneIndex===0)return null;let s=e[t.sceneIndex-1];return{sceneIndex:t.sceneIndex-1,stepIndex:s.kind==="walkthrough"||s.kind==="stacked-diff"||s.kind==="deconstructed-diff"?s.steps.length-1:0}}function Ct(e,t,n){if(!t)return null;let r=e.map((i,u)=>({file:i,fileIndex:u})).filter(({file:i})=>i.kind==="text-diff"),s=r.findIndex(({file:i})=>i.path===t),a=s+n,c=s>=0?r[a]:null;return c?{fileIndex:c.fileIndex,path:c.file.path}:null}function Lt(e,t,n){let r=e[t.sceneIndex],s=Tt(r,t.sceneIndex,t.stepIndex,n);if(s)return s;for(let a=0;a<e.length;a+=1){if(a===t.sceneIndex)continue;let c=Tt(e[a],a,0,n);if(c)return c}return null}function Tt(e,t,n,r){if(!e||e.kind!=="stacked-diff"&&e.kind!=="deconstructed-diff"||!e.files.some(c=>c.path===r))return null;let a=e.steps[n]?.file===r?n:e.steps.findIndex(c=>c.file===r);return{sceneIndex:t,stepIndex:a>=0?a:Math.max(n,0)}}function $t(e,t,n="all",r=300){let s=t.trim().toLocaleLowerCase();if(!s||r<=0)return[];let a=[];if(n!=="code"){let c=new Map;e.chapters.forEach(i=>i.sceneIds.forEach(u=>c.set(u,i.title))),e.scenes.forEach((i,u)=>{let d=[c.get(i.id),i.title,i.summary,...i.bullets,...i.tags,i.takeaway],g=kt(d,s);g&&a.push({kind:"narrative",sceneIndex:u,label:i.title,preview:g}),Rn(i)&&i.steps.forEach((h,E)=>{let L=kt([h.title,h.body,"connection"in h?h.connection?.label:void 0],s);L&&a.push({kind:"narrative",sceneIndex:u,stepIndex:E,label:`${i.title} \xB7 ${h.title}`,preview:L})})})}if(n!=="narrative"&&a.length<r)for(let c=0;c<e.files.length;c+=1){let i=e.files[c];if(i.kind==="text-diff"){for(let[u,d]of[[0,i.leftContent],[1,i.rightContent]])for(let g of An(d,s))if(a.push({kind:"code",fileIndex:c,sideIndex:u,label:`${i.path} \xB7 ${u===0?"base":"head"}`,...g}),a.length>=r)return a}}return a.slice(0,r)}function kt(e,t){return e.find(n=>n?.toLocaleLowerCase().includes(t))}function An(e,t){let n=[];return e.replace(/\r\n/g,`
|
|
149
149
|
`).split(`
|
|
150
|
-
`).forEach((r,s)=>{let a=r.toLocaleLowerCase(),l=0;for(;l<=a.length-t.length;){let i=a.indexOf(t,l);if(i<0)break;n.push({lineNumber:s+1,startColumn:i+1,endColumn:i+t.length+1,preview:r}),l=i+Math.max(t.length,1)}}),n}function An(e){return e.kind==="walkthrough"||e.kind==="stacked-diff"||e.kind==="deconstructed-diff"}function $t(e,t){let n=e?.blocks[0],r=t==="left"?e?.leftLines:e?.rightLines;if(!n||!r?.length)return;let s=t==="left"?n.leftStart:n.rightStart,a=t==="left"?n.leftEnd:n.rightEnd,l=r.slice(s,a),i=l[0]?.lineNumber??r[Math.min(s,r.length-1)]?.lineNumber;if(Number.isInteger(i))return{startLine:i,endLine:l.at(-1)?.lineNumber??i}}function At(e,t,n,r){let s=[];return e.scenes.forEach((a,l)=>{a.kind==="walkthrough"&&a.steps.forEach((i,u)=>{i.diff.path===t&&s.push({side:i.focus.revision==="base"?"left":"right",startLine:i.focus.startLine,endLine:i.focus.endLine,label:`${a.title} \xB7 ${i.title}: ${i.body}`,active:l===n&&u===r,jumpTarget:{sceneIndex:l,stepIndex:u}})})}),s}function Rt(e,t,n,r,s){let a=[];return e.scenes.forEach((l,i)=>{l.kind==="stacked-diff"&&l.steps.forEach((u,d)=>{if(u.file!==t)return;let g=u.startLine===void 0?s?.(u.pairIndex,u.side):{startLine:u.startLine,endLine:u.endLine??u.startLine};if(!g)return;let h=u.pairIndex+(u.side==="right"?1:0);a.push({pairIndex:u.pairIndex,panelIndex:h,side:u.side,startLine:g.startLine,endLine:g.endLine,label:`${l.title} \xB7 ${u.title}: ${u.body}`,active:i===n&&d===r,jumpTarget:{sceneIndex:i,stepIndex:d}})})}),a}(function(){let t="bygone.tourSidebarWidth",s="bygone.tourNarrativeHeight",i={mode:"empty",left:null,right:null,comparisonId:0,tour:null,activeSceneIndex:-1,activeStepIndex:0,activeTourFilePath:null,tourFocusFilePath:null,tourSidebarWidth:I(),tourSidebarHidden:!1,tourNarrativeHeight:_()};window.__BYGONE_HOST__={environment:"web",editorWorkerUrl:"/media/editor.worker.js",postMessage(o){d(o)}},window.addEventListener("DOMContentLoaded",()=>{g(),j("Browser host ready.")});function u(o){window.dispatchEvent(new window.CustomEvent("bygone:host-message",{detail:o}))}async function d(o){if(!(!o||typeof o!="object")){if(o.type==="ready"){let c=new URLSearchParams(window.location.search),m=c.get("manifest");m?fe(m):c.get("demo")==="1"&&Xe();return}if(o.type==="navigateFile"&&i.mode==="tour"){Dt(o.direction==="previous"?-1:1);return}if(o.type==="navigateTourStep"&&i.mode==="tour"){let c=o.sceneIndex,m=o.stepIndex;Number.isInteger(c)&&Number.isInteger(m)&&oe(c,m);return}o.type==="recomputeDiff"&&i.mode==="diff"&&i.left&&i.right&&(i.left.content=o.leftContent,i.right.content=o.rightContent,u({type:"showDiff",file1:i.left.name,file2:i.right.name,comparisonId:`web-${i.comparisonId}`,leftContent:i.left.content,rightContent:i.right.content,diffModel:Q(i.left.content,i.right.content),history:null}))}}function g(){let o=document.getElementById("web-compare-test"),c=document.getElementById("web-open-diff"),m=document.getElementById("web-open-diff3"),f=document.getElementById("web-diff-input"),p=document.getElementById("web-diff3-input"),E=document.getElementById("tour-previous"),S=document.getElementById("tour-next"),$=document.getElementById("tour-return-focus"),R=document.getElementById("tour-search-input"),U=document.getElementById("tour-search-scope");C(),N(),o?.addEventListener("click",()=>{Xe()}),c?.addEventListener("click",()=>{f.value="",f.click()}),m?.addEventListener("click",()=>{p.value="",p.click()}),f?.addEventListener("change",async()=>{let y=Array.from(f.files||[]);if(y.length!==2){j("Select exactly 2 files for a diff.");return}await zt(y)}),p?.addEventListener("change",async()=>{let y=Array.from(p.files||[]);if(y.length<1){j("Select one or more files.");return}await qt(y)}),E?.addEventListener("click",()=>me(-1)),S?.addEventListener("click",()=>me(1)),$?.addEventListener("click",_t),R?.addEventListener("input",T),U?.addEventListener("change",T),document.getElementById("tour-search-results")?.addEventListener("click",y=>{let W=y.target instanceof Element?y.target.closest("[data-tour-search-result]"):null;W&&L(Number(W.getAttribute("data-tour-search-result")))}),window.addEventListener("keydown",y=>{if(i.mode==="tour"&&(y.metaKey||y.ctrlKey)&&y.shiftKey&&y.key.toLocaleLowerCase()==="f"){y.preventDefault(),y.stopImmediatePropagation(),i.tourSidebarHidden&&k(!1),R?.focus(),R?.select();return}i.mode!=="tour"||y.metaKey||y.ctrlKey||y.altKey||Wt(y.target)||(y.key==="PageUp"||y.key==="ArrowLeft"?(y.preventDefault(),me(-1)):(y.key==="PageDown"||y.key==="ArrowRight")&&(y.preventDefault(),me(1)))},!0)}let h=[];function T(){let o=document.getElementById("tour-search-input"),c=document.getElementById("tour-search-scope"),m=document.getElementById("tour-search-status"),f=document.getElementById("tour-search-results");if(!(!i.tour||!o||!c||!m||!f)){if(h=Nt(i.tour,o.value,c.value),!o.value.trim()){m.textContent="Cmd/Ctrl+Shift+F",f.replaceChildren();return}m.textContent=`${h.length} result${h.length===1?"":"s"}`,f.replaceChildren(...h.map((p,E)=>{let S=document.createElement("button");S.type="button",S.className="tour-search-result",S.setAttribute("role","option"),S.dataset.tourSearchResult=String(E),S.title=`Open ${p.kind==="code"?`${p.label}:${p.lineNumber}`:p.label}`;let $=document.createElement("span");$.className="tour-search-location",$.textContent=p.kind==="code"?`${p.label}:${p.lineNumber}`:p.label;let R=document.createElement("span");return R.className="tour-search-preview",R.textContent=p.preview.trim(),S.append($,R),S}))}}function L(o){let c=h[o];if(c){if(c.kind==="narrative"){oe(c.sceneIndex,c.stepIndex??0);return}je(c.fileIndex)&&window.requestAnimationFrame(()=>u({type:"revealSearchResult",sideIndex:c.sideIndex,lineNumber:c.lineNumber,startColumn:c.startColumn,endColumn:c.endColumn}))}}function C(){let o=document.getElementById("tour-shell"),c=document.getElementById("tour-sidebar-resizer"),m=document.getElementById("tour-sidebar-hide"),f=document.getElementById("tour-sidebar-show");!o||!c||!m||!f||(x(),m.addEventListener("click",()=>k(!0)),f.addEventListener("click",()=>k(!1)),c.addEventListener("pointerdown",p=>{p.preventDefault(),document.body.classList.add("is-resizing-tour-sidebar"),c.setPointerCapture?.(p.pointerId);let E=$=>b($.clientX),S=()=>{document.body.classList.remove("is-resizing-tour-sidebar"),window.removeEventListener("pointermove",E),window.removeEventListener("pointerup",S),window.removeEventListener("pointercancel",S),window.localStorage.setItem(t,String(i.tourSidebarWidth))};window.addEventListener("pointermove",E),window.addEventListener("pointerup",S),window.addEventListener("pointercancel",S)}),c.addEventListener("keydown",p=>{if(!["ArrowLeft","ArrowRight","Home","End"].includes(p.key))return;p.preventDefault();let E=i.tourSidebarWidth;p.key==="Home"?E=240:p.key==="End"?E=w():E+=p.key==="ArrowLeft"?-16:16,b(E),window.localStorage.setItem(t,String(i.tourSidebarWidth))}))}function I(){let o=Number.parseInt(window.localStorage.getItem(t)||"",10);return Number.isFinite(o)?Math.min(600,Math.max(240,o)):360}function w(){return Math.max(240,Math.min(600,Math.floor(window.innerWidth*.6)))}function b(o){i.tourSidebarWidth=Math.min(w(),Math.max(240,Math.round(o))),x(),window.dispatchEvent(new Event("resize"))}function x(){document.documentElement.style.setProperty("--tour-rail-width",`${i.tourSidebarWidth}px`);let o=document.getElementById("tour-sidebar-resizer");o?.setAttribute("aria-valuemax",String(w())),o?.setAttribute("aria-valuenow",String(i.tourSidebarWidth))}function k(o){i.tourSidebarHidden=o,document.body.classList.toggle("tour-sidebar-hidden",o);let c=document.getElementById("tour-sidebar-show");c&&(c.hidden=!o),window.dispatchEvent(new Event("resize"))}function N(){let o=document.getElementById("tour-narrative-resizer");o&&(B(),o.addEventListener("pointerdown",c=>{c.preventDefault(),document.body.classList.add("is-resizing-tour-narrative"),o.setPointerCapture?.(c.pointerId),window.dispatchEvent(new CustomEvent("bygone:workspace-resize-start"));let m=document.getElementById("tour-narrative")?.getBoundingClientRect().top||0,f=E=>O(E.clientY-m),p=()=>{document.body.classList.remove("is-resizing-tour-narrative"),window.removeEventListener("pointermove",f),window.removeEventListener("pointerup",p),window.removeEventListener("pointercancel",p),window.dispatchEvent(new CustomEvent("bygone:workspace-resize-end")),ie()};window.addEventListener("pointermove",f),window.addEventListener("pointerup",p),window.addEventListener("pointercancel",p)}),o.addEventListener("keydown",c=>{if(!["ArrowUp","ArrowDown","Home","End"].includes(c.key))return;c.preventDefault();let m=c.key==="Home"?180:c.key==="End"?M():i.tourNarrativeHeight+(c.key==="ArrowUp"?-16:16);O(m),ie()}),window.addEventListener("resize",()=>{i.tourNarrativeHeight=Math.min(M(),i.tourNarrativeHeight),B()}))}function _(){let o=Number.parseInt(window.localStorage.getItem(s)||"",10);if(Number.isFinite(o))return Math.max(180,o);let c=Number.parseInt(window.getComputedStyle(document.documentElement).getPropertyValue("--tour-narrative-height"),10);return Number.isFinite(c)?c:296}function M(){let o=document.getElementById("tour-narrative")?.getBoundingClientRect().top||0;return Math.max(180,window.innerHeight-o-180)}function O(o){i.tourNarrativeHeight=Math.min(M(),Math.max(180,Math.round(o))),B(),window.dispatchEvent(new Event("resize"))}function B(){document.documentElement.style.setProperty("--tour-narrative-height",`${i.tourNarrativeHeight}px`);let o=document.getElementById("tour-narrative-resizer");o?.setAttribute("aria-valuemax",String(M())),o?.setAttribute("aria-valuenow",String(i.tourNarrativeHeight))}function ie(){window.localStorage.setItem(s,String(i.tourNarrativeHeight))}async function fe(o){j("Loading change tour\u2026");try{let c=await fetch(o,{cache:"no-store"});if(!c.ok)throw new Error(`Manifest request failed (${c.status}).`);i.tour=It(await c.json()),i.mode="tour",document.body.classList.add("tour-mode"),Ft(),T();let m=new URLSearchParams(window.location.search),f=St(i.tour.scenes,m.get("scene"),m.get("step"));oe(f.sceneIndex,f.stepIndex),j("")}catch(c){j(`Could not load change tour: ${c instanceof Error?c.message:String(c)}`)}}function Ft(){let o=i.tour;if(!o)return;let c=document.getElementById("tour-shell"),m=document.getElementById("tour-title"),f=document.getElementById("tour-source"),p=document.getElementById("tour-range"),E=document.getElementById("tour-stats"),S=document.getElementById("tour-scenes"),$=document.getElementById("tour-scene-count"),R=document.getElementById("tour-files"),U=document.getElementById("tour-file-count"),y=document.getElementById("tour-commits"),W=document.getElementById("tour-commits-summary");if(!c||!m||!f||!p||!E||!S||!$||!R||!U||!y||!W)throw new Error("Presenter UI is incomplete.");c.hidden=!1,m.textContent=o.title,o.sourceUrl?(f.href=o.sourceUrl,f.hidden=!1):f.hidden=!0;let K=be(o.range.baseRef),F=be(o.range.headRef),z=o.range.headOid.slice(0,7);p.textContent=`${K} \u2192 ${F}${F===z?"":` \xB7 ${z}`}`,E.textContent=`${ce(o.summary.changedFiles,"file")} \xB7 +${o.summary.additions} \u2212${o.summary.deletions} \xB7 ${ce(o.summary.commitCount,"commit")}`,$.textContent=String(o.scenes.length),U.textContent=String(o.files.length),W.textContent=ce(o.summary.commitCount,"commit"),S.replaceChildren();let we=new Map(o.scenes.map(v=>[v.id,v]));for(let v of o.chapters){let G=document.createElement("h2");G.className="tour-chapter-title",G.textContent=v.title,S.append(G);for(let D of v.sceneIds){let P=we.get(D);if(!P)continue;let te=o.scenes.indexOf(P),q=document.createElement("button");q.type="button",q.className="tour-scene",q.dataset.sceneId=P.id,q.title=`Open scene: ${P.kind==="text-diff"?P.path:P.title}`,q.addEventListener("click",()=>oe(te));let Z=document.createElement("span");Z.className="tour-scene-number",Z.textContent=String(te+1).padStart(2,"0");let $e=document.createElement("span");$e.className="tour-scene-copy";for(let[jt,Kt]of[["tour-scene-title",P.title],["tour-scene-path",P.kind==="text-diff"?P.path:P.kind==="deconstructed-diff"?ce(P.steps.length,"explanation stage"):ae(P)?ce(P.steps.length,"code step"):"Discussion"],["tour-scene-note",P.takeaway]]){let Ae=document.createElement("span");Ae.className=jt,Ae.textContent=Kt,$e.append(Ae)}q.append(Z,$e),S.append(q)}}R.replaceChildren(...o.files.map((v,G)=>{let D=document.createElement("button");D.type="button",D.className=`tour-file${v.kind==="omitted"?" is-omitted":""}`,D.dataset.filePath=v.path,D.disabled=v.kind==="omitted",D.title=v.kind==="omitted"?`${v.path}: ${v.reason}`:`Open file: ${v.path}`,v.kind==="text-diff"&&D.addEventListener("click",()=>Ke(G));let P=document.createElement("span");P.className="tour-file-marker",P.textContent=v.kind==="omitted"?"\xD7":Pt(v.changeKind);let te=document.createElement("span");te.className="tour-file-copy";let q=document.createElement("span");q.className="tour-file-path",q.textContent=v.path;let Z=document.createElement("span");return Z.className="tour-file-meta",Z.textContent=v.kind==="omitted"?`Not rendered \xB7 ${v.reason}`:`${Ot(v.changeKind)} \xB7 +${v.additions} \u2212${v.deletions}`,te.append(q,Z),D.append(P,te),D})),y.replaceChildren(...o.commits.map(v=>{let G=document.createElement("li"),D=document.createElement("span");return D.className="tour-commit-oid",D.textContent=v.shortOid,G.append(D,document.createTextNode(v.summary)),G}))}function oe(o,c=0){let m=i.tour;if(!m||o<0||o>=m.scenes.length)return;let f=m.scenes[o];i.activeSceneIndex=o,i.activeStepIndex=ae(f)?Math.min(Math.max(c,0),Math.max(f.steps.length-1,0)):0,i.tourFocusFilePath=f.kind==="text-diff"?f.path:f.kind==="walkthrough"?f.steps[i.activeStepIndex]?.diff.path??null:pe(f)?f.steps[i.activeStepIndex]?.file??null:null;let p=Bt(m,o);document.querySelectorAll(".tour-scene").forEach(S=>{S.classList.toggle("is-active",S.dataset.sceneId===f.id)}),document.querySelector(`.tour-scene[data-scene-id="${f.id}"]`)?.scrollIntoView({block:"nearest"}),Gt(f,p);let E=new URLSearchParams(window.location.search);if(E.set("scene",f.id),ae(f)?E.set("step",f.steps[i.activeStepIndex].id):E.delete("step"),window.history.replaceState(null,"",`${window.location.pathname}?${E.toString()}`),f.kind==="discussion"){document.body.classList.add("tour-discussion"),Ne();return}if(document.body.classList.remove("tour-discussion"),f.kind==="walkthrough"){Ge(f);return}if(pe(f)){ze(f);return}ge(f,he(f.path))}function he(o){let c=i.tour;return!c||!o?[]:At(c,o,i.activeSceneIndex,i.activeStepIndex)}function Mt(o,c){let m=i.tour;return!m||!o?[]:Rt(m,o,i.activeSceneIndex,i.activeStepIndex,(f,p)=>$t(c?.[f]?.diffModel,p))}function Le(o){return`file::${o}`}function ge(o,c=[],m=Le(o.path)){if(!i.tour)return;i.activeTourFilePath=o.path,Ne();let p=Q(o.leftContent,o.rightContent),E=We(o,o.leftLabel,"base"),S=We(o,o.rightLabel,"head"),$=c.find(R=>R.active);u({type:"showDiff",file1:E,file2:S,comparisonId:`tour-${m}`,leftContent:o.leftContent,rightContent:o.rightContent,sourceInfo:{leftPath:o.path,rightPath:o.path},diffModel:p,history:null,fileNavigation:{canGoPrevious:!!se(-1),canGoNext:!!se(1)},editableSides:{left:!1,right:!1},comparisonSummary:`${o.path} \xB7 ${o.takeaway}`,initialChangeIndex:$?Ve(p,$.side,$.startLine):o.focusChangeIndex,tourAnnotations:c})}function We(o,c,m){let f=c.startsWith(o.path)?c.slice(o.path.length).trim():c.trim();return f?`${m} ${f}`:m}function Ge(o){let c=o.steps[i.activeStepIndex];c&&ge(c.diff,he(c.diff.path),Le(c.diff.path))}function ze(o){let c=o.steps[i.activeStepIndex];c&&qe(o,c.file,c)}function qe(o,c,m){let f=o.files.find(F=>F.path===c);if(!m||!f)return;i.activeTourFilePath=f.path,Ne();let p=f.panels.map((F,z)=>({id:`${o.id}-${f.path}-${F.id}`,label:F.label,path:F.path||f.path,content:F.content,savedContent:F.content,dirty:!1,editable:!1,stackId:Ht(o)[z].id})),E=p.slice(0,-1).map((F,z)=>({leftIndex:z,rightIndex:z+1,diffModel:Q(F.content,p[z+1].content)})),S=o.kind==="stacked-diff"?Mt(f.path,E):[],$=S.find(F=>F.active),R=$?.pairIndex??m.pairIndex,U=$?.side??m.side,y=$?.startLine??m.startLine,W=E[R]?.diffModel,K=W&&y?Ve(W,U,y):0;u({type:"showMultiDiff",panels:p,pairs:E,activePanelId:p[R+(U==="right"?1:0)]?.id,activePairIndex:R,initialChangeIndex:K,revealFirstChangeInEachPanel:o.kind==="deconstructed-diff",history:null,fileNavigation:{canGoPrevious:!!se(-1),canGoNext:!!se(1)},mutationEnabled:!1,comparisonSummary:o.kind==="deconstructed-diff"?`${o.stageLabel} \xB7 ${f.path} \xB7 ${be(o.realRange.baseRef)} \u2192 ${be(o.realRange.targetRef)}`:`${f.path} \xB7 ${o.takeaway}`,tourAnnotations:S})}function ke(o){let c=i.tour;return!c||o!==-1&&o!==1?null:Tt(c.scenes,{sceneIndex:i.activeSceneIndex,stepIndex:i.activeStepIndex},o)}function me(o){let c=ke(o);return c?(oe(c.sceneIndex,c.stepIndex),!0):!1}function se(o){let c=i.tour;return!c||o!==-1&&o!==1?null:Ct(c.files,i.activeTourFilePath,o)}function Dt(o){let c=se(o);return c?Ke(c.fileIndex):!1}function je(o){let c=i.tour?.files[o];return!c||c.kind!=="text-diff"?!1:(ge(c,he(c.path),Le(c.path)),!0)}function Ke(o){let c=i.tour?.files[o];if(c?.kind==="text-diff"&&i.tour){let m=Lt(i.tour.scenes,{sceneIndex:i.activeSceneIndex,stepIndex:i.activeStepIndex},c.path);if(m){let f=i.tour.scenes[m.sceneIndex],p=pe(f)?f.steps[m.stepIndex]:null;if(p)return qe(f,c.path,p),!0}}return je(o)}function _t(){let o=i.tour?.scenes[i.activeSceneIndex];if(!o||!i.tourFocusFilePath)return!1;if(o.kind==="walkthrough")Ge(o);else if(pe(o))ze(o);else if(o.kind==="text-diff")ge(o,he(o.path));else return!1;return!0}function Ne(){document.querySelectorAll(".tour-file").forEach(c=>{c.classList.toggle("is-active",c.dataset.filePath===i.activeTourFilePath),c.classList.toggle("is-tour-focus",c.dataset.filePath===i.tourFocusFilePath)}),document.querySelector(".tour-file.is-active")?.scrollIntoView({block:"nearest"});let o=document.getElementById("tour-return-focus");o&&(o.hidden=!i.tourFocusFilePath||i.activeTourFilePath===i.tourFocusFilePath)}function ae(o){return o.kind==="walkthrough"||o.kind==="stacked-diff"||o.kind==="deconstructed-diff"}function pe(o){return o.kind==="stacked-diff"||o.kind==="deconstructed-diff"}function Ht(o){return o.kind==="deconstructed-diff"?o.panels:o.stack}function Pt(o){return{added:"+",deleted:"\u2212",renamed:"\u2192",modified:"\u2022"}[o]||"\u2022"}function Ot(o){return`${o.charAt(0).toUpperCase()}${o.slice(1)}`}function Bt(o,c){let m=o.scenes[c],f=o.chapters.findIndex($=>$.sceneIds.includes(m.id)),p=f>=0?o.chapters[f]:null,E=p?p.sceneIds.indexOf(m.id)+1:c+1,S=p?p.sceneIds.length:o.scenes.length;return{chapter:p,chapterIndex:f,chapterNumber:f>=0?f+1:c+1,sceneInChapter:E,scenesInChapter:S}}function Ut(o,c,m){let f=[`Ch ${o.chapterNumber}`,`Scene ${o.sceneInChapter}/${o.scenesInChapter}`];return ae(c)&&f.push(`Step ${m+1}/${c.steps.length}`),f.join(" \xB7 ")}function Ve(o,c,m){let p=(c==="left"?o.leftLines:o.rightLines).findIndex(y=>y.lineNumber===m);if(p<0)return 0;let E=c==="left"?"leftStart":"rightStart",S=c==="left"?"leftEnd":"rightEnd",$=o.blocks.findIndex(y=>p>=y[E]&&p<y[S]);if($>=0)return $;let R=0,U=Number.POSITIVE_INFINITY;return o.blocks.forEach((y,W)=>{let K=Math.min(Math.abs(p-y[E]),Math.abs(p-y[S]));K<U&&(R=W,U=K)}),R}function be(o){return/^[0-9a-f]{40}$/i.test(o)?o.slice(0,7):o}function ce(o,c){return`${o} ${o===1?c:`${c}s`}`}function Wt(o){return o instanceof Element&&!!o.closest('a, button, input, select, summary, textarea, [contenteditable="true"], [role="textbox"], .monaco-editor')}function Gt(o,c){let m=document.getElementById("tour-narrative"),f=document.getElementById("tour-breadcrumb"),p=document.getElementById("tour-narrative-chapter"),E=document.getElementById("tour-narrative-title"),S=document.getElementById("tour-narrative-summary"),$=document.getElementById("tour-narrative-bullets"),R=document.getElementById("tour-narrative-tags"),U=document.getElementById("tour-narrative-takeaway"),y=document.getElementById("tour-step"),W=document.getElementById("tour-step-title"),K=document.getElementById("tour-step-body"),F=document.getElementById("tour-connection"),z=document.getElementById("tour-previous"),we=document.getElementById("tour-next");if(!m||!f||!p||!E||!S||!$||!R||!U||!y||!W||!K||!F||!z||!we)throw new Error("Tour narrative UI is incomplete.");m.hidden=!1,f.textContent=Ut(c,o,i.activeStepIndex),p.textContent=o.kind==="deconstructed-diff"?`${c.chapter?.title||"Change tour"} \xB7 ${o.stageLabel}`:c.chapter?.title||"Change tour",E.textContent=o.title,S.textContent=o.summary,$.replaceChildren(...o.bullets.map(G=>{let D=document.createElement("li");return D.textContent=G,D})),R.replaceChildren(...o.tags.map(G=>{let D=document.createElement("span");return D.textContent=G,D})),U.textContent=o.takeaway;let v=ae(o)?o.steps[i.activeStepIndex]:null;y.hidden=!v,v?(W.textContent=o.kind==="deconstructed-diff"?`Stage ${i.activeStepIndex+1}: ${v.title}`:v.title,K.textContent=v.body,"connection"in v&&v.connection?(F.hidden=!1,F.textContent=`${v.connection.from.path} \u2192 ${v.connection.to.path} \xB7 ${v.connection.label}`):(F.hidden=!0,F.textContent="")):(F.hidden=!0,F.textContent=""),z.disabled=!ke(-1),we.disabled=!ke(1)}function Xe(){let o=yt();i.mode="diff",i.comparisonId+=1,i.left={name:o.leftFileName,content:o.leftContent},i.right={name:o.rightFileName,content:o.rightContent},j("Loaded sample diff."),u({type:"showDiff",file1:i.left.name,file2:i.right.name,comparisonId:`web-${i.comparisonId}`,leftContent:i.left.content,rightContent:i.right.content,diffModel:Q(i.left.content,i.right.content),history:null})}async function zt(o){let[c,m]=o,[f,p]=await Promise.all([c.text(),m.text()]);i.mode="diff",i.comparisonId+=1,i.left={name:c.name,content:f},i.right={name:m.name,content:p},j(`Loaded ${c.name} and ${m.name}.`),u({type:"showDiff",file1:c.name,file2:m.name,comparisonId:`web-${i.comparisonId}`,leftContent:f,rightContent:p,diffModel:Q(f,p),history:null})}async function qt(o){let c=await Promise.all(o.map(async(m,f)=>{let p=await m.text();return{id:`web-panel-${f}`,label:m.name,content:p,savedContent:p,dirty:!1,editable:!0}}));i.mode="multi-diff",j(`Loaded ${c.length}-panel diff for ${c.map(m=>m.label).join(", ")}.`),u({type:"showMultiDiff",panels:c,pairs:c.slice(0,-1).map((m,f)=>({leftIndex:f,rightIndex:f+1,diffModel:Q(m.content,c[f+1].content)}))})}function j(o){let c=document.getElementById("web-status");c&&(c.textContent=o)}})();})();
|
|
150
|
+
`).forEach((r,s)=>{let a=r.toLocaleLowerCase(),c=0;for(;c<=a.length-t.length;){let i=a.indexOf(t,c);if(i<0)break;n.push({lineNumber:s+1,startColumn:i+1,endColumn:i+t.length+1,preview:r}),c=i+Math.max(t.length,1)}}),n}function Rn(e){return e.kind==="walkthrough"||e.kind==="stacked-diff"||e.kind==="deconstructed-diff"}function Nt(e,t){let n=e?.blocks[0],r=t==="left"?e?.leftLines:e?.rightLines;if(!n||!r?.length)return;let s=t==="left"?n.leftStart:n.rightStart,a=t==="left"?n.leftEnd:n.rightEnd,c=r.slice(s,a),i=c[0]?.lineNumber??r[Math.min(s,r.length-1)]?.lineNumber;if(Number.isInteger(i))return{startLine:i,endLine:c.at(-1)?.lineNumber??i}}function At(e,t,n,r){let s=[];return e.scenes.forEach((a,c)=>{a.kind==="walkthrough"&&a.steps.forEach((i,u)=>{i.diff.path===t&&s.push({side:i.focus.revision==="base"?"left":"right",startLine:i.focus.startLine,endLine:i.focus.endLine,label:`${a.title} \xB7 ${i.title}: ${i.body}`,active:c===n&&u===r,jumpTarget:{sceneIndex:c,stepIndex:u}})})}),s}function Rt(e,t,n,r,s){let a=[];return e.scenes.forEach((c,i)=>{c.kind==="stacked-diff"&&c.steps.forEach((u,d)=>{if(u.file!==t)return;let g=u.startLine===void 0?s?.(u.pairIndex,u.side):{startLine:u.startLine,endLine:u.endLine??u.startLine};if(!g)return;let h=u.pairIndex+(u.side==="right"?1:0);a.push({pairIndex:u.pairIndex,panelIndex:h,side:u.side,startLine:g.startLine,endLine:g.endLine,label:`${c.title} \xB7 ${u.title}: ${u.body}`,active:i===n&&d===r,jumpTarget:{sceneIndex:i,stepIndex:d}})})}),a}function Mn(e,t=120){return e.length<=t?e:`${e.slice(0,t-1)}\u2026`}function Mt(e,t="Bygone"){let n=e?.windowTitle?.trim()||e?.title?.trim();return n?Mn(n):`${t} Tour`}(function(){let t="bygone.tourSidebarWidth",s="bygone.tourNarrativeHeight",i={mode:"empty",left:null,right:null,comparisonId:0,tour:null,activeSceneIndex:-1,activeStepIndex:0,activeTourFilePath:null,tourFocusFilePath:null,tourSidebarWidth:I(),tourSidebarHidden:!1,tourNarrativeHeight:_()};window.__BYGONE_HOST__={environment:"web",editorWorkerUrl:"/media/editor.worker.js",postMessage(o){d(o)}},window.addEventListener("DOMContentLoaded",()=>{g(),q("Browser host ready.")});function u(o){window.dispatchEvent(new window.CustomEvent("bygone:host-message",{detail:o}))}async function d(o){if(!(!o||typeof o!="object")){if(o.type==="ready"){let l=new URLSearchParams(window.location.search),m=l.get("manifest");m?fe(m):l.get("demo")==="1"&&Xe();return}if(o.type==="navigateFile"&&i.mode==="tour"){_t(o.direction==="previous"?-1:1);return}if(o.type==="navigateTourStep"&&i.mode==="tour"){let l=o.sceneIndex,m=o.stepIndex;Number.isInteger(l)&&Number.isInteger(m)&&oe(l,m);return}o.type==="recomputeDiff"&&i.mode==="diff"&&i.left&&i.right&&(i.left.content=o.leftContent,i.right.content=o.rightContent,u({type:"showDiff",file1:i.left.name,file2:i.right.name,comparisonId:`web-${i.comparisonId}`,leftContent:i.left.content,rightContent:i.right.content,diffModel:Q(i.left.content,i.right.content),history:null}))}}function g(){let o=document.getElementById("web-compare-test"),l=document.getElementById("web-open-diff"),m=document.getElementById("web-open-diff3"),f=document.getElementById("web-diff-input"),p=document.getElementById("web-diff3-input"),T=document.getElementById("tour-previous"),S=document.getElementById("tour-next"),A=document.getElementById("tour-return-focus"),R=document.getElementById("tour-search-input"),W=document.getElementById("tour-search-scope");C(),N(),o?.addEventListener("click",()=>{Xe()}),l?.addEventListener("click",()=>{f.value="",f.click()}),m?.addEventListener("click",()=>{p.value="",p.click()}),f?.addEventListener("change",async()=>{let y=Array.from(f.files||[]);if(y.length!==2){q("Select exactly 2 files for a diff.");return}await jt(y)}),p?.addEventListener("change",async()=>{let y=Array.from(p.files||[]);if(y.length<1){q("Select one or more files.");return}await qt(y)}),T?.addEventListener("click",()=>me(-1)),S?.addEventListener("click",()=>me(1)),A?.addEventListener("click",Pt),R?.addEventListener("input",E),W?.addEventListener("change",E),document.getElementById("tour-search-results")?.addEventListener("click",y=>{let U=y.target instanceof Element?y.target.closest("[data-tour-search-result]"):null;U&&L(Number(U.getAttribute("data-tour-search-result")))}),window.addEventListener("keydown",y=>{if(i.mode==="tour"&&(y.metaKey||y.ctrlKey)&&y.shiftKey&&y.key.toLocaleLowerCase()==="f"){y.preventDefault(),y.stopImmediatePropagation(),i.tourSidebarHidden&&k(!1),R?.focus(),R?.select();return}i.mode!=="tour"||y.metaKey||y.ctrlKey||y.altKey||Gt(y.target)||(y.key==="PageUp"||y.key==="ArrowLeft"?(y.preventDefault(),me(-1)):(y.key==="PageDown"||y.key==="ArrowRight")&&(y.preventDefault(),me(1)))},!0)}let h=[];function E(){let o=document.getElementById("tour-search-input"),l=document.getElementById("tour-search-scope"),m=document.getElementById("tour-search-status"),f=document.getElementById("tour-search-results");if(!(!i.tour||!o||!l||!m||!f)){if(h=$t(i.tour,o.value,l.value),!o.value.trim()){m.textContent="Cmd/Ctrl+Shift+F",f.replaceChildren();return}m.textContent=`${h.length} result${h.length===1?"":"s"}`,f.replaceChildren(...h.map((p,T)=>{let S=document.createElement("button");S.type="button",S.className="tour-search-result",S.setAttribute("role","option"),S.dataset.tourSearchResult=String(T),S.title=`Open ${p.kind==="code"?`${p.label}:${p.lineNumber}`:p.label}`;let A=document.createElement("span");A.className="tour-search-location",A.textContent=p.kind==="code"?`${p.label}:${p.lineNumber}`:p.label;let R=document.createElement("span");return R.className="tour-search-preview",R.textContent=p.preview.trim(),S.append(A,R),S}))}}function L(o){let l=h[o];if(l){if(l.kind==="narrative"){oe(l.sceneIndex,l.stepIndex??0);return}qe(l.fileIndex)&&window.requestAnimationFrame(()=>u({type:"revealSearchResult",sideIndex:l.sideIndex,lineNumber:l.lineNumber,startColumn:l.startColumn,endColumn:l.endColumn}))}}function C(){let o=document.getElementById("tour-shell"),l=document.getElementById("tour-sidebar-resizer"),m=document.getElementById("tour-sidebar-hide"),f=document.getElementById("tour-sidebar-show");!o||!l||!m||!f||(x(),m.addEventListener("click",()=>k(!0)),f.addEventListener("click",()=>k(!1)),l.addEventListener("pointerdown",p=>{p.preventDefault(),document.body.classList.add("is-resizing-tour-sidebar"),l.setPointerCapture?.(p.pointerId);let T=A=>b(A.clientX),S=()=>{document.body.classList.remove("is-resizing-tour-sidebar"),window.removeEventListener("pointermove",T),window.removeEventListener("pointerup",S),window.removeEventListener("pointercancel",S),window.localStorage.setItem(t,String(i.tourSidebarWidth))};window.addEventListener("pointermove",T),window.addEventListener("pointerup",S),window.addEventListener("pointercancel",S)}),l.addEventListener("keydown",p=>{if(!["ArrowLeft","ArrowRight","Home","End"].includes(p.key))return;p.preventDefault();let T=i.tourSidebarWidth;p.key==="Home"?T=240:p.key==="End"?T=w():T+=p.key==="ArrowLeft"?-16:16,b(T),window.localStorage.setItem(t,String(i.tourSidebarWidth))}))}function I(){let o=Number.parseInt(window.localStorage.getItem(t)||"",10);return Number.isFinite(o)?Math.min(600,Math.max(240,o)):360}function w(){return Math.max(240,Math.min(600,Math.floor(window.innerWidth*.6)))}function b(o){i.tourSidebarWidth=Math.min(w(),Math.max(240,Math.round(o))),x(),window.dispatchEvent(new Event("resize"))}function x(){document.documentElement.style.setProperty("--tour-rail-width",`${i.tourSidebarWidth}px`);let o=document.getElementById("tour-sidebar-resizer");o?.setAttribute("aria-valuemax",String(w())),o?.setAttribute("aria-valuenow",String(i.tourSidebarWidth))}function k(o){i.tourSidebarHidden=o,document.body.classList.toggle("tour-sidebar-hidden",o);let l=document.getElementById("tour-sidebar-show");l&&(l.hidden=!o),window.dispatchEvent(new Event("resize"))}function N(){let o=document.getElementById("tour-narrative-resizer");o&&(B(),o.addEventListener("pointerdown",l=>{l.preventDefault(),document.body.classList.add("is-resizing-tour-narrative"),o.setPointerCapture?.(l.pointerId),window.dispatchEvent(new CustomEvent("bygone:workspace-resize-start"));let m=document.getElementById("tour-narrative")?.getBoundingClientRect().top||0,f=T=>O(T.clientY-m),p=()=>{document.body.classList.remove("is-resizing-tour-narrative"),window.removeEventListener("pointermove",f),window.removeEventListener("pointerup",p),window.removeEventListener("pointercancel",p),window.dispatchEvent(new CustomEvent("bygone:workspace-resize-end")),ie()};window.addEventListener("pointermove",f),window.addEventListener("pointerup",p),window.addEventListener("pointercancel",p)}),o.addEventListener("keydown",l=>{if(!["ArrowUp","ArrowDown","Home","End"].includes(l.key))return;l.preventDefault();let m=l.key==="Home"?180:l.key==="End"?F():i.tourNarrativeHeight+(l.key==="ArrowUp"?-16:16);O(m),ie()}),window.addEventListener("resize",()=>{i.tourNarrativeHeight=Math.min(F(),i.tourNarrativeHeight),B()}))}function _(){let o=Number.parseInt(window.localStorage.getItem(s)||"",10);if(Number.isFinite(o))return Math.max(180,o);let l=Number.parseInt(window.getComputedStyle(document.documentElement).getPropertyValue("--tour-narrative-height"),10);return Number.isFinite(l)?l:296}function F(){let o=document.getElementById("tour-narrative")?.getBoundingClientRect().top||0;return Math.max(180,window.innerHeight-o-180)}function O(o){i.tourNarrativeHeight=Math.min(F(),Math.max(180,Math.round(o))),B(),window.dispatchEvent(new Event("resize"))}function B(){document.documentElement.style.setProperty("--tour-narrative-height",`${i.tourNarrativeHeight}px`);let o=document.getElementById("tour-narrative-resizer");o?.setAttribute("aria-valuemax",String(F())),o?.setAttribute("aria-valuenow",String(i.tourNarrativeHeight))}function ie(){window.localStorage.setItem(s,String(i.tourNarrativeHeight))}async function fe(o){q("Loading change tour\u2026");try{let l=await fetch(o,{cache:"no-store"});if(!l.ok)throw new Error(`Manifest request failed (${l.status}).`);i.tour=It(await l.json()),i.mode="tour",document.body.classList.add("tour-mode"),Ft(),E();let m=new URLSearchParams(window.location.search),f=St(i.tour.scenes,m.get("scene"),m.get("step"));oe(f.sceneIndex,f.stepIndex),q("")}catch(l){q(`Could not load change tour: ${l instanceof Error?l.message:String(l)}`)}}function Ft(){let o=i.tour;if(!o)return;let l=document.getElementById("tour-shell"),m=document.getElementById("tour-title"),f=document.getElementById("tour-source"),p=document.getElementById("tour-range"),T=document.getElementById("tour-stats"),S=document.getElementById("tour-scenes"),A=document.getElementById("tour-scene-count"),R=document.getElementById("tour-files"),W=document.getElementById("tour-file-count"),y=document.getElementById("tour-commits"),U=document.getElementById("tour-commits-summary");if(!l||!m||!f||!p||!T||!S||!A||!R||!W||!y||!U)throw new Error("Presenter UI is incomplete.");l.hidden=!1,m.textContent=o.title,document.title=Mt(o),o.sourceUrl?(f.href=o.sourceUrl,f.hidden=!1):f.hidden=!0;let K=be(o.range.baseRef),M=be(o.range.headRef),z=o.range.headOid.slice(0,7);p.textContent=`${K} \u2192 ${M}${M===z?"":` \xB7 ${z}`}`,T.textContent=`${le(o.summary.changedFiles,"file")} \xB7 +${o.summary.additions} \u2212${o.summary.deletions} \xB7 ${le(o.summary.commitCount,"commit")}`,A.textContent=String(o.scenes.length),W.textContent=String(o.files.length),U.textContent=le(o.summary.commitCount,"commit"),S.replaceChildren();let we=new Map(o.scenes.map(v=>[v.id,v]));for(let v of o.chapters){let G=document.createElement("h2");G.className="tour-chapter-title",G.textContent=v.title,S.append(G);for(let D of v.sceneIds){let H=we.get(D);if(!H)continue;let te=o.scenes.indexOf(H),j=document.createElement("button");j.type="button",j.className="tour-scene",j.dataset.sceneId=H.id,j.title=`Open scene: ${H.kind==="text-diff"?H.path:H.title}`,j.addEventListener("click",()=>oe(te));let Z=document.createElement("span");Z.className="tour-scene-number",Z.textContent=String(te+1).padStart(2,"0");let Ne=document.createElement("span");Ne.className="tour-scene-copy";for(let[Kt,Vt]of[["tour-scene-title",H.title],["tour-scene-path",H.kind==="text-diff"?H.path:H.kind==="deconstructed-diff"?le(H.steps.length,"explanation stage"):ae(H)?le(H.steps.length,"code step"):"Discussion"],["tour-scene-note",H.takeaway]]){let Ae=document.createElement("span");Ae.className=Kt,Ae.textContent=Vt,Ne.append(Ae)}j.append(Z,Ne),S.append(j)}}R.replaceChildren(...o.files.map((v,G)=>{let D=document.createElement("button");D.type="button",D.className=`tour-file${v.kind==="omitted"?" is-omitted":""}`,D.dataset.filePath=v.path,D.disabled=v.kind==="omitted",D.title=v.kind==="omitted"?`${v.path}: ${v.reason}`:`Open file: ${v.path}`,v.kind==="text-diff"&&D.addEventListener("click",()=>Ke(G));let H=document.createElement("span");H.className="tour-file-marker",H.textContent=v.kind==="omitted"?"\xD7":Ot(v.changeKind);let te=document.createElement("span");te.className="tour-file-copy";let j=document.createElement("span");j.className="tour-file-path",j.textContent=v.path;let Z=document.createElement("span");return Z.className="tour-file-meta",Z.textContent=v.kind==="omitted"?`Not rendered \xB7 ${v.reason}`:`${Bt(v.changeKind)} \xB7 +${v.additions} \u2212${v.deletions}`,te.append(j,Z),D.append(H,te),D})),y.replaceChildren(...o.commits.map(v=>{let G=document.createElement("li"),D=document.createElement("span");return D.className="tour-commit-oid",D.textContent=v.shortOid,G.append(D,document.createTextNode(v.summary)),G}))}function oe(o,l=0){let m=i.tour;if(!m||o<0||o>=m.scenes.length)return;let f=m.scenes[o];i.activeSceneIndex=o,i.activeStepIndex=ae(f)?Math.min(Math.max(l,0),Math.max(f.steps.length-1,0)):0,i.tourFocusFilePath=f.kind==="text-diff"?f.path:f.kind==="walkthrough"?f.steps[i.activeStepIndex]?.diff.path??null:pe(f)?f.steps[i.activeStepIndex]?.file??null:null;let p=Wt(m,o);document.querySelectorAll(".tour-scene").forEach(S=>{S.classList.toggle("is-active",S.dataset.sceneId===f.id)}),document.querySelector(`.tour-scene[data-scene-id="${f.id}"]`)?.scrollIntoView({block:"nearest"}),zt(f,p);let T=new URLSearchParams(window.location.search);if(T.set("scene",f.id),ae(f)?T.set("step",f.steps[i.activeStepIndex].id):T.delete("step"),window.history.replaceState(null,"",`${window.location.pathname}?${T.toString()}`),f.kind==="discussion"){document.body.classList.add("tour-discussion"),$e();return}if(document.body.classList.remove("tour-discussion"),f.kind==="walkthrough"){Ge(f);return}if(pe(f)){ze(f);return}ge(f,he(f.path))}function he(o){let l=i.tour;return!l||!o?[]:At(l,o,i.activeSceneIndex,i.activeStepIndex)}function Dt(o,l){let m=i.tour;return!m||!o?[]:Rt(m,o,i.activeSceneIndex,i.activeStepIndex,(f,p)=>Nt(l?.[f]?.diffModel,p))}function Le(o){return`file::${o}`}function ge(o,l=[],m=Le(o.path)){if(!i.tour)return;i.activeTourFilePath=o.path,$e();let p=Q(o.leftContent,o.rightContent),T=Ue(o,o.leftLabel,"base"),S=Ue(o,o.rightLabel,"head"),A=l.find(R=>R.active);u({type:"showDiff",file1:T,file2:S,comparisonId:`tour-${m}`,leftContent:o.leftContent,rightContent:o.rightContent,sourceInfo:{leftPath:o.path,rightPath:o.path},diffModel:p,history:null,fileNavigation:{canGoPrevious:!!se(-1),canGoNext:!!se(1)},editableSides:{left:!1,right:!1},comparisonSummary:`${o.path} \xB7 ${o.takeaway}`,initialChangeIndex:A?Ve(p,A.side,A.startLine):o.focusChangeIndex,tourAnnotations:l})}function Ue(o,l,m){let f=l.startsWith(o.path)?l.slice(o.path.length).trim():l.trim();return f?`${m} ${f}`:m}function Ge(o){let l=o.steps[i.activeStepIndex];l&&ge(l.diff,he(l.diff.path),Le(l.diff.path))}function ze(o){let l=o.steps[i.activeStepIndex];l&&je(o,l.file,l)}function je(o,l,m){let f=o.files.find(M=>M.path===l);if(!m||!f)return;i.activeTourFilePath=f.path,$e();let p=f.panels.map((M,z)=>({id:`${o.id}-${f.path}-${M.id}`,label:M.label,path:M.path||f.path,content:M.content,savedContent:M.content,dirty:!1,editable:!1,stackId:Ht(o)[z].id})),T=p.slice(0,-1).map((M,z)=>({leftIndex:z,rightIndex:z+1,diffModel:Q(M.content,p[z+1].content)})),S=o.kind==="stacked-diff"?Dt(f.path,T):[],A=S.find(M=>M.active),R=A?.pairIndex??m.pairIndex,W=A?.side??m.side,y=A?.startLine??m.startLine,U=T[R]?.diffModel,K=U&&y?Ve(U,W,y):0;u({type:"showMultiDiff",panels:p,pairs:T,activePanelId:p[R+(W==="right"?1:0)]?.id,activePairIndex:R,initialChangeIndex:K,revealFirstChangeInEachPanel:o.kind==="deconstructed-diff",history:null,fileNavigation:{canGoPrevious:!!se(-1),canGoNext:!!se(1)},mutationEnabled:!1,comparisonSummary:o.kind==="deconstructed-diff"?`${o.stageLabel} \xB7 ${f.path} \xB7 ${be(o.realRange.baseRef)} \u2192 ${be(o.realRange.targetRef)}`:`${f.path} \xB7 ${o.takeaway}`,tourAnnotations:S})}function ke(o){let l=i.tour;return!l||o!==-1&&o!==1?null:Et(l.scenes,{sceneIndex:i.activeSceneIndex,stepIndex:i.activeStepIndex},o)}function me(o){let l=ke(o);return l?(oe(l.sceneIndex,l.stepIndex),!0):!1}function se(o){let l=i.tour;return!l||o!==-1&&o!==1?null:Ct(l.files,i.activeTourFilePath,o)}function _t(o){let l=se(o);return l?Ke(l.fileIndex):!1}function qe(o){let l=i.tour?.files[o];return!l||l.kind!=="text-diff"?!1:(ge(l,he(l.path),Le(l.path)),!0)}function Ke(o){let l=i.tour?.files[o];if(l?.kind==="text-diff"&&i.tour){let m=Lt(i.tour.scenes,{sceneIndex:i.activeSceneIndex,stepIndex:i.activeStepIndex},l.path);if(m){let f=i.tour.scenes[m.sceneIndex],p=pe(f)?f.steps[m.stepIndex]:null;if(p)return je(f,l.path,p),!0}}return qe(o)}function Pt(){let o=i.tour?.scenes[i.activeSceneIndex];if(!o||!i.tourFocusFilePath)return!1;if(o.kind==="walkthrough")Ge(o);else if(pe(o))ze(o);else if(o.kind==="text-diff")ge(o,he(o.path));else return!1;return!0}function $e(){document.querySelectorAll(".tour-file").forEach(l=>{l.classList.toggle("is-active",l.dataset.filePath===i.activeTourFilePath),l.classList.toggle("is-tour-focus",l.dataset.filePath===i.tourFocusFilePath)}),document.querySelector(".tour-file.is-active")?.scrollIntoView({block:"nearest"});let o=document.getElementById("tour-return-focus");o&&(o.hidden=!i.tourFocusFilePath||i.activeTourFilePath===i.tourFocusFilePath)}function ae(o){return o.kind==="walkthrough"||o.kind==="stacked-diff"||o.kind==="deconstructed-diff"}function pe(o){return o.kind==="stacked-diff"||o.kind==="deconstructed-diff"}function Ht(o){return o.kind==="deconstructed-diff"?o.panels:o.stack}function Ot(o){return{added:"+",deleted:"\u2212",renamed:"\u2192",modified:"\u2022"}[o]||"\u2022"}function Bt(o){return`${o.charAt(0).toUpperCase()}${o.slice(1)}`}function Wt(o,l){let m=o.scenes[l],f=o.chapters.findIndex(A=>A.sceneIds.includes(m.id)),p=f>=0?o.chapters[f]:null,T=p?p.sceneIds.indexOf(m.id)+1:l+1,S=p?p.sceneIds.length:o.scenes.length;return{chapter:p,chapterIndex:f,chapterNumber:f>=0?f+1:l+1,sceneInChapter:T,scenesInChapter:S}}function Ut(o,l,m){let f=[`Ch ${o.chapterNumber}`,`Scene ${o.sceneInChapter}/${o.scenesInChapter}`];return ae(l)&&f.push(`Step ${m+1}/${l.steps.length}`),f.join(" \xB7 ")}function Ve(o,l,m){let p=(l==="left"?o.leftLines:o.rightLines).findIndex(y=>y.lineNumber===m);if(p<0)return 0;let T=l==="left"?"leftStart":"rightStart",S=l==="left"?"leftEnd":"rightEnd",A=o.blocks.findIndex(y=>p>=y[T]&&p<y[S]);if(A>=0)return A;let R=0,W=Number.POSITIVE_INFINITY;return o.blocks.forEach((y,U)=>{let K=Math.min(Math.abs(p-y[T]),Math.abs(p-y[S]));K<W&&(R=U,W=K)}),R}function be(o){return/^[0-9a-f]{40}$/i.test(o)?o.slice(0,7):o}function le(o,l){return`${o} ${o===1?l:`${l}s`}`}function Gt(o){return o instanceof Element&&!!o.closest('a, button, input, select, summary, textarea, [contenteditable="true"], [role="textbox"], .monaco-editor')}function zt(o,l){let m=document.getElementById("tour-narrative"),f=document.getElementById("tour-breadcrumb"),p=document.getElementById("tour-narrative-chapter"),T=document.getElementById("tour-narrative-title"),S=document.getElementById("tour-narrative-summary"),A=document.getElementById("tour-narrative-bullets"),R=document.getElementById("tour-narrative-tags"),W=document.getElementById("tour-narrative-takeaway"),y=document.getElementById("tour-step"),U=document.getElementById("tour-step-title"),K=document.getElementById("tour-step-body"),M=document.getElementById("tour-connection"),z=document.getElementById("tour-previous"),we=document.getElementById("tour-next");if(!m||!f||!p||!T||!S||!A||!R||!W||!y||!U||!K||!M||!z||!we)throw new Error("Tour narrative UI is incomplete.");m.hidden=!1,f.textContent=Ut(l,o,i.activeStepIndex),p.textContent=o.kind==="deconstructed-diff"?`${l.chapter?.title||"Change tour"} \xB7 ${o.stageLabel}`:l.chapter?.title||"Change tour",T.textContent=o.title,S.textContent=o.summary,A.replaceChildren(...o.bullets.map(G=>{let D=document.createElement("li");return D.textContent=G,D})),R.replaceChildren(...o.tags.map(G=>{let D=document.createElement("span");return D.textContent=G,D})),W.textContent=o.takeaway;let v=ae(o)?o.steps[i.activeStepIndex]:null;y.hidden=!v,v?(U.textContent=o.kind==="deconstructed-diff"?`Stage ${i.activeStepIndex+1}: ${v.title}`:v.title,K.textContent=v.body,"connection"in v&&v.connection?(M.hidden=!1,M.textContent=`${v.connection.from.path} \u2192 ${v.connection.to.path} \xB7 ${v.connection.label}`):(M.hidden=!0,M.textContent="")):(M.hidden=!0,M.textContent=""),z.disabled=!ke(-1),we.disabled=!ke(1)}function Xe(){let o=yt();i.mode="diff",i.comparisonId+=1,i.left={name:o.leftFileName,content:o.leftContent},i.right={name:o.rightFileName,content:o.rightContent},q("Loaded sample diff."),u({type:"showDiff",file1:i.left.name,file2:i.right.name,comparisonId:`web-${i.comparisonId}`,leftContent:i.left.content,rightContent:i.right.content,diffModel:Q(i.left.content,i.right.content),history:null})}async function jt(o){let[l,m]=o,[f,p]=await Promise.all([l.text(),m.text()]);i.mode="diff",i.comparisonId+=1,i.left={name:l.name,content:f},i.right={name:m.name,content:p},q(`Loaded ${l.name} and ${m.name}.`),u({type:"showDiff",file1:l.name,file2:m.name,comparisonId:`web-${i.comparisonId}`,leftContent:f,rightContent:p,diffModel:Q(f,p),history:null})}async function qt(o){let l=await Promise.all(o.map(async(m,f)=>{let p=await m.text();return{id:`web-panel-${f}`,label:m.name,content:p,savedContent:p,dirty:!1,editable:!0}}));i.mode="multi-diff",q(`Loaded ${l.length}-panel diff for ${l.map(m=>m.label).join(", ")}.`),u({type:"showMultiDiff",panels:l,pairs:l.slice(0,-1).map((m,f)=>({leftIndex:f,rightIndex:f+1,diffModel:Q(m.content,l[f+1].content)}))})}function q(o){let l=document.getElementById("web-status");l&&(l.textContent=o)}})();})();
|
|
151
151
|
//# sourceMappingURL=web-host.js.map
|