Skip to content

Commit 543af1b

Browse files
committed
Move core to lib/
1 parent 1850c7a commit 543af1b

File tree

4 files changed

+232
-219
lines changed

4 files changed

+232
-219
lines changed

index.js

Lines changed: 9 additions & 217 deletions
Original file line numberDiff line numberDiff line change
@@ -1,220 +1,12 @@
11
/**
2-
* @typedef Options
3-
* @property {Test} [ignore]
4-
*
5-
* @typedef {import('hast').Text} Text
6-
* @typedef {import('hast').Parent} Parent
7-
* @typedef {import('hast').Root} Root
8-
* @typedef {import('hast').Element} Element
9-
* @typedef {import('hast').Content} Content
10-
* @typedef {Root|Content} Node
11-
*
12-
* @typedef {import('hast-util-is-element').Test} Test
13-
* @typedef {import('unist-util-visit-parents').VisitorResult} VisitorResult
14-
*
15-
* @typedef RegExpMatchObject
16-
* @property {number} index
17-
* @property {string} input
18-
*
19-
* @typedef {string|RegExp} Find
20-
* @typedef {string|ReplaceFunction} Replace
21-
*
22-
* @typedef {[Find, Replace]} FindAndReplaceTuple
23-
* @typedef {Record<string, Replace>} FindAndReplaceSchema
24-
* @typedef {Array<FindAndReplaceTuple>} FindAndReplaceList
25-
*
26-
* @typedef {[RegExp, ReplaceFunction]} Pair
27-
* @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
2810
*/
2911

30-
/**
31-
* @callback ReplaceFunction
32-
* @param {...any} parameters
33-
* @returns {Array<Content>|Content|string|false|undefined|null}
34-
*/
35-
36-
import {visitParents} from 'unist-util-visit-parents'
37-
import {convertElement} from 'hast-util-is-element'
38-
import escape from 'escape-string-regexp'
39-
40-
const own = {}.hasOwnProperty
41-
42-
export const defaultIgnore = ['title', 'script', 'style', 'svg', 'math']
43-
44-
/**
45-
* @param {Node} tree
46-
* @param {Find|FindAndReplaceSchema|FindAndReplaceList} find
47-
* @param {Replace|Options} [replace]
48-
* @param {Options} [options]
49-
*/
50-
export function findAndReplace(tree, find, replace, options) {
51-
/** @type {Options|undefined} */
52-
let settings
53-
/** @type {FindAndReplaceSchema|FindAndReplaceList} */
54-
let schema
55-
56-
if (typeof find === 'string' || find instanceof RegExp) {
57-
// @ts-expect-error don’t expect options twice.
58-
schema = [[find, replace]]
59-
settings = options
60-
} else {
61-
schema = find
62-
// @ts-expect-error don’t expect replace twice.
63-
settings = replace
64-
}
65-
66-
if (!settings) {
67-
settings = {}
68-
}
69-
70-
const ignored = convertElement(settings.ignore || defaultIgnore)
71-
const pairs = toPairs(schema)
72-
let pairIndex = -1
73-
74-
while (++pairIndex < pairs.length) {
75-
visitParents(tree, 'text', visitor)
76-
}
77-
78-
return tree
79-
80-
/** @type {import('unist-util-visit-parents/complex-types').BuildVisitor<Node, 'text'>} */
81-
function visitor(node, parents) {
82-
let index = -1
83-
/** @type {Root|Element|undefined} */
84-
let grandparent
85-
86-
while (++index < parents.length) {
87-
const parent = parents[index]
88-
89-
if (
90-
ignored(
91-
parent,
92-
// @ts-expect-error: TS doesn’t understand but it’s perfect.
93-
grandparent ? grandparent.children.indexOf(parent) : undefined,
94-
grandparent
95-
)
96-
) {
97-
return
98-
}
99-
100-
grandparent = parent
101-
}
102-
103-
if (grandparent) {
104-
return handler(node, grandparent)
105-
}
106-
}
107-
108-
/**
109-
* @param {Text} node
110-
* @param {Parent} parent
111-
* @returns {VisitorResult}
112-
*/
113-
function handler(node, parent) {
114-
const find = pairs[pairIndex][0]
115-
const replace = pairs[pairIndex][1]
116-
let start = 0
117-
let index = parent.children.indexOf(node)
118-
/** @type {Array<Content>} */
119-
let nodes = []
120-
/** @type {number|undefined} */
121-
let position
122-
123-
find.lastIndex = 0
124-
125-
let match = find.exec(node.value)
126-
127-
while (match) {
128-
position = match.index
129-
let value = replace(...match, {index: match.index, input: match.input})
130-
131-
if (typeof value === 'string') {
132-
value = value.length > 0 ? {type: 'text', value} : undefined
133-
}
134-
135-
if (value !== false) {
136-
if (start !== position) {
137-
nodes.push({type: 'text', value: node.value.slice(start, position)})
138-
}
139-
140-
if (Array.isArray(value)) {
141-
nodes.push(...value)
142-
} else if (value) {
143-
nodes.push(value)
144-
}
145-
146-
start = position + match[0].length
147-
}
148-
149-
if (!find.global) {
150-
break
151-
}
152-
153-
match = find.exec(node.value)
154-
}
155-
156-
if (position === undefined) {
157-
nodes = [node]
158-
index--
159-
} else {
160-
if (start < node.value.length) {
161-
nodes.push({type: 'text', value: node.value.slice(start)})
162-
}
163-
164-
parent.children.splice(index, 1, ...nodes)
165-
}
166-
167-
return index + nodes.length + 1
168-
}
169-
}
170-
171-
/**
172-
* @param {FindAndReplaceSchema|FindAndReplaceList} schema
173-
* @returns {Pairs}
174-
*/
175-
function toPairs(schema) {
176-
/** @type {Pairs} */
177-
const result = []
178-
179-
if (typeof schema !== 'object') {
180-
throw new TypeError('Expected array or object as schema')
181-
}
182-
183-
if (Array.isArray(schema)) {
184-
let index = -1
185-
186-
while (++index < schema.length) {
187-
result.push([
188-
toExpression(schema[index][0]),
189-
toFunction(schema[index][1])
190-
])
191-
}
192-
} else {
193-
/** @type {string} */
194-
let key
195-
196-
for (key in schema) {
197-
if (own.call(schema, key)) {
198-
result.push([toExpression(key), toFunction(schema[key])])
199-
}
200-
}
201-
}
202-
203-
return result
204-
}
205-
206-
/**
207-
* @param {Find} find
208-
* @returns {RegExp}
209-
*/
210-
function toExpression(find) {
211-
return typeof find === 'string' ? new RegExp(escape(find), 'g') : find
212-
}
213-
214-
/**
215-
* @param {Replace} replace
216-
* @returns {ReplaceFunction}
217-
*/
218-
function toFunction(replace) {
219-
return typeof replace === 'function' ? replace : () => replace
220-
}
12+
export {defaultIgnore, findAndReplace} from './lib/index.js'

0 commit comments

Comments
 (0)