Published: 15.12.2020 | Edited: 22.12.2020 | Tags: javascript,css,markdown

Using CSS selectors on Markdown in JS

It is possible target specific elements in a DOM via CSS using selectors 1

h2 {
  /* property: value; */
}

It is also possible to use CSS selector in JS DOM 2

const elements = document.querySelector("h2")

With the advent of a JAMstack it is also possible to target Markdown elements using CSS selectors

  • Init the project
npm init -y
  • In package.json change type to ESM to enable import statement 3
{
  ...
  "type": "module"
}

Alternatively, enable it via the command line 4

npx json -I -f package.json -e 'this.type="module"'
  • Install required dependencies
npm i unified remark-parse remark-stringify unist-util-select
  • Create the post.md file
[//]: # "This is a comment"

# Main heading

## Second level heading A

Paragraph

## Second level heading B
  • Create the index.js script
import fs from "fs"
import markdown from "remark-parse"
import stringify from "remark-stringify"
import unified from "unified"
import util from "unist-util-select"
const { selectAll } = util

let mdast
unified()
  .use(markdown)
  .use(() => tree => (mdast = tree))
  .use(stringify)
  .process(fs.readFileSync("post.md"))

const headingsNodes = selectAll("heading[depth=2]", mdast)
const json = JSON.stringify(headingsNodes, null, 2)

console.log(json)
  • Running the script
node index.js

Prints an array containg both level 2 headings as mdast tree nodes 5

[
  {
    "type": "heading",
    "depth": 2,
    "children": [
      {
        "type": "text",
        "value": "Second level heading A",
        ...
      }
    ],
    ...
  },
  {
    "type": "heading",
    "depth": 2,
    "children": [
      {
        "type": "text",
        "value": "Second level heading B",
        ...
      }
    ],
    ...
  }
]

The magic is happening because of selectAll funtion from the unist-util-select package 6

const headingsNodes = selectAll("heading[depth=2]", mdast)

Sources are available in the repository