Skip to content

Commit

Permalink
Add support for phrasing content
Browse files Browse the repository at this point in the history
Previously, only the textual content of headings was used to generate the entries in the Table of Contents. This lead to a bug (or feature?) where HTML in headings made entries in the TOC appear with literal HTML.

mdast has a concept of static phrasing content, which includes all the things that can appear in links. Instead of using just the textual content of a heading, this commit introduces a new behaviour where any static phrasing content, such as HTML, inline code, and emphasis, are copied over into the Table of Contents. Interactive phrasing content (links, link references) are handled by replacing them with their children.

See: <https://github.com/syntax-tree/mdast#staticphrasingcontent>

Closes GH-56.
Closes GH-57.
Closes GH-58.

Reviewed-by: Christian Murphy <christian.murphy.42@gmail.com>
Reviewed-by: Jonathan Haines <jonno.haines@gmail.com>
  • Loading branch information
wooorm committed May 13, 2019
1 parent 32d2a8f commit 6fbb123
Show file tree
Hide file tree
Showing 9 changed files with 442 additions and 26 deletions.
59 changes: 47 additions & 12 deletions lib/contents.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
'use strict'

var extend = require('extend')

module.exports = contents

var LIST = 'list'
var LIST_ITEM = 'listItem'
var PARAGRAPH = 'paragraph'
var LINK = 'link'
var TEXT = 'text'
var LINK_REFERENCE = 'linkReference'

// Transform a list of heading objects to a markdown list.
function contents(map, tight) {
Expand Down Expand Up @@ -42,16 +44,16 @@ function contents(map, tight) {
return table
}

// Insert a `node` into a `parent`.
function insert(node, parent, tight) {
// Insert an entry into `parent`.
function insert(entry, parent, tight) {
var children = parent.children
var length = children.length
var last = children[length - 1]
var isLoose = false
var index
var item

if (node.depth === 1) {
if (entry.depth === 1) {
item = listItem()

item.children.push({
Expand All @@ -60,30 +62,30 @@ function insert(node, parent, tight) {
{
type: LINK,
title: null,
url: '#' + node.id,
children: [{type: TEXT, value: node.value}]
url: '#' + entry.id,
children: all(entry.children)
}
]
})

children.push(item)
} else if (last && last.type === LIST_ITEM) {
insert(node, last, tight)
insert(entry, last, tight)
} else if (last && last.type === LIST) {
node.depth--
entry.depth--

insert(node, last, tight)
insert(entry, last, tight)
} else if (parent.type === LIST) {
item = listItem()

insert(node, item, tight)
insert(entry, item, tight)

children.push(item)
} else {
item = list()
node.depth--
entry.depth--

insert(node, item, tight)
insert(entry, item, tight)

children.push(item)
}
Expand Down Expand Up @@ -129,6 +131,39 @@ function insert(node, parent, tight) {
}
}

function all(children) {
var result = []
var length = children.length
var index = -1

while (++index < length) {
result = result.concat(one(children[index]))
}

return result
}

function one(node) {
var copy

if (node.type === LINK || node.type === LINK_REFERENCE) {
return all(node.children)
}

copy = extend({}, node)

delete copy.children
delete copy.position

copy = extend(true, {}, copy)

if (node.children) {
copy.children = all(node.children)
}

return copy
}

// Create a list.
function list() {
return {type: LIST, ordered: false, spread: false, children: []}
Expand Down
6 changes: 5 additions & 1 deletion lib/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ function search(root, expression, settings) {
}

if (!lookingForToc && value && child.depth <= maxDepth) {
map.push({depth: child.depth, value: value, id: slugs.slug(id || value)})
map.push({
depth: child.depth,
children: child.children,
id: slugs.slug(id || value)
})
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"index.js"
],
"dependencies": {
"extend": "^3.0.2",
"github-slugger": "^1.2.1",
"mdast-util-to-string": "^1.0.5",
"unist-util-is": "^2.1.2",
Expand All @@ -32,10 +33,12 @@
"remark": "^10.0.0",
"remark-attr": "^0.8.0",
"remark-cli": "^6.0.0",
"remark-parse": "^6.0.3",
"remark-preset-wooorm": "^4.0.0",
"remark-usage": "^6.1.3",
"tape": "^4.10.1",
"tinyify": "^2.5.0",
"unified": "^7.1.0",
"unist-builder": "^1.0.3",
"xo": "^0.24.0"
},
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/normal-attr/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"useRemarkAttr": true
}
5 changes: 5 additions & 0 deletions test/fixtures/phrasing-content/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"remarkParseOptions": {
"footnotes": true
}
}
29 changes: 29 additions & 0 deletions test/fixtures/phrasing-content/input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Text

# *Emphasis*

# **Importance**

# ~~Strikethrough~~

# <i>HTML<i>

# `inline.code()`

# [^a footnote]

# footnote reference [^1]

# ![image](image.png)

# ![image reference][image]

# [link](example.com)

# ![link reference][link]

[^1]: footnote reference

[image]: image.png

[link]: example.com

0 comments on commit 6fbb123

Please sign in to comment.