remarkjs / strip-markdown
Showing 1 of 10 files from the diff.
Other files ignored by Codecov
package.json has changed.
types/index.d.ts was deleted.
types/tslint.json was deleted.
.gitignore has changed.
types/test.ts was deleted.
test.js has changed.
readme.md has changed.

@@ -1,5 +1,29 @@
Loading
1 -
// Expose modifiers for available node types.
2 -
// Node types not listed here are not changed (but their children are).
1 +
/**
2 +
 * @typedef {import('mdast').Content} Content
3 +
 * @typedef {import('mdast').Root} Root
4 +
 * @typedef {Root|Content} Node
5 +
 * @typedef {Node['type']} Type
6 +
 *
7 +
 * @callback Handler
8 +
 * @param {any} node
9 +
 * @returns {Node|Node[]} node
10 +
 *
11 +
 * @typedef {Partial<Record<Type, Handler>>} Handlers
12 +
 *
13 +
 * @typedef Options
14 +
 *   Configuration.
15 +
 * @property {Array.<Type>|undefined} [keep]
16 +
 *   List of node types to leave unchanged.
17 +
 * @property {Array.<Type|[Type, Handler]>|undefined} [remove]
18 +
 *   List of additional node types to remove or replace.
19 +
 */
20 +
21 +
/**
22 +
 * Expose modifiers for available node types.
23 +
 * Node types not listed here are not changed (but their children are).
24 +
 *
25 +
 * @type {Handlers}
26 +
 */
3 27
const defaults = {
4 28
  heading: paragraph,
5 29
  text,
@@ -18,13 +42,14 @@
Loading
18 42
  linkReference: children,
19 43
20 44
  code: empty,
21 -
  horizontalRule: empty,
22 45
  thematicBreak: empty,
23 46
  html: empty,
24 47
  table: empty,
25 48
  tableCell: empty,
26 49
  definition: empty,
27 50
  yaml: empty,
51 +
52 +
  // @ts-expect-error: custom frontmatter node.
28 53
  toml: empty,
29 54
30 55
  footnoteReference: empty,
@@ -33,6 +58,12 @@
Loading
33 58
34 59
const own = {}.hasOwnProperty
35 60
61 +
/**
62 +
 * Plugin to remove markdown formatting.
63 +
 *
64 +
 * @type {import('unified').Plugin<[Options?] | void[], Root>}
65 +
 * @returns {import('unified').Transformer<Root>}
66 +
 */
36 67
export default function stripMarkdown(options = {}) {
37 68
  const handlers = Object.assign({}, defaults)
38 69
  const remove = options.remove || []
@@ -50,11 +81,13 @@
Loading
50 81
    }
51 82
  }
52 83
84 +
  /** @type {Handlers} */
53 85
  let map = {}
54 86
55 87
  if (keep.length === 0) {
56 88
    map = handlers
57 89
  } else {
90 +
    /** @type {Type} */
58 91
    let key
59 92
60 93
    for (key in handlers) {
@@ -79,32 +112,48 @@
Loading
79 112
    }
80 113
  }
81 114
115 +
  // @ts-expect-error: assume content model (for root) matches.
82 116
  return one
83 117
118 +
  /**
119 +
   * @param {Node} node
120 +
   * @returns {Node|Node[]}
121 +
   */
84 122
  function one(node) {
123 +
    /** @type {Type} */
85 124
    const type = node.type
125 +
    /** @type {Node|Node[]} */
126 +
    let result = node
86 127
87 128
    if (type in map) {
88 -
      const result = map[type](node)
89 -
      node = Array.isArray(result) ? all(result) : result
129 +
      const handler = map[type]
130 +
      if (handler) result = handler(result)
90 131
    }
91 132
92 -
    if (node.children) {
93 -
      node.children = all(node.children)
133 +
    result = Array.isArray(result) ? all(result) : result
134 +
135 +
    if ('children' in result) {
136 +
      // @ts-expect-error: assume content models match.
137 +
      result.children = all(result.children)
94 138
    }
95 139
96 -
    return node
140 +
    return result
97 141
  }
98 142
143 +
  /**
144 +
   * @param {Node[]} nodes
145 +
   * @returns {Node[]}
146 +
   */
99 147
  function all(nodes) {
100 -
    const result = []
101 148
    let index = -1
149 +
    /** @type {Node[]} */
150 +
    const result = []
102 151
103 152
    while (++index < nodes.length) {
104 153
      const value = one(nodes[index])
105 154
106 155
      if (Array.isArray(value)) {
107 -
        result.push(...value.map((d) => one(d)))
156 +
        result.push(...value.flatMap((d) => one(d)))
108 157
      } else {
109 158
        result.push(value)
110 159
      }
@@ -114,16 +163,24 @@
Loading
114 163
  }
115 164
}
116 165
117 -
// Clean nodes: merges texts.
166 +
/**
167 +
 * Clean nodes: merges literals.
168 +
 *
169 +
 * @param {Node[]} values
170 +
 * @returns {Node[]}
171 +
 */
118 172
function clean(values) {
119 -
  const result = []
120 173
  let index = -1
174 +
  /** @type {Node[]} */
175 +
  const result = []
176 +
  /** @type {Node|undefined} */
121 177
  let previous
122 178
123 179
  while (++index < values.length) {
124 180
    const value = values[index]
125 181
126 182
    if (previous && value.type === previous.type && 'value' in value) {
183 +
      // @ts-expect-error: we just checked that they’re the same node.
127 184
      previous.value += value.value
128 185
    } else {
129 186
      result.push(value)
@@ -134,26 +191,49 @@
Loading
134 191
  return result
135 192
}
136 193
194 +
/**
195 +
 * @type {Handler}
196 +
 * @param {import('mdast').Image|import('mdast').ImageReference} node
197 +
 */
137 198
function image(node) {
138 -
  return {type: 'text', value: node.alt || node.title || ''}
199 +
  const title = 'title' in node ? node.title : ''
200 +
  return {type: 'text', value: node.alt || title || ''}
139 201
}
140 202
203 +
/**
204 +
 * @type {Handler}
205 +
 * @param {import('mdast').Text} node
206 +
 */
141 207
function text(node) {
142 208
  return {type: 'text', value: node.value}
143 209
}
144 210
211 +
/**
212 +
 * @type {Handler}
213 +
 * @param {import('mdast').Paragraph} node
214 +
 */
145 215
function paragraph(node) {
146 216
  return {type: 'paragraph', children: node.children}
147 217
}
148 218
219 +
/**
220 +
 * @type {Handler}
221 +
 * @param {Extract<Node, import('unist').Parent>} node
222 +
 */
149 223
function children(node) {
150 224
  return node.children || []
151 225
}
152 226
227 +
/**
228 +
 * @type {Handler}
229 +
 */
153 230
function lineBreak() {
154 231
  return {type: 'text', value: '\n'}
155 232
}
156 233
234 +
/**
235 +
 * @type {Handler}
236 +
 */
157 237
function empty() {
158 238
  return {type: 'text', value: ''}
159 239
}
Files Coverage
index.js 100.00%
Project Totals (1 files) 100.00%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading