@stnd/layout 0.2.0 → 0.5.0
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/Base.astro +106 -130
- package/CHANGELOG.md +36 -0
- package/Encrypted.astro +175 -188
- package/Footer.astro +184 -0
- package/Header.astro +533 -0
- package/Meta.astro +226 -328
- package/README.md +543 -0
- package/StndInit.astro +49 -0
- package/package.json +11 -4
package/Meta.astro
CHANGED
|
@@ -1,260 +1,196 @@
|
|
|
1
1
|
---
|
|
2
2
|
/**
|
|
3
|
-
* Meta.astro
|
|
3
|
+
* Meta.astro — Universal <head> Meta Tags
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Self-contained, zero-config. Reads site defaults from virtual:stnd/config
|
|
6
|
+
* (same pattern as manifest/robots/headers folios). Per-page props override.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* <Meta /> — site defaults from config
|
|
10
|
+
* <Meta title="My Page" /> — override title
|
|
11
|
+
* <Meta title="Article" type="article" created="2024-01-01" />
|
|
7
12
|
*/
|
|
8
|
-
import
|
|
9
|
-
// import { ClientRouter } from "astro:transitions";
|
|
10
|
-
|
|
11
|
-
// Access site configuration from global
|
|
12
|
-
const config = (globalThis['__STANDARD_CONFIG__'] as any) || {};
|
|
13
|
+
import config from "virtual:stnd/config";
|
|
13
14
|
|
|
14
|
-
// Props interface for universal usage
|
|
15
15
|
interface Props {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
16
|
+
// Per-page metadata (overrides config defaults)
|
|
17
|
+
title?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
image?: string;
|
|
20
|
+
author?: string;
|
|
21
|
+
language?: string;
|
|
22
|
+
created?: string;
|
|
23
|
+
modified?: string;
|
|
24
|
+
tags?: string[];
|
|
25
|
+
|
|
26
|
+
// Page type (controls og:type and Schema.org @type)
|
|
27
|
+
type?: "website" | "article" | "profile";
|
|
28
|
+
|
|
29
|
+
// Appearance
|
|
30
|
+
themeColor?: string | { light: string; dark: string };
|
|
31
|
+
tileColor?: string;
|
|
32
|
+
|
|
33
|
+
// Visibility
|
|
34
|
+
visibility?: "public" | "private" | "unlisted";
|
|
35
|
+
|
|
36
|
+
// Optional features
|
|
37
|
+
rssFeedUrl?: string | null;
|
|
38
|
+
rssFeedTitle?: string;
|
|
39
|
+
faviconPath?: string;
|
|
40
|
+
headExtensions?: string | string[];
|
|
41
|
+
|
|
42
|
+
// Absolute origin overriding Astro.site (Astro.site is a build-time
|
|
43
|
+
// constant — pass this when the actual per-request origin, e.g. a
|
|
44
|
+
// user's verified custom domain, differs from the build's default site).
|
|
45
|
+
siteUrl?: string;
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
const {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// Get user preferences if context is available
|
|
82
|
-
const userPrefs = contextData?.visitor?.raw?.preferences || contextData?.preferences || {
|
|
83
|
-
theme: "default",
|
|
84
|
-
colorMode: "light",
|
|
85
|
-
uiLanguage: "en",
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// Extract frontmatter from data source if available
|
|
89
|
-
const sourceFrontmatter = dataView?.frontmatter || effectiveDataSource?.raw?.frontmatter || {};
|
|
90
|
-
const effectiveFrontmatter = { ...frontmatter, ...sourceFrontmatter };
|
|
91
|
-
|
|
92
|
-
// Build metadata with dynamic data support
|
|
93
|
-
const ogData = dataView?.og || {};
|
|
94
|
-
const title = propsTitle || ogData.title || effectiveFrontmatter?.title || config?.title;
|
|
95
|
-
const description = propsDescription || ogData.description || effectiveFrontmatter?.description || config?.description;
|
|
96
|
-
const image = propsImage || ogData.image || effectiveFrontmatter?.image;
|
|
97
|
-
const created = propsCreated || effectiveFrontmatter?.created;
|
|
98
|
-
const modified = propsModified || effectiveFrontmatter?.modified;
|
|
99
|
-
const tags = propsTags || effectiveFrontmatter?.tags;
|
|
100
|
-
const securityHeaders = propsSecurityHeaders || effectiveFrontmatter?.securityHeaders || site?.securityHeaders;
|
|
101
|
-
|
|
102
|
-
const fullTitle = title && title !== site.title ? `${title} · ${site.title}` : site.title;
|
|
103
|
-
|
|
104
|
-
// Ensure we have a valid base URL
|
|
105
|
-
const baseUrl = site.url || config?.url || Astro.site || 'http://localhost:4321';
|
|
106
|
-
const pageUrl = new URL(Astro.url.pathname, baseUrl);
|
|
49
|
+
title: propsTitle,
|
|
50
|
+
description: propsDescription,
|
|
51
|
+
image: propsImage,
|
|
52
|
+
author: propsAuthor,
|
|
53
|
+
language: propsLanguage,
|
|
54
|
+
created: propsCreated,
|
|
55
|
+
modified: propsModified,
|
|
56
|
+
tags: propsTags,
|
|
57
|
+
type = "website",
|
|
58
|
+
themeColor,
|
|
59
|
+
tileColor,
|
|
60
|
+
visibility = "public",
|
|
61
|
+
rssFeedUrl,
|
|
62
|
+
rssFeedTitle,
|
|
63
|
+
faviconPath,
|
|
64
|
+
headExtensions,
|
|
65
|
+
siteUrl: propsSiteUrl,
|
|
66
|
+
} = Astro.props as Props;
|
|
67
|
+
|
|
68
|
+
// ── Site defaults from standard() config ──
|
|
69
|
+
const siteTitle = config.title || "";
|
|
70
|
+
const siteDescription = config.description || "";
|
|
71
|
+
const siteAuthor = config.author?.name || "";
|
|
72
|
+
const siteLanguage = config.language || "en";
|
|
73
|
+
|
|
74
|
+
// ── Resolved metadata — props override config ──
|
|
75
|
+
const title = propsTitle || siteTitle;
|
|
76
|
+
const description = propsDescription || siteDescription;
|
|
77
|
+
const authorName = propsAuthor || siteAuthor;
|
|
78
|
+
const pageLanguage = propsLanguage || siteLanguage;
|
|
79
|
+
const image = propsImage;
|
|
80
|
+
const created = propsCreated;
|
|
81
|
+
const modified = propsModified;
|
|
82
|
+
const tags = propsTags;
|
|
83
|
+
|
|
84
|
+
// ── URL construction ──
|
|
85
|
+
const baseUrl = (propsSiteUrl || Astro.site?.toString() || "").replace(/\/$/, "");
|
|
86
|
+
const pageUrl = new URL(Astro.url.pathname, baseUrl || "http://localhost:4321");
|
|
107
87
|
const canonicalUrl = new URL(
|
|
108
|
-
|
|
109
|
-
|
|
88
|
+
Astro.url.pathname.replace(/index\.html$/, ""),
|
|
89
|
+
baseUrl || "http://localhost:4321",
|
|
110
90
|
);
|
|
111
91
|
|
|
112
|
-
// Description
|
|
113
|
-
const
|
|
114
|
-
const metaDescription = (description ||
|
|
115
|
-
getExcerpt(pageExcerpt, { maxChars: 150 }) ||
|
|
116
|
-
site.description ||
|
|
117
|
-
"").toString();
|
|
92
|
+
// ── Description ──
|
|
93
|
+
const metaDescription = (description || "").toString();
|
|
118
94
|
|
|
119
|
-
// Image
|
|
95
|
+
// ── Image ──
|
|
120
96
|
const imageUrl = image
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
: null;
|
|
136
|
-
const dateModified = modified || created
|
|
137
|
-
? new Date(modified || created).toISOString()
|
|
97
|
+
? image.startsWith("http")
|
|
98
|
+
? image
|
|
99
|
+
: `${baseUrl}/assets/img/${image}`
|
|
100
|
+
: baseUrl
|
|
101
|
+
? `${baseUrl}/assets/img/default.png`
|
|
102
|
+
: "/assets/img/default.png";
|
|
103
|
+
const imageAlt = title || "";
|
|
104
|
+
|
|
105
|
+
// ── Dates ──
|
|
106
|
+
const datePublished = created ? new Date(created).toISOString() : null;
|
|
107
|
+
const dateModified = modified
|
|
108
|
+
? new Date(modified).toISOString()
|
|
109
|
+
: created
|
|
110
|
+
? new Date(created).toISOString()
|
|
138
111
|
: null;
|
|
139
112
|
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
//
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
//
|
|
151
|
-
const
|
|
113
|
+
// ── Favicon ──
|
|
114
|
+
const faviconBase = faviconPath || "/assets/favicon";
|
|
115
|
+
|
|
116
|
+
// ── Theme colors ──
|
|
117
|
+
const resolvedThemeColor =
|
|
118
|
+
typeof themeColor === "string"
|
|
119
|
+
? { light: themeColor, dark: themeColor }
|
|
120
|
+
: themeColor || { light: "#ffffff", dark: "#1a1a1a" };
|
|
121
|
+
const resolvedTileColor = tileColor || "#ffffff";
|
|
122
|
+
|
|
123
|
+
// ── OG & Schema.org types ──
|
|
124
|
+
const ogType = type;
|
|
125
|
+
const schemaType =
|
|
126
|
+
type === "article"
|
|
127
|
+
? "BlogPosting"
|
|
128
|
+
: type === "profile"
|
|
129
|
+
? "ProfilePage"
|
|
130
|
+
: "WebSite";
|
|
131
|
+
|
|
132
|
+
// ── Head extensions ──
|
|
133
|
+
const headExtraHtml = Array.isArray(headExtensions)
|
|
134
|
+
? headExtensions.join("\n")
|
|
135
|
+
: headExtensions || "";
|
|
152
136
|
---
|
|
153
137
|
|
|
154
138
|
<meta charset="utf-8" />
|
|
155
139
|
{headExtraHtml && <Fragment set:html={headExtraHtml} />}
|
|
156
|
-
<!-- Standard Framework | https://standard.ffp.co -->
|
|
157
140
|
|
|
158
141
|
<meta
|
|
159
|
-
|
|
160
|
-
|
|
142
|
+
name="viewport"
|
|
143
|
+
content="width=device-width, initial-scale=1, viewport-fit=cover"
|
|
161
144
|
/>
|
|
162
145
|
|
|
163
|
-
|
|
164
|
-
{contextData && (
|
|
165
|
-
<>
|
|
166
|
-
<meta name="mobile-web-app-capable" content="yes" />
|
|
167
|
-
<meta
|
|
168
|
-
name="apple-mobile-web-app-status-bar-style"
|
|
169
|
-
content="black-translucent"
|
|
170
|
-
/>
|
|
171
|
-
</>
|
|
172
|
-
)}
|
|
173
|
-
|
|
174
|
-
{fontsUrl && (
|
|
175
|
-
<!-- External fonts -->
|
|
176
|
-
<link rel="stylesheet" href={fontsUrl} />
|
|
177
|
-
)}
|
|
178
|
-
|
|
179
|
-
<title>{fullTitle}</title>
|
|
146
|
+
<title>{title}</title>
|
|
180
147
|
<meta name="description" content={metaDescription} />
|
|
181
|
-
<meta name="author" content={authorName} />
|
|
148
|
+
{authorName && <meta name="author" content={authorName} />}
|
|
182
149
|
<meta name="language" content={pageLanguage} />
|
|
183
150
|
<meta name="referrer" content="strict-origin-when-cross-origin" />
|
|
184
151
|
|
|
185
|
-
<!-- Canonical URL -->
|
|
186
152
|
<link rel="canonical" href={canonicalUrl} />
|
|
187
153
|
|
|
188
|
-
<!-- Feed & Sitemap -->
|
|
189
154
|
{
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
{site?.url && (
|
|
199
|
-
<link
|
|
200
|
-
rel="sitemap"
|
|
201
|
-
type="application/xml"
|
|
202
|
-
title="Sitemap"
|
|
203
|
-
href={`${site.url}/sitemap.xml`}
|
|
204
|
-
/>
|
|
205
|
-
)}
|
|
206
|
-
</>
|
|
207
|
-
) : null
|
|
155
|
+
rssFeedUrl && (
|
|
156
|
+
<link
|
|
157
|
+
rel="alternate"
|
|
158
|
+
type="application/atom+xml"
|
|
159
|
+
title={rssFeedTitle || title}
|
|
160
|
+
href={rssFeedUrl}
|
|
161
|
+
/>
|
|
162
|
+
)
|
|
208
163
|
}
|
|
209
164
|
|
|
210
165
|
{
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
{securityHeaders.referrerPolicy && (
|
|
220
|
-
<meta
|
|
221
|
-
http-equiv="Referrer-Policy"
|
|
222
|
-
content={securityHeaders.referrerPolicy}
|
|
223
|
-
/>
|
|
224
|
-
)}
|
|
225
|
-
{securityHeaders.permissions && (
|
|
226
|
-
<meta
|
|
227
|
-
http-equiv="Permissions-Policy"
|
|
228
|
-
content={securityHeaders.permissions}
|
|
229
|
-
/>
|
|
230
|
-
)}
|
|
231
|
-
{securityHeaders.xContentTypeOptions && (
|
|
232
|
-
<meta
|
|
233
|
-
http-equiv="X-Content-Type-Options"
|
|
234
|
-
content={securityHeaders.xContentTypeOptions}
|
|
235
|
-
/>
|
|
236
|
-
)}
|
|
237
|
-
</>
|
|
238
|
-
)
|
|
166
|
+
baseUrl && (
|
|
167
|
+
<link
|
|
168
|
+
rel="sitemap"
|
|
169
|
+
type="application/xml"
|
|
170
|
+
title="Sitemap"
|
|
171
|
+
href={`${baseUrl}/sitemap.xml`}
|
|
172
|
+
/>
|
|
173
|
+
)
|
|
239
174
|
}
|
|
240
175
|
|
|
241
|
-
<!--
|
|
176
|
+
<!-- CSP is handled natively by Astro 6 via security.csp config -->
|
|
177
|
+
|
|
242
178
|
{
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
179
|
+
visibility === "private" || visibility === "unlisted" ? (
|
|
180
|
+
<meta name="robots" content="noindex, nofollow" />
|
|
181
|
+
) : (
|
|
182
|
+
<meta
|
|
183
|
+
name="robots"
|
|
184
|
+
content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"
|
|
185
|
+
/>
|
|
186
|
+
)
|
|
251
187
|
}
|
|
252
188
|
|
|
253
189
|
<!-- Open Graph -->
|
|
254
|
-
<meta property="og:title" content={title
|
|
255
|
-
<meta property="og:type" content={
|
|
190
|
+
<meta property="og:title" content={title} />
|
|
191
|
+
<meta property="og:type" content={ogType} />
|
|
256
192
|
<meta property="og:locale" content={pageLanguage} />
|
|
257
|
-
<meta property="og:site_name" content={
|
|
193
|
+
{siteTitle && <meta property="og:site_name" content={siteTitle} />}
|
|
258
194
|
<meta property="og:url" content={pageUrl} />
|
|
259
195
|
<meta property="og:description" content={metaDescription} />
|
|
260
196
|
|
|
@@ -264,139 +200,101 @@ const headExtraHtml = Array.isArray(headExtensions) ? headExtensions.join("\n")
|
|
|
264
200
|
<meta property="og:image:height" content="630" />
|
|
265
201
|
|
|
266
202
|
{
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
203
|
+
type === "article" && datePublished && (
|
|
204
|
+
<>
|
|
205
|
+
<meta property="article:published_time" content={datePublished} />
|
|
206
|
+
{authorName && <meta property="article:author" content={authorName} />}
|
|
207
|
+
{tags &&
|
|
208
|
+
tags.map((tag: string) => (
|
|
209
|
+
<meta property="article:tag" content={tag} />
|
|
210
|
+
))}
|
|
211
|
+
</>
|
|
212
|
+
)
|
|
277
213
|
}
|
|
278
214
|
|
|
279
215
|
<!-- Twitter Cards -->
|
|
280
|
-
<meta name="twitter:card" content={
|
|
216
|
+
<meta name="twitter:card" content={image ? "summary_large_image" : "summary"} />
|
|
281
217
|
<meta name="twitter:image" content={imageUrl} />
|
|
282
218
|
<meta name="twitter:image:alt" content={imageAlt} />
|
|
283
|
-
<meta name="twitter:
|
|
284
|
-
<meta name="twitter:creator" content={`@${twitterUsername}`} />
|
|
285
|
-
<meta name="twitter:title" content={fullTitle} />
|
|
219
|
+
<meta name="twitter:title" content={title} />
|
|
286
220
|
<meta name="twitter:description" content={metaDescription} />
|
|
287
221
|
|
|
288
222
|
<!-- Schema.org -->
|
|
289
223
|
<script
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
224
|
+
type="application/ld+json"
|
|
225
|
+
set:html={JSON.stringify({
|
|
226
|
+
"@context": "https://schema.org",
|
|
227
|
+
"@type": schemaType,
|
|
228
|
+
...(type === "article"
|
|
229
|
+
? {
|
|
230
|
+
headline: title,
|
|
231
|
+
description: metaDescription,
|
|
232
|
+
...(authorName
|
|
233
|
+
? {
|
|
234
|
+
author: { "@type": "Person", name: authorName },
|
|
235
|
+
publisher: { "@type": "Person", name: authorName },
|
|
236
|
+
}
|
|
237
|
+
: {}),
|
|
238
|
+
...(datePublished ? { datePublished } : {}),
|
|
239
|
+
...(dateModified ? { dateModified } : {}),
|
|
240
|
+
image: {
|
|
241
|
+
"@type": "ImageObject",
|
|
242
|
+
url: imageUrl,
|
|
243
|
+
width: 1200,
|
|
244
|
+
height: 630,
|
|
245
|
+
},
|
|
246
|
+
mainEntityOfPage: { "@type": "WebPage", "@id": pageUrl },
|
|
247
|
+
}
|
|
248
|
+
: {
|
|
249
|
+
name: siteTitle || title,
|
|
250
|
+
description: metaDescription,
|
|
251
|
+
url: baseUrl,
|
|
252
|
+
...(authorName
|
|
295
253
|
? {
|
|
296
|
-
|
|
297
|
-
description: metaDescription,
|
|
298
|
-
author: {
|
|
299
|
-
"@type": "Person",
|
|
300
|
-
name: authorName,
|
|
301
|
-
url: `${site.url}/now/`,
|
|
302
|
-
},
|
|
303
|
-
publisher: {
|
|
304
|
-
"@type": "Person",
|
|
305
|
-
name: authorName,
|
|
306
|
-
url: site.url,
|
|
307
|
-
},
|
|
308
|
-
...(datePublished ? { datePublished } : {}),
|
|
309
|
-
...(dateModified ? { dateModified } : {}),
|
|
310
|
-
image: {
|
|
311
|
-
"@type": "ImageObject",
|
|
312
|
-
url: imageUrl,
|
|
313
|
-
width: 1200,
|
|
314
|
-
height: 630,
|
|
315
|
-
},
|
|
316
|
-
mainEntityOfPage: {
|
|
317
|
-
"@type": "WebPage",
|
|
318
|
-
"@id": pageUrl,
|
|
319
|
-
},
|
|
254
|
+
author: { "@type": "Person", name: authorName },
|
|
320
255
|
}
|
|
321
|
-
: {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
url: site.url,
|
|
325
|
-
author: {
|
|
326
|
-
"@type": "Person",
|
|
327
|
-
name: authorName,
|
|
328
|
-
url: site.url,
|
|
329
|
-
},
|
|
330
|
-
}),
|
|
331
|
-
})}
|
|
256
|
+
: {}),
|
|
257
|
+
}),
|
|
258
|
+
})}
|
|
332
259
|
/>
|
|
333
260
|
|
|
334
261
|
<!-- Favicons -->
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
<meta name="apple-mobile-web-app-title" content={site.title} />
|
|
351
|
-
<link rel="manifest" href={`${faviconBasePath}/site.webmanifest`} />
|
|
352
|
-
</>
|
|
353
|
-
) : (
|
|
354
|
-
<>
|
|
355
|
-
<link
|
|
356
|
-
rel="apple-touch-icon"
|
|
357
|
-
sizes="180x180"
|
|
358
|
-
href={`${faviconBasePath}/apple-touch-icon.png`}
|
|
359
|
-
/>
|
|
360
|
-
<link
|
|
361
|
-
rel="icon"
|
|
362
|
-
type="image/png"
|
|
363
|
-
sizes="32x32"
|
|
364
|
-
href={`${faviconBasePath}/favicon-32x32.png`}
|
|
365
|
-
/>
|
|
366
|
-
<link
|
|
367
|
-
rel="icon"
|
|
368
|
-
type="image/png"
|
|
369
|
-
sizes="16x16"
|
|
370
|
-
href={`${faviconBasePath}/favicon-16x16.png`}
|
|
371
|
-
/>
|
|
372
|
-
<link rel="manifest" href="/site.webmanifest" />
|
|
373
|
-
<link
|
|
374
|
-
rel="mask-icon"
|
|
375
|
-
href={`${faviconBasePath}/safari-pinned-tab.svg`}
|
|
376
|
-
color="#000000"
|
|
377
|
-
/>
|
|
378
|
-
<link rel="shortcut icon" href={`${faviconBasePath}/favicon.ico`} />
|
|
379
|
-
</>
|
|
380
|
-
)}
|
|
262
|
+
<link
|
|
263
|
+
rel="icon"
|
|
264
|
+
type="image/png"
|
|
265
|
+
href={`${faviconBase}/favicon-96x96.png`}
|
|
266
|
+
sizes="96x96"
|
|
267
|
+
/>
|
|
268
|
+
<link rel="icon" type="image/svg+xml" href={`${faviconBase}/favicon.svg`} />
|
|
269
|
+
<link rel="shortcut icon" href={`${faviconBase}/favicon.ico`} />
|
|
270
|
+
<link
|
|
271
|
+
rel="apple-touch-icon"
|
|
272
|
+
sizes="180x180"
|
|
273
|
+
href={`${faviconBase}/apple-touch-icon.png`}
|
|
274
|
+
/>
|
|
275
|
+
<meta name="apple-mobile-web-app-title" content={siteTitle || title || ""} />
|
|
276
|
+
<link rel="manifest" href="/site.webmanifest" />
|
|
381
277
|
|
|
382
278
|
<!-- Mobile -->
|
|
383
279
|
<meta
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
280
|
+
name="theme-color"
|
|
281
|
+
content={resolvedThemeColor.light}
|
|
282
|
+
media="(prefers-color-scheme: light)"
|
|
387
283
|
/>
|
|
388
284
|
<meta
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
285
|
+
name="theme-color"
|
|
286
|
+
content={resolvedThemeColor.dark}
|
|
287
|
+
media="(prefers-color-scheme: dark)"
|
|
288
|
+
/>
|
|
289
|
+
<meta name="mobile-web-app-capable" content="yes" />
|
|
290
|
+
<meta
|
|
291
|
+
name="apple-mobile-web-app-status-bar-style"
|
|
292
|
+
content="black-translucent"
|
|
392
293
|
/>
|
|
393
294
|
|
|
394
295
|
<!-- Windows Tiles -->
|
|
395
|
-
<meta name="msapplication-TileColor" content=
|
|
296
|
+
<meta name="msapplication-TileColor" content={resolvedTileColor} />
|
|
396
297
|
<meta
|
|
397
|
-
|
|
398
|
-
|
|
298
|
+
name="msapplication-config"
|
|
299
|
+
content={`${faviconBase}/browserconfig.xml`}
|
|
399
300
|
/>
|
|
400
|
-
|
|
401
|
-
<!-- Client Router (Astro view transitions) -->
|
|
402
|
-
<!-- {enableClientRouter && <ClientRouter />} -->
|