Skip to content

Commit 999260c

Browse files
committed
fix(2.8.0): eslint.cjs + comment-free vendor sync
Rename eslint.config.js to eslint.config.cjs for ESM package type. Sync vendor/engine from glyph-s 2.8.0 with stripComments bundle.
1 parent 80fe97f commit 999260c

4 files changed

Lines changed: 12 additions & 175 deletions

File tree

eslint.config.js renamed to eslint.config.cjs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import js from '@eslint/js';
2-
import globals from 'globals';
1+
const js = require('@eslint/js');
2+
const globals = require('globals');
33

4-
export default [
4+
module.exports = [
55
js.configs.recommended,
6-
76
{
8-
ignores: ['node_modules/**', 'vendor/**', 'eslint.config.js', 'vitest.config.js'],
7+
ignores: ['node_modules/**', 'vendor/**', 'vitest.config.js'],
98
},
10-
119
{
1210
files: ['**/*.test.js'],
1311
languageOptions: {
@@ -18,7 +16,6 @@ export default [
1816
},
1917
},
2018
},
21-
2219
{
2320
files: ['**/*.js'],
2421
ignores: ['**/*.test.js'],
@@ -31,11 +28,11 @@ export default [
3128
},
3229
},
3330
rules: {
34-
'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
31+
'no-unused-vars': ['error', { argsIgnorePattern: '^_', caughtErrors: 'none' }],
3532
'prefer-const': 'error',
36-
'eqeqeq': ['error', 'always', { null: 'ignore' }],
37-
'semi': ['error', 'always'],
38-
'quotes': ['error', 'single', { avoidEscape: true }],
33+
eqeqeq: ['error', 'always', { null: 'ignore' }],
34+
semi: ['error', 'always'],
35+
quotes: ['error', 'single', { avoidEscape: true }],
3936
'no-var': 'error',
4037
},
4138
},

vendor/VERSION.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "glyph-s",
3-
"version": "2.7.2",
4-
"stampedAt": "2026-07-19T00:58:01.213Z",
3+
"version": "2.8.0",
4+
"stampedAt": "2026-07-20T11:57:03.687Z",
55
"files": [
66
"engine.js",
77
"engine.cjs",

vendor/engine.cjs

Lines changed: 1 addition & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
1-
/**
2-
* Query tokenization and extended search grammar.
3-
* @module tokenize
4-
*/
5-
6-
/**
7-
* Split a query into lowercase tokens on whitespace / punctuation.
8-
* @param {string} q
9-
* @returns {string[]}
10-
*/
111
function tokenizeQuery(q) {
122
return String(q || '')
133
.trim()
144
.toLowerCase()
15-
.split(/[\s#./_\-]+/)
5+
.split(/[\s#./_-]+/)
166
.filter(Boolean);
177
}
188

19-
/**
20-
* Parse extended query grammar into tokens + structured filters.
21-
* Supports phrases, exclusions, OR groups, and type/page/app/path/tag filters.
22-
* @param {string} raw
23-
* @returns {import('./types.js').ParsedSearchQuery}
24-
*/
259
function parseSearchQuery(raw) {
2610
const text = String(raw || '').trim();
2711
const filters = {
@@ -207,44 +191,24 @@ function expandQueryVariants(rawQ, settings = {}) {
207191
return Array.from(set);
208192
}
209193

210-
/**
211-
* Search quality/speed profiles for glyph-s.
212-
* Data lives in profiles.json; this module re-exports for ESM and CJS bundling.
213-
* @module profiles
214-
*/
215-
216-
/** @type {Record<string, import('./types.js').SearchProfileConfig>} */
217194
const PROFILE_SETTINGS = {
218195
legacy: { fuzzyCutoff: 0.4, scoreScale: 1, maxCandidates: 8000 },
219196
balanced: { fuzzyCutoff: 0.48, scoreScale: 1.08, maxCandidates: 4000 },
220197
'max-quality': { fuzzyCutoff: 0.35, scoreScale: 1.16, maxCandidates: 9000 },
221198
};
222199

223-
/**
224-
* Resolve a profile name to its config (falls back to `legacy`).
225-
* @param {string} [profile]
226-
* @returns {import('./types.js').SearchProfileConfig}
227-
*/
228200
function getProfileConfig(profile) {
229201
const key = String(profile || 'legacy').toLowerCase();
230202
return PROFILE_SETTINGS[key] || PROFILE_SETTINGS.legacy;
231203
}
232204

233-
/** Stable list of known profile ids. */
234205
const PROFILE_IDS = Object.freeze(['legacy', 'balanced', 'max-quality']);
235206

236-
/**
237-
* Glyph Search core: ranking, snippets, index + engine factory.
238-
* @module engine
239-
*/
240-
241207

242208

243209

244210

245-
/** @type {Record<string, number>} */
246211
const CAT_PRIORITY = { page: 40, note: 36, app: 32, release: 30, action: 24, news: 20 };
247-
/** @type {import('./types.js').SearchSettings} */
248212
const SEARCH_SETTINGS = { fuzzyLayout: true, fuzzyTransliteration: true };
249213
const TOKEN_VARIANT_CACHE = new Map();
250214
const SNIPPET_CACHE = new Map();
@@ -286,11 +250,6 @@ function getTokenVariantsCached(tok, settings) {
286250
return variants;
287251
}
288252

289-
/**
290-
* @param {import('./types.js').SearchItem} it
291-
* @param {import('./types.js').ParsedSearchQuery|null|undefined} filters
292-
* @returns {boolean}
293-
*/
294253
function matchesSearchFilters(it, filters) {
295254
if (!filters) return true;
296255
if (filters.type === 'release' && it.cat !== 'release') return false;
@@ -319,14 +278,6 @@ function matchesSearchFilters(it, filters) {
319278
return true;
320279
}
321280

322-
/**
323-
* Score one item against query tokens / filters.
324-
* @param {import('./types.js').SearchItem} it
325-
* @param {string[]} tokens
326-
* @param {import('./types.js').ParsedSearchQuery|null|undefined} filters
327-
* @param {import('./types.js').SearchSettings} [settings]
328-
* @returns {number}
329-
*/
330281
function scoreSearchItem(it, tokens, filters, settings = SEARCH_SETTINGS) {
331282
if (filters && !matchesSearchFilters(it, filters)) return 0;
332283
const title = it.title().toLowerCase();
@@ -424,14 +375,6 @@ function findSnippetInBlob(blob, tok, settings) {
424375
return null;
425376
}
426377

427-
/**
428-
* Build a short HTML-friendly snippet for the first matching token.
429-
* @param {import('./types.js').SearchItem} it
430-
* @param {string[]} tokens
431-
* @param {(s: string) => string} [esc]
432-
* @param {import('./types.js').SearchSettings} [settings]
433-
* @returns {string}
434-
*/
435378
function snippetForItem(it, tokens, esc = (s) => s, settings = SEARCH_SETTINGS) {
436379
if (!tokens.length) return '';
437380
const body = typeof it.body === 'function' ? it.body() : it.body || '';
@@ -464,10 +407,6 @@ function itemBodyText(it) {
464407
return String(it.body || '');
465408
}
466409

467-
/**
468-
* Cheap haystack for fast-path gating. MUST include body — otherwise
469-
* paragraph-only hits never reach scoreSearchItem (full-text search broken).
470-
*/
471410
function textBagForItem(it) {
472411
const title = String(it.title?.() || '').toLowerCase();
473412
const sub = String(it.sub || '').toLowerCase();
@@ -517,13 +456,6 @@ function collectTopK(scored, limit) {
517456
return top.sort((a, b) => b.score - a.score);
518457
}
519458

520-
/**
521-
* Rank corpus items for a query string.
522-
* @param {import('./types.js').SearchItem[]} items
523-
* @param {string} q
524-
* @param {import('./types.js').RankSearchOptions} [opts]
525-
* @returns {import('./types.js').RankedHit[]}
526-
*/
527459
function rankSearchItems(items, q, opts = {}) {
528460
const settings = { ...SEARCH_SETTINGS, ...(opts.settings || {}) };
529461
settings.profile = settings.profile || opts.profile || 'legacy';
@@ -533,7 +465,6 @@ function rankSearchItems(items, q, opts = {}) {
533465
const tokens = filters.tokens.length ? filters.tokens : tokenizeQuery(q);
534466
const limit = opts.limit ?? 12;
535467

536-
// Prefer precomputed bags from buildIndex / createSearchEngine when provided.
537468
const indexRows = Array.isArray(opts.index?.items) ? opts.index.items : null;
538469
const sourceLen = indexRows ? indexRows.length : items.length;
539470
const candidates = [];
@@ -567,12 +498,6 @@ function rankSearchItems(items, q, opts = {}) {
567498
return out;
568499
}
569500

570-
/**
571-
* Pre-compute text bags for repeated searches.
572-
* @param {import('./types.js').SearchItem[]} [items]
573-
* @param {import('./types.js').BuildIndexOptions} [opts]
574-
* @returns {import('./types.js').SearchIndex}
575-
*/
576501
function buildIndex(items = [], opts = {}) {
577502
const profile = opts.profile || 'legacy';
578503
const index = items.map((it, idx) => ({
@@ -584,11 +509,6 @@ function buildIndex(items = [], opts = {}) {
584509
return { items: index, profile, createdAt: Date.now() };
585510
}
586511

587-
/**
588-
* Create a reusable search engine bound to an index / items.
589-
* @param {import('./types.js').CreateSearchEngineOptions} [options]
590-
* @returns {import('./types.js').SearchEngine}
591-
*/
592512
function createSearchEngine(options = {}) {
593513
const profile = options.profile || 'balanced';
594514
const settings = { ...SEARCH_SETTINGS, ...(options.settings || {}), profile };

vendor/engine.js

Lines changed: 1 addition & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
1-
/**
2-
* Query tokenization and extended search grammar.
3-
* @module tokenize
4-
*/
5-
6-
/**
7-
* Split a query into lowercase tokens on whitespace / punctuation.
8-
* @param {string} q
9-
* @returns {string[]}
10-
*/
111
function tokenizeQuery(q) {
122
return String(q || '')
133
.trim()
144
.toLowerCase()
15-
.split(/[\s#./_\-]+/)
5+
.split(/[\s#./_-]+/)
166
.filter(Boolean);
177
}
188

19-
/**
20-
* Parse extended query grammar into tokens + structured filters.
21-
* Supports phrases, exclusions, OR groups, and type/page/app/path/tag filters.
22-
* @param {string} raw
23-
* @returns {import('./types.js').ParsedSearchQuery}
24-
*/
259
function parseSearchQuery(raw) {
2610
const text = String(raw || '').trim();
2711
const filters = {
@@ -207,44 +191,24 @@ function expandQueryVariants(rawQ, settings = {}) {
207191
return Array.from(set);
208192
}
209193

210-
/**
211-
* Search quality/speed profiles for glyph-s.
212-
* Data lives in profiles.json; this module re-exports for ESM and CJS bundling.
213-
* @module profiles
214-
*/
215-
216-
/** @type {Record<string, import('./types.js').SearchProfileConfig>} */
217194
const PROFILE_SETTINGS = {
218195
legacy: { fuzzyCutoff: 0.4, scoreScale: 1, maxCandidates: 8000 },
219196
balanced: { fuzzyCutoff: 0.48, scoreScale: 1.08, maxCandidates: 4000 },
220197
'max-quality': { fuzzyCutoff: 0.35, scoreScale: 1.16, maxCandidates: 9000 },
221198
};
222199

223-
/**
224-
* Resolve a profile name to its config (falls back to `legacy`).
225-
* @param {string} [profile]
226-
* @returns {import('./types.js').SearchProfileConfig}
227-
*/
228200
function getProfileConfig(profile) {
229201
const key = String(profile || 'legacy').toLowerCase();
230202
return PROFILE_SETTINGS[key] || PROFILE_SETTINGS.legacy;
231203
}
232204

233-
/** Stable list of known profile ids. */
234205
const PROFILE_IDS = Object.freeze(['legacy', 'balanced', 'max-quality']);
235206

236-
/**
237-
* Glyph Search core: ranking, snippets, index + engine factory.
238-
* @module engine
239-
*/
240-
241207

242208

243209

244210

245-
/** @type {Record<string, number>} */
246211
const CAT_PRIORITY = { page: 40, note: 36, app: 32, release: 30, action: 24, news: 20 };
247-
/** @type {import('./types.js').SearchSettings} */
248212
const SEARCH_SETTINGS = { fuzzyLayout: true, fuzzyTransliteration: true };
249213
const TOKEN_VARIANT_CACHE = new Map();
250214
const SNIPPET_CACHE = new Map();
@@ -286,11 +250,6 @@ function getTokenVariantsCached(tok, settings) {
286250
return variants;
287251
}
288252

289-
/**
290-
* @param {import('./types.js').SearchItem} it
291-
* @param {import('./types.js').ParsedSearchQuery|null|undefined} filters
292-
* @returns {boolean}
293-
*/
294253
function matchesSearchFilters(it, filters) {
295254
if (!filters) return true;
296255
if (filters.type === 'release' && it.cat !== 'release') return false;
@@ -319,14 +278,6 @@ function matchesSearchFilters(it, filters) {
319278
return true;
320279
}
321280

322-
/**
323-
* Score one item against query tokens / filters.
324-
* @param {import('./types.js').SearchItem} it
325-
* @param {string[]} tokens
326-
* @param {import('./types.js').ParsedSearchQuery|null|undefined} filters
327-
* @param {import('./types.js').SearchSettings} [settings]
328-
* @returns {number}
329-
*/
330281
function scoreSearchItem(it, tokens, filters, settings = SEARCH_SETTINGS) {
331282
if (filters && !matchesSearchFilters(it, filters)) return 0;
332283
const title = it.title().toLowerCase();
@@ -424,14 +375,6 @@ function findSnippetInBlob(blob, tok, settings) {
424375
return null;
425376
}
426377

427-
/**
428-
* Build a short HTML-friendly snippet for the first matching token.
429-
* @param {import('./types.js').SearchItem} it
430-
* @param {string[]} tokens
431-
* @param {(s: string) => string} [esc]
432-
* @param {import('./types.js').SearchSettings} [settings]
433-
* @returns {string}
434-
*/
435378
function snippetForItem(it, tokens, esc = (s) => s, settings = SEARCH_SETTINGS) {
436379
if (!tokens.length) return '';
437380
const body = typeof it.body === 'function' ? it.body() : it.body || '';
@@ -464,10 +407,6 @@ function itemBodyText(it) {
464407
return String(it.body || '');
465408
}
466409

467-
/**
468-
* Cheap haystack for fast-path gating. MUST include body — otherwise
469-
* paragraph-only hits never reach scoreSearchItem (full-text search broken).
470-
*/
471410
function textBagForItem(it) {
472411
const title = String(it.title?.() || '').toLowerCase();
473412
const sub = String(it.sub || '').toLowerCase();
@@ -517,13 +456,6 @@ function collectTopK(scored, limit) {
517456
return top.sort((a, b) => b.score - a.score);
518457
}
519458

520-
/**
521-
* Rank corpus items for a query string.
522-
* @param {import('./types.js').SearchItem[]} items
523-
* @param {string} q
524-
* @param {import('./types.js').RankSearchOptions} [opts]
525-
* @returns {import('./types.js').RankedHit[]}
526-
*/
527459
function rankSearchItems(items, q, opts = {}) {
528460
const settings = { ...SEARCH_SETTINGS, ...(opts.settings || {}) };
529461
settings.profile = settings.profile || opts.profile || 'legacy';
@@ -533,7 +465,6 @@ function rankSearchItems(items, q, opts = {}) {
533465
const tokens = filters.tokens.length ? filters.tokens : tokenizeQuery(q);
534466
const limit = opts.limit ?? 12;
535467

536-
// Prefer precomputed bags from buildIndex / createSearchEngine when provided.
537468
const indexRows = Array.isArray(opts.index?.items) ? opts.index.items : null;
538469
const sourceLen = indexRows ? indexRows.length : items.length;
539470
const candidates = [];
@@ -567,12 +498,6 @@ function rankSearchItems(items, q, opts = {}) {
567498
return out;
568499
}
569500

570-
/**
571-
* Pre-compute text bags for repeated searches.
572-
* @param {import('./types.js').SearchItem[]} [items]
573-
* @param {import('./types.js').BuildIndexOptions} [opts]
574-
* @returns {import('./types.js').SearchIndex}
575-
*/
576501
function buildIndex(items = [], opts = {}) {
577502
const profile = opts.profile || 'legacy';
578503
const index = items.map((it, idx) => ({
@@ -584,11 +509,6 @@ function buildIndex(items = [], opts = {}) {
584509
return { items: index, profile, createdAt: Date.now() };
585510
}
586511

587-
/**
588-
* Create a reusable search engine bound to an index / items.
589-
* @param {import('./types.js').CreateSearchEngineOptions} [options]
590-
* @returns {import('./types.js').SearchEngine}
591-
*/
592512
function createSearchEngine(options = {}) {
593513
const profile = options.profile || 'balanced';
594514
const settings = { ...SEARCH_SETTINGS, ...(options.settings || {}), profile };

0 commit comments

Comments
 (0)