@hagicode/hagilight 0.3.2-dev.55.1.1e29eba → 0.3.2-dev.58.1.bee3693

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/Footer.astro DELETED
@@ -1,157 +0,0 @@
1
- ---
2
- import Copyright from './Copyright.astro';
3
- import { resolveRssFooterLinks } from './rss-footer-context.mjs';
4
- import { resolveSiteLinks, type SiteLinksOptions } from './site-links.ts';
5
-
6
- interface Props {
7
- locale?: string;
8
- links?: SiteLinksOptions;
9
- }
10
-
11
- const { locale: propLocale, links } = Astro.props;
12
- const locale = propLocale ?? Astro.currentLocale ?? 'en-US';
13
- const footerLinks = resolveRssFooterLinks(Astro.locals, locale, links);
14
- const resolvedLinks = resolveSiteLinks(locale, footerLinks);
15
- ---
16
-
17
- <footer class="hagilight-footer">
18
- <div class="hagilight-footer__sections">
19
- {resolvedLinks.relatedSites.length > 0 && (
20
- <section>
21
- <h2>{resolvedLinks.labels.relatedSites}</h2>
22
- <nav aria-label={resolvedLinks.labels.navigation.relatedSites}>
23
- <ul>
24
- {resolvedLinks.relatedSites.map((site) => (
25
- <li>
26
- <a href={site.href} target={site.target} rel={site.rel}>{site.name}</a>
27
- </li>
28
- ))}
29
- </ul>
30
- </nav>
31
- </section>
32
- )}
33
- <section>
34
- <h2>{resolvedLinks.labels.quickLinks}</h2>
35
- <nav aria-label={resolvedLinks.labels.navigation.quickLinks}>
36
- <ul>
37
- {resolvedLinks.quick.map((link) => (
38
- <li>
39
- <a
40
- href={link.href}
41
- target={link.target}
42
- rel={link.rel}
43
- aria-label={link.ariaLabel}
44
- >{link.label}</a>
45
- </li>
46
- ))}
47
- </ul>
48
- </nav>
49
- </section>
50
- <section>
51
- <h2>{resolvedLinks.labels.community}</h2>
52
- <nav aria-label={resolvedLinks.labels.navigation.community}>
53
- <ul>
54
- {resolvedLinks.community.map((link) => (
55
- <li>
56
- <a
57
- href={link.href}
58
- target={link.target}
59
- rel={link.rel}
60
- aria-label={link.ariaLabel}
61
- >{link.label}</a>
62
- </li>
63
- ))}
64
- </ul>
65
- </nav>
66
- </section>
67
- </div>
68
- <nav class="hagilight-footer__filings" aria-label={resolvedLinks.labels.navigation.filings}>
69
- {resolvedLinks.filings.map((link) => (
70
- <a
71
- href={link.href}
72
- target={link.target}
73
- rel={link.rel}
74
- aria-label={link.ariaLabel}
75
- >{link.label}</a>
76
- ))}
77
- </nav>
78
- <p class="hagilight-footer__copyright"><Copyright name="HagiCode" /></p>
79
- </footer>
80
-
81
- <style>
82
- .hagilight-footer {
83
- border-top: 1px solid var(--hagilight-footer-border, currentColor);
84
- color: var(--hagilight-footer-color, inherit);
85
- padding: 1.5rem 1rem 1rem;
86
- }
87
-
88
- .hagilight-footer__sections {
89
- display: grid;
90
- grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
91
- gap: 1.5rem;
92
- margin: 0 auto 1.5rem;
93
- max-width: 72rem;
94
- }
95
-
96
- .hagilight-footer section {
97
- min-width: 0;
98
- }
99
-
100
- .hagilight-footer h2 {
101
- margin: 0 0 0.75rem;
102
- font-size: 0.95rem;
103
- font-weight: 650;
104
- }
105
-
106
- .hagilight-footer ul {
107
- display: grid;
108
- gap: 0.5rem;
109
- margin: 0;
110
- padding: 0;
111
- list-style: none;
112
- }
113
-
114
- .hagilight-footer a {
115
- color: inherit;
116
- text-decoration: none;
117
- text-underline-offset: 0.2em;
118
- }
119
-
120
- .hagilight-footer a:hover {
121
- text-decoration: underline;
122
- }
123
-
124
- .hagilight-footer a:focus-visible {
125
- border-radius: 0.125rem;
126
- outline: 2px solid currentColor;
127
- outline-offset: 0.2rem;
128
- }
129
-
130
- .hagilight-footer__filings {
131
- display: flex;
132
- flex-wrap: wrap;
133
- justify-content: center;
134
- gap: 0.75rem 1.5rem;
135
- border-top: 1px solid var(--hagilight-footer-border, currentColor);
136
- padding-top: 1rem;
137
- text-align: center;
138
- }
139
-
140
- .hagilight-footer__copyright {
141
- margin: 1rem 0 0;
142
- font-size: 0.8rem;
143
- text-align: center;
144
- }
145
-
146
- @media (max-width: 40rem) {
147
- .hagilight-footer__sections {
148
- grid-template-columns: 1fr;
149
- gap: 1.25rem;
150
- }
151
-
152
- .hagilight-footer__filings {
153
- justify-content: flex-start;
154
- gap: 0.75rem 1rem;
155
- }
156
- }
157
- </style>
@@ -1,21 +0,0 @@
1
- ---
2
- interface Props {
3
- measurementId: string;
4
- }
5
-
6
- const { measurementId } = Astro.props;
7
- if (!measurementId?.trim()) throw new Error('GoogleAnalytics requires a measurementId prop.');
8
- const scriptUrl = `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(measurementId)}`;
9
- ---
10
-
11
- {import.meta.env.PROD && (
12
- <>
13
- <script async src={scriptUrl}></script>
14
- <script is:inline define:vars={{ measurementId }}>
15
- window.dataLayer = window.dataLayer || [];
16
- function gtag(){dataLayer.push(arguments);}
17
- gtag('js', new Date());
18
- gtag('config', measurementId);
19
- </script>
20
- </>
21
- )}
@@ -1,346 +0,0 @@
1
- ---
2
- import type { PromotionCard } from './promotions';
3
-
4
- interface Props {
5
- fallback?: PromotionCard;
6
- locale?: string;
7
- }
8
-
9
- const { fallback, locale = Astro.currentLocale ?? 'en' } = Astro.props;
10
- ---
11
-
12
- <hagilight-promoto-banner
13
- class="hagilight-promoto"
14
- data-locale={locale}
15
- data-fallback={fallback ? JSON.stringify(fallback) : undefined}
16
- hidden
17
- >
18
- <section class="hagilight-promoto__shell" data-promoto-shell hidden aria-label="Featured promotion">
19
- <button
20
- type="button"
21
- class="hagilight-promoto__dismiss"
22
- data-promoto-dismiss
23
- aria-label="Dismiss promotion"
24
- >&times;</button>
25
- <div class="hagilight-promoto__viewport">
26
- <div class="hagilight-promoto__track" data-promoto-track></div>
27
- </div>
28
- <nav class="hagilight-promoto__controls" data-promoto-controls aria-label="Promotion controls" hidden>
29
- <button type="button" class="hagilight-promoto__control" data-promoto-previous aria-label="Previous promotion">‹</button>
30
- <span class="hagilight-promoto__count" data-promoto-count aria-label="Promotion progress"></span>
31
- <button type="button" class="hagilight-promoto__control" data-promoto-next aria-label="Next promotion">›</button>
32
- <button type="button" class="hagilight-promoto__control" data-promoto-pause aria-pressed="false">Pause</button>
33
- </nav>
34
- <span class="hagilight-promoto__status" data-promoto-status aria-live="polite"></span>
35
- </section>
36
- </hagilight-promoto-banner>
37
-
38
- <script>
39
- import { definePromotoBannerElement } from './promoto-banner';
40
-
41
- definePromotoBannerElement();
42
- </script>
43
-
44
- <style is:global>
45
- .hagilight-promoto {
46
- display: block;
47
- }
48
-
49
- .hagilight-promoto[hidden],
50
- .hagilight-promoto__shell[hidden],
51
- .hagilight-promoto__controls[hidden] {
52
- display: none !important;
53
- }
54
-
55
- .hagilight-promoto__shell {
56
- position: fixed;
57
- z-index: 40;
58
- inset-inline: 0;
59
- bottom: max(1rem, env(safe-area-inset-bottom));
60
- width: min(72rem, calc(100vw - 1rem));
61
- margin-inline: auto;
62
- overflow: hidden;
63
- border: 1px solid color-mix(in srgb, var(--sl-color-accent, #2563eb) 24%, var(--sl-color-gray-5, #cbd5e1));
64
- border-radius: 1.25rem;
65
- background: color-mix(in srgb, var(--sl-color-bg, #fff) 96%, var(--sl-color-accent-low, #dbeafe) 4%);
66
- box-shadow: 0 18px 48px color-mix(in srgb, var(--sl-color-black, #000) 16%, transparent);
67
- color: var(--sl-color-text, #1f2937);
68
- opacity: 1;
69
- visibility: visible;
70
- transition: opacity 0.24s ease, visibility 0s linear;
71
- }
72
-
73
- .hagilight-promoto[data-state='footer-hidden'] .hagilight-promoto__shell {
74
- opacity: 0;
75
- visibility: hidden;
76
- pointer-events: none;
77
- transition: opacity 0.24s ease, visibility 0s linear 0.24s;
78
- }
79
-
80
- .hagilight-promoto__viewport {
81
- overflow: hidden;
82
- }
83
-
84
- .hagilight-promoto__track {
85
- display: flex;
86
- align-items: stretch;
87
- width: 100%;
88
- transition: transform 0.34s ease;
89
- }
90
-
91
- .hagilight-promoto__slide {
92
- display: grid;
93
- grid-template-columns: minmax(0, 1fr) auto auto;
94
- align-items: center;
95
- gap: 1.25rem;
96
- width: 100%;
97
- min-width: 100%;
98
- padding: 1.25rem 4rem 1.25rem 1.25rem;
99
- }
100
-
101
- .hagilight-promoto__slide[aria-hidden='true'] {
102
- pointer-events: none;
103
- }
104
-
105
- .hagilight-promoto__copy {
106
- display: grid;
107
- grid-template-columns: 1fr;
108
- align-items: start;
109
- gap: 0.4rem;
110
- min-width: 0;
111
- }
112
-
113
- .hagilight-promoto__title,
114
- .hagilight-promoto__description {
115
- display: -webkit-box;
116
- overflow: hidden;
117
- margin: 0;
118
- color: var(--sl-color-text-high, var(--sl-color-gray-1, #111827));
119
- font-size: var(--sl-text-sm);
120
- font-weight: 600;
121
- line-height: 1.35;
122
- -webkit-box-orient: vertical;
123
- -webkit-line-clamp: 2;
124
- }
125
-
126
- .hagilight-promoto__description {
127
- color: var(--sl-color-text, #1f2937);
128
- }
129
-
130
- .hagilight-promoto__media {
131
- display: inline-flex;
132
- align-items: center;
133
- justify-content: center;
134
- width: clamp(4.5rem, 8vw, 6.25rem);
135
- min-width: clamp(4.5rem, 8vw, 6.25rem);
136
- aspect-ratio: 1;
137
- overflow: hidden;
138
- border: 1px solid color-mix(in srgb, var(--sl-color-accent-high, #1d4ed8) 18%, var(--sl-color-gray-5, #cbd5e1));
139
- border-radius: 0.8rem;
140
- background: color-mix(in srgb, var(--sl-color-bg-sidebar, #f8fafc) 82%, transparent);
141
- }
142
-
143
- .hagilight-promoto__image {
144
- display: block;
145
- width: 100%;
146
- height: 100%;
147
- object-fit: cover;
148
- }
149
-
150
- .hagilight-promoto__cta {
151
- display: inline-flex;
152
- align-items: center;
153
- justify-content: center;
154
- min-width: 7.5rem;
155
- min-height: 2.6rem;
156
- border: 1px solid color-mix(in srgb, var(--sl-color-accent-high, #1d4ed8) 30%, transparent);
157
- border-radius: 999px;
158
- background: var(--sl-color-accent, #2563eb);
159
- color: #fff;
160
- font-size: var(--sl-text-xs);
161
- font-weight: 700;
162
- padding-inline: 1rem;
163
- text-align: center;
164
- text-decoration: none;
165
- }
166
-
167
- .hagilight-promoto__cta:hover,
168
- .hagilight-promoto__cta:focus-visible {
169
- background: var(--sl-color-accent-high, #1d4ed8);
170
- }
171
-
172
- .hagilight-promoto__dismiss,
173
- .hagilight-promoto__control {
174
- display: inline-flex;
175
- align-items: center;
176
- justify-content: center;
177
- min-width: 2.5rem;
178
- min-height: 2.5rem;
179
- border: 1px solid color-mix(in srgb, var(--sl-color-accent-high, #1d4ed8) 20%, var(--sl-color-gray-5, #cbd5e1));
180
- border-radius: 999px;
181
- background: var(--sl-color-bg-nav, #f8fafc);
182
- color: var(--sl-color-text-high, #111827);
183
- cursor: pointer;
184
- }
185
-
186
- .hagilight-promoto__dismiss {
187
- position: absolute;
188
- z-index: 1;
189
- inset-block-start: 0.6rem;
190
- inset-inline-end: 0.6rem;
191
- }
192
-
193
- .hagilight-promoto__controls {
194
- display: flex;
195
- align-items: center;
196
- justify-content: flex-end;
197
- gap: 0.5rem;
198
- padding: 0 1.25rem 1rem;
199
- }
200
-
201
- .hagilight-promoto__count {
202
- min-width: 3.5rem;
203
- text-align: center;
204
- font-size: var(--sl-text-xs);
205
- font-variant-numeric: tabular-nums;
206
- }
207
-
208
- .hagilight-promoto__control:disabled {
209
- cursor: default;
210
- opacity: 0.6;
211
- }
212
-
213
- .hagilight-promoto__status {
214
- position: absolute;
215
- width: 1px;
216
- height: 1px;
217
- overflow: hidden;
218
- clip: rect(0, 0, 0, 0);
219
- white-space: nowrap;
220
- }
221
-
222
- .hagilight-promoto__dismiss:focus-visible,
223
- .hagilight-promoto__control:focus-visible,
224
- .hagilight-promoto__cta:focus-visible {
225
- outline: 3px solid var(--sl-color-accent-high, #1d4ed8);
226
- outline-offset: 3px;
227
- }
228
-
229
- @media (max-width: 960px) {
230
- .hagilight-promoto__slide {
231
- grid-template-columns: 1fr;
232
- gap: 0.75rem;
233
- padding-inline-end: 3.7rem;
234
- }
235
-
236
- .hagilight-promoto__slide[data-has-image='true'] {
237
- grid-template-columns: 1fr;
238
- }
239
-
240
- .hagilight-promoto__copy {
241
- grid-template-columns: 1fr;
242
- gap: 0.45rem;
243
- }
244
-
245
- .hagilight-promoto__media {
246
- width: min(100%, 8rem);
247
- min-width: 0;
248
- }
249
-
250
- .hagilight-promoto__cta {
251
- justify-self: start;
252
- white-space: normal;
253
- }
254
-
255
- .hagilight-promoto__controls {
256
- justify-content: flex-start;
257
- padding-top: 0;
258
- }
259
- }
260
-
261
- @media (max-width: 720px) {
262
- .hagilight-promoto__shell {
263
- bottom: calc(env(safe-area-inset-bottom) + 0.5rem);
264
- width: min(calc(100vw - 1rem), 24rem);
265
- border-radius: 1rem;
266
- }
267
-
268
- .hagilight-promoto__slide {
269
- grid-template-columns: 1fr;
270
- gap: 0.7rem;
271
- padding: 0.85rem 4.8rem 0.85rem 0.85rem;
272
- }
273
-
274
- .hagilight-promoto__slide[data-has-image='true'] {
275
- grid-template-columns: minmax(0, 1fr) 4.5rem;
276
- align-items: start;
277
- }
278
-
279
- .hagilight-promoto__copy {
280
- grid-column: 1;
281
- grid-row: 1;
282
- gap: 0.45rem;
283
- }
284
-
285
- .hagilight-promoto__title {
286
- font-size: 0.92rem;
287
- }
288
-
289
- .hagilight-promoto__description {
290
- font-size: 0.84rem;
291
- font-weight: 500;
292
- line-height: 1.3;
293
- }
294
-
295
- .hagilight-promoto__media {
296
- width: 4.5rem;
297
- min-width: 4.5rem;
298
- align-self: start;
299
- grid-column: 2;
300
- grid-row: 1;
301
- }
302
-
303
- .hagilight-promoto__cta {
304
- grid-column: 1 / -1;
305
- justify-self: stretch;
306
- min-width: 0;
307
- min-height: 2.35rem;
308
- width: 100%;
309
- font-size: 0.82rem;
310
- white-space: normal;
311
- }
312
-
313
- .hagilight-promoto__control {
314
- min-width: 2.2rem;
315
- min-height: 2.2rem;
316
- }
317
-
318
- .hagilight-promoto__count {
319
- min-width: 2.75rem;
320
- font-size: 0.75rem;
321
- }
322
-
323
- .hagilight-promoto__dismiss {
324
- inset-block-start: 0.55rem;
325
- inset-inline-end: 0.55rem;
326
- width: auto;
327
- min-width: 2rem;
328
- height: 2rem;
329
- gap: 0.25rem;
330
- padding-inline: 0.55rem;
331
- }
332
-
333
- .hagilight-promoto__controls {
334
- flex-wrap: wrap;
335
- gap: 0.35rem;
336
- padding: 0 0.85rem 0.9rem;
337
- }
338
- }
339
-
340
- @media (prefers-reduced-motion: reduce) {
341
- .hagilight-promoto__shell,
342
- .hagilight-promoto__track {
343
- transition: none;
344
- }
345
- }
346
- </style>
package/favicon.ico DELETED
Binary file
package/favicon.mjs DELETED
@@ -1,76 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { fileURLToPath } from 'node:url';
3
-
4
- const faviconPath = fileURLToPath(new URL('./favicon.ico', import.meta.url));
5
- let cachedDataUri;
6
-
7
- /**
8
- * Resolve the bundled HagiCode favicon as an inline data URI.
9
- * Memoized so the binary is read at most once per process.
10
- */
11
- export function getHagilightFaviconDataUri() {
12
- if (cachedDataUri === undefined) {
13
- const bytes = readFileSync(faviconPath);
14
- cachedDataUri = `data:image/x-icon;base64,${bytes.toString('base64')}`;
15
- }
16
- return cachedDataUri;
17
- }
18
-
19
- function isIconLink(entry) {
20
- return entry?.tag === 'link'
21
- && typeof entry.attrs?.rel === 'string'
22
- && /\bicon\b/u.test(entry.attrs.rel);
23
- }
24
-
25
- function headHasIconLink(head) {
26
- return (head ?? []).some(isIconLink);
27
- }
28
-
29
- /**
30
- * Resolve the favicon `<link>` head entry to inject, or `undefined` to skip.
31
- *
32
- * Shared by both the `hagilightFavicon` integration and the Starlight plugin so the
33
- * favicon behavior has a single source of truth.
34
- *
35
- * Override options:
36
- * - Pass `{ href: '/your-favicon.ico' }` to use a consumer-provided favicon instead.
37
- * - If `head` already contains an icon link, injection is skipped (so manual favicons
38
- * are never duplicated).
39
- *
40
- * @param {Array<{tag:string, attrs?:Record<string,string>}>} head existing head entries
41
- * @param {{href?:string}} [options] optional override href
42
- */
43
- export function resolveFaviconHeadEntry(head = [], options = {}) {
44
- if (headHasIconLink(head)) return undefined;
45
- const overrideHref = typeof options.href === 'string' && options.href.trim()
46
- ? options.href.trim()
47
- : undefined;
48
- const href = overrideHref ?? getHagilightFaviconDataUri();
49
- const attrs = { rel: 'icon', href };
50
- if (overrideHref === undefined) attrs.type = 'image/x-icon';
51
- return { tag: 'link', attrs };
52
- }
53
-
54
- /**
55
- * Astro integration that auto-applies the bundled HagiCode favicon.
56
- *
57
- * Any site referencing `@hagicode/hagilight` can add `integrations: [hagilightFavicon()]`
58
- * to get the shared favicon with no further configuration.
59
- */
60
- export function hagilightFavicon(options = {}) {
61
- if (options !== undefined && (!options || typeof options !== 'object' || Array.isArray(options))) {
62
- throw new TypeError('Hagilight favicon options must be an object.');
63
- }
64
- return {
65
- name: '@hagicode/hagilight:favicon',
66
- hooks: {
67
- 'astro:config:setup'({ config, updateConfig }) {
68
- const entry = resolveFaviconHeadEntry(config.head, options);
69
- if (!entry) return;
70
- updateConfig({
71
- head: [...(config.head ?? []), entry],
72
- });
73
- },
74
- },
75
- };
76
- }