Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to change section attributes based on heading #5

Open
TheComputerM opened this issue Aug 9, 2020 · 9 comments
Open

Add ability to change section attributes based on heading #5

TheComputerM opened this issue Aug 9, 2020 · 9 comments

Comments

@TheComputerM
Copy link

No description provided.

@TheComputerM
Copy link
Author

For example give the section a unique id based on the heading text content

@steveruizok
Copy link

I'd love to have a clue as to the depth, like <section data-depth="0">!

@steveruizok
Copy link

Nevermind, looks like that's already in ;)

@jrson83
Copy link

jrson83 commented Mar 3, 2022

Is it possible to add an id to every section, depending on current heading?

@jake-low
Copy link
Owner

jake-low commented Mar 4, 2022

That functionality isn't built into this plugin, but it is possible. Here's an example.

// This rehype plugin traverses <section> elements in the document, and if that section's first
// child is a heading (h1, h2, etc), it moves that child's `id` attribute to the section element.

const visit = require('unist-util-visit-parents')

const MAX_HEADING_DEPTH = 6
const HEADINGS = ["h1", "h2", "h3", "h4", "h5", "h6"]

module.exports = plugin

function plugin () {
  return transform
}

function transform (tree) {
  visit(
    tree,
    node => node.tagName === "section",
    update
  )
}

function update (section) {
  if (section.children && section.children[0] && HEADINGS.includes(section.children[0].tagName)) {
    const heading = section.children[0]
    const { id, ...rest } = heading.properties
    section.properties.id = id
    heading.properties = rest
  }
}

The code above is a rehype plugin: it transforms HTML ASTs, not Markdown ASTs. Add it to your project and name it something sensible, like rehype-heading-ids-to-section-ids.js. Then to use it, you'd do something like this.

var unified = require("unified") // unified is the text processing interface that powers remark and rehype

var processor = unified()
  .use(require("remark-parse")) // parse markdown text to an AST
  .use(require("remark-sectionize")) // wraps stuff in sections (transforming the AST)
  .use(require("remark-rehype")) // convert the markdown AST to an HTML AST
  .use(require("rehype-slug")) // adds `id` attributes to headings
  .use(require('./rehype-heading-ids-to-section-ids.js')) // the filename for the above plugin code
  .use(require("rehype-stringify")) // convert the modified HTML AST to a string

var outputHTML = processor.process(inputMarkdown)

There's no reason that you couldn't modify the plugin shown above to operate directly on the Markdown AST, but I didn't have sample code handy for that.

@jrson83
Copy link

jrson83 commented Mar 4, 2022

Oh man thank you, this is great!

@jake-low
Copy link
Owner

jake-low commented Mar 4, 2022

You're welcome! 🙂

@aquaductape
Copy link

This should be included as an option for this plugin

@jrson83
Copy link

jrson83 commented Apr 20, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants