tecitheme 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CTA.svelte +1 -1
- package/dist/components/CTASplitImage.svelte +1 -1
- package/dist/components/Footer.svelte +1 -1
- package/dist/components/Header.svelte +1 -1
- package/dist/components/PageNav.svelte +1 -1
- package/dist/components/Search/SearchModal.svelte +6 -1
- package/dist/components/Search/TeciSearchHits.svelte +100 -1
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<section {id} class="{data.bgColor?'p-8':''} {getColorStyles('background', data.bgColor)}
|
|
8
8
|
{data.fullwidth?'w-full mx-auto':'max-w-3xl mx-auto'}
|
|
9
9
|
{data.justifyText?(data.justifyText=='left'?'text-left':(data.justifyText=='right'?'text-right':'')):'text-center'}
|
|
10
|
-
not-prose
|
|
10
|
+
not-prose print:hidden
|
|
11
11
|
"
|
|
12
12
|
>
|
|
13
13
|
{#if data.title}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
let id = makeIdString(data.name);
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
|
-
<section {id} class="relative {getColorStyles('background', data.color)}">
|
|
8
|
+
<section {id} class="relative {getColorStyles('background', data.color)} print:hidden">
|
|
9
9
|
<div class="h-56 sm:h-72 md:absolute md:left-0 md:h-full md:w-1/2">
|
|
10
10
|
<img class="h-full w-full object-cover" src="https://files.thunderheadeng.com/www/images/{data.image}?w=608&fit=clip&auto=compress&auto=format" alt="Image for {data.preheading}">
|
|
11
11
|
</div>
|
|
@@ -4,7 +4,7 @@ import Button from './Button.svelte'
|
|
|
4
4
|
let d = new Date();
|
|
5
5
|
</script>
|
|
6
6
|
|
|
7
|
-
<footer id="bottom" class="bg-gray-800" aria-labelledby="footerHeading">
|
|
7
|
+
<footer id="bottom" class="bg-gray-800 print:hidden" aria-labelledby="footerHeading">
|
|
8
8
|
<h2 id="footerHeading" class="sr-only">Footer</h2>
|
|
9
9
|
<div class="mx-auto max-w-7xl py-12 px-4 sm:px-6 lg:py-16 lg:px-8">
|
|
10
10
|
<div class="xl:grid xl:grid-cols-3 xl:gap-8">
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
<svelte:window on:keyup={handleEscape} />
|
|
40
40
|
|
|
41
|
-
<header {id} class="sticky top-0 w-full z-40 bg-white">
|
|
41
|
+
<header {id} class="sticky top-0 w-full z-40 bg-white print:hidden">
|
|
42
42
|
<div
|
|
43
43
|
aria-hidden="true"
|
|
44
44
|
class="pointer-events-none absolute inset-0 z-30 shadow"
|
|
@@ -16,7 +16,12 @@
|
|
|
16
16
|
|
|
17
17
|
const { searchClient, setMeiliSearchParams } = instantMeiliSearch (
|
|
18
18
|
"https://ms-6689ffd3d866-29089.nyc.meilisearch.io",
|
|
19
|
-
"d9f20886cbbbe171f3933dc93a1ec38e365d53f072854e5d9f92a9b130fa1f7d"
|
|
19
|
+
"d9f20886cbbbe171f3933dc93a1ec38e365d53f072854e5d9f92a9b130fa1f7d",
|
|
20
|
+
{
|
|
21
|
+
meiliSearchParams: {
|
|
22
|
+
showMatchesPosition: true
|
|
23
|
+
}
|
|
24
|
+
}
|
|
20
25
|
)
|
|
21
26
|
|
|
22
27
|
onMount(() => {
|
|
@@ -90,7 +90,106 @@
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
function tokenizeHTML(html) {
|
|
94
|
+
const tokens = [];
|
|
95
|
+
let buffer = "";
|
|
96
|
+
let insideTag = false;
|
|
97
|
+
|
|
98
|
+
for (let i = 0; i < html.length; i++) {
|
|
99
|
+
const c = html[i];
|
|
100
|
+
|
|
101
|
+
if (c === "<") {
|
|
102
|
+
// flush text buffer
|
|
103
|
+
if (buffer) tokens.push({ type: "text", value: buffer });
|
|
104
|
+
buffer = "<";
|
|
105
|
+
insideTag = true;
|
|
106
|
+
} else if (c === ">" && insideTag) {
|
|
107
|
+
buffer += ">";
|
|
108
|
+
tokens.push({ type: "tag", value: buffer });
|
|
109
|
+
buffer = "";
|
|
110
|
+
insideTag = false;
|
|
111
|
+
} else {
|
|
112
|
+
buffer += c;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (buffer) {
|
|
117
|
+
tokens.push({ type: insideTag ? "tag" : "text", value: buffer });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return tokens;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function buildOffsetMap(tokens) {
|
|
124
|
+
let global = 0;
|
|
125
|
+
|
|
126
|
+
return tokens.map(t => {
|
|
127
|
+
const start = global;
|
|
128
|
+
const end = start + t.value.length;
|
|
129
|
+
|
|
130
|
+
global = end;
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
...t,
|
|
134
|
+
globalStart: start,
|
|
135
|
+
globalEnd: end
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function applyHighlights(tokens, matches) {
|
|
141
|
+
// Process matches from last → first to prevent index shifting
|
|
142
|
+
matches.sort((a, b) => b.start - a.start);
|
|
143
|
+
|
|
144
|
+
matches.forEach(({ start, length }) => {
|
|
145
|
+
const end = start + length;
|
|
146
|
+
|
|
147
|
+
tokens.forEach(token => {
|
|
148
|
+
if (token.type === "tag") return;
|
|
93
149
|
|
|
150
|
+
// skip if match does not touch this token
|
|
151
|
+
if (end <= token.globalStart || start >= token.globalEnd) return;
|
|
152
|
+
|
|
153
|
+
// ----- compute localStart -----
|
|
154
|
+
let localStart;
|
|
155
|
+
if (start < token.globalStart) {
|
|
156
|
+
localStart = 0;
|
|
157
|
+
} else {
|
|
158
|
+
localStart = start - token.globalStart;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ----- compute localEnd -----
|
|
162
|
+
let localEnd;
|
|
163
|
+
const tokenLength = token.value.length;
|
|
164
|
+
|
|
165
|
+
if (end > token.globalEnd) {
|
|
166
|
+
localEnd = tokenLength;
|
|
167
|
+
} else {
|
|
168
|
+
localEnd = end - token.globalStart;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// apply the highlight
|
|
172
|
+
const text = token.value;
|
|
173
|
+
|
|
174
|
+
token.value =
|
|
175
|
+
text.slice(0, localStart) +
|
|
176
|
+
"<mark>" +
|
|
177
|
+
text.slice(localStart, localEnd) +
|
|
178
|
+
"</mark>" +
|
|
179
|
+
text.slice(localEnd);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
return tokens.map(t => t.value).join("");
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function highlightHTMLWithMatches(html, matches) {
|
|
187
|
+
if (!matches || matches.length === 0) return html
|
|
188
|
+
|
|
189
|
+
const tokens = tokenizeHTML(html);
|
|
190
|
+
const mapped = buildOffsetMap(tokens);
|
|
191
|
+
return applyHighlights(mapped, matches);
|
|
192
|
+
}
|
|
94
193
|
</script>
|
|
95
194
|
|
|
96
195
|
<svelte:window on:keydown={(e) => handleKeyPress(e)} />
|
|
@@ -209,7 +308,7 @@
|
|
|
209
308
|
<!-- Content Preview -->
|
|
210
309
|
<div class="flex flex-col">
|
|
211
310
|
<h4 class="text-lg font-bold text-black uppercase">Preview</h4>
|
|
212
|
-
<p class="line-clamp-4 mb-4"
|
|
311
|
+
<p class="highlightedSearchContent line-clamp-4 mb-4">{@html highlightHTMLWithMatches(hit.content, hit._matchesPosition.content)}</p>
|
|
213
312
|
</div>
|
|
214
313
|
|
|
215
314
|
<!-- On This Page headings -->
|