Skip to content

Commit ce07127

Browse files
committed
Move core to lib/
1 parent 4dcef73 commit ce07127

File tree

4 files changed

+259
-246
lines changed

4 files changed

+259
-246
lines changed

index.js

+9-243
Original file line numberDiff line numberDiff line change
@@ -1,246 +1,12 @@
11
/**
2-
* @typedef Options
3-
* Configuration (optional).
4-
* @property {Test} [ignore]
5-
* `unist-util-is` test used to assert parents
6-
*
7-
* @typedef {import('mdast').Root} Root
8-
* @typedef {import('mdast').Content} Content
9-
* @typedef {import('mdast').PhrasingContent} PhrasingContent
10-
* @typedef {import('mdast').Text} Text
11-
* @typedef {Content|Root} Node
12-
* @typedef {Extract<Node, import('mdast').Parent>} Parent
13-
*
14-
* @typedef {import('unist-util-visit-parents').Test} Test
15-
* @typedef {import('unist-util-visit-parents').VisitorResult} VisitorResult
16-
*
17-
* @typedef RegExpMatchObject
18-
* @property {number} index
19-
* @property {string} input
20-
*
21-
* @typedef {string|RegExp} Find
22-
* @typedef {string|ReplaceFunction} Replace
23-
*
24-
* @typedef {[Find, Replace]} FindAndReplaceTuple
25-
* @typedef {Record<string, Replace>} FindAndReplaceSchema
26-
* @typedef {Array<FindAndReplaceTuple>} FindAndReplaceList
27-
*
28-
* @typedef {[RegExp, ReplaceFunction]} Pair
29-
* @typedef {Array<Pair>} Pairs
2+
* @typedef {import('./lib/index.js').Options} Options
3+
* @typedef {import('./lib/index.js').RegExpMatchObject} RegExpMatchObject
4+
* @typedef {import('./lib/index.js').Find} Find
5+
* @typedef {import('./lib/index.js').Replace} Replace
6+
* @typedef {import('./lib/index.js').ReplaceFunction} ReplaceFunction
7+
* @typedef {import('./lib/index.js').FindAndReplaceTuple} FindAndReplaceTuple
8+
* @typedef {import('./lib/index.js').FindAndReplaceSchema} FindAndReplaceSchema
9+
* @typedef {import('./lib/index.js').FindAndReplaceList} FindAndReplaceList
3010
*/
3111

