|
2 | 2 | import { minisearches, processTerm } from '$lib/minisearch.svelte';
|
3 | 3 | import siglaFromHandle from '$lib/functions/siglaFromHandle';
|
4 | 4 | import Datatable from './Datatable.svelte';
|
5 |
| - import { RadioGroup, RadioItem, SlideToggle } from '@skeletonlabs/skeleton'; |
| 5 | + import { RadioGroup, RadioItem } from '@skeletonlabs/skeleton'; |
6 | 6 | let hasDocuments = $state(!!minisearches[0].documentCount);
|
7 | 7 | let searchtext = $state('');
|
8 | 8 | let useExactSearch = $state(true);
|
|
50 | 50 | */
|
51 | 51 | let searchResults = $state(new Promise((resolve) => resolve([])));
|
52 | 52 |
|
| 53 | + /** |
| 54 | + * @param {string} base |
| 55 | + * @param {string} compareTo |
| 56 | + */ |
| 57 | + function highlightDifferences(base, compareTo) { |
| 58 | + let result = ''; |
| 59 | + let i = 0, |
| 60 | + j = 0; |
| 61 | +
|
| 62 | + while (i < base.length) { |
| 63 | + if (j < compareTo.length && base[i] === compareTo[j]) { |
| 64 | + result += base[i]; |
| 65 | + j++; // Move both pointers when characters match |
| 66 | + } else { |
| 67 | + result += `<span>${base[i]}</span>`; // Highlight extra characters |
| 68 | + } |
| 69 | + i++; // Always move pointer for base |
| 70 | + } |
| 71 | +
|
| 72 | + return result; |
| 73 | + } |
| 74 | +
|
53 | 75 | const handleSearch = async (/** @type {import("minisearch").Query} */ query) => {
|
54 | 76 | let results = activeMinisearch.search(query, { fuzzy: useExactSearch ? 0 : 0.3 });
|
55 | 77 | results = await Promise.all(
|
|
61 | 83 | results.map((r) => {
|
62 | 84 | r.humanReadableSigil = siglaFromHandle(r.sigla);
|
63 | 85 | const matches = Object.keys(r.match);
|
| 86 | + if (r.content_all !== r.content) { |
| 87 | + r.content_all = highlightDifferences(r.content_all, r.content); |
| 88 | + } |
64 | 89 | //Mark all matches in the content
|
65 |
| - r.content = r.content |
| 90 | + r.content_all = r.content_all |
66 | 91 | .split(' ')
|
67 | 92 | .map((/** @type {string} */ c) => {
|
68 | 93 | //if the matches include the processed term without punctuation, mark it
|
69 |
| - if (matches.includes(processTerm(c.replaceAll(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, '')))) { |
| 94 | + if ( |
| 95 | + matches.includes( |
| 96 | + processTerm( |
| 97 | + c |
| 98 | + .replaceAll('<span>', '') |
| 99 | + .replaceAll('</span>', '') |
| 100 | + .replaceAll(/[<>.,\/#!$%\^&\*;:{}=\-_`~()]/g, '') |
| 101 | + ) |
| 102 | + ) |
| 103 | + ) { |
70 | 104 | return `<mark>${c}</mark>`;
|
71 | 105 | }
|
72 | 106 | return c;
|
|
94 | 128 | };
|
95 | 129 | </script>
|
96 | 130 |
|
97 |
| -<section class="container mx-auto typography grid grid-cols-2 my-4 gap-8"> |
| 131 | +<section class="container mx-auto typography grid sm:grid-cols-2 my-4 gap-8"> |
98 | 132 | <div>
|
99 | 133 | <h1>Suche</h1>
|
100 | 134 | <p>
|
101 |
| - Durchsuchen Sie hier den kompletten Textkopus des Parzival. Standardmässig durchsuchen Sie die |
102 |
| - Fassungsverse und Ihnen werden nur genaue Treffer gezeigt. Dabei wurden einige |
103 |
| - Normalisierungen durchgeführt, so dass Ligaturen und andere Sonderformen auch in den Suchen |
104 |
| - gefunden werden. Die Suche nach Spigel enthält so zum Beispiel auch Treffer mit Schaft-S |
105 |
| - (ſpigel). |
| 135 | + Durchsuchen Sie hier das komplette Textkorpus des ›Parzival‹. Standardmäßig durchsuchen Sie |
| 136 | + die Fassungsverse, und Ihnen werden nur genaue Treffer gezeigt. Dabei werden einige |
| 137 | + Normalisierungen berücksichtigt, so dass Ligaturen und andere Sonderformen auch gefunden |
| 138 | + werden. Die Suche nach <i>spigel</i> enthält so zum Beispiel auch Treffer mit Schaft-<i>s</i> |
| 139 | + (<i>ſpigel</i>). Für die Textzeugensuche empfiehlt sich eine unscharfe Suche. |
| 140 | + </p> |
| 141 | + <p> |
| 142 | + Klicken Sie auf das jeweilige Ergebnis, um direkt in die Transkription zu gelangen (aus |
| 143 | + technischen Gründen kann das Suchresultat mitunter von der Transkription leicht abweichen). |
106 | 144 | </p>
|
107 | 145 | </div>
|
108 | 146 | <div>
|
109 | 147 | <h2 class="h2">Suchoptionen</h2>
|
110 |
| - <div class="flex gap-2 items-center"> |
111 |
| - <SlideToggle active="bg-primary-500" name="exact" bind:checked={useExactSearch} |
112 |
| - >{useExactSearch ? 'exakte' : 'fuzzy'} Suche</SlideToggle |
113 |
| - > |
| 148 | + <div class="flex flex-col w-fit gap-2"> |
| 149 | + <RadioGroup active="variant-filled-primary"> |
| 150 | + <RadioItem bind:group={useExactSearch} name="Suchvariante" value={true} |
| 151 | + >exakte Suche</RadioItem |
| 152 | + > |
| 153 | + <RadioItem bind:group={useExactSearch} name="Suchvariante" value={false}> |
| 154 | + unscharfe Suche |
| 155 | + </RadioItem> |
| 156 | + </RadioGroup> |
114 | 157 | <RadioGroup active="variant-filled-primary">
|
115 | 158 | <RadioItem bind:group={corpus} name="korpus" value={'fassungen'} disabled={!hasDocuments}>
|
116 | 159 | Fassungen (1.67MB)
|
|
147 | 190 | >Lade Suche <i class="ml-1 fa-solid fa-spinner fa-spin"></i></button
|
148 | 191 | >
|
149 | 192 | {/if}
|
| 193 | + {#await searchResults then r} |
| 194 | + <p>{r.length === 1 ? '1 Ergebnis' : `${r.length} Ergebnisse`}</p> |
| 195 | + {/await} |
150 | 196 | </form>
|
151 | 197 | </section>
|
152 | 198 | <section class="container mx-auto mt-4">
|
|
0 commit comments