xtralab 0.15.0 → 0.15.1

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.
Files changed (228) hide show
  1. package/README.md +10 -0
  2. package/lib/about/icons.d.ts +0 -5
  3. package/lib/about/icons.js +0 -5
  4. package/lib/about/index.d.ts +4 -8
  5. package/lib/about/index.js +6 -17
  6. package/lib/agentSessions.d.ts +9 -29
  7. package/lib/agentSessions.js +2 -7
  8. package/lib/askAgent/editorSelection.d.ts +20 -26
  9. package/lib/askAgent/editorSelection.js +11 -26
  10. package/lib/askAgent/icons.d.ts +2 -3
  11. package/lib/askAgent/icons.js +2 -3
  12. package/lib/askAgent/index.d.ts +4 -26
  13. package/lib/askAgent/index.js +54 -158
  14. package/lib/askAgent/popup.d.ts +12 -16
  15. package/lib/askAgent/popup.js +18 -37
  16. package/lib/askAgent/prompt.d.ts +3 -5
  17. package/lib/askAgent/prompt.js +6 -19
  18. package/lib/askAgent/queue.d.ts +11 -21
  19. package/lib/askAgent/queue.js +9 -19
  20. package/lib/askAgent/queuePanel.d.ts +13 -18
  21. package/lib/askAgent/queuePanel.js +15 -37
  22. package/lib/askAgent/targetPicker.d.ts +2 -9
  23. package/lib/askAgent/targetPicker.js +6 -11
  24. package/lib/askAgent/tokens.d.ts +32 -46
  25. package/lib/askAgent/tokens.js +4 -6
  26. package/lib/commandBar/index.d.ts +4 -13
  27. package/lib/commandBar/index.js +21 -39
  28. package/lib/customPanel/index.js +15 -0
  29. package/lib/editorBreadcrumbs/index.d.ts +3 -6
  30. package/lib/editorBreadcrumbs/index.js +10 -6
  31. package/lib/editorBreadcrumbs/widget.d.ts +17 -4
  32. package/lib/editorBreadcrumbs/widget.js +11 -17
  33. package/lib/editorIndent/index.d.ts +4 -12
  34. package/lib/editorIndent/index.js +8 -23
  35. package/lib/fileBrowser/commands.d.ts +28 -19
  36. package/lib/fileBrowser/commands.js +39 -98
  37. package/lib/fileBrowser/contents.d.ts +3 -0
  38. package/lib/fileBrowser/dragAndDrop.d.ts +17 -4
  39. package/lib/fileBrowser/dragAndDrop.js +2 -7
  40. package/lib/fileBrowser/fileBrowser.d.ts +19 -9
  41. package/lib/fileBrowser/fileBrowser.js +68 -216
  42. package/lib/fileBrowser/gitStatus.d.ts +4 -9
  43. package/lib/fileBrowser/gitStatus.js +7 -17
  44. package/lib/fileBrowser/gitignore.d.ts +4 -17
  45. package/lib/fileBrowser/gitignore.js +4 -25
  46. package/lib/fileBrowser/icons.d.ts +7 -17
  47. package/lib/fileBrowser/icons.js +25 -80
  48. package/lib/fileBrowser/index.js +2 -4
  49. package/lib/fileBrowser/widget.d.ts +126 -48
  50. package/lib/fileBrowser/widget.js +89 -4
  51. package/lib/fileTypeIcons/index.js +0 -10
  52. package/lib/git/api.d.ts +5 -13
  53. package/lib/git/api.js +10 -36
  54. package/lib/git/askRequest.d.ts +4 -8
  55. package/lib/git/askRequest.js +6 -20
  56. package/lib/git/commands.d.ts +40 -5
  57. package/lib/git/commands.js +16 -10
  58. package/lib/git/diffModel.js +4 -0
  59. package/lib/git/diffSurface.d.ts +41 -55
  60. package/lib/git/diffSurface.js +42 -117
  61. package/lib/git/diffWidget.d.ts +81 -2
  62. package/lib/git/diffWidget.js +62 -12
  63. package/lib/git/imageDiff.d.ts +5 -6
  64. package/lib/git/imageDiff.js +18 -48
  65. package/lib/git/index.d.ts +0 -3
  66. package/lib/git/index.js +3 -8
  67. package/lib/git/notebookDiff.d.ts +110 -33
  68. package/lib/git/notebookDiff.js +52 -195
  69. package/lib/git/tokens.d.ts +73 -31
  70. package/lib/git/tokens.js +2 -3
  71. package/lib/highlight/index.d.ts +4 -10
  72. package/lib/highlight/index.js +10 -41
  73. package/lib/index.d.ts +0 -9
  74. package/lib/index.js +0 -9
  75. package/lib/launcher/agents.d.ts +55 -51
  76. package/lib/launcher/agents.js +15 -57
  77. package/lib/launcher/availability.d.ts +3 -9
  78. package/lib/launcher/availability.js +3 -9
  79. package/lib/launcher/commands.d.ts +7 -32
  80. package/lib/launcher/commands.js +14 -45
  81. package/lib/launcher/dashboard.d.ts +19 -24
  82. package/lib/launcher/dashboard.js +21 -67
  83. package/lib/launcher/editorRegistry.d.ts +10 -22
  84. package/lib/launcher/editorRegistry.js +14 -18
  85. package/lib/launcher/editors.d.ts +39 -45
  86. package/lib/launcher/editors.js +8 -34
  87. package/lib/launcher/icons.d.ts +0 -12
  88. package/lib/launcher/icons.js +5 -39
  89. package/lib/launcher/index.js +12 -55
  90. package/lib/launcher/invocation.d.ts +4 -10
  91. package/lib/launcher/invocation.js +7 -22
  92. package/lib/launcher/registry.d.ts +9 -7
  93. package/lib/launcher/registry.js +9 -7
  94. package/lib/launcher/tokens.d.ts +10 -22
  95. package/lib/launcher/tokens.js +5 -8
  96. package/lib/menuBar/index.d.ts +3 -10
  97. package/lib/menuBar/index.js +11 -28
  98. package/lib/menus/index.d.ts +3 -9
  99. package/lib/menus/index.js +14 -30
  100. package/lib/omnibox/files.d.ts +2 -4
  101. package/lib/omnibox/files.js +5 -11
  102. package/lib/omnibox/index.d.ts +4 -14
  103. package/lib/omnibox/index.js +9 -27
  104. package/lib/omnibox/model.d.ts +38 -10
  105. package/lib/omnibox/model.js +15 -33
  106. package/lib/omnibox/recents.d.ts +15 -17
  107. package/lib/omnibox/recents.js +12 -17
  108. package/lib/omnibox/tokens.d.ts +5 -10
  109. package/lib/omnibox/tokens.js +2 -6
  110. package/lib/omnibox/widget.d.ts +11 -7
  111. package/lib/omnibox/widget.js +8 -16
  112. package/lib/searchReplace/index.d.ts +4 -20
  113. package/lib/searchReplace/index.js +7 -27
  114. package/lib/showOutput/index.d.ts +3 -12
  115. package/lib/showOutput/index.js +6 -22
  116. package/lib/sidebar/index.d.ts +4 -7
  117. package/lib/sidebar/index.js +5 -12
  118. package/lib/terminalNotifications/index.d.ts +4 -10
  119. package/lib/terminalNotifications/index.js +6 -20
  120. package/lib/terminals/agentTerminals.d.ts +12 -5
  121. package/lib/terminals/agentTerminals.js +25 -44
  122. package/lib/terminals/detection.d.ts +4 -8
  123. package/lib/terminals/detection.js +4 -8
  124. package/lib/terminals/index.d.ts +0 -35
  125. package/lib/terminals/index.js +12 -101
  126. package/lib/terminals/model.d.ts +64 -139
  127. package/lib/terminals/model.js +80 -220
  128. package/lib/terminals/tokens.d.ts +11 -22
  129. package/lib/terminals/tokens.js +2 -2
  130. package/lib/terminals/widget.d.ts +43 -13
  131. package/lib/terminals/widget.js +33 -18
  132. package/lib/topBar/icons.d.ts +3 -8
  133. package/lib/topBar/icons.js +3 -8
  134. package/lib/topBar/index.d.ts +4 -11
  135. package/lib/topBar/index.js +10 -38
  136. package/lib/walkthrough/index.d.ts +4 -9
  137. package/lib/walkthrough/index.js +6 -20
  138. package/lib/walkthrough/panel.d.ts +40 -9
  139. package/lib/walkthrough/panel.js +4 -10
  140. package/package.json +2 -2
  141. package/src/about/icons.ts +0 -5
  142. package/src/about/index.tsx +6 -17
  143. package/src/agentSessions.ts +9 -29
  144. package/src/askAgent/editorSelection.ts +22 -29
  145. package/src/askAgent/icons.ts +2 -3
  146. package/src/askAgent/index.ts +54 -158
  147. package/src/askAgent/popup.tsx +23 -45
  148. package/src/askAgent/prompt.ts +6 -19
  149. package/src/askAgent/queue.ts +13 -24
  150. package/src/askAgent/queuePanel.tsx +21 -46
  151. package/src/askAgent/targetPicker.tsx +5 -15
  152. package/src/askAgent/tokens.ts +32 -46
  153. package/src/commandBar/index.ts +24 -39
  154. package/src/customPanel/index.ts +15 -0
  155. package/src/editorBreadcrumbs/index.ts +10 -6
  156. package/src/editorBreadcrumbs/widget.ts +23 -17
  157. package/src/editorIndent/index.ts +17 -23
  158. package/src/fileBrowser/commands.ts +57 -98
  159. package/src/fileBrowser/contents.ts +3 -0
  160. package/src/fileBrowser/dragAndDrop.ts +17 -7
  161. package/src/fileBrowser/fileBrowser.tsx +84 -223
  162. package/src/fileBrowser/gitStatus.ts +7 -17
  163. package/src/fileBrowser/gitignore.ts +4 -25
  164. package/src/fileBrowser/icons.ts +25 -80
  165. package/src/fileBrowser/index.ts +2 -4
  166. package/src/fileBrowser/widget.tsx +149 -50
  167. package/src/fileTypeIcons/index.ts +0 -10
  168. package/src/git/api.ts +10 -36
  169. package/src/git/askRequest.ts +6 -20
  170. package/src/git/commands.ts +70 -10
  171. package/src/git/diffModel.ts +25 -0
  172. package/src/git/diffSurface.tsx +71 -159
  173. package/src/git/diffWidget.tsx +104 -14
  174. package/src/git/imageDiff.tsx +45 -51
  175. package/src/git/index.ts +3 -8
  176. package/src/git/notebookDiff.tsx +211 -238
  177. package/src/git/tokens.ts +73 -31
  178. package/src/highlight/index.ts +10 -41
  179. package/src/index.ts +0 -9
  180. package/src/launcher/agents.ts +64 -95
  181. package/src/launcher/availability.ts +3 -9
  182. package/src/launcher/commands.ts +14 -51
  183. package/src/launcher/dashboard.tsx +49 -88
  184. package/src/launcher/editorRegistry.ts +21 -29
  185. package/src/launcher/editors.ts +39 -58
  186. package/src/launcher/icons.ts +5 -39
  187. package/src/launcher/index.ts +12 -55
  188. package/src/launcher/invocation.ts +7 -22
  189. package/src/launcher/registry.ts +9 -7
  190. package/src/launcher/tokens.ts +10 -22
  191. package/src/menuBar/index.ts +11 -28
  192. package/src/menus/index.ts +14 -30
  193. package/src/omnibox/files.ts +10 -14
  194. package/src/omnibox/index.ts +9 -27
  195. package/src/omnibox/model.ts +50 -38
  196. package/src/omnibox/recents.ts +17 -22
  197. package/src/omnibox/tokens.ts +5 -10
  198. package/src/omnibox/widget.tsx +14 -19
  199. package/src/searchReplace/index.ts +7 -27
  200. package/src/showOutput/index.ts +6 -22
  201. package/src/sidebar/index.ts +20 -12
  202. package/src/terminalNotifications/index.ts +42 -25
  203. package/src/terminals/agentTerminals.ts +25 -49
  204. package/src/terminals/detection.ts +4 -8
  205. package/src/terminals/index.ts +12 -101
  206. package/src/terminals/model.ts +130 -246
  207. package/src/terminals/tokens.ts +11 -22
  208. package/src/terminals/widget.tsx +48 -31
  209. package/src/topBar/icons.ts +3 -8
  210. package/src/topBar/index.ts +21 -44
  211. package/src/walkthrough/index.ts +6 -20
  212. package/src/walkthrough/panel.ts +40 -10
  213. package/style/about.css +2 -7
  214. package/style/askAgent.css +8 -40
  215. package/style/base.css +9 -45
  216. package/style/chrome.css +108 -308
  217. package/style/commandBar.css +4 -20
  218. package/style/customPanel.css +1 -4
  219. package/style/git.css +22 -184
  220. package/style/highlight.css +1 -3
  221. package/style/launcher.css +6 -70
  222. package/style/omnibox.css +2 -14
  223. package/style/showOutput.css +0 -6
  224. package/style/sidebar.css +29 -9
  225. package/style/tabs.css +5 -13
  226. package/style/terminals.css +6 -53
  227. package/style/topBar.css +2 -22
  228. package/style/walkthrough.css +0 -8
