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