In-page links?

Heya,

I have a very long document. I want to use in-page links between my content and footnotes (bibliography). I’m attempting to use Markdown-style links - i.e. [link text](#footnote_id) in a Markdown block, to link to <a name="footnote_id"></a> in a HTML block.

However, the link isn’t working. Can anyone shed any light on why this might be? Does anyone have any tips on in-page links?

Doc not shared as it’s a big private WiP for now!

Edit to add MWE: https://observablehq.com/@kimadactyl/bilbiography-wip

Thanks,

Kim

The recommended way to do this is to split your markdown blocks into different named cells and link to those. See the discussion here:

@bgchen beat me to the punch! :clap:

Here’s a little demo of using Markdown to write footnote links in Observable:

The reason your original code wasn’t working is that Observable notebooks run in a sandboxed iframe, for safety — when you add a fragment to the URL bar, it’s referring to the parent page, not your content within the iframe. We promote the names of cells to the parent frame to make this work.

2 Likes

Oooh thanks for these responses - glad to have one way that works.

However, I’m currently using BibTeX -> citation-js -> markdown -> vanilla javascript to turn the a hrefs into a names (yes I’m a sucker for punishment).

Is there any way to programatically create all these code blocks? Or any other way to do it that might work with this setup? (I can make a MWE if needed)

Hrmm… that sounds harder! We don’t currently provide a way to programmatically create notebook source code, or to programmatically register cell anchor links with the parent frame. (I’ll take those as feature requests.)

That said, you could probably find a way to make it work with JavaScript, by observing changes to window.location, and scrolling to the relevant footnote programmatically. I’m afraid I don’t have time to write that up right now, but that’s what I’d suggest trying next…

From what I understand the iframe has no control over the parent page’s scroll offset. What strategy did you have in mind?

How do you feel about inlined footnotes?

I don’t have a strategy in mind — just a hope and a prayer. I was anticipating that a DOM API like Element.scrollIntoView() might work. But if iframes aren’t permitted to do that, then I’m fresh out of ideas.

1 Like

That’s the approach taken in @mbostock’s TOC notebook mentioned in the thread I linked above:

1 Like

Glad to hear I was wrong! :partying_face:

OK I made a MWE. Ideally I would want the LaTeX style author-year citation shorthand that’s supported by Rmd (R Markdown).

FWIW this is a common frustration us humanities folk have working with data science-y things so if there was a nicer way of doing bibliographies in observable that would be sweet, and my full feature request :slight_smile:

MWE: https://observablehq.com/@kimadactyl/bilbiography-wip

Let me know if anyone has any pointers on how I can link this up. As it is I’ll prob just manually convert it to cells for now as it’s not that many citations. (is there a way to print raw output?)

1 Like

Here’s a snippet that you can just drop into your notebooks to get your links working:

{
  const isLocalLink = a => a instanceof HTMLAnchorElement && a.getAttribute('href').match(/^#/);
  const scrollTo = e => {
    let l = e.target, t;
    if(isLocalLink(l) && (t = document.querySelector(`[name="${l.hash.slice(1)}"]`))) {
      e.preventDefault();
      t.scrollIntoView();
    }
  };
  document.addEventListener('click', scrollTo);
  invalidation.then(() => document.removeEventListener('click', scrollTo));
}

Note that currently a jump target might be covered by the top toolbar. This can be mitigated with a bit of CSS, but may not work in older browsers:

html`<style>
a[name] { scroll-margin-top: 55px }
`
4 Likes

Amazing thankyou that works a treat!!