UNPKG

3.31 kBJavaScriptView Raw
1'use strict'
2
3var extend = require('extend')
4
5module.exports = contents
6
7var LIST = 'list'
8var LIST_ITEM = 'listItem'
9var PARAGRAPH = 'paragraph'
10var LINK = 'link'
11var LINK_REFERENCE = 'linkReference'
12
13// Transform a list of heading objects to a markdown list.
14function contents(map, tight, prefix) {
15 var minDepth = Infinity
16 var index = -1
17 var length = map.length
18 var table
19
20 // Find minimum depth.
21 while (++index < length) {
22 if (map[index].depth < minDepth) {
23 minDepth = map[index].depth
24 }
25 }
26
27 // Normalize depth.
28 index = -1
29
30 while (++index < length) {
31 map[index].depth -= minDepth - 1
32 }
33
34 // Construct the main list.
35 table = list()
36
37 // Add TOC to list.
38 index = -1
39
40 while (++index < length) {
41 insert(map[index], table, tight, prefix)
42 }
43
44 return table
45}
46
47// Insert an entry into `parent`.
48function insert(entry, parent, tight, prefix) {
49 var children = parent.children
50 var length = children.length
51 var last = children[length - 1]
52 var isLoose = false
53 var index
54 var item
55
56 if (entry.depth === 1) {
57 item = listItem()
58
59 item.children.push({
60 type: PARAGRAPH,
61 children: [
62 {
63 type: LINK,
64 title: null,
65 url: '#' + (prefix || '') + entry.id,
66 children: all(entry.children)
67 }
68 ]
69 })
70
71 children.push(item)
72 } else if (last && last.type === LIST_ITEM) {
73 insert(entry, last, tight, prefix)
74 } else if (last && last.type === LIST) {
75 entry.depth--
76
77 insert(entry, last, tight, prefix)
78 } else if (parent.type === LIST) {
79 item = listItem()
80
81 insert(entry, item, tight, prefix)
82
83 children.push(item)
84 } else {
85 item = list()
86 entry.depth--
87
88 insert(entry, item, tight, prefix)
89
90 children.push(item)
91 }
92
93 // Properly style list-items with new lines.
94 parent.spread = !tight
95
96 if (parent.type === LIST && parent.spread) {
97 parent.spread = false
98 index = -1
99
100 while (++index < length) {
101 if (children[index].children.length > 1) {
102 parent.spread = true
103 break
104 }
105 }
106 }
107
108 // To do: remove `loose` in next major release.
109 if (parent.type === LIST_ITEM) {
110 parent.loose = tight ? false : children.length > 1
111 } else {
112 if (tight) {
113 isLoose = false
114 } else {
115 index = -1
116
117 while (++index < length) {
118 if (children[index].loose) {
119 isLoose = true
120
121 break
122 }
123 }
124 }
125
126 index = -1
127
128 while (++index < length) {
129 children[index].loose = isLoose
130 }
131 }
132}
133
134function all(children) {
135 var result = []
136 var length = children.length
137 var index = -1
138
139 while (++index < length) {
140 result = result.concat(one(children[index]))
141 }
142
143 return result
144}
145
146function one(node) {
147 var copy
148
149 if (node.type === LINK || node.type === LINK_REFERENCE) {
150 return all(node.children)
151 }
152
153 copy = extend({}, node)
154
155 delete copy.children
156 delete copy.position
157
158 copy = extend(true, {}, copy)
159
160 if (node.children) {
161 copy.children = all(node.children)
162 }
163
164 return copy
165}
166
167// Create a list.
168function list() {
169 return {type: LIST, ordered: false, spread: false, children: []}
170}
171
172// Create a list item.
173function listItem() {
174 // To do: remove `loose` in next major.
175 return {type: LIST_ITEM, loose: false, spread: false, children: []}
176}