Tokenize, merge, and subtract space-separated booru tag queries
Tento skript by neměl být instalován přímo. Jedná se o knihovnu, kterou by měly jiné skripty využívat pomocí meta příkazu // @require https://update.greasyfork.org/scripts/583965/1875072/Brazen%20Framework%20-%20Tag%20Query%20Engine.js
Optional. Core algorithms for sites where the whole search query is one space-separated string (Gelbooru-style tags=, Shimmie path segments, etc.): tokenize with parenthesis-aware OR-groups, merge default filters idempotently, subtract defaults for display.
Greasy Fork: 583965 · Requires: Utilities · @require after Item Attributes Resolver, before site adapters and Framework core.
Site-specific URL shapes, empty-query sentinels, and atom normalization live in adapters (e.g. Gelbooru Family Search Adapter), not in this module.
| Idiom | Example | This module |
|---|---|---|
| Single param / path carries full query | ?tags=catgirl -gore sort:score:desc |
Yes — tokenize / merge / subtract |
| Distinct form params per filter | e-hentai f_srdd, f_spf |
No — use framework togglable-operation helpers only |
Pair with a search adapter that implements read/write/serialize for your site's wire format. See the workspace search-augmentation and search-defaults-injection pattern specs.
This engine is typically used inside a script that extends BrazenFramework, to implement default token injection without redirect loops:
const engine = new BrazenTagQueryEngine({
singleInstanceKeys: new Set(['sort', 'rating', 'width', 'height']),
})
const defaults = ['sort:score:desc', 'rating:explicit']
const current = /* read current query string from your adapter */
const mergedTokens = engine.merge(current, defaults)
const merged = mergedTokens.join(' ')
// Redirect only if something actually changed.
if (merged !== engine.tokenize(current).join(' ')) {
location.href = /* adapter.buildListUrl(merged) */
}
What it does: Splits a query string on whitespace, but treats balanced parenthesis groups ( ... ) as a single token.\n\nThis is important on “tag query” sites where OR groups are written as one logical unit.
What it does: merge(userQuery, defaultTokens) appends default tokens after user tokens while:\n\n- Skipping exact duplicates\n- Respecting singleInstanceKeys (if the user already set a key, defaults for that key are skipped)\n- Remaining idempotent (merging an already-merged query yields the same token list) so your injection logic can safely run on every page load.
What it does: subtract(tokens, defaultTokens) removes exact default tokens for “display mode” (e.g. writing a cleaner query string back into the search input).
BrazenTagQueryEngineConstructor: new BrazenTagQueryEngine(options?)
| Option | Default | Role |
|---|---|---|
singleInstanceKeys |
new Set() |
Metatag keys that accept at most one token per query; defaults with the same key are skipped when the user already set that key |
metatagKey |
BrazenTagQueryEngine.defaultMetatagKey |
`(token) => string \ |
defaultMetatagKey(token)Returns the substring before the first : for metatag tokens; ignores a leading -. Returns null when the token is a plain tag or starts with (.
| Method | Returns | Description |
|---|---|---|
tokenize(query) |
string[] |
Split on whitespace; keep ( … ) groups as single tokens (paren-depth tracking) |
metatagKey(token) |
`string \ | null` |
merge(userQuery, defaultTokens) |
string[] |
Append defaults after user tokens; skip single-instance key conflicts and exact duplicates. Idempotent — re-merging an already merged query yields the same token list (redirect loop guard) |
subtract(tokens, defaultTokens) |
string[] |
Remove tokens present in defaultTokens (exact match) — for showing user-only tags in the search input |
const engine = new BrazenTagQueryEngine({
singleInstanceKeys: new Set(['sort', 'rating', 'width', 'height']),
})
let user = engine.tokenize('catgirl -gore')
let defaults = ['sort:score:desc', 'rating:explicit']
let merged = engine.merge(user.join(' '), defaults) // ['catgirl', '-gore', 'sort:score:desc', 'rating:explicit']
let display = engine.subtract(merged, defaults).join(' ') // 'catgirl -gore'
( a ~ b ) is one token; never split on spaces inside balanced parentheses.width and height are typically single-instance per dimension: one user width:>=1000 suppresses default width tokens only, not height defaults.Adapters supply singleInstanceKeys for each site family (Gelbooru, Shimmie, etc.).
new BrazenTagQueryEngine(options?)BrazenTagQueryEngine.defaultMetatagKey(token)tokenize(query), metatagKey(token), merge(userQuery, defaultTokens), subtract(tokens, defaultTokens)This module declares no Tampermonkey grants.
@run-at document-end
Next in stack (typical): Gelbooru Family Search Adapter (optional) → Framework core