forked from NovemLinguae/UserScripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStringFilter.js
More file actions
80 lines (78 loc) · 2.76 KB
/
Copy pathStringFilter.js
File metadata and controls
80 lines (78 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
* Lets you use regex to specify what parts of a very long string you want to specify as "off limits", then you can do additional regex's and search/replace to the remaining parts of the string.
*/
export class StringFilter {
/**
* Does a replace, but specifies areas of the file that should NOT be replaced. Those areas are specified by providing an openingTag and a closingTag, and those areas are marked as off limits.
*/
surgicalReplaceOutsideTags( regex, replacement, haystack, openingTags, closingTags ) {
const allTags = [ ...openingTags, ...closingTags ];
const parts = this._splitStringUsingMultiplePatterns( haystack, allTags );
const resultArray = [];
for ( let part of parts ) {
let openingTagMatch = false;
for ( const tag of openingTags ) {
if ( part.startsWith( tag ) ) {
openingTagMatch = true;
break;
}
}
if ( !openingTagMatch ) {
part = part.replace( regex, replacement );
}
resultArray.push( part );
}
return resultArray.join( '' );
}
/**
* Does a replace, but specifies areas of the file that SHOULD be replaced, then skips the rest of the file. The area that should be replaced is specified by providing an openingTag and a closingTag.
*/
surgicalReplaceInsideTags( regex, replacement, haystack, openingTags, closingTags ) {
const allTags = [ ...openingTags, ...closingTags ];
const parts = this._splitStringUsingMultiplePatterns( haystack, allTags );
const resultArray = [];
for ( let part of parts ) {
for ( const tag of openingTags ) {
if ( part.startsWith( tag ) ) {
part = part.replace( regex, replacement );
}
}
resultArray.push( part );
}
return resultArray.join( '' );
}
/**
* Also keeps the pattern in the result, unlike string.prototype.split. Algorithm isn't perfect, will fail with this pattern: <ref>Test/>Test</ref>. But should be good enough for DraftCleaner stuff.
*
* @param {string} string
* @param {string[]} patterns
* @return {string[]}
*/
_splitStringUsingMultiplePatterns( string, patterns ) {
const length = string.length;
const result = [];
let positionOfLastMatch = 0;
for ( let i = 0; i < length; i++ ) {
const lookAhead = string.slice( i ); // the rest of the string after current position
let patternMatch = false;
for ( const pattern of patterns ) {
if ( lookAhead.startsWith( pattern ) ) {
patternMatch = true;
break;
}
}
if ( patternMatch ) {
const chunk = string.slice( positionOfLastMatch, i );
// if blank (happens if i=0 matches), continue instead of putting an empty "" into the array
if ( !chunk ) {
continue;
}
result.push( chunk );
positionOfLastMatch = i;
}
}
// Don't forget the last chunk.
result.push( string.slice( positionOfLastMatch ) );
return result;
}
}