notebook icon indicating copy to clipboard operation
notebook copied to clipboard

`<a name="...">` no longer rendered in Markdown cells

Open orionlee opened this issue 2 months ago • 11 comments

Description

<a name="...">no longer renders in markdown cells in v7.4.7 .

It works in the previous version I used, v7.1.3 (w/ jupyterlab 4.1.6), and older versions. It is as if some sanitizer logic too aggressively strips out name attribute.

Reproduce

Enter the following in markdown cell

# Section Foo
<a name="foo">

In v7.4.7, the <a> is rendered as <a rel="nofollow" target="_self"></a> , with name stripped, effectively making the section anchor useless.

Expected behavior

The name attribute of <a> should be retained.

Context

  • Operating System and version: Windows 11
  • Browser and version: Chrome 141
  • Jupyter Notebook version: v7.4.7 (jupyterlab 4.4.10)

I use <a name="..."> in markdown cells to jump to specific section of a notebook.

orionlee avatar Oct 28 '25 21:10 orionlee

Unfortunately, due to vulnerabilities in third party dependencies we had to strip these attributes to prevent exploitation of user data. The related advisory is GHSA-9q39-rmj3-p4r2.

effectively making the section anchor useless.

Scrolling to anchor targets based on id (not name) should work in the latest versions thanks to:

  • https://github.com/jupyterlab/jupyterlab/pull/17727

Maybe we should also handle name? CC @brichet for thoughts as author of the above-mentioned PR.

Also, you can change the sanitizer's behaviour in Settings UI in the Sanitizer section, or with JSON settings overrides with:

{
  "@jupyterlab/apputils-extension:sanitizer": {
    "allowNamedProperties": true
  }
}

For more information see:

  • https://github.com/jupyterlab/jupyterlab/issues/16937
  • https://github.com/jupyterlab/jupyterlab/issues/17496

krassowski avatar Oct 29 '25 09:10 krassowski

krassowski, thanks for your explanation!

Can I assume then id will be mapped to data-jupyter-id in the DOM going forward?

In my use case, the scrolling is done in javascript, so I'd need something like document.querySelector('a[data-jupyter-id="foo_a"]').scrollIntoView().

orionlee avatar Oct 29 '25 15:10 orionlee

I think you can assume that since this is documented in https://jupyterlab.readthedocs.io/en/latest/getting_started/faq.html#attributes-sanitization

krassowski avatar Oct 29 '25 16:10 krassowski

Thanks! For my use case, I could drop name and migrate to <a id="..."> .

But then I run into a new issue. Javascript codes such as document.querySelector('a[data-jupyter-id="foo_a"]').scrollIntoView() only work intermittently. Specifically, the codes seem to work only when the relevant DOM is on the screen, (and might or might not work when the relevant DOM is off screen), largely defeating the purpose (of quickly jumping to relevant section of a long notebook).

It is as if the DOM elements are dynamically created / destroyed by the latest Jupyter (notebook 7.4.7). The logic used to work in the previous version I use (notebook v7.1.3)

Any thoughts on if there is a supported way to scrolling in javascript (embedded in a notebook)? (If not, I would drop the issue and rely on the existing Table of Contents pane. My use case is probably too niche to spend too much time on it.)

orionlee avatar Oct 29 '25 19:10 orionlee

Could you use location.href = '#foo_a'?

There should also be a way to scroll to the cell containing the anchor using public API if you are writing an extension.

krassowski avatar Oct 30 '25 16:10 krassowski

location.href = '#foo_a' doesn't work for me either.

At this point, I think I will stick with the built-in Table of Contents pane, instead of digging it further. The built-in Table of Contents pane does most of what I need (except some customized features such as keyboard shortcuts) anyway.

Thanks for taking the time and looking into it!

orionlee avatar Oct 30 '25 21:10 orionlee

Maybe we should also handle name?

At first glance, I don't see any technical blocker to handle the name attribute, that could be renamed data-jupyter-name. I can take a look at it if there is this is expected.

brichet avatar Nov 03 '25 12:11 brichet

For handling name attribute, it could be helpful in general, but would not help my specific case. See https://github.com/jupyter/notebook/issues/7754#issuecomment-3463446995 (DOM access via Javascript no longer appears to be reliable in the latest notebook)

orionlee avatar Nov 03 '25 16:11 orionlee

location.href = '#foo_a' doesn't work for me either.

It worked for me when I tired (assuming there is something like <a id="foo_a">test</a>.

DOM access via Javascript no longer appears to be reliable in the latest notebook

You would need to use public API to interact with notebook cells, the direct manipulation of notebook DOM was never part of the API contract. To be precise I believe access still works, just scrolling is implemented differently in full windowing mode. However, this all depends on the windowing mode, so depending on what you want to achieve you may just switch to latest beta/RC (lab 4.5.0, notebook 7.5.0) where the default windowing mode makes smaller changes to the underlying DOM.

krassowski avatar Nov 03 '25 16:11 krassowski

In my notebook, location.href ="#foo_a" only works intermittently. Anyway, it is a different from the initial issue of <a name=...>. I'll look into it later (and use the built-in table-of-contents pane in the meantime).

For this github issue, I'm okay of closing it, but leave it open in case someone wants to use it to keep track of the issue that <a name="..."> is not rendered.

orionlee avatar Nov 03 '25 21:11 orionlee

location.href = '#foo_a' doesn't work for me either.

It worked for me when I tired (assuming there is something like <a id="foo_a">test</a>.

DOM access via Javascript no longer appears to be reliable in the latest notebook

You would need to use public API to interact with notebook cells, the direct manipulation of notebook DOM was never part of the API contract. To be precise I believe access still works, just scrolling is implemented differently in full windowing mode. However, this all depends on the windowing mode, so depending on what you want to achieve you may just switch to latest beta/RC (lab 4.5.0, notebook 7.5.0) where the default windowing mode makes smaller changes to the underlying DOM.

The suggestion of using <a id="foo"></a> worked consistently for me. Thanks for providing a workaround.

rodrigosf672 avatar Nov 07 '25 06:11 rodrigosf672