@mannisto/astro-metadata 1.0.1 → 2.0.0-alpha.1
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 +427 -82
- package/package.json +35 -22
- package/src/assets/icons/LICENSE.md +35 -0
- package/src/assets/icons/binoculars.svg +1 -0
- package/src/assets/icons/caret-right.svg +1 -0
- package/src/assets/icons/check.svg +1 -0
- package/src/assets/icons/copy.svg +1 -0
- package/src/assets/icons/seal-check-duotone.svg +1 -0
- package/src/assets/icons/seal-question-duotone.svg +1 -0
- package/src/assets/icons/warning-circle-duotone.svg +1 -0
- package/src/assets/icons/warning-duotone.svg +1 -0
- package/src/assets/icons/x.svg +1 -0
- package/src/components/Metadata.astro +145 -0
- package/src/components/index.ts +2 -0
- package/src/integration.d.ts +112 -0
- package/src/integration.js +508 -0
- package/src/lib/checks.d.ts +70 -0
- package/src/lib/checks.js +193 -0
- package/src/lib/config.ts +111 -0
- package/src/lib/favicon-files.d.ts +29 -0
- package/src/lib/favicon-files.js +103 -0
- package/src/lib/favicon-image.ts +124 -0
- package/src/lib/favicon.ts +167 -0
- package/src/lib/head.d.ts +25 -0
- package/src/lib/head.js +141 -0
- package/src/lib/manifest.ts +126 -0
- package/src/lib/rules.d.ts +73 -0
- package/src/lib/rules.js +902 -0
- package/src/lib/schema.ts +208 -0
- package/src/lib/site.ts +72 -0
- package/src/lib/url.ts +79 -0
- package/src/routes/favicon.ts +14 -0
- package/src/routes/manifest.ts +18 -0
- package/src/runtime.ts +16 -0
- package/src/toolbar/app.ts +72 -0
- package/src/toolbar/assets.ts +81 -0
- package/src/toolbar/data.ts +282 -0
- package/src/toolbar/define.ts +7 -0
- package/src/toolbar/env.d.ts +10 -0
- package/src/toolbar/highlight.ts +83 -0
- package/src/toolbar/styles/shared.css +18 -0
- package/src/toolbar/styles/tokens.css +182 -0
- package/src/toolbar/toolbar-badge.ts +78 -0
- package/src/toolbar/ui/alert/alert.css +126 -0
- package/src/toolbar/ui/alert/alert.ts +102 -0
- package/src/toolbar/ui/badge/badge.css +41 -0
- package/src/toolbar/ui/badge/badge.ts +24 -0
- package/src/toolbar/ui/code-block/code-block.css +90 -0
- package/src/toolbar/ui/code-block/code-block.ts +68 -0
- package/src/toolbar/ui/color-swatch/color-swatch.css +15 -0
- package/src/toolbar/ui/color-swatch/color-swatch.ts +31 -0
- package/src/toolbar/ui/icon/icon.css +11 -0
- package/src/toolbar/ui/icon/icon.ts +46 -0
- package/src/toolbar/ui/image/image.css +18 -0
- package/src/toolbar/ui/image/image.ts +58 -0
- package/src/toolbar/ui/inline-code/inline-code.css +16 -0
- package/src/toolbar/ui/inline-code/inline-code.ts +41 -0
- package/src/toolbar/ui/section/section.css +88 -0
- package/src/toolbar/ui/section/section.ts +78 -0
- package/src/toolbar/ui/tab/tab.css +7 -0
- package/src/toolbar/ui/tab/tab.ts +47 -0
- package/src/toolbar/ui/tab-group/tab-group.css +42 -0
- package/src/toolbar/ui/tab-group/tab-group.ts +101 -0
- package/src/toolbar/ui/table/table.css +124 -0
- package/src/toolbar/ui/table/table.ts +155 -0
- package/src/toolbar/views/code-blocks.ts +35 -0
- package/src/toolbar/views/metadata-panel.css +101 -0
- package/src/toolbar/views/metadata-panel.ts +125 -0
- package/src/toolbar/views/overview-view.css +27 -0
- package/src/toolbar/views/overview-view.ts +401 -0
- package/src/toolbar/views/previews/discord.css +70 -0
- package/src/toolbar/views/previews/discord.ts +60 -0
- package/src/toolbar/views/previews/facebook.css +65 -0
- package/src/toolbar/views/previews/facebook.ts +36 -0
- package/src/toolbar/views/previews/google.css +75 -0
- package/src/toolbar/views/previews/google.ts +36 -0
- package/src/toolbar/views/previews/linkedin.css +58 -0
- package/src/toolbar/views/previews/linkedin.ts +34 -0
- package/src/toolbar/views/previews/page.ts +129 -0
- package/src/toolbar/views/previews/platform.ts +14 -0
- package/src/toolbar/views/previews/previews-view.css +37 -0
- package/src/toolbar/views/previews/previews-view.ts +52 -0
- package/src/toolbar/views/previews/slack.css +61 -0
- package/src/toolbar/views/previews/slack.ts +47 -0
- package/src/toolbar/views/previews/twitter.css +89 -0
- package/src/toolbar/views/previews/twitter.ts +57 -0
- package/src/toolbar/views/previews/whatsapp.css +88 -0
- package/src/toolbar/views/previews/whatsapp.ts +65 -0
- package/src/toolbar/views/raw-view.ts +41 -0
- package/index.ts +0 -31
- package/src/components/Canonical.astro +0 -11
- package/src/components/Description.astro +0 -9
- package/src/components/Favicon.astro +0 -88
- package/src/components/Head.astro +0 -96
- package/src/components/Keywords.astro +0 -9
- package/src/components/LanguageAlternates.astro +0 -18
- package/src/components/OpenGraph.astro +0 -75
- package/src/components/Robots.astro +0 -25
- package/src/components/Schema.astro +0 -9
- package/src/components/Title.astro +0 -10
- package/src/components/Twitter.astro +0 -25
- package/src/lib/metadata.ts +0 -77
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The style of the Supabase alert: a dark tinted background and border, and the icon
|
|
3
|
+
* in a filled square of the level color. The text keeps the normal text colors.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
:host {
|
|
7
|
+
display: grid;
|
|
8
|
+
grid-template-columns: auto 1fr;
|
|
9
|
+
align-items: flex-start;
|
|
10
|
+
gap: var(--space-200);
|
|
11
|
+
background: var(--background);
|
|
12
|
+
border-radius: var(--radius);
|
|
13
|
+
border: 1px solid var(--border);
|
|
14
|
+
font-size: var(--font-size-small);
|
|
15
|
+
color: var(--color);
|
|
16
|
+
padding: var(--space-300) var(--space-200);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
:host([level="success"]) {
|
|
20
|
+
--background: color-mix(in srgb, var(--green-350) 15%, transparent);
|
|
21
|
+
--icon: var(--green-250);
|
|
22
|
+
--text: var(--green-50);
|
|
23
|
+
--border: var(--green-350);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
:host([level="info"]) {
|
|
27
|
+
--background: color-mix(in srgb, var(--blue-350) 15%, transparent);
|
|
28
|
+
--icon: var(--blue-250);
|
|
29
|
+
--text: var(--blue-50);
|
|
30
|
+
--border: var(--blue-350);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:host([level="warning"]) {
|
|
34
|
+
--background: color-mix(in srgb, var(--yellow-350) 10%, transparent);
|
|
35
|
+
--icon: var(--yellow-250);
|
|
36
|
+
--text: var(--yellow-150);
|
|
37
|
+
--border: var(--yellow-500);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
:host([level="error"]) {
|
|
41
|
+
--background: var(--red-950);
|
|
42
|
+
--icon: var(--red-250);
|
|
43
|
+
--text: var(--red-150);
|
|
44
|
+
--border: var(--red-500);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.icon {
|
|
48
|
+
--icon-size: 18px;
|
|
49
|
+
color: var(--icon);
|
|
50
|
+
margin: 0;
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.content {
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
color: var(--text);
|
|
60
|
+
font-size: var(--font-size-small);
|
|
61
|
+
font-weight: 400;
|
|
62
|
+
height: 100%;
|
|
63
|
+
|
|
64
|
+
/* Inline code in the alert uses the colors of the level */
|
|
65
|
+
--code-color: var(--text);
|
|
66
|
+
--code-border: color-mix(in srgb, var(--border) 40%, transparent);
|
|
67
|
+
--code-background: color-mix(in srgb, var(--border) 20%, transparent);
|
|
68
|
+
|
|
69
|
+
.heading {
|
|
70
|
+
font-weight: 500;
|
|
71
|
+
margin: 0;
|
|
72
|
+
line-height: 1.2;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* The list of items, each with a dot in the color of its level */
|
|
77
|
+
.items {
|
|
78
|
+
display: grid;
|
|
79
|
+
gap: var(--space-50);
|
|
80
|
+
margin: 0.5em 0 0;
|
|
81
|
+
padding: 0;
|
|
82
|
+
list-style: none;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.item {
|
|
86
|
+
display: flex;
|
|
87
|
+
gap: var(--space-200);
|
|
88
|
+
|
|
89
|
+
&::before {
|
|
90
|
+
flex: none;
|
|
91
|
+
width: 6px;
|
|
92
|
+
height: 6px;
|
|
93
|
+
margin-top: 0.6em;
|
|
94
|
+
content: "";
|
|
95
|
+
border-radius: 50%;
|
|
96
|
+
background: currentColor;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
&.error::before {
|
|
100
|
+
background: var(--red-400);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
&.warning::before {
|
|
104
|
+
background: var(--yellow-400);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
&.info::before {
|
|
108
|
+
background: var(--blue-400);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* An item with a target: a click shows the row of the problem */
|
|
113
|
+
.target {
|
|
114
|
+
padding: 0;
|
|
115
|
+
font: inherit;
|
|
116
|
+
color: inherit;
|
|
117
|
+
text-align: left;
|
|
118
|
+
cursor: pointer;
|
|
119
|
+
border: 0;
|
|
120
|
+
background: none;
|
|
121
|
+
|
|
122
|
+
&:hover {
|
|
123
|
+
text-decoration: underline;
|
|
124
|
+
text-underline-offset: 2px;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { html, LitElement, nothing, unsafeCSS } from "lit"
|
|
2
|
+
import type { TemplateResult } from "lit"
|
|
3
|
+
|
|
4
|
+
import { define } from "../../define.ts"
|
|
5
|
+
import type { Level } from "../badge/badge.ts"
|
|
6
|
+
import type { IconName } from "../icon/icon.ts"
|
|
7
|
+
import styles from "./alert.css?inline"
|
|
8
|
+
|
|
9
|
+
import "../icon/icon.ts"
|
|
10
|
+
|
|
11
|
+
const ICONS: Record<Level, IconName> = {
|
|
12
|
+
success: "seal-check",
|
|
13
|
+
info: "seal-question",
|
|
14
|
+
warning: "warning",
|
|
15
|
+
error: "warning-circle",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** An item in the list of an alert, e.g. one problem of the page. */
|
|
19
|
+
export type AlertItem = {
|
|
20
|
+
/** The level of the item gives the color of its dot. */
|
|
21
|
+
level?: Level
|
|
22
|
+
content: string | TemplateResult
|
|
23
|
+
/** Makes the item a button: a click fires a `select` event with this value. */
|
|
24
|
+
target?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A message with a level: a heading, an optional list of items, and optional content under it.
|
|
29
|
+
* A click on an item with a `target` fires a `select` event with the target as its detail.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* <astro-metadata-alert level="warning" heading="2 warnings" .items=${items}>
|
|
33
|
+
* </astro-metadata-alert>
|
|
34
|
+
*/
|
|
35
|
+
export class Alert extends LitElement {
|
|
36
|
+
static properties = {
|
|
37
|
+
level: { reflect: true },
|
|
38
|
+
heading: {},
|
|
39
|
+
items: { attribute: false },
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static styles = unsafeCSS(styles)
|
|
43
|
+
|
|
44
|
+
declare level: Level
|
|
45
|
+
declare heading: string
|
|
46
|
+
declare items: AlertItem[]
|
|
47
|
+
|
|
48
|
+
constructor() {
|
|
49
|
+
super()
|
|
50
|
+
this.level = "info"
|
|
51
|
+
this.heading = ""
|
|
52
|
+
this.items = []
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
select(target: string): void {
|
|
56
|
+
this.dispatchEvent(new CustomEvent("select", { detail: target }))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
renderContent(item: AlertItem) {
|
|
60
|
+
if (!item.target) return html`<span>${item.content}</span>`
|
|
61
|
+
|
|
62
|
+
const target = item.target
|
|
63
|
+
return html`
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
class="target"
|
|
67
|
+
@click=${() => {
|
|
68
|
+
this.select(target)
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
${item.content}
|
|
72
|
+
</button>
|
|
73
|
+
`
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
renderItems() {
|
|
77
|
+
if (this.items.length === 0) return nothing
|
|
78
|
+
|
|
79
|
+
return html`
|
|
80
|
+
<ul class="items">
|
|
81
|
+
${this.items.map((item) => {
|
|
82
|
+
return html`<li class="item ${item.level ?? ""}">${this.renderContent(item)}</li>`
|
|
83
|
+
})}
|
|
84
|
+
</ul>
|
|
85
|
+
`
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
render() {
|
|
89
|
+
return html`
|
|
90
|
+
<div class="icon">
|
|
91
|
+
<astro-metadata-icon name=${ICONS[this.level]}></astro-metadata-icon>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="content">
|
|
94
|
+
<p class="heading">${this.heading}</p>
|
|
95
|
+
${this.renderItems()}
|
|
96
|
+
<slot></slot>
|
|
97
|
+
</div>
|
|
98
|
+
`
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
define("astro-metadata-alert", Alert)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
height: 20px;
|
|
7
|
+
min-width: 20px;
|
|
8
|
+
padding: 0 var(--space-150);
|
|
9
|
+
font-family: var(--font-mono);
|
|
10
|
+
font-size: var(--font-size-tiny);
|
|
11
|
+
line-height: 1;
|
|
12
|
+
color: var(--zinc-300);
|
|
13
|
+
border: 1px solid var(--zinc-800);
|
|
14
|
+
border-radius: 999px;
|
|
15
|
+
background: var(--zinc-900);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* The levels use the same colors as the alert */
|
|
19
|
+
:host([level="error"]) {
|
|
20
|
+
color: var(--red-150);
|
|
21
|
+
border-color: var(--red-500);
|
|
22
|
+
background: var(--red-950);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
:host([level="info"]) {
|
|
26
|
+
color: var(--blue-50);
|
|
27
|
+
border-color: var(--blue-350);
|
|
28
|
+
background: color-mix(in srgb, var(--blue-350) 15%, transparent);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
:host([level="warning"]) {
|
|
32
|
+
color: var(--yellow-150);
|
|
33
|
+
border-color: var(--yellow-500);
|
|
34
|
+
background: color-mix(in srgb, var(--yellow-350) 10%, transparent);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
:host([level="success"]) {
|
|
38
|
+
color: var(--green-50);
|
|
39
|
+
border-color: var(--green-350);
|
|
40
|
+
background: color-mix(in srgb, var(--green-350) 15%, transparent);
|
|
41
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { html, LitElement, unsafeCSS } from "lit"
|
|
2
|
+
|
|
3
|
+
import { define } from "../../define.ts"
|
|
4
|
+
import styles from "./badge.css?inline"
|
|
5
|
+
|
|
6
|
+
export type Level = "success" | "info" | "warning" | "error"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A small rounded label, e.g. the number of problems. `level` sets the colors.
|
|
10
|
+
*
|
|
11
|
+
* @example <astro-metadata-badge level="warning">2</astro-metadata-badge>
|
|
12
|
+
*/
|
|
13
|
+
export class Badge extends LitElement {
|
|
14
|
+
static properties = { level: { reflect: true } }
|
|
15
|
+
static styles = unsafeCSS(styles)
|
|
16
|
+
|
|
17
|
+
declare level: Level | undefined
|
|
18
|
+
|
|
19
|
+
render() {
|
|
20
|
+
return html`<slot></slot>`
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
define("astro-metadata-badge", Badge)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.block {
|
|
6
|
+
position: relative;
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
border: 1px solid var(--zinc-800);
|
|
9
|
+
border-radius: var(--radius);
|
|
10
|
+
background: var(--zinc-950);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.toolbar {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: space-between;
|
|
17
|
+
padding: var(--space-100) var(--space-100) var(--space-100) var(--space-300);
|
|
18
|
+
font-size: var(--font-size-small);
|
|
19
|
+
color: var(--zinc-400);
|
|
20
|
+
border-bottom: 1px solid var(--zinc-800);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
button {
|
|
24
|
+
display: grid;
|
|
25
|
+
place-items: center;
|
|
26
|
+
width: 26px;
|
|
27
|
+
height: 26px;
|
|
28
|
+
color: inherit;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
background: none;
|
|
31
|
+
border: 0;
|
|
32
|
+
border-radius: var(--radius-small);
|
|
33
|
+
|
|
34
|
+
&:hover {
|
|
35
|
+
color: var(--zinc-100);
|
|
36
|
+
background: var(--zinc-800);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
pre {
|
|
41
|
+
margin: 0;
|
|
42
|
+
padding: var(--space-300);
|
|
43
|
+
overflow: auto;
|
|
44
|
+
font-family: var(--font-mono);
|
|
45
|
+
font-size: var(--font-size-small);
|
|
46
|
+
line-height: 1.6;
|
|
47
|
+
counter-reset: line;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* One block for each line: CSS counters number the lines, so a copy has no numbers */
|
|
51
|
+
.line {
|
|
52
|
+
display: block;
|
|
53
|
+
min-height: 1lh;
|
|
54
|
+
|
|
55
|
+
&::before {
|
|
56
|
+
display: inline-block;
|
|
57
|
+
width: 2.5em;
|
|
58
|
+
margin-right: var(--space-300);
|
|
59
|
+
color: var(--zinc-400);
|
|
60
|
+
text-align: right;
|
|
61
|
+
content: counter(line);
|
|
62
|
+
counter-increment: line;
|
|
63
|
+
user-select: none;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.token {
|
|
68
|
+
&.key,
|
|
69
|
+
&.attribute {
|
|
70
|
+
color: var(--blue-300);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&.string,
|
|
74
|
+
&.value {
|
|
75
|
+
color: var(--green-300);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
&.number,
|
|
79
|
+
&.keyword {
|
|
80
|
+
color: var(--red-300);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
&.tag {
|
|
84
|
+
color: var(--orange-300);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&.punctuation {
|
|
88
|
+
color: var(--zinc-400);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { html, LitElement, unsafeCSS } from "lit"
|
|
2
|
+
import { unsafeHTML } from "lit/directives/unsafe-html.js"
|
|
3
|
+
|
|
4
|
+
import { define } from "../../define.ts"
|
|
5
|
+
import { highlight } from "../../highlight.ts"
|
|
6
|
+
import type { Language } from "../../highlight.ts"
|
|
7
|
+
import styles from "./code-block.css?inline"
|
|
8
|
+
|
|
9
|
+
import "../icon/icon.ts"
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A code block with line numbers, highlighting and a copy button.
|
|
13
|
+
*
|
|
14
|
+
* @example <astro-metadata-code .code=${json} language="json" label="WebSite"></astro-metadata-code>
|
|
15
|
+
*/
|
|
16
|
+
export class CodeBlock extends LitElement {
|
|
17
|
+
static properties = {
|
|
18
|
+
code: {},
|
|
19
|
+
language: {},
|
|
20
|
+
label: {},
|
|
21
|
+
copied: { state: true },
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static styles = unsafeCSS(styles)
|
|
25
|
+
|
|
26
|
+
declare code: string
|
|
27
|
+
declare language: Language
|
|
28
|
+
declare label: string | undefined
|
|
29
|
+
declare copied: boolean
|
|
30
|
+
|
|
31
|
+
constructor() {
|
|
32
|
+
super()
|
|
33
|
+
this.code = ""
|
|
34
|
+
this.language = "html"
|
|
35
|
+
this.label = undefined
|
|
36
|
+
this.copied = false
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async copy(): Promise<void> {
|
|
40
|
+
await navigator.clipboard.writeText(this.code)
|
|
41
|
+
this.copied = true
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
this.copied = false
|
|
44
|
+
}, 1500)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
render() {
|
|
48
|
+
const lines = highlight(this.code, this.language).split("\n")
|
|
49
|
+
const code = lines.map((line) => {
|
|
50
|
+
return html`<span class="line">${unsafeHTML(line)}</span>`
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
// No spaces inside <pre>: the template text would show in the code
|
|
54
|
+
return html`
|
|
55
|
+
<div class="block">
|
|
56
|
+
<div class="toolbar">
|
|
57
|
+
<span>${this.label ?? this.language.toUpperCase()}</span>
|
|
58
|
+
<button @click=${this.copy} aria-label="Copy the code">
|
|
59
|
+
<astro-metadata-icon name=${this.copied ? "check" : "copy"}></astro-metadata-icon>
|
|
60
|
+
</button>
|
|
61
|
+
</div>
|
|
62
|
+
<pre><code>${code}</code></pre>
|
|
63
|
+
</div>
|
|
64
|
+
`
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
define("astro-metadata-code", CodeBlock)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
gap: var(--space-100);
|
|
5
|
+
margin-right: var(--space-300);
|
|
6
|
+
font-family: var(--font-mono);
|
|
7
|
+
font-size: var(--font-size-small);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.color {
|
|
11
|
+
width: 12px;
|
|
12
|
+
height: 12px;
|
|
13
|
+
border: 1px solid var(--zinc-700);
|
|
14
|
+
border-radius: 3px;
|
|
15
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { html, LitElement, unsafeCSS } from "lit"
|
|
2
|
+
import { styleMap } from "lit/directives/style-map.js"
|
|
3
|
+
|
|
4
|
+
import { define } from "../../define.ts"
|
|
5
|
+
import styles from "./color-swatch.css?inline"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A small square of a color, and the color value.
|
|
9
|
+
*
|
|
10
|
+
* @example <astro-metadata-color-swatch color="#6366f1"></astro-metadata-color-swatch>
|
|
11
|
+
*/
|
|
12
|
+
export class ColorSwatch extends LitElement {
|
|
13
|
+
static properties = { color: {} }
|
|
14
|
+
static styles = unsafeCSS(styles)
|
|
15
|
+
|
|
16
|
+
declare color: string
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
super()
|
|
20
|
+
this.color = ""
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
render() {
|
|
24
|
+
return html`
|
|
25
|
+
<span class="color" style=${styleMap({ background: this.color })}></span>
|
|
26
|
+
${this.color}
|
|
27
|
+
`
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
define("astro-metadata-color-swatch", ColorSwatch)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { html, LitElement, nothing, unsafeCSS } from "lit"
|
|
2
|
+
import { unsafeSVG } from "lit/directives/unsafe-svg.js"
|
|
3
|
+
|
|
4
|
+
import caretRight from "../../../assets/icons/caret-right.svg?raw"
|
|
5
|
+
import check from "../../../assets/icons/check.svg?raw"
|
|
6
|
+
import copy from "../../../assets/icons/copy.svg?raw"
|
|
7
|
+
import sealCheck from "../../../assets/icons/seal-check-duotone.svg?raw"
|
|
8
|
+
import sealQuestion from "../../../assets/icons/seal-question-duotone.svg?raw"
|
|
9
|
+
import warningCircle from "../../../assets/icons/warning-circle-duotone.svg?raw"
|
|
10
|
+
import warning from "../../../assets/icons/warning-duotone.svg?raw"
|
|
11
|
+
import close from "../../../assets/icons/x.svg?raw"
|
|
12
|
+
import { define } from "../../define.ts"
|
|
13
|
+
import styles from "./icon.css?inline"
|
|
14
|
+
|
|
15
|
+
// All icons of the panel. Add a new icon to src/assets/icons/ and to this list.
|
|
16
|
+
const ICONS = {
|
|
17
|
+
"caret-right": caretRight,
|
|
18
|
+
check,
|
|
19
|
+
close,
|
|
20
|
+
copy,
|
|
21
|
+
"seal-check": sealCheck,
|
|
22
|
+
"seal-question": sealQuestion,
|
|
23
|
+
warning,
|
|
24
|
+
"warning-circle": warningCircle,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type IconName = keyof typeof ICONS
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* An icon from `src/assets/icons/`. The color is `currentColor`, and `--icon-size` sets the size.
|
|
31
|
+
*
|
|
32
|
+
* @example <astro-metadata-icon name="close"></astro-metadata-icon>
|
|
33
|
+
*/
|
|
34
|
+
export class Icon extends LitElement {
|
|
35
|
+
static properties = { name: {} }
|
|
36
|
+
static styles = unsafeCSS(styles)
|
|
37
|
+
|
|
38
|
+
declare name: IconName | undefined
|
|
39
|
+
|
|
40
|
+
render() {
|
|
41
|
+
const svg = this.name ? ICONS[this.name] : undefined
|
|
42
|
+
return svg ? html`${unsafeSVG(svg)}` : nothing
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
define("astro-metadata-icon", Icon)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/* The view sets the size, the radius and the colors of the image */
|
|
2
|
+
:host {
|
|
3
|
+
display: block;
|
|
4
|
+
overflow: hidden;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
img {
|
|
8
|
+
display: block;
|
|
9
|
+
width: 100%;
|
|
10
|
+
height: 100%;
|
|
11
|
+
object-fit: cover;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.message {
|
|
15
|
+
display: grid;
|
|
16
|
+
place-items: center;
|
|
17
|
+
height: 100%;
|
|
18
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { html, LitElement, unsafeCSS } from "lit"
|
|
2
|
+
|
|
3
|
+
import { define } from "../../define.ts"
|
|
4
|
+
import styles from "./image.css?inline"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* An image that shows a message when it does not load. The social images use the `site`
|
|
8
|
+
* of the Astro config, so in dev they often do not exist yet: then the image loads
|
|
9
|
+
* from the dev server. The `missing` attribute shows when the image does not load.
|
|
10
|
+
*
|
|
11
|
+
* @example <astro-metadata-image src=${url}></astro-metadata-image>
|
|
12
|
+
*/
|
|
13
|
+
export class Image extends LitElement {
|
|
14
|
+
static properties = {
|
|
15
|
+
src: {},
|
|
16
|
+
missing: { type: Boolean, reflect: true },
|
|
17
|
+
current: { state: true },
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static styles = unsafeCSS(styles)
|
|
21
|
+
|
|
22
|
+
declare src: string | undefined
|
|
23
|
+
declare missing: boolean
|
|
24
|
+
/** The URL that the image loads now: `src`, or the same path on the dev server. */
|
|
25
|
+
declare current: string | undefined
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
super()
|
|
29
|
+
this.src = undefined
|
|
30
|
+
this.missing = false
|
|
31
|
+
this.current = undefined
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
willUpdate(changed: Map<string, unknown>): void {
|
|
35
|
+
if (changed.has("src")) {
|
|
36
|
+
this.current = this.src
|
|
37
|
+
this.missing = !this.src
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
onError(): void {
|
|
42
|
+
const url = new URL(this.current ?? "", location.href)
|
|
43
|
+
if (url.origin !== location.origin) {
|
|
44
|
+
this.current = `${location.origin}${url.pathname}${url.search}`
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
this.missing = true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
render() {
|
|
51
|
+
if (this.missing) {
|
|
52
|
+
return html`<span class="message">${this.src ? "The image does not load" : "No image"}</span>`
|
|
53
|
+
}
|
|
54
|
+
return html`<img src=${this.current ?? ""} alt="" @error=${this.onError} />`
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
define("astro-metadata-image", Image)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The look of backticks in Markdown: a small monospace label on a zinc background.
|
|
3
|
+
* A parent can change the colors with --code-color, --code-border and --code-background,
|
|
4
|
+
* e.g. the alert uses the colors of its level.
|
|
5
|
+
*/
|
|
6
|
+
:host {
|
|
7
|
+
display: inline;
|
|
8
|
+
padding: 0 var(--space-100);
|
|
9
|
+
font-family: var(--font-mono);
|
|
10
|
+
font-size: 0.9em;
|
|
11
|
+
color: var(--code-color, var(--zinc-200));
|
|
12
|
+
white-space: nowrap;
|
|
13
|
+
border: 1px solid var(--code-border, var(--zinc-700));
|
|
14
|
+
border-radius: var(--radius-small);
|
|
15
|
+
background: var(--code-background, var(--zinc-800));
|
|
16
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { html, LitElement, unsafeCSS } from "lit"
|
|
2
|
+
|
|
3
|
+
import { define } from "../../define.ts"
|
|
4
|
+
import styles from "./inline-code.css?inline"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A code word in a text, e.g. a tag name or a value.
|
|
8
|
+
*
|
|
9
|
+
* @example <astro-metadata-inline-code>og:image</astro-metadata-inline-code>
|
|
10
|
+
*/
|
|
11
|
+
export class InlineCode extends LitElement {
|
|
12
|
+
static styles = unsafeCSS(styles)
|
|
13
|
+
|
|
14
|
+
render() {
|
|
15
|
+
return html`<slot></slot>`
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
define("astro-metadata-inline-code", InlineCode)
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Returns a text with each part between backticks as inline code.
|
|
23
|
+
*
|
|
24
|
+
* @example withCode("The `og:image` has no width.")
|
|
25
|
+
*/
|
|
26
|
+
export function withCode(text: string) {
|
|
27
|
+
const parts = text.split(/`([^`]+)`/)
|
|
28
|
+
return html`${parts.map((part, index) => {
|
|
29
|
+
// The odd parts are the parts between the backticks
|
|
30
|
+
return index % 2 === 1
|
|
31
|
+
? html`<astro-metadata-inline-code>${part}</astro-metadata-inline-code>`
|
|
32
|
+
: part
|
|
33
|
+
})}`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns a value as inline code, or undefined for an empty value.
|
|
38
|
+
*/
|
|
39
|
+
export function code(value: string | undefined) {
|
|
40
|
+
return value ? html`<astro-metadata-inline-code>${value}</astro-metadata-inline-code>` : undefined
|
|
41
|
+
}
|