No flags found
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
306095d
... +1 ...
7357886
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
1 | 1 | /** |
|
2 | - | * @typedef Options |
|
3 | - | * @property {Test} [ignore] |
|
2 | + | * @typedef Options Configuration. |
|
3 | + | * @property {Test} [ignore] `unist-util-is` test used to assert parents |
|
4 | 4 | * |
|
5 | 5 | * @typedef {import('mdast').Text} Text |
|
6 | 6 | * @typedef {import('mdast').Parent} Parent |
26 | 26 | * @typedef {Array.<Pair>} Pairs |
|
27 | 27 | */ |
|
28 | 28 | ||
29 | - | /** |
|
30 | - | * @callback Handler |
|
31 | - | * @param {Text} node |
|
32 | - | * @param {Parent} parent |
|
33 | - | * @returns {VisitorResult} |
|
34 | - | */ |
|
35 | - | ||
36 | 29 | /** |
|
37 | 30 | * @callback ReplaceFunction |
|
38 | - | * @param {...string} parameters |
|
39 | - | * @param {RegExpMatchObject} matchObject |
|
31 | + | * @param {...unknown} parameters |
|
40 | 32 | * @returns {Array.<PhrasingContent>|PhrasingContent|string|false|undefined|null} |
|
41 | 33 | */ |
|
42 | 34 |
47 | 39 | var own = {}.hasOwnProperty |
|
48 | 40 | ||
49 | 41 | /** |
|
50 | - | * @param {Node} tree |
|
51 | - | * @param {Find|FindAndReplaceSchema|FindAndReplaceList} find |
|
52 | - | * @param {Replace|Options} [replace] |
|
53 | - | * @param {Options} [options] |
|
42 | + | * @param tree mdast tree |
|
43 | + | * @param find Value to find and remove. When `string`, escaped and made into a global `RegExp` |
|
44 | + | * @param [replace] Value to insert. |
|
45 | + | * * When `string`, turned into a Text node. |
|
46 | + | * * When `Function`, called with the results of calling `RegExp.exec` as |
|
47 | + | * arguments, in which case it can return a single or a list of `Node`, |
|
48 | + | * a `string` (which is wrapped in a `Text` node), or `false` to not replace |
|
49 | + | * @param [options] Configuration. |
|
54 | 50 | */ |
|
55 | - | export function findAndReplace(tree, find, replace, options) { |
|
56 | - | /** @type {Options} */ |
|
57 | - | var settings |
|
58 | - | /** @type {FindAndReplaceSchema|FindAndReplaceList} */ |
|
59 | - | var schema |
|
60 | - | ||
61 | - | if (typeof find === 'string' || find instanceof RegExp) { |
|
62 | - | // @ts-expect-error don’t expect options twice. |
|
63 | - | schema = [[find, replace]] |
|
64 | - | settings = options |
|
65 | - | } else { |
|
66 | - | schema = find |
|
67 | - | // @ts-expect-error don’t expect replace twice. |
|
68 | - | settings = replace |
|
69 | - | } |
|
70 | - | ||
71 | - | if (!settings) { |
|
72 | - | settings = {} |
|
73 | - | } |
|
74 | - | ||
75 | - | search(tree, settings, handlerFactory(toPairs(schema))) |
|
51 | + | export const findAndReplace = |
|
52 | + | /** |
|
53 | + | * @type {( |
|
54 | + | * ((tree: Node, find: Find, replace?: Replace, options?: Options) => Node) & |
|
55 | + | * ((tree: Node, schema: FindAndReplaceSchema|FindAndReplaceList, options?: Options) => Node) |
|
56 | + | * )} |
|
57 | + | **/ |
|
58 | + | ( |
|
59 | + | /** |
|
60 | + | * @param {Node} tree |
|
61 | + | * @param {Find|FindAndReplaceSchema|FindAndReplaceList} find |
|
62 | + | * @param {Replace|Options} [replace] |
|
63 | + | * @param {Options} [options] |
|
64 | + | */ |
|
65 | + | function (tree, find, replace, options) { |
|
66 | + | /** @type {Options} */ |
|
67 | + | var settings |
|
68 | + | /** @type {FindAndReplaceSchema|FindAndReplaceList} */ |
|
69 | + | var schema |
|
70 | + | ||
71 | + | if (typeof find === 'string' || find instanceof RegExp) { |
|
72 | + | // @ts-expect-error don’t expect options twice. |
|
73 | + | schema = [[find, replace]] |
|
74 | + | settings = options |
|
75 | + | } else { |
|
76 | + | schema = find |
|
77 | + | // @ts-expect-error don’t expect replace twice. |
|
78 | + | settings = replace |
|
79 | + | } |
|
76 | 80 | ||
77 | - | return tree |
|
81 | + | if (!settings) { |
|
82 | + | settings = {} |
|
83 | + | } |
|
78 | 84 | ||
79 | - | /** |
|
80 | - | * @param {Pairs} pairs |
|
81 | - | * @returns {Handler} |
|
82 | - | */ |
|
83 | - | function handlerFactory(pairs) { |
|
84 | - | var pair = pairs[0] |
|
85 | + | var ignored = convert(settings.ignore || []) |
|
86 | + | var pairs = toPairs(schema) |
|
87 | + | var pairIndex = -1 |
|
85 | 88 | ||
86 | - | return handler |
|
89 | + | while (++pairIndex < pairs.length) { |
|
90 | + | visitParents(tree, 'text', visitor) |
|
91 | + | } |
|
87 | 92 | ||
88 | - | /** |
|
89 | - | * @type {Handler} |
|
90 | - | */ |
|
91 | - | function handler(node, parent) { |
|
92 | - | var find = pair[0] |
|
93 | - | var replace = pair[1] |
|
94 | - | /** @type {Array.<PhrasingContent>} */ |
|
95 | - | var nodes = [] |
|
96 | - | var start = 0 |
|
97 | - | var index = parent.children.indexOf(node) |
|
98 | - | /** @type {number} */ |
|
99 | - | var position |
|
100 | - | /** @type {RegExpMatchArray} */ |
|
101 | - | var match |
|
102 | - | /** @type {Handler} */ |
|
103 | - | var subhandler |
|
104 | - | /** @type {PhrasingContent} */ |
|
105 | - | var child |
|
106 | - | /** @type {Array.<PhrasingContent>|PhrasingContent|string|false|undefined|null} */ |
|
107 | - | var value |
|
108 | - | ||
109 | - | find.lastIndex = 0 |
|
110 | - | ||
111 | - | match = find.exec(node.value) |
|
112 | - | ||
113 | - | while (match) { |
|
114 | - | position = match.index |
|
115 | - | // @ts-expect-error this is perfectly fine, typescript. |
|
116 | - | value = replace(...match, {index: position, input: match.input}) |
|
117 | - | ||
118 | - | if (typeof value === 'string' && value.length > 0) { |
|
119 | - | value = {type: 'text', value} |
|
120 | - | } |
|
93 | + | return tree |
|
121 | 94 | ||
122 | - | if (value !== false) { |
|
123 | - | if (start !== position) { |
|
124 | - | nodes.push({type: 'text', value: node.value.slice(start, position)}) |
|
125 | - | } |
|
95 | + | /** @type {import('unist-util-visit-parents').Visitor<Text>} */ |
|
96 | + | function visitor(node, parents) { |
|
97 | + | var index = -1 |
|
98 | + | /** @type {Parent} */ |
|
99 | + | var parent |
|
100 | + | /** @type {Parent} */ |
|
101 | + | var grandparent |
|
126 | 102 | ||
127 | - | if (value) { |
|
128 | - | nodes = [].concat(nodes, value) |
|
103 | + | while (++index < parents.length) { |
|
104 | + | // @ts-expect-error mdast vs. unist parent. |
|
105 | + | parent = parents[index] |
|
106 | + | ||
107 | + | if ( |
|
108 | + | ignored( |
|
109 | + | parent, |
|
110 | + | // @ts-expect-error mdast vs. unist parent. |
|
111 | + | grandparent ? grandparent.children.indexOf(parent) : undefined, |
|
112 | + | grandparent |
|
113 | + | ) |
|
114 | + | ) { |
|
115 | + | return |
|
129 | 116 | } |
|
130 | 117 | ||
131 | - | start = position + match[0].length |
|
118 | + | grandparent = parent |
|
132 | 119 | } |
|
133 | 120 | ||
134 | - | if (!find.global) { |
|
135 | - | break |
|
136 | - | } |
|
121 | + | return handler(node, grandparent) |
|
122 | + | } |
|
123 | + | ||
124 | + | /** |
|
125 | + | * @param {Text} node |
|
126 | + | * @param {Parent} parent |
|
127 | + | * @returns {VisitorResult} |
|
128 | + | */ |
|
129 | + | function handler(node, parent) { |
|
130 | + | var find = pairs[pairIndex][0] |
|
131 | + | var replace = pairs[pairIndex][1] |
|
132 | + | /** @type {Array.<PhrasingContent>} */ |
|
133 | + | var nodes = [] |
|
134 | + | var start = 0 |
|
135 | + | var index = parent.children.indexOf(node) |
|
136 | + | /** @type {number} */ |
|
137 | + | var position |
|
138 | + | /** @type {RegExpMatchArray} */ |
|
139 | + | var match |
|
140 | + | /** @type {Array.<PhrasingContent>|PhrasingContent|string|false|undefined|null} */ |
|
141 | + | var value |
|
142 | + | ||
143 | + | find.lastIndex = 0 |
|
137 | 144 | ||
138 | 145 | match = find.exec(node.value) |
|
139 | - | } |
|
140 | 146 | ||
141 | - | if (position === undefined) { |
|
142 | - | nodes = [node] |
|
143 | - | index-- |
|
144 | - | } else { |
|
145 | - | if (start < node.value.length) { |
|
146 | - | nodes.push({type: 'text', value: node.value.slice(start)}) |
|
147 | - | } |
|
147 | + | while (match) { |
|
148 | + | position = match.index |
|
149 | + | // @ts-expect-error this is perfectly fine, typescript. |
|
150 | + | value = replace(...match, {index: match.index, input: match.input}) |
|
148 | 151 | ||
149 | - | parent.children.splice(index, 1, ...nodes) |
|
150 | - | } |
|
152 | + | if (typeof value === 'string' && value.length > 0) { |
|
153 | + | value = {type: 'text', value} |
|
154 | + | } |
|
151 | 155 | ||
152 | - | if (pairs.length > 1) { |
|
153 | - | subhandler = handlerFactory(pairs.slice(1)) |
|
154 | - | position = -1 |
|
156 | + | if (value !== false) { |
|
157 | + | if (start !== position) { |
|
158 | + | nodes.push({ |
|
159 | + | type: 'text', |
|
160 | + | value: node.value.slice(start, position) |
|
161 | + | }) |
|
162 | + | } |
|
155 | 163 | ||
156 | - | while (++position < nodes.length) { |
|
157 | - | child = nodes[position] |
|
164 | + | if (value) { |
|
165 | + | nodes = [].concat(nodes, value) |
|
166 | + | } |
|
158 | 167 | ||
159 | - | if (child.type === 'text') { |
|
160 | - | subhandler(child, parent) |
|
161 | - | } else { |
|
162 | - | search(child, settings, subhandler) |
|
168 | + | start = position + match[0].length |
|
163 | 169 | } |
|
170 | + | ||
171 | + | if (!find.global) { |
|
172 | + | break |
|
173 | + | } |
|
174 | + | ||
175 | + | match = find.exec(node.value) |
|
164 | 176 | } |
|
165 | - | } |
|
166 | 177 | ||
167 | - | return index + nodes.length + 1 |
|
168 | - | } |
|
169 | - | } |
|
170 | - | } |
|
178 | + | if (position === undefined) { |
|
179 | + | nodes = [node] |
|
180 | + | index-- |
|
181 | + | } else { |
|
182 | + | if (start < node.value.length) { |
|
183 | + | nodes.push({type: 'text', value: node.value.slice(start)}) |
|
184 | + | } |
|
171 | 185 | ||
172 | - | /** |
|
173 | - | * @param {Node} tree |
|
174 | - | * @param {Options} options |
|
175 | - | * @param {Handler} handler |
|
176 | - | * @returns {void} |
|
177 | - | */ |
|
178 | - | function search(tree, options, handler) { |
|
179 | - | var ignored = convert(options.ignore || []) |
|
180 | - | ||
181 | - | visitParents(tree, 'text', visitor) |
|
182 | - | ||
183 | - | /** @type {import('unist-util-visit-parents').Visitor<Text>} */ |
|
184 | - | function visitor(node, parents) { |
|
185 | - | var index = -1 |
|
186 | - | /** @type {Parent} */ |
|
187 | - | var parent |
|
188 | - | /** @type {Parent} */ |
|
189 | - | var grandparent |
|
190 | - | ||
191 | - | while (++index < parents.length) { |
|
192 | - | // @ts-expect-error mdast vs. unist parent. |
|
193 | - | parent = parents[index] |
|
194 | - | ||
195 | - | if ( |
|
196 | - | ignored( |
|
197 | - | parent, |
|
198 | - | // @ts-expect-error mdast vs. unist parent. |
|
199 | - | grandparent ? grandparent.children.indexOf(parent) : undefined, |
|
200 | - | grandparent |
|
201 | - | ) |
|
202 | - | ) { |
|
203 | - | return |
|
204 | - | } |
|
186 | + | parent.children.splice(index, 1, ...nodes) |
|
187 | + | } |
|
205 | 188 | ||
206 | - | grandparent = parent |
|
189 | + | return index + nodes.length + 1 |
|
190 | + | } |
|
207 | 191 | } |
|
208 | - | ||
209 | - | return handler(node, grandparent) |
|
210 | - | } |
|
211 | - | } |
|
192 | + | ) |
|
212 | 193 | ||
213 | 194 | /** |
|
214 | 195 | * @param {FindAndReplaceSchema|FindAndReplaceList} schema |
Files | Coverage |
---|---|
index.js | 100.00% |
Project Totals (1 files) | 100.00% |
7357886
c85728a
306095d