Skip to content

Commit

Permalink
feat(supersearch): Add qualifier pill plugin (#1176)
Browse files Browse the repository at this point in the history
* Add extension with decorators

* Atomic ranges

* Insert quotes on empty value

* Keep extension and extension-specific components together

* Export qualifier plugin from supersearch package

* Remove sveltekit specific import

Imports from '$app/stores' are SvelteKit-specific imports which would require @sveltejs/kit to be added as a peer-dependency, resulting in larger bundle-sizes for non-svelte implementations.

* Add lxlquery language and qualifier plugin to demo app

* Add qualifier colors to demo page

* Capitalize lezer rules for qualifiers

* Use visibleRanges to only render widgets when visible

* Prepend qualifier classes with lxl

* Fix tests

---------

Co-authored-by: Johan Bisse Mattsson <[email protected]>
Co-authored-by: Johan Bisse Mattsson <[email protected]>
  • Loading branch information
3 people authored Nov 28, 2024
1 parent f29cb78 commit bf186fb
Show file tree
Hide file tree
Showing 15 changed files with 331 additions and 81 deletions.
3 changes: 2 additions & 1 deletion lxl-web/src/lib/components/Search.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { env } from '$env/dynamic/public';
import { page } from '$app/stores';
import { afterNavigate } from '$app/navigation';
import { SuperSearch } from 'supersearch';
import { SuperSearch, lxlQualifierPlugin } from 'supersearch';
import addDefaultSearchParams from '$lib/utils/addDefaultSearchParams';
import getSortedSearchParams from '$lib/utils/getSortedSearchParams';
import BiSearch from '~icons/bi/search';
Expand Down Expand Up @@ -70,6 +70,7 @@
_limit: '10'
})}
paginationQueryFn={handlePaginationQuery}
extensions={[lxlQualifierPlugin]}
>
{#snippet resultItem(item)}
<button type="button">
Expand Down
27 changes: 8 additions & 19 deletions lxl-web/src/lib/styles/lxlquery.css
Original file line number Diff line number Diff line change
@@ -1,28 +1,17 @@
.lxlq.qualifier {
color: green;
.lxl-qualifier,
.lxl-qualifier-remove {
background: rgba(14, 113, 128, 0.15);
padding: 2px 5px;
}

.lxlq.qualifier-key {
.lxl-qualifier-key {
color: green;
}

.lxlq.qualifier-value {
color: green;
}

.lxlq.equal-operator,
.lxlq.compare-operator {
color: darkolivegreen;
}

.lxlq.boolean-operator {
color: #935493;
}

.lxlq.boolean-query {
.lxl-boolean-query {
color: purple;
}

.lxlq.wildcard {
color: orange;
.lxl-wildcard {
color: purple;
}
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 7 additions & 23 deletions packages/codemirror-lang-lxlquery/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@ import { styleTags, Tag, tagHighlighter } from '@lezer/highlight';

// custom tags attached to the language parser
const customTags = {
Qualifier: Tag.define('Qualifier'),
QualifierKey: Tag.define('QualifierKey'),
QualifierValue: Tag.define('QualifierValue'),
EqualOperator: Tag.define('EqualOperator'),
CompareOperator: Tag.define('CompareOperator'),
BooleanQuery: Tag.define('BooleanQuery'),
BooleanOperator: Tag.define('BooleanOperator'),
Wildcard: Tag.define('Wildcard')
};

Expand All @@ -22,26 +16,16 @@ export const lxlQueryLanguage = LRLanguage.define({
languageData: {}
});

const highlighter = tagHighlighter(
[
{ tag: customTags.Qualifier, class: 'qualifier' },
{ tag: customTags.QualifierKey, class: 'qualifier-key' },
{ tag: customTags.QualifierValue, class: 'qualifier-value' },
{ tag: customTags.EqualOperator, class: 'equal-operator' },
{ tag: customTags.CompareOperator, class: 'compare-operator' },
{ tag: customTags.BooleanOperator, class: 'boolean-operator' },
{ tag: customTags.BooleanQuery, class: 'boolean-query' },
{ tag: customTags.Wildcard, class: 'wildcard' }
],
{
all: 'lxlq'
}
);
const highlighter = tagHighlighter([
// adding qualifier classes handled by sypersearch/lxlQualifier plugin
{ tag: customTags.BooleanQuery, class: 'lxl-boolean-query' },
{ tag: customTags.Wildcard, class: 'lxl-wildcard' }
]);

const highlighterExtension = syntaxHighlighting(highlighter);

/**
* Libris XL query language together with a highlighter extension
* Libris XL query language together with a highlighter extension
* that adds CSS classes for certain nodes
*/
export const lxlQuery = new LanguageSupport(lxlQueryLanguage, highlighterExtension)
export const lxlQuery = new LanguageSupport(lxlQueryLanguage, highlighterExtension);
26 changes: 15 additions & 11 deletions packages/codemirror-lang-lxlquery/src/syntax.grammar
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,50 @@ term {
Group { "(" term* ")" }

BooleanQuery {
(freetext | Qualifier) BooleanOperator (freetext | Qualifier)
(BooleanOperator (freetext | Qualifier))+?
(freetext | Qualifier) booleanOperator (freetext | Qualifier)
(booleanOperator (freetext | Qualifier))+?
}

Qualifier {
(QualifierKey (EqualOperator | CompareOperator) QualifierValue) | reserved
(QualifierKey QualifierOperator QualifierValue) | reserved
}

QualifierKey {
identifier | string
Identifier | String
}

QualifierValue {
freetext | Group
Identifier | String | Number | Group
}

QualifierOperator {
EqualOperator | CompareOperator
}

freetext {
(identifier | string | number) Wildcard?
(Identifier | String | Number) Wildcard?
}

@tokens {
identifier { $[a-zA-ZåäöÅÄÖ]+ }
Identifier { $[a-zA-ZåäöÅÄÖ]+ }

string { '"' (!["\\] | "\\" _)* '"' }
String { '"' (!["\\] | "\\" _)* '"' }

number { @digit+ }
Number { @digit+ }

EqualOperator { ":" | "=" }

CompareOperator { ">" | "<" | ">=" | "<=" }

BooleanOperator { "AND" | "OR" | "NOT" }
booleanOperator { "AND" | "OR" | "NOT" }

Wildcard { "*"+ }

reserved { "includeEplikt" | "includePreliminary" }

space { @whitespace+ }

@precedence {BooleanOperator, reserved, identifier}
@precedence { booleanOperator, reserved, Identifier }
}

@detectDelim
43 changes: 23 additions & 20 deletions packages/codemirror-lang-lxlquery/test/cases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Astrid lindgren

==>

Query()
Query(Identifier Identifier)


# Freetext string
Expand All @@ -13,7 +13,7 @@ Query()

==>

Query()
Query(String)


# Freetext with Wildcard
Expand All @@ -22,7 +22,7 @@ Astrid lind*

==>

Query(Wildcard)
Query(Identifier Identifier Wildcard)


# Qualifier with EqualOperator
Expand All @@ -32,7 +32,7 @@ Query(Wildcard)
==>

Query(
Qualifier(QualifierKey,EqualOperator,QualifierValue)
Qualifier(QualifierKey(Identifier), QualifierOperator(EqualOperator), QualifierValue(Number))
)


Expand All @@ -44,8 +44,8 @@ Query(
==>

Query(
Qualifier(QualifierKey,CompareOperator,QualifierValue)
Qualifier(QualifierKey,CompareOperator,QualifierValue)
Qualifier(QualifierKey(Identifier), QualifierOperator(CompareOperator), QualifierValue(Number))
Qualifier(QualifierKey(Identifier), QualifierOperator(CompareOperator), QualifierValue(Number))
)


Expand All @@ -56,7 +56,7 @@ Query(
==>

Query(
Qualifier(QualifierKey,EqualOperator,QualifierValue)
Qualifier(QualifierKey(String),QualifierOperator(EqualOperator),QualifierValue(Identifier))
)


Expand All @@ -67,7 +67,7 @@ contributor:"Astrid Lindgren"
==>

Query(
Qualifier(QualifierKey,EqualOperator,QualifierValue)
Qualifier(QualifierKey(Identifier), QualifierOperator(EqualOperator), QualifierValue(String))
)


Expand All @@ -78,7 +78,7 @@ contributor:"libris:fcrtpljz1qp2bdv#it"
==>

Query(
Qualifier(QualifierKey,EqualOperator,QualifierValue)
Qualifier(QualifierKey(Identifier), QualifierOperator(EqualOperator), QualifierValue(String))
)


Expand All @@ -89,7 +89,7 @@ sommar OR vinter NOT vår
==>

Query(
BooleanQuery(BooleanOperator,BooleanOperator)
BooleanQuery(Identifier, Identifier, Identifier)
)


Expand All @@ -99,9 +99,7 @@ OR AND sommar

==>

Query(
⚠(BooleanOperator),⚠(BooleanOperator)
)
Query(⚠, ⚠, Identifier)


# Combined: Qualifier and Freetext
Expand All @@ -111,7 +109,7 @@ contributor:"Astrid Lindgren" Pippi Långstrump
==>

Query(
Qualifier(QualifierKey,EqualOperator,QualifierValue)
Qualifier(QualifierKey(Identifier), QualifierOperator(EqualOperator), QualifierValue(String)) Identifier Identifier
)


Expand All @@ -122,7 +120,7 @@ träd* bibliografi:"sigel:DST" NOT typ:Text
==>

Query(
Wildcard,BooleanQuery(Qualifier(...),BooleanOperator,Qualifier(...))
Identifier, Wildcard, BooleanQuery(Qualifier(QualifierKey(Identifier), QualifierOperator(EqualOperator), QualifierValue(String)), Qualifier(QualifierKey(Identifier), QualifierOperator(EqualOperator), QualifierValue(Identifier)))
)


Expand All @@ -133,14 +131,19 @@ pippi långstrump språk:(engelska OR franska) ÅR>2002
==>

Query(
Identifier,
Identifier,
Qualifier(
QualifierKey,EqualOperator,QualifierValue(
QualifierKey(Identifier), QualifierOperator(EqualOperator), QualifierValue(
Group(
BooleanQuery(BooleanOperator)
BooleanQuery(
Identifier,
Identifier
)
)
)
),
Qualifier(...)
Qualifier(QualifierKey(Identifier), QualifierOperator(CompareOperator), QualifierValue(Number))
)


Expand All @@ -159,7 +162,7 @@ Pippi includeEplikt

==>

Query(Qualifier)
Query(Identifier, Qualifier)


# Other filters: include preliminary
Expand All @@ -168,4 +171,4 @@ includePreliminary Pippi

==>

Query(Qualifier)
Query(Qualifier, Identifier)
1 change: 1 addition & 0 deletions packages/supersearch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ To use `supersearch` in a non-Svelte project ...
| `queryFn` | `QueryFunction` | A function that converts `value` to `URLSearchParams` (which will be appended to the endpoint). | `undefined` |
| `paginationQueryFn` | `PaginationQueryFunction` | A function which should return `URLSearchParams` used for querying more paginated data (if available) | `undefined` |
| `transformFn` | `TransformFunction` | A generic helper function which can be used to transform data fetched from the endpoint. | `undefined` |
| `extensions` | `Extension[]` | A list of extensions which should extend the default extensions. | `[]` |
| `resultItem` | `Snippet<[ResultItem]>` | A [Snippet](https://svelte.dev/docs/svelte/snippet) used for customized rendering of result items. | `undefined` |
| `debouncedWait` | `number` | The wait time, in milliseconds that debounce function should wait between invocated search queries. | `300` |

Expand Down
1 change: 1 addition & 0 deletions packages/supersearch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@types/eslint": "^9.6.0",
"codemirror": "^6.0.1",
"codemirror-lang-lxlquery": "^0.1.0",
"eslint": "^9.7.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.36.0",
Expand Down
Loading

0 comments on commit bf186fb

Please sign in to comment.