Giter VIP home page Giter VIP logo

Comments (3)

nhoizey avatar nhoizey commented on September 27, 2024

This is how I get this result with markdown-it-anchor v7 (and Eleventy):

https://github.com/nhoizey/nicolas-hoizey.com/blob/main/.eleventy.js#L102-L177

const markdownItAnchorOptions = {
    permalink: true,
    permalinkClass: 'deeplink',
    permalinkSymbol:
      '<svg class="icon" role="img" focusable="false" viewBox="0 0 24 24" width="1em" height="1em"><use xlink:href="#symbol-anchor" /></svg>',
    level: [2, 3, 4],
    slugify: function (s) {
      return slugify(s);
    },
    renderPermalink: (slug, opts, state, idx) => {
      // based on fifth version in
      // https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/
      const linkContent = state.tokens[idx + 1].children[0].content;

      // Create the openning <div> for the wrapper
      const headingWrapperTokenOpen = Object.assign(
        new state.Token('div_open', 'div', 1),
        {
          attrs: [['class', 'heading-wrapper']],
        }
      );
      // Create the closing </div> for the wrapper
      const headingWrapperTokenClose = Object.assign(
        new state.Token('div_close', 'div', -1),
        {
          attrs: [['class', 'heading-wrapper']],
        }
      );

      // Create the tokens for the full accessible anchor link
      // <a class="deeplink" href="#your-own-platform-is-the-nearest-you-can-get-help-to-setup">
      //   <span aria-hidden="true">
      //     ${opts.permalinkSymbol}
      //   </span>
      //   <span class="visually-hidden">
      //     Section titled Your "own" platform is the nearest you can(get help to) setup
      //   </span>
      // </a >
      const anchorTokens = [
        Object.assign(new state.Token('link_open', 'a', 1), {
          attrs: [
            ...(opts.permalinkClass ? [['class', opts.permalinkClass]] : []),
            ['href', opts.permalinkHref(slug, state)],
            ...Object.entries(opts.permalinkAttrs(slug, state)),
          ],
        }),
        Object.assign(new state.Token('span_open', 'span', 1), {
          attrs: [['aria-hidden', 'true']],
        }),
        Object.assign(new state.Token('html_block', '', 0), {
          content: opts.permalinkSymbol,
        }),
        Object.assign(new state.Token('span_close', 'span', -1), {}),
        Object.assign(new state.Token('span_open', 'span', 1), {
          attrs: [['class', 'visually-hidden']],
        }),
        Object.assign(new state.Token('html_block', '', 0), {
          content: `Section titled ${linkContent}`,
        }),
        Object.assign(new state.Token('span_close', 'span', -1), {}),
        new state.Token('link_close', 'a', -1),
      ];

      // idx is the index of the heading's first token
      // insert the wrapper opening before the heading
      state.tokens.splice(idx, 0, headingWrapperTokenOpen);
      // insert the anchor link tokens after the wrapper opening and the 3 tokens of the heading
      state.tokens.splice(idx + 3 + 1, 0, ...anchorTokens);
      // insert the wrapper closing after all these
      state.tokens.splice(
        idx + 3 + 1 + anchorTokens.length,
        0,
        headingWrapperTokenClose
      );
    },
  };

from markdown-it-anchor.

valeriangalliat avatar valeriangalliat commented on September 27, 2024

Hey! Sorry for the late reply.

I was about to suggest the following:

const linkAfterHeader = anchor.permalink.linkAfterHeader({
  class: 'deeplink',
  symbol: '<svg class="icon" role="img" focusable="false" viewBox="0 0 24 24" width="1em" height="1em"><use xlink:href="#symbol-anchor" /></svg>',
  style: 'visually-hidden',
  visuallyHiddenClass: 'visually-hidden',
  assistiveText: (title) => `Permalink to heading ${title}`,
})

const options = {
  level: [2, 3, 4],
  slugify,
  permalink (slug, opts, state, idx) {
    state.tokens.splice(idx, 0, Object.assign(new state.Token('div_open', 'div', 1), {
      attrs: [['class', 'heading-wrapper']],
      block: true
    }))

    state.tokens.splice(idx + 4, 0, Object.assign(new state.Token('div_close', 'div', -1), {
      block: true
    }))

    linkAfterHeader(slug, opts, state, idx + 1)
  }
}

But sadly this doesn't work because the fact we splice before the current header causes an infinite loop (the "next" token from markdown-it-anchor's perspective is the header we just processed, so we call the permalink on it again and so on). By default it just throws on the second iteration of the same header because the id is now explicit and not unique...

I just made a quick fix so that markdown-it-anchor is more friendly to renderers that use splice on the top-level, the example above should now work with 8.3.0!

from markdown-it-anchor.

nhoizey avatar nhoizey commented on September 27, 2024

Hi @valeriangalliat, it works indeed, thanks a lot! 🙏

from markdown-it-anchor.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.