@@ -68,65 +68,116 @@ export class XtralabFileBrowser extends Widget {
68
68
  this._section.addWidget(this._content);
69
69
  layout.addWidget(this._section);
70
70
  }
71
+ /**
72
+ * The contents manager backing the tree.
73
+ */
71
74
  get contentsManager() {
72
75
  return this._contentsManager;
73
76
  }
77
+ /**
78
+ * The toolbar above the tree.
79
+ */
74
80
  get toolbar() {
75
81
  return this._toolbar;
76
82
  }
83
+ /**
84
+ * Canonical selected paths; folder paths carry a trailing slash.
85
+ */
77
86
  get selectedPaths() {
78
87
  return this._selectedPaths;
79
88
  }
89
+ /**
90
+ * A signal emitted when the tree's selection changes.
91
+ */
80
92
  get selectionChanged() {
81
93
  return this._selectionChanged;
82
94
  }
95
+ /**
96
+ * A signal emitted when {@link refresh} is called.
97
+ */
83
98
  get refreshRequested() {
84
99
  return this._refreshRequested;
85
100
  }
101
+ /**
102
+ * A signal emitting a newly-created canonical path for the tree to insert.
103
+ */
86
104
  get pathAdded() {
87
105
  return this._pathAdded;
88
106
  }
