@mannisto/astro-metadata 1.0.0-alpha.3 → 1.0.0-alpha.5
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/README.md +22 -80
- package/index.ts +1 -2
- package/package.json +1 -1
- package/src/components/Favicon.astro +54 -151
- package/src/components/Head.astro +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Astro Metadata
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|
|
|
5
5
|

|
|
6
6
|

|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
Astro components for managing your page head — metadata, social sharing, favicons, and SEO.
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
## Table of contents
|
|
13
12
|
|
|
14
13
|
- [Installation](#installation)
|
|
@@ -30,7 +29,6 @@ Astro components for managing your page head — metadata, social sharing, favic
|
|
|
30
29
|
- [Twitter](#twitter)
|
|
31
30
|
- [License](#license)
|
|
32
31
|
|
|
33
|
-
|
|
34
32
|
## Installation
|
|
35
33
|
```bash
|
|
36
34
|
# pnpm
|
|
@@ -52,7 +50,6 @@ There are three ways to use this package. Pick what suits your project, or combi
|
|
|
52
50
|
The simplest approach. Use `Head` in your layout and pass props down from your pages. Charset and viewport are included automatically.
|
|
53
51
|
```astro
|
|
54
52
|
---
|
|
55
|
-
|
|
56
53
|
// layouts/Layout.astro
|
|
57
54
|
import { Head } from "@mannisto/astro-metadata"
|
|
58
55
|
import type { HeadProps } from "@mannisto/astro-metadata"
|
|
@@ -60,7 +57,6 @@ import type { HeadProps } from "@mannisto/astro-metadata"
|
|
|
60
57
|
interface Props extends HeadProps {}
|
|
61
58
|
|
|
62
59
|
const { title, description, ...rest } = Astro.props
|
|
63
|
-
|
|
64
60
|
---
|
|
65
61
|
|
|
66
62
|
<html>
|
|
@@ -75,13 +71,10 @@ const { title, description, ...rest } = Astro.props
|
|
|
75
71
|
</body>
|
|
76
72
|
</html>
|
|
77
73
|
```
|
|
78
|
-
|
|
79
74
|
```astro
|
|
80
75
|
---
|
|
81
|
-
|
|
82
76
|
// pages/index.astro
|
|
83
77
|
import Layout from "../layouts/Layout.astro"
|
|
84
|
-
|
|
85
78
|
---
|
|
86
79
|
|
|
87
80
|
<Layout title="Home" description="Welcome to my site">
|
|
@@ -91,16 +84,12 @@ import Layout from "../layouts/Layout.astro"
|
|
|
91
84
|
|
|
92
85
|
Best for simple sites where pages pass metadata as props to their layout.
|
|
93
86
|
|
|
94
|
-
|
|
95
87
|
### 2. Individual components
|
|
96
88
|
|
|
97
89
|
Use components directly inside your own `<head>`. Useful when you only need specific pieces, or want full control over the structure.
|
|
98
|
-
|
|
99
90
|
```astro
|
|
100
91
|
---
|
|
101
|
-
|
|
102
92
|
import { Title, Description, OpenGraph, Favicon } from "@mannisto/astro-metadata"
|
|
103
|
-
|
|
104
93
|
---
|
|
105
94
|
|
|
106
95
|
<html>
|
|
@@ -120,12 +109,10 @@ import { Title, Description, OpenGraph, Favicon } from "@mannisto/astro-metadata
|
|
|
120
109
|
}}
|
|
121
110
|
/>
|
|
122
111
|
<Favicon
|
|
123
|
-
icons={
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
},
|
|
128
|
-
}}
|
|
112
|
+
icons={[
|
|
113
|
+
{ path: "/favicon.ico" },
|
|
114
|
+
{ path: "/favicon.svg" },
|
|
115
|
+
]}
|
|
129
116
|
/>
|
|
130
117
|
</head>
|
|
131
118
|
<body>
|
|
@@ -136,14 +123,11 @@ import { Title, Description, OpenGraph, Favicon } from "@mannisto/astro-metadata
|
|
|
136
123
|
|
|
137
124
|
Best for when you want to compose only what you need, or when `Head` is too opinionated for your setup.
|
|
138
125
|
|
|
139
|
-
|
|
140
126
|
### 3. Metadata utility
|
|
141
127
|
|
|
142
128
|
Set metadata in your page, resolve it in your layout. Eliminates prop drilling through nested layout layers.
|
|
143
|
-
|
|
144
129
|
```astro
|
|
145
130
|
---
|
|
146
|
-
|
|
147
131
|
// pages/about.astro
|
|
148
132
|
import { Metadata } from "@mannisto/astro-metadata"
|
|
149
133
|
import Layout from "../layouts/Layout.astro"
|
|
@@ -158,17 +142,14 @@ Metadata.set({
|
|
|
158
142
|
},
|
|
159
143
|
},
|
|
160
144
|
})
|
|
161
|
-
|
|
162
145
|
---
|
|
163
146
|
|
|
164
147
|
<Layout>
|
|
165
148
|
<h1>About</h1>
|
|
166
149
|
</Layout>
|
|
167
150
|
```
|
|
168
|
-
|
|
169
151
|
```astro
|
|
170
152
|
---
|
|
171
|
-
|
|
172
153
|
// layouts/Layout.astro
|
|
173
154
|
import { Head, Metadata } from "@mannisto/astro-metadata"
|
|
174
155
|
|
|
@@ -177,7 +158,6 @@ const meta = Metadata.resolve({
|
|
|
177
158
|
description: "Default description",
|
|
178
159
|
titleTemplate: "%s | My Site",
|
|
179
160
|
})
|
|
180
|
-
|
|
181
161
|
---
|
|
182
162
|
|
|
183
163
|
<html>
|
|
@@ -192,14 +172,12 @@ const meta = Metadata.resolve({
|
|
|
192
172
|
|
|
193
173
|
Best for sites with deeply nested layouts, or when you want to keep metadata co-located with page content.
|
|
194
174
|
|
|
195
|
-
|
|
196
175
|
## Components
|
|
197
176
|
|
|
198
177
|
<details>
|
|
199
178
|
<summary><strong>Canonical</strong></summary>
|
|
200
179
|
|
|
201
180
|
Renders a canonical link tag. Falls back to `Astro.url.href` when no value is provided, so every page gets a canonical tag with zero configuration.
|
|
202
|
-
|
|
203
181
|
```astro
|
|
204
182
|
<Canonical value="https://example.com/page" />
|
|
205
183
|
```
|
|
@@ -210,10 +188,8 @@ Renders a canonical link tag. Falls back to `Astro.url.href` when no value is pr
|
|
|
210
188
|
|
|
211
189
|
</details>
|
|
212
190
|
|
|
213
|
-
|
|
214
191
|
<details>
|
|
215
192
|
<summary><strong>Description</strong></summary>
|
|
216
|
-
|
|
217
193
|
```astro
|
|
218
194
|
<Description value="Welcome to my site" />
|
|
219
195
|
```
|
|
@@ -224,65 +200,44 @@ Renders a canonical link tag. Falls back to `Astro.url.href` when no value is pr
|
|
|
224
200
|
|
|
225
201
|
</details>
|
|
226
202
|
|
|
227
|
-
|
|
228
203
|
<details>
|
|
229
204
|
<summary><strong>Favicon</strong></summary>
|
|
230
205
|
|
|
231
|
-
Favicon support with
|
|
232
|
-
|
|
206
|
+
Favicon support with light and dark mode variants and automatic MIME type detection.
|
|
233
207
|
```astro
|
|
234
208
|
<Favicon
|
|
235
|
-
icons={
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
},
|
|
242
|
-
|
|
243
|
-
svg: { path: "/favicon-light.svg" },
|
|
244
|
-
},
|
|
245
|
-
darkMode: {
|
|
246
|
-
svg: { path: "/favicon-dark.svg" },
|
|
247
|
-
},
|
|
248
|
-
}}
|
|
209
|
+
icons={[
|
|
210
|
+
{ path: "/favicon.ico" },
|
|
211
|
+
{ path: "/favicon.svg" },
|
|
212
|
+
{ path: "/favicon-96x96.png", size: 96 },
|
|
213
|
+
{ path: "/apple-touch-icon.png", size: 180, apple: true },
|
|
214
|
+
{ path: "/favicon-dark.svg", theme: "dark" },
|
|
215
|
+
{ path: "/favicon-light.svg", theme: "light" },
|
|
216
|
+
]}
|
|
249
217
|
manifest="/site.webmanifest"
|
|
250
|
-
cacheBust
|
|
251
218
|
/>
|
|
252
219
|
```
|
|
253
220
|
|
|
254
221
|
| Prop | Type | Description |
|
|
255
222
|
|------|------|-------------|
|
|
256
|
-
| `icons
|
|
257
|
-
| `icons.lightMode` | `FaviconIcons` | Favicons shown in light color scheme |
|
|
258
|
-
| `icons.darkMode` | `FaviconIcons` | Favicons shown in dark color scheme |
|
|
223
|
+
| `icons` | `FaviconFile[]` | List of favicon files |
|
|
259
224
|
| `manifest` | `string` | Path to web app manifest |
|
|
260
|
-
| `cacheBust` | `boolean` | Append `?v={timestamp}` to favicon URLs |
|
|
261
|
-
|
|
262
|
-
#### FaviconIcons
|
|
263
|
-
|
|
264
|
-
| Prop | Type | Description |
|
|
265
|
-
|------|------|-------------|
|
|
266
|
-
| `ico` | `FaviconFile` | `.ico` favicon |
|
|
267
|
-
| `svg` | `FaviconFile` | `.svg` favicon |
|
|
268
|
-
| `png` | `FaviconFile \| FaviconFile[]` | One or more `.png` favicons |
|
|
269
|
-
| `apple` | `FaviconFile` | Apple touch icon |
|
|
270
225
|
|
|
271
226
|
#### FaviconFile
|
|
272
227
|
|
|
273
228
|
| Prop | Type | Description |
|
|
274
229
|
|------|------|-------------|
|
|
275
|
-
| `path` | `string` | Path to the file |
|
|
230
|
+
| `path` | `string` | Path to the file. MIME type is detected automatically. |
|
|
276
231
|
| `size` | `number` | Size in pixels. Rendered as `NxN` in the `sizes` attribute. |
|
|
232
|
+
| `theme` | `"light" \| "dark"` | Adds a `prefers-color-scheme` media query |
|
|
233
|
+
| `apple` | `boolean` | Renders as `<link rel="apple-touch-icon">` |
|
|
277
234
|
|
|
278
235
|
</details>
|
|
279
236
|
|
|
280
|
-
|
|
281
237
|
<details>
|
|
282
238
|
<summary><strong>Head</strong></summary>
|
|
283
239
|
|
|
284
240
|
Wraps the entire page head and composes all sub-components internally. Charset and viewport are always included and can be overridden if needed.
|
|
285
|
-
|
|
286
241
|
```astro
|
|
287
242
|
<Head
|
|
288
243
|
title="Home"
|
|
@@ -297,11 +252,10 @@ Wraps the entire page head and composes all sub-components internally. Charset a
|
|
|
297
252
|
},
|
|
298
253
|
}}
|
|
299
254
|
favicon={{
|
|
300
|
-
icons:
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
},
|
|
255
|
+
icons: [
|
|
256
|
+
{ path: "/favicon.ico" },
|
|
257
|
+
{ path: "/favicon.svg" },
|
|
258
|
+
],
|
|
305
259
|
}}
|
|
306
260
|
/>
|
|
307
261
|
```
|
|
@@ -323,7 +277,6 @@ Wraps the entire page head and composes all sub-components internally. Charset a
|
|
|
323
277
|
| `languageAlternates` | `LanguageAlternate[]` | — | Hreflang alternate links |
|
|
324
278
|
|
|
325
279
|
#### Slots
|
|
326
|
-
|
|
327
280
|
```astro
|
|
328
281
|
<Head title="My Site">
|
|
329
282
|
<!-- Renders before charset and viewport -->
|
|
@@ -336,10 +289,8 @@ Wraps the entire page head and composes all sub-components internally. Charset a
|
|
|
336
289
|
|
|
337
290
|
</details>
|
|
338
291
|
|
|
339
|
-
|
|
340
292
|
<details>
|
|
341
293
|
<summary><strong>Keywords</strong></summary>
|
|
342
|
-
|
|
343
294
|
```astro
|
|
344
295
|
<Keywords value={["astro", "seo", "metadata"]} />
|
|
345
296
|
```
|
|
@@ -350,12 +301,10 @@ Wraps the entire page head and composes all sub-components internally. Charset a
|
|
|
350
301
|
|
|
351
302
|
</details>
|
|
352
303
|
|
|
353
|
-
|
|
354
304
|
<details>
|
|
355
305
|
<summary><strong>LanguageAlternates</strong></summary>
|
|
356
306
|
|
|
357
307
|
Renders `<link rel="alternate" hreflang>` tags for multilingual sites. Tells search engines which language version to serve for a given region.
|
|
358
|
-
|
|
359
308
|
```astro
|
|
360
309
|
<LanguageAlternates
|
|
361
310
|
alternates={[
|
|
@@ -374,7 +323,6 @@ Renders `<link rel="alternate" hreflang>` tags for multilingual sites. Tells sea
|
|
|
374
323
|
|
|
375
324
|
</details>
|
|
376
325
|
|
|
377
|
-
|
|
378
326
|
<details>
|
|
379
327
|
<summary><strong>OpenGraph</strong></summary>
|
|
380
328
|
|
|
@@ -410,7 +358,6 @@ Renders Open Graph meta tags for rich previews when your pages are shared on soc
|
|
|
410
358
|
|
|
411
359
|
</details>
|
|
412
360
|
|
|
413
|
-
|
|
414
361
|
<details>
|
|
415
362
|
<summary><strong>Robots</strong></summary>
|
|
416
363
|
|
|
@@ -432,7 +379,6 @@ Controls how search engines crawl and index your page. Defaults to `index, follo
|
|
|
432
379
|
|
|
433
380
|
</details>
|
|
434
381
|
|
|
435
|
-
|
|
436
382
|
<details>
|
|
437
383
|
<summary><strong>Schema</strong></summary>
|
|
438
384
|
|
|
@@ -454,12 +400,10 @@ Outputs a `<script type="application/ld+json">` tag for structured data. Use it
|
|
|
454
400
|
|
|
455
401
|
</details>
|
|
456
402
|
|
|
457
|
-
|
|
458
403
|
<details>
|
|
459
404
|
<summary><strong>Title</strong></summary>
|
|
460
405
|
|
|
461
406
|
Renders the `<title>` tag. The template must contain `%s`, which is replaced with the page title — TypeScript enforces this at the type level.
|
|
462
|
-
|
|
463
407
|
```astro
|
|
464
408
|
<Title value="My Page" template="%s | My Site" />
|
|
465
409
|
```
|
|
@@ -471,12 +415,10 @@ Renders the `<title>` tag. The template must contain `%s`, which is replaced wit
|
|
|
471
415
|
|
|
472
416
|
</details>
|
|
473
417
|
|
|
474
|
-
|
|
475
418
|
<details>
|
|
476
419
|
<summary><strong>Twitter</strong></summary>
|
|
477
420
|
|
|
478
421
|
Renders Twitter card meta tags for rich previews on X. When used inside `Head`, `title` and `description` fall back to the page values automatically.
|
|
479
|
-
|
|
480
422
|
```astro
|
|
481
423
|
<Twitter
|
|
482
424
|
card="summary_large_image"
|
package/index.ts
CHANGED
|
@@ -20,8 +20,7 @@ export type { Props as RobotsProps } from "./src/components/Robots.a
|
|
|
20
20
|
export type { Props as OpenGraphProps } from "./src/components/OpenGraph.astro"
|
|
21
21
|
export type { Props as TwitterProps } from "./src/components/Twitter.astro"
|
|
22
22
|
export type { Props as FaviconProps,
|
|
23
|
-
FaviconFile
|
|
24
|
-
FaviconIcons } from "./src/components/Favicon.astro"
|
|
23
|
+
FaviconFile } from "./src/components/Favicon.astro"
|
|
25
24
|
export type { Props as SchemaProps } from "./src/components/Schema.astro"
|
|
26
25
|
export type { Props as LanguageAlternatesProps,
|
|
27
26
|
LanguageAlternate } from "./src/components/LanguageAlternates.astro"
|
package/package.json
CHANGED
|
@@ -1,177 +1,80 @@
|
|
|
1
1
|
---
|
|
2
2
|
|
|
3
3
|
export type FaviconFile = {
|
|
4
|
-
path
|
|
5
|
-
size?
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export type FaviconIcons = {
|
|
9
|
-
ico? : FaviconFile
|
|
10
|
-
png? : FaviconFile | FaviconFile[]
|
|
11
|
-
svg? : FaviconFile
|
|
12
|
-
apple? : FaviconFile
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
type PreparedFile = {
|
|
16
|
-
path : string
|
|
17
|
-
size? : string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
type PreparedIcons = {
|
|
21
|
-
ico? : PreparedFile
|
|
22
|
-
png? : PreparedFile[]
|
|
23
|
-
svg? : PreparedFile
|
|
24
|
-
apple? : PreparedFile
|
|
4
|
+
path : string
|
|
5
|
+
size? : number
|
|
6
|
+
theme? : "light" | "dark"
|
|
7
|
+
apple? : boolean
|
|
25
8
|
}
|
|
26
9
|
|
|
27
10
|
export type Props = {
|
|
28
|
-
icons:
|
|
29
|
-
|
|
30
|
-
lightMode? : FaviconIcons
|
|
31
|
-
darkMode? : FaviconIcons
|
|
32
|
-
}
|
|
33
|
-
manifest? : string
|
|
34
|
-
cacheBust? : boolean
|
|
11
|
+
icons : FaviconFile[]
|
|
12
|
+
manifest? : string
|
|
35
13
|
}
|
|
36
14
|
|
|
37
|
-
const {
|
|
38
|
-
icons,
|
|
39
|
-
manifest
|
|
40
|
-
cacheBust = false
|
|
15
|
+
const {
|
|
16
|
+
icons,
|
|
17
|
+
manifest
|
|
41
18
|
} = Astro.props
|
|
42
19
|
|
|
43
|
-
const cacheBustString = cacheBust
|
|
44
|
-
? `?v=${Date.now()}`
|
|
45
|
-
: ""
|
|
46
|
-
|
|
47
20
|
/**
|
|
48
|
-
*
|
|
49
|
-
* and converting the numeric size to the "NxN" format browsers expect.
|
|
21
|
+
* Detects the MIME type of a favicon file from its extension.
|
|
50
22
|
*
|
|
51
|
-
* @param
|
|
52
|
-
* @returns The
|
|
23
|
+
* @param path - The path to the favicon file.
|
|
24
|
+
* @returns The MIME type of the file.
|
|
53
25
|
*/
|
|
54
|
-
function
|
|
55
|
-
if (
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
26
|
+
function getMimeType(path: string): string {
|
|
27
|
+
if (path.endsWith(".svg")) return "image/svg+xml"
|
|
28
|
+
if (path.endsWith(".png")) return "image/png"
|
|
29
|
+
if (path.endsWith(".webp")) return "image/webp"
|
|
30
|
+
if (path.endsWith(".jpg") ||
|
|
31
|
+
path.endsWith(".jpeg")) return "image/jpeg"
|
|
32
|
+
if (path.endsWith(".ico")) return "image/x-icon"
|
|
33
|
+
return "image/x-icon"
|
|
60
34
|
}
|
|
61
35
|
|
|
62
36
|
/**
|
|
63
|
-
*
|
|
64
|
-
* Normalizes the png field to always be an array for consistent rendering.
|
|
37
|
+
* Builds the media query string for a given theme.
|
|
65
38
|
*
|
|
66
|
-
* @param
|
|
67
|
-
* @returns The
|
|
39
|
+
* @param theme - The theme to build the media query for.
|
|
40
|
+
* @returns The media query string, or undefined if no theme was provided.
|
|
68
41
|
*/
|
|
69
|
-
function
|
|
70
|
-
if (
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
svg: prepareFile(set.svg),
|
|
74
|
-
apple: prepareFile(set.apple),
|
|
75
|
-
png: set.png
|
|
76
|
-
? (Array.isArray(set.png) ? set.png : [set.png]).map((file) => prepareFile(file)!)
|
|
77
|
-
: undefined,
|
|
78
|
-
}
|
|
42
|
+
function getMedia(theme?: "light" | "dark"): string | undefined {
|
|
43
|
+
if (theme === "light") return "(prefers-color-scheme: light)"
|
|
44
|
+
if (theme === "dark") return "(prefers-color-scheme: dark)"
|
|
45
|
+
return undefined
|
|
79
46
|
}
|
|
80
47
|
|
|
81
|
-
const prepared = {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
48
|
+
const prepared = icons.map((file) => ({
|
|
49
|
+
path : file.path,
|
|
50
|
+
size : file.size ? `${file.size}x${file.size}` : undefined,
|
|
51
|
+
type : getMimeType(file.path),
|
|
52
|
+
media : getMedia(file.theme),
|
|
53
|
+
apple : file.apple ?? false,
|
|
54
|
+
}))
|
|
86
55
|
|
|
87
56
|
---
|
|
88
57
|
|
|
89
58
|
{manifest && <link rel="manifest" href={manifest} />}
|
|
90
59
|
|
|
91
|
-
{prepared.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
rel="icon"
|
|
102
|
-
type="image/svg+xml"
|
|
103
|
-
href={prepared.default.svg.path}
|
|
104
|
-
sizes={prepared.default.svg.size}
|
|
105
|
-
/>
|
|
106
|
-
)}
|
|
107
|
-
{prepared.default?.apple && (
|
|
108
|
-
<link
|
|
109
|
-
rel="apple-touch-icon"
|
|
110
|
-
href={prepared.default.apple.path}
|
|
111
|
-
sizes={prepared.default.apple.size}
|
|
112
|
-
/>
|
|
113
|
-
)}
|
|
114
|
-
{prepared.default?.png?.map((png) => (
|
|
115
|
-
<link
|
|
116
|
-
rel="icon"
|
|
117
|
-
type="image/png"
|
|
118
|
-
href={png.path}
|
|
119
|
-
sizes={png.size}
|
|
120
|
-
/>
|
|
121
|
-
))}
|
|
122
|
-
|
|
123
|
-
{prepared.lightMode?.ico && (
|
|
124
|
-
<link
|
|
125
|
-
rel="icon"
|
|
126
|
-
type="image/x-icon"
|
|
127
|
-
href={prepared.lightMode.ico.path}
|
|
128
|
-
sizes={prepared.lightMode.ico.size}
|
|
129
|
-
media="(prefers-color-scheme: light)"
|
|
130
|
-
/>
|
|
131
|
-
)}
|
|
132
|
-
{prepared.lightMode?.svg && (
|
|
133
|
-
<link
|
|
134
|
-
rel="icon"
|
|
135
|
-
type="image/svg+xml"
|
|
136
|
-
href={prepared.lightMode.svg.path}
|
|
137
|
-
sizes={prepared.lightMode.svg.size}
|
|
138
|
-
media="(prefers-color-scheme: light)"
|
|
139
|
-
/>
|
|
140
|
-
)}
|
|
141
|
-
{prepared.lightMode?.png?.map((png) => (
|
|
142
|
-
<link
|
|
143
|
-
rel="icon"
|
|
144
|
-
type="image/png"
|
|
145
|
-
href={png.path}
|
|
146
|
-
sizes={png.size}
|
|
147
|
-
media="(prefers-color-scheme: light)"
|
|
148
|
-
/>
|
|
149
|
-
))}
|
|
60
|
+
{prepared.map((icon) => {
|
|
61
|
+
if (icon.apple) {
|
|
62
|
+
return (
|
|
63
|
+
<link
|
|
64
|
+
rel="apple-touch-icon"
|
|
65
|
+
href={icon.path}
|
|
66
|
+
sizes={icon.size}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
150
70
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
<link
|
|
162
|
-
rel="icon"
|
|
163
|
-
type="image/svg+xml"
|
|
164
|
-
href={prepared.darkMode.svg.path}
|
|
165
|
-
sizes={prepared.darkMode.svg.size}
|
|
166
|
-
media="(prefers-color-scheme: dark)"
|
|
167
|
-
/>
|
|
168
|
-
)}
|
|
169
|
-
{prepared.darkMode?.png?.map((png) => (
|
|
170
|
-
<link
|
|
171
|
-
rel="icon"
|
|
172
|
-
type="image/png"
|
|
173
|
-
href={png.path}
|
|
174
|
-
sizes={png.size}
|
|
175
|
-
media="(prefers-color-scheme: dark)"
|
|
176
|
-
/>
|
|
177
|
-
))}
|
|
71
|
+
return (
|
|
72
|
+
<link
|
|
73
|
+
rel="icon"
|
|
74
|
+
type={icon.type}
|
|
75
|
+
href={icon.path}
|
|
76
|
+
sizes={icon.size}
|
|
77
|
+
media={icon.media}
|
|
78
|
+
/>
|
|
79
|
+
)
|
|
80
|
+
})}
|