@astronox/core 0.2.4 → 0.3.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 +16 -1
- package/package.json +18 -4
- package/src/admin/authController.ts +166 -0
- package/src/admin/cache.ts +44 -17
- package/src/admin/index.ts +3 -0
- package/src/admin/preparedDestination.ts +114 -0
- package/src/admin/resourceClient.ts +107 -0
- package/src/ads/adsense/index.ts +1 -0
- package/src/ads/adsense.ts +112 -0
- package/src/ads/contracts.ts +11 -0
- package/src/ads/index.ts +2 -0
- package/src/ads/slot.ts +16 -0
- package/src/auth/contracts.ts +1 -4
- package/src/auth/firebase/client.ts +19 -6
- package/src/auth/firebase/index.ts +1 -0
- package/src/client/formSubmission.ts +6 -1
- package/src/client/preferences.ts +8 -4
- package/src/components/actions/Button/Button.astro +30 -42
- package/src/components/actions/CardAction/CardAction.astro +7 -0
- package/src/components/actions/CardAction/CardAction.css +31 -10
- package/src/components/actions/IdentityProviderAction/IdentityProviderAction.astro +6 -8
- package/src/components/actions/MediaTrigger/MediaTrigger.astro +1 -1
- package/src/components/actions/ScrollToTop/ScrollToTop.astro +2 -1
- package/src/components/actions/ScrollToTop/ScrollToTop.css +2 -6
- package/src/components/actions/ThemeToggle/ThemeToggle.astro +3 -3
- package/src/components/actions/ThemeToggle/themeToggleController.ts +7 -4
- package/src/components/content/CardFooter/CardFooter.css +2 -4
- package/src/components/content/CardHeader/CardHeader.astro +1 -4
- package/src/components/content/CardLink/CardLink.astro +3 -15
- package/src/components/content/CardLink/CardLink.css +4 -15
- package/src/components/content/CodeBlock/CodeBlock.astro +7 -6
- package/src/components/content/CodeBlock/CodeBlock.css +2 -5
- package/src/components/content/CodeBlock/codeBlockController.ts +1 -2
- package/src/components/content/MarkdownContent/MarkdownContent.astro +1 -3
- package/src/components/content/MarkdownContent/MarkdownContent.css +7 -2
- package/src/components/content/MarkdownContent/MarkdownInline.astro +11 -3
- package/src/components/content/MarkdownContent/MarkdownNode.astro +28 -33
- package/src/components/content/MarkdownContent/MarkdownSymbol.astro +30 -19
- package/src/components/content/MarkdownContent/contracts.ts +15 -15
- package/src/components/content/MarkdownContent/markdownContentRenderer.ts +27 -83
- package/src/components/feedback/PreferenceBootstrap/PreferenceBootstrap.astro +19 -22
- package/src/components/feedback/Spinner/Spinner.astro +1 -2
- package/src/components/feedback/Tooltip/tooltipController.ts +1 -4
- package/src/components/forms/ChoiceGroup/ChoiceGroup.css +1 -4
- package/src/components/forms/DateTimeInput/DateTimeInput.astro +2 -1
- package/src/components/forms/PreparedFormBootstrap/PreparedFormBootstrap.astro +10 -8
- package/src/components/forms/PreparedFormBootstrap/parsePreparedFormState.ts +48 -0
- package/src/components/forms/Textarea/Textarea.astro +2 -2
- package/src/components/icons/BurnIcon.astro +2 -1
- package/src/components/icons/FieldIcon.astro +10 -4
- package/src/components/icons/GrassIcon.astro +3 -2
- package/src/components/icons/SlowIcon.astro +1 -2
- package/src/components/icons/StunIcon.astro +2 -1
- package/src/components/icons/WaterIcon.astro +3 -2
- package/src/components/index.ts +2 -0
- package/src/components/media/CanvasFrame/CanvasFrame.astro +1 -2
- package/src/components/media/CanvasFrame/canvasFrameController.ts +1 -4
- package/src/components/media/EmbedFrame/EmbedFrame.astro +5 -12
- package/src/components/media/EmbedFrame/embedFrameController.ts +4 -4
- package/src/components/monetization/AdSlot/AdSlot.astro +33 -0
- package/src/components/monetization/AdSlot/AdSlot.css +53 -0
- package/src/components/navigation/DesktopNavigation.css +1 -2
- package/src/components/navigation/Footer/Footer.css +3 -9
- package/src/components/navigation/MobileNavigation.astro +10 -2
- package/src/components/navigation/MobileNavigation.css +8 -22
- package/src/components/navigation/navigationTypes.ts +1 -4
- package/src/components/seo/SeoHead.astro +21 -6
- package/src/composition/SurfaceGroup/SurfaceGroup.css +4 -14
- package/src/config/environment.ts +52 -0
- package/src/config/index.ts +3 -0
- package/src/config/integrations.ts +9 -0
- package/src/config/siteConfig.ts +7 -0
- package/src/config/storage.ts +16 -0
- package/src/content/admin.ts +354 -0
- package/src/content/cache.ts +177 -0
- package/src/content/catalog.ts +72 -0
- package/src/content/contracts.ts +77 -0
- package/src/content/drafts.ts +49 -0
- package/src/content/index.ts +7 -0
- package/src/content/markdown.ts +146 -0
- package/src/content/snapshot.ts +139 -0
- package/src/data/firestore/client/contracts.ts +10 -2
- package/src/data/index.ts +1 -0
- package/src/data/memoizedLoader.ts +13 -0
- package/src/display/contracts.ts +1 -5
- package/src/i18n/config.ts +2 -8
- package/src/i18n/coreMessages.ts +2 -9
- package/src/i18n/preference.ts +2 -6
- package/src/patterns/Combobox/Combobox.astro +9 -12
- package/src/patterns/Combobox/comboboxController.ts +14 -8
- package/src/patterns/Fullscreen/FullscreenControl.astro +5 -1
- package/src/patterns/Fullscreen/fullscreenController.ts +1 -3
- package/src/patterns/MapViewport/geometry.ts +1 -4
- package/src/patterns/Modal/Modal.css +1 -4
- package/src/patterns/Modal/ModalOpen.astro +5 -1
- package/src/patterns/Table/Table.astro +10 -10
- package/src/patterns/Table/TableBody.astro +1 -4
- package/src/patterns/Table/TableBody.css +2 -4
- package/src/patterns/Table/TablePagination.astro +23 -30
- package/src/patterns/Table/TableSkeleton.astro +1 -5
- package/src/patterns/Table/tableClientController.ts +2 -2
- package/src/patterns/Table/tableFilterController.ts +1 -3
- package/src/patterns/Table/tableHeaderOverflowController.ts +1 -4
- package/src/patterns/Table/tableProgressiveController.ts +62 -60
- package/src/patterns/Table/tableScrollController.ts +3 -2
- package/src/primitives/text/TextBlock/TextBlock.astro +1 -3
- package/src/publication/contracts.ts +11 -0
- package/src/publication/http.ts +31 -0
- package/src/publication/index.ts +2 -0
- package/src/routing/localized.ts +9 -12
- package/src/seo/localizedMeta.ts +2 -6
- package/src/styles/interaction.css +14 -7
- package/src/styles/style.css +11 -20
- package/src/theme/contracts.ts +1 -6
|
@@ -154,26 +154,17 @@
|
|
|
154
154
|
);
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
.card-link:is(
|
|
158
|
-
[data-media-size='compact'],
|
|
159
|
-
[data-media-size='small']
|
|
160
|
-
)
|
|
157
|
+
.card-link:is([data-media-size='compact'], [data-media-size='small'])
|
|
161
158
|
.card-link__layout {
|
|
162
159
|
--card-link-artwork-max-size: var(--card-link-resolved-media-size);
|
|
163
160
|
}
|
|
164
161
|
|
|
165
|
-
.card-link:is(
|
|
166
|
-
[data-media-size='compact'],
|
|
167
|
-
[data-media-size='small']
|
|
168
|
-
)
|
|
162
|
+
.card-link:is([data-media-size='compact'], [data-media-size='small'])
|
|
169
163
|
.card-link__content {
|
|
170
164
|
--card-link-content-media-size: var(--card-link-resolved-media-size);
|
|
171
165
|
}
|
|
172
166
|
|
|
173
|
-
.card-link:is(
|
|
174
|
-
[data-media-size='compact'],
|
|
175
|
-
[data-media-size='small']
|
|
176
|
-
)
|
|
167
|
+
.card-link:is([data-media-size='compact'], [data-media-size='small'])
|
|
177
168
|
:is(.card-link__media, .card-link__content-media)
|
|
178
169
|
[data-widget='media'] {
|
|
179
170
|
--media-object-inline-size: 100%;
|
|
@@ -203,9 +194,7 @@
|
|
|
203
194
|
}
|
|
204
195
|
|
|
205
196
|
.card-link[data-density='relaxed'] .card-link__layout {
|
|
206
|
-
--card-link-size: calc(
|
|
207
|
-
var(--nox-navigation-block-size) + var(--nox-space-5)
|
|
208
|
-
);
|
|
197
|
+
--card-link-size: calc(var(--nox-navigation-block-size) + var(--nox-space-5));
|
|
209
198
|
}
|
|
210
199
|
|
|
211
200
|
.card-link[data-density='relaxed'] .card-link__content {
|
|
@@ -3,10 +3,7 @@ import type { HTMLAttributes } from 'astro/types';
|
|
|
3
3
|
import Button from '../../actions/Button/Button.astro';
|
|
4
4
|
import CopyIcon from '../../icons/CopyIcon.astro';
|
|
5
5
|
import type { Tone } from '../../../theme/contracts';
|
|
6
|
-
import type {
|
|
7
|
-
CodeBlockCopy,
|
|
8
|
-
CodeBlockPresentation,
|
|
9
|
-
} from './contracts';
|
|
6
|
+
import type { CodeBlockCopy, CodeBlockPresentation } from './contracts';
|
|
10
7
|
|
|
11
8
|
type Props = HTMLAttributes<'pre'> & {
|
|
12
9
|
copy?: CodeBlockCopy;
|
|
@@ -42,7 +39,9 @@ const resolvedTone = tone ?? dataTone;
|
|
|
42
39
|
data-code-block-content
|
|
43
40
|
data-code-block-presentation={presentation}
|
|
44
41
|
data-wrap={wrap ? true : undefined}
|
|
45
|
-
>
|
|
42
|
+
>
|
|
43
|
+
{text}
|
|
44
|
+
</pre>
|
|
46
45
|
<Button
|
|
47
46
|
class="code-block__copy"
|
|
48
47
|
type="button"
|
|
@@ -75,7 +74,9 @@ const resolvedTone = tone ?? dataTone;
|
|
|
75
74
|
data-code-block-presentation={presentation}
|
|
76
75
|
data-tone={resolvedTone}
|
|
77
76
|
data-wrap={wrap ? true : undefined}
|
|
78
|
-
>
|
|
77
|
+
>
|
|
78
|
+
{text}
|
|
79
|
+
</pre>
|
|
79
80
|
)
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
--code-block-light-line-height: 1.125rem;
|
|
19
19
|
--code-block-copy-size: calc(
|
|
20
20
|
var(--code-block-light-line-height) + var(--nox-space-3) +
|
|
21
|
-
var(--nox-space-3) + var(--nox-border-width) +
|
|
22
|
-
var(--nox-border-width)
|
|
21
|
+
var(--nox-space-3) + var(--nox-border-width) + var(--nox-border-width)
|
|
23
22
|
);
|
|
24
23
|
|
|
25
24
|
position: relative;
|
|
@@ -30,9 +29,7 @@
|
|
|
30
29
|
.code-block-shell .code-block {
|
|
31
30
|
box-sizing: border-box;
|
|
32
31
|
inline-size: 100%;
|
|
33
|
-
padding-inline-end: calc(
|
|
34
|
-
var(--code-block-copy-size) + var(--nox-space-3)
|
|
35
|
-
);
|
|
32
|
+
padding-inline-end: calc(var(--code-block-copy-size) + var(--nox-space-3));
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
.code-block[data-code-block-presentation='light'] {
|
|
@@ -17,8 +17,7 @@ export function initCodeBlock(root: HTMLElement): () => void {
|
|
|
17
17
|
root.setAttribute(initializedAttribute, 'true');
|
|
18
18
|
const copyLabel = copyButton.dataset.copyLabel ?? '';
|
|
19
19
|
const copiedLabel = copyButton.dataset.copiedLabel ?? copyLabel;
|
|
20
|
-
const unavailableLabel =
|
|
21
|
-
copyButton.dataset.copyUnavailableLabel ?? copyLabel;
|
|
20
|
+
const unavailableLabel = copyButton.dataset.copyUnavailableLabel ?? copyLabel;
|
|
22
21
|
let feedbackTimeout: number | undefined;
|
|
23
22
|
|
|
24
23
|
const setButtonLabel = (label: string): void => {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { HTMLAttributes } from 'astro/types';
|
|
3
|
-
import type {
|
|
4
|
-
CodeBlockCopy,
|
|
5
|
-
} from '../CodeBlock/contracts';
|
|
3
|
+
import type { CodeBlockCopy } from '../CodeBlock/contracts';
|
|
6
4
|
import MarkdownNode from './MarkdownNode.astro';
|
|
7
5
|
import type { MarkdownDocument } from './contracts';
|
|
8
6
|
|
|
@@ -163,8 +163,7 @@
|
|
|
163
163
|
gap: 0;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
.markdown-content__list-item[data-markdown-resource]
|
|
167
|
-
.markdown-content__list {
|
|
166
|
+
.markdown-content__list-item[data-markdown-resource] .markdown-content__list {
|
|
168
167
|
padding-inline-start: 0;
|
|
169
168
|
list-style: none;
|
|
170
169
|
}
|
|
@@ -268,6 +267,12 @@
|
|
|
268
267
|
block-size: 1em;
|
|
269
268
|
}
|
|
270
269
|
|
|
270
|
+
.markdown-content__symbol-media {
|
|
271
|
+
block-size: 1.5em;
|
|
272
|
+
inline-size: 1.5em;
|
|
273
|
+
object-fit: contain;
|
|
274
|
+
}
|
|
275
|
+
|
|
271
276
|
.markdown-content__symbol[data-markdown-symbol^='terrain-']
|
|
272
277
|
.markdown-content__symbol-icon {
|
|
273
278
|
inline-size: 1.25em;
|
|
@@ -20,10 +20,16 @@ const { node }: Props = Astro.props;
|
|
|
20
20
|
<MarkdownSymbol node={node} />
|
|
21
21
|
) : node.type === 'strong' ? (
|
|
22
22
|
<strong class="markdown-content__strong">
|
|
23
|
-
{node.children.map((child) =>
|
|
23
|
+
{node.children.map((child) => (
|
|
24
|
+
<Astro.self node={child} />
|
|
25
|
+
))}
|
|
24
26
|
</strong>
|
|
25
27
|
) : node.type === 'emphasis' ? (
|
|
26
|
-
<em>
|
|
28
|
+
<em>
|
|
29
|
+
{node.children.map((child) => (
|
|
30
|
+
<Astro.self node={child} />
|
|
31
|
+
))}
|
|
32
|
+
</em>
|
|
27
33
|
) : node.type === 'code' ? (
|
|
28
34
|
<code class="markdown-content__inline-code">{node.value}</code>
|
|
29
35
|
) : node.type === 'link' ? (
|
|
@@ -36,7 +42,9 @@ const { node }: Props = Astro.props;
|
|
|
36
42
|
rel={node.external ? 'noopener noreferrer' : undefined}
|
|
37
43
|
target={node.external ? '_blank' : undefined}
|
|
38
44
|
>
|
|
39
|
-
{node.children.map((child) =>
|
|
45
|
+
{node.children.map((child) => (
|
|
46
|
+
<Astro.self node={child} />
|
|
47
|
+
))}
|
|
40
48
|
</a>
|
|
41
49
|
) : (
|
|
42
50
|
<br />
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import CodeBlock from '../CodeBlock/CodeBlock.astro';
|
|
3
|
-
import type {
|
|
4
|
-
CodeBlockCopy,
|
|
5
|
-
} from '../CodeBlock/contracts';
|
|
3
|
+
import type { CodeBlockCopy } from '../CodeBlock/contracts';
|
|
6
4
|
import Media from '../../../primitives/media/Media/Media.astro';
|
|
7
5
|
import Separator from '../../../primitives/layout/Separator/Separator.astro';
|
|
8
6
|
import type { Tone } from '../../../theme/contracts';
|
|
@@ -26,14 +24,14 @@ function toHeadingTag(
|
|
|
26
24
|
return `h${level}` as 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
27
25
|
}
|
|
28
26
|
|
|
29
|
-
const defaultListMarker = {
|
|
27
|
+
const defaultListMarker: MarkdownListMarker = {
|
|
30
28
|
symbol: 'bullet',
|
|
31
29
|
tone: 'neutral',
|
|
32
|
-
}
|
|
33
|
-
const nestedListMarker = {
|
|
30
|
+
};
|
|
31
|
+
const nestedListMarker: MarkdownListMarker = {
|
|
34
32
|
symbol: 'arrow-right',
|
|
35
33
|
tone: 'neutral',
|
|
36
|
-
}
|
|
34
|
+
};
|
|
37
35
|
|
|
38
36
|
const codeBlockTones = new Set<Tone>([
|
|
39
37
|
'neutral',
|
|
@@ -77,10 +75,7 @@ const listItems =
|
|
|
77
75
|
|
|
78
76
|
{
|
|
79
77
|
node.type === 'section' ? (
|
|
80
|
-
<section
|
|
81
|
-
class="markdown-content__section"
|
|
82
|
-
aria-labelledby={node.id}
|
|
83
|
-
>
|
|
78
|
+
<section class="markdown-content__section" aria-labelledby={node.id}>
|
|
84
79
|
<HeadingTag
|
|
85
80
|
class="markdown-content__section-title"
|
|
86
81
|
data-markdown-heading-level={node.level}
|
|
@@ -89,16 +84,16 @@ const listItems =
|
|
|
89
84
|
{node.title}
|
|
90
85
|
</HeadingTag>
|
|
91
86
|
<div class="markdown-content__section-body">
|
|
92
|
-
{
|
|
93
|
-
node
|
|
94
|
-
|
|
95
|
-
))
|
|
96
|
-
}
|
|
87
|
+
{node.blocks.map((block) => (
|
|
88
|
+
<Astro.self node={block} codeBlockCopy={codeBlockCopy} />
|
|
89
|
+
))}
|
|
97
90
|
</div>
|
|
98
91
|
</section>
|
|
99
92
|
) : node.type === 'paragraph' ? (
|
|
100
93
|
<p class="markdown-content__paragraph">
|
|
101
|
-
{node.children.map((child) =>
|
|
94
|
+
{node.children.map((child) => (
|
|
95
|
+
<MarkdownInline node={child} />
|
|
96
|
+
))}
|
|
102
97
|
</p>
|
|
103
98
|
) : node.type === 'heading' ? (
|
|
104
99
|
<HeadingTag
|
|
@@ -106,17 +101,23 @@ const listItems =
|
|
|
106
101
|
data-markdown-heading-level={node.level}
|
|
107
102
|
id={node.id}
|
|
108
103
|
>
|
|
109
|
-
{node.children.map((child) =>
|
|
104
|
+
{node.children.map((child) => (
|
|
105
|
+
<MarkdownInline node={child} />
|
|
106
|
+
))}
|
|
110
107
|
</HeadingTag>
|
|
111
108
|
) : node.type === 'change' ? (
|
|
112
109
|
<div class="markdown-content__change">
|
|
113
110
|
<span class="markdown-content__change-label">
|
|
114
|
-
{node.label.map((child) =>
|
|
111
|
+
{node.label.map((child) => (
|
|
112
|
+
<MarkdownInline node={child} />
|
|
113
|
+
))}
|
|
115
114
|
<span>:</span>
|
|
116
115
|
</span>
|
|
117
116
|
{node.presentation === 'statement' ? (
|
|
118
117
|
<span class="markdown-content__change-values">
|
|
119
|
-
{node.value.map((child) =>
|
|
118
|
+
{node.value.map((child) => (
|
|
119
|
+
<MarkdownInline node={child} />
|
|
120
|
+
))}
|
|
120
121
|
</span>
|
|
121
122
|
) : (
|
|
122
123
|
<span class="markdown-content__change-values" lang={node.valueLang}>
|
|
@@ -187,9 +188,7 @@ const listItems =
|
|
|
187
188
|
media={item.resource.media}
|
|
188
189
|
size="fill"
|
|
189
190
|
upscale={
|
|
190
|
-
item.resource.mediaScale === 'compact'
|
|
191
|
-
? 'prevent'
|
|
192
|
-
: undefined
|
|
191
|
+
item.resource.mediaScale === 'compact' ? 'prevent' : undefined
|
|
193
192
|
}
|
|
194
193
|
/>
|
|
195
194
|
) : null}
|
|
@@ -242,11 +241,9 @@ const listItems =
|
|
|
242
241
|
)}
|
|
243
242
|
</div>
|
|
244
243
|
) : null}
|
|
245
|
-
{
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
))
|
|
249
|
-
}
|
|
244
|
+
{item.children.map((block) => (
|
|
245
|
+
<Astro.self node={block} codeBlockCopy={codeBlockCopy} />
|
|
246
|
+
))}
|
|
250
247
|
</div>
|
|
251
248
|
</li>
|
|
252
249
|
))}
|
|
@@ -256,11 +253,9 @@ const listItems =
|
|
|
256
253
|
class="markdown-content__quote"
|
|
257
254
|
data-tone={node.tone ?? 'neutral'}
|
|
258
255
|
>
|
|
259
|
-
{
|
|
260
|
-
node
|
|
261
|
-
|
|
262
|
-
))
|
|
263
|
-
}
|
|
256
|
+
{node.children.map((block) => (
|
|
257
|
+
<Astro.self node={block} codeBlockCopy={codeBlockCopy} />
|
|
258
|
+
))}
|
|
264
259
|
</blockquote>
|
|
265
260
|
) : node.type === 'separator' ? (
|
|
266
261
|
<Separator bleed emphasis={node.emphasis} />
|
|
@@ -5,29 +5,24 @@ import ArrowRightIcon from '../../icons/ArrowRightIcon.astro';
|
|
|
5
5
|
import ArrowUpIcon from '../../icons/ArrowUpIcon.astro';
|
|
6
6
|
import BulletIcon from '../../icons/BulletIcon.astro';
|
|
7
7
|
import EqualIcon from '../../icons/EqualIcon.astro';
|
|
8
|
-
import
|
|
9
|
-
import GrassIcon from '../../icons/GrassIcon.astro';
|
|
10
|
-
import MountainIcon from '../../icons/MountainIcon.astro';
|
|
11
|
-
import WaterIcon from '../../icons/WaterIcon.astro';
|
|
12
|
-
import type { MarkdownSymbol } from './contracts';
|
|
8
|
+
import type { MarkdownBuiltinSymbolName, MarkdownSymbol } from './contracts';
|
|
13
9
|
|
|
14
10
|
type Props = {
|
|
15
11
|
node: MarkdownSymbol;
|
|
16
12
|
};
|
|
17
13
|
|
|
18
14
|
const { node }: Props = Astro.props;
|
|
19
|
-
const
|
|
15
|
+
const icons = {
|
|
20
16
|
adjustment: ArrowUpDownIcon,
|
|
21
17
|
'arrow-right': ArrowRightIcon,
|
|
22
18
|
bullet: BulletIcon,
|
|
23
19
|
decrease: ArrowDownIcon,
|
|
24
20
|
increase: ArrowUpIcon,
|
|
25
21
|
neutral: EqualIcon,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}[node.name];
|
|
22
|
+
} satisfies Record<MarkdownBuiltinSymbolName, typeof ArrowUpDownIcon>;
|
|
23
|
+
const Icon = node.media ? null : icons[node.name as MarkdownBuiltinSymbolName];
|
|
24
|
+
if (!node.media && !Icon)
|
|
25
|
+
throw new Error(`Unknown Markdown symbol: ${node.name}`);
|
|
31
26
|
---
|
|
32
27
|
|
|
33
28
|
<span
|
|
@@ -36,12 +31,28 @@ const Icon = {
|
|
|
36
31
|
data-tone={node.tone}
|
|
37
32
|
lang={node.lang}
|
|
38
33
|
>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
34
|
+
{
|
|
35
|
+
node.media ? (
|
|
36
|
+
<img
|
|
37
|
+
class="markdown-content__symbol-media"
|
|
38
|
+
src={node.media.src}
|
|
39
|
+
alt={node.media.alt}
|
|
40
|
+
width={node.media.width}
|
|
41
|
+
height={node.media.height}
|
|
42
|
+
loading={node.media.loading ?? 'lazy'}
|
|
43
|
+
decoding={node.media.decoding ?? 'async'}
|
|
44
|
+
/>
|
|
45
|
+
) : Icon ? (
|
|
46
|
+
<Icon class="markdown-content__symbol-icon" />
|
|
47
|
+
) : null
|
|
48
|
+
}
|
|
49
|
+
{
|
|
50
|
+
node.label ? (
|
|
51
|
+
<span class="markdown-content__symbol-label">{node.label}</span>
|
|
52
|
+
) : node.accessibleLabel ? (
|
|
53
|
+
<span class="markdown-content__visually-hidden">
|
|
54
|
+
{node.accessibleLabel}
|
|
55
|
+
</span>
|
|
56
|
+
) : null
|
|
57
|
+
}
|
|
47
58
|
</span>
|
|
@@ -7,27 +7,27 @@ export type MarkdownText = {
|
|
|
7
7
|
value: string;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
export type
|
|
11
|
-
| '
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
| 'decrease'
|
|
15
|
-
| 'increase'
|
|
16
|
-
| 'neutral'
|
|
17
|
-
| 'terrain-field'
|
|
18
|
-
| 'terrain-grass'
|
|
19
|
-
| 'terrain-mountain'
|
|
20
|
-
| 'terrain-water';
|
|
21
|
-
|
|
22
|
-
export type MarkdownSymbol = {
|
|
10
|
+
export type MarkdownBuiltinSymbolName =
|
|
11
|
+
'adjustment' | 'arrow-right' | 'bullet' | 'decrease' | 'increase' | 'neutral';
|
|
12
|
+
|
|
13
|
+
type MarkdownSymbolBase = {
|
|
23
14
|
type: 'symbol';
|
|
24
15
|
accessibleLabel?: string;
|
|
25
16
|
lang?: string;
|
|
26
17
|
label?: string;
|
|
27
|
-
name: MarkdownSymbolName;
|
|
28
18
|
tone?: Tone;
|
|
29
19
|
};
|
|
30
20
|
|
|
21
|
+
export type MarkdownSymbol =
|
|
22
|
+
| (MarkdownSymbolBase & {
|
|
23
|
+
media?: never;
|
|
24
|
+
name: MarkdownBuiltinSymbolName;
|
|
25
|
+
})
|
|
26
|
+
| (MarkdownSymbolBase & {
|
|
27
|
+
media: DisplayMedia;
|
|
28
|
+
name: string;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
31
|
export type MarkdownStrong = {
|
|
32
32
|
type: 'strong';
|
|
33
33
|
children: readonly MarkdownInline[];
|
|
@@ -91,7 +91,7 @@ export type MarkdownListMarker = {
|
|
|
91
91
|
lang?: string;
|
|
92
92
|
label?: string;
|
|
93
93
|
symbol: Extract<
|
|
94
|
-
|
|
94
|
+
MarkdownBuiltinSymbolName,
|
|
95
95
|
| 'adjustment'
|
|
96
96
|
| 'arrow-right'
|
|
97
97
|
| 'bullet'
|
|
@@ -24,14 +24,14 @@ const codeBlockTones = new Set<Tone>([
|
|
|
24
24
|
'warning',
|
|
25
25
|
'danger',
|
|
26
26
|
]);
|
|
27
|
-
const defaultListMarker = {
|
|
27
|
+
const defaultListMarker: MarkdownListMarker = {
|
|
28
28
|
symbol: 'bullet',
|
|
29
29
|
tone: 'neutral',
|
|
30
|
-
}
|
|
31
|
-
const nestedListMarker = {
|
|
30
|
+
};
|
|
31
|
+
const nestedListMarker: MarkdownListMarker = {
|
|
32
32
|
symbol: 'arrow-right',
|
|
33
33
|
tone: 'neutral',
|
|
34
|
-
}
|
|
34
|
+
};
|
|
35
35
|
|
|
36
36
|
export function renderMarkdownDocument(
|
|
37
37
|
root: HTMLElement,
|
|
@@ -103,10 +103,7 @@ function renderNode(
|
|
|
103
103
|
document.createTextNode(node.after),
|
|
104
104
|
);
|
|
105
105
|
if (node.delta) {
|
|
106
|
-
const delta = createElement(
|
|
107
|
-
'span',
|
|
108
|
-
'markdown-content__change-delta',
|
|
109
|
-
);
|
|
106
|
+
const delta = createElement('span', 'markdown-content__change-delta');
|
|
110
107
|
delta.dataset.tone = node.delta.tone;
|
|
111
108
|
delta.append('(');
|
|
112
109
|
if (node.delta.sign !== 'neutral') {
|
|
@@ -125,10 +122,7 @@ function renderNode(
|
|
|
125
122
|
}
|
|
126
123
|
values.append(transition);
|
|
127
124
|
if (node.suffix?.length) {
|
|
128
|
-
const suffix = createElement(
|
|
129
|
-
'span',
|
|
130
|
-
'markdown-content__change-suffix',
|
|
131
|
-
);
|
|
125
|
+
const suffix = createElement('span', 'markdown-content__change-suffix');
|
|
132
126
|
appendInline(suffix, node.suffix);
|
|
133
127
|
values.append(suffix);
|
|
134
128
|
}
|
|
@@ -216,10 +210,7 @@ function renderListItem(
|
|
|
216
210
|
appendInline(heading, item.heading);
|
|
217
211
|
body.append(heading);
|
|
218
212
|
} else if (item.resource) {
|
|
219
|
-
const heading = createElement(
|
|
220
|
-
'div',
|
|
221
|
-
'markdown-content__resource-heading',
|
|
222
|
-
);
|
|
213
|
+
const heading = createElement('div', 'markdown-content__resource-heading');
|
|
223
214
|
if (item.resource.mediaPlacement === 'inline') {
|
|
224
215
|
heading.append(
|
|
225
216
|
renderMedia(
|
|
@@ -295,24 +286,35 @@ function renderSymbol(node: MarkdownSymbol): HTMLSpanElement {
|
|
|
295
286
|
symbol.dataset.markdownSymbol = node.name;
|
|
296
287
|
if (node.tone) symbol.dataset.tone = node.tone;
|
|
297
288
|
if (node.lang) symbol.lang = node.lang;
|
|
298
|
-
symbol.append(createSymbolIcon(node
|
|
289
|
+
symbol.append(createSymbolIcon(node));
|
|
299
290
|
|
|
300
291
|
if (node.label) {
|
|
301
292
|
const label = createElement('span', 'markdown-content__symbol-label');
|
|
302
293
|
label.textContent = node.label;
|
|
303
294
|
symbol.append(label);
|
|
304
295
|
} else if (node.accessibleLabel) {
|
|
305
|
-
const label = createElement(
|
|
306
|
-
'span',
|
|
307
|
-
'markdown-content__visually-hidden',
|
|
308
|
-
);
|
|
296
|
+
const label = createElement('span', 'markdown-content__visually-hidden');
|
|
309
297
|
label.textContent = node.accessibleLabel;
|
|
310
298
|
symbol.append(label);
|
|
311
299
|
}
|
|
312
300
|
return symbol;
|
|
313
301
|
}
|
|
314
302
|
|
|
315
|
-
function createSymbolIcon(
|
|
303
|
+
function createSymbolIcon(
|
|
304
|
+
node: MarkdownSymbol,
|
|
305
|
+
): SVGSVGElement | HTMLImageElement {
|
|
306
|
+
if (node.media) {
|
|
307
|
+
const image = document.createElement('img');
|
|
308
|
+
image.classList.add('markdown-content__symbol-media');
|
|
309
|
+
image.src = node.media.src;
|
|
310
|
+
image.alt = node.media.alt;
|
|
311
|
+
image.width = node.media.width;
|
|
312
|
+
image.height = node.media.height;
|
|
313
|
+
image.loading = node.media.loading ?? 'lazy';
|
|
314
|
+
image.decoding = node.media.decoding ?? 'async';
|
|
315
|
+
return image;
|
|
316
|
+
}
|
|
317
|
+
const name = node.name;
|
|
316
318
|
const svg = document.createElementNS(svgNamespace, 'svg');
|
|
317
319
|
svg.setAttribute('viewBox', '0 0 32 32');
|
|
318
320
|
svg.setAttribute('fill', 'none');
|
|
@@ -320,13 +322,6 @@ function createSymbolIcon(name: MarkdownSymbol['name']): SVGSVGElement {
|
|
|
320
322
|
svg.setAttribute('focusable', 'false');
|
|
321
323
|
svg.classList.add('markdown-content__symbol-icon');
|
|
322
324
|
|
|
323
|
-
if (name.startsWith('terrain-')) {
|
|
324
|
-
svg.classList.add('circle-symbol-icon');
|
|
325
|
-
svg.dataset.terrainIcon = name.slice('terrain-'.length);
|
|
326
|
-
appendTerrainIcon(svg, name);
|
|
327
|
-
return svg;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
325
|
if (name === 'bullet') {
|
|
331
326
|
const circle = document.createElementNS(svgNamespace, 'circle');
|
|
332
327
|
circle.setAttribute('cx', '16');
|
|
@@ -358,55 +353,6 @@ function createSymbolIcon(name: MarkdownSymbol['name']): SVGSVGElement {
|
|
|
358
353
|
return svg;
|
|
359
354
|
}
|
|
360
355
|
|
|
361
|
-
function appendTerrainIcon(
|
|
362
|
-
svg: SVGSVGElement,
|
|
363
|
-
name: Extract<MarkdownSymbol['name'], `terrain-${string}`>,
|
|
364
|
-
): void {
|
|
365
|
-
const surface = document.createElementNS(svgNamespace, 'circle');
|
|
366
|
-
surface.setAttribute('cx', '16');
|
|
367
|
-
surface.setAttribute('cy', '16');
|
|
368
|
-
surface.setAttribute('r', '13');
|
|
369
|
-
surface.classList.add('circle-symbol-icon__surface');
|
|
370
|
-
svg.append(surface);
|
|
371
|
-
|
|
372
|
-
if (name === 'terrain-field') {
|
|
373
|
-
const rectangle = document.createElementNS(svgNamespace, 'rect');
|
|
374
|
-
rectangle.setAttribute('x', '9');
|
|
375
|
-
rectangle.setAttribute('y', '9');
|
|
376
|
-
rectangle.setAttribute('width', '14');
|
|
377
|
-
rectangle.setAttribute('height', '14');
|
|
378
|
-
rectangle.setAttribute('rx', '1');
|
|
379
|
-
rectangle.classList.add('circle-symbol-icon__mark');
|
|
380
|
-
const grid = document.createElementNS(svgNamespace, 'path');
|
|
381
|
-
grid.setAttribute('d', 'M13.7 9v14m4.6-14v14M9 13.7h14M9 18.3h14');
|
|
382
|
-
grid.classList.add('circle-symbol-icon__mark');
|
|
383
|
-
svg.append(rectangle, grid);
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
const fill = document.createElementNS(svgNamespace, 'path');
|
|
388
|
-
fill.classList.add('circle-symbol-icon__fill');
|
|
389
|
-
fill.setAttribute(
|
|
390
|
-
'd',
|
|
391
|
-
name === 'terrain-grass'
|
|
392
|
-
? 'M23.5 8.5c.2 8.4-3.7 14-11.7 15.2-3.1-6.8.2-13.5 11.7-15.2Z'
|
|
393
|
-
: name === 'terrain-water'
|
|
394
|
-
? 'M16 5.5c3.1 4.2 7.5 9 7.5 13.3A7.5 7.5 0 1 1 8.5 18.8C8.5 14.5 12.9 9.7 16 5.5Z'
|
|
395
|
-
: 'm5.5 24 7.3-13 3.1 5.1 3.4-7.1 7.2 15H5.5Z',
|
|
396
|
-
);
|
|
397
|
-
const highlight = document.createElementNS(svgNamespace, 'path');
|
|
398
|
-
highlight.classList.add('circle-symbol-icon__highlight');
|
|
399
|
-
highlight.setAttribute(
|
|
400
|
-
'd',
|
|
401
|
-
name === 'terrain-grass'
|
|
402
|
-
? 'M10.4 23.5c2.2-5.3 5.4-8.7 10.2-11.6'
|
|
403
|
-
: name === 'terrain-water'
|
|
404
|
-
? 'M12.2 19.2a4.5 4.5 0 0 0 4.5 4.1'
|
|
405
|
-
: 'm10.8 14.6 2-3.6 3.1 5.1 1.4-2.9 2.4 3.6-3.5-1.1-2.5 2.1-2.9-3.2Z',
|
|
406
|
-
);
|
|
407
|
-
svg.append(fill, highlight);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
356
|
function renderMedia(
|
|
411
357
|
media: DisplayMedia,
|
|
412
358
|
className: string,
|
|
@@ -476,7 +422,8 @@ function renderCodeBlock(
|
|
|
476
422
|
return content;
|
|
477
423
|
}
|
|
478
424
|
|
|
479
|
-
const shell = createElement('nox-code-block'
|
|
425
|
+
const shell = document.createElement('nox-code-block');
|
|
426
|
+
shell.className = 'code-block-shell';
|
|
480
427
|
shell.dataset.widget = 'code-block';
|
|
481
428
|
shell.dataset.tone = tone;
|
|
482
429
|
content.dataset.codeBlockContent = '';
|
|
@@ -530,10 +477,7 @@ function createCopyIcon(): SVGSVGElement {
|
|
|
530
477
|
return svg;
|
|
531
478
|
}
|
|
532
479
|
|
|
533
|
-
function createHeading(
|
|
534
|
-
level: number,
|
|
535
|
-
className: string,
|
|
536
|
-
): HTMLHeadingElement {
|
|
480
|
+
function createHeading(level: number, className: string): HTMLHeadingElement {
|
|
537
481
|
const heading = createElement(
|
|
538
482
|
`h${Math.min(6, Math.max(2, level))}` as keyof HTMLElementTagNameMap,
|
|
539
483
|
className,
|