107
+ /**
108
+ * A signal emitting a canonical path to load, expand, select, and scroll to.
109
+ */
89
110
  get revealRequested() {
90
111
  return this._revealRequested;
91
112
  }
113
+ /**
114
+ * A signal emitted when the tree should return to the workspace root.
115
+ */
92
116
  get rootRequested() {
93
117
  return this._rootRequested;
94
118
  }
119
+ /**
120
+ * A signal emitted when every expanded folder should collapse.
121
+ */
95
122
  get collapseAllRequested() {
96
123
  return this._collapseAllRequested;
97
124
  }
125
+ /**
126
+ * Whether the filter box above the tree is shown.
127
+ */
98
128
  get fileFilterVisible() {
99
129
  return this._fileFilterVisible;
100
130
  }
131
+ /**
132
+ * A signal emitted when {@link fileFilterVisible} changes.
133
+ */
101
134
  get fileFilterVisibleChanged() {
102
135
  return this._fileFilterVisibleChanged;
103
136
  }
104
137
  /**
105
- * Update the cached selection. Called from the React tree when the
106
- * underlying `@pierre/trees` model emits a selection change.
138
+ * Update the cached selection from the React tree.
107
139
  */
108
140
  updateSelection(paths) {
109
141
  this._selectedPaths = paths;
110
142
  this._selectionChanged.emit(paths);
111
143
  }
