@davmash/bygone 0.9.8 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/README.md +74 -1
- package/cli/commandSpec.js +2 -0
- package/cli/completions.js +3 -3
- package/cli/present.js +28 -10
- package/cli/tour.js +22 -1
- package/cli/tourExport.js +147 -0
- package/cli/tourFile.js +109 -4
- package/cli/tourHistory.js +31 -1
- package/completions/_bygone +1 -1
- package/completions/bygone +1 -1
- package/completions/bygone.fish +1 -1
- package/docs/change-tour-format.md +85 -68
- package/docs/explore.md +14 -3
- package/docs/generating-change-tours.md +84 -46
- package/docs/present.md +103 -14
- package/docs/product-surface.md +19 -8
- package/docs/sharing-tours.md +95 -0
- package/docs/visual-walkthrough/README.md +89 -0
- package/docs/visual-walkthrough/build-tour.mjs +54 -0
- package/docs/visual-walkthrough/capture-desktop.cjs +42 -0
- package/docs/visual-walkthrough/capture-desktop.mjs +21 -0
- package/docs/visual-walkthrough/captures.md +49 -0
- package/docs/visual-walkthrough/create-demo.mjs +57 -0
- package/docs/visual-walkthrough/deconstructed-demo.bygone +100 -0
- package/docs/visual-walkthrough/images/01-two-files.png +0 -0
- package/docs/visual-walkthrough/images/02-many-panels.png +0 -0
- package/docs/visual-walkthrough/images/03-directories.png +0 -0
- package/docs/visual-walkthrough/images/04-search.png +0 -0
- package/docs/visual-walkthrough/images/05-repository-history.png +0 -0
- package/docs/visual-walkthrough/images/06-file-history.png +0 -0
- package/docs/visual-walkthrough/images/07-branch-review.png +0 -0
- package/docs/visual-walkthrough/images/08-tour-reader.png +0 -0
- package/docs/visual-walkthrough/images/09-focused-step.png +0 -0
- package/docs/visual-walkthrough/images/10-deconstructed.png +0 -0
- package/docs/visual-walkthrough/images/11-exploration.png +0 -0
- package/docs/visual-walkthrough/images/12-authoring.png +0 -0
- package/docs/visual-walkthrough/images/13-export.png +0 -0
- package/docs/visual-walkthrough/images/14-vscode.png +0 -0
- package/docs/visual-walkthrough/images/15-cli.png +0 -0
- package/docs/visual-walkthrough/narrative.md +134 -0
- package/docs/visual-walkthrough/outline.md +52 -0
- package/docs/visual-walkthrough/walkthrough.bygone +340 -0
- package/docs/walkthrough.md +6 -101
- package/examples/bygone-history.bygone +11 -44
- package/examples/marker-focus.bygone +116 -0
- package/examples/navigation-lab.bygone.yaml +401 -336
- package/examples/tour-orientation.bygone +349 -0
- package/media/diff.worker.js +13 -3
- package/media/webview.css +1 -1
- package/media/webview.js +394 -319
- package/out/changeTour.js +865 -397
- package/out/deepLink.js +167 -0
- package/out/historyDirectory.js +66 -0
- package/out/standalone-main.js +20514 -16821
- package/out/tourCoverage.js +850 -386
- package/out/tourDocument.js +97 -0
- package/package.json +1 -1
- package/schemas/change-tour-source.schema.json +91 -64
- package/skills/pr-tour-guide/SKILL.md +144 -128
- package/skills/pr-tour-guide/references/expectations-and-feedback.md +57 -0
- package/standalone/index.html +10 -25
- package/web/export-bootstrap.js +62 -0
- package/web/export-licenses.txt +78 -0
- package/web/export-runtime.json +12 -0
- package/web/index.html +54 -47
- package/web/presenter.css +332 -178
- package/web/web-host.js +239 -137
|
@@ -1,420 +1,485 @@
|
|
|
1
|
-
version:
|
|
2
|
-
title:
|
|
1
|
+
version: 5
|
|
2
|
+
title: Explore a tour without losing your place
|
|
3
3
|
windowTitle: Bygone navigation lab
|
|
4
|
+
opening:
|
|
5
|
+
title: Leave step 3. Come back to step 3.
|
|
6
|
+
summary: >-
|
|
7
|
+
You pause at a code step to read the chapter overview. Returning should bring you back to that
|
|
8
|
+
step, with its code still in view. Two Bygone commits address those two needs: one remembers the
|
|
9
|
+
return destination; the next prevents layout changes from disturbing it. We’ll follow the saved
|
|
10
|
+
position, then the scroll guard. This tour examines an earlier viewer implementation.
|
|
11
|
+
conclusion:
|
|
12
|
+
title: A saved step also needs stable code focus
|
|
13
|
+
summary: >-
|
|
14
|
+
Opening an overview keeps the selected step; returning resumes it before advancing. The URL
|
|
15
|
+
preserves both choices across reload. Separately, the scroll guard prevents layout-only
|
|
16
|
+
notifications from invoking synchronization. The source explains the return path, and callback
|
|
17
|
+
tests check the guard. Neither demonstrates the complete interaction: refresh, return, and
|
|
18
|
+
resize still need a browser check.
|
|
4
19
|
range:
|
|
5
20
|
base: 1f8fdc07d56fc7a0e50dcab0383a63159c77178c
|
|
6
21
|
head: 901a193203e4840dbf6e06c6a273fac7f2d713bd
|
|
7
22
|
anchors:
|
|
8
|
-
path-host:
|
|
9
|
-
file: web/index.html
|
|
10
|
-
revision: head
|
|
11
|
-
contains: <nav id="tour-reading-path" class="tour-reading-path" aria-label="Reading hierarchy"></nav>
|
|
12
|
-
path-levels:
|
|
13
|
-
file: web/host.js
|
|
14
|
-
revision: head
|
|
15
|
-
contains: " if (tour.scenes.length > 1) levels.push(['tour', tour.title]);\n if (tour.chapters.length\
|
|
16
|
-
\ > 1 && chapter && (chapter.sceneIds.length > 1 || state.narrativeParent === 'chapter')) levels.push(['chapter',\
|
|
17
|
-
\ chapter.title]);\n levels.push(['scene', scene.title]);\n if (hasStep) levels.push(['step',\
|
|
18
|
-
\ `Step ${state.activeStepIndex + 1}`]);"
|
|
19
23
|
path-children:
|
|
20
24
|
file: web/host.js
|
|
21
25
|
revision: head
|
|
22
|
-
contains:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
contains: |2-
|
|
27
|
+
children.append(readingButton(item.title, `Read chapter: ${item.title}`, () => {
|
|
28
|
+
if (!item.sceneIds.includes(scene.id)) showTourScene(first, 0, { userNavigation: true, showIntro: true });
|
|
29
|
+
setNarrativeView(item.sceneIds.length > 1 ? 'chapter' : 'scene');
|
|
30
|
+
}));
|
|
26
31
|
remember-step:
|
|
27
32
|
file: web/host.js
|
|
28
33
|
revision: head
|
|
29
|
-
contains:
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
contains: |2-
|
|
35
|
+
if (step) parameters.set('step', step.id);
|
|
36
|
+
else parameters.delete('step');
|
|
37
|
+
if (state.narrativeParent) parameters.set('view', state.narrativeParent);
|
|
38
|
+
else if (step && state.sceneIntroVisible) parameters.set('view', 'overview');
|
|
39
|
+
else parameters.delete('view');
|
|
32
40
|
resume-parent:
|
|
33
41
|
file: web/host.js
|
|
34
42
|
revision: head
|
|
35
|
-
contains:
|
|
36
|
-
|
|
37
|
-
|
|
43
|
+
contains: |2-
|
|
44
|
+
if (direction === 1 && state.narrativeParent) {
|
|
45
|
+
showTourScene(state.activeSceneIndex, state.activeStepIndex, { userNavigation: true, showIntro: false });
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
38
48
|
restore-parent:
|
|
39
49
|
file: web/host.js
|
|
40
50
|
revision: head
|
|
41
|
-
contains:
|
|
51
|
+
contains: |2-
|
|
52
|
+
const requestedPosition = resolveTourPosition(
|
|
53
|
+
state.tour.scenes,
|
|
54
|
+
parameters.get('scene'),
|
|
55
|
+
parameters.get('step')
|
|
56
|
+
);
|
|
57
|
+
showTourScene(requestedPosition.sceneIndex, requestedPosition.stepIndex, {
|
|
58
|
+
showIntro: parameters.get('view') === 'overview' || !parameters.get('step')
|
|
59
|
+
});
|
|
60
|
+
if (['tour', 'chapter'].includes(parameters.get('view'))) setNarrativeView(parameters.get('view'));
|
|
42
61
|
ignore-layout:
|
|
43
62
|
file: media/script.js
|
|
44
63
|
revision: head
|
|
45
|
-
contains:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
contains: " if (editorMode === MODE_MULTI_WAY) {\n synchronizeMultiScroll(editor);\n\
|
|
51
|
-
\ } else {\n synchronizeEditorScroll(editor);\n }"
|
|
64
|
+
contains: |2-
|
|
65
|
+
if (suppressEditorEvents || (!event.scrollTopChanged && !event.scrollLeftChanged)) {
|
|
66
|
+
connectorController.scheduleDrawConnections();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
52
69
|
width-test:
|
|
53
70
|
file: test/runTests.js
|
|
54
71
|
revision: head
|
|
55
|
-
contains:
|
|
56
|
-
|
|
57
|
-
|
|
72
|
+
contains: |2-
|
|
73
|
+
assert.deepEqual(
|
|
74
|
+
invokeScrollHandler({ scrollTopChanged: false, scrollLeftChanged: false, scrollWidthChanged: true }),
|
|
75
|
+
['draw']
|
|
76
|
+
);
|
|
77
|
+
real-scroll-tests:
|
|
58
78
|
file: test/runTests.js
|
|
59
79
|
revision: head
|
|
60
|
-
contains:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
80
|
+
contains: |2-
|
|
81
|
+
assert.deepEqual(
|
|
82
|
+
invokeScrollHandler({ scrollTopChanged: true, scrollLeftChanged: false }),
|
|
83
|
+
['two-way-scroll', 'draw']
|
|
84
|
+
);
|
|
85
|
+
assert.deepEqual(
|
|
86
|
+
invokeScrollHandler({ scrollTopChanged: false, scrollLeftChanged: true }, 'multi-way'),
|
|
87
|
+
['multi-scroll', 'draw']
|
|
88
|
+
);
|
|
89
|
+
parent-view:
|
|
90
|
+
file: web/host.js
|
|
64
91
|
revision: head
|
|
65
|
-
contains:
|
|
66
|
-
|
|
92
|
+
contains: |2-
|
|
93
|
+
if (view === 'tour' || view === 'chapter') {
|
|
94
|
+
state.narrativeParent = view;
|
|
95
|
+
renderNarrativeViewControls();
|
|
96
|
+
renderTourProgress();
|
|
97
|
+
updateTourLocationUrl();
|
|
98
|
+
} else {
|
|
67
99
|
connections: []
|
|
68
100
|
chapters:
|
|
69
|
-
- id: reading
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
- navigation-demo
|
|
177
|
-
takeaway: The reading level and the return step are separate pieces of state.
|
|
178
|
-
steps:
|
|
179
|
-
- id: remember-step
|
|
180
|
-
title: Keep your step ready to resume
|
|
181
|
-
body: Selecting a parent keeps your current step ready to resume. The URL preserves the step and
|
|
182
|
-
selected reading level, so refreshing restores both.
|
|
183
|
-
focus: remember-step
|
|
184
|
-
- id: resume-parent
|
|
185
|
-
title: Resume from a parent
|
|
186
|
-
body: Next from a parent returns to the remembered step instead of advancing past it. The button
|
|
187
|
-
label becomes Resume to make that behavior explicit.
|
|
188
|
-
focus: resume-parent
|
|
189
|
-
- id: restore-parent
|
|
190
|
-
title: Restore the parent after refresh
|
|
191
|
-
body: Loading the URL restores the selected tour or chapter view after establishing the saved scene
|
|
192
|
-
and step. Try refreshing while viewing this chapter.
|
|
193
|
-
focus: restore-parent
|
|
194
|
-
- id: evidence
|
|
195
|
-
title: Code focus
|
|
196
|
-
scenes:
|
|
197
|
-
- id: marker-focus
|
|
198
|
-
title: Keep the marker in view
|
|
199
|
-
summary: Panel layout changes can emit scroll events without a scroll-position change. The renderer
|
|
200
|
-
must not treat those events as reader navigation.
|
|
201
|
-
bullets: []
|
|
202
|
-
tags:
|
|
203
|
-
- navigation-demo
|
|
204
|
-
takeaway: The fix filters layout noise without disabling synchronized scrolling.
|
|
205
|
-
steps:
|
|
206
|
-
- id: ignore-layout
|
|
207
|
-
title: Ignore extent-only scroll events
|
|
208
|
-
body: The guard exits when neither vertical nor horizontal position changed. A panel-width change
|
|
209
|
-
therefore cannot synchronize an old position back into the focused editor.
|
|
210
|
-
focus: ignore-layout
|
|
211
|
-
- id: keep-sync
|
|
212
|
-
title: Continue synchronizing real scrolling
|
|
213
|
-
body: After the guard, actual scroll events still dispatch to the appropriate two-panel or multi-panel
|
|
214
|
-
synchronization path.
|
|
215
|
-
focus: keep-sync
|
|
216
|
-
- id: scroll-proof
|
|
217
|
-
title: Inspect the regression checks
|
|
218
|
-
summary: These tests invoke the renderer scroll callback with different event shapes. Use the Files
|
|
219
|
-
section to explore the complete change set, then return to the tour.
|
|
220
|
-
bullets: []
|
|
221
|
-
tags:
|
|
222
|
-
- navigation-demo
|
|
223
|
-
takeaway: Use the mode buttons to open either tour or live History. To inspect the final result without narration,
|
|
224
|
-
open Compare and choose Final diff.
|
|
225
|
-
steps:
|
|
226
|
-
- id: width-test
|
|
227
|
-
title: A width change only redraws
|
|
228
|
-
body: A width-only event must draw connectors without requesting either kind of synchronized scroll.
|
|
229
|
-
focus: width-test
|
|
230
|
-
- id: vertical-test
|
|
231
|
-
title: Vertical scrolling still synchronizes
|
|
232
|
-
body: A real vertical movement in a two-panel comparison still synchronizes and redraws.
|
|
233
|
-
focus: vertical-test
|
|
234
|
-
- id: horizontal-test
|
|
235
|
-
title: Multi-panel scrolling still synchronizes
|
|
236
|
-
body: A horizontal movement in multi-panel mode reaches the multi-panel synchronizer. This is callback
|
|
237
|
-
coverage; the panel-switch landing was also checked manually in the browser.
|
|
238
|
-
focus: horizontal-test
|
|
239
|
-
|
|
101
|
+
- id: reading
|
|
102
|
+
title: Remember where to return
|
|
103
|
+
scenes:
|
|
104
|
+
- id: reading-path
|
|
105
|
+
title: An overview changes the view, not the selected step
|
|
106
|
+
summary: >-
|
|
107
|
+
Suppose you are reading step 3 and open its chapter overview. The viewer needs to change
|
|
108
|
+
what it explains while keeping step 3 as the return destination. We’ll trace that
|
|
109
|
+
separation, then the boundary: choosing a different chapter deliberately selects a new
|
|
110
|
+
destination.
|
|
111
|
+
bullets: []
|
|
112
|
+
tags:
|
|
113
|
+
- navigation-demo
|
|
114
|
+
takeaway: >-
|
|
115
|
+
Opening the current chapter preserves its selection; choosing another chapter starts
|
|
116
|
+
there.
|
|
117
|
+
steps:
|
|
118
|
+
- id: parent-view
|
|
119
|
+
title: Change the view without resetting the selection
|
|
120
|
+
body: >-
|
|
121
|
+
Opening a tour or chapter overview sets narrativeParent and redraws the navigation.
|
|
122
|
+
This branch does not change the active scene or step. Step 3 can therefore remain
|
|
123
|
+
selected while the reader sees its broader context.
|
|
124
|
+
focus: parent-view
|
|
125
|
+
- id: path-children
|
|
126
|
+
title: A different chapter needs a different destination
|
|
127
|
+
body: >-
|
|
128
|
+
The chapter button checks whether it contains the current scene. If it does, the
|
|
129
|
+
selection stays put. If it does not, the button selects that chapter’s first scene at
|
|
130
|
+
step 1 before opening its overview. Preserving your place applies to stepping outward;
|
|
131
|
+
it does not prevent deliberate navigation elsewhere.
|
|
132
|
+
focus: path-children
|
|
133
|
+
- id: return-position
|
|
134
|
+
title: Return to the saved step—even after a reload
|
|
135
|
+
summary: >-
|
|
136
|
+
The selection survives in memory, but it also has to survive returning and reloading.
|
|
137
|
+
Still in the same comparison, follow the two values into the URL, the forward action, and
|
|
138
|
+
startup. Together they explain why an overview need not become a dead end.
|
|
139
|
+
bullets: []
|
|
140
|
+
tags:
|
|
141
|
+
- navigation-demo
|
|
142
|
+
takeaway: Save both the step to resume and the view to show; restoring either alone is insufficient.
|
|
143
|
+
steps:
|
|
144
|
+
- id: remember-step
|
|
145
|
+
title: "Save two facts: where to return, and what to show"
|
|
146
|
+
body: >-
|
|
147
|
+
The URL keeps the selected step while view records the open overview. In our example,
|
|
148
|
+
it needs both “step 3” and “chapter view.” Saving only the chapter would lose the
|
|
149
|
+
return destination; saving only the step would reopen code instead of the overview.
|
|
150
|
+
focus: remember-step
|
|
151
|
+
- id: resume-parent
|
|
152
|
+
title: Resume step 3 before considering step 4
|
|
153
|
+
body: >-
|
|
154
|
+
The forward action checks for a parent view before normal advancement. It opens the
|
|
155
|
+
saved scene and step, then returns immediately. From the chapter overview, that means
|
|
156
|
+
resume step 3—not skip ahead to step 4.
|
|
157
|
+
focus: resume-parent
|
|
158
|
+
- id: restore-parent
|
|
159
|
+
title: Reload the destination, then reopen the overview
|
|
160
|
+
body: >-
|
|
161
|
+
Startup first resolves the scene and step from the URL and selects them. Only then
|
|
162
|
+
does it apply the parent view. That order restores a return destination underneath the
|
|
163
|
+
overview. The code establishes this sequence; a reload-and-return interaction remains
|
|
164
|
+
the browser check.
|
|
165
|
+
focus: restore-parent
|
|
166
|
+
- id: evidence
|
|
167
|
+
title: Keep that code in view
|
|
168
|
+
scenes:
|
|
169
|
+
- id: marker-focus
|
|
170
|
+
title: A resize notification is not necessarily a scroll
|
|
171
|
+
summary: >-
|
|
172
|
+
A saved step is not enough if resizing the panels moves its highlighted code off-screen.
|
|
173
|
+
Monaco can report a changed scrollable area even when the scroll position stays put. The
|
|
174
|
+
old handler could synchronize that notification. This scene follows the new guard and
|
|
175
|
+
checks that real scrolling still works.
|
|
176
|
+
bullets: []
|
|
177
|
+
tags:
|
|
178
|
+
- navigation-demo
|
|
179
|
+
takeaway: >-
|
|
180
|
+
A change in scrollable size needs a redraw; an unsuppressed position change still needs
|
|
181
|
+
synchronization.
|
|
182
|
+
steps:
|
|
183
|
+
- id: ignore-layout
|
|
184
|
+
title: Redraw layout changes without moving the other panels
|
|
185
|
+
body: >-
|
|
186
|
+
The new condition asks whether either scroll position changed. If neither did, it
|
|
187
|
+
redraws the lines connecting matching code and returns before synchronization.
|
|
188
|
+
Existing event suppression also takes this early exit. Unsuppressed movement still
|
|
189
|
+
reaches the synchronizer, so fixing the resize case does not require disabling linked
|
|
190
|
+
scrolling.
|
|
191
|
+
focus: ignore-layout
|
|
192
|
+
- id: width-test
|
|
193
|
+
title: A wider scrollable area must not move the code
|
|
194
|
+
body: >-
|
|
195
|
+
The test changes the scrollable width while leaving both position flags false. It
|
|
196
|
+
expects only a connector redraw. Calling a synchronizer here would reopen the route by
|
|
197
|
+
which layout changes can disturb a code reveal.
|
|
198
|
+
focus: width-test
|
|
199
|
+
- id: real-scroll-tests
|
|
200
|
+
title: Real movement must still keep panels together
|
|
201
|
+
body: >-
|
|
202
|
+
Skipping synchronization for every scroll event would pass the previous check but
|
|
203
|
+
break linked scrolling. These assertions rule that out: vertical movement in two-panel
|
|
204
|
+
mode and horizontal movement in multi-panel mode each synchronize, then redraw. Panel
|
|
205
|
+
mode selects the synchronizer; the direction of movement does not. These tests check
|
|
206
|
+
callback routing, not on-screen marker visibility.
|
|
207
|
+
focus: real-scroll-tests
|
|
240
208
|
tours:
|
|
241
209
|
historical:
|
|
210
|
+
opening:
|
|
211
|
+
title: Leave step 3. Come back to step 3.
|
|
212
|
+
summary: >-
|
|
213
|
+
You pause at a code step to read the chapter overview. Returning should bring you back to
|
|
214
|
+
that step, with its code still in view. Two Bygone commits address those two needs: one
|
|
215
|
+
remembers the return destination; the next prevents layout changes from disturbing it. We’ll
|
|
216
|
+
follow the saved position, then the scroll guard. This tour examines an earlier viewer
|
|
217
|
+
implementation.
|
|
218
|
+
conclusion:
|
|
219
|
+
title: A saved step also needs stable code focus
|
|
220
|
+
summary: >-
|
|
221
|
+
Opening an overview keeps the selected step; returning resumes it before advancing. The URL
|
|
222
|
+
preserves both choices across reload. Separately, the scroll guard prevents layout-only
|
|
223
|
+
notifications from invoking synchronization. The source explains the return path, and
|
|
224
|
+
callback tests check the guard. Neither demonstrates the complete interaction: refresh,
|
|
225
|
+
return, and resize still need a browser check.
|
|
242
226
|
chapters:
|
|
243
|
-
- id:
|
|
244
|
-
title:
|
|
227
|
+
- id: reading
|
|
228
|
+
title: Remember where to return
|
|
245
229
|
scenes:
|
|
246
|
-
- id:
|
|
247
|
-
overview
|
|
248
|
-
kind: directory-diff
|
|
249
|
-
path: web
|
|
250
|
-
comparison:
|
|
251
|
-
from: before
|
|
252
|
-
to: hierarchy
|
|
253
|
-
kind: stacked-diff
|
|
254
|
-
title: Add reading levels in a real commit
|
|
230
|
+
- id: reading-path
|
|
231
|
+
title: An overview changes the view, not the selected step
|
|
255
232
|
summary: >-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
233
|
+
Suppose you are reading step 3 and open its chapter overview. The viewer needs to
|
|
234
|
+
change what it explains while keeping step 3 as the return destination. We’ll trace
|
|
235
|
+
that separation, then the boundary: choosing a different chapter deliberately selects
|
|
236
|
+
a new destination.
|
|
259
237
|
bullets: []
|
|
260
238
|
tags:
|
|
261
|
-
- real-revisions
|
|
262
239
|
- navigation-demo
|
|
263
240
|
takeaway: >-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
stack:
|
|
267
|
-
- id: before
|
|
268
|
-
ref: 1f8fdc07d56fc7a0e50dcab0383a63159c77178c
|
|
269
|
-
label: Before hierarchy
|
|
270
|
-
- id: hierarchy
|
|
271
|
-
ref: a50c2a6f58a2dfd7f85039105a27e4b92b98a3f7
|
|
272
|
-
label: Hierarchy added
|
|
273
|
-
- id: marker
|
|
274
|
-
ref: 901a193203e4840dbf6e06c6a273fac7f2d713bd
|
|
275
|
-
label: Marker fix added
|
|
276
|
-
files:
|
|
277
|
-
- web/index.html
|
|
278
|
-
- web/host.js
|
|
279
|
-
- web/presenter.css
|
|
241
|
+
Opening the current chapter preserves its selection; choosing another chapter starts
|
|
242
|
+
there.
|
|
280
243
|
steps:
|
|
281
|
-
- id:
|
|
282
|
-
title:
|
|
244
|
+
- id: parent-view
|
|
245
|
+
title: Change the view without resetting the selection
|
|
283
246
|
body: >-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
- hierarchy
|
|
291
|
-
side: right
|
|
292
|
-
- id: historical-behavior
|
|
293
|
-
title: Connect the reading levels
|
|
294
|
-
body: >-
|
|
295
|
-
The same commit wires parent navigation and return positions in the host. The
|
|
296
|
-
hierarchy was introduced as a coherent UI change, rather than as separate Git
|
|
297
|
-
commits for each explanation stage.
|
|
298
|
-
file: web/host.js
|
|
299
|
-
pair:
|
|
300
|
-
- before
|
|
301
|
-
- hierarchy
|
|
302
|
-
side: right
|
|
303
|
-
- id: historical-style
|
|
304
|
-
title: Style the parent choices
|
|
247
|
+
Opening a tour or chapter overview sets narrativeParent and redraws the
|
|
248
|
+
navigation. This branch does not change the active scene or step. Step 3 can
|
|
249
|
+
therefore remain selected while the reader sees its broader context.
|
|
250
|
+
focus: parent-view
|
|
251
|
+
- id: path-children
|
|
252
|
+
title: A different chapter needs a different destination
|
|
305
253
|
body: >-
|
|
306
|
-
The
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
side: right
|
|
314
|
-
- id: historical-return
|
|
315
|
-
title: Return without losing your place
|
|
254
|
+
The chapter button checks whether it contains the current scene. If it does, the
|
|
255
|
+
selection stays put. If it does not, the button selects that chapter’s first scene
|
|
256
|
+
at step 1 before opening its overview. Preserving your place applies to stepping
|
|
257
|
+
outward; it does not prevent deliberate navigation elsewhere.
|
|
258
|
+
focus: path-children
|
|
259
|
+
- id: return-position
|
|
260
|
+
title: Return to the saved step—even after a reload
|
|
316
261
|
summary: >-
|
|
317
|
-
|
|
318
|
-
|
|
262
|
+
The selection survives in memory, but it also has to survive returning and reloading.
|
|
263
|
+
Still in the same comparison, follow the two values into the URL, the forward action,
|
|
264
|
+
and startup. Together they explain why an overview need not become a dead end.
|
|
319
265
|
bullets: []
|
|
320
266
|
tags:
|
|
321
267
|
- navigation-demo
|
|
322
|
-
takeaway:
|
|
268
|
+
takeaway: >-
|
|
269
|
+
Save both the step to resume and the view to show; restoring either alone is
|
|
270
|
+
insufficient.
|
|
323
271
|
steps:
|
|
324
272
|
- id: remember-step
|
|
325
|
-
title:
|
|
273
|
+
title: "Save two facts: where to return, and what to show"
|
|
326
274
|
body: >-
|
|
327
|
-
|
|
328
|
-
|
|
275
|
+
The URL keeps the selected step while view records the open overview. In our
|
|
276
|
+
example, it needs both “step 3” and “chapter view.” Saving only the chapter would
|
|
277
|
+
lose the return destination; saving only the step would reopen code instead of the
|
|
278
|
+
overview.
|
|
329
279
|
focus: remember-step
|
|
330
280
|
- id: resume-parent
|
|
331
|
-
title: Resume
|
|
281
|
+
title: Resume step 3 before considering step 4
|
|
332
282
|
body: >-
|
|
333
|
-
|
|
334
|
-
|
|
283
|
+
The forward action checks for a parent view before normal advancement. It opens
|
|
284
|
+
the saved scene and step, then returns immediately. From the chapter overview,
|
|
285
|
+
that means resume step 3—not skip ahead to step 4.
|
|
335
286
|
focus: resume-parent
|
|
336
287
|
- id: restore-parent
|
|
337
|
-
title:
|
|
288
|
+
title: Reload the destination, then reopen the overview
|
|
338
289
|
body: >-
|
|
339
|
-
|
|
340
|
-
|
|
290
|
+
Startup first resolves the scene and step from the URL and selects them. Only then
|
|
291
|
+
does it apply the parent view. That order restores a return destination underneath
|
|
292
|
+
the overview. The code establishes this sequence; a reload-and-return interaction
|
|
293
|
+
remains the browser check.
|
|
341
294
|
focus: restore-parent
|
|
342
|
-
- id:
|
|
343
|
-
title:
|
|
295
|
+
- id: evidence
|
|
296
|
+
title: Keep that code in view
|
|
344
297
|
scenes:
|
|
345
|
-
- id: marker-
|
|
346
|
-
|
|
347
|
-
title: Fix marker focus after the hierarchy change
|
|
298
|
+
- id: marker-focus
|
|
299
|
+
title: A resize notification is not necessarily a scroll
|
|
348
300
|
summary: >-
|
|
349
|
-
|
|
350
|
-
|
|
301
|
+
Now isolate the second commit: navigation is already in place, but a panel resize can
|
|
302
|
+
still disturb the highlighted code. Monaco reports changes in scrollable size through
|
|
303
|
+
its scroll callback, even without a position change. The guard separates those
|
|
304
|
+
notifications from movement; the tests check both paths.
|
|
351
305
|
bullets: []
|
|
352
306
|
tags:
|
|
353
|
-
- real-revisions
|
|
354
307
|
- navigation-demo
|
|
355
|
-
takeaway:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
ref: 1f8fdc07d56fc7a0e50dcab0383a63159c77178c
|
|
359
|
-
label: Before hierarchy
|
|
360
|
-
- id: hierarchy
|
|
361
|
-
ref: a50c2a6f58a2dfd7f85039105a27e4b92b98a3f7
|
|
362
|
-
label: Hierarchy added
|
|
363
|
-
- id: marker
|
|
364
|
-
ref: 901a193203e4840dbf6e06c6a273fac7f2d713bd
|
|
365
|
-
label: Marker fix added
|
|
366
|
-
files:
|
|
367
|
-
- media/script.js
|
|
368
|
-
- test/runTests.js
|
|
308
|
+
takeaway: >-
|
|
309
|
+
A change in scrollable size needs a redraw; an unsuppressed position change still
|
|
310
|
+
needs synchronization.
|
|
369
311
|
steps:
|
|
370
312
|
- id: historical-marker
|
|
371
|
-
title:
|
|
313
|
+
title: Redraw layout changes without moving the other panels
|
|
372
314
|
body: >-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
315
|
+
The new condition asks whether either scroll position changed. If neither did, it
|
|
316
|
+
redraws the lines connecting matching code and returns before synchronization.
|
|
317
|
+
Existing event suppression also takes this early exit. Unsuppressed movement still
|
|
318
|
+
reaches the synchronizer, so fixing the resize case does not require disabling
|
|
319
|
+
linked scrolling.
|
|
376
320
|
file: media/script.js
|
|
377
321
|
pair:
|
|
378
322
|
- hierarchy
|
|
379
323
|
- marker
|
|
380
324
|
side: right
|
|
381
325
|
- id: historical-proof
|
|
382
|
-
title:
|
|
326
|
+
title: Reject layout-only events without breaking linked scrolling
|
|
383
327
|
body: >-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
328
|
+
In the same commit comparison, this file checks both sides of the guard. A
|
|
329
|
+
width-only event must call draw alone. Vertical movement in two-panel mode and
|
|
330
|
+
horizontal movement in multi-panel mode must each synchronize, then draw. The
|
|
331
|
+
positive cases matter: disabling all synchronization would also pass the
|
|
332
|
+
width-only check. These assertions verify routing, not visible marker behavior.
|
|
387
333
|
file: test/runTests.js
|
|
388
334
|
pair:
|
|
389
335
|
- hierarchy
|
|
390
336
|
- marker
|
|
391
337
|
side: right
|
|
392
|
-
|
|
393
|
-
|
|
338
|
+
kind: stacked-diff
|
|
339
|
+
stack:
|
|
340
|
+
- id: before
|
|
341
|
+
ref: 1f8fdc07d56fc7a0e50dcab0383a63159c77178c
|
|
342
|
+
label: Before hierarchy
|
|
343
|
+
- id: hierarchy
|
|
344
|
+
ref: a50c2a6f58a2dfd7f85039105a27e4b92b98a3f7
|
|
345
|
+
label: Hierarchy added
|
|
346
|
+
- id: marker
|
|
347
|
+
ref: 901a193203e4840dbf6e06c6a273fac7f2d713bd
|
|
348
|
+
label: Marker fix added
|
|
349
|
+
files:
|
|
350
|
+
- media/script.js
|
|
351
|
+
- test/runTests.js
|
|
352
|
+
deconstructed:
|
|
353
|
+
opening:
|
|
354
|
+
title: Leave step 3. Come back to step 3.
|
|
355
|
+
summary: >-
|
|
356
|
+
You pause at a code step to read the chapter overview. Returning should bring you back to
|
|
357
|
+
that step, with its code still in view. Two Bygone commits address those two needs: one
|
|
358
|
+
remembers the return destination; the next prevents layout changes from disturbing it. We’ll
|
|
359
|
+
follow the saved position, then the scroll guard. This tour examines an earlier viewer
|
|
360
|
+
implementation.
|
|
361
|
+
conclusion:
|
|
362
|
+
title: A saved step also needs stable code focus
|
|
363
|
+
summary: >-
|
|
364
|
+
Opening an overview keeps the selected step; returning resumes it before advancing. The URL
|
|
365
|
+
preserves both choices across reload. Separately, the scroll guard prevents layout-only
|
|
366
|
+
notifications from invoking synchronization. The source explains the return path, and
|
|
367
|
+
callback tests check the guard. Neither demonstrates the complete interaction: refresh,
|
|
368
|
+
return, and resize still need a browser check.
|
|
369
|
+
chapters:
|
|
370
|
+
- id: reading
|
|
371
|
+
title: Remember where to return
|
|
372
|
+
scenes:
|
|
373
|
+
- id: reading-path
|
|
374
|
+
title: Make the overview reachable, then make the return reliable
|
|
375
|
+
summary: >-
|
|
376
|
+
Leave step 3 for its chapter overview: the controls expose the overview, while
|
|
377
|
+
separate view and selection state preserve the way back. Returning resumes step 3
|
|
378
|
+
before advancing. Reload restores the selection before reopening the overview;
|
|
379
|
+
choosing another chapter deliberately selects a new destination. These two constructed
|
|
380
|
+
stages separate controls from behavior, not commit history. The next scene returns to
|
|
381
|
+
committed evidence for the scroll guard.
|
|
382
|
+
bullets: []
|
|
383
|
+
tags:
|
|
384
|
+
- navigation-demo
|
|
385
|
+
takeaway: >-
|
|
386
|
+
The controls let the reader step outward; separate view and selection state make the
|
|
387
|
+
trip reversible.
|
|
388
|
+
kind: deconstructed-diff
|
|
389
|
+
base: 1f8fdc07d56fc7a0e50dcab0383a63159c77178c
|
|
390
|
+
target: 901a193203e4840dbf6e06c6a273fac7f2d713bd
|
|
391
|
+
stages:
|
|
392
|
+
- id: surface
|
|
393
|
+
title: Give the reader a way to step outward
|
|
394
|
+
narration: >-
|
|
395
|
+
The markup and styling provide parent navigation and destination lists. The next
|
|
396
|
+
stage supplies the behavior that preserves the return destination.
|
|
397
|
+
changes:
|
|
398
|
+
- file: web/index.html
|
|
399
|
+
hunks:
|
|
400
|
+
- hunk-2828c9627055
|
|
401
|
+
- hunk-68a3bdc9f262
|
|
402
|
+
- hunk-ad7073e10ed7
|
|
403
|
+
- file: web/presenter.css
|
|
404
|
+
hunks:
|
|
405
|
+
- hunk-3d4093808d4b
|
|
406
|
+
- id: navigation
|
|
407
|
+
title: Keep the selected step underneath the overview
|
|
408
|
+
narration: >-
|
|
409
|
+
The parent view changes independently of the selected step. Saving both lets
|
|
410
|
+
return and reload preserve the reader’s place.
|
|
411
|
+
changes:
|
|
412
|
+
- file: docs/present.md
|
|
413
|
+
hunks:
|
|
414
|
+
- hunk-5b7f86aadb64
|
|
415
|
+
- hunk-635769fc5c13
|
|
416
|
+
- hunk-d3f94ec64c1f
|
|
417
|
+
- file: web/host.js
|
|
418
|
+
hunks:
|
|
419
|
+
- hunk-3bd48ca387ae
|
|
420
|
+
- hunk-069a2fee2f36
|
|
421
|
+
- hunk-e7def68037d5
|
|
422
|
+
- hunk-755dbc1b8067
|
|
423
|
+
- hunk-82249952520f
|
|
424
|
+
- hunk-db24a55e418e
|
|
425
|
+
- hunk-87209fb2e340
|
|
426
|
+
- hunk-5ebccafb6522
|
|
427
|
+
- hunk-b62a3aedf12b
|
|
428
|
+
- hunk-50d651bf7762
|
|
429
|
+
- hunk-3a1c863cc48a
|
|
430
|
+
- hunk-1d2fb5f32ab9
|
|
431
|
+
- hunk-df6ed3ebba70
|
|
432
|
+
- hunk-5106426d3c27
|
|
433
|
+
- hunk-8d0ffe62e5b7
|
|
434
|
+
- hunk-fc04b2890333
|
|
435
|
+
exclusions:
|
|
436
|
+
- file: media/script.js
|
|
437
|
+
reason: >-
|
|
438
|
+
The marker correction is explained with exact committed evidence in the following
|
|
439
|
+
scene.
|
|
440
|
+
- file: test/runTests.js
|
|
441
|
+
reason: >-
|
|
442
|
+
The scroll callback assertions are explained beside the guard in the following
|
|
443
|
+
scene.
|
|
444
|
+
- id: evidence
|
|
445
|
+
title: Keep that code in view
|
|
446
|
+
scenes:
|
|
447
|
+
- id: marker-focus
|
|
448
|
+
title: A resize notification is not necessarily a scroll
|
|
394
449
|
summary: >-
|
|
395
|
-
|
|
396
|
-
|
|
450
|
+
A saved step is not enough if resizing the panels moves its highlighted code
|
|
451
|
+
off-screen. Monaco can report a changed scrollable area even when the scroll position
|
|
452
|
+
stays put. The old handler could synchronize that notification. This scene follows the
|
|
453
|
+
new guard and checks that real scrolling still works.
|
|
397
454
|
bullets: []
|
|
398
455
|
tags:
|
|
399
456
|
- navigation-demo
|
|
400
457
|
takeaway: >-
|
|
401
|
-
|
|
402
|
-
|
|
458
|
+
A change in scrollable size needs a redraw; an unsuppressed position change still
|
|
459
|
+
needs synchronization.
|
|
403
460
|
steps:
|
|
461
|
+
- id: ignore-layout
|
|
462
|
+
title: Redraw layout changes without moving the other panels
|
|
463
|
+
body: >-
|
|
464
|
+
The new condition asks whether either scroll position changed. If neither did, it
|
|
465
|
+
redraws the lines connecting matching code and returns before synchronization.
|
|
466
|
+
Existing event suppression also takes this early exit. Unsuppressed movement still
|
|
467
|
+
reaches the synchronizer, so fixing the resize case does not require disabling
|
|
468
|
+
linked scrolling.
|
|
469
|
+
focus: ignore-layout
|
|
404
470
|
- id: width-test
|
|
405
|
-
title: A
|
|
471
|
+
title: A wider scrollable area must not move the code
|
|
406
472
|
body: >-
|
|
407
|
-
|
|
408
|
-
|
|
473
|
+
The test changes the scrollable width while leaving both position flags false. It
|
|
474
|
+
expects only a connector redraw. Calling a synchronizer here would reopen the
|
|
475
|
+
route by which layout changes can disturb a code reveal.
|
|
409
476
|
focus: width-test
|
|
410
|
-
- id:
|
|
411
|
-
title:
|
|
412
|
-
body: A real vertical movement in a two-panel comparison still synchronizes and redraws.
|
|
413
|
-
focus: vertical-test
|
|
414
|
-
- id: horizontal-test
|
|
415
|
-
title: Multi-panel scrolling still synchronizes
|
|
477
|
+
- id: real-scroll-tests
|
|
478
|
+
title: Real movement must still keep panels together
|
|
416
479
|
body: >-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
480
|
+
Skipping synchronization for every scroll event would pass the previous check but
|
|
481
|
+
break linked scrolling. These assertions rule that out: vertical movement in
|
|
482
|
+
two-panel mode and horizontal movement in multi-panel mode each synchronize, then
|
|
483
|
+
redraw. Panel mode selects the synchronizer; the direction of movement does not.
|
|
484
|
+
These tests check callback routing, not on-screen marker visibility.
|
|
485
|
+
focus: real-scroll-tests
|