Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/engine-adr0061-icontains-docblock.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
---
"@objectstack/objectql": patch
---

docs(objectql): correct the ADR-0061 search-expansion docblock to `$icontains` (#13744)

Comment-only, zero behaviour. The ADR-0061 docblock on `ObjectQL`'s
`expandSearchOnAst` described the `$search` expansion as a cross-field `$or` of
`$contains` in **two** places, and both were false:

- "expand `search` into a server-resolved cross-field `$or` of `$contains`" —
the shape of the expansion;
- "All drivers already execute `$or`/`$contains`, so this needs no driver
changes" — the easier one to miss, because it reads as a statement of fact
about driver capability rather than a description of the expansion.

The implementation one file over (`search-filter.ts`) emits `$icontains` for the
source-column clauses and records the adjudication in its own header:
"[#7641] The case-insensitive operator is `$icontains`, NOT `$contains`." The
two files contradicted each other and the implementation was the correct one, so
the docblock is brought into line with it. `search-filter.ts` is not touched.

Why a stale comment was worth a change at all: `engine.ts` is the file an agent
working the query engine reads first, so a docblock asserting the retired
spelling is a live invitation to re-introduce the defect #7641 paid to retire.

Deliberately NOT changed, in the same file: the multi-value containment passage
on `referenceProbeFilter`, where `$contains` is the *correct* spelling — that
paragraph is about membership over a stored array, not about ADR-0061 search
expansion. Likewise the `__search` companion clause in `search-filter.ts`, which
stays `$contains` by design (both sides are already lowercase, so a
case-sensitive operator over two folded values is exact).
4 changes: 2 additions & 2 deletions packages/objectql/src/engine.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8644,7 +8644,7 @@ export class ObjectQL implements IObjectQLEngine {

/**
* ADR-0061: expand `search` into a server-resolved cross-field `$or` of
* `$contains`, AND it with any caller `where`, then strip the search keys off
* `$icontains`, AND it with any caller `where`, then strip the search keys off
* the AST.
*
* Shared by `find` and `findOne` (#4419). It lived inline in `find` and
Expand All@@ -8661,7 +8661,7 @@ export class ObjectQL implements IObjectQLEngine {
*
* Field resolution is server-side (declared `searchableFields` →
* auto-default); the optional `searchFields` override is intersected with the
* allowed set, never widened. All drivers already execute `$or`/`$contains`,
* allowed set, never widened. All drivers already execute `$or`/`$icontains`,
* so this needs no driver changes.
*
* The keys are deleted whether or not anything expanded — leaving them on
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/engine-adr0061-icontains-docblock.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
---
"@objectstack/objectql": patch
---

docs(objectql): correct the ADR-0061 search-expansion docblock to `$icontains` (#13744)

Comment-only, zero behaviour. The ADR-0061 docblock on `ObjectQL`'s
`expandSearchOnAst` described the `$search` expansion as a cross-field `$or` of
`$contains` in **two** places, and both were false:

- "expand `search` into a server-resolved cross-field `$or` of `$contains`" —
the shape of the expansion;
- "All drivers already execute `$or`/`$contains`, so this needs no driver
changes" — the easier one to miss, because it reads as a statement of fact
about driver capability rather than a description of the expansion.

The implementation one file over (`search-filter.ts`) emits `$icontains` for the
source-column clauses and records the adjudication in its own header:
"[#7641] The case-insensitive operator is `$icontains`, NOT `$contains`." The
two files contradicted each other and the implementation was the correct one, so
the docblock is brought into line with it. `search-filter.ts` is not touched.

Why a stale comment was worth a change at all: `engine.ts` is the file an agent
working the query engine reads first, so a docblock asserting the retired
spelling is a live invitation to re-introduce the defect #7641 paid to retire.

Deliberately NOT changed, in the same file: the multi-value containment passage
on `referenceProbeFilter`, where `$contains` is the *correct* spelling — that
paragraph is about membership over a stored array, not about ADR-0061 search
expansion. Likewise the `__search` companion clause in `search-filter.ts`, which
stays `$contains` by design (both sides are already lowercase, so a
case-sensitive operator over two folded values is exact).
4 changes: 2 additions & 2 deletions packages/objectql/src/engine.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8644,7 +8644,7 @@ export class ObjectQL implements IObjectQLEngine {

/**
* ADR-0061: expand `search` into a server-resolved cross-field `$or` of
* `$contains`, AND it with any caller `where`, then strip the search keys off
* `$icontains`, AND it with any caller `where`, then strip the search keys off
* the AST.
*
* Shared by `find` and `findOne` (#4419). It lived inline in `find` and
Expand All@@ -8661,7 +8661,7 @@ export class ObjectQL implements IObjectQLEngine {
*
* Field resolution is server-side (declared `searchableFields` →
* auto-default); the optional `searchFields` override is intersected with the
* allowed set, never widened. All drivers already execute `$or`/`$contains`,
* allowed set, never widened. All drivers already execute `$or`/`$icontains`,
* so this needs no driver changes.
*
* The keys are deleted whether or not anything expanded — leaving them on
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/engine-adr0061-icontains-docblock.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
---
"@objectstack/objectql": patch
---

docs(objectql): correct the ADR-0061 search-expansion docblock to `$icontains` (#13744)

Comment-only, zero behaviour. The ADR-0061 docblock on `ObjectQL`'s
`expandSearchOnAst` described the `$search` expansion as a cross-field `$or` of
`$contains` in **two** places, and both were false:

- "expand `search` into a server-resolved cross-field `$or` of `$contains`" —
the shape of the expansion;
- "All drivers already execute `$or`/`$contains`, so this needs no driver
changes" — the easier one to miss, because it reads as a statement of fact
about driver capability rather than a description of the expansion.

The implementation one file over (`search-filter.ts`) emits `$icontains` for the
source-column clauses and records the adjudication in its own header:
"[#7641] The case-insensitive operator is `$icontains`, NOT `$contains`." The
two files contradicted each other and the implementation was the correct one, so
the docblock is brought into line with it. `search-filter.ts` is not touched.

Why a stale comment was worth a change at all: `engine.ts` is the file an agent
working the query engine reads first, so a docblock asserting the retired
spelling is a live invitation to re-introduce the defect #7641 paid to retire.

Deliberately NOT changed, in the same file: the multi-value containment passage
on `referenceProbeFilter`, where `$contains` is the *correct* spelling — that
paragraph is about membership over a stored array, not about ADR-0061 search
expansion. Likewise the `__search` companion clause in `search-filter.ts`, which
stays `$contains` by design (both sides are already lowercase, so a
case-sensitive operator over two folded values is exact).
4 changes: 2 additions & 2 deletions packages/objectql/src/engine.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8644,7 +8644,7 @@ export class ObjectQL implements IObjectQLEngine {

/**
* ADR-0061: expand `search` into a server-resolved cross-field `$or` of
* `$contains`, AND it with any caller `where`, then strip the search keys off
* `$icontains`, AND it with any caller `where`, then strip the search keys off
* the AST.
*
* Shared by `find` and `findOne` (#4419). It lived inline in `find` and
Expand All@@ -8661,7 +8661,7 @@ export class ObjectQL implements IObjectQLEngine {
*
* Field resolution is server-side (declared `searchableFields` →
* auto-default); the optional `searchFields` override is intersected with the
* allowed set, never widened. All drivers already execute `$or`/`$contains`,
* allowed set, never widened. All drivers already execute `$or`/`$icontains`,
* so this needs no driver changes.
*
* The keys are deleted whether or not anything expanded — leaving them on
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/engine-adr0061-icontains-docblock.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
---
"@objectstack/objectql": patch
---

docs(objectql): correct the ADR-0061 search-expansion docblock to `$icontains` (#13744)

Comment-only, zero behaviour. The ADR-0061 docblock on `ObjectQL`'s
`expandSearchOnAst` described the `$search` expansion as a cross-field `$or` of
`$contains` in **two** places, and both were false:

- "expand `search` into a server-resolved cross-field `$or` of `$contains`" —
the shape of the expansion;
- "All drivers already execute `$or`/`$contains`, so this needs no driver
changes" — the easier one to miss, because it reads as a statement of fact
about driver capability rather than a description of the expansion.

The implementation one file over (`search-filter.ts`) emits `$icontains` for the
source-column clauses and records the adjudication in its own header:
"[#7641] The case-insensitive operator is `$icontains`, NOT `$contains`." The
two files contradicted each other and the implementation was the correct one, so
the docblock is brought into line with it. `search-filter.ts` is not touched.

Why a stale comment was worth a change at all: `engine.ts` is the file an agent
working the query engine reads first, so a docblock asserting the retired
spelling is a live invitation to re-introduce the defect #7641 paid to retire.

Deliberately NOT changed, in the same file: the multi-value containment passage
on `referenceProbeFilter`, where `$contains` is the *correct* spelling — that
paragraph is about membership over a stored array, not about ADR-0061 search
expansion. Likewise the `__search` companion clause in `search-filter.ts`, which
stays `$contains` by design (both sides are already lowercase, so a
case-sensitive operator over two folded values is exact).
4 changes: 2 additions & 2 deletions packages/objectql/src/engine.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8644,7 +8644,7 @@ export class ObjectQL implements IObjectQLEngine {

/**
* ADR-0061: expand `search` into a server-resolved cross-field `$or` of
* `$contains`, AND it with any caller `where`, then strip the search keys off
* `$icontains`, AND it with any caller `where`, then strip the search keys off
* the AST.
*
* Shared by `find` and `findOne` (#4419). It lived inline in `find` and
Expand All@@ -8661,7 +8661,7 @@ export class ObjectQL implements IObjectQLEngine {
*
* Field resolution is server-side (declared `searchableFields` →
* auto-default); the optional `searchFields` override is intersected with the
* allowed set, never widened. All drivers already execute `$or`/`$contains`,
* allowed set, never widened. All drivers already execute `$or`/`$icontains`,
* so this needs no driver changes.
*
* The keys are deleted whether or not anything expanded — leaving them on
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/engine-adr0061-icontains-docblock.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
---
"@objectstack/objectql": patch
---

docs(objectql): correct the ADR-0061 search-expansion docblock to `$icontains` (#13744)

Comment-only, zero behaviour. The ADR-0061 docblock on `ObjectQL`'s
`expandSearchOnAst` described the `$search` expansion as a cross-field `$or` of
`$contains` in **two** places, and both were false:

- "expand `search` into a server-resolved cross-field `$or` of `$contains`" —
the shape of the expansion;
- "All drivers already execute `$or`/`$contains`, so this needs no driver
changes" — the easier one to miss, because it reads as a statement of fact
about driver capability rather than a description of the expansion.

The implementation one file over (`search-filter.ts`) emits `$icontains` for the
source-column clauses and records the adjudication in its own header:
"[#7641] The case-insensitive operator is `$icontains`, NOT `$contains`." The
two files contradicted each other and the implementation was the correct one, so
the docblock is brought into line with it. `search-filter.ts` is not touched.

Why a stale comment was worth a change at all: `engine.ts` is the file an agent
working the query engine reads first, so a docblock asserting the retired
spelling is a live invitation to re-introduce the defect #7641 paid to retire.

Deliberately NOT changed, in the same file: the multi-value containment passage
on `referenceProbeFilter`, where `$contains` is the *correct* spelling — that
paragraph is about membership over a stored array, not about ADR-0061 search
expansion. Likewise the `__search` companion clause in `search-filter.ts`, which
stays `$contains` by design (both sides are already lowercase, so a
case-sensitive operator over two folded values is exact).
4 changes: 2 additions & 2 deletions packages/objectql/src/engine.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8644,7 +8644,7 @@ export class ObjectQL implements IObjectQLEngine {

/**
* ADR-0061: expand `search` into a server-resolved cross-field `$or` of
* `$contains`, AND it with any caller `where`, then strip the search keys off
* `$icontains`, AND it with any caller `where`, then strip the search keys off
* the AST.
*
* Shared by `find` and `findOne` (#4419). It lived inline in `find` and
Expand All@@ -8661,7 +8661,7 @@ export class ObjectQL implements IObjectQLEngine {
*
* Field resolution is server-side (declared `searchableFields` →
* auto-default); the optional `searchFields` override is intersected with the
* allowed set, never widened. All drivers already execute `$or`/`$contains`,
* allowed set, never widened. All drivers already execute `$or`/`$icontains`,
* so this needs no driver changes.
*
* The keys are deleted whether or not anything expanded — leaving them on
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/engine-adr0061-icontains-docblock.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
---
"@objectstack/objectql": patch
---

docs(objectql): correct the ADR-0061 search-expansion docblock to `$icontains` (#13744)

Comment-only, zero behaviour. The ADR-0061 docblock on `ObjectQL`'s
`expandSearchOnAst` described the `$search` expansion as a cross-field `$or` of
`$contains` in **two** places, and both were false:

- "expand `search` into a server-resolved cross-field `$or` of `$contains`" —
the shape of the expansion;
- "All drivers already execute `$or`/`$contains`, so this needs no driver
changes" — the easier one to miss, because it reads as a statement of fact
about driver capability rather than a description of the expansion.

The implementation one file over (`search-filter.ts`) emits `$icontains` for the
source-column clauses and records the adjudication in its own header:
"[#7641] The case-insensitive operator is `$icontains`, NOT `$contains`." The
two files contradicted each other and the implementation was the correct one, so
the docblock is brought into line with it. `search-filter.ts` is not touched.

Why a stale comment was worth a change at all: `engine.ts` is the file an agent
working the query engine reads first, so a docblock asserting the retired
spelling is a live invitation to re-introduce the defect #7641 paid to retire.

Deliberately NOT changed, in the same file: the multi-value containment passage
on `referenceProbeFilter`, where `$contains` is the *correct* spelling — that
paragraph is about membership over a stored array, not about ADR-0061 search
expansion. Likewise the `__search` companion clause in `search-filter.ts`, which
stays `$contains` by design (both sides are already lowercase, so a
case-sensitive operator over two folded values is exact).
4 changes: 2 additions & 2 deletions packages/objectql/src/engine.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8644,7 +8644,7 @@ export class ObjectQL implements IObjectQLEngine {

/**
* ADR-0061: expand `search` into a server-resolved cross-field `$or` of
* `$contains`, AND it with any caller `where`, then strip the search keys off
* `$icontains`, AND it with any caller `where`, then strip the search keys off
* the AST.
*
* Shared by `find` and `findOne` (#4419). It lived inline in `find` and
Expand All@@ -8661,7 +8661,7 @@ export class ObjectQL implements IObjectQLEngine {
*
* Field resolution is server-side (declared `searchableFields` →
* auto-default); the optional `searchFields` override is intersected with the
* allowed set, never widened. All drivers already execute `$or`/`$contains`,
* allowed set, never widened. All drivers already execute `$or`/`$icontains`,
* so this needs no driver changes.
*
* The keys are deleted whether or not anything expanded — leaving them on
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/engine-adr0061-icontains-docblock.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
---
"@objectstack/objectql": patch
---

docs(objectql): correct the ADR-0061 search-expansion docblock to `$icontains` (#13744)

Comment-only, zero behaviour. The ADR-0061 docblock on `ObjectQL`'s
`expandSearchOnAst` described the `$search` expansion as a cross-field `$or` of
`$contains` in **two** places, and both were false:

- "expand `search` into a server-resolved cross-field `$or` of `$contains`" —
the shape of the expansion;
- "All drivers already execute `$or`/`$contains`, so this needs no driver
changes" — the easier one to miss, because it reads as a statement of fact
about driver capability rather than a description of the expansion.

The implementation one file over (`search-filter.ts`) emits `$icontains` for the
source-column clauses and records the adjudication in its own header:
"[#7641] The case-insensitive operator is `$icontains`, NOT `$contains`." The
two files contradicted each other and the implementation was the correct one, so
the docblock is brought into line with it. `search-filter.ts` is not touched.

Why a stale comment was worth a change at all: `engine.ts` is the file an agent
working the query engine reads first, so a docblock asserting the retired
spelling is a live invitation to re-introduce the defect #7641 paid to retire.

Deliberately NOT changed, in the same file: the multi-value containment passage
on `referenceProbeFilter`, where `$contains` is the *correct* spelling — that
paragraph is about membership over a stored array, not about ADR-0061 search
expansion. Likewise the `__search` companion clause in `search-filter.ts`, which
stays `$contains` by design (both sides are already lowercase, so a
case-sensitive operator over two folded values is exact).
4 changes: 2 additions & 2 deletions packages/objectql/src/engine.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8644,7 +8644,7 @@ export class ObjectQL implements IObjectQLEngine {

/**
* ADR-0061: expand `search` into a server-resolved cross-field `$or` of
* `$contains`, AND it with any caller `where`, then strip the search keys off
* `$icontains`, AND it with any caller `where`, then strip the search keys off
* the AST.
*
* Shared by `find` and `findOne` (#4419). It lived inline in `find` and
Expand All@@ -8661,7 +8661,7 @@ export class ObjectQL implements IObjectQLEngine {
*
* Field resolution is server-side (declared `searchableFields` →
* auto-default); the optional `searchFields` override is intersected with the
* allowed set, never widened. All drivers already execute `$or`/`$contains`,
* allowed set, never widened. All drivers already execute `$or`/`$icontains`,
* so this needs no driver changes.
*
* The keys are deleted whether or not anything expanded — leaving them on
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/engine-adr0061-icontains-docblock.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
---
"@objectstack/objectql": patch
---

docs(objectql): correct the ADR-0061 search-expansion docblock to `$icontains` (#13744)

Comment-only, zero behaviour. The ADR-0061 docblock on `ObjectQL`'s
`expandSearchOnAst` described the `$search` expansion as a cross-field `$or` of
`$contains` in **two** places, and both were false:

- "expand `search` into a server-resolved cross-field `$or` of `$contains`" —
the shape of the expansion;
- "All drivers already execute `$or`/`$contains`, so this needs no driver
changes" — the easier one to miss, because it reads as a statement of fact
about driver capability rather than a description of the expansion.

The implementation one file over (`search-filter.ts`) emits `$icontains` for the
source-column clauses and records the adjudication in its own header:
"[#7641] The case-insensitive operator is `$icontains`, NOT `$contains`." The
two files contradicted each other and the implementation was the correct one, so
the docblock is brought into line with it. `search-filter.ts` is not touched.

Why a stale comment was worth a change at all: `engine.ts` is the file an agent
working the query engine reads first, so a docblock asserting the retired
spelling is a live invitation to re-introduce the defect #7641 paid to retire.

Deliberately NOT changed, in the same file: the multi-value containment passage
on `referenceProbeFilter`, where `$contains` is the *correct* spelling — that
paragraph is about membership over a stored array, not about ADR-0061 search
expansion. Likewise the `__search` companion clause in `search-filter.ts`, which
stays `$contains` by design (both sides are already lowercase, so a
case-sensitive operator over two folded values is exact).
4 changes: 2 additions & 2 deletions packages/objectql/src/engine.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8644,7 +8644,7 @@ export class ObjectQL implements IObjectQLEngine {

/**
* ADR-0061: expand `search` into a server-resolved cross-field `$or` of
* `$contains`, AND it with any caller `where`, then strip the search keys off
* `$icontains`, AND it with any caller `where`, then strip the search keys off
* the AST.
*
* Shared by `find` and `findOne` (#4419). It lived inline in `find` and
Expand All@@ -8661,7 +8661,7 @@ export class ObjectQL implements IObjectQLEngine {
*
* Field resolution is server-side (declared `searchableFields` →
* auto-default); the optional `searchFields` override is intersected with the
* allowed set, never widened. All drivers already execute `$or`/`$contains`,
* allowed set, never widened. All drivers already execute `$or`/`$icontains`,
* so this needs no driver changes.
*
* The keys are deleted whether or not anything expanded — leaving them on
Expand Down
Loading