144
+ /**
145
+ * Trigger a refresh of every loaded directory in the tree.
146
+ */
112
147
  refresh() {
113
148
  this._refreshRequested.emit();
114
149
  }
150
+ /**
151
+ * Notify the tree that a new canonical path was created.
152
+ */
115
153
  notifyPathAdded(canonicalPath) {
116
154
  this._pathAdded.emit(canonicalPath);
117
155
  }
156
+ /**
157
+ * Reveal a non-empty canonical path in the tree; use {@link scrollToRoot}
158
+ * for the workspace root, which has no tree row of its own.
159
+ */
118
160
  reveal(canonicalPath) {
119
161
  if (canonicalPath.length === 0) {
120
162
  throw new Error('XtralabFileBrowser.reveal requires a non-empty canonical path; use scrollToRoot for the workspace root.');
121
163
  }
122
164
  this._revealRequested.emit(canonicalPath);
123
165
  }
166
+ /**
167
+ * Return to the workspace root: clear the selection and scroll to the top.
168
+ */
124
169
  scrollToRoot() {
125
170
  this._rootRequested.emit();
126
171
  }
172
+ /**
173
+ * Ask the tree to collapse every currently expanded folder.
174
+ */
127
175
  collapseAll() {
128
176
  this._collapseAllRequested.emit();
129
177
  }
