| 1 | function splitByPattern(tokens, pattern) { |
| 2 | const result = []; |
| 3 | for (let index = 0, length = tokens.length; index < length; index++) { |
| 4 | const token = tokens[index]; |
| 5 | if (token.type === 'list' || token.type === 'item') { |
| 6 | token.children = splitByPattern(token.children, pattern); |
| 7 | result.push(token); |
| 8 | } else if (token.type === 'text') { |
| 9 | const { value } = token; |
| 10 | const matches = value.match(pattern); |
| 11 | |
| 12 | if (matches) { |
| 13 | let indexes = []; |
| 14 | let needles = []; |
| 15 | let search = value.slice(); |
| 16 | for (const match of matches) { |
| 17 | const start = search.indexOf(match); |
| 18 | const end = start + match.length; |
| 19 | indexes.push(start); |
| 20 | needles.push(start); |
| 21 | indexes.push(end); |
| 22 | search = search.replace(match, '_'.repeat(match.length)); |
| 23 | } |
| 24 | |
| 25 | if (indexes[0] !== 0) { |
| 26 | indexes.unshift(0); |
| 27 | } |
| 28 | if (indexes[indexes.length - 1] !== value.length) { |
| 29 | indexes.push(value.length); |
| 30 | } |
| 31 | |
| 32 | for (let index = 0, length = indexes.length; index < length; index++) { |
| 33 | const current = indexes[index]; |
| 34 | const next = indexes[index + 1]; |
| 35 | if (typeof current === 'number' && typeof next === 'number') { |
| 36 | const text = value.substring(current, next); |
| 37 | if (needles.includes(current)) { |
| 38 | if (text.startsWith('[') && text.endsWith(')')) { |
| 39 | const title = text.substring(1, text.indexOf(']')); |
| 40 | const url = text.substring( |
| 41 | text.indexOf('(') + 1, |
| 42 | text.lastIndexOf(')') |
| 43 | ); |
| 44 | result.push({ |
| 45 | type: 'url', |
| 46 | url: url, |
| 47 | value: url, |
| 48 | source: text, |
| 49 | title: title, |
| 50 | }); |
| 51 | } else { |
| 52 | const [url, title] = text.split('|'); |
| 53 | result.push({ |
| 54 | type: 'url', |
| 55 | url: url, |
| 56 | value: url, |
| 57 | source: title ? `${url}|${title}` : url, |
| 58 | title: title || url, |
| 59 | }); |
| 60 | } |