@tooee/fuzzy 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Fuzzy match a query against text, returning match positions and a score.
3
+ *
4
+ * Scoring:
5
+ * - +3 for a match at the start of the string
6
+ * - +2 for a match after a word boundary (space, hyphen, underscore, dot, slash)
7
+ * - +1 for a consecutive match
8
+ *
9
+ * Returns null if the query doesn't match.
10
+ */
11
+ export declare function fuzzyMatchPositions(query: string, text: string): {
12
+ score: number;
13
+ positions: number[];
14
+ } | null;
15
+ /**
16
+ * Fuzzy match a query against text, returning only the score.
17
+ * Returns null if the query doesn't match.
18
+ */
19
+ export declare function fuzzyMatch(query: string, text: string): number | null;
20
+ //# sourceMappingURL=fuzzy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy.d.ts","sourceRoot":"","sources":["../src/fuzzy.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAyB/C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGrE"}
package/dist/fuzzy.js ADDED
@@ -0,0 +1,45 @@
1
+ const WORD_BOUNDARY_CHARS = new Set([" ", "-", "_", ".", "/"]);
2
+ /**
3
+ * Fuzzy match a query against text, returning match positions and a score.
4
+ *
5
+ * Scoring:
6
+ * - +3 for a match at the start of the string
7
+ * - +2 for a match after a word boundary (space, hyphen, underscore, dot, slash)
8
+ * - +1 for a consecutive match
9
+ *
10
+ * Returns null if the query doesn't match.
11
+ */
12
+ export function fuzzyMatchPositions(query, text) {
13
+ const lowerQuery = query.toLowerCase();
14
+ const lowerText = text.toLowerCase();
15
+ const positions = [];
16
+ let score = 0;
17
+ let qi = 0;
18
+ for (let ti = 0; ti < lowerText.length && qi < lowerQuery.length; ti++) {
19
+ if (lowerText[ti] === lowerQuery[qi]) {
20
+ positions.push(ti);
21
+ if (ti === 0) {
22
+ score += 3;
23
+ }
24
+ else if (WORD_BOUNDARY_CHARS.has(lowerText[ti - 1])) {
25
+ score += 2;
26
+ }
27
+ else if (positions.length > 1 && positions[positions.length - 2] === ti - 1) {
28
+ score += 1;
29
+ }
30
+ qi++;
31
+ }
32
+ }
33
+ if (qi < lowerQuery.length)
34
+ return null;
35
+ return { score, positions };
36
+ }
37
+ /**
38
+ * Fuzzy match a query against text, returning only the score.
39
+ * Returns null if the query doesn't match.
40
+ */
41
+ export function fuzzyMatch(query, text) {
42
+ const result = fuzzyMatchPositions(query, text);
43
+ return result ? result.score : null;
44
+ }
45
+ //# sourceMappingURL=fuzzy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy.js","sourceRoot":"","sources":["../src/fuzzy.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;AAE9D;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,IAAY;IAEZ,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IACpC,MAAM,SAAS,GAAa,EAAE,CAAA;IAC9B,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,EAAE,GAAG,CAAC,CAAA;IAEV,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,MAAM,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QACvE,IAAI,SAAS,CAAC,EAAE,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;YACrC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAElB,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;gBACb,KAAK,IAAI,CAAC,CAAA;YACZ,CAAC;iBAAM,IAAI,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtD,KAAK,IAAI,CAAC,CAAA;YACZ,CAAC;iBAAM,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;gBAC9E,KAAK,IAAI,CAAC,CAAA;YACZ,CAAC;YAED,EAAE,EAAE,CAAA;QACN,CAAC;IACH,CAAC;IAED,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IACvC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,IAAY;IACpD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAC/C,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;AACrC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { fuzzyMatch, fuzzyMatchPositions } from "./fuzzy.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { fuzzyMatch, fuzzyMatchPositions } from "./fuzzy.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@tooee/fuzzy",
3
+ "version": "0.1.11",
4
+ "description": "Fuzzy string matching for Tooee",
5
+ "keywords": [
6
+ "filter",
7
+ "fuzzy",
8
+ "search",
9
+ "terminal",
10
+ "tui"
11
+ ],
12
+ "homepage": "https://github.com/gingerhendrix/tooee",
13
+ "bugs": "https://github.com/gingerhendrix/tooee/issues",
14
+ "license": "MIT",
15
+ "author": "Gareth Andrew",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/gingerhendrix/tooee.git",
19
+ "directory": "packages/fuzzy"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "src"
24
+ ],
25
+ "type": "module",
26
+ "exports": {
27
+ ".": {
28
+ "import": {
29
+ "@tooee/source": "./src/index.ts",
30
+ "default": "./dist/index.js"
31
+ }
32
+ }
33
+ },
34
+ "scripts": {
35
+ "typecheck": "tsc --noEmit"
36
+ },
37
+ "devDependencies": {
38
+ "typescript": "^5.9.3"
39
+ }
40
+ }
package/src/fuzzy.ts ADDED
@@ -0,0 +1,50 @@
1
+ const WORD_BOUNDARY_CHARS = new Set([" ", "-", "_", ".", "/"])
2
+
3
+ /**
4
+ * Fuzzy match a query against text, returning match positions and a score.
5
+ *
6
+ * Scoring:
7
+ * - +3 for a match at the start of the string
8
+ * - +2 for a match after a word boundary (space, hyphen, underscore, dot, slash)
9
+ * - +1 for a consecutive match
10
+ *
11
+ * Returns null if the query doesn't match.
12
+ */
13
+ export function fuzzyMatchPositions(
14
+ query: string,
15
+ text: string,
16
+ ): { score: number; positions: number[] } | null {
17
+ const lowerQuery = query.toLowerCase()
18
+ const lowerText = text.toLowerCase()
19
+ const positions: number[] = []
20
+ let score = 0
21
+ let qi = 0
22
+
23
+ for (let ti = 0; ti < lowerText.length && qi < lowerQuery.length; ti++) {
24
+ if (lowerText[ti] === lowerQuery[qi]) {
25
+ positions.push(ti)
26
+
27
+ if (ti === 0) {
28
+ score += 3
29
+ } else if (WORD_BOUNDARY_CHARS.has(lowerText[ti - 1])) {
30
+ score += 2
31
+ } else if (positions.length > 1 && positions[positions.length - 2] === ti - 1) {
32
+ score += 1
33
+ }
34
+
35
+ qi++
36
+ }
37
+ }
38
+
39
+ if (qi < lowerQuery.length) return null
40
+ return { score, positions }
41
+ }
42
+
43
+ /**
44
+ * Fuzzy match a query against text, returning only the score.
45
+ * Returns null if the query doesn't match.
46
+ */
47
+ export function fuzzyMatch(query: string, text: string): number | null {
48
+ const result = fuzzyMatchPositions(query, text)
49
+ return result ? result.score : null
50
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { fuzzyMatch, fuzzyMatchPositions } from "./fuzzy.js"