178
+ /**
179
+ * Show or hide the filter box above the tree.
180
+ */
130
181
  setFileFilterVisible(visible) {
131
182
  if (this._fileFilterVisible === visible) {
132
183
  return;
@@ -134,24 +185,45 @@ export class XtralabFileBrowser extends Widget {
134
185
  this._fileFilterVisible = visible;
135
186
  this._fileFilterVisibleChanged.emit(visible);
136
187
  }
188
+ /**
189
+ * Toggle the filter box above the tree.
190
+ */
137
191
  toggleFileFilter() {
138
192
  this.setFileFilterVisible(!this._fileFilterVisible);
139
193
  }
194
+ /**
195
+ * The DOM node of the movable "Files" section.
196
+ */
140
197
  get sectionNode() {
141
198
  return this._section.node;
142
199
  }
200
+ /**
201
+ * Whether the panel currently holds no sections, its own tree included.
202
+ */
143
203
  get isEmpty() {
144
204
  return this._panelLayout.widgets.length === 0;
145
205
  }
206
+ /**
207
+ * A signal emitted when a section is added to or removed from the panel.
208
+ */
146
209
  get contentChanged() {
147
210
  return this._contentChanged;
148
211
  }
212
+ /**
213
+ * A signal emitting each section entry announced to the move plugin.
214
+ */
149
215
  get sectionAdded() {
150
216
  return this._sectionAdded;
151
217
  }
218
+ /**
219
+ * The accordion hosting the sections, or `null` while the tree sits alone.
220
+ */
152
221
  get accordionPanel() {
153
222
  return this._accordion;
154
223
  }
224
+ /**
225
+ * Section widgets hosted from other panels; the tree section is excluded.
226
+ */
155
227
  get sections() {
156
228
  if (!this._accordion) {
157
229
  return [];
@@ -173,6 +245,10 @@ export class XtralabFileBrowser extends Widget {
173
245
  ]
174
246
  : [];
175
247
  }
248
+ /**
249
+ * Detach and return the tree section so the move plugin can re-host it;
250
+ * `null` for any other id or when the section is already away from home.
251
+ */
176
252
  removeSectionById(sectionId) {
177
253
  if (sectionId !== TREE_SECTION_ID || !this._isSectionHome()) {
178
254
  return null;
@@ -188,6 +264,9 @@ export class XtralabFileBrowser extends Widget {
188
264
  this._contentChanged.emit();
189
265
  return this._section;
190
266
  }
267
+ /**
268
+ * Re-attach the tree section after a move back to this panel.
269
+ */
191
270
  reinsertSection(widget) {
192
271
  if (this._accordion) {
193
272
  this._accordion.insertWidget(0, widget);
@@ -228,6 +307,10 @@ export class XtralabFileBrowser extends Widget {
228
307
  }
229
308
  this._contentChanged.emit();
230
309
  }
310
+ /**
311
+ * Remove a hosted section; the accordion is torn down once only the
312
+ * panel's own tree section (or nothing) remains.
313
+ */
231
314
  removeSectionWidget(widget) {
232
315
  if (!this._accordion || widget.parent !== this._accordion) {
233
316
  return;
@@ -262,14 +345,16 @@ export class XtralabFileBrowser extends Widget {
262
345
  }
263
346
  }
264
347
  /**
265
- * The React-rendered region of the file browser. Lives inside the host
266
- * widget below the toolbar and renders the actual tree.
348
+ * The React-rendered region below the toolbar that hosts the actual tree.
267
349
  */
268
350
  class XtralabFileTreeContent extends ReactWidget {
269
351
  constructor(options) {
270
352
  super();
271
353
  this._options = options;
272
354
  }
355
+ /**
356
+ * Render the file browser React component.
357
+ */
273
358
  render() {
274
359
  return (React.createElement(FileBrowserComponent, { contentsManager: this._options.contentsManager, docManager: this._options.docManager, onOpenFile: this._options.onOpenFile, translator: this._options.translator, widget: this._options.browser }));
275
360
  }
@@ -11,12 +11,8 @@ function representativePath(fileType) {
11
11
  if (extension === undefined || extension === '') {
12
12
  return null;
13
13
  }
14
- // Extensions are stored with a leading dot (e.g. `.py`, `.tar.gz`).
15
14
  return `file${extension.startsWith('.') ? extension : `.${extension}`}`;
16
15
  }
17
- /**
18
- * Point a file type's icon at the tree glyph for its extension.
19
- */
20
16
  function applyTreeIcon(fileType) {
21
17
  const path = representativePath(fileType);
22
18
  if (path === null) {
@@ -62,9 +58,6 @@ const EXTRA_FILE_TYPE_EXTENSIONS = [
62
58
  '.graphql',
63
59
  '.wasm'
64
60
  ];
65
- /**
66
- * Register icon-only file types for unclaimed source extensions.
67
- */
68
61
  function registerExtraFileTypes(docRegistry) {
69
62
  for (const extension of EXTRA_FILE_TYPE_EXTENSIONS) {
70
63
  const icon = getSpecificTreeIcon(`file${extension}`);
@@ -100,7 +93,6 @@ const plugin = {
100
93
  applyTreeIcon(fileType);
101
94
  }
102
95
  registerExtraFileTypes(docRegistry);
103
- // Pick up file types registered after this plugin activates.
104
96
  docRegistry.changed.connect((_, args) => {
105
97
  if (args.type === 'fileType' &&
106
98
  args.change === 'added' &&
@@ -120,8 +112,6 @@ const plugin = {
120
112
  }
121
113
  };
122
114
  setIcon();
123
- // Keep the tab icon right after a rename, and release the listener
124
- // when the document closes.
125
115
  widget.context.pathChanged.connect(setIcon);
126
116
  widget.disposed.connect(() => {
127
117
  widget.context.pathChanged.disconnect(setIcon);
package/lib/git/api.d.ts CHANGED
@@ -1,24 +1,16 @@
1
1
  import { GitReference, IFileChange, IGitContentResult, IGitStatusFile, IGitStatusResult } from './tokens';
2
2
  /**
3
- * Fetch `git status --porcelain` for the repository the server resolves at
4
- * `repoPath`. When `repoPath` is the empty string, git resolves the repo
5
- * from the JupyterLab server's root directory.
3
+ * Fetch `git status --porcelain` for the repo at `repoPath` (empty string
4
+ * resolves from the server's root directory).
6
5
  */
7
6
  export declare function status(repoPath: string): Promise<IGitStatusResult>;
8
7
  /**
9
- * Fetch a file's contents at a particular git reference. `filename` is the
10
- * file's path relative to the git repository root (matching the `to` field
11
- * of {@link status}'s response).
8
+ * Fetch a file's contents at a git reference; `filename` is relative to the
9
+ * git repository root.
12
10
  */
13
11
  export declare function content(repoPath: string, filename: string, reference: GitReference): Promise<IGitContentResult>;
14
12
  /**
15
13
  * Expand the porcelain `files` array into one entry per logical change.
16
- * A single porcelain row may map to two `IFileChange` rows (a file that's
17
- * both staged and modified again in the worktree); callers that just want
18
- * a flat list of all changes — without any staged-vs-unstaged grouping —
19
- * can use this helper.
20
- *
21
- * Provided as a manual concat rather than `Array.prototype.flatMap` so we
22
- * don't pin our `tsconfig.lib` to ES2019.
14
+ * Manual concat rather than `flatMap` so `tsconfig.lib` need not be ES2019.
23
15
  */
24
16
  export declare function expandStatusFiles(files: IGitStatusFile[]): IFileChange[];
package/lib/git/api.js CHANGED
@@ -1,24 +1,10 @@
1
1
  import { URLExt } from '@jupyterlab/coreutils';
2
2
  import { ServerConnection } from '@jupyterlab/services';
3
- /**
4
- * Root URL segment used by the `jupyterlab_git` server extension. Every
5
- * endpoint hangs off this prefix; the `<repoPath>` between it and the
6
- * endpoint suffix is the JupyterLab server-relative path of the git
7
- * repository (URL-encoded). For an empty `repoPath` the URL collapses to
8
- * `/git/<endpoint>` — a shape git's URL routing also accepts.
9
- */
10
3
  const GIT_NAMESPACE = 'git';
11
- /**
12
- * Issue a `POST` against a `jupyterlab_git` endpoint that takes a `<path>`
13
- * prefix (e.g. `/git/<path>/status`). The response body is decoded as JSON;
14
- * non-2xx responses are surfaced via the JupyterLab `ServerConnection`
15
- * machinery so callers can show their `message` field as-is.
16
- */
17
4
  async function postWithPath(endpoint, repoPath, body) {
18
5
  var _a, _b;
19
6
  const settings = ServerConnection.makeSettings();
20
- // `URLExt.encodeParts` encodes each path segment but preserves slashes
21
- // between them — the server expects the path to look like a posix path.
7
+ // encodeParts keeps the slashes the server's posix-path routing expects.
22
8
  const encodedPath = repoPath.length > 0 ? URLExt.encodeParts(repoPath) : '';
23
9
  const url = URLExt.join(settings.baseUrl, GIT_NAMESPACE, encodedPath, endpoint);
24
10
  const init = {
@@ -33,7 +19,7 @@ async function postWithPath(endpoint, repoPath, body) {
33
19
  data = JSON.parse(text);
34
20
  }
35
21
  catch (_c) {
36
- // Fall through into the error handling below.
22
+ // Non-JSON bodies still surface via the ResponseError below.
37
23
  }
38
24
  }
39
25
  if (!response.ok) {
@@ -43,17 +29,15 @@ async function postWithPath(endpoint, repoPath, body) {
43
29
  return (data !== null && data !== void 0 ? data : {});
44
30
  }
45
31
  /**
46
- * Fetch `git status --porcelain` for the repository the server resolves at
47
- * `repoPath`. When `repoPath` is the empty string, git resolves the repo
48
- * from the JupyterLab server's root directory.
32
+ * Fetch `git status --porcelain` for the repo at `repoPath` (empty string
33
+ * resolves from the server's root directory).
49
34
  */
50
35
  export async function status(repoPath) {
51
36
  return postWithPath('status', repoPath, {});
52
37
  }
53
38
  /**
54
- * Fetch a file's contents at a particular git reference. `filename` is the
55
- * file's path relative to the git repository root (matching the `to` field
56
- * of {@link status}'s response).
39
+ * Fetch a file's contents at a git reference; `filename` is relative to the
40
+ * git repository root.
57
41
  */
58
42
  export async function content(repoPath, filename, reference) {
59
43
  return postWithPath('content', repoPath, {
@@ -63,13 +47,7 @@ export async function content(repoPath, filename, reference) {
63
47
  }
64
48
  /**
65
49
  * Expand the porcelain `files` array into one entry per logical change.
66
- * A single porcelain row may map to two `IFileChange` rows (a file that's
67
- * both staged and modified again in the worktree); callers that just want
68
- * a flat list of all changes — without any staged-vs-unstaged grouping —
69
- * can use this helper.
70
- *
71
- * Provided as a manual concat rather than `Array.prototype.flatMap` so we
72
- * don't pin our `tsconfig.lib` to ES2019.
50
+ * Manual concat rather than `flatMap` so `tsconfig.lib` need not be ES2019.
73
51
  */
74
52
  export function expandStatusFiles(files) {
75
53
  const result = [];
@@ -81,16 +59,12 @@ export function expandStatusFiles(files) {
81
59
  return result;
82
60
  }
83
61
  /**
84
- * Translate one entry in the porcelain `files` array into the panel's
85
- * preferred shape. A single porcelain entry may represent up to two changes
86
- * (one in the index, one in the worktree); we emit one {@link IFileChange}
87
- * per non-empty side, so a "modified-staged-and-then-modified-again" file
88
- * shows up twice in the panel — once under "Staged Changes" and once under
89
- * "Changes" — matching the layout the user sees in VS Code.
62
+ * Map one porcelain entry to up to two {@link IFileChange} rows — one per
63
+ * non-empty index/worktree side — so a staged-then-modified-again file
64
+ * appears under both groups, as in VS Code.
90
65
  */
91
66
  function porcelainToFileChanges(file) {
92
67
  const result = [];
93
- // Untracked files are reported with `??` and only appear under "Changes".
94
68
  if (file.x === '?' && file.y === '?') {
95
69
  return [
96
70
  {
@@ -4,14 +4,10 @@ import type { IAskAgentRequest } from '../askAgent/tokens';
4
4
  import type { IXtralabDiffModel } from './diffWidget';
5
5
  /**
6
6
  * Build the ask-agent request for a line range selected in a git diff.
7
- *
8
- * The range's `side` decides which file version the line numbers (and the
9
- * embedded snippet) refer to: `deletions` reads from the reference text,
10
- * anything else — including the sideless context rows of a unified diff,
11
- * whose gutter shows new-side numbers — reads from the challenger text. A
12
- * gutter drag that crosses the two split columns has endpoints in different
13
- * line-number spaces, so it is described textually instead of as a numeric
14
- * range.
7
+ * `deletions` ranges index the reference text; other ranges — including
8
+ * sideless unified context rows, whose gutter shows new-side numbers —
9
+ * index the challenger. A drag across the two split columns mixes
10
+ * line-number spaces, so it is described textually instead of numerically.
15
11
  */
16
12
  export declare function buildDiffAskRequest(options: {
17
13
  model: IXtralabDiffModel;
@@ -1,9 +1,7 @@
1
1
  import { Git } from '@jupyterlab/git';
2
2
  /**
3
- * Agent-facing name of a diff content source: the special refs get plain
4
- * words, a git ref string is used verbatim, anything else falls back to the
5
- * side name. English on purpose — this ends up in the agent prompt, not in
6
- * the UI.
3
+ * Agent-facing name of a diff content source. English on purpose — this
4
+ * ends up in the agent prompt, not in the UI.
7
5
  */
8
6
  function describeSource(source, fallback) {
9
7
  if (source === Git.Diff.SpecialRef.WORKING) {
@@ -23,9 +21,6 @@ function describeSource(source, fallback) {
23
21
  function sideName(side) {
24
22
  return side === 'deletions' ? 'old side' : 'new side';
25
23
  }
26
- /**
27
- * Extract lines `startLine`–`endLine` (1-indexed, inclusive) from `text`.
28
- */
29
24
  function sliceLines(text, startLine, endLine) {
30
25
  return text
31
26
  .split('\n')
@@ -34,14 +29,10 @@ function sliceLines(text, startLine, endLine) {
34
29
  }
35
30
  /**
36
31
  * Build the ask-agent request for a line range selected in a git diff.
37
- *
38
- * The range's `side` decides which file version the line numbers (and the
39
- * embedded snippet) refer to: `deletions` reads from the reference text,
40
- * anything else — including the sideless context rows of a unified diff,
41
- * whose gutter shows new-side numbers — reads from the challenger text. A
42
- * gutter drag that crosses the two split columns has endpoints in different
43
- * line-number spaces, so it is described textually instead of as a numeric
44
- * range.
32
+ * `deletions` ranges index the reference text; other ranges — including
33
+ * sideless unified context rows, whose gutter shows new-side numbers —
34
+ * index the challenger. A drag across the two split columns mixes
35
+ * line-number spaces, so it is described textually instead of numerically.
45
36
  */
46
37
  export function buildDiffAskRequest(options) {
47
38
  var _a, _b, _c;
@@ -75,14 +66,9 @@ export function buildDiffAskRequest(options) {
75
66
  ...base,
76
67
  startLine,
77
68
  endLine,
78
- // Only new-side lines of a working-tree diff index the file on disk;
79
- // old-side and historical line numbers must not be used to highlight
80
- // the working file.
81
69
  linesInWorkingFile: !isOld && model.challenger.source === Git.Diff.SpecialRef.WORKING,
82
70
  text: sliceLines(isOld ? oldText : newText, startLine, endLine),
83
71
  location: `the ${sideName(startSide)} (${ref}) of the current git diff`,
84
- // New-side lines read as the file's current content, so only old-side
85
- // ranges need a clarifying tag in the popup header.
86
72
  ...(isOld ? { note: trans.__('old version') } : {})
87
73
  },
88
74
  anchor
@@ -17,15 +17,24 @@ export declare namespace CommandIDs {
17
17
  * Argument shapes used by {@link CommandIDs.openDiff}.
18
18
  */
19
19
  export declare namespace CommandArguments {
20
+ /**
21
+ * The arguments for the open-diff command.
22
+ */
20
23
  interface IOpenDiff {
24
+ /**
25
+ * The server-relative path of the repository containing the change.
26
+ */
21
27
  repoPath: string;
28
+ /**
29
+ * The file change to show.
30
+ */
22
31
  change: IFileChange;
32
+ /**
33
+ * Whether to open the diff as a pinned tab instead of the shared preview.
34
+ */
23
35
  pin?: boolean;
24
36
  }
25
37
  }
26
- /**
27
- * Widget id of the single, reused preview diff tab.
28
- */
29
38
  export declare const PREVIEW_DIFF_WIDGET_ID = "xtralab:diff:preview";
30
39
  /**
31
40
  * Deterministic widget id for a pinned file/group pair.
@@ -36,18 +45,42 @@ export declare function pinnedDiffWidgetId(change: IFileChange): string;
36
45
  */
37
46
  export declare class DiffMainAreaWidget extends MainAreaWidget<XtralabDiffWidget> {
38
47
  constructor(options: MainAreaWidget.IOptions<XtralabDiffWidget>, change: IFileChange, pinned: boolean, trans: TranslationBundle);
48
+ /**
49
+ * The file change currently displayed.
50
+ */
39
51
  get change(): IFileChange;
52
+ /**
53
+ * Whether the widget is pinned rather than the shared preview.
54
+ */
40
55
  get pinned(): boolean;
56
+ /**
57
+ * Pin the widget; a no-op when already pinned.
58
+ */
41
59
  pin(): void;
60
+ /**
61
+ * A signal emitted when the widget becomes pinned.
62
+ */
42
63
  get pinnedChanged(): ISignal<this, boolean>;
64
+ /**
65
+ * Display a new file change and update the tab title, caption, and icon.
66
+ */
43
67
  setChange(repoPath: string, change: IFileChange): void;
44
68
  private _change;
45
69
  private _pinned;
46
70
  private _trans;
47
71
  private _pinnedChanged;
48
72
  }
73
+ /**
74
+ * The options for {@link registerGitCommands}.
75
+ */
49
76
  interface IRegisterGitCommandsOptions {
77
+ /**
78
+ * The JupyterLab application, providing the commands registry and shell.
79
+ */
50
80
  app: JupyterFrontEnd;
81
+ /**
82
+ * Theme manager the diff views follow; may be `null`.
83
+ */
51
84
  themeManager: IThemeManager | null;
52
85
  /**
53
86
  * Contents manager used to write hunk-discard results.
@@ -73,11 +106,13 @@ interface IRegisterGitCommandsOptions {
73
106
  * Look up an already-open diff widget for a file change.
74
107
  */
75
108
  findDiff(change: IFileChange, pin?: boolean): DiffMainAreaWidget | undefined;
109
+ /**
110
+ * Callback invoked when a preview diff widget becomes pinned.
111
+ */
76
112
  onPinned(widget: DiffMainAreaWidget): void;
77
113
  }
78
114
  /**
79
- * Register the launcher's git diff command on the application command
80
- * registry.
115
+ * Register the launcher's git diff command.
81
116
  */
82
117
  export declare function registerGitCommands(options: IRegisterGitCommandsOptions): void;
83
118
  export {};
@@ -11,9 +11,6 @@ export var CommandIDs;
11
11
  (function (CommandIDs) {
12
12
  CommandIDs.openDiff = 'xtralab:git:open-diff';
13
13
  })(CommandIDs || (CommandIDs = {}));
14
- /**
15
- * Widget id of the single, reused preview diff tab.
16
- */
17
14
  export const PREVIEW_DIFF_WIDGET_ID = 'xtralab:diff:preview';
18
15
  /**
19
16
  * Deterministic widget id for a pinned file/group pair.
@@ -38,12 +35,21 @@ export class DiffMainAreaWidget extends MainAreaWidget {
38
35
  this._pinned = pinned;
39
36
  this._trans = trans;
40
37
  }
38
+ /**
39
+ * The file change currently displayed.
40
+ */
41
41
  get change() {
42
42
  return this._change;
43
43
  }
44
+ /**
45
+ * Whether the widget is pinned rather than the shared preview.
46
+ */
44
47
  get pinned() {
45
48
  return this._pinned;
46
49
  }
50
+ /**
51
+ * Pin the widget; a no-op when already pinned.
52
+ */
47
53
  pin() {
48
54
  if (this._pinned) {
49
55
  return;
@@ -51,9 +57,15 @@ export class DiffMainAreaWidget extends MainAreaWidget {
51
57
  this._pinned = true;
52
58
  this._pinnedChanged.emit(true);
53
59
  }
60
+ /**
61
+ * A signal emitted when the widget becomes pinned.
62
+ */
54
63
  get pinnedChanged() {
55
64
  return this._pinnedChanged;
56
65
  }
66
+ /**
67
+ * Display a new file change and update the tab title, caption, and icon.
68
+ */
57
69
  setChange(repoPath, change) {
58
70
  this._change = change;
59
71
  this.content.setModel(fileChangeToDiffModel(repoPath, change));
@@ -62,9 +74,6 @@ export class DiffMainAreaWidget extends MainAreaWidget {
62
74
  this.title.icon = getTreeIcon(change.path);
63
75
  }
64
76
  }
65
- /**
66
- * Build the launcher's diff tab around the shared diff widget.
67
- */
68
77
  function createDiffWidget(options) {
69
78
  var _a;
70
79
  const { repoPath, change, themeManager, contentsManager, rendermime, askAgent, trans } = options;
@@ -89,7 +98,6 @@ function createDiffWidget(options) {
89
98
  }
90
99
  widget.toolbar.addItem('pin', pinButton);
91
100
  addDiffToolbarItems(widget.toolbar, content);
92
- // Keep chrome visible only while there is a relevant toolbar control.
93
101
  const syncToolbarVisibility = () => {
94
102
  if (widget.isDisposed) {
95
103
  return;
@@ -115,7 +123,6 @@ function createDiffWidget(options) {
115
123
  }
116
124
  syncToolbarVisibility();
117
125
  };
118
- // Auto-close once a discard leaves nothing to show.
119
126
  const onEmptied = () => {
120
127
  if (!widget.isDisposed) {
121
128
  widget.close();
@@ -135,8 +142,7 @@ function createDiffWidget(options) {
135
142
  return widget;
136
143
  }
137
144
  /**
138
- * Register the launcher's git diff command on the application command
139
- * registry.
145
+ * Register the launcher's git diff command.
140
146
  */
141
147
  export function registerGitCommands(options) {
142
148
  const { app, themeManager, contentsManager, rendermime, askAgent, trans, trackDiff, findDiff, onPinned } = options;
@@ -40,6 +40,10 @@ function referenceSource(ref) {
40
40
  class FileChangeDiffModel {
41
41
  constructor(repoPath, change) {
42
42
  var _a;
43
+ /**
44
+ * A signal emitted when the reference or challenger changes; this static
45
+ * model never emits it.
46
+ */
43
47
  this.changed = new Signal(this);
44
48
  const { oldRef, newRef } = resolveReferences(change);
45
49
  // Renames compare the new path against the old path's previous content.