32-
/**
33-
* @callback ReplaceFunction
34-
* @param {...any} parameters
35-
* @returns {Array<PhrasingContent>|PhrasingContent|string|false|undefined|null}
36-
*/
37-
38-
import escape from 'escape-string-regexp'
39-
import {visitParents} from 'unist-util-visit-parents'
40-
import {convert} from 'unist-util-is'
41-
42-
const own = {}.hasOwnProperty
43-
44-
/**
45-
* @param tree mdast tree
46-
* @param find Value to find and remove. When `string`, escaped and made into a global `RegExp`
47-
* @param [replace] Value to insert.
48-
* * When `string`, turned into a Text node.
49-
* * When `Function`, called with the results of calling `RegExp.exec` as
50-
* arguments, in which case it can return a single or a list of `Node`,
51-
* a `string` (which is wrapped in a `Text` node), or `false` to not replace
52-
* @param [options] Configuration.
53-
*/
54-
export const findAndReplace =
55-
/**
56-
* @type {(
57-
* ((tree: Node, find: Find, replace?: Replace, options?: Options) => Node) &
58-
* ((tree: Node, schema: FindAndReplaceSchema|FindAndReplaceList, options?: Options) => Node)
59-
* )}
60-
**/
61-
(
62-
/**
63-
* @param {Node} tree
64-
* @param {Find|FindAndReplaceSchema|FindAndReplaceList} find
65-
* @param {Replace|Options} [replace]
66-
* @param {Options} [options]
67-
*/
68-
function (tree, find, replace, options) {
69-
/** @type {Options|undefined} */
70-
let settings
71-
/** @type {FindAndReplaceSchema|FindAndReplaceList} */
72-
let schema
73-
74-
if (typeof find === 'string' || find instanceof RegExp) {
75-
// @ts-expect-error don’t expect options twice.
76-
schema = [[find, replace]]
77-
settings = options
78-
} else {
79-
schema = find
80-
// @ts-expect-error don’t expect replace twice.
81-
settings = replace
82-
}
83-
84-
if (!settings) {
85-
settings = {}
86-
}
87-
88-
const ignored = convert(settings.ignore || [])
89-
const pairs = toPairs(schema)
90-
let pairIndex = -1
91-
92-
while (++pairIndex < pairs.length) {
93-
visitParents(tree, 'text', visitor)
94-
}
95-
96-
return tree
97-
98-
/** @type {import('unist-util-visit-parents/complex-types').BuildVisitor<Root, 'text'>} */
99-
function visitor(node, parents) {
100-
let index = -1
101-
/** @type {Parent|undefined} */
102-
let grandparent
103-
104-
while (++index < parents.length) {
105-
const parent = /** @type {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
116-
}
117-
118-
grandparent = parent
119-
}
120-
121-
if (grandparent) {
122-
return handler(node, grandparent)
123-
}
124-
}
125-
126-
/**
127-
* @param {Text} node
128-
* @param {Parent} parent
129-
* @returns {VisitorResult}
130-
*/
131-
function handler(node, parent) {
132-
const find = pairs[pairIndex][0]
133-
const replace = pairs[pairIndex][1]
134-
let start = 0
135-
// @ts-expect-error: TS is wrong, some of these children can be text.
136-
let index = parent.children.indexOf(node)
137-
/** @type {Array<PhrasingContent>} */
138-
let nodes = []
139-
/** @type {number|undefined} */
140-
let position
141-
142-
find.lastIndex = 0
143-
144-
let match = find.exec(node.value)
145-
146-
while (match) {
147-
position = match.index
148-
let value = replace(...match, {
149-
index: match.index,
150-
input: match.input
151-
})
152-
153-
if (typeof value === 'string') {
154-
value = value.length > 0 ? {type: 'text', value} : undefined
155-
}
156-
157-
if (value !== false) {
158-
if (start !== position) {
159-
nodes.push({
160-
type: 'text',
161-
value: node.value.slice(start, position)
162-
})
163-
}
164-
165-
if (Array.isArray(value)) {
166-
nodes.push(...value)
167-
} else if (value) {
168-
nodes.push(value)
169-
}
170-
171-
start = position + match[0].length
172-
}
173-
174-
if (!find.global) {
175-
break
176-
}
177-
178-
match = find.exec(node.value)
179-
}
180-
181-
if (position === undefined) {
182-
nodes = [node]
183-
index--
184-
} else {
185-
if (start < node.value.length) {
186-
nodes.push({type: 'text', value: node.value.slice(start)})
187-
}
188-
189-
parent.children.splice(index, 1, ...nodes)
190-
}
191-
192-
return index + nodes.length + 1
193-
}
194-
}
195-
)
196-
197-
/**
198-
* @param {FindAndReplaceSchema|FindAndReplaceList} schema
199-
* @returns {Pairs}
200-
*/
201-
function toPairs(schema) {
202-
/** @type {Pairs} */
203-
const result = []
204-
205-
if (typeof schema !== 'object') {
206-
throw new TypeError('Expected array or object as schema')
207-
}
208-
209-
if (Array.isArray(schema)) {
210-
let index = -1
211-
212-
while (++index < schema.length) {
213-
result.push([
214-
toExpression(schema[index][0]),
215-
toFunction(schema[index][1])
216-
])
217-
}
218-
} else {
219-
/** @type {string} */
220-
let key
221-
222-
for (key in schema) {
223-
if (own.call(schema, key)) {
224-
result.push([toExpression(key), toFunction(schema[key])])
225-
}
226-
}
227-
}
228-
229-
return result
230-
}
231-
232-
/**
233-
* @param {Find} find
234-
* @returns {RegExp}
235-
*/
236-
function toExpression(find) {
237-
return typeof find === 'string' ? new RegExp(escape(find), 'g') : find
238-
}
239-
240-
/**
241-
* @param {Replace} replace
242-
* @returns {ReplaceFunction}
243-
*/
244-
function toFunction(replace) {
245-
return typeof replace === 'function' ? replace : () => replace
246-
}
12+
export {findAndReplace} from './lib/index.js'

0 commit comments

Comments
 (0)