Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
string.js201 linesDownload Raw Back to util
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.longestCommonPrefix = longestCommonPrefix;
4exports.longestCommonSuffix = longestCommonSuffix;
5exports.replacePrefix = replacePrefix;
6exports.replaceSuffix = replaceSuffix;
7exports.removePrefix = removePrefix;
8exports.removeSuffix = removeSuffix;
9exports.maximumOverlap = maximumOverlap;
10exports.hasOnlyWinLineEndings = hasOnlyWinLineEndings;
11exports.hasOnlyUnixLineEndings = hasOnlyUnixLineEndings;
12exports.segment = segment;
13exports.trailingWs = trailingWs;
14exports.leadingWs = leadingWs;
15exports.leadingAndTrailingWs = leadingAndTrailingWs;
16function longestCommonPrefix(str1, str2) {
17    var i;
18    for (i = 0; i < str1.length && i < str2.length; i++) {
19        if (str1[i] != str2[i]) {
20            return str1.slice(0, i);
21        }
22    }
23    return str1.slice(0, i);
24}
25function longestCommonSuffix(str1, str2) {
26    var i;
27    // Unlike longestCommonPrefix, we need a special case to handle all scenarios
28    // where we return the empty string since str1.slice(-0) will return the
29    // entire string.
30    if (!str1 || !str2 || str1[str1.length - 1] != str2[str2.length - 1]) {
31        return '';
32    }
33    for (i = 0; i < str1.length && i < str2.length; i++) {
34        if (str1[str1.length - (i + 1)] != str2[str2.length - (i + 1)]) {
35            return str1.slice(-i);
36        }
37    }
38    return str1.slice(-i);
39}
40function replacePrefix(string, oldPrefix, newPrefix) {
41    if (string.slice(0, oldPrefix.length) != oldPrefix) {
42        throw Error("string ".concat(JSON.stringify(string), " doesn't start with prefix ").concat(JSON.stringify(oldPrefix), "; this is a bug"));
43    }
44    return newPrefix + string.slice(oldPrefix.length);
45}
46function replaceSuffix(string, oldSuffix, newSuffix) {
47    if (!oldSuffix) {
48        return string + newSuffix;
49    }
50    if (string.slice(-oldSuffix.length) != oldSuffix) {
51        throw Error("string ".concat(JSON.stringify(string), " doesn't end with suffix ").concat(JSON.stringify(oldSuffix), "; this is a bug"));
52    }
53    return string.slice(0, -oldSuffix.length) + newSuffix;
54}
55function removePrefix(string, oldPrefix) {
56    return replacePrefix(string, oldPrefix, '');
57}
58function removeSuffix(string, oldSuffix) {
59    return replaceSuffix(string, oldSuffix, '');
60}
61function maximumOverlap(string1, string2) {
62    return string2.slice(0, overlapCount(string1, string2));
63}
64// Nicked from https://stackoverflow.com/a/60422853/1709587
65function overlapCount(a, b) {
66    // Deal with cases where the strings differ in length
67    var startA = 0;
68    if (a.length > b.length) {
69        startA = a.length - b.length;
70    }
71    var endB = b.length;
72    if (a.length < b.length) {
73        endB = a.length;
74    }
75    // Create a back-reference for each index
76    //   that should be followed in case of a mismatch.
77    //   We only need B to make these references:
78    var map = Array(endB);
79    var k = 0; // Index that lags behind j
80    map[0] = 0;
81    for (var j = 1; j < endB; j++) {
82        if (b[j] == b[k]) {
83            map[j] = map[k]; // skip over the same character (optional optimisation)
84        }
85        else {
86            map[j] = k;
87        }
88        while (k > 0 && b[j] != b[k]) {
89            k = map[k];
90        }
91        if (b[j] == b[k]) {
92            k++;
93        }
94    }
95    // Phase 2: use these references while iterating over A
96    k = 0;
97    for (var i = startA; i < a.length; i++) {
98        while (k > 0 && a[i] != b[k]) {
99            k = map[k];
100        }
101        if (a[i] == b[k]) {
102            k++;
103        }
104    }
105    return k;
106}
107/**
108 * Returns true if the string consistently uses Windows line endings.
109 */
110function hasOnlyWinLineEndings(string) {
111    return string.includes('\r\n') && !string.startsWith('\n') && !string.match(/[^\r]\n/);
112}
113/**
114 * Returns true if the string consistently uses Unix line endings.
115 */
116function hasOnlyUnixLineEndings(string) {
117    return !string.includes('\r\n') && string.includes('\n');
118}
119/**
120 * Split a string into segments using a word segmenter, merging consecutive
121 * segments if they are both whitespace segments. Whitespace segments can
122 * appear adjacent to one another for two reasons:
123 * - newlines always get their own segment
124 * - where a diacritic is attached to a whitespace character in the text, the
125 *   segment ends after the diacritic, so e.g. " \u0300 " becomes two segments.
126 * This function therefore runs the segmenter's .segment() method and then
127 * merges consecutive segments of whitespace into a single part.
128 */
129function segment(string, segmenter) {
130    var parts = [];
131    for (var _i = 0, _a = Array.from(segmenter.segment(string)); _i < _a.length; _i++) {
132        var segmentObj = _a[_i];
133        var segment_1 = segmentObj.segment;
134        if (parts.length && (/\s/).test(parts[parts.length - 1]) && (/\s/).test(segment_1)) {
135            parts[parts.length - 1] += segment_1;
136        }
137        else {
138            parts.push(segment_1);
139        }
140    }
141    return parts;
142}
143// The functions below take a `segmenter` argument so that, when called from
144// diffWords when it is using a segmenter, they can use a notion of what
145// constitutes "whitespace" that is consistent with the segmenter.
146//
147// USUALLY this will be identical to the result of the non-segmenter-based
148// logic, but it differs in at least one case: when whitespace characters are
149// modified by diacritics. A word segmenter considers these diacritics to be
150// part of the whitespace, whereas our non-segmenter-based logic does not.
151//
152// Because the segmenter-based approach necessarily requires segmenting the
153// entire string, we offer a leadingAndTrailingWs function to allow getting the
154// whitespace prefix AND whitespace suffix with a single call to the segmenter,
155// for efficiency's sake.
156function trailingWs(string, segmenter) {
157    if (segmenter) {
158        return leadingAndTrailingWs(string, segmenter)[1];
159    }
160    // Yes, this looks overcomplicated and dumb - why not replace the whole function with
161    //     return string.match(/\s*$/)[0]
162    // you ask? Because:
163    // 1. the trap described at https://markamery.com/blog/quadratic-time-regexes/ would mean doing
164    //    this would cause this function to take O(n²) time in the worst case (specifically when
165    //    there is a massive run of NON-TRAILING whitespace in `string`), and
166    // 2. the fix proposed in the same blog post, of using a negative lookbehind, is incompatible
167    //    with old Safari versions that we'd like to not break if possible (see
168    //    https://github.com/kpdecker/jsdiff/pull/550)
169    // It feels absurd to do this with an explicit loop instead of a regex, but I really can't see a
170    // better way that doesn't result in broken behaviour.
171    var i;
172    for (i = string.length - 1; i >= 0; i--) {
173        if (!string[i].match(/\s/)) {
174            break;
175        }
176    }
177    return string.substring(i + 1);
178}
179function leadingWs(string, segmenter) {
180    if (segmenter) {
181        return leadingAndTrailingWs(string, segmenter)[0];
182    }
183    // Thankfully the annoying considerations described in trailingWs don't apply here:
184    var match = string.match(/^\s*/);
185    return match ? match[0] : '';
186}
187function leadingAndTrailingWs(string, segmenter) {
188    if (!segmenter) {
189        return [leadingWs(string), trailingWs(string)];
190    }
191    if (segmenter.resolvedOptions().granularity != 'word') {
192        throw new Error('The segmenter passed must have a granularity of "word"');
193    }
194    var segments = segment(string, segmenter);
195    var firstSeg = segments[0];
196    var lastSeg = segments[segments.length - 1];
197    var head = (/\s/).test(firstSeg) ? firstSeg : '';
198    var tail = (/\s/).test(lastSeg) ? lastSeg : '';
199    return [head, tail];
200}
201 
codekingpro/portable-devtools · Team Ai