@jupyterlab/notebook 4.4.5 → 4.4.7

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/src/widget.ts CHANGED
@@ -1399,6 +1399,7 @@ class ScrollbarItem implements WindowedList.IRenderer.IScrollbarItem {
1399
1399
  'trusted' | 'isDirty' | 'executionCount' | 'executionState'
1400
1400
  >
1401
1401
  ) => {
1402
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
1402
1403
  switch (change.name) {
1403
1404
  case 'executionCount':
1404
1405
  case 'executionState':
@@ -2061,9 +2062,9 @@ export class Notebook extends StaticNotebook {
2061
2062
 
2062
2063
  const parts = cleanedFragment.split('=');
2063
2064
  if (parts.length === 1) {
2064
- // Default to heading if no prefix is given.
2065
+ // Default to legacy if no prefix is given.
2065
2066
  return {
2066
- kind: 'heading',
2067
+ kind: 'legacy',
2067
2068
  value: cleanedFragment
2068
2069
  };
2069
2070
  }
@@ -2093,11 +2094,14 @@ export class Notebook extends StaticNotebook {
2093
2094
  case 'cell-id':
2094
2095
  result = this._findCellById(parsedFragment.value);
2095
2096
  break;
2097
+ case 'legacy':
2098
+ result = await this._findLegacy(parsedFragment.value);
2099
+ break;
2096
2100
  default:
2097
2101
  console.warn(
2098
2102
  `Unknown target type for URI fragment ${fragment}, interpreting as a heading`
2099
2103
  );
2100
- result = await this._findHeading(
2104
+ result = await this._findLegacy(
2101
2105
  parsedFragment.kind + '=' + parsedFragment.value
2102
2106
  );
2103
2107
  break;
@@ -2115,15 +2119,9 @@ export class Notebook extends StaticNotebook {
2115
2119
  if (element == null) {
2116
2120
  element = cell.node;
2117
2121
  }
2118
- const widgetBox = this.node.getBoundingClientRect();
2119
- const elementBox = element.getBoundingClientRect();
2120
2122
 
2121
- if (
2122
- elementBox.top > widgetBox.bottom ||
2123
- elementBox.bottom < widgetBox.top
2124
- ) {
2125
- element.scrollIntoView({ block: 'center' });
2126
- }
2123
+ // Scroll notebook to set the target on top.
2124
+ element.scrollIntoView();
2127
2125
  }
2128
2126
 
2129
2127
  /**
@@ -2547,7 +2545,9 @@ export class Notebook extends StaticNotebook {
2547
2545
  /**
2548
2546
  * Find heading with given ID in any of the cells.
2549
2547
  */
2550
- async _findHeading(queryId: string): Promise<Private.IScrollTarget | null> {
2548
+ private async _findHeading(
2549
+ queryId: string
2550
+ ): Promise<Private.IScrollTarget | null> {
2551
2551
  // Loop on cells, get headings and search for first matching id.
2552
2552
  for (let cellIdx = 0; cellIdx < this.widgets.length; cellIdx++) {
2553
2553
  const cell = this.widgets[cellIdx];
@@ -2578,8 +2578,12 @@ export class Notebook extends StaticNotebook {
2578
2578
  break;
2579
2579
  }
2580
2580
  if (id === queryId) {
2581
+ const attribute =
2582
+ this.rendermime.sanitizer.allowNamedProperties ?? false
2583
+ ? 'id'
2584
+ : 'data-jupyter-id';
2581
2585
  const element = this.node.querySelector(
2582
- `h${heading.level}[id="${CSS.escape(id)}"]`
2586
+ `h${heading.level}[${attribute}="${CSS.escape(id)}"]`
2583
2587
  ) as HTMLElement;
2584
2588
 
2585
2589
  return {
@@ -2595,7 +2599,7 @@ export class Notebook extends StaticNotebook {
2595
2599
  /**
2596
2600
  * Find cell by its unique ID.
2597
2601
  */
2598
- _findCellById(queryId: string): Private.IScrollTarget | null {
2602
+ private _findCellById(queryId: string): Private.IScrollTarget | null {
2599
2603
  for (let cellIdx = 0; cellIdx < this.widgets.length; cellIdx++) {
2600
2604
  const cell = this.widgets[cellIdx];
2601
2605
  if (cell.model.id === queryId) {
@@ -2607,6 +2611,40 @@ export class Notebook extends StaticNotebook {
2607
2611
  return null;
2608
2612
  }
2609
2613
 
2614
+ /**
2615
+ * Find anchor target by any ID in any of the cell.
2616
+ */
2617
+ private async _findLegacy(
2618
+ queryId: string
2619
+ ): Promise<Private.IScrollTarget | null> {
2620
+ // Loop on cells, search for first matching id.
2621
+ for (let cellIdx = 0; cellIdx < this.widgets.length; cellIdx++) {
2622
+ const cell = this.widgets[cellIdx];
2623
+ if (
2624
+ cell.model.type === 'raw' ||
2625
+ (cell.model.type === 'markdown' && !(cell as MarkdownCell).rendered)
2626
+ ) {
2627
+ // Bail early
2628
+ continue;
2629
+ }
2630
+
2631
+ const attribute =
2632
+ this.rendermime.sanitizer.allowNamedProperties ?? false
2633
+ ? 'id'
2634
+ : 'data-jupyter-id';
2635
+ const element = cell.node.querySelector(
2636
+ `[${attribute}="${CSS.escape(queryId)}"]`
2637
+ );
2638
+ if (element !== null) {
2639
+ return {
2640
+ cell,
2641
+ element: element as HTMLElement
2642
+ };
2643
+ }
2644
+ }
2645
+ return null;
2646
+ }
2647
+
2610
2648
  /**
2611
2649
  * Handle `contextmenu` event.
2612
2650
  */
@@ -3375,7 +3413,7 @@ namespace Private {
3375
3413
  /**
3376
3414
  * The kind of notebook element targeted by the fragment identifier.
3377
3415
  */
3378
- kind: 'heading' | 'cell-id';
3416
+ kind: 'legacy' | 'heading' | 'cell-id';
3379
3417
  /*
3380
3418
  * The value of the fragment query.
3381
3419
  */