Use accessible indentation (#2253)

This commit is contained in:
Jonathan Neal 2021-12-22 16:11:05 -05:00 committed by GitHub
parent 305ce4182f
commit 6ddd7678ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
440 changed files with 21261 additions and 20879 deletions

View file

@ -4,9 +4,12 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
end_of_line = lf
indent_size = 2
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = false
[{.*,*.md,*.json,*.toml,*.yml,}]
indent_style = space

View file

@ -3,5 +3,14 @@
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5"
"trailingComma": "es5",
"useTabs": true,
"overrides": [
{
"files": [".*", "*.json", "*.md", "*.toml", "*.yml"],
"options": {
"useTabs": false
}
}
]
}

View file

@ -1,12 +1,12 @@
// @ts-check
export default /** @type {import('astro').AstroUserConfig} */ ({
buildOptions: {
site: 'https://docs.astro.build/',
},
renderers: [
// Our main renderer for frontend components
'@astrojs/renderer-preact',
// Needed for Algolia search component
'@astrojs/renderer-react',
],
buildOptions: {
site: 'https://docs.astro.build/',
},
renderers: [
// Our main renderer for frontend components
'@astrojs/renderer-preact',
// Needed for Algolia search component
'@astrojs/renderer-react',
],
});

View file

@ -1,34 +1,34 @@
.language-css > code,
.language-sass > code,
.language-scss > code {
color: #fd9170;
color: #fd9170;
}
.language-diff .token.prefix.deleted,
.language-diff .token.prefix.inserted {
user-select: none;
user-select: none;
}
[class*='language-'] .namespace {
opacity: 0.7;
opacity: 0.7;
}
.token.plain-text,
[class*='language-bash'] span.token,
[class*='language-shell'] span.token {
color: hsla(var(--color-gray-90), 1);
color: hsla(var(--color-gray-90), 1);
}
[class*='language-bash'] span.token,
[class*='language-shell'] span.token {
font-style: bold;
font-style: bold;
}
.token.prolog,
.token.comment,
[class*='language-bash'] span.token.comment,
[class*='language-shell'] span.token.comment {
color: hsla(var(--color-gray-70), 1);
color: hsla(var(--color-gray-70), 1);
}
.token.selector,
@ -38,7 +38,7 @@
.token.variable,
.token.entity,
.token.deleted {
color: #fa5e5b;
color: #fa5e5b;
}
.token.boolean,
@ -51,7 +51,7 @@
.token.hexcode,
.token.class-name,
.token.attr-name {
color: hsla(var(--color-yellow), 1);
color: hsla(var(--color-yellow), 1);
}
.token.atrule,
@ -61,41 +61,41 @@
.token.pseudo-class,
.token.pseudo-element,
.token.string {
color: hsla(var(--color-green), 1);
color: hsla(var(--color-green), 1);
}
.token.symbol,
.token.function,
.token.id,
.token.important {
color: hsla(var(--color-blue), 1);
color: hsla(var(--color-blue), 1);
}
.token.important,
.token.id {
font-weight: bold;
font-weight: bold;
}
.token.cdata,
.token.char,
.token.property {
color: #23b1af;
color: #23b1af;
}
.token.inserted {
color: hsla(var(--color-green), 1);
color: hsla(var(--color-green), 1);
}
.token.keyword {
color: #ff657c;
font-style: italic;
color: #ff657c;
font-style: italic;
}
.token.operator {
color: hsla(var(--color-gray-70), 1);
color: hsla(var(--color-gray-70), 1);
}
.token.attr-value .token.attr-equals,
.token.punctuation {
color: hsla(var(--color-gray-80), 1);
color: hsla(var(--color-gray-80), 1);
}

View file

@ -1,46 +1,46 @@
* {
box-sizing: border-box;
margin: 0;
box-sizing: border-box;
margin: 0;
}
/* Global focus outline reset */
*:focus:not(:focus-visible) {
outline: none;
outline: none;
}
:root {
--user-font-scale: 1rem - 16px;
--max-width: calc(100% - 1rem);
--user-font-scale: 1rem - 16px;
--max-width: calc(100% - 1rem);
}
@media (min-width: 50em) {
:root {
--max-width: 46em;
}
:root {
--max-width: 46em;
}
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
font-family: var(--font-body);
font-size: 1rem;
font-size: clamp(0.9rem, 0.75rem + 0.375vw + var(--user-font-scale), 1rem);
line-height: 1.5;
max-width: 100vw;
display: flex;
flex-direction: column;
min-height: 100vh;
font-family: var(--font-body);
font-size: 1rem;
font-size: clamp(0.9rem, 0.75rem + 0.375vw + var(--user-font-scale), 1rem);
line-height: 1.5;
max-width: 100vw;
}
nav ul {
list-style: none;
padding: 0;
list-style: none;
padding: 0;
}
.content > section > * + * {
margin-top: 1.25rem;
margin-top: 1.25rem;
}
.content > section > :first-child {
margin-top: 0;
margin-top: 0;
}
/* Typography */
@ -50,335 +50,335 @@ h3,
h4,
h5,
h6 {
margin-bottom: 1rem;
font-weight: bold;
line-height: 1;
margin-bottom: 1rem;
font-weight: bold;
line-height: 1;
}
h1,
h2 {
max-width: 40ch;
max-width: 40ch;
}
:is(h2, h3):not(:first-child) {
margin-top: 3rem;
margin-top: 3rem;
}
:is(h4, h5, h6):not(:first-child) {
margin-top: 2rem;
margin-top: 2rem;
}
h1 {
font-size: 3.25rem;
font-weight: 800;
font-size: 3.25rem;
font-weight: 800;
}
h2 {
font-size: 2.5rem;
font-size: 2.5rem;
}
h3 {
font-size: 1.75rem;
font-size: 1.75rem;
}
h4 {
font-size: 1.3rem;
font-size: 1.3rem;
}
h5 {
font-size: 1rem;
font-size: 1rem;
}
p,
.content ul {
line-height: 1.65em;
line-height: 1.65em;
}
p,
.content ul {
color: var(--theme-text-light);
color: var(--theme-text-light);
}
small,
.text_small {
font-size: 0.833rem;
font-size: 0.833rem;
}
a {
color: var(--theme-text-accent);
text-underline-offset: 0.08em;
align-items: center;
gap: 0.5rem;
color: var(--theme-text-accent);
text-underline-offset: 0.08em;
align-items: center;
gap: 0.5rem;
}
article > section :is(ul, ol) > * + * {
margin-top: 0.25rem;
margin-top: 0.25rem;
}
article > section nav :is(ul, ol) > * + * {
margin-top: inherit;
margin-top: inherit;
}
article > section li > :is(p, pre, blockquote):not(:first-child) {
margin-top: 1rem;
margin-top: 1rem;
}
article > section :is(ul, ol) {
padding-left: 1em;
padding-left: 1em;
}
article > section nav :is(ul, ol) {
padding-left: inherit;
padding-left: inherit;
}
article > section nav {
margin-top: 1rem;
margin-bottom: 2rem;
margin-top: 1rem;
margin-bottom: 2rem;
}
article > section ::marker {
font-weight: bold;
color: var(--theme-text-light);
font-weight: bold;
color: var(--theme-text-light);
}
article > section iframe {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
}
a > code:not([class*='language']) {
position: relative;
color: var(--theme-text-accent);
background: transparent;
text-underline-offset: var(--padding-block);
position: relative;
color: var(--theme-text-accent);
background: transparent;
text-underline-offset: var(--padding-block);
}
a > code:not([class*='language'])::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
background: var(--theme-accent);
opacity: var(--theme-accent-opacity);
border-radius: var(--border-radius);
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
background: var(--theme-accent);
opacity: var(--theme-accent-opacity);
border-radius: var(--border-radius);
}
a:hover,
a:focus {
text-decoration: underline;
text-decoration: underline;
}
a:focus {
outline: 2px solid currentColor;
outline-offset: 0.25em;
outline: 2px solid currentColor;
outline-offset: 0.25em;
}
strong {
font-weight: 600;
color: inherit;
font-weight: 600;
color: inherit;
}
/* Supporting Content */
code {
font-family: var(--font-mono);
font-size: 0.85em;
font-family: var(--font-mono);
font-size: 0.85em;
}
code:not([class*='language']) {
--border-radius: 3px;
--padding-block: 0.2rem;
--padding-inline: 0.4rem;
color: var(--theme-code-inline-text);
background-color: var(--theme-code-inline-bg);
padding: var(--padding-block) var(--padding-inline);
margin: calc(var(--padding-block) * -1) -0.125em;
border-radius: var(--border-radius);
box-shadow: 0 2px 1px 0 rgba(0, 0, 0, 0.08);
word-break: break-word;
--border-radius: 3px;
--padding-block: 0.2rem;
--padding-inline: 0.4rem;
color: var(--theme-code-inline-text);
background-color: var(--theme-code-inline-bg);
padding: var(--padding-block) var(--padding-inline);
margin: calc(var(--padding-block) * -1) -0.125em;
border-radius: var(--border-radius);
box-shadow: 0 2px 1px 0 rgba(0, 0, 0, 0.08);
word-break: break-word;
}
pre > code:not([class*='language']) {
background-color: transparent;
padding: 0;
margin: 0;
border-radius: 0;
color: inherit;
background-color: transparent;
padding: 0;
margin: 0;
border-radius: 0;
color: inherit;
}
pre > code {
font-size: 1em;
font-size: 1em;
}
table,
pre {
position: relative;
--padding-block: 1rem;
--padding-inline: 2rem;
padding: var(--padding-block) var(--padding-inline);
padding-right: calc(var(--padding-inline) * 2);
margin-left: calc(var(--padding-inline) * -1);
margin-right: calc(var(--padding-inline) * -1);
font-family: var(--font-mono);
position: relative;
--padding-block: 1rem;
--padding-inline: 2rem;
padding: var(--padding-block) var(--padding-inline);
padding-right: calc(var(--padding-inline) * 2);
margin-left: calc(var(--padding-inline) * -1);
margin-right: calc(var(--padding-inline) * -1);
font-family: var(--font-mono);
line-height: 1.5;
font-size: 0.85em;
overflow-y: hidden;
overflow-x: auto;
line-height: 1.5;
font-size: 0.85em;
overflow-y: hidden;
overflow-x: auto;
}
table {
width: 100%;
padding: var(--padding-block) 0;
margin: 0;
border-collapse: collapse;
width: 100%;
padding: var(--padding-block) 0;
margin: 0;
border-collapse: collapse;
}
/* Zebra striping */
tr:nth-of-type(odd) {
background: var(--theme-bg-hover);
background: var(--theme-bg-hover);
}
th {
background: var(--color-black);
color: var(--theme-color);
font-weight: bold;
background: var(--color-black);
color: var(--theme-color);
font-weight: bold;
}
td,
th {
padding: 6px;
text-align: left;
padding: 6px;
text-align: left;
}
pre {
background-color: var(--theme-code-bg);
color: var(--theme-code-text);
background-color: var(--theme-code-bg);
color: var(--theme-code-text);
}
blockquote code:not([class*='language']) {
background-color: var(--theme-bg);
background-color: var(--theme-bg);
}
@media (min-width: 37.75em) {
pre {
--padding-inline: 1.25rem;
border-radius: 8px;
margin-left: 0;
margin-right: 0;
}
pre {
--padding-inline: 1.25rem;
border-radius: 8px;
margin-left: 0;
margin-right: 0;
}
}
blockquote {
margin: 2rem 0;
padding: 1.25em 1.5rem;
border-left: 3px solid var(--theme-text-light);
background-color: var(--theme-bg-offset);
border-radius: 0 0.25rem 0.25rem 0;
line-height: 1.7;
margin: 2rem 0;
padding: 1.25em 1.5rem;
border-left: 3px solid var(--theme-text-light);
background-color: var(--theme-bg-offset);
border-radius: 0 0.25rem 0.25rem 0;
line-height: 1.7;
}
img {
max-width: 100%;
max-width: 100%;
}
.flex {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
button {
display: flex;
align-items: center;
justify-items: center;
gap: 0.25em;
padding: 0.33em 0.67em;
border: 0;
background: var(--theme-bg);
display: flex;
font-size: 1rem;
align-items: center;
gap: 0.25em;
border-radius: 99em;
color: var(--theme-text);
background-color: var(--theme-bg);
display: flex;
align-items: center;
justify-items: center;
gap: 0.25em;
padding: 0.33em 0.67em;
border: 0;
background: var(--theme-bg);
display: flex;
font-size: 1rem;
align-items: center;
gap: 0.25em;
border-radius: 99em;
color: var(--theme-text);
background-color: var(--theme-bg);
}
h2.heading {
font-size: 1rem;
font-weight: 700;
padding: 0.1rem 1rem;
text-transform: uppercase;
margin-bottom: 0.5rem;
font-size: 1rem;
font-weight: 700;
padding: 0.1rem 1rem;
text-transform: uppercase;
margin-bottom: 0.5rem;
}
.header-link {
font-size: 1rem;
padding: 0.1rem 0 0.1rem 1rem;
border-left: 4px solid var(--theme-divider);
font-size: 1rem;
padding: 0.1rem 0 0.1rem 1rem;
border-left: 4px solid var(--theme-divider);
}
.header-link:hover,
.header-link:focus {
border-left-color: var(--theme-accent);
color: var(--theme-accent);
border-left-color: var(--theme-accent);
color: var(--theme-accent);
}
.header-link:focus-within {
color: var(--theme-text-light);
border-left-color: hsla(var(--color-gray-40), 1);
color: var(--theme-text-light);
border-left-color: hsla(var(--color-gray-40), 1);
}
.header-link svg {
opacity: 0.6;
opacity: 0.6;
}
.header-link:hover svg {
opacity: 0.8;
opacity: 0.8;
}
.header-link a {
display: inline-flex;
gap: 0.5em;
width: 100%;
padding: 0.15em 0 0.15em 0;
display: inline-flex;
gap: 0.5em;
width: 100%;
padding: 0.15em 0 0.15em 0;
}
.header-link.depth-3 {
padding-left: 2rem;
padding-left: 2rem;
}
.header-link.depth-4 {
padding-left: 3rem;
padding-left: 3rem;
}
.header-link a {
font: inherit;
color: inherit;
text-decoration: none;
font: inherit;
color: inherit;
text-decoration: none;
}
/* Screenreader Only Text */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.focus\:not-sr-only:focus,
.focus\:not-sr-only:focus-visible {
position: static;
width: auto;
height: auto;
padding: 0;
margin: 0;
overflow: visible;
clip: auto;
white-space: normal;
position: static;
width: auto;
height: auto;
padding: 0;
margin: 0;
overflow: visible;
clip: auto;
white-space: normal;
}
:target {
scroll-margin: calc(var(--theme-sidebar-offset, 5rem) + 2rem) 0 2rem;
scroll-margin: calc(var(--theme-sidebar-offset, 5rem) + 2rem) 0 2rem;
}

View file

@ -1,3 +1,3 @@
Array.from(document.getElementsByTagName('pre')).forEach((element) => {
element.setAttribute('tabindex', '0');
element.setAttribute('tabindex', '0');
});

View file

@ -1,13 +1,13 @@
:root {
--font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
sans-serif, Apple Color Emoji, Segoe UI Emoji;
--font-body: system-ui, var(--font-fallback);
--font-mono: 'IBM Plex Mono', Consolas, 'Andale Mono WT', 'Andale Mono',
'Lucida Console', 'Lucida Sans Typewriter', 'DejaVu Sans Mono',
'Bitstream Vera Sans Mono', 'Liberation Mono', 'Nimbus Mono L', Monaco,
'Courier New', Courier, monospace;
--font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
sans-serif, Apple Color Emoji, Segoe UI Emoji;
--font-body: system-ui, var(--font-fallback);
--font-mono: 'IBM Plex Mono', Consolas, 'Andale Mono WT', 'Andale Mono',
'Lucida Console', 'Lucida Sans Typewriter', 'DejaVu Sans Mono',
'Bitstream Vera Sans Mono', 'Liberation Mono', 'Nimbus Mono L', Monaco,
'Courier New', Courier, monospace;
/*
/*
* Variables with --color-base prefix define
* the hue, and saturation values to be used for
* hsla colors.
@ -18,109 +18,109 @@
*
*/
--color-base-white: 0, 0%;
--color-base-black: 240, 100%;
--color-base-gray: 215, 14%;
--color-base-blue: 212, 100%;
--color-base-blue-dark: 212, 72%;
--color-base-green: 158, 79%;
--color-base-orange: 22, 100%;
--color-base-purple: 269, 79%;
--color-base-red: 351, 100%;
--color-base-yellow: 41, 100%;
--color-base-white: 0, 0%;
--color-base-black: 240, 100%;
--color-base-gray: 215, 14%;
--color-base-blue: 212, 100%;
--color-base-blue-dark: 212, 72%;
--color-base-green: 158, 79%;
--color-base-orange: 22, 100%;
--color-base-purple: 269, 79%;
--color-base-red: 351, 100%;
--color-base-yellow: 41, 100%;
/*
/*
* Color palettes are made using --color-base
* variables, along with a lightness value to
* define different variants.
*
*/
--color-gray-5: var(--color-base-gray), 5%;
--color-gray-10: var(--color-base-gray), 10%;
--color-gray-20: var(--color-base-gray), 20%;
--color-gray-30: var(--color-base-gray), 30%;
--color-gray-40: var(--color-base-gray), 40%;
--color-gray-50: var(--color-base-gray), 50%;
--color-gray-60: var(--color-base-gray), 60%;
--color-gray-70: var(--color-base-gray), 70%;
--color-gray-80: var(--color-base-gray), 80%;
--color-gray-90: var(--color-base-gray), 90%;
--color-gray-95: var(--color-base-gray), 95%;
--color-gray-5: var(--color-base-gray), 5%;
--color-gray-10: var(--color-base-gray), 10%;
--color-gray-20: var(--color-base-gray), 20%;
--color-gray-30: var(--color-base-gray), 30%;
--color-gray-40: var(--color-base-gray), 40%;
--color-gray-50: var(--color-base-gray), 50%;
--color-gray-60: var(--color-base-gray), 60%;
--color-gray-70: var(--color-base-gray), 70%;
--color-gray-80: var(--color-base-gray), 80%;
--color-gray-90: var(--color-base-gray), 90%;
--color-gray-95: var(--color-base-gray), 95%;
--color-blue: var(--color-base-blue), 61%;
--color-blue-dark: var(--color-base-blue-dark), 39%;
--color-green: var(--color-base-green), 42%;
--color-orange: var(--color-base-orange), 50%;
--color-purple: var(--color-base-purple), 54%;
--color-red: var(--color-base-red), 54%;
--color-yellow: var(--color-base-yellow), 59%;
--color-blue: var(--color-base-blue), 61%;
--color-blue-dark: var(--color-base-blue-dark), 39%;
--color-green: var(--color-base-green), 42%;
--color-orange: var(--color-base-orange), 50%;
--color-purple: var(--color-base-purple), 54%;
--color-red: var(--color-base-red), 54%;
--color-yellow: var(--color-base-yellow), 59%;
}
:root {
color-scheme: light;
--theme-accent: hsla(var(--color-orange), 1);
--theme-text-accent: hsla(var(--color-orange), 1);
--theme-accent-opacity: 0.1;
--theme-divider: hsla(var(--color-gray-95), 1);
--theme-text: hsla(var(--color-gray-10), 1);
--theme-text-light: hsla(var(--color-gray-40), 1);
/* @@@: not used anywhere */
--theme-text-lighter: hsla(var(--color-gray-80), 1);
--theme-bg: hsla(var(--color-base-white), 100%, 1);
--theme-bg-hover: hsla(var(--color-gray-95), 1);
--theme-bg-offset: hsla(var(--color-gray-90), 1);
--theme-bg-accent: hsla(var(--color-orange), var(--theme-accent-opacity));
--theme-code-inline-bg: hsla(var(--color-gray-95), 1);
--theme-code-inline-text: var(--theme-text);
--theme-code-bg: hsla(217, 19%, 27%, 1);
--theme-code-text: hsla(var(--color-gray-95), 1);
--theme-navbar-bg: hsla(var(--color-base-white), 100%, 1);
--theme-navbar-height: 6rem;
--theme-selection-color: hsla(var(--color-orange), 1);
--theme-selection-bg: hsla(var(--color-orange), var(--theme-accent-opacity));
color-scheme: light;
--theme-accent: hsla(var(--color-orange), 1);
--theme-text-accent: hsla(var(--color-orange), 1);
--theme-accent-opacity: 0.1;
--theme-divider: hsla(var(--color-gray-95), 1);
--theme-text: hsla(var(--color-gray-10), 1);
--theme-text-light: hsla(var(--color-gray-40), 1);
/* @@@: not used anywhere */
--theme-text-lighter: hsla(var(--color-gray-80), 1);
--theme-bg: hsla(var(--color-base-white), 100%, 1);
--theme-bg-hover: hsla(var(--color-gray-95), 1);
--theme-bg-offset: hsla(var(--color-gray-90), 1);
--theme-bg-accent: hsla(var(--color-orange), var(--theme-accent-opacity));
--theme-code-inline-bg: hsla(var(--color-gray-95), 1);
--theme-code-inline-text: var(--theme-text);
--theme-code-bg: hsla(217, 19%, 27%, 1);
--theme-code-text: hsla(var(--color-gray-95), 1);
--theme-navbar-bg: hsla(var(--color-base-white), 100%, 1);
--theme-navbar-height: 6rem;
--theme-selection-color: hsla(var(--color-orange), 1);
--theme-selection-bg: hsla(var(--color-orange), var(--theme-accent-opacity));
}
body {
background: var(--theme-bg);
color: var(--theme-text);
background: var(--theme-bg);
color: var(--theme-text);
}
:root.theme-dark {
color-scheme: dark;
--theme-accent-opacity: 0.4;
--theme-accent: hsla(var(--color-orange), 1);
--theme-text-accent: hsla(var(--color-orange), 1);
--theme-divider: hsla(var(--color-gray-10), 1);
--theme-text: hsla(var(--color-gray-90), 1);
--theme-text-light: hsla(var(--color-gray-80), 1);
color-scheme: dark;
--theme-accent-opacity: 0.4;
--theme-accent: hsla(var(--color-orange), 1);
--theme-text-accent: hsla(var(--color-orange), 1);
--theme-divider: hsla(var(--color-gray-10), 1);
--theme-text: hsla(var(--color-gray-90), 1);
--theme-text-light: hsla(var(--color-gray-80), 1);
/* @@@: not used anywhere */
--theme-text-lighter: hsla(var(--color-gray-40), 1);
--theme-bg: hsla(215, 28%, 17%, 1);
--theme-bg-hover: hsla(var(--color-gray-40), 1);
--theme-bg-offset: hsla(var(--color-gray-5), 1);
--theme-code-inline-bg: hsla(var(--color-gray-10), 1);
--theme-code-inline-text: hsla(var(--color-base-white), 100%, 1);
--theme-code-bg: hsla(var(--color-gray-5), 1);
--theme-code-text: hsla(var(--color-base-white), 100%, 1);
--theme-navbar-bg: hsla(215, 28%, 17%, 1);
--theme-selection-color: hsla(var(--color-base-white), 100%, 1);
--theme-selection-bg: hsla(var(--color-purple), var(--theme-accent-opacity));
/* @@@: not used anywhere */
--theme-text-lighter: hsla(var(--color-gray-40), 1);
--theme-bg: hsla(215, 28%, 17%, 1);
--theme-bg-hover: hsla(var(--color-gray-40), 1);
--theme-bg-offset: hsla(var(--color-gray-5), 1);
--theme-code-inline-bg: hsla(var(--color-gray-10), 1);
--theme-code-inline-text: hsla(var(--color-base-white), 100%, 1);
--theme-code-bg: hsla(var(--color-gray-5), 1);
--theme-code-text: hsla(var(--color-base-white), 100%, 1);
--theme-navbar-bg: hsla(215, 28%, 17%, 1);
--theme-selection-color: hsla(var(--color-base-white), 100%, 1);
--theme-selection-bg: hsla(var(--color-purple), var(--theme-accent-opacity));
/* DocSearch [Algolia] */
--docsearch-modal-background: var(--theme-bg);
--docsearch-searchbox-focus-background: var(--theme-divider);
--docsearch-footer-background: var(--theme-divider);
--docsearch-text-color: var(--theme-text);
--docsearch-hit-background: var(--theme-divider);
--docsearch-hit-shadow: none;
--docsearch-hit-color: var(--theme-text);
--docsearch-footer-shadow: inset 0 2px 10px #000;
--docsearch-modal-shadow: inset 0 0 8px #000;
/* DocSearch [Algolia] */
--docsearch-modal-background: var(--theme-bg);
--docsearch-searchbox-focus-background: var(--theme-divider);
--docsearch-footer-background: var(--theme-divider);
--docsearch-text-color: var(--theme-text);
--docsearch-hit-background: var(--theme-divider);
--docsearch-hit-shadow: none;
--docsearch-hit-color: var(--theme-text);
--docsearch-footer-shadow: inset 0 2px 10px #000;
--docsearch-modal-shadow: inset 0 0 8px #000;
}
::selection {
color: var(--theme-selection-color);
background-color: var(--theme-selection-bg);
color: var(--theme-selection-color);
background-color: var(--theme-selection-bg);
}

View file

@ -1,52 +1,62 @@
---
const {data, index} = Astro.props;
const { data, index } = Astro.props;
const hasScreenshot = !!data.demo;
const backgroundStyle = hasScreenshot ? `url('https://v1.screenshot.11ty.dev/${encodeURIComponent(data.demo)}/medium/9:16/')` : `linear-gradient(60deg, var(--theme-bg-accent), var(--theme-accent))`
const backgroundStyle = hasScreenshot
? `url('https://v1.screenshot.11ty.dev/${encodeURIComponent(
data.demo
)}/medium/9:16/')`
: `linear-gradient(60deg, var(--theme-bg-accent), var(--theme-accent))`;
---
<style>
.card {
position: relative;
display: flex;
flex-direction: column;
grid-column: span 1;
flex-grow: 1;
height: 200px;
justify-content: center;
align-items: center;
padding: 1rem;
text-align: center;
}
.card-header {
flex-grow: 1;
font-weight: bold;
font-size: 1.8rem;
}
.background-dimmer {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: linear-gradient(45deg, #0004, #000B);
z-index: 2;
}
.card-body, .card-header {
color: var(--text-color);
}
.card-body {
z-index: 3;
}
.card.has-screenshot .card-header,
.card.has-screenshot .card-body {
color: white;
}
</style>
<article class={`card ${hasScreenshot ? 'has-screenshot' : ''}`} style={`background: ${backgroundStyle}; background-size: cover;`}>
{hasScreenshot && <div class="background-dimmer"></div>}
<div class="card-body">
<a href={data.github} class="card-header" target="_blank">
{data.name}
<span>{` →`}</span>
</a>
</div>
<article
class={`card ${hasScreenshot ? 'has-screenshot' : ''}`}
style={`background: ${backgroundStyle}; background-size: cover;`}
>
{hasScreenshot && <div class="background-dimmer"></div>}
<div class="card-body">
<a href={data.github} class="card-header" target="_blank">
{data.name}
<span>{` →`}</span>
</a>
</div>
</article>
<style>
.card {
position: relative;
display: flex;
flex-direction: column;
grid-column: span 1;
flex-grow: 1;
height: 200px;
justify-content: center;
align-items: center;
padding: 1rem;
text-align: center;
}
.card-header {
flex-grow: 1;
font-weight: bold;
font-size: 1.8rem;
}
.background-dimmer {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: linear-gradient(45deg, #0004, #000b);
z-index: 2;
}
.card-body,
.card-header {
color: var(--text-color);
}
.card-body {
z-index: 3;
}
.card.has-screenshot .card-header,
.card.has-screenshot .card-body {
color: white;
}
</style>

View file

@ -2,7 +2,7 @@
// fetch all commits for just this page's path
export interface Props {
path: string;
path: string;
}
const { path } = Astro.props as Props;
@ -11,147 +11,166 @@ const url = `https://api.github.com/repos/withastro/astro/commits?path=${commitP
const commitsURL = `https://github.com/withastro/astro/commits/main/${commitPath}`;
async function getCommits(url) {
try {
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN;
if (!token) {
throw new Error(
'Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.'
);
}
try {
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN;
if (!token) {
throw new Error(
'Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.'
);
}
const auth = `Basic ${Buffer.from(token, "binary").toString("base64")}`;
const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`;
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: auth,
"User-Agent": "astro-docs/1.0",
},
});
const res = await fetch(url, {
method: 'GET',
headers: {
Authorization: auth,
'User-Agent': 'astro-docs/1.0',
},
});
const data = await res.json();
const data = await res.json();
if (!res.ok) {
throw new Error(
`Request to fetch commits failed. Reason: ${res.statusText}
if (!res.ok) {
throw new Error(
`Request to fetch commits failed. Reason: ${res.statusText}
Message: ${data.message}`
);
}
);
}
return data;
} catch (e) {
console.warn(`[error] /src/components/AvatarList.astro
return data;
} catch (e) {
console.warn(`[error] /src/components/AvatarList.astro
${e?.message ?? e}`);
return new Array();
}
return new Array();
}
}
function removeDups(arr) {
if (!arr) {
return new Array();
}
let map = new Map();
if (!arr) {
return new Array();
}
let map = new Map();
for (let item of arr) {
let author = item.author;
// Deduplicate based on author.id
map.set(author.id, { login: author.login, id: author.id });
}
for (let item of arr) {
let author = item.author;
// Deduplicate based on author.id
map.set(author.id, { login: author.login, id: author.id });
}
return Array.from(map.values());
return Array.from(map.values());
}
const data = await getCommits(url);
const unique = removeDups(data);
const recentContributors = unique.slice(0, 3); // only show avatars for the 3 most recent contributors
const additionalContributors = unique.length - recentContributors.length; // list the rest of them as # of extra contributors
---
<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
<div class="contributors">
<ul class="avatar-list" style={`--avatar-count: ${recentContributors.length}`}>
{recentContributors.map((item) => (
<li><a href={`https://github.com/${item.login}`}><img alt={`Contributor ${item.login}`} title={`Contributor ${item.login}`} width="64" height="64" src={`https://avatars.githubusercontent.com/u/${item.id}`}/></a></li>
))}
</ul>
{additionalContributors > 0 && <span><a href={commitsURL}>{`and ${additionalContributors} additional contributor${additionalContributors > 1 ? 's' : ''}.`}</a></span>}
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
<ul
class="avatar-list"
style={`--avatar-count: ${recentContributors.length}`}
>
{recentContributors.map((item) => (
<li>
<a href={`https://github.com/${item.login}`}>
<img
alt={`Contributor ${item.login}`}
title={`Contributor ${item.login}`}
width="64"
height="64"
src={`https://avatars.githubusercontent.com/u/${item.id}`}
/>
</a>
</li>
))}
</ul>
{additionalContributors > 0 && (
<span>
<a
href={commitsURL}
>{`and ${additionalContributors} additional contributor${
additionalContributors > 1 ? 's' : ''
}.`}</a>
</span>
)}
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
</div>
<style>
.avatar-list {
--avatar-size: 2.5rem;
--avatar-count: 3;
.avatar-list {
--avatar-size: 2.5rem;
--avatar-count: 3;
display: grid;
list-style: none;
/* Default to displaying most of the avatar to
display: grid;
list-style: none;
/* Default to displaying most of the avatar to
enable easier access on touch devices, ensuring
the WCAG touch target size is met or exceeded */
grid-template-columns: repeat(
var(--avatar-count),
max(44px, calc(var(--avatar-size) / 1.15))
);
/* `padding` matches added visual dimensions of
grid-template-columns: repeat(
var(--avatar-count),
max(44px, calc(var(--avatar-size) / 1.15))
);
/* `padding` matches added visual dimensions of
the `box-shadow` to help create a more accurate
computed component size */
padding: 0.08em;
font-size: var(--avatar-size);
}
padding: 0.08em;
font-size: var(--avatar-size);
}
@media (any-hover: hover) and (any-pointer: fine) {
.avatar-list {
/* We create 1 extra cell to enable the computed
@media (any-hover: hover) and (any-pointer: fine) {
.avatar-list {
/* We create 1 extra cell to enable the computed
width to match the final visual width */
grid-template-columns: repeat(
calc(var(--avatar-count) + 1),
calc(var(--avatar-size) / 1.75)
);
}
}
grid-template-columns: repeat(
calc(var(--avatar-count) + 1),
calc(var(--avatar-size) / 1.75)
);
}
}
.avatar-list li {
width: var(--avatar-size);
height: var(--avatar-size);
}
.avatar-list li {
width: var(--avatar-size);
height: var(--avatar-size);
}
.avatar-list li:hover ~ li a,
.avatar-list li:focus-within ~ li a {
transform: translateX(33%);
}
.avatar-list li:hover ~ li a,
.avatar-list li:focus-within ~ li a {
transform: translateX(33%);
}
.avatar-list img,
.avatar-list a {
display: block;
border-radius: 50%;
}
.avatar-list img,
.avatar-list a {
display: block;
border-radius: 50%;
}
.avatar-list a {
transition: transform 180ms ease-in-out;
}
.avatar-list a {
transition: transform 180ms ease-in-out;
}
.avatar-list img {
width: 100%;
height: 100%;
object-fit: cover;
background-color: #fff;
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
}
.avatar-list img {
width: 100%;
height: 100%;
object-fit: cover;
background-color: #fff;
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
}
.avatar-list a:focus {
outline: 2px solid transparent;
/* Double-layer trick to work for dark and light backgrounds */
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
}
.avatar-list a:focus {
outline: 2px solid transparent;
/* Double-layer trick to work for dark and light backgrounds */
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
}
.contributors {
display: flex;
align-items: center;
}
.contributors {
display: flex;
align-items: center;
}
.contributors > * + * {
margin-left: .75rem;
}
.contributors > * + * {
margin-left: 0.75rem;
}
</style>

View file

@ -4,13 +4,13 @@ const { path } = Astro.props;
---
<footer>
<AvatarList path={path} />
<AvatarList {path} />
</footer>
<style>
footer {
margin-top: auto;
padding: 2rem 0;
border-top: 3px solid var(--theme-divider);
}
footer {
margin-top: auto;
padding: 2rem 0;
border-top: 3px solid var(--theme-divider);
}
</style>

View file

@ -1,10 +1,10 @@
<!-- Global Metadata -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#ff5e00"/>
<link rel="icon" type="image/svg+xml" href="/favicon.svg"/>
<meta name="viewport" content="width=device-width" />
<meta name="theme-color" content="#ff5e00" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="alternate icon" type="image/x-icon" href="/favicon.ico" />
<link rel="sitemap" href="/sitemap.xml"/>
<link rel="sitemap" href="/sitemap.xml" />
<!-- Global CSS -->
<link rel="stylesheet" href="/theme.css" />
@ -12,29 +12,38 @@
<link rel="stylesheet" href="/index.css" />
<!-- Preload Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap"
rel="stylesheet"
/>
<!-- Scrollable a11y code helper -->
<script type="module" src="/make-scrollable-code-focusable.js" />
<script type="module" src="/make-scrollable-code-focusable.js"></script>
<!-- This is intentionally inlined to avoid FOUC -->
<script>
const root = document.documentElement;
const theme = localStorage.getItem('theme');
if (theme === 'dark' || (!theme) && window.matchMedia('(prefers-color-scheme: dark)').matches) {
root.classList.add('theme-dark');
} else {
root.classList.remove('theme-dark');
}
const root = document.documentElement;
const theme = localStorage.getItem('theme');
if (
theme === 'dark' ||
(!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
root.classList.add('theme-dark');
} else {
root.classList.remove('theme-dark');
}
</script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-130280175-15"></script>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-130280175-15"
></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-130280175-15');
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-130280175-15');
</script>

View file

@ -1,43 +1,48 @@
---
import {SITE, OPEN_GRAPH} from '../config.ts';
import { SITE, OPEN_GRAPH } from '../config.ts';
import { getLanguageFromURL } from '../util.ts';
export interface Props {
content: any,
site: any,
canonicalURL: URL,
};
const {
content = {},
canonicalURL,
} = Astro.props;
content: any;
site: any;
canonicalURL: URL;
}
const { content = {}, canonicalURL } = Astro.props;
const imageSrc = content?.image?.src ?? OPEN_GRAPH.image.src;
const canonicalImageSrc = new URL(imageSrc, Astro.site);
const imageAlt = content?.image?.alt ?? OPEN_GRAPH.image.alt;
const lang = canonicalURL && getLanguageFromURL(canonicalURL.pathname);
---
<!-- Page Metadata -->
<link rel="canonical" href={canonicalURL}/>
<link rel="canonical" href={canonicalURL} />
<!-- Algolia docsearch language facet -->
<meta name="docsearch:language" content={lang} />
<!-- OpenGraph Tags -->
<meta property="og:title" content={content.title ?? SITE.title}/>
<meta property="og:type" content="article"/>
<meta property="og:url" content={canonicalURL}/>
<meta property="og:locale" content={content.ogLocale ?? OPEN_GRAPH.locale}/>
<meta property="og:image" content={canonicalImageSrc}/>
<meta property="og:image:alt" content={imageAlt}/>
<meta name="description" property="og:description" content={content.description ? content.description : SITE.description}/>
<meta property="og:site_name" content={SITE.title}/>
<meta property="og:title" content={content.title ?? SITE.title} />
<meta property="og:type" content="article" />
<meta property="og:url" content={canonicalURL} />
<meta property="og:locale" content={content.ogLocale ?? OPEN_GRAPH.locale} />
<meta property="og:image" content={canonicalImageSrc} />
<meta property="og:image:alt" content={imageAlt} />
<meta
name="description"
property="og:description"
content={content.description ? content.description : SITE.description}
/>
<meta property="og:site_name" content={SITE.title} />
<!-- Twitter Tags -->
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:site" content={OPEN_GRAPH.twitter}/>
<meta name="twitter:title" content={content.title ?? SITE.title}/>
<meta name="twitter:description" content={content.description ? content.description : SITE.description}/>
<meta name="twitter:image" content={canonicalImageSrc}/>
<meta name="twitter:image:alt" content={imageAlt}/>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content={OPEN_GRAPH.twitter} />
<meta name="twitter:title" content={content.title ?? SITE.title} />
<meta
name="twitter:description"
content={content.description ? content.description : SITE.description}
/>
<meta name="twitter:image" content={canonicalImageSrc} />
<meta name="twitter:image:alt" content={imageAlt} />
<!--
TODO: Add json+ld data, maybe https://schema.org/APIReference makes sense?

View file

@ -1,20 +1,36 @@
---
const {size} = Astro.props;
const { size } = Astro.props;
---
<svg class="logo" width={size} height={size} viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
#flame {
/* fill: #ff5d01; */
fill: #3894ff;
}
#a {
/* fill: #000014; */
fill: #3894ff;
}
</style>
<title>Logo</title>
<path id="a" fill-rule="evenodd" clip-rule="evenodd"
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z" />
<path id="flame" fill-rule="evenodd" clip-rule="evenodd"
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z" />
<svg
class="logo"
width={size}
height={size}
viewBox="0 0 256 256"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<style>
#flame {
/* fill: #ff5d01; */
fill: #3894ff;
}
#a {
/* fill: #000014; */
fill: #3894ff;
}
</style>
<title>Logo</title>
<path
id="a"
fill-rule="evenodd"
clip-rule="evenodd"
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
></path>
<path
id="flame"
fill-rule="evenodd"
clip-rule="evenodd"
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
></path>
</svg>

View file

@ -2,158 +2,183 @@
import SkipToContent from './SkipToContent.astro';
import SidebarToggle from './SidebarToggle.tsx';
import LanguageSelect from './LanguageSelect.tsx';
import Search from "./Search.tsx";
import Search from './Search.tsx';
import { getLanguageFromURL } from '../../util.ts';
const {currentPage} = Astro.props;
const { currentPage } = Astro.props;
const lang = currentPage && getLanguageFromURL(currentPage);
---
<style>
header {
z-index: 11;
height: var(--theme-navbar-height);
width: 100%;
background-color: var(--theme-navbar-bg);
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
position: sticky;
top: 0;
}
.logo {
direction: ltr;
display: flex;
overflow: hidden;
width: 30px;
font-size: 1rem;
flex-shrink: 0;
font-weight: 600;
line-height: 1;
color: hsla(var(--color-base-white), 100%, 1);
text-decoration: none;
gap: 0.5em;
z-index: -1;
}
.logo a {
padding: 0.5em 0.25em;
margin: -0.5em -0.25em;
}
.logo svg {
height: 40px;
width: auto;
display: block;
color: var(--theme-accent);
}
.logo .hover {
opacity: 0.0;
}
.logo a {
transition: transform 180ms ease-out;
}
.logo a:hover,
.logo a:focus {
outline: none;
opacity: 1.0;
transform: translateY(-2px);
}
.logo h1 {
font: inherit;
color: inherit;
margin: 0;
}
.nav-wrapper {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 1em;
width: 100%;
max-width: 82em;
padding: 0 1rem;
}
@media (min-width: 50em) {
header {
position: static;
padding: 2rem 0rem 0 2rem;
}
.logo {
width: auto;
margin: 0;
z-index: 0;
}
.menu-toggle {
display: none;
}
.logo {
width: auto;
}
}
/** Style Algolia */
:root {
--docsearch-primary-color: var(--theme-accent);
--docsearch-logo-color: var(--theme-text);
}
.search-item {
display: none;
position: relative;
z-index: 10;
flex-grow: 1;
padding-right: 0.7rem;
display: flex;
max-width: 200px;
}
:global(.search-item > *) {
flex-grow: 1;
}
@media (min-width: 50em) {
.search-item {
max-width: 400px;
}
}
</style>
<header>
<SkipToContent />
<nav class="nav-wrapper" title="Top Navigation">
<div class="menu-toggle">
<SidebarToggle client:idle/>
</div>
<div class="logo flex">
<a href="https://astro.build/">
<h1 class="sr-only">Astro</h1>
<svg xmlns="http://www.w3.org/2000/svg" width="363" height="102" viewBox="0 0 363 102" fill="none">
<style>
.text {
fill: var(--theme-text);
}
.hover {
fill: var(--theme-accent);
}
</style>
<path class="text" fill-rule="evenodd" d="M55.07 14.216l16.81 54.865a72.6 72.6 0 00-20.765-6.984L39.808 24.135a1.475 1.475 0 00-2.827.005L25.81 62.078a72.598 72.598 0 00-20.859 6.995L21.847 14.2c.998-3.243 1.497-4.865 2.47-6.066a8 8 0 013.239-2.392c1.434-.576 3.13-.576 6.524-.576h8.751c3.398 0 5.097 0 6.532.577a8 8 0 013.241 2.397c.972 1.203 1.47 2.827 2.465 6.076z" clip-rule="evenodd"/>
<path fill="#FF5D01" fill-rule="evenodd" d="M54.618 71.779c-2.863 2.432-8.578 4.091-15.161 4.091-8.08 0-14.852-2.499-16.649-5.86-.642 1.926-.786 4.13-.786 5.539 0 0-.423 6.915 4.418 11.725 0-2.498 2.037-4.522 4.551-4.522 4.309 0 4.304 3.734 4.3 6.764v.27c0 4.6 2.829 8.541 6.852 10.203a9.22 9.22 0 01-.938-4.064c0-4.386 2.592-6.02 5.604-7.917 2.396-1.51 5.06-3.188 6.894-6.554a12.297 12.297 0 001.502-5.905c0-1.314-.206-2.581-.587-3.77z" clip-rule="evenodd"/>
<path class="text" d="M126.554 69c13.115 0 21.047-3.14 25.68-9.654 0 2.904.157 5.651.55 8.163h7.774c-.706-4.082-.863-6.75-.863-14.128V43.334c0-10.831-8.403-16.56-24.424-16.56-15.47 0-25.522 5.964-26.779 14.598h8.246c1.256-5.808 7.774-8.87 18.533-8.87 10.602 0 16.885 3.69 16.885 9.969v.785l-24.502 1.413c-9.974.549-13.665 1.962-16.492 4.003-2.67 1.962-4.162 5.023-4.162 8.555C107 64.683 114.696 69 126.554 69zm2.513-5.573c-9.109 0-14.135-2.119-14.135-6.357 0-4.553 3.141-6.593 14.214-7.3l23.01-1.412v1.805c0 8.241-9.66 13.264-23.089 13.264zM196.086 69c16.256 0 22.775-5.337 22.775-13.108 0-6.436-4.006-9.732-14.215-10.596l-19.083-1.49c-5.183-.393-8.088-1.884-8.088-5.102 0-4.082 4.476-6.201 14.135-6.201 10.995 0 16.727 2.198 20.497 7.064l6.361-3.061c-3.927-6.122-12.644-9.733-26.151-9.733-13.9 0-22.224 4.631-22.224 12.244 0 6.829 4.947 10.125 14.292 10.91l18.926 1.492c6.204.47 8.089 1.726 8.089 4.944 0 4.631-4.79 6.829-14.293 6.829-11.544 0-18.847-3.14-22.381-8.87l-6.204 3.376C173.312 64.918 181.715 69 196.086 69zM234.929 34.151v18.916c0 7.77 2.67 15.54 17.198 15.54 3.691 0 8.167-.706 10.131-1.57V60.68c-2.749.628-6.047 1.1-9.267 1.1-6.832 0-10.523-2.67-10.523-9.42V34.151h19.633v-5.887h-19.633V15l-7.539 3.061v10.204h-12.33v5.886h12.33zM280.823 28.265h-6.911v39.244h7.461V52.83c0-5.65 1.099-10.439 4.24-13.735 2.749-3.061 6.283-4.788 12.487-4.788 2.12 0 3.455.157 5.262.471v-7.22c-1.65-.393-3.063-.472-5.184-.472-8.402 0-15.078 4.945-17.355 12.558v-11.38zM334.807 69C351.534 69 363 60.523 363 47.887c0-12.637-11.466-21.114-28.193-21.114-16.727 0-28.193 8.477-28.193 21.114C306.614 60.523 318.08 69 334.807 69zm0-6.2c-12.329 0-20.261-5.809-20.261-14.913 0-9.105 7.932-14.913 20.261-14.913 12.251 0 20.261 5.808 20.261 14.913 0 9.104-8.01 14.912-20.261 14.912z"/>
</svg>
</a>
<a href="https://docs.astro.build/">
<h1 class="sr-only">Docs</h1>
<svg xmlns="http://www.w3.org/2000/svg" width="226" height="102" viewBox="0 0 226 102" fill="none">
<path fill="currentColor" d="M25.805 68c14.688 0 24.883-8.41 24.883-21.14 0-12.786-9.62-19.756-24.653-19.756H0V68h25.805zm-14.17-33.005H24.25c8.352 0 14.17 4.09 14.17 12.039 0 8.236-5.3 13.075-14.113 13.075H11.635V34.995zM82.673 69.382c16.704 0 27.418-8.582 27.418-21.83 0-13.248-10.771-21.83-27.418-21.83-16.589 0-27.418 8.582-27.418 21.83 0 13.19 10.83 21.83 27.418 21.83zm0-8.64c-9.1 0-15.149-5.299-15.149-13.19 0-7.891 6.048-13.19 15.15-13.19 9.1 0 15.205 5.299 15.205 13.19 0 7.891-6.105 13.19-15.206 13.19zM141.497 69.382c13.306 0 22.637-5.299 25.978-14.572l-11.866-2.535c-1.67 5.415-6.393 8.295-13.709 8.295-9.216 0-15.033-5.127-15.033-13.018 0-8.006 5.702-13.018 14.918-13.018 7.43 0 12.154 3.053 13.709 8.64l12.038-2.13c-2.707-9.562-12.268-15.322-25.574-15.322-16.128 0-27.302 9.043-27.302 22.003 0 13.133 10.425 21.657 26.841 21.657zM194.94 69.382c14.745 0 23.212-5.01 23.212-14.054 0-7.603-4.665-10.944-15.955-12.096l-11.289-1.094c-5.242-.576-6.97-1.556-6.97-4.09 0-2.765 3.456-4.262 9.792-4.262 7.834 0 13.709 2.476 16.762 6.508l7.315-6.163c-5.069-5.702-13.133-8.41-23.501-8.41-13.997 0-21.888 4.781-21.888 12.903 0 7.546 4.781 11.232 14.803 12.326l12.557 1.383c4.896.518 6.624 1.555 6.624 4.09 0 3.225-3.456 4.723-10.886 4.723-8.352 0-14.688-3.226-18.087-8.007l-8.294 5.818c4.205 6.451 13.709 10.425 25.805 10.425z"/>
</svg>
</a>
</div>
<div style="flex-grow: 1;"></div>
{lang && <LanguageSelect lang={lang} client:idle />}
<div class="search-item"><Search lang={lang} client:idle /></div>
</nav>
<SkipToContent />
<nav class="nav-wrapper" title="Top Navigation">
<div class="menu-toggle">
<SidebarToggle client:idle />
</div>
<div class="logo flex">
<a href="https://astro.build/">
<h1 class="sr-only">Astro</h1>
<svg
xmlns="http://www.w3.org/2000/svg"
width="363"
height="102"
viewBox="0 0 363 102"
fill="none"
>
<style>
.text {
fill: var(--theme-text);
}
.hover {
fill: var(--theme-accent);
}
</style>
<path
class="text"
fill-rule="evenodd"
d="M55.07 14.216l16.81 54.865a72.6 72.6 0 00-20.765-6.984L39.808 24.135a1.475 1.475 0 00-2.827.005L25.81 62.078a72.598 72.598 0 00-20.859 6.995L21.847 14.2c.998-3.243 1.497-4.865 2.47-6.066a8 8 0 013.239-2.392c1.434-.576 3.13-.576 6.524-.576h8.751c3.398 0 5.097 0 6.532.577a8 8 0 013.241 2.397c.972 1.203 1.47 2.827 2.465 6.076z"
clip-rule="evenodd"></path>
<path
fill="#FF5D01"
fill-rule="evenodd"
d="M54.618 71.779c-2.863 2.432-8.578 4.091-15.161 4.091-8.08 0-14.852-2.499-16.649-5.86-.642 1.926-.786 4.13-.786 5.539 0 0-.423 6.915 4.418 11.725 0-2.498 2.037-4.522 4.551-4.522 4.309 0 4.304 3.734 4.3 6.764v.27c0 4.6 2.829 8.541 6.852 10.203a9.22 9.22 0 01-.938-4.064c0-4.386 2.592-6.02 5.604-7.917 2.396-1.51 5.06-3.188 6.894-6.554a12.297 12.297 0 001.502-5.905c0-1.314-.206-2.581-.587-3.77z"
clip-rule="evenodd"></path>
<path
class="text"
d="M126.554 69c13.115 0 21.047-3.14 25.68-9.654 0 2.904.157 5.651.55 8.163h7.774c-.706-4.082-.863-6.75-.863-14.128V43.334c0-10.831-8.403-16.56-24.424-16.56-15.47 0-25.522 5.964-26.779 14.598h8.246c1.256-5.808 7.774-8.87 18.533-8.87 10.602 0 16.885 3.69 16.885 9.969v.785l-24.502 1.413c-9.974.549-13.665 1.962-16.492 4.003-2.67 1.962-4.162 5.023-4.162 8.555C107 64.683 114.696 69 126.554 69zm2.513-5.573c-9.109 0-14.135-2.119-14.135-6.357 0-4.553 3.141-6.593 14.214-7.3l23.01-1.412v1.805c0 8.241-9.66 13.264-23.089 13.264zM196.086 69c16.256 0 22.775-5.337 22.775-13.108 0-6.436-4.006-9.732-14.215-10.596l-19.083-1.49c-5.183-.393-8.088-1.884-8.088-5.102 0-4.082 4.476-6.201 14.135-6.201 10.995 0 16.727 2.198 20.497 7.064l6.361-3.061c-3.927-6.122-12.644-9.733-26.151-9.733-13.9 0-22.224 4.631-22.224 12.244 0 6.829 4.947 10.125 14.292 10.91l18.926 1.492c6.204.47 8.089 1.726 8.089 4.944 0 4.631-4.79 6.829-14.293 6.829-11.544 0-18.847-3.14-22.381-8.87l-6.204 3.376C173.312 64.918 181.715 69 196.086 69zM234.929 34.151v18.916c0 7.77 2.67 15.54 17.198 15.54 3.691 0 8.167-.706 10.131-1.57V60.68c-2.749.628-6.047 1.1-9.267 1.1-6.832 0-10.523-2.67-10.523-9.42V34.151h19.633v-5.887h-19.633V15l-7.539 3.061v10.204h-12.33v5.886h12.33zM280.823 28.265h-6.911v39.244h7.461V52.83c0-5.65 1.099-10.439 4.24-13.735 2.749-3.061 6.283-4.788 12.487-4.788 2.12 0 3.455.157 5.262.471v-7.22c-1.65-.393-3.063-.472-5.184-.472-8.402 0-15.078 4.945-17.355 12.558v-11.38zM334.807 69C351.534 69 363 60.523 363 47.887c0-12.637-11.466-21.114-28.193-21.114-16.727 0-28.193 8.477-28.193 21.114C306.614 60.523 318.08 69 334.807 69zm0-6.2c-12.329 0-20.261-5.809-20.261-14.913 0-9.105 7.932-14.913 20.261-14.913 12.251 0 20.261 5.808 20.261 14.913 0 9.104-8.01 14.912-20.261 14.912z"
></path>
</svg>
</a>
<a href="https://docs.astro.build/">
<h1 class="sr-only">Docs</h1>
<svg
xmlns="http://www.w3.org/2000/svg"
width="226"
height="102"
viewBox="0 0 226 102"
fill="none"
>
<path
fill="currentColor"
d="M25.805 68c14.688 0 24.883-8.41 24.883-21.14 0-12.786-9.62-19.756-24.653-19.756H0V68h25.805zm-14.17-33.005H24.25c8.352 0 14.17 4.09 14.17 12.039 0 8.236-5.3 13.075-14.113 13.075H11.635V34.995zM82.673 69.382c16.704 0 27.418-8.582 27.418-21.83 0-13.248-10.771-21.83-27.418-21.83-16.589 0-27.418 8.582-27.418 21.83 0 13.19 10.83 21.83 27.418 21.83zm0-8.64c-9.1 0-15.149-5.299-15.149-13.19 0-7.891 6.048-13.19 15.15-13.19 9.1 0 15.205 5.299 15.205 13.19 0 7.891-6.105 13.19-15.206 13.19zM141.497 69.382c13.306 0 22.637-5.299 25.978-14.572l-11.866-2.535c-1.67 5.415-6.393 8.295-13.709 8.295-9.216 0-15.033-5.127-15.033-13.018 0-8.006 5.702-13.018 14.918-13.018 7.43 0 12.154 3.053 13.709 8.64l12.038-2.13c-2.707-9.562-12.268-15.322-25.574-15.322-16.128 0-27.302 9.043-27.302 22.003 0 13.133 10.425 21.657 26.841 21.657zM194.94 69.382c14.745 0 23.212-5.01 23.212-14.054 0-7.603-4.665-10.944-15.955-12.096l-11.289-1.094c-5.242-.576-6.97-1.556-6.97-4.09 0-2.765 3.456-4.262 9.792-4.262 7.834 0 13.709 2.476 16.762 6.508l7.315-6.163c-5.069-5.702-13.133-8.41-23.501-8.41-13.997 0-21.888 4.781-21.888 12.903 0 7.546 4.781 11.232 14.803 12.326l12.557 1.383c4.896.518 6.624 1.555 6.624 4.09 0 3.225-3.456 4.723-10.886 4.723-8.352 0-14.688-3.226-18.087-8.007l-8.294 5.818c4.205 6.451 13.709 10.425 25.805 10.425z"
></path>
</svg>
</a>
</div>
<div style="flex-grow: 1;"></div>
{lang && <LanguageSelect lang={lang} client:idle />}
<div class="search-item"><Search {lang} client:idle /></div>
</nav>
</header>
<style>
header {
z-index: 11;
height: var(--theme-navbar-height);
width: 100%;
background-color: var(--theme-navbar-bg);
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
position: sticky;
top: 0;
}
.logo {
direction: ltr;
display: flex;
overflow: hidden;
width: 30px;
font-size: 1rem;
flex-shrink: 0;
font-weight: 600;
line-height: 1;
color: hsla(var(--color-base-white), 100%, 1);
text-decoration: none;
gap: 0.5em;
z-index: -1;
}
.logo a {
padding: 0.5em 0.25em;
margin: -0.5em -0.25em;
}
.logo svg {
height: 40px;
width: auto;
display: block;
color: var(--theme-accent);
}
.logo .hover {
opacity: 0;
}
.logo a {
transition: transform 180ms ease-out;
}
.logo a:hover,
.logo a:focus {
outline: none;
opacity: 1;
transform: translateY(-2px);
}
.logo h1 {
font: inherit;
color: inherit;
margin: 0;
}
.nav-wrapper {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 1em;
width: 100%;
max-width: 82em;
padding: 0 1rem;
}
@media (min-width: 50em) {
header {
position: static;
padding: 2rem 0rem 0 2rem;
}
.logo {
width: auto;
margin: 0;
z-index: 0;
}
.menu-toggle {
display: none;
}
.logo {
width: auto;
}
}
/** Style Algolia */
:root {
--docsearch-primary-color: var(--theme-accent);
--docsearch-logo-color: var(--theme-text);
}
.search-item {
display: none;
position: relative;
z-index: 10;
flex-grow: 1;
padding-right: 0.7rem;
display: flex;
max-width: 200px;
}
:global(.search-item > *) {
flex-grow: 1;
}
@media (min-width: 50em) {
.search-item {
max-width: 400px;
}
}
</style>

View file

@ -1,50 +1,50 @@
.language-select {
flex-grow: 1;
width: 48px;
box-sizing: border-box;
margin: 0;
padding: 0.33em 2rem;
overflow: visible;
font-weight: 500;
font-size: 1rem;
font-family: inherit;
line-height: inherit;
background-color: var(--theme-bg);
border-color: var(--theme-text-lighter);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
outline: 0;
cursor: pointer;
transition-timing-function: ease-out;
transition-duration: 0.2s;
transition-property: border-color, color;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: 97%;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
-webkit-font-smoothing: antialiased;
-webkit-appearance: none;
flex-grow: 1;
width: 48px;
box-sizing: border-box;
margin: 0;
padding: 0.33em 2rem;
overflow: visible;
font-weight: 500;
font-size: 1rem;
font-family: inherit;
line-height: inherit;
background-color: var(--theme-bg);
border-color: var(--theme-text-lighter);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
outline: 0;
cursor: pointer;
transition-timing-function: ease-out;
transition-duration: 0.2s;
transition-property: border-color, color;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: 97%;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
-webkit-font-smoothing: antialiased;
-webkit-appearance: none;
}
.language-select-wrapper .language-select:hover,
.language-select-wrapper .language-select:focus {
color: var(--theme-text);
border-color: var(--theme-text-light);
color: var(--theme-text);
border-color: var(--theme-text-light);
}
.language-select-wrapper {
color: var(--theme-text-light);
position: relative;
color: var(--theme-text-light);
position: relative;
}
.language-select-wrapper > svg {
position: absolute;
top: 8px;
left: 8px;
pointer-events: none;
position: absolute;
top: 8px;
left: 8px;
pointer-events: none;
}
@media (min-width: 50em) {
.language-select {
width: 100%;
}
.language-select {
width: 100%;
}
}

View file

@ -3,104 +3,104 @@ import { h } from 'preact';
import './LanguageSelect.css';
const LanguageSelect: FunctionalComponent<{ lang: string }> = ({ lang }) => {
return (
<div class="language-select-wrapper">
<svg
aria-hidden="true"
focusable="false"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 88.6 77.3"
height="1.2em"
width="1.2em"
>
<path
fill="currentColor"
d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z"
/>
<path
fill="currentColor"
d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z"
/>
</svg>
<select
class="language-select"
value={lang}
aria-label="Select language"
onChange={(e) => {
const newLang = e.target.value;
if (newLang === 'en') {
window.location.pathname = `/getting-started`;
} else {
window.location.pathname = `/${newLang}/getting-started`;
}
// TODO: Preserve the current page, if it exists:
// const oldPathname = window.location.pathname;
// const oldPathnameParts = oldPathname.split('/');
// oldPathnameParts.shift();
// if (/^[a-z]{2}$/.test(oldPathnameParts[0])) {
// oldPathnameParts.shift();
// }
// if (newLang !== 'en') {
// oldPathnameParts.unshift(newLang);
// }
// window.location.pathname = '/' + oldPathnameParts.join('/');
}}
>
<option value="en">
<span>English</span>
</option>
<option value="de">
<span>Deutsch</span>
</option>
<option value="nl">
<span>Nederlands</span>
</option>
<option value="pt-br">
<span>Português do Brasil</span>
</option>
<option value="fi">
<span>Suomi</span>
</option>
<option value="es">
<span>Español</span>
</option>
<option value="zh-CN">
<span></span>
</option>
<option value="zh-TW">
<span></span>
</option>
<option value="bg">
<span>Български</span>
</option>
<option value="fr">
<span>Français</span>
</option>
<option value="bn">
<span></span>
</option>
<option value="kr">
<span></span>
</option>
<option value="ar">
<span>العربية</span>
</option>
<option value="da">
<span>Dansk</span>
</option>
<option value="ja">
<span></span>
</option>
<option value="ru">
<span>Русский</span>
</option>
<option value="it">
<span>Italiano</span>
</option>
</select>
</div>
);
return (
<div class="language-select-wrapper">
<svg
aria-hidden="true"
focusable="false"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 88.6 77.3"
height="1.2em"
width="1.2em"
>
<path
fill="currentColor"
d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z"
/>
<path
fill="currentColor"
d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z"
/>
</svg>
<select
class="language-select"
value={lang}
aria-label="Select language"
onChange={(e) => {
const newLang = e.target.value;
if (newLang === 'en') {
window.location.pathname = `/getting-started`;
} else {
window.location.pathname = `/${newLang}/getting-started`;
}
// TODO: Preserve the current page, if it exists:
// const oldPathname = window.location.pathname;
// const oldPathnameParts = oldPathname.split('/');
// oldPathnameParts.shift();
// if (/^[a-z]{2}$/.test(oldPathnameParts[0])) {
// oldPathnameParts.shift();
// }
// if (newLang !== 'en') {
// oldPathnameParts.unshift(newLang);
// }
// window.location.pathname = '/' + oldPathnameParts.join('/');
}}
>
<option value="en">
<span>English</span>
</option>
<option value="de">
<span>Deutsch</span>
</option>
<option value="nl">
<span>Nederlands</span>
</option>
<option value="pt-br">
<span>Português do Brasil</span>
</option>
<option value="fi">
<span>Suomi</span>
</option>
<option value="es">
<span>Español</span>
</option>
<option value="zh-CN">
<span></span>
</option>
<option value="zh-TW">
<span></span>
</option>
<option value="bg">
<span>Български</span>
</option>
<option value="fr">
<span>Français</span>
</option>
<option value="bn">
<span></span>
</option>
<option value="kr">
<span></span>
</option>
<option value="ar">
<span>العربية</span>
</option>
<option value="da">
<span>Dansk</span>
</option>
<option value="ja">
<span></span>
</option>
<option value="ru">
<span>Русский</span>
</option>
<option value="it">
<span>Italiano</span>
</option>
</select>
</div>
);
};
export default LanguageSelect;

View file

@ -1,75 +1,75 @@
/** Style Algolia */
:root {
--docsearch-primary-color: var(--theme-accent);
--docsearch-logo-color: var(--theme-text);
--docsearch-primary-color: var(--theme-accent);
--docsearch-logo-color: var(--theme-text);
}
.DocSearch-Modal .DocSearch-Hit a {
box-shadow: none;
border: 1px solid var(--theme-accent);
box-shadow: none;
border: 1px solid var(--theme-accent);
}
/** Style Search Bar */
.search-placeholder {
flex-grow: 1;
text-align: initial;
flex-grow: 1;
text-align: initial;
}
.search-input {
flex-grow: 1;
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 0.33em 0.5em;
overflow: visible;
font-weight: 500;
font-size: 1rem;
font-family: inherit;
line-height: inherit;
background-color: var(--theme-divider);
border-color: var(--theme-divider);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
outline: 0;
cursor: pointer;
transition-timing-function: ease-out;
transition-duration: 0.2s;
transition-property: border-color, color;
-webkit-font-smoothing: antialiased;
flex-grow: 1;
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 0.33em 0.5em;
overflow: visible;
font-weight: 500;
font-size: 1rem;
font-family: inherit;
line-height: inherit;
background-color: var(--theme-divider);
border-color: var(--theme-divider);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
outline: 0;
cursor: pointer;
transition-timing-function: ease-out;
transition-duration: 0.2s;
transition-property: border-color, color;
-webkit-font-smoothing: antialiased;
}
.search-input:hover,
.search-input:focus {
color: var(--theme-text);
border-color: var(--theme-text-light);
color: var(--theme-text);
border-color: var(--theme-text-light);
}
.search-input:hover::placeholder,
.search-input:focus::placeholder {
color: var(--theme-text-light);
color: var(--theme-text-light);
}
.search-input::placeholder {
color: var(--theme-text-light);
color: var(--theme-text-light);
}
.search-hint {
padding: 3px 5px;
display: none;
display: none;
align-items: center;
justify-content: center;
letter-spacing: 0.125em;
font-size: 13px;
font-family: var(--font-mono);
pointer-events: none;
border-color: var(--theme-text-lighter);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
line-height: 14px;
padding: 3px 5px;
display: none;
display: none;
align-items: center;
justify-content: center;
letter-spacing: 0.125em;
font-size: 13px;
font-family: var(--font-mono);
pointer-events: none;
border-color: var(--theme-text-lighter);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
line-height: 14px;
}
@media (min-width: 50em) {
.search-hint {
display: flex;
}
.search-hint {
display: flex;
}
}

View file

@ -6,88 +6,88 @@ import '@docsearch/css/dist/style.css';
import './Search.css';
const { DocSearchModal, useDocSearchKeyboardEvents } =
(docsearch as unknown as { default: typeof docsearch }).default || docsearch;
(docsearch as unknown as { default: typeof docsearch }).default || docsearch;
export default function Search(props) {
const [isOpen, setIsOpen] = useState(false);
const searchButtonRef = useRef();
const [initialQuery, setInitialQuery] = useState(null);
const { lang = 'en' } = props;
const [isOpen, setIsOpen] = useState(false);
const searchButtonRef = useRef();
const [initialQuery, setInitialQuery] = useState(null);
const { lang = 'en' } = props;
const onOpen = useCallback(() => {
setIsOpen(true);
}, [setIsOpen]);
const onOpen = useCallback(() => {
setIsOpen(true);
}, [setIsOpen]);
const onClose = useCallback(() => {
setIsOpen(false);
}, [setIsOpen]);
const onClose = useCallback(() => {
setIsOpen(false);
}, [setIsOpen]);
const onInput = useCallback(
(e) => {
setIsOpen(true);
setInitialQuery(e.key);
},
[setIsOpen, setInitialQuery]
);
const onInput = useCallback(
(e) => {
setIsOpen(true);
setInitialQuery(e.key);
},
[setIsOpen, setInitialQuery]
);
useDocSearchKeyboardEvents({
isOpen,
onOpen,
onClose,
onInput,
searchButtonRef,
});
useDocSearchKeyboardEvents({
isOpen,
onOpen,
onClose,
onInput,
searchButtonRef,
});
return (
<>
<button
type="button"
ref={searchButtonRef}
onClick={onOpen}
className="search-input"
>
<svg width="24" height="24" fill="none">
<path
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
<span className="search-placeholder">Search</span>
<span className="search-hint">
<span className="sr-only">Press </span>
<kbd>/</kbd>
<span className="sr-only"> to search</span>
</span>
</button>
{isOpen &&
createPortal(
<DocSearchModal
initialQuery={initialQuery}
initialScrollY={window.scrollY}
onClose={onClose}
indexName="astro"
apiKey="0f387260ad74f9cbf4353facd29c919c"
// Set facetFilters once Astro docs have been indexed by language
// searchParameters={{ facetFilters: [`lang:${lang}`] }}
transformItems={(items) => {
return items.map((item) => {
// We transform the absolute URL into a relative URL to
// work better on localhost, preview URLS.
const a = document.createElement('a');
a.href = item.url;
const hash = a.hash === '#overview' ? '' : a.hash;
return {
...item,
url: `${a.pathname}${hash}`,
};
});
}}
/>,
document.body
)}
</>
);
return (
<>
<button
type="button"
ref={searchButtonRef}
onClick={onOpen}
className="search-input"
>
<svg width="24" height="24" fill="none">
<path
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
<span className="search-placeholder">Search</span>
<span className="search-hint">
<span className="sr-only">Press </span>
<kbd>/</kbd>
<span className="sr-only"> to search</span>
</span>
</button>
{isOpen &&
createPortal(
<DocSearchModal
initialQuery={initialQuery}
initialScrollY={window.scrollY}
onClose={onClose}
indexName="astro"
apiKey="0f387260ad74f9cbf4353facd29c919c"
// Set facetFilters once Astro docs have been indexed by language
// searchParameters={{ facetFilters: [`lang:${lang}`] }}
transformItems={(items) => {
return items.map((item) => {
// We transform the absolute URL into a relative URL to
// work better on localhost, preview URLS.
const a = document.createElement('a');
a.href = item.url;
const hash = a.hash === '#overview' ? '' : a.hash;
return {
...item,
url: `${a.pathname}${hash}`,
};
});
}}
/>,
document.body
)}
</>
);
}

View file

@ -3,42 +3,42 @@ import { h, Fragment } from 'preact';
import { useState, useEffect } from 'preact/hooks';
const MenuToggle: FunctionalComponent = () => {
const [sidebarShown, setSidebarShown] = useState(false);
const [sidebarShown, setSidebarShown] = useState(false);
useEffect(() => {
const body = document.getElementsByTagName('body')[0];
if (sidebarShown) {
body.classList.add('mobile-sidebar-toggle');
} else {
body.classList.remove('mobile-sidebar-toggle');
}
}, [sidebarShown]);
useEffect(() => {
const body = document.getElementsByTagName('body')[0];
if (sidebarShown) {
body.classList.add('mobile-sidebar-toggle');
} else {
body.classList.remove('mobile-sidebar-toggle');
}
}, [sidebarShown]);
return (
<button
type="button"
aria-pressed={sidebarShown ? 'true' : 'false'}
id="menu-toggle"
onClick={() => setSidebarShown(!sidebarShown)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
<span className="sr-only">Toggle sidebar</span>
</button>
);
return (
<button
type="button"
aria-pressed={sidebarShown ? 'true' : 'false'}
id="menu-toggle"
onClick={() => setSidebarShown(!sidebarShown)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
<span className="sr-only">Toggle sidebar</span>
</button>
);
};
export default MenuToggle;

View file

@ -1,21 +1,22 @@
<style>
.skiplink,
.skiplink:focus,
.skiplink:focus-visible {
position: absolute;
padding: 0.25em;
font-size: larger;
top: 0;
left: 0;
right: 0;
z-index: 9;
display: block;
text-align: center;
background-color: var(--theme-text-accent);
color: var(--theme-bg);
border-radius: 0.25em;
outline: var(--theme-bg) solid 1px;
outline-offset: 0;
}
</style>
<a href="#article" class="sr-only skiplink"><span>Skip to Content</span></a>
<style>
.skiplink,
.skiplink:focus,
.skiplink:focus-visible {
position: absolute;
padding: 0.25em;
font-size: larger;
top: 0;
left: 0;
right: 0;
z-index: 9;
display: block;
text-align: center;
background-color: var(--theme-text-accent);
color: var(--theme-bg);
border-radius: 0.25em;
outline: var(--theme-bg) solid 1px;
outline-offset: 0;
}
</style>

View file

@ -1,153 +1,186 @@
---
import { SIDEBAR } from '../../config.ts';
import { getLanguageFromURL, removeLeadingSlash, removeTrailingSlash } from '../../util.ts';
const {currentPage} = Astro.props;
import {
getLanguageFromURL,
removeLeadingSlash,
removeTrailingSlash,
} from '../../util.ts';
const { currentPage } = Astro.props;
// Get the slug w/o a leading or trailing slash
const currentPageMatch = removeLeadingSlash(removeTrailingSlash(currentPage));
const langCode = getLanguageFromURL(currentPage);
// SIDEBAR is a flat array. Group it by sections to properly render.
const sidebarSections = SIDEBAR[langCode].reduce((col, item) => {
if (item.header) {
col.push({...item, children: []});
} else {
col[col.length-1].children.push(item);
}
return col;
if (item.header) {
col.push({ ...item, children: [] });
} else {
col[col.length - 1].children.push(item);
}
return col;
}, []);
---
<nav aria-labelledby="grid-left">
<ul class="nav-groups">
<li>
<div class="nav-group">
<h2 class="sponsors-title">Sponsored by</h2>
<div class="sponsors">
<a href="https://www.netlify.com/" aria-label="Go to Netlify website">
<svg class="sponsor-logo__netlify" viewBox="0 0 147 40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><radialGradient id="netlify-gradient" cx="-779.0521" cy="1839.7205" gradientTransform="matrix(0 38.301 44.1228 0 -81154.2578 29839.2441)" gradientUnits="userSpaceOnUse" r="1.0011"><stop offset="0" stop-color="#20c6b7"/><stop offset="1" stop-color="#4d9abf"/></radialGradient><path clip-rule="evenodd" d="m53.37 12.98.12 2.2c1.4-1.7 3.24-2.55 5.53-2.55 3.95 0 5.96 2.27 6.03 6.8v12.57h-4.26v-12.32c0-1.21-.26-2.1-.78-2.68s-1.37-.87-2.55-.87c-1.72 0-3 .78-3.84 2.34v13.53h-4.26v-19.02zm24.38 19.37c-2.7 0-4.89-.85-6.57-2.56-1.68-1.7-2.52-3.98-2.52-6.81v-.53c0-1.9.36-3.59 1.1-5.09.73-1.49 1.76-2.66 3.08-3.49s2.79-1.25 4.42-1.25c2.58 0 4.58.83 5.99 2.48s2.11 3.99 2.11 7.01v1.72h-12.4c.13 1.57.65 2.81 1.57 3.73s2.07 1.37 3.46 1.37c1.95 0 3.54-.79 4.77-2.37l2.3 2.2c-.76 1.14-1.77 2.02-3.04 2.65s-2.69.94-4.27.94zm-.51-16.29c-1.17 0-2.11.41-2.83 1.23s-1.18 1.96-1.38 3.43h8.12v-.32c-.09-1.43-.47-2.51-1.14-3.24-.67-.74-1.59-1.1-2.77-1.1zm16.76-7.7v4.62h3.35v3.16h-3.35v10.62c0 .73.14 1.25.43 1.57s.8.48 1.54.48c.5 0 1-.06 1.49-.18v3.31c-.97.27-1.9.4-2.81.4-3.27 0-4.91-1.81-4.91-5.43v-10.77h-3.12v-3.16h3.12v-4.63zm11.14 23.64h-4.26v-27h4.26zm9.17 0h-4.26v-19.02h4.26zm-4.52-23.96c0-.65.21-1.2.62-1.63.42-.43 1.01-.65 1.78-.65s1.37.22 1.79.65.63.98.63 1.64c0 .64-.21 1.18-.63 1.61s-1.02.64-1.79.64-1.36-.21-1.78-.64c-.41-.44-.62-.98-.62-1.62zm10.66 23.96v-15.86h-2.89v-3.16h2.89v-1.74c0-2.11.58-3.74 1.75-4.89s2.81-1.72 4.91-1.72c.75 0 1.54.11 2.39.32l-.1 3.34c-.54-.1-1.08-.15-1.63-.14-2.04 0-3.05 1.05-3.05 3.15v1.69h3.86v3.16h-3.86v15.85zm17.87-6.12 3.86-12.9h4.54l-7.54 21.9c-1.16 3.2-3.12 4.8-5.89 4.8-.62 0-1.3-.11-2.05-.32v-3.31l.81.05c1.07 0 1.88-.2 2.43-.59.54-.39.97-1.05 1.29-1.98l.61-1.64-6.66-18.93h4.6z" fill-rule="evenodd"/><path d="m27.89 14.14-.01-.01c-.01 0-.02-.01-.02-.01-.02-.02-.03-.06-.03-.09l.77-4.73 3.62 3.63-3.77 1.6c-.01 0-.02.01-.03.01h-.02s-.01-.01-.02-.02c-.14-.16-.31-.29-.49-.38zm5.26-.29 3.88 3.88c.81.81 1.21 1.21 1.35 1.67.02.07.04.14.05.21l-9.26-3.92s-.01 0-.01-.01c-.04-.02-.08-.03-.08-.07s.04-.06.08-.07l.01-.01zm5.12 7c-.2.38-.59.77-1.25 1.43l-4.37 4.37-5.65-1.18-.03-.01c-.05-.01-.1-.02-.1-.06-.04-.47-.28-.9-.66-1.19-.02-.02-.02-.06-.01-.09v-.01l1.06-6.53v-.02c.01-.05.01-.11.06-.11.46-.06.88-.3 1.16-.67.01-.01.01-.02.03-.03.03-.01.07 0 .1.01zm-6.62 6.8-7.19 7.19 1.23-7.56v-.01c0-.01 0-.02.01-.03.01-.02.04-.03.06-.04h.01c.27-.11.51-.29.69-.52.02-.03.05-.06.09-.06h.03zm-8.71 8.71-.81.81-8.95-12.94s-.01-.01-.01-.01c-.01-.02-.03-.04-.03-.06s.01-.03.02-.04l.01-.01c.03-.04.05-.08.07-.12l.02-.03c.01-.02.03-.05.05-.06s.05-.01.07 0l9.92 2.05c.03 0 .05.02.08.03.01.01.02.03.02.04.14.53.52.97 1.03 1.17.03.01.02.05 0 .08-.01.01-.01.03-.01.05-.12.74-1.19 7.27-1.48 9.04zm-1.69 1.69c-.6.59-.95.9-1.35 1.03-.39.12-.81.12-1.21 0-.47-.15-.87-.55-1.67-1.36l-8.99-8.99 2.35-3.64c.01-.02.02-.03.04-.05s.06-.01.09 0c.54.16 1.12.13 1.64-.08.03-.01.05-.02.07 0l.03.03zm-14.09-10.19-2.06-2.06 4.07-1.74c.01 0 .02-.01.03-.01.03 0 .05.03.07.07.04.06.08.12.13.18l.01.02c.01.02 0 .03-.01.05zm-2.98-2.97-2.61-2.61c-.44-.44-.77-.77-.99-1.04l7.94 1.65h.03c.05.01.1.02.1.06 0 .05-.06.07-.11.09l-.02.01zm-4.05-5c.01-.17.04-.33.09-.5.15-.47.55-.87 1.36-1.67l3.34-3.34c1.54 2.23 3.08 4.46 4.63 6.69.03.04.06.08.03.11-.15.16-.29.34-.4.53-.01.02-.03.05-.05.06-.01.01-.03 0-.04 0zm5.68-6.4 4.49-4.49c.42.19 1.96.83 3.33 1.41 1.04.44 1.99.84 2.29.97.03.01.06.02.07.05.01.02 0 .04 0 .06-.14.66.05 1.35.52 1.83.03.03 0 .07-.03.11l-.01.02-4.56 7.06c-.01.02-.02.04-.04.05s-.06.01-.09 0c-.18-.05-.36-.07-.54-.07-.16 0-.34.03-.52.06-.02 0-.04.01-.05 0-.02-.01-.03-.03-.05-.05zm5.4-5.4 5.81-5.81c.81-.81 1.21-1.21 1.67-1.36.39-.12.81-.12 1.21 0 .47.15.87.55 1.67 1.36l1.26 1.26-4.14 6.4c-.01.02-.02.03-.04.05s-.06.01-.09 0c-.66-.2-1.38-.06-1.92.37-.03.03-.07.01-.1 0-.53-.24-4.73-2.01-5.33-2.27zm12.5-3.67 3.82 3.82-.92 5.7v.02c0 .01 0 .03-.01.04-.01.02-.03.02-.05.03-.2.06-.38.15-.55.27-.01.01-.01.01-.02.02s-.02.02-.04.02c-.01 0-.03 0-.04-.01l-5.82-2.47-.01-.01c-.04-.02-.08-.03-.08-.07-.03-.32-.14-.64-.31-.91-.03-.05-.06-.09-.03-.14zm-3.93 8.6 5.45 2.31c.03.01.06.03.08.06.01.02.01.04 0 .06-.02.08-.03.17-.03.26v.15c0 .04-.04.05-.08.07h-.01c-.86.37-12.13 5.17-12.15 5.17s-.03 0-.05-.02c-.03-.03 0-.07.03-.11 0-.01.01-.01.01-.02l4.48-6.94.01-.01c.03-.04.06-.09.1-.09l.05.01c.1.01.19.03.28.03.68 0 1.31-.33 1.69-.9.01-.02.02-.03.03-.04.04-.01.08 0 .11.01zm-6.25 9.19 12.28-5.24s.02 0 .03.02c.07.07.12.11.18.15l.03.02c.02.01.05.03.05.06v.02l-1.05 6.46v.03c-.01.05-.01.11-.06.11-.57.04-1.08.36-1.37.85v.01c-.01.02-.03.05-.05.06s-.05.01-.07 0l-9.79-2.02c-.02-.02-.16-.53-.18-.53z" fill="url(#netlify-gradient)"/></svg>
</a>
</div>
</div>
</li>
{sidebarSections.map(section => (
<li>
<div class="nav-group">
<h2 class="nav-group-title">{section.text}</h2>
<ul>
{section.children.map(child => (
<li class="nav-link"><a href={`${Astro.site.pathname}${child.link}`} aria-current={`${currentPageMatch === child.link ? 'page' : 'false'}`}>{child.text}</a></li>
))}
</ul>
</div>
</li>
))}
</ul>
<ul class="nav-groups">
<li>
<div class="nav-group">
<h2 class="sponsors-title">Sponsored by</h2>
<div class="sponsors">
<a href="https://www.netlify.com/" aria-label="Go to Netlify website">
<svg
class="sponsor-logo__netlify"
viewBox="0 0 147 40"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
><radialGradient
id="netlify-gradient"
cx="-779.0521"
cy="1839.7205"
gradientTransform="matrix(0 38.301 44.1228 0 -81154.2578 29839.2441)"
gradientUnits="userSpaceOnUse"
r="1.0011"
><stop offset="0" stop-color="#20c6b7"></stop><stop
offset="1"
stop-color="#4d9abf"></stop></radialGradient
><path
clip-rule="evenodd"
d="m53.37 12.98.12 2.2c1.4-1.7 3.24-2.55 5.53-2.55 3.95 0 5.96 2.27 6.03 6.8v12.57h-4.26v-12.32c0-1.21-.26-2.1-.78-2.68s-1.37-.87-2.55-.87c-1.72 0-3 .78-3.84 2.34v13.53h-4.26v-19.02zm24.38 19.37c-2.7 0-4.89-.85-6.57-2.56-1.68-1.7-2.52-3.98-2.52-6.81v-.53c0-1.9.36-3.59 1.1-5.09.73-1.49 1.76-2.66 3.08-3.49s2.79-1.25 4.42-1.25c2.58 0 4.58.83 5.99 2.48s2.11 3.99 2.11 7.01v1.72h-12.4c.13 1.57.65 2.81 1.57 3.73s2.07 1.37 3.46 1.37c1.95 0 3.54-.79 4.77-2.37l2.3 2.2c-.76 1.14-1.77 2.02-3.04 2.65s-2.69.94-4.27.94zm-.51-16.29c-1.17 0-2.11.41-2.83 1.23s-1.18 1.96-1.38 3.43h8.12v-.32c-.09-1.43-.47-2.51-1.14-3.24-.67-.74-1.59-1.1-2.77-1.1zm16.76-7.7v4.62h3.35v3.16h-3.35v10.62c0 .73.14 1.25.43 1.57s.8.48 1.54.48c.5 0 1-.06 1.49-.18v3.31c-.97.27-1.9.4-2.81.4-3.27 0-4.91-1.81-4.91-5.43v-10.77h-3.12v-3.16h3.12v-4.63zm11.14 23.64h-4.26v-27h4.26zm9.17 0h-4.26v-19.02h4.26zm-4.52-23.96c0-.65.21-1.2.62-1.63.42-.43 1.01-.65 1.78-.65s1.37.22 1.79.65.63.98.63 1.64c0 .64-.21 1.18-.63 1.61s-1.02.64-1.79.64-1.36-.21-1.78-.64c-.41-.44-.62-.98-.62-1.62zm10.66 23.96v-15.86h-2.89v-3.16h2.89v-1.74c0-2.11.58-3.74 1.75-4.89s2.81-1.72 4.91-1.72c.75 0 1.54.11 2.39.32l-.1 3.34c-.54-.1-1.08-.15-1.63-.14-2.04 0-3.05 1.05-3.05 3.15v1.69h3.86v3.16h-3.86v15.85zm17.87-6.12 3.86-12.9h4.54l-7.54 21.9c-1.16 3.2-3.12 4.8-5.89 4.8-.62 0-1.3-.11-2.05-.32v-3.31l.81.05c1.07 0 1.88-.2 2.43-.59.54-.39.97-1.05 1.29-1.98l.61-1.64-6.66-18.93h4.6z"
fill-rule="evenodd"></path><path
d="m27.89 14.14-.01-.01c-.01 0-.02-.01-.02-.01-.02-.02-.03-.06-.03-.09l.77-4.73 3.62 3.63-3.77 1.6c-.01 0-.02.01-.03.01h-.02s-.01-.01-.02-.02c-.14-.16-.31-.29-.49-.38zm5.26-.29 3.88 3.88c.81.81 1.21 1.21 1.35 1.67.02.07.04.14.05.21l-9.26-3.92s-.01 0-.01-.01c-.04-.02-.08-.03-.08-.07s.04-.06.08-.07l.01-.01zm5.12 7c-.2.38-.59.77-1.25 1.43l-4.37 4.37-5.65-1.18-.03-.01c-.05-.01-.1-.02-.1-.06-.04-.47-.28-.9-.66-1.19-.02-.02-.02-.06-.01-.09v-.01l1.06-6.53v-.02c.01-.05.01-.11.06-.11.46-.06.88-.3 1.16-.67.01-.01.01-.02.03-.03.03-.01.07 0 .1.01zm-6.62 6.8-7.19 7.19 1.23-7.56v-.01c0-.01 0-.02.01-.03.01-.02.04-.03.06-.04h.01c.27-.11.51-.29.69-.52.02-.03.05-.06.09-.06h.03zm-8.71 8.71-.81.81-8.95-12.94s-.01-.01-.01-.01c-.01-.02-.03-.04-.03-.06s.01-.03.02-.04l.01-.01c.03-.04.05-.08.07-.12l.02-.03c.01-.02.03-.05.05-.06s.05-.01.07 0l9.92 2.05c.03 0 .05.02.08.03.01.01.02.03.02.04.14.53.52.97 1.03 1.17.03.01.02.05 0 .08-.01.01-.01.03-.01.05-.12.74-1.19 7.27-1.48 9.04zm-1.69 1.69c-.6.59-.95.9-1.35 1.03-.39.12-.81.12-1.21 0-.47-.15-.87-.55-1.67-1.36l-8.99-8.99 2.35-3.64c.01-.02.02-.03.04-.05s.06-.01.09 0c.54.16 1.12.13 1.64-.08.03-.01.05-.02.07 0l.03.03zm-14.09-10.19-2.06-2.06 4.07-1.74c.01 0 .02-.01.03-.01.03 0 .05.03.07.07.04.06.08.12.13.18l.01.02c.01.02 0 .03-.01.05zm-2.98-2.97-2.61-2.61c-.44-.44-.77-.77-.99-1.04l7.94 1.65h.03c.05.01.1.02.1.06 0 .05-.06.07-.11.09l-.02.01zm-4.05-5c.01-.17.04-.33.09-.5.15-.47.55-.87 1.36-1.67l3.34-3.34c1.54 2.23 3.08 4.46 4.63 6.69.03.04.06.08.03.11-.15.16-.29.34-.4.53-.01.02-.03.05-.05.06-.01.01-.03 0-.04 0zm5.68-6.4 4.49-4.49c.42.19 1.96.83 3.33 1.41 1.04.44 1.99.84 2.29.97.03.01.06.02.07.05.01.02 0 .04 0 .06-.14.66.05 1.35.52 1.83.03.03 0 .07-.03.11l-.01.02-4.56 7.06c-.01.02-.02.04-.04.05s-.06.01-.09 0c-.18-.05-.36-.07-.54-.07-.16 0-.34.03-.52.06-.02 0-.04.01-.05 0-.02-.01-.03-.03-.05-.05zm5.4-5.4 5.81-5.81c.81-.81 1.21-1.21 1.67-1.36.39-.12.81-.12 1.21 0 .47.15.87.55 1.67 1.36l1.26 1.26-4.14 6.4c-.01.02-.02.03-.04.05s-.06.01-.09 0c-.66-.2-1.38-.06-1.92.37-.03.03-.07.01-.1 0-.53-.24-4.73-2.01-5.33-2.27zm12.5-3.67 3.82 3.82-.92 5.7v.02c0 .01 0 .03-.01.04-.01.02-.03.02-.05.03-.2.06-.38.15-.55.27-.01.01-.01.01-.02.02s-.02.02-.04.02c-.01 0-.03 0-.04-.01l-5.82-2.47-.01-.01c-.04-.02-.08-.03-.08-.07-.03-.32-.14-.64-.31-.91-.03-.05-.06-.09-.03-.14zm-3.93 8.6 5.45 2.31c.03.01.06.03.08.06.01.02.01.04 0 .06-.02.08-.03.17-.03.26v.15c0 .04-.04.05-.08.07h-.01c-.86.37-12.13 5.17-12.15 5.17s-.03 0-.05-.02c-.03-.03 0-.07.03-.11 0-.01.01-.01.01-.02l4.48-6.94.01-.01c.03-.04.06-.09.1-.09l.05.01c.1.01.19.03.28.03.68 0 1.31-.33 1.69-.9.01-.02.02-.03.03-.04.04-.01.08 0 .11.01zm-6.25 9.19 12.28-5.24s.02 0 .03.02c.07.07.12.11.18.15l.03.02c.02.01.05.03.05.06v.02l-1.05 6.46v.03c-.01.05-.01.11-.06.11-.57.04-1.08.36-1.37.85v.01c-.01.02-.03.05-.05.06s-.05.01-.07 0l-9.79-2.02c-.02-.02-.16-.53-.18-.53z"
fill="url(#netlify-gradient)"></path></svg
>
</a>
</div>
</div>
</li>
{sidebarSections.map((section) => (
<li>
<div class="nav-group">
<h2 class="nav-group-title">{section.text}</h2>
<ul>
{section.children.map((child) => (
<li class="nav-link">
<a
href={`${Astro.site.pathname}${child.link}`}
aria-current={`${
currentPageMatch === child.link ? 'page' : 'false'
}`}
>
{child.text}
</a>
</li>
))}
</ul>
</div>
</li>
))}
</ul>
</nav>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
var target = document.querySelector('[aria-current="page"]');
if (target && (target.offsetTop > (window.innerHeight - 100))) {
document.querySelector('.nav-groups').scrollTop = target.offsetTop;
}
});
window.addEventListener('DOMContentLoaded', (event) => {
var target = document.querySelector('[aria-current="page"]');
if (target && target.offsetTop > window.innerHeight - 100) {
document.querySelector('.nav-groups').scrollTop = target.offsetTop;
}
});
</script>
<style lang="scss">
nav {
width: 100%;
margin-right: 1rem;
}
.nav-groups {
height: 100%;
padding: 2rem 0;
overflow-x: visible;
overflow-y: auto;
max-height: 100vh;
nav {
width: 100%;
margin-right: 1rem;
}
.nav-groups {
height: 100%;
padding: 2rem 0;
overflow-x: visible;
overflow-y: auto;
max-height: 100vh;
> li + li {
margin-top: 1.75rem;
}
> li + li {
margin-top: 1.75rem;
}
> :first-child {
padding-top: var(--doc-padding);
}
> :first-child {
padding-top: var(--doc-padding);
}
> :last-child {
padding-bottom: 2rem;
margin-bottom: var(--theme-navbar-height);
}
> :last-child {
padding-bottom: 2rem;
margin-bottom: var(--theme-navbar-height);
}
@media (min-width: 50em) {
padding: 0;
}
}
@media (min-width: 50em) {
padding: 0;
}
}
.nav-group-title {
font-size: 1.0rem;
font-weight: 700;
padding: 0.1rem 1rem;
text-transform: uppercase;
margin-bottom: 0.5rem;
}
.nav-group-title {
font-size: 1rem;
font-weight: 700;
padding: 0.1rem 1rem;
text-transform: uppercase;
margin-bottom: 0.5rem;
}
.nav-link a {
font-size: 1.0rem;
margin: 1px;
padding: 0.3rem 1rem;
font: inherit;
color: inherit;
text-decoration: none;
display: block;
.nav-link a {
font-size: 1rem;
margin: 1px;
padding: 0.3rem 1rem;
font: inherit;
color: inherit;
text-decoration: none;
display: block;
&:hover,
&:focus {
background-color: var(--theme-bg-hover);
}
&:hover,
&:focus {
background-color: var(--theme-bg-hover);
}
&[aria-current="page"] {
color: var(--theme-text-accent);
background-color: var(--theme-bg-accent);
font-weight: 600;
}
}
&[aria-current='page'] {
color: var(--theme-text-accent);
background-color: var(--theme-bg-accent);
font-weight: 600;
}
}
:global(:root.theme-dark) .nav-link a[aria-current="page"] {
color: hsla(var(--color-base-white), 100%, 1);
}
:global(:root.theme-dark) .nav-link a[aria-current='page'] {
color: hsla(var(--color-base-white), 100%, 1);
}
.sponsors {
display: grid;
padding-left: 1rem;
padding-top: 0.25rem;
margin-bottom: -0.375rem; // logo overshoot creates extra perceived space
grid-gap: 0.5rem;
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
.sponsors {
display: grid;
padding-left: 1rem;
padding-top: 0.25rem;
margin-bottom: -0.375rem; // logo overshoot creates extra perceived space
grid-gap: 0.5rem;
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
svg {
color: var(--theme-text);
fill: currentColor;
}
}
svg {
color: var(--theme-text);
fill: currentColor;
}
}
.sponsor-logo__netlify {
width: 90px;
}
.sponsor-logo__netlify {
width: 90px;
}
.sponsor-logo__vercel {
width: 90px;
}
:global(:root.theme-dark .sponsors-title) {
color: hsl(var(--color-base-gray), 75%);
}
.sponsors-title {
color: hsl(var(--color-base-gray), 25%);
font-size: 0.8em;
font-weight: 300;
letter-spacing: 0.0625em;
margin: 0 0 0.5rem;
padding-left: 1rem;
text-transform: uppercase;
}
.sponsor-logo__vercel {
width: 90px;
}
:global(:root.theme-dark .sponsors-title) {
color: hsl(var(--color-base-gray), 75%);
}
.sponsors-title {
color: hsl(var(--color-base-gray), 25%);
font-size: 0.8em;
font-weight: 300;
letter-spacing: 0.0625em;
margin: 0 0 0.5rem;
padding-left: 1rem;
text-transform: uppercase;
}
</style>

View file

@ -1,59 +1,78 @@
---
import MoreMenu from '../RightSidebar/MoreMenu.astro';
import TableOfContents from '../RightSidebar/TableOfContents.tsx';
import {getLanguageFromURL} from '../../util.ts';
import {SIDEBAR} from '../../config.ts';
const {content, githubEditUrl, currentPage} = Astro.props;
import { getLanguageFromURL } from '../../util.ts';
import { SIDEBAR } from '../../config.ts';
const { content, githubEditUrl, currentPage } = Astro.props;
const title = content.title;
const headers = content.astro?.headers;
const langCode = getLanguageFromURL(currentPage);
const links = SIDEBAR[langCode].filter(x => x.link && typeof x.header === 'undefined');
const links = SIDEBAR[langCode].filter(
(x) => x.link && typeof x.header === 'undefined'
);
// handle cases with a trailing slash or not
const index = links.findIndex(x => `/${x.link}/` === currentPage || `/${x.link}` === currentPage);
const next = index !== -1 ? (index === links.length - 1 ? null : links[index + 1]) : null;
const index = links.findIndex(
(x) => `/${x.link}/` === currentPage || `/${x.link}` === currentPage
);
const next =
index !== -1 ? (index === links.length - 1 ? null : links[index + 1]) : null;
const previous = index !== -1 ? (index === 0 ? null : links[index - 1]) : null;
---
<style>
.content {
padding: 0;
max-width: 75ch;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.content > section {
margin-bottom: 4rem;
}
.block {
display: block;
}
@media (min-width: 50em) {
.sm\:hidden {
display: none;
}
}
</style>
<article id="article" class="content">
<section class="main-section">
<h1 class="content-title" id="overview">{title}</h1>
{headers && <nav class="block sm:hidden">
<TableOfContents client:media="(max-width: 50em)" headers={headers}/>
</nav>}
<slot />
</section>
<nav class="block sm:hidden">
<MoreMenu editHref={githubEditUrl}/>
</nav>
{
(previous || next) && <aside>
{
previous && <div>Previous Article: <a rel="prev" href={new URL(previous.link, Astro.site).pathname}>{previous.text}</a></div>
}
{
next && <div>Next Article: <a rel="next" href={new URL(next.link, Astro.site).pathname}>{next.text}</a></div>
}
</aside>
}
<section class="main-section">
<h1 class="content-title" id="overview">{title}</h1>
{headers && (
<nav class="block sm:hidden">
<TableOfContents client:media="(max-width: 50em)" headers={headers} />
</nav>
)}
<slot />
</section>
<nav class="block sm:hidden">
<MoreMenu editHref={githubEditUrl} />
</nav>
{(previous || next) && (
<aside>
{previous && (
<div>
Previous Article:{' '}
<a rel="prev" href={new URL(previous.link, Astro.site).pathname}>
{previous.text}
</a>
</div>
)}
{next && (
<div>
Next Article:{' '}
<a rel="next" href={new URL(next.link, Astro.site).pathname}>
{next.text}
</a>
</div>
)}
</aside>
)}
</article>
<style>
.content {
padding: 0;
max-width: 75ch;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.content > section {
margin-bottom: 4rem;
}
.block {
display: block;
}
@media (min-width: 50em) {
.sm\:hidden {
display: none;
}
}
</style>

View file

@ -1,68 +1,91 @@
---
import ThemeToggleButton from './ThemeToggleButton.tsx';
const {editHref} = Astro.props;
const { editHref } = Astro.props;
---
<style>
.edit-on-github {
text-decoration: none;
font: inherit;
color: inherit;
font-size: 1rem;
}
</style>
<h2 class="heading">More</h2>
<ul>
<li class={`header-link depth-2`}>
<a class="edit-on-github" href={editHref} target="_blank">
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="pen"
class="svg-inline--fa fa-pen fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
height="1em"
width="1em"
>
<path
fill="currentColor"
d="M290.74 93.24l128.02 128.02-277.99 277.99-114.14 12.6C11.35 513.54-1.56 500.62.14 485.34l12.7-114.22 277.9-277.88zm207.2-19.06l-60.11-60.11c-18.75-18.75-49.16-18.75-67.91 0l-56.55 56.55 128.02 128.02 56.55-56.55c18.75-18.76 18.75-49.16 0-67.91z"
></path>
</svg>
<span>Edit this page</span>
</a>
</li>
<li class={`header-link depth-2`}>
<a href="https://github.com/withastro/astro/blob/main/CONTRIBUTING.md#translations" target="_blank">
<svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88.6 77.3" height="1.24em" width="1.24em" style="margin: -2px;"> <path fill="currentColor" d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z" /> <path fill="currentColor" d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z" /> </svg>
<span>Translate this page</span>
</a>
</li>
<li class={`header-link depth-2`}>
<a href="https://astro.build/chat" target="_blank">
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="comment-alt"
class="svg-inline--fa fa-comment-alt fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
height="1em"
width="1em"
>
<path
fill="currentColor"
d="M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 9.8 11.2 15.5 19.1 9.7L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64z"
></path>
</svg>
<span>Join our community</span>
</a>
</li>
<li class={`header-link depth-2`}>
<a class="edit-on-github" href={editHref} target="_blank">
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="pen"
class="svg-inline--fa fa-pen fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
height="1em"
width="1em"
>
<path
fill="currentColor"
d="M290.74 93.24l128.02 128.02-277.99 277.99-114.14 12.6C11.35 513.54-1.56 500.62.14 485.34l12.7-114.22 277.9-277.88zm207.2-19.06l-60.11-60.11c-18.75-18.75-49.16-18.75-67.91 0l-56.55 56.55 128.02 128.02 56.55-56.55c18.75-18.76 18.75-49.16 0-67.91z"
></path>
</svg>
<span>Edit this page</span>
</a>
</li>
<li class={`header-link depth-2`}>
<a
href="https://github.com/withastro/astro/blob/main/CONTRIBUTING.md#translations"
target="_blank"
>
<svg
aria-hidden="true"
focusable="false"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 88.6 77.3"
height="1.24em"
width="1.24em"
style="margin: -2px;"
>
<path
fill="currentColor"
d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z"
></path>
<path
fill="currentColor"
d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z"
></path>
</svg>
<span>Translate this page</span>
</a>
</li>
<li class={`header-link depth-2`}>
<a href="https://astro.build/chat" target="_blank">
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="comment-alt"
class="svg-inline--fa fa-comment-alt fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
height="1em"
width="1em"
>
<path
fill="currentColor"
d="M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 9.8 11.2 15.5 19.1 9.7L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64z"
></path>
</svg>
<span>Join our community</span>
</a>
</li>
</ul>
<div style="margin: 2rem 0; text-align: center;">
<ThemeToggleButton client:visible />
<ThemeToggleButton client:visible />
</div>
<style>
.edit-on-github {
text-decoration: none;
font: inherit;
color: inherit;
font-size: 1rem;
}
</style>

View file

@ -1,25 +1,29 @@
---
import TableOfContents from './TableOfContents.tsx';
import MoreMenu from './MoreMenu.astro';
const {content, githubEditUrl} = Astro.props;
const { content, githubEditUrl } = Astro.props;
const headers = content.astro?.headers;
---
<style>
.sidebar-nav {
width: 100%;
position: sticky;
top: 0;
}
.sidebar-nav-inner {
height: 100%;
padding: 0;
padding-top: var(--doc-padding);
overflow: auto;
}
</style>
<nav class="sidebar-nav" aria-labelledby="grid-right">
<div class="sidebar-nav-inner">
{headers && <TableOfContents client:media="(min-width: 50em)" headers={headers} />}
<MoreMenu editHref={githubEditUrl} />
</div>
<div class="sidebar-nav-inner">
{headers && (
<TableOfContents client:media="(min-width: 50em)" headers={headers} />
)}
<MoreMenu editHref={githubEditUrl} />
</div>
</nav>
<style>
.sidebar-nav {
width: 100%;
position: sticky;
top: 0;
}
.sidebar-nav-inner {
height: 100%;
padding: 0;
padding-top: var(--doc-padding);
overflow: auto;
}
</style>

View file

@ -3,53 +3,53 @@ import { h, Fragment } from 'preact';
import { useState, useEffect, useRef } from 'preact/hooks';
const TableOfContents: FunctionalComponent<{ headers: any[] }> = ({
headers = [],
headers = [],
}) => {
const itemOffsets = useRef([]);
const [activeId, setActiveId] = useState<string>(undefined);
const itemOffsets = useRef([]);
const [activeId, setActiveId] = useState<string>(undefined);
useEffect(() => {
const getItemOffsets = () => {
const titles = document.querySelectorAll('article :is(h1, h2, h3, h4)');
itemOffsets.current = Array.from(titles).map((title) => ({
id: title.id,
topOffset: title.getBoundingClientRect().top + window.scrollY,
}));
};
useEffect(() => {
const getItemOffsets = () => {
const titles = document.querySelectorAll('article :is(h1, h2, h3, h4)');
itemOffsets.current = Array.from(titles).map((title) => ({
id: title.id,
topOffset: title.getBoundingClientRect().top + window.scrollY,
}));
};
getItemOffsets();
window.addEventListener('resize', getItemOffsets);
getItemOffsets();
window.addEventListener('resize', getItemOffsets);
return () => {
window.removeEventListener('resize', getItemOffsets);
};
}, []);
return () => {
window.removeEventListener('resize', getItemOffsets);
};
}, []);
return (
<>
<h2 class="heading">On this page</h2>
<ul>
<li
class={`header-link depth-2 ${
activeId === 'overview' ? 'active' : ''
}`.trim()}
>
<a href="#overview">Overview</a>
</li>
{headers
.filter(({ depth }) => depth > 1 && depth < 4)
.map((header) => (
<li
class={`header-link depth-${header.depth} ${
activeId === header.slug ? 'active' : ''
}`.trim()}
>
<a href={`#${header.slug}`}>{header.text}</a>
</li>
))}
</ul>
</>
);
return (
<>
<h2 class="heading">On this page</h2>
<ul>
<li
class={`header-link depth-2 ${
activeId === 'overview' ? 'active' : ''
}`.trim()}
>
<a href="#overview">Overview</a>
</li>
{headers
.filter(({ depth }) => depth > 1 && depth < 4)
.map((header) => (
<li
class={`header-link depth-${header.depth} ${
activeId === header.slug ? 'active' : ''
}`.trim()}
>
<a href={`#${header.slug}`}>{header.text}</a>
</li>
))}
</ul>
</>
);
};
export default TableOfContents;

View file

@ -1,38 +1,38 @@
.theme-toggle {
display: inline-flex;
align-items: center;
gap: 0.25em;
padding: 0.33em 0.67em;
border-radius: 99em;
background-color: var(--theme-code-inline-bg);
display: inline-flex;
align-items: center;
gap: 0.25em;
padding: 0.33em 0.67em;
border-radius: 99em;
background-color: var(--theme-code-inline-bg);
}
.theme-toggle > label:focus-within {
outline: 2px solid transparent;
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
outline: 2px solid transparent;
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
}
.theme-toggle > label {
color: var(--theme-code-inline-text);
position: relative;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.5;
cursor: pointer;
color: var(--theme-code-inline-text);
position: relative;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.5;
cursor: pointer;
}
.theme-toggle .checked {
color: var(--theme-accent);
opacity: 1;
color: var(--theme-accent);
opacity: 1;
}
input[name='theme-toggle'] {
position: absolute;
opacity: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
position: absolute;
opacity: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
}

View file

@ -6,78 +6,78 @@ import './ThemeToggleButton.css';
const themes = ['light', 'dark'];
const icons = [
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
clip-rule="evenodd"
/>
</svg>,
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>,
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
clip-rule="evenodd"
/>
</svg>,
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>,
];
function ThemeToggle() {
const [theme, setTheme] = useState(() => {
if (import.meta.env.SSR) {
return undefined;
}
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
});
const [theme, setTheme] = useState(() => {
if (import.meta.env.SSR) {
return undefined;
}
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
});
useEffect(() => {
const root = document.documentElement;
if (theme === 'light') {
root.classList.remove('theme-dark');
} else {
root.classList.add('theme-dark');
}
}, [theme]);
useEffect(() => {
const root = document.documentElement;
if (theme === 'light') {
root.classList.remove('theme-dark');
} else {
root.classList.add('theme-dark');
}
}, [theme]);
return (
<div class="theme-toggle">
{themes.map((t, i) => {
const icon = icons[i];
const checked = t === theme;
return (
<label class={checked ? 'checked' : ''}>
{icon}
<input
type="radio"
name="theme-toggle"
checked={checked}
value={t}
title={`Use ${t} theme`}
aria-label={`Use ${t} theme`}
onChange={() => {
localStorage.setItem('theme', t);
setTheme(t);
}}
/>
</label>
);
})}
</div>
);
return (
<div class="theme-toggle">
{themes.map((t, i) => {
const icon = icons[i];
const checked = t === theme;
return (
<label class={checked ? 'checked' : ''}>
{icon}
<input
type="radio"
name="theme-toggle"
checked={checked}
value={t}
title={`Use ${t} theme`}
aria-label={`Use ${t} theme`}
onChange={() => {
localStorage.setItem('theme', t);
setTheme(t);
}}
/>
</label>
);
})}
</div>
);
}
export default ThemeToggle;

View file

@ -1,204 +1,204 @@
export const SIDEBAR = {
en: [
{ text: 'Setup', header: true },
{ text: 'Getting Started', link: 'getting-started' },
{ text: 'Quickstart', link: 'quick-start' },
{ text: 'Installation', link: 'installation' },
{ text: 'Themes', link: 'themes' },
{ text: 'Astro vs. X', link: 'comparing-astro-vs-other-tools' },
{ text: 'Migrate to v0.21', link: 'migration/0.21.0' },
en: [
{ text: 'Setup', header: true },
{ text: 'Getting Started', link: 'getting-started' },
{ text: 'Quickstart', link: 'quick-start' },
{ text: 'Installation', link: 'installation' },
{ text: 'Themes', link: 'themes' },
{ text: 'Astro vs. X', link: 'comparing-astro-vs-other-tools' },
{ text: 'Migrate to v0.21', link: 'migration/0.21.0' },
{ text: 'Basics', header: true },
{ text: 'Project Structure', link: 'core-concepts/project-structure' },
{ text: 'Component Syntax', link: 'core-concepts/astro-components' },
{ text: 'Pages', link: 'core-concepts/astro-pages' },
{ text: 'Layouts', link: 'core-concepts/layouts' },
{ text: 'Routing', link: 'core-concepts/routing' },
{ text: 'Partial Hydration', link: 'core-concepts/component-hydration' },
{ text: 'Basics', header: true },
{ text: 'Project Structure', link: 'core-concepts/project-structure' },
{ text: 'Component Syntax', link: 'core-concepts/astro-components' },
{ text: 'Pages', link: 'core-concepts/astro-pages' },
{ text: 'Layouts', link: 'core-concepts/layouts' },
{ text: 'Routing', link: 'core-concepts/routing' },
{ text: 'Partial Hydration', link: 'core-concepts/component-hydration' },
{ text: 'Guides', header: true },
{ text: 'Styling & CSS', link: 'guides/styling' },
{ text: 'Markdown', link: 'guides/markdown-content' },
{ text: 'Debugging', link: 'guides/debugging' },
{ text: 'Data Fetching', link: 'guides/data-fetching' },
{ text: 'Pagination', link: 'guides/pagination' },
{ text: 'RSS', link: 'guides/rss' },
{ text: 'Supported Imports', link: 'guides/imports' },
{ text: 'Aliases', link: 'guides/aliases' },
{ text: 'Environment Variables', link: 'guides/environment-variables' },
{ text: 'Deploy to the web', link: 'guides/deploy' },
{ text: 'Publish to npm', link: 'guides/publish-to-npm' },
{ text: 'Guides', header: true },
{ text: 'Styling & CSS', link: 'guides/styling' },
{ text: 'Markdown', link: 'guides/markdown-content' },
{ text: 'Debugging', link: 'guides/debugging' },
{ text: 'Data Fetching', link: 'guides/data-fetching' },
{ text: 'Pagination', link: 'guides/pagination' },
{ text: 'RSS', link: 'guides/rss' },
{ text: 'Supported Imports', link: 'guides/imports' },
{ text: 'Aliases', link: 'guides/aliases' },
{ text: 'Environment Variables', link: 'guides/environment-variables' },
{ text: 'Deploy to the web', link: 'guides/deploy' },
{ text: 'Publish to npm', link: 'guides/publish-to-npm' },
{ text: 'Reference', header: true },
{ text: 'Built-In Components', link: 'reference/builtin-components' },
{ text: 'API Reference', link: 'reference/api-reference' },
{ text: 'CLI Reference', link: 'reference/cli-reference' },
{
text: 'Configuration Reference',
link: 'reference/configuration-reference',
},
{ text: 'Renderer Reference', link: 'reference/renderer-reference' },
],
de: [
{ text: 'Einrichtung', header: true },
{ text: 'Erste Schritte', link: 'de/getting-started' },
{ text: 'Schnellstart', link: 'de/quick-start' },
{ text: 'Installation', link: 'de/installation' },
{ text: 'Vorlagen', link: 'de/themes' },
{ text: 'Astro vs. X', link: 'de/comparing-astro-vs-other-tools' },
{ text: 'Umstellung auf v0.21', link: 'de/migration/0.21.0' },
{ text: 'Reference', header: true },
{ text: 'Built-In Components', link: 'reference/builtin-components' },
{ text: 'API Reference', link: 'reference/api-reference' },
{ text: 'CLI Reference', link: 'reference/cli-reference' },
{
text: 'Configuration Reference',
link: 'reference/configuration-reference',
},
{ text: 'Renderer Reference', link: 'reference/renderer-reference' },
],
de: [
{ text: 'Einrichtung', header: true },
{ text: 'Erste Schritte', link: 'de/getting-started' },
{ text: 'Schnellstart', link: 'de/quick-start' },
{ text: 'Installation', link: 'de/installation' },
{ text: 'Vorlagen', link: 'de/themes' },
{ text: 'Astro vs. X', link: 'de/comparing-astro-vs-other-tools' },
{ text: 'Umstellung auf v0.21', link: 'de/migration/0.21.0' },
{ text: 'Grundlagen', header: true },
{ text: 'Projektstruktur', link: 'de/core-concepts/project-structure' },
{ text: 'Astro-Komponenten', link: 'de/core-concepts/astro-components' },
{ text: 'Astro-Seiten', link: 'de/core-concepts/astro-pages' },
{ text: 'Layouts', link: 'de/core-concepts/layouts' },
{ text: 'Routing', link: 'de/core-concepts/routing' },
{ text: 'Partial Hydration', link: 'de/core-concepts/component-hydration' },
{ text: 'Grundlagen', header: true },
{ text: 'Projektstruktur', link: 'de/core-concepts/project-structure' },
{ text: 'Astro-Komponenten', link: 'de/core-concepts/astro-components' },
{ text: 'Astro-Seiten', link: 'de/core-concepts/astro-pages' },
{ text: 'Layouts', link: 'de/core-concepts/layouts' },
{ text: 'Routing', link: 'de/core-concepts/routing' },
{ text: 'Partial Hydration', link: 'de/core-concepts/component-hydration' },
{ text: 'Anleitungen', header: true },
{ text: 'Styling & CSS', link: 'de/guides/styling' },
{ text: 'Anleitungen', header: true },
{ text: 'Styling & CSS', link: 'de/guides/styling' },
{ text: 'Referenz', header: true },
],
nl: [
{ text: 'Welkom', header: true },
{ text: 'Beginnen', link: 'nl/getting-started' },
{ text: 'Snel start', link: 'nl/quick-start' },
],
fi: [
{ text: 'Tervetuloa', header: true },
{ text: 'Aloittaminen', link: 'fi/getting-started' },
{ text: 'Pika-aloitus', link: 'fi/quick-start' },
{ text: 'Asennus', link: 'fi/installation' },
],
es: [
{ text: 'Configuración', header: true },
{ text: 'Empezando', link: 'es/getting-started' },
{ text: 'Comienzo rápido', link: 'es/quick-start' },
{ text: 'Instalación', link: 'es/installation' },
{ text: 'Astro vs. X', link: 'es/comparing-astro-vs-other-tools' },
{ text: 'Referenz', header: true },
],
nl: [
{ text: 'Welkom', header: true },
{ text: 'Beginnen', link: 'nl/getting-started' },
{ text: 'Snel start', link: 'nl/quick-start' },
],
fi: [
{ text: 'Tervetuloa', header: true },
{ text: 'Aloittaminen', link: 'fi/getting-started' },
{ text: 'Pika-aloitus', link: 'fi/quick-start' },
{ text: 'Asennus', link: 'fi/installation' },
],
es: [
{ text: 'Configuración', header: true },
{ text: 'Empezando', link: 'es/getting-started' },
{ text: 'Comienzo rápido', link: 'es/quick-start' },
{ text: 'Instalación', link: 'es/installation' },
{ text: 'Astro vs. X', link: 'es/comparing-astro-vs-other-tools' },
{ text: 'Fundamentos', header: true },
{
text: 'Estructura del Proyecto',
link: 'es/core-concepts/project-structure',
},
{
text: 'Sintaxis del Componente',
link: 'es/core-concepts/astro-components',
},
{ text: 'Páginas', link: 'es/core-concepts/astro-pages' },
{ text: 'Maquetas', link: 'es/core-concepts/layouts' },
{ text: 'Enrutamiento', link: 'es/core-concepts/routing' },
{
text: 'Hidratación parcial',
link: 'es/core-concepts/component-hydration',
},
{ text: 'Fundamentos', header: true },
{
text: 'Estructura del Proyecto',
link: 'es/core-concepts/project-structure',
},
{
text: 'Sintaxis del Componente',
link: 'es/core-concepts/astro-components',
},
{ text: 'Páginas', link: 'es/core-concepts/astro-pages' },
{ text: 'Maquetas', link: 'es/core-concepts/layouts' },
{ text: 'Enrutamiento', link: 'es/core-concepts/routing' },
{
text: 'Hidratación parcial',
link: 'es/core-concepts/component-hydration',
},
{ text: 'Guías', header: true },
{ text: 'Estilo y CSS', link: 'es/guides/styling' },
{ text: 'Markdown', link: 'es/guides/markdown-content' },
{ text: 'Depuración', link: 'es/guides/debugging' },
{ text: 'Obtención de datos', link: 'es/guides/data-fetching' },
{ text: 'Paginación', link: 'es/guides/pagination' },
{ text: 'RSS', link: 'es/guides/rss' },
{ text: 'Importaciones admitidas', link: 'es/guides/imports' },
{ text: 'Alias', link: 'es/guides/aliases' },
{ text: 'Desplegar en la web', link: 'es/guides/deploy' },
{ text: 'Publicar en npm', link: 'es/guides/publish-to-npm' },
{ text: 'Guías', header: true },
{ text: 'Estilo y CSS', link: 'es/guides/styling' },
{ text: 'Markdown', link: 'es/guides/markdown-content' },
{ text: 'Depuración', link: 'es/guides/debugging' },
{ text: 'Obtención de datos', link: 'es/guides/data-fetching' },
{ text: 'Paginación', link: 'es/guides/pagination' },
{ text: 'RSS', link: 'es/guides/rss' },
{ text: 'Importaciones admitidas', link: 'es/guides/imports' },
{ text: 'Alias', link: 'es/guides/aliases' },
{ text: 'Desplegar en la web', link: 'es/guides/deploy' },
{ text: 'Publicar en npm', link: 'es/guides/publish-to-npm' },
{ text: 'Referencia', header: true },
{
text: 'Componentes incorporados',
link: 'es/reference/builtin-components',
},
{ text: 'Referencia de API', link: 'es/reference/api-reference' },
{ text: 'Referencia de CLI', link: 'es/reference/cli-reference' },
{
text: 'Referencia de configuración',
link: 'es/reference/configuration-reference',
},
{
text: 'Referencia de renderizador',
link: 'es/reference/renderer-reference',
},
],
'zh-CN': [
{ text: '起步', header: true },
{ text: '入门指南', link: 'zh-CN/getting-started' },
{ text: '快速入门', link: 'zh-CN/quick-start' },
{ text: '安装指南', link: 'zh-CN/installation' },
{ text: '模板样例', link: 'zh-CN/examples' },
{
text: 'Astro 对比其他框架',
link: 'zh-CN/comparing-astro-vs-other-tools',
},
],
'zh-TW': [
{ text: '設定', header: true },
{ text: '新手上路', link: 'zh-TW/getting-started' },
{ text: '快速開始', link: 'zh-TW/quick-start' },
{ text: '安裝', link: 'zh-TW/installation' },
{ text: '佈景主題', link: 'zh-TW/themes' },
],
bg: [
{ text: 'Главни', header: true },
{ text: 'Започваме!', link: 'bg/getting-started' },
],
fr: [
{ text: 'Bienvenue', header: true },
{ text: 'Bien démarrer', link: 'fr/getting-started' },
{ text: 'Démarrage rapide', link: 'fr/quick-start' },
{ text: 'Installation', link: 'fr/installation' },
],
bn: [
{ text: 'সেটআপ', header: true },
{ text: 'শুরু করুন', link: 'bn/getting-started' },
],
kr: [
{ text: '환영합니다', header: true },
{ text: '시작하기', link: 'kr/getting-started' },
],
ar: [
{ text: 'التهيئة', header: true },
{ text: 'باشر البدأ', link: 'ar/getting-started' },
],
da: [
{ text: 'Velkommen', header: true },
{ text: 'Introduktion', link: 'da/getting-started' },
],
ja: [
{ text: 'セットアップ', header: true },
{ text: 'はじめに', link: 'ja/getting-started' },
{ text: 'クイックスタート', link: 'ja/quick-start' },
{ text: 'インストール', link: 'ja/installation' },
{ text: 'テーマ', link: 'ja/themes' },
{ text: 'Astro vs. X', link: 'ja/comparing-astro-vs-other-tools' },
],
ru: [
{ text: 'Введение', header: true },
{ text: 'Начало работы', link: 'ru/getting-started' },
{ text: 'Быстрый старт', link: 'ru/quick-start' },
],
it: [
{ text: 'Impostare', header: true },
{ text: 'Come iniziare', link: 'it/getting-started' },
],
{ text: 'Referencia', header: true },
{
text: 'Componentes incorporados',
link: 'es/reference/builtin-components',
},
{ text: 'Referencia de API', link: 'es/reference/api-reference' },
{ text: 'Referencia de CLI', link: 'es/reference/cli-reference' },
{
text: 'Referencia de configuración',
link: 'es/reference/configuration-reference',
},
{
text: 'Referencia de renderizador',
link: 'es/reference/renderer-reference',
},
],
'zh-CN': [
{ text: '起步', header: true },
{ text: '入门指南', link: 'zh-CN/getting-started' },
{ text: '快速入门', link: 'zh-CN/quick-start' },
{ text: '安装指南', link: 'zh-CN/installation' },
{ text: '模板样例', link: 'zh-CN/examples' },
{
text: 'Astro 对比其他框架',
link: 'zh-CN/comparing-astro-vs-other-tools',
},
],
'zh-TW': [
{ text: '設定', header: true },
{ text: '新手上路', link: 'zh-TW/getting-started' },
{ text: '快速開始', link: 'zh-TW/quick-start' },
{ text: '安裝', link: 'zh-TW/installation' },
{ text: '佈景主題', link: 'zh-TW/themes' },
],
bg: [
{ text: 'Главни', header: true },
{ text: 'Започваме!', link: 'bg/getting-started' },
],
fr: [
{ text: 'Bienvenue', header: true },
{ text: 'Bien démarrer', link: 'fr/getting-started' },
{ text: 'Démarrage rapide', link: 'fr/quick-start' },
{ text: 'Installation', link: 'fr/installation' },
],
bn: [
{ text: 'সেটআপ', header: true },
{ text: 'শুরু করুন', link: 'bn/getting-started' },
],
kr: [
{ text: '환영합니다', header: true },
{ text: '시작하기', link: 'kr/getting-started' },
],
ar: [
{ text: 'التهيئة', header: true },
{ text: 'باشر البدأ', link: 'ar/getting-started' },
],
da: [
{ text: 'Velkommen', header: true },
{ text: 'Introduktion', link: 'da/getting-started' },
],
ja: [
{ text: 'セットアップ', header: true },
{ text: 'はじめに', link: 'ja/getting-started' },
{ text: 'クイックスタート', link: 'ja/quick-start' },
{ text: 'インストール', link: 'ja/installation' },
{ text: 'テーマ', link: 'ja/themes' },
{ text: 'Astro vs. X', link: 'ja/comparing-astro-vs-other-tools' },
],
ru: [
{ text: 'Введение', header: true },
{ text: 'Начало работы', link: 'ru/getting-started' },
{ text: 'Быстрый старт', link: 'ru/quick-start' },
],
it: [
{ text: 'Impostare', header: true },
{ text: 'Come iniziare', link: 'it/getting-started' },
],
};
export const SITE = {
title: 'Astro Documentation',
description: 'Build faster websites with less client-side Javascript.',
title: 'Astro Documentation',
description: 'Build faster websites with less client-side Javascript.',
};
export const OPEN_GRAPH = {
locale: 'en_US',
image: {
src: '/default-og-image.png?v=1',
alt:
'astro logo on a starry expanse of space,' +
' with a purple saturn-like planet floating in the right foreground',
},
twitter: 'astrodotbuild',
locale: 'en_US',
image: {
src: '/default-og-image.png?v=1',
alt:
'astro logo on a starry expanse of space,' +
' with a purple saturn-like planet floating in the right foreground',
},
twitter: 'astrodotbuild',
};

View file

@ -1,122 +1,126 @@
---
import HeadCommon from "../components/HeadCommon.astro";
import HeadSEO from "../components/HeadSEO.astro";
import HeadCommon from '../components/HeadCommon.astro';
import HeadSEO from '../components/HeadSEO.astro';
import Header from '../components/Header/Header.astro';
import Footer from '../components/Footer/Footer.astro';
import PageContent from '../components/PageContent/PageContent.astro';
import LeftSidebar from '../components/LeftSidebar/LeftSidebar.astro';
import RightSidebar from '../components/RightSidebar/RightSidebar.astro';
import { SITE } from "../config.ts";
import { SITE } from '../config.ts';
const { content = {}, hideRightSidebar = false} = Astro.props;
const { content = {}, hideRightSidebar = false } = Astro.props;
const currentPage = Astro.request.url.pathname;
const currentFile = `src/pages${currentPage.replace(/\/$/, "")}.md`;
const currentFile = `src/pages${currentPage.replace(/\/$/, '')}.md`;
const githubEditUrl = `https://github.com/withastro/astro/blob/main/docs/${currentFile}`;
const formatTitle = (content, SITE) => content.title ? `${content.title} 🚀 ${SITE.title}` : SITE.title;
const formatTitle = (content, SITE) =>
content.title ? `${content.title} 🚀 ${SITE.title}` : SITE.title;
---
<html dir={content.dir ?? 'ltr'} lang={content.lang ?? 'en-us'} class="initial">
<head>
<HeadCommon />
<HeadSEO {content} canonicalURL={Astro.request.canonicalURL} />
<title>{formatTitle(content, SITE)}</title>
<style>
body {
width: 100%;
display: grid;
grid-template-rows: var(--theme-navbar-height) 1fr;
--gutter: 0.5rem;
--doc-padding: 2rem;
}
.layout {
display: grid;
grid-auto-flow: column;
grid-template-columns:
minmax(var(--gutter), 1fr)
minmax(0, var(--max-width))
minmax(var(--gutter), 1fr);
overflow-x: hidden;
}
.layout :global(> *) {
width: 100%;
height: 100%;
}
.grid-sidebar {
height: 100vh;
position: sticky;
top: 0;
padding: 0;
}
#grid-left {
position: fixed;
background-color: var(--theme-bg);
z-index: 10;
display: none;
}
#grid-main {
padding: var(--doc-padding) var(--gutter);
grid-column: 2;
display: flex;
flex-direction: column;
height: 100%;
}
#grid-right {
display: none;
}
:global(.mobile-sidebar-toggle) {
overflow: hidden;
}
:global(.mobile-sidebar-toggle #grid-left) {
display: block;
top: 2rem;
}
@media (min-width: 50em) {
.layout {
overflow: initial;
grid-template-columns:
20rem
minmax(0, var(--max-width));
gap: 1em;
}
#grid-left {
display: flex;
padding-left: 2rem;
position: sticky;
grid-column: 1;
}
}
<head>
<HeadCommon />
<HeadSEO {content} canonicalURL={Astro.request.canonicalURL} />
<title>{formatTitle(content, SITE)}</title>
<style>
body {
width: 100%;
display: grid;
grid-template-rows: var(--theme-navbar-height) 1fr;
--gutter: 0.5rem;
--doc-padding: 2rem;
}
.layout {
display: grid;
grid-auto-flow: column;
grid-template-columns:
minmax(var(--gutter), 1fr)
minmax(0, var(--max-width))
minmax(var(--gutter), 1fr);
overflow-x: hidden;
}
.layout :global(> *) {
width: 100%;
height: 100%;
}
.grid-sidebar {
height: 100vh;
position: sticky;
top: 0;
padding: 0;
}
#grid-left {
position: fixed;
background-color: var(--theme-bg);
z-index: 10;
display: none;
}
#grid-main {
padding: var(--doc-padding) var(--gutter);
grid-column: 2;
display: flex;
flex-direction: column;
height: 100%;
}
#grid-right {
display: none;
}
:global(.mobile-sidebar-toggle) {
overflow: hidden;
}
:global(.mobile-sidebar-toggle #grid-left) {
display: block;
top: 2rem;
}
@media (min-width: 50em) {
.layout {
overflow: initial;
grid-template-columns:
20rem
minmax(0, var(--max-width));
gap: 1em;
}
#grid-left {
display: flex;
padding-left: 2rem;
position: sticky;
grid-column: 1;
}
}
@media (min-width: 72em) {
.layout {
grid-template-columns:
20rem
minmax(0, var(--max-width))
18rem;
padding-left: 0;
padding-right: 0;
margin: 0 auto;
}
#grid-right {
grid-column: 3;
display: flex;
}
}
</style>
</head>
@media (min-width: 72em) {
.layout {
grid-template-columns:
20rem
minmax(0, var(--max-width))
18rem;
padding-left: 0;
padding-right: 0;
margin: 0 auto;
}
#grid-right {
grid-column: 3;
display: flex;
}
}
</style>
</head>
<body>
<Header currentPage={currentPage} />
<main class="layout">
<aside id="grid-left" class="grid-sidebar" title="Site Navigation">
<LeftSidebar currentPage={currentPage} />
</aside>
<div id="grid-main">
<PageContent content={content} githubEditUrl={githubEditUrl} currentPage={currentPage}>
<slot />
</PageContent>
</div>
<aside id="grid-right" class="grid-sidebar" title="Table of Contents">
{!hideRightSidebar && <RightSidebar content={content} githubEditUrl={githubEditUrl} />}
</aside>
</main>
</body>
<body>
<Header {currentPage} />
<main class="layout">
<aside id="grid-left" class="grid-sidebar" title="Site Navigation">
<LeftSidebar {currentPage} />
</aside>
<div id="grid-main">
<PageContent {content} {githubEditUrl} {currentPage}>
<slot />
</PageContent>
</div>
<aside id="grid-right" class="grid-sidebar" title="Table of Contents">
{!hideRightSidebar && (
<RightSidebar content={content} githubEditUrl={githubEditUrl} />
)}
</aside>
</main>
</body>
</html>

View file

@ -1,48 +1,48 @@
---
import HeadCommon from "../components/HeadCommon.astro";
import HeadCommon from '../components/HeadCommon.astro';
import Header from '../components/Header/Header.astro';
import { SITE } from "../config.ts";
import { SITE } from '../config.ts';
const { title } = Astro.props;
---
<html dir="ltr" lang="en-us" class="initial">
<head>
<HeadCommon />
<title>{`${title} 🚀 ${SITE.title}`}</title>
<style>
body {
width: 100%;
display: grid;
grid-template-rows: var(--theme-navbar-height) 1fr;
--gutter: 0.5rem;
--doc-padding: 2rem;
}
.layout {
display: grid;
grid-auto-flow: column;
grid-template-columns:
minmax(var(--gutter), 1fr)
minmax(0, var(--max-width))
minmax(var(--gutter), 1fr);
overflow-x: hidden;
}
article {
padding: var(--doc-padding) var(--gutter);
grid-column: 2;
display: flex;
flex-direction: column;
height: 100%;
}
</style>
</head>
<head>
<HeadCommon />
<title>{`${title} 🚀 ${SITE.title}`}</title>
<style>
body {
width: 100%;
display: grid;
grid-template-rows: var(--theme-navbar-height) 1fr;
--gutter: 0.5rem;
--doc-padding: 2rem;
}
.layout {
display: grid;
grid-auto-flow: column;
grid-template-columns:
minmax(var(--gutter), 1fr)
minmax(0, var(--max-width))
minmax(var(--gutter), 1fr);
overflow-x: hidden;
}
article {
padding: var(--doc-padding) var(--gutter);
grid-column: 2;
display: flex;
flex-direction: column;
height: 100%;
}
</style>
</head>
<body>
<Header />
<main class="layout splash-layout">
<article>
<slot />
</article>
</main>
</body>
<body>
<Header />
<main class="layout splash-layout">
<article>
<slot />
</article>
</main>
</body>
</html>

View file

@ -3,7 +3,7 @@ import SplashLayout from '../layouts/SplashLayout.astro';
---
<SplashLayout title="Not Found">
<h1>404</h1>
<p>This page isn't in our solar system.</p>
<a href="/">Take me home.</a>
<h1>404</h1>
<p>This page isn't in our solar system.</p>
<a href="/">Take me home.</a>
</SplashLayout>

View file

@ -3,7 +3,7 @@ import SplashLayout from '../../layouts/SplashLayout.astro';
---
<SplashLayout title="Nicht gefunden">
<h1>404</h1>
<p>Diese Seite befindet sich nicht in unserem Sonnensystem.</p>
<a href="/">Bring mich nach Hause.</a>
<h1>404</h1>
<p>Diese Seite befindet sich nicht in unserem Sonnensystem.</p>
<a href="/">Bring mich nach Hause.</a>
</SplashLayout>

View file

@ -5,48 +5,49 @@ import { Markdown } from 'astro/components';
import themes from '../../data/themes.json';
import components from '../../data/components.json';
---
<Layout content={{title: 'Vorlagen'}} hideRightSidebar>
<style>
.card-grid {
display: grid;
grid-column-gap: 15px;
grid-row-gap: 15px;
grid-auto-flow: dense;
grid-template-columns: repeat(auto-fit,minmax(300px,1fr))
}
</style>
<Markdown>
## Vorgestellte Vorlagen
</Markdown>
<div class="card-grid">
{themes.featured.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## Offizielle Vorlagen
Astro pflegt verschiedene offizielle Vorlagen für Dokumentationssites, Portfolios und mehr.
</Markdown>
<div class="card-grid">
{themes.official.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## Vorlagen aus der Community
<Layout content={{ title: 'Vorlagen' }} hideRightSidebar>
<style>
.card-grid {
display: grid;
grid-column-gap: 15px;
grid-row-gap: 15px;
grid-auto-flow: dense;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
</style>
<Markdown>
## Vorgestellte Vorlagen
</Markdown>
<div class="card-grid">
{themes.featured.map((item) => <Card data={item} />)}
</div>
<Markdown>
## Offizielle Vorlagen
Sieh dir einige von unserer Community entwickelte Vorlagen an!
</Markdown>
<div class="card-grid">
{themes.community.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## Vorgestellte Packages
Astro pflegt verschiedene offizielle Vorlagen für Dokumentationssites, Portfolios und mehr.
</Markdown>
<div class="card-grid">
{themes.official.map((item) => <Card data={item} />)}
</div>
<Markdown>
## Vorlagen aus der Community
Unser Package-Ökosystem wächst stetig! Sieh dir die hier vorgestellten Packages unserer Community an. Durchsuche unsere vollständige Sammlung [auf npm.](https://www.npmjs.com/search?q=keywords%3Aastro-component)
</Markdown>
<div class="card-grid">
{components.community.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
> Möchtest du deine eigene Arbeit hier sehen? [Teile sie in Discord!](https://astro.build/chat)
Wir teilen hier regelmäßig unsere Favoriten aus dem #showcase-Channel.
</Markdown>
Sieh dir einige von unserer Community entwickelte Vorlagen an!
</Markdown>
<div class="card-grid">
{themes.community.map((item) => <Card data={item} />)}
</div>
<Markdown>
## Vorgestellte Packages
Unser Package-Ökosystem wächst stetig! Sieh dir die hier vorgestellten Packages unserer Community an. Durchsuche unsere vollständige Sammlung [auf npm.](https://www.npmjs.com/search?q=keywords%3Aastro-component)
</Markdown>
<div class="card-grid">
{components.community.map((item) => <Card data={item} />)}
</div>
<Markdown>
> Möchtest du deine eigene Arbeit hier sehen? [Teile sie in Discord!](https://astro.build/chat)
> Wir teilen hier regelmäßig unsere Favoriten aus dem #showcase-Channel.
</Markdown>
</Layout>

View file

@ -4,10 +4,9 @@ import MainLayout from '~/layouts/MainLayout.astro';
const [content] = Astro.fetchContent('/src/pages/guides/markdown-content.md');
---
<MainLayout content="{content}">
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
<MainLayout {content}>
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
</MainLayout>

View file

@ -4,10 +4,9 @@ import MainLayout from '~/layouts/MainLayout.astro';
const [content] = Astro.fetchContent('/src/pages/guides/pagination.md');
---
<MainLayout content="{content}">
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
<MainLayout {content}>
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
</MainLayout>

View file

@ -4,10 +4,9 @@ import MainLayout from '~/layouts/MainLayout.astro';
const [content] = Astro.fetchContent('/src/pages/guides/publish-to-npm.md');
---
<MainLayout content="{content}">
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
<MainLayout {content}>
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
</MainLayout>

View file

@ -4,10 +4,9 @@ import MainLayout from '~/layouts/MainLayout.astro';
const [content] = Astro.fetchContent('/src/pages/guides/styling.md');
---
<MainLayout content="{content}">
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
<MainLayout {content}>
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
</MainLayout>

View file

@ -1,13 +1,14 @@
---
import { Markdown } from 'astro/components';
import MainLayout from '~/layouts/MainLayout.astro';
const [content] = Astro.fetchContent('/src/pages/reference/renderer-reference.md');
const [content] = Astro.fetchContent(
'/src/pages/reference/renderer-reference.md'
);
---
<MainLayout content="{content}">
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
<MainLayout {content}>
<Markdown>
> Esta página todavía no está disponible en Español. Se muestra la versión en inglés.
</Markdown>
{content.astro.html}
</MainLayout>

View file

@ -3,19 +3,37 @@ import Layout from '../layouts/MainLayout.astro';
---
<script>
// WIP: trigger a client-side redirect based on the browser language.
// A vercel.json redirect is enforced in production, so no user should ever see this page.
// Remove the vercel.json redirect when this is ready.
const KNOWN_LANGUAGES = ['bg', 'de','en','es','fi','nl','pt-br','zh-CN','zh-TW', 'fr', 'kr', 'da', 'ja'];
let newLangWithRegion = (window.navigator.userLanguage || window.navigator.language || 'en-US').substr(0, 5);
let newLang = newLangWithRegion.substr(0, 2);
if (newLang === 'en') {
window.location.pathname = '/getting-started';
} else if (KNOWN_LANGUAGES.includes(newLangWithRegion)) {
window.location.pathname = '/' + newLangWithRegion + '/getting-started';
} else if (KNOWN_LANGUAGES.includes(newLang)) {
window.location.pathname = '/' + newLang + '/getting-started';
} else {
window.location.pathname = '/getting-started';
}
// WIP: trigger a client-side redirect based on the browser language.
// A vercel.json redirect is enforced in production, so no user should ever see this page.
// Remove the vercel.json redirect when this is ready.
const KNOWN_LANGUAGES = [
'bg',
'de',
'en',
'es',
'fi',
'nl',
'pt-br',
'zh-CN',
'zh-TW',
'fr',
'kr',
'da',
'ja',
];
let newLangWithRegion = (
window.navigator.userLanguage ||
window.navigator.language ||
'en-US'
).substr(0, 5);
let newLang = newLangWithRegion.substr(0, 2);
if (newLang === 'en') {
window.location.pathname = '/getting-started';
} else if (KNOWN_LANGUAGES.includes(newLangWithRegion)) {
window.location.pathname = '/' + newLangWithRegion + '/getting-started';
} else if (KNOWN_LANGUAGES.includes(newLang)) {
window.location.pathname = '/' + newLang + '/getting-started';
} else {
window.location.pathname = '/getting-started';
}
</script>

View file

@ -1,52 +1,53 @@
---
import Layout from '../../layouts/MainLayout.astro';
import Card from '../../components/Card.astro';
import {Markdown} from 'astro/components';
import { Markdown } from 'astro/components';
import themes from '../../data/themes.json';
import components from '../../data/components.json';
---
<Layout content={{title: 'テーマ'}} hideRightSidebar>
<style>
.card-grid {
display: grid;
grid-column-gap: 15px;
grid-row-gap: 15px;
grid-auto-flow: dense;
grid-template-columns: repeat(auto-fit,minmax(300px,1fr))
}
</style>
<Markdown>
## 注目のテーマ
</Markdown>
<div class="card-grid">
{themes.featured.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## 公式テーマ
Astroでは、ドキュメントサイトやポートフォリオなど、いくつかの公式テーマを用意しています。
</Markdown>
<div class="card-grid">
{themes.official.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## コミュニティテーマ
<Layout content={{ title: 'テーマ' }} hideRightSidebar>
<style>
.card-grid {
display: grid;
grid-column-gap: 15px;
grid-row-gap: 15px;
grid-auto-flow: dense;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
</style>
<Markdown>
## 注目のテーマ
</Markdown>
<div class="card-grid">
{themes.featured.map((item) => <Card data={item} />)}
</div>
<Markdown>
## 公式テーマ
コミュニティが開発したテーマをご覧ください。
</Markdown>
<div class="card-grid">
{themes.community.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## 注目のパッケージ
Astro では、ドキュメントサイトやポートフォリオなど、いくつかの公式テーマを用意しています
</Markdown>
<div class="card-grid">
{themes.official.map((item) => <Card data={item} />)}
</div>
<Markdown>
## コミュニティテーマ
私たちのパッケージエコシステムは成長し続けています。注目のコミュニティパッケージをご覧ください。コレクション全体は[npm](https://www.npmjs.com/search?q=keywords%3Aastro-component)で検索できます。
</Markdown>
<div class="card-grid">
{components.community.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
> 自分のテーマを紹介したい場合は、[Discordでシェアしてください](https://astro.build/chat)
`#showcase` チャンネルに投稿されたお気に入りの作品をよくピックアップしています。
</Markdown>
コミュニティが開発したテーマをご覧ください。
</Markdown>
<div class="card-grid">
{themes.community.map((item) => <Card data={item} />)}
</div>
<Markdown>
## 注目のパッケージ
私たちのパッケージエコシステムは成長し続けています。注目のコミュニティパッケージをご覧ください。コレクション全体は[npm](https://www.npmjs.com/search?q=keywords%3Aastro-component)で検索できます。
</Markdown>
<div class="card-grid">
{components.community.map((item) => <Card data={item} />)}
</div>
<Markdown>
> 自分のテーマを紹介したい場合は、[Discord でシェアしてください!](https://astro.build/chat)
> `#showcase` チャンネルに投稿されたお気に入りの作品をよくピックアップしています。
</Markdown>
</Layout>

View file

@ -5,48 +5,49 @@ import { Markdown } from 'astro/components';
import themes from '../data/themes.json';
import components from '../data/components.json';
---
<Layout content={{title: 'Themes'}} hideRightSidebar>
<style>
.card-grid {
display: grid;
grid-column-gap: 15px;
grid-row-gap: 15px;
grid-auto-flow: dense;
grid-template-columns: repeat(auto-fit,minmax(300px,1fr))
}
</style>
<Markdown>
## Featured Theme
</Markdown>
<div class="card-grid">
{themes.featured.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## Official Themes
Astro maintains several official themes for documentation sites, portfolios, and more.
</Markdown>
<div class="card-grid">
{themes.official.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## Community Themes
<Layout content={{ title: 'Themes' }} hideRightSidebar>
<style>
.card-grid {
display: grid;
grid-column-gap: 15px;
grid-row-gap: 15px;
grid-auto-flow: dense;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
</style>
<Markdown>
## Featured Theme
</Markdown>
<div class="card-grid">
{themes.featured.map((item) => <Card data={item} />)}
</div>
<Markdown>
## Official Themes
Checkout some themes developed by our community!
</Markdown>
<div class="card-grid">
{themes.community.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## Featured Packages
Astro maintains several official themes for documentation sites, portfolios, and more.
</Markdown>
<div class="card-grid">
{themes.official.map((item) => <Card data={item} />)}
</div>
<Markdown>
## Community Themes
Our package ecosystem is growing! Check out these featured community packages. Search the entire collection [on npm.](https://www.npmjs.com/search?q=keywords%3Aastro-component)
</Markdown>
<div class="card-grid">
{components.community.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
> Want to see your own work featured? [Share it to Discord!](https://astro.build/chat)
We'll often take our favorites from the `#showcase` channel and post them here.
</Markdown>
Checkout some themes developed by our community!
</Markdown>
<div class="card-grid">
{themes.community.map((item) => <Card data={item} />)}
</div>
<Markdown>
## Featured Packages
Our package ecosystem is growing! Check out these featured community packages. Search the entire collection [on npm.](https://www.npmjs.com/search?q=keywords%3Aastro-component)
</Markdown>
<div class="card-grid">
{components.community.map((item) => <Card data={item} />)}
</div>
<Markdown>
> Want to see your own work featured? [Share it to Discord!](https://astro.build/chat)
> We'll often take our favorites from the `#showcase` channel and post them here.
</Markdown>
</Layout>

View file

@ -5,48 +5,49 @@ import { Markdown } from 'astro/components';
import themes from '../../data/themes.json';
import components from '../../data/components.json';
---
<Layout content={{title: '佈景主題'}} hideRightSidebar>
<style>
.card-grid {
display: grid;
grid-column-gap: 15px;
grid-row-gap: 15px;
grid-auto-flow: dense;
grid-template-columns: repeat(auto-fit,minmax(300px,1fr))
}
</style>
<Markdown>
## 精選佈景主題
</Markdown>
<div class="card-grid">
{themes.featured.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## 官方佈景主題
Astro 維護的文件網站、作品集⋯等官方佈景主題。
</Markdown>
<div class="card-grid">
{themes.official.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## 社群佈景主題
<Layout content={{ title: '佈景主題' }} hideRightSidebar>
<style>
.card-grid {
display: grid;
grid-column-gap: 15px;
grid-row-gap: 15px;
grid-auto-flow: dense;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
</style>
<Markdown>
## 精選佈景主題
</Markdown>
<div class="card-grid">
{themes.featured.map((item) => <Card data={item} />)}
</div>
<Markdown>
## 官方佈景主題
趕緊來看看社群開發的佈景主題!
</Markdown>
<div class="card-grid">
{themes.community.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
## 精選套件
Astro 維護的文件網站、作品集 ⋯ 等官方佈景主題。
</Markdown>
<div class="card-grid">
{themes.official.map((item) => <Card data={item} />)}
</div>
<Markdown>
## 社群佈景主題
我們的套件生態持續成長!所有精選社群套件都可以在 [npm](https://www.npmjs.com/search?q=keywords%3Aastro-component) 發掘。
</Markdown>
<div class="card-grid">
{components.community.map((item)=>(<Card data={item} />))}
</div>
<Markdown>
> 想要讓自己的作品成為精選嗎?[在 Discord 分享!](https://astro.build/chat)
我們常在 `#showcase` 頻道取材,把深受喜愛的在這裡發布。
</Markdown>
趕緊來看看社群開發的佈景主題!
</Markdown>
<div class="card-grid">
{themes.community.map((item) => <Card data={item} />)}
</div>
<Markdown>
## 精選套件
我們的套件生態持續成長!所有精選社群套件都可以在 [npm](https://www.npmjs.com/search?q=keywords%3Aastro-component) 發掘。
</Markdown>
<div class="card-grid">
{components.community.map((item) => <Card data={item} />)}
</div>
<Markdown>
> 想要讓自己的作品成為精選嗎?[在 Discord 分享!](https://astro.build/chat)
> 我們常在 `#showcase` 頻道取材,把深受喜愛的在這裡發布。
</Markdown>
</Layout>

View file

@ -1,14 +1,14 @@
export function getLanguageFromURL(pathname: string) {
const langCodeMatch = pathname.match(/\/([a-z]{2}-?[A-Z]{0,2})\//);
return langCodeMatch ? langCodeMatch[1] : 'en';
const langCodeMatch = pathname.match(/\/([a-z]{2}-?[A-Z]{0,2})\//);
return langCodeMatch ? langCodeMatch[1] : 'en';
}
/** Remove \ and / from beginning of string */
export function removeLeadingSlash(path: string) {
return path.replace(/^[/\\]+/, '');
return path.replace(/^[/\\]+/, '');
}
/** Remove \ and / from end of string */
export function removeTrailingSlash(path: string) {
return path.replace(/[/\\]+$/, '');
return path.replace(/[/\\]+$/, '');
}

View file

@ -8,6 +8,6 @@
// @ts-check
export default /** @type {import('astro').AstroUserConfig} */ ({
// Enable the Preact renderer to support Preact JSX components.
renderers: ['@astrojs/renderer-preact'],
// Enable the Preact renderer to support Preact JSX components.
renderers: ['@astrojs/renderer-preact'],
});

View file

@ -1,45 +1,45 @@
---
export interface Props {
title: string;
description: string;
image?: string;
type?: string;
next?: string;
prev?: string;
canonicalURL?: string | URL;
title: string;
description: string;
image?: string;
type?: string;
next?: string;
prev?: string;
canonicalURL?: string | URL;
}
const { title, description, image, type, next, prev, canonicalURL } = Astro.props as Props;
---
<!-- Common -->
<meta charset="UTF-8">
<meta charset="UTF-8" />
<title>{title}</title>
<meta name="description" content={description}>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
<meta name="description" content={description} />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link href="https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href={Astro.resolve('../styles/global.css')} />
<!-- Sitemap -->
<link rel="sitemap" href="/sitemap.xml">
<link rel="sitemap" href="/sitemap.xml" />
<!-- RSS -->
<link rel="alternate" type="application/rss+xml" href="/feed/posts.xml">
<link rel="alternate" type="application/rss+xml" href="/feed/posts.xml" />
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<!-- SEO -->
<link rel="canonical" href={canonicalURL}>
<link rel="canonical" href={canonicalURL} />
{next && <link rel="next" aria-label="Previous Page" href={new URL(next, canonicalURL).href}>}
{prev && <link rel="prev" aria-label="Next Page" href={new URL(prev, canonicalURL).href}>}
<!-- OpenGraph -->
<meta property="og:title" content={title}>
<meta property="og:description" content={description}>
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
{image && (<meta property="og:image" content={new URL(image, canonicalURL)}>)}
<!-- Twitter -->
<meta name="twitter:card" content={image ? 'summary_large_image' : 'summary'}>
<meta name="twitter:site" content="@astro">
<meta name="twitter:title" content={title}>
<meta name="twitter:description" content={description}>
<meta name="twitter:card" content={image ? 'summary_large_image' : 'summary'} />
<meta name="twitter:site" content="@astro" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
{image && (<meta name="twitter:image" content={image}>)}

View file

@ -1,63 +1,63 @@
---
export interface Props {
title: string;
title: string;
}
const { title } = Astro.props;
---
<style lang="scss">
.header {
text-align: center;
@media (min-width: 600px) {
display: flex;
align-items: center;
padding: 2rem;
}
}
.title {
margin: 0;
font-size: 1.2em;
letter-spacing: -0.03em;
font-weight: 400;
margin-right: 1em;
}
.nav {
text-align: center;
@media (min-width: 600px) {
display: flex;
}
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
margin: 0;
}
a {
display: block;
font-size: 1.2em;
letter-spacing: -0.02em;
margin-left: 0.75em;
margin-right: 0.75em;
}
</style>
<nav class="header">
<h1 class="title">Dons Blog</h1>
<ul class="nav">
<li><a href="/">Home</a></li>
<li><a href="/posts">All Posts</a></li>
<li><a href="/authors/don">Author: Don</a></li>
<li><a href="/authors/sancho">Author: Sancho</a></li>
<li><a href="/about">About</a></li>
</ul>
<h1 class="title">Dons Blog</h1>
<ul class="nav">
<li><a href="/">Home</a></li>
<li><a href="/posts">All Posts</a></li>
<li><a href="/authors/don">Author: Don</a></li>
<li><a href="/authors/sancho">Author: Sancho</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
<style lang="scss">
.header {
text-align: center;
@media (min-width: 600px) {
display: flex;
align-items: center;
padding: 2rem;
}
}
.title {
margin: 0;
font-size: 1.2em;
letter-spacing: -0.03em;
font-weight: 400;
margin-right: 1em;
}
.nav {
text-align: center;
@media (min-width: 600px) {
display: flex;
}
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
margin: 0;
}
a {
display: block;
font-size: 1.2em;
letter-spacing: -0.02em;
margin-left: 0.75em;
margin-right: 0.75em;
}
</style>

View file

@ -1,44 +1,44 @@
---
export interface Props {
prevUrl: string;
nextUrl: string;
prevUrl: string;
nextUrl: string;
}
const { prevUrl, nextUrl } = Astro.props;
---
<style lang="scss">
.nav {
display: flex;
margin-right: auto;
margin-left: auto;
padding-top: 4rem;
padding-bottom: 4rem;
}
.prev,
.next {
display: block;
text-transform: uppercase;
font-size: 0.8em;
&[href="#"] {
display: none;
}
}
.prev {
margin-right: auto;
}
.next {
margin-left: auto;
}
</style>
<div class="wrapper">
<nav class="nav">
<a class="prev" href={prevUrl || '#'} aria-label="Previous Page">Prev</a>
<a class="next" href={nextUrl || '#'} aria-label="Next Page">Next</a>
</nav>
<nav class="nav">
<a class="prev" href={prevUrl || '#'} aria-label="Previous Page">Prev</a>
<a class="next" href={nextUrl || '#'} aria-label="Next Page">Next</a>
</nav>
</div>
<style lang="scss">
.nav {
display: flex;
margin-right: auto;
margin-left: auto;
padding-top: 4rem;
padding-bottom: 4rem;
}
.prev,
.next {
display: block;
text-transform: uppercase;
font-size: 0.8em;
&[href='#'] {
display: none;
}
}
.prev {
margin-right: auto;
}
.next {
margin-left: auto;
}
</style>

View file

@ -1,66 +1,65 @@
---
export interface Props {
post: any;
author: string;
post: any;
author: string;
}
const { post, author } = Astro.props;
function formatDate(date) {
return new Date(date).toUTCString().replace(/(\d\d\d\d) .*/, '$1'); // remove everything after YYYY
return new Date(date).toUTCString().replace(/(\d\d\d\d) .*/, '$1'); // remove everything after YYYY
}
---
<style lang="scss">
.post {
padding-top: 6rem;
padding-bottom: 6rem;
border-bottom: 1px solid rgba(black, 0.25);
text-align: center;
}
.author {
text-transform: uppercase;
}
.date {
font-style: italic;
}
.description {
font-size: 1.25em;
}
.link {
text-transform: uppercase;
font-size: 0.8em;
margin-left: 1em;
}
h2 {
font-weight: 700;
font-size: 2.75em;
line-height: 1;
letter-spacing: -0.04em;
margin-top: 0;
margin-bottom: 0;
}
time {
display: block;
margin-top: 0.25rem;
margin-bottom: 0.5em;
}
</style>
<article class="post">
<div class="data">
<h2>{post.title}</h2>
<a class="author" href={`/authors/${post.author}`}>{author.name}</a>
<time class="date" datetime={post.date}>{formatDate(post.date)}</time>
<p class="description">
{post.description}
<a class="link" href={post.url} aria-label={`Read ${post.title}`}>Read</a>
</p>
</div>
<div class="data">
<h2>{post.title}</h2>
<a class="author" href={`/authors/${post.author}`}>{author.name}</a>
<time class="date" datetime={post.date}>{formatDate(post.date)}</time>
<p class="description">
{post.description}
<a class="link" href={post.url} aria-label={`Read ${post.title}`}>Read</a>
</p>
</div>
</article>
<style lang="scss">
.post {
padding-top: 6rem;
padding-bottom: 6rem;
border-bottom: 1px solid rgba(black, 0.25);
text-align: center;
}
.author {
text-transform: uppercase;
}
.date {
font-style: italic;
}
.description {
font-size: 1.25em;
}
.link {
text-transform: uppercase;
font-size: 0.8em;
margin-left: 1em;
}
h2 {
font-weight: 700;
font-size: 2.75em;
line-height: 1;
letter-spacing: -0.04em;
margin-top: 0;
margin-bottom: 0;
}
time {
display: block;
margin-top: 0.25rem;
margin-bottom: 0.5em;
}
</style>

View file

@ -7,73 +7,72 @@ const { content } = Astro.props;
let canonicalURL = Astro.request.canonicalURL;
---
<html lang={ content.lang || 'en' }>
<head>
<title>{content.title}</title>
<MainHead title={content.title} description={content.description} image={content.image} canonicalURL={canonicalURL} />
<style lang="scss">
.title {
margin-top: 4rem;
margin-bottom: 4rem;
font-size: 3em;
letter-spacing: -0.04em;
text-align: center;
}
<html lang={content.lang || 'en'}>
<head>
<title>{content.title}</title>
<MainHead title={content.title} description={content.description} image={content.image} {canonicalURL} />
<style lang="scss">
.title {
margin-top: 4rem;
margin-bottom: 4rem;
font-size: 3em;
letter-spacing: -0.04em;
text-align: center;
}
.description {
margin-bottom: 4rem;
font-size: 1.4em;
font-weight: 400;
text-align: justify;
text-transform: uppercase;
}
.description {
margin-bottom: 4rem;
font-size: 1.4em;
font-weight: 400;
text-align: justify;
text-transform: uppercase;
}
.img {
display: block;
width: 100%;
height: auto;
}
.img {
display: block;
width: 100%;
height: auto;
}
.article {
margin-top: 4rem;
margin-bottom: 6rem;
.article {
margin-top: 4rem;
margin-bottom: 6rem;
:global(p) {
font-size: 1.3em;
line-height: 2;
margin-top: 2em;
margin-bottom: 2em;
}
}
:global(p) {
font-size: 1.3em;
line-height: 2;
margin-top: 2em;
margin-bottom: 2em;
}
}
.posts {
text-transform: uppercase;
}
.posts {
text-transform: uppercase;
}
.footer {
margin-top: 6rem;
padding-bottom: 6rem;
text-align: center;
}
</style>
</head>
.footer {
margin-top: 6rem;
padding-bottom: 6rem;
text-align: center;
}
</style>
</head>
<body>
<Nav />
<body>
<Nav />
<main class="wrapper">
<h2 class="title">{content.title}</h2>
<p class="description">{content.description}</p>
<img class="img" src={content.image} alt="">
<article class="article">
<slot />
</article>
<footer class="footer">
<a class="posts" href="/posts">All Posts</a>
</footer>
</main>
<main class="wrapper">
<h2 class="title">{content.title}</h2>
<p class="description">{content.description}</p>
<img class="img" src={content.image} alt="" />
<article class="article">
<slot />
</article>
<footer class="footer">
<a class="posts" href="/posts">All Posts</a>
</footer>
</main>
<footer>
</footer>
</body>
<footer></footer>
</body>
</html>

View file

@ -2,65 +2,69 @@
import MainHead from '../components/MainHead.astro';
import Nav from '../components/Nav.astro';
let title = "About";
let description = "About page of an example blog on Astro";
let title = 'About';
let description = 'About page of an example blog on Astro';
let canonicalURL = Astro.request.canonicalURL;
---
<html lang="en">
<head>
<MainHead
title={title}
description={description}
canonicalURL={canonicalURL}
/>
<style lang="scss">
<head>
<MainHead {title} {description} {canonicalURL} />
<style lang="scss">
.text {
padding-bottom: 6rem;
.text {
padding-bottom: 6rem;
p {
font-size: 1.2em;
line-height: 2;
margin-top: 2em;
margin-bottom: 2em;
}
}
p {
font-size: 1.2em;
line-height: 2;
margin-top: 2em;
margin-bottom: 2em;
}
}
.hero {
display: block;
height: 16rem;
overflow: hidden;
margin: 4rem 0;
.hero {
display: block;
height: 16rem;
overflow: hidden;
margin: 4rem 0;
&-img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
&-img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.title {
font-size: 3em;
letter-spacing: -0.04em;
margin-top: 2rem;
margin-bottom: 0;
text-align: center;
}
</style>
</head>
<body>
<Nav {title} />
.title {
font-size: 3em;
letter-spacing: -0.04em;
margin-top: 2rem;
margin-bottom: 0;
text-align: center;
}
</style>
</head>
<body>
<Nav title={title} />
<main class="wrapper">
<h2 class="title">{title}</h2>
<div class="hero">
<img class="hero-img" src="/images/chapter-01.jpg" alt="">
</div>
<div class="text">
<p>The book cover and spine above and the images which follow were not part of the original Ormsby translation—they are taken from the 1880 edition of J. W. Clark, illustrated by Gustave Doré. Clark in his edition states that, “The English text of Don Quixote adopted in this edition is that of Jarvis, with occasional corrections from Motteaux.”</p>
<p>See in the introduction below John Ormsbys critique of both the Jarvis and Motteaux translations. It has been elected in the present Project Gutenberg edition to attach the famous engravings of Gustave Doré to the Ormsby translation instead of the Jarvis/Motteaux. The detail of many of the Doré engravings can be fully appreciated only by utilizing the “Full Size” button to expand them to their original dimensions. Ormsby in his Preface has criticized the fanciful nature of Dorés illustrations; others feel these woodcuts and steel engravings well match Quixotes dreams.</p>
</div>
</main>
</body>
<main class="wrapper">
<h2 class="title">{title}</h2>
<div class="hero">
<img class="hero-img" src="/images/chapter-01.jpg" alt="" />
</div>
<div class="text">
<p>
The book cover and spine above and the images which follow were not part of the original Ormsby translation—they are taken from the 1880 edition of J. W. Clark,
illustrated by Gustave Doré. Clark in his edition states that, “The English text of Don Quixote adopted in this edition is that of Jarvis, with occasional corrections
from Motteaux.”
</p>
<p>
See in the introduction below John Ormsbys critique of both the Jarvis and Motteaux translations. It has been elected in the present Project Gutenberg edition to attach
the famous engravings of Gustave Doré to the Ormsby translation instead of the Jarvis/Motteaux. The detail of many of the Doré engravings can be fully appreciated only by
utilizing the “Full Size” button to expand them to their original dimensions. Ormsby in his Preface has criticized the fanciful nature of Dorés illustrations; others
feel these woodcuts and steel engravings well match Quixotes dreams.
</p>
</div>
</main>
</body>
</html>

View file

@ -1,5 +1,4 @@
---
import MainHead from '../../components/MainHead.astro';
import Nav from '../../components/Nav.astro';
import PostPreview from '../../components/PostPreview.astro';
@ -7,16 +6,16 @@ import Pagination from '../../components/Pagination.astro';
import authorData from '../../data/authors.json';
export function getStaticPaths() {
const allPosts = Astro.fetchContent<MarkdownFrontmatter>('../post/*.md');
let allAuthorsUnique = [...new Set(allPosts.map(p => p.author))];
return allAuthorsUnique.map(author => ({params: {author}, props: {allPosts}}));
const allPosts = Astro.fetchContent<MarkdownFrontmatter>('../post/*.md');
let allAuthorsUnique = [...new Set(allPosts.map((p) => p.author))];
return allAuthorsUnique.map((author) => ({ params: { author }, props: { allPosts } }));
}
interface MarkdownFrontmatter {
date: number;
description: string;
title: string;
author: string;
date: number;
description: string;
title: string;
author: string;
}
const { allPosts } = Astro.props;
@ -25,65 +24,58 @@ const title = 'Dons Blog';
const description = 'An example blog on Astro';
/** filter posts by author, sort by date */
const posts = allPosts
.filter((post) => post.author === params.author)
.sort((a, b) => new Date(b.date).valueOf() - new Date(a.date).valueOf());
const posts = allPosts.filter((post) => post.author === params.author).sort((a, b) => new Date(b.date).valueOf() - new Date(a.date).valueOf());
const author = authorData[posts[0].author];
---
<html lang="en">
<head>
<title>{title}</title>
<MainHead
title={title}
description={description}
image={posts[0].image}
canonicalURL={canonicalURL.toString()}
/>
<head>
<title>{title}</title>
<MainHead {title} {description} image={posts[0].image} canonicalURL={canonicalURL.toString()} />
<style lang="scss">
.title {
display: flex;
align-items: center;
justify-content: center;
font-size: 3em;
letter-spacing: -0.04em;
margin-top: 2rem;
margin-bottom: 0;
}
<style lang="scss">
.title {
display: flex;
align-items: center;
justify-content: center;
font-size: 3em;
letter-spacing: -0.04em;
margin-top: 2rem;
margin-bottom: 0;
}
.avatar {
width: 1em;
height: 1em;
margin-right: 0.5em;
border-radius: 50%;
overflow:hidden;
.avatar {
width: 1em;
height: 1em;
margin-right: 0.5em;
border-radius: 50%;
overflow: hidden;
&-img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
}
&-img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
}
.count {
font-size: 1em;
display: block;
text-align: center;
}
</style>
</head>
.count {
font-size: 1em;
display: block;
text-align: center;
}
</style>
</head>
<body>
<Nav title={title} />
<body>
<Nav {title} />
<main class="wrapper">
<h2 class="title">
<div class="avatar"><img class="avatar-img" src={author.image} alt="" /></div>
{author.name}
</h2>
{posts.map((post) => <PostPreview post={post} author={author} />)}
</main>
</body>
<main class="wrapper">
<h2 class="title">
<div class="avatar"><img class="avatar-img" src={author.image} alt="" /></div>
{author.name}
</h2>
{posts.map((post) => <PostPreview post={post} author={author} />)}
</main>
</body>
</html>

View file

@ -7,9 +7,9 @@ import Pagination from '../components/Pagination.astro';
import authorData from '../data/authors.json';
interface MarkdownFrontmatter {
date: number;
image: string;
author: string;
date: number;
image: string;
author: string;
}
// Component Script:
@ -28,26 +28,22 @@ let firstPage = allPosts.slice(0, 2);
// Full Astro Component Syntax:
// https://docs.astro.build/core-concepts/astro-components/
---
<html lang="en">
<head>
<title>{title}</title>
<MainHead
title={title}
description={description}
image={allPosts[0].image}
canonicalURL={canonicalURL}
/>
</head>
<head>
<title>{title}</title>
<MainHead {title} {description} image={allPosts[0].image} {canonicalURL} />
</head>
<body>
<Nav title={title} />
<body>
<Nav {title} />
<main class="wrapper">
{allPosts.map((post) => <PostPreview post={post} author={authorData[post.author]} />)}
</main>
<main class="wrapper">
{allPosts.map((post) => <PostPreview post={post} author={authorData[post.author]} />)}
</main>
<footer>
<Pagination prevUrl="/posts" nextUrl="/posts/2" />
</footer>
</body>
<footer>
<Pagination prevUrl="/posts" nextUrl="/posts/2" />
</footer>
</body>
</html>

View file

@ -5,26 +5,26 @@ import PostPreview from '../../components/PostPreview.astro';
import Pagination from '../../components/Pagination.astro';
import authorData from '../../data/authors.json';
export async function getStaticPaths({paginate, rss}) {
const allPosts = Astro.fetchContent<MarkdownFrontmatter>('../post/*.md');
const sortedPosts = allPosts.sort((a, b) => new Date(b.date).valueOf() - new Date(a.date).valueOf());
export async function getStaticPaths({ paginate, rss }) {
const allPosts = Astro.fetchContent<MarkdownFrontmatter>('../post/*.md');
const sortedPosts = allPosts.sort((a, b) => new Date(b.date).valueOf() - new Date(a.date).valueOf());
// Generate an RSS feed from this collection of posts.
// NOTE: This is disabled by default, since it requires `buildOptions.site` to be set in your "astro.config.mjs" file.
// rss({
// title: 'Dons Blog',
// description: 'An example blog on Astro',
// customData: `<language>en-us</language>`,
// items: sortedPosts.map(item => ({
// title: item.title,
// description: item.description,
// link: item.url,
// pubDate: item.date,
// })),
// });
// Generate an RSS feed from this collection of posts.
// NOTE: This is disabled by default, since it requires `buildOptions.site` to be set in your "astro.config.mjs" file.
// rss({
// title: 'Dons Blog',
// description: 'An example blog on Astro',
// customData: `<language>en-us</language>`,
// items: sortedPosts.map(item => ({
// title: item.title,
// description: item.description,
// link: item.url,
// pubDate: item.date,
// })),
// });
// Return a paginated collection of paths for all posts
return paginate(sortedPosts, {pageSize: 1});
// Return a paginated collection of paths for all posts
return paginate(sortedPosts, { pageSize: 1 });
}
// page
@ -34,55 +34,47 @@ let canonicalURL = Astro.request.canonicalURL;
// collection
interface MarkdownFrontmatter {
date: number;
description: string;
title: string;
date: number;
description: string;
title: string;
}
const { page } = Astro.props;
---
<html lang="en">
<head>
<title>{title}</title>
<MainHead
title={title}
description={description}
image={page.data[0].image}
canonicalURL={canonicalURL.toString()}
prev={page.url.prev}
next={page.url.next}
/>
<head>
<title>{title}</title>
<MainHead {title} {description} image={page.data[0].image} canonicalURL={canonicalURL.toString()} prev={page.url.prev} next={page.url.next} />
<style lang="scss">
.title {
font-size: 3em;
letter-spacing: -0.04em;
margin-top: 2rem;
margin-bottom: 0;
text-align: center;
}
<style lang="scss">
.title {
font-size: 3em;
letter-spacing: -0.04em;
margin-top: 2rem;
margin-bottom: 0;
text-align: center;
}
.count {
font-size: 1em;
display: block;
text-align: center;
}
</style>
</head>
.count {
font-size: 1em;
display: block;
text-align: center;
}
</style>
</head>
<body>
<Nav title={title} />
<body>
<Nav {title} />
<main class="wrapper">
<h2 class="title">All Posts</h2>
<small class="count">{page.start + 1}{page.end + 1} of {page.total}</small>
{page.data.map((post) => <PostPreview post={post} author={authorData[post.author]} />)}
</main>
<main class="wrapper">
<h2 class="title">All Posts</h2>
<small class="count">{page.start + 1}{page.end + 1} of {page.total}</small>
{page.data.map((post) => <PostPreview post={post} author={authorData[post.author]} />)}
</main>
<footer>
<Pagination prevUrl={page.url.prev} nextUrl={page.url.next} />
</footer>
</body>
<footer>
<Pagination prevUrl={page.url.prev} nextUrl={page.url.next} />
</footer>
</body>
</html>

View file

@ -1,25 +1,25 @@
body {
font-family: 'Spectral', serif;
line-height: 1.4;
font-family: 'Spectral', serif;
line-height: 1.4;
}
p {
line-height: 2;
line-height: 2;
}
a {
color: crimson;
color: crimson;
}
img {
max-width: 100%;
height: auto;
max-width: 100%;
height: auto;
}
.wrapper {
max-width: 60rem;
margin-left: auto;
margin-right: auto;
padding-left: 2rem;
padding-right: 2rem;
max-width: 60rem;
margin-left: auto;
margin-right: auto;
padding-left: 2rem;
padding-right: 2rem;
}

View file

@ -8,6 +8,6 @@
// @ts-check
export default /** @type {import('astro').AstroUserConfig} */ ({
// Enable the Preact renderer to support Preact JSX components.
renderers: ['@astrojs/renderer-preact'],
// Enable the Preact renderer to support Preact JSX components.
renderers: ['@astrojs/renderer-preact'],
});

View file

@ -1,16 +1,18 @@
---
export interface Props {
name: string;
href: string;
name: string;
href: string;
}
const { name, href } = Astro.props;
---
<style>
.author {
margin-bottom: 0.75rem;
}
</style>
<div class="author">
<p><a href={href}>{name}</a></p>
<p><a {href}>{name}</a></p>
</div>
<style>
.author {
margin-bottom: 0.75rem;
}
</style>

View file

@ -1,8 +1,8 @@
---
export interface Props {
title: string;
description: string;
permalink: string;
title: string;
description: string;
permalink: string;
}
const { title, description, permalink } = Astro.props;
---
@ -12,7 +12,6 @@ const { title, description, permalink } = Astro.props;
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<!-- Primary Meta Tags -->
<title>{title}</title>
<meta name="title" content={title} />
@ -34,4 +33,4 @@ const { title, description, permalink } = Astro.props;
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&family=IBM+Plex+Sans:wght@400;700&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&family=IBM+Plex+Sans:wght@400;700&display=swap" />

View file

@ -1,90 +1,90 @@
<style>
header {
padding-top: 1rem;
padding-bottom: 1rem;
height: 5rem;
}
article {
display: flex;
align-items: center;
justify-content: space-between;
}
.header-subitem {
display: flex;
flex-grow: 0;
gap: 0.5em;
align-items: center;
justify-content: center;
color: var(--theme-text-lighter);
font-size: initial;
padding: 0.5rem;
}
.header-subitem:hover {
color: var(--theme-accent);
}
.header-subitem svg {
width: 1.5rem;
height: 1.5rem;
}
@media (max-width: 32em) {
.header-subitem {
display: none;
}
}
h1 {
margin: 0;
font-size: 1.5rem;
max-width: 100%;
display: flex;
flex-grow: 1;
}
.logo {
transform: translateY(0.25rem);
}
svg {
width: 2.5rem;
height: 2.5rem;
}
h1 a {
text-decoration: none;
display: inline-flex;
}
</style>
<header class="wrapper">
<article>
<h1>
<a href="/">
<svg class="logo" width="32" height="32" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
#flame {
fill: #ff5d01;
}
#a {
fill: #000014;
}
</style>
<title>Logo</title>
<path
id="a"
fill-rule="evenodd"
clip-rule="evenodd"
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
/>
<path
id="flame"
fill-rule="evenodd"
clip-rule="evenodd"
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
/>
</svg>
<span>My Blog</span>
</a>
</h1>
</article>
<article>
<h1>
<a href="/">
<svg class="logo" width="32" height="32" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
#flame {
fill: #ff5d01;
}
#a {
fill: #000014;
}
</style>
<title>Logo</title>
<path
id="a"
fill-rule="evenodd"
clip-rule="evenodd"
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
></path>
<path
id="flame"
fill-rule="evenodd"
clip-rule="evenodd"
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
></path>
</svg>
<span>My Blog</span>
</a>
</h1>
</article>
</header>
<style>
header {
padding-top: 1rem;
padding-bottom: 1rem;
height: 5rem;
}
article {
display: flex;
align-items: center;
justify-content: space-between;
}
.header-subitem {
display: flex;
flex-grow: 0;
gap: 0.5em;
align-items: center;
justify-content: center;
color: var(--theme-text-lighter);
font-size: initial;
padding: 0.5rem;
}
.header-subitem:hover {
color: var(--theme-accent);
}
.header-subitem svg {
width: 1.5rem;
height: 1.5rem;
}
@media (max-width: 32em) {
.header-subitem {
display: none;
}
}
h1 {
margin: 0;
font-size: 1.5rem;
max-width: 100%;
display: flex;
flex-grow: 1;
}
.logo {
transform: translateY(0.25rem);
}
svg {
width: 2.5rem;
height: 2.5rem;
}
h1 a {
text-decoration: none;
display: inline-flex;
}
</style>

View file

@ -2,87 +2,87 @@
import Author from './Author.astro';
export interface Props {
title: string;
author: string;
publishDate: string;
heroImage: string;
alt: string;
title: string;
author: string;
publishDate: string;
heroImage: string;
alt: string;
}
const { title, author, publishDate, heroImage, alt } = Astro.props;
---
<div class="layout">
<article class="content">
<div>
<header>
{heroImage && <img width="720" height="420" class="hero-image" loading="lazy" src={heroImage} alt={alt} />}
<p class="publish-date">{publishDate}</p>
<h1 class="title">{title}</h1>
<Author name="@FredKSchott" href="https://twitter.com/FredKSchott" />
</header>
<main>
<slot />
</main>
</div>
</article>
<article class="content">
<div>
<header>
{heroImage && <img width="720" height="420" class="hero-image" loading="lazy" src={heroImage} alt={alt} />}
<p class="publish-date">{publishDate}</p>
<h1 class="title">{title}</h1>
<Author name="@FredKSchott" href="https://twitter.com/FredKSchott" />
</header>
<main>
<slot />
</main>
</div>
</article>
</div>
<style>
.hero-image {
width: 100vw;
object-fit: cover;
object-position: center;
margin-top: 2rem;
margin-bottom: 4rem;
max-width: 1280px;
}
.hero-image {
width: 100vw;
object-fit: cover;
object-position: center;
margin-top: 2rem;
margin-bottom: 4rem;
max-width: 1280px;
}
@media (max-width: 50em) {
.hero-image {
height: 260px;
margin-top: 0;
margin-bottom: 2rem;
}
}
@media (max-width: 50em) {
.hero-image {
height: 260px;
margin-top: 0;
margin-bottom: 2rem;
}
}
.content {
margin-bottom: 8rem;
}
.content {
margin-bottom: 8rem;
}
.content :global(main > * + *) {
margin-top: 1rem;
}
.content :global(main > * + *) {
margin-top: 1rem;
}
.content :global(h2) {
margin-top: 4rem;
}
.content :global(h2) {
margin-top: 4rem;
}
header {
display: flex;
flex-direction: column;
text-align: center;
align-items: center;
justify-content: center;
header {
display: flex;
flex-direction: column;
text-align: center;
align-items: center;
justify-content: center;
padding-bottom: 2rem;
margin-bottom: 2rem;
border-bottom: 4px solid var(--theme-divider);
}
padding-bottom: 2rem;
margin-bottom: 2rem;
border-bottom: 4px solid var(--theme-divider);
}
.title,
.author,
.publish-date {
margin: 0;
}
.title,
.author,
.publish-date {
margin: 0;
}
.publish-date,
.author {
color: var(--theme-text-lighter);
}
.publish-date,
.author {
color: var(--theme-text-lighter);
}
.title {
font-size: 2.25rem;
font-weight: 700;
}
.title {
font-size: 2.25rem;
font-weight: 700;
}
</style>

View file

@ -1,54 +1,55 @@
---
export interface Props {
post: any;
post: any;
}
const { post } = Astro.props;
---
<article class="post-preview">
<header>
<p class="publish-date">{post.publishDate}</p>
<a href={post.url}><h1 class="title">{post.title}</h1></a>
</header>
<p>{post.description}</p>
<a href={post.url}>Read more</a>
<header>
<p class="publish-date">{post.publishDate}</p>
<a href={post.url}><h1 class="title">{post.title}</h1></a>
</header>
<p>{post.description}</p>
<a href={post.url}>Read more</a>
</article>
<style>
.content :global(main > * + *) {
margin-top: 1rem;
}
.content :global(main > * + *) {
margin-top: 1rem;
}
.post-preview {
padding-bottom: 2rem;
margin-bottom: 2rem;
border-bottom: 4px solid var(--theme-divider);
}
.post-preview {
padding-bottom: 2rem;
margin-bottom: 2rem;
border-bottom: 4px solid var(--theme-divider);
}
header {
align-items: flex-start;
display: flex;
flex-direction: column;
justify-content: center;
padding-bottom: 2rem;
text-align: left;
}
header {
align-items: flex-start;
display: flex;
flex-direction: column;
justify-content: center;
padding-bottom: 2rem;
text-align: left;
}
.title,
.author,
.publish-date {
margin: 0;
}
.title,
.author,
.publish-date {
margin: 0;
}
.publish-date,
.author {
font-size: 1.25rem;
color: var(--theme-text-lighter);
}
.publish-date,
.author {
font-size: 1.25rem;
color: var(--theme-text-lighter);
}
.title {
font-size: 2.25rem;
font-weight: 700;
color: var(--theme-text);
}
.title {
font-size: 2.25rem;
font-weight: 700;
color: var(--theme-text);
}
</style>

View file

@ -1,9 +1,9 @@
<h1>
<slot/>
<slot />
</h1>
<style>
h1 {
color: red;
}
h1 {
color: red;
}
</style>

View file

@ -1,56 +1,86 @@
<svg class="logo" width="158" height="170" viewBox="0 0 158 170" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M96.5039 9.46441C97.4758 10.671 97.9714 12.2991 98.9626 15.5553L120.617 86.6902C112.611 82.5368 103.907 79.5413 94.7281 77.9252L80.6289 30.2798C80.3982 29.5002 79.6822 28.9654 78.8692 28.9654C78.0541 28.9654 77.3367 29.503 77.1079 30.2853L63.1795 77.9011C53.9579 79.51 45.2146 82.5109 37.1741 86.6793L58.9347 15.5388C59.929 12.2882 60.4262 10.6629 61.3981 9.45854C62.2562 8.39532 63.3723 7.56959 64.64 7.06003C66.076 6.48285 67.7756 6.48285 71.1749 6.48285H86.7174C90.1211 6.48285 91.823 6.48285 93.2603 7.06124C94.5291 7.575 95.6459 8.39925 96.5039 9.46441Z" fill="white" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M99.0951 90.0755C95.5253 93.1279 88.4002 95.2097 80.1929 95.2097C70.1197 95.2097 61.6767 92.0737 59.4363 87.8561C58.6354 90.2733 58.4558 93.0397 58.4558 94.8069C58.4558 94.8069 57.9281 103.485 63.9636 109.52C63.9636 106.386 66.5042 103.846 69.6381 103.846C75.0097 103.846 75.0036 108.532 74.9987 112.334C74.9986 112.448 74.9984 112.561 74.9984 112.673C74.9984 118.444 78.5255 123.391 83.5416 125.477C82.7924 123.936 82.3721 122.205 82.3721 120.377C82.3721 114.873 85.6034 112.823 89.3588 110.441C92.3469 108.546 95.6668 106.441 97.9548 102.217C99.1486 100.013 99.8265 97.4893 99.8265 94.8069C99.8265 93.1573 99.5702 91.5676 99.0951 90.0755Z" fill="#FF5D01" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M99.0951 90.0755C95.5253 93.1279 88.4002 95.2097 80.1929 95.2097C70.1197 95.2097 61.6767 92.0737 59.4363 87.8561C58.6354 90.2733 58.4558 93.0397 58.4558 94.8069C58.4558 94.8069 57.9281 103.485 63.9636 109.52C63.9636 106.386 66.5042 103.846 69.6381 103.846C75.0097 103.846 75.0036 108.532 74.9987 112.334C74.9986 112.448 74.9984 112.561 74.9984 112.673C74.9984 118.444 78.5255 123.391 83.5416 125.477C82.7924 123.936 82.3721 122.205 82.3721 120.377C82.3721 114.873 85.6034 112.823 89.3588 110.441C92.3469 108.546 95.6668 106.441 97.9548 102.217C99.1486 100.013 99.8265 97.4893 99.8265 94.8069C99.8265 93.1573 99.5702 91.5676 99.0951 90.0755Z" fill="url(#paint1_linear)" />
<path d="M11.9957 169.024C20.0117 169.024 24.8597 167.104 27.6917 163.12C27.6917 164.896 27.7877 166.576 28.0277 168.112H32.7797C32.3477 165.616 32.2517 163.984 32.2517 159.472V153.328C32.2517 146.704 27.1157 143.2 17.3237 143.2C7.8677 143.2 1.7237 146.848 0.955701 152.128H5.9957C6.7637 148.576 10.7477 146.704 17.3237 146.704C23.8037 146.704 27.6437 148.96 27.6437 152.8V153.28L12.6677 154.144C6.5717 154.48 4.3157 155.344 2.5877 156.592C0.955701 157.792 0.0437012 159.664 0.0437012 161.824C0.0437012 166.384 4.7477 169.024 11.9957 169.024ZM13.5317 165.616C7.9637 165.616 4.8917 164.32 4.8917 161.728C4.8917 158.944 6.8117 157.696 13.5797 157.264L27.6437 156.4V157.504C27.6437 162.544 21.7397 165.616 13.5317 165.616Z" fill="white" />
<path d="M55.9352 169.024C65.8712 169.024 69.8552 165.76 69.8552 161.008C69.8552 157.072 67.4072 155.056 61.1672 154.528L49.5032 153.616C46.3352 153.376 44.5592 152.464 44.5592 150.496C44.5592 148 47.2952 146.704 53.1992 146.704C59.9192 146.704 63.4232 148.048 65.7272 151.024L69.6152 149.152C67.2152 145.408 61.8872 143.2 53.6312 143.2C45.1352 143.2 40.0472 146.032 40.0472 150.688C40.0472 154.864 43.0712 156.88 48.7832 157.36L60.3512 158.272C64.1432 158.56 65.2952 159.328 65.2952 161.296C65.2952 164.128 62.3672 165.472 56.5592 165.472C49.5032 165.472 45.0392 163.552 42.8792 160.048L39.0872 162.112C42.0152 166.528 47.1512 169.024 55.9352 169.024Z" fill="white" />
<path d="M79.6765 147.712V159.28C79.6765 164.032 81.3085 168.784 90.1885 168.784C92.4445 168.784 95.1805 168.352 96.3805 167.824V163.936C94.7005 164.32 92.6845 164.608 90.7165 164.608C86.5405 164.608 84.2845 162.976 84.2845 158.848V147.712H96.2845V144.112H84.2845V136L79.6765 137.872V144.112H72.1404V147.712H79.6765Z" fill="white" />
<path d="M107.728 144.112H103.504V168.112H108.064V159.136C108.064 155.68 108.736 152.752 110.656 150.736C112.336 148.864 114.496 147.808 118.288 147.808C119.584 147.808 120.4 147.904 121.504 148.096V143.68C120.496 143.44 119.632 143.392 118.336 143.392C113.2 143.392 109.12 146.416 107.728 151.072V144.112Z" fill="white" />
<path d="M140.724 169.024C150.948 169.024 157.956 163.84 157.956 156.112C157.956 148.384 150.948 143.2 140.724 143.2C130.5 143.2 123.492 148.384 123.492 156.112C123.492 163.84 130.5 169.024 140.724 169.024ZM140.724 165.232C133.188 165.232 128.34 161.68 128.34 156.112C128.34 150.544 133.188 146.992 140.724 146.992C148.212 146.992 153.108 150.544 153.108 156.112C153.108 161.68 148.212 165.232 140.724 165.232Z" fill="white" />
<defs>
<linearGradient id="paint1_linear" x1="115.168" y1="65.245" x2="94.0326" y2="109.491" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF1639" />
<stop offset="1" stop-color="#FF1639" stop-opacity="0" />
</linearGradient>
</defs>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M96.5039 9.46441C97.4758 10.671 97.9714 12.2991 98.9626 15.5553L120.617 86.6902C112.611 82.5368 103.907 79.5413 94.7281 77.9252L80.6289 30.2798C80.3982 29.5002 79.6822 28.9654 78.8692 28.9654C78.0541 28.9654 77.3367 29.503 77.1079 30.2853L63.1795 77.9011C53.9579 79.51 45.2146 82.5109 37.1741 86.6793L58.9347 15.5388C59.929 12.2882 60.4262 10.6629 61.3981 9.45854C62.2562 8.39532 63.3723 7.56959 64.64 7.06003C66.076 6.48285 67.7756 6.48285 71.1749 6.48285H86.7174C90.1211 6.48285 91.823 6.48285 93.2603 7.06124C94.5291 7.575 95.6459 8.39925 96.5039 9.46441Z"
fill="white"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M99.0951 90.0755C95.5253 93.1279 88.4002 95.2097 80.1929 95.2097C70.1197 95.2097 61.6767 92.0737 59.4363 87.8561C58.6354 90.2733 58.4558 93.0397 58.4558 94.8069C58.4558 94.8069 57.9281 103.485 63.9636 109.52C63.9636 106.386 66.5042 103.846 69.6381 103.846C75.0097 103.846 75.0036 108.532 74.9987 112.334C74.9986 112.448 74.9984 112.561 74.9984 112.673C74.9984 118.444 78.5255 123.391 83.5416 125.477C82.7924 123.936 82.3721 122.205 82.3721 120.377C82.3721 114.873 85.6034 112.823 89.3588 110.441C92.3469 108.546 95.6668 106.441 97.9548 102.217C99.1486 100.013 99.8265 97.4893 99.8265 94.8069C99.8265 93.1573 99.5702 91.5676 99.0951 90.0755Z"
fill="#FF5D01"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M99.0951 90.0755C95.5253 93.1279 88.4002 95.2097 80.1929 95.2097C70.1197 95.2097 61.6767 92.0737 59.4363 87.8561C58.6354 90.2733 58.4558 93.0397 58.4558 94.8069C58.4558 94.8069 57.9281 103.485 63.9636 109.52C63.9636 106.386 66.5042 103.846 69.6381 103.846C75.0097 103.846 75.0036 108.532 74.9987 112.334C74.9986 112.448 74.9984 112.561 74.9984 112.673C74.9984 118.444 78.5255 123.391 83.5416 125.477C82.7924 123.936 82.3721 122.205 82.3721 120.377C82.3721 114.873 85.6034 112.823 89.3588 110.441C92.3469 108.546 95.6668 106.441 97.9548 102.217C99.1486 100.013 99.8265 97.4893 99.8265 94.8069C99.8265 93.1573 99.5702 91.5676 99.0951 90.0755Z"
fill="url(#paint1_linear)"
/>
<path
d="M11.9957 169.024C20.0117 169.024 24.8597 167.104 27.6917 163.12C27.6917 164.896 27.7877 166.576 28.0277 168.112H32.7797C32.3477 165.616 32.2517 163.984 32.2517 159.472V153.328C32.2517 146.704 27.1157 143.2 17.3237 143.2C7.8677 143.2 1.7237 146.848 0.955701 152.128H5.9957C6.7637 148.576 10.7477 146.704 17.3237 146.704C23.8037 146.704 27.6437 148.96 27.6437 152.8V153.28L12.6677 154.144C6.5717 154.48 4.3157 155.344 2.5877 156.592C0.955701 157.792 0.0437012 159.664 0.0437012 161.824C0.0437012 166.384 4.7477 169.024 11.9957 169.024ZM13.5317 165.616C7.9637 165.616 4.8917 164.32 4.8917 161.728C4.8917 158.944 6.8117 157.696 13.5797 157.264L27.6437 156.4V157.504C27.6437 162.544 21.7397 165.616 13.5317 165.616Z"
fill="white"
/>
<path
d="M55.9352 169.024C65.8712 169.024 69.8552 165.76 69.8552 161.008C69.8552 157.072 67.4072 155.056 61.1672 154.528L49.5032 153.616C46.3352 153.376 44.5592 152.464 44.5592 150.496C44.5592 148 47.2952 146.704 53.1992 146.704C59.9192 146.704 63.4232 148.048 65.7272 151.024L69.6152 149.152C67.2152 145.408 61.8872 143.2 53.6312 143.2C45.1352 143.2 40.0472 146.032 40.0472 150.688C40.0472 154.864 43.0712 156.88 48.7832 157.36L60.3512 158.272C64.1432 158.56 65.2952 159.328 65.2952 161.296C65.2952 164.128 62.3672 165.472 56.5592 165.472C49.5032 165.472 45.0392 163.552 42.8792 160.048L39.0872 162.112C42.0152 166.528 47.1512 169.024 55.9352 169.024Z"
fill="white"
/>
<path
d="M79.6765 147.712V159.28C79.6765 164.032 81.3085 168.784 90.1885 168.784C92.4445 168.784 95.1805 168.352 96.3805 167.824V163.936C94.7005 164.32 92.6845 164.608 90.7165 164.608C86.5405 164.608 84.2845 162.976 84.2845 158.848V147.712H96.2845V144.112H84.2845V136L79.6765 137.872V144.112H72.1404V147.712H79.6765Z"
fill="white"
/>
<path
d="M107.728 144.112H103.504V168.112H108.064V159.136C108.064 155.68 108.736 152.752 110.656 150.736C112.336 148.864 114.496 147.808 118.288 147.808C119.584 147.808 120.4 147.904 121.504 148.096V143.68C120.496 143.44 119.632 143.392 118.336 143.392C113.2 143.392 109.12 146.416 107.728 151.072V144.112Z"
fill="white"
/>
<path
d="M140.724 169.024C150.948 169.024 157.956 163.84 157.956 156.112C157.956 148.384 150.948 143.2 140.724 143.2C130.5 143.2 123.492 148.384 123.492 156.112C123.492 163.84 130.5 169.024 140.724 169.024ZM140.724 165.232C133.188 165.232 128.34 161.68 128.34 156.112C128.34 150.544 133.188 146.992 140.724 146.992C148.212 146.992 153.108 150.544 153.108 156.112C153.108 161.68 148.212 165.232 140.724 165.232Z"
fill="white"
/>
<defs>
<linearGradient id="paint1_linear" x1="115.168" y1="65.245" x2="94.0326" y2="109.491" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF1639" />
<stop offset="1" stop-color="#FF1639" stop-opacity="0" />
</linearGradient>
</defs>
</svg>
<style lang="scss">
.logo {
margin: 2rem auto;
}
.logo {
margin: 2rem auto;
}
.title {
font-family: var(--font-sans);
font-size: 1rem;
}
.title svg {
margin-right: -100%;
}
.title svg text {
font-size: 16px;
font-family: var(--font-sans);
}
.title svg text.span {
fill: white;
font-size: 16.2px;
transform: translate(0, 18px);
}
.title svg text.em {
fill: var(--color-green);
transform: translate(0, 36px);
}
.title {
font-family: var(--font-sans);
font-size: 1rem;
}
.title svg {
margin-right: -100%;
}
.title svg text {
font-size: 16px;
font-family: var(--font-sans);
}
.title svg text.span {
fill: white;
font-size: 16.2px;
transform: translate(0, 18px);
}
.title svg text.em {
fill: var(--color-green);
transform: translate(0, 36px);
}
@media (min-width: 40em) {
.title svg {
margin-right: 0;
margin-bottom: -40px;
}
.title svg text.span {
font-size: 16px;
}
.title svg text.em {
transform: translate(190px, 18px);
}
}
@media (min-width: 40em) {
.title svg {
margin-right: 0;
margin-bottom: -40px;
}
.title svg text.span {
font-size: 16px;
}
.title svg text.em {
transform: translate(190px, 18px);
}
}
</style>

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -3,23 +3,22 @@ import BaseHead from '../components/BaseHead.astro';
import BlogHeader from '../components/BlogHeader.astro';
import BlogPost from '../components/BlogPost.astro';
const {content} = Astro.props;
const {title, description, publishDate, author, heroImage, permalink, alt} = content;
const { content } = Astro.props;
const { title, description, publishDate, author, heroImage, permalink, alt } = content;
---
<html lang={ content.lang || 'en' }>
<head>
<BaseHead title={title} description={description} permalink={permalink} />
<link rel="stylesheet" href={Astro.resolve('../styles/blog.css')} />
</head>
<html lang={content.lang || 'en'}>
<head>
<BaseHead {title} {description} {permalink} />
<link rel="stylesheet" href={Astro.resolve('../styles/blog.css')} />
</head>
<body>
<BlogHeader />
<div class="wrapper">
<BlogPost title={title} author={author} heroImage={heroImage} publishDate={publishDate} alt={alt}>
<slot />
</BlogPost>
</div>
</body>
<body>
<BlogHeader />
<div class="wrapper">
<BlogPost {title} {author} {heroImage} {publishDate} {alt}>
<slot />
</BlogPost>
</div>
</body>
</html>

View file

@ -5,7 +5,7 @@ import BlogHeader from '../components/BlogHeader.astro';
import BlogPostPreview from '../components/BlogPostPreview.astro';
interface MarkdownFrontmatter {
publishDate: number;
publishDate: number;
}
// Component Script:
@ -24,59 +24,60 @@ allPosts = allPosts.sort((a, b) => new Date(b.publishDate).valueOf() - new Date(
// Full Astro Component Syntax:
// https://docs.astro.build/core-concepts/astro-components/
---
<html lang="en">
<head>
<BaseHead title={title} description={description} permalink={permalink} />
<link rel="stylesheet" href={Astro.resolve('../styles/blog.css')} />
<head>
<BaseHead {title} {description} {permalink} />
<link rel="stylesheet" href={Astro.resolve('../styles/blog.css')} />
<style>
header {
width: 100%;
height: 100%;
background-color: var(--theme-bg-offset);
display: flex;
align-items: center;
justify-content: center;
}
<style>
header {
width: 100%;
height: 100%;
background-color: var(--theme-bg-offset);
display: flex;
align-items: center;
justify-content: center;
}
.content {
margin-top: 4rem;
margin-bottom: 8rem;
}
.content {
margin-top: 4rem;
margin-bottom: 8rem;
}
.content :global(main > * + *) {
margin-top: 1rem;
}
.content :global(main > * + *) {
margin-top: 1rem;
}
.intro {
padding-bottom: 4rem;
margin-bottom: 2rem;
border-bottom: 4px solid var(--theme-divider);
}
.intro {
padding-bottom: 4rem;
margin-bottom: 2rem;
border-bottom: 4px solid var(--theme-divider);
}
.intro > * {
margin: 0;
}
.intro > * {
margin: 0;
}
.latest {
font-size: 2.5rem;
font-weight: 700;
}
</style>
</head>
.latest {
font-size: 2.5rem;
font-weight: 700;
}
</style>
</head>
<body>
<BlogHeader />
<div class="wrapper">
<main class="content">
<section class="intro">
<h1 class="latest">{title}</h1>
<p>{description}</p>
</section>
<section aria-label="Blog post list">
{allPosts.map(p => <BlogPostPreview post={p} />)}
</section>
</main>
</div>
</body>
<body>
<BlogHeader />
<div class="wrapper">
<main class="content">
<section class="intro">
<h1 class="latest">{title}</h1>
<p>{description}</p>
</section>
<section aria-label="Blog post list">
{allPosts.map((p) => <BlogPostPreview post={p} />)}
</section>
</main>
</div>
</body>
</html>

View file

@ -1,284 +1,284 @@
:root {
--font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
--font-body: 'IBM Plex Sans', var(--font-fallback);
--font-mono: 'IBM Plex Mono', Consolas, 'Andale Mono WT', 'Andale Mono', 'Lucida Console', 'Lucida Sans Typewriter', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono',
'Liberation Mono', 'Nimbus Mono L', Monaco, 'Courier New', Courier, monospace;
--font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
--font-body: 'IBM Plex Sans', var(--font-fallback);
--font-mono: 'IBM Plex Mono', Consolas, 'Andale Mono WT', 'Andale Mono', 'Lucida Console', 'Lucida Sans Typewriter', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono',
'Liberation Mono', 'Nimbus Mono L', Monaco, 'Courier New', Courier, monospace;
--color-white: #fff;
--color-black: #000014;
--color-white: #fff;
--color-black: #000014;
--color-gray-50: #f9fafb;
--color-gray-100: #f3f4f6;
--color-gray-200: #e5e7eb;
--color-gray-300: #d1d5db;
--color-gray-400: #9ca3af;
--color-gray-500: #6b7280;
--color-gray-600: #4b5563;
--color-gray-700: #374151;
--color-gray-800: #1f2937;
--color-gray-900: #111827;
--color-gray-50: #f9fafb;
--color-gray-100: #f3f4f6;
--color-gray-200: #e5e7eb;
--color-gray-300: #d1d5db;
--color-gray-400: #9ca3af;
--color-gray-500: #6b7280;
--color-gray-600: #4b5563;
--color-gray-700: #374151;
--color-gray-800: #1f2937;
--color-gray-900: #111827;
--color-blue: #3894ff;
--color-blue-rgb: 56, 148, 255;
--color-green: #17c083;
--color-green-rgb: 23, 192, 131;
--color-orange: #ff5d01;
--color-orange-rgb: 255, 93, 1;
--color-purple: #882de7;
--color-purple-rgb: 136, 45, 231;
--color-red: #ff1639;
--color-red-rgb: 255, 22, 57;
--color-yellow: #ffbe2d;
--color-yellow-rgb: 255, 190, 45;
--color-blue: #3894ff;
--color-blue-rgb: 56, 148, 255;
--color-green: #17c083;
--color-green-rgb: 23, 192, 131;
--color-orange: #ff5d01;
--color-orange-rgb: 255, 93, 1;
--color-purple: #882de7;
--color-purple-rgb: 136, 45, 231;
--color-red: #ff1639;
--color-red-rgb: 255, 22, 57;
--color-yellow: #ffbe2d;
--color-yellow-rgb: 255, 190, 45;
}
:root {
color-scheme: light;
--theme-accent: var(--color-orange);
--theme-accent-rgb: var(--color-orange-rgb);
--theme-accent-opacity: 0.1;
--theme-divider: var(--color-gray-100);
--theme-text: var(--color-gray-800);
--theme-text-light: var(--color-gray-600);
--theme-text-lighter: var(--color-gray-400);
--theme-bg: var(--color-white);
--theme-bg-offset: var(--color-gray-100);
--theme-bg-accent: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity));
--theme-code-inline-bg: var(--color-gray-100);
--theme-code-text: var(--color-gray-100);
--theme-code-bg: var(--color-gray-700);
color-scheme: light;
--theme-accent: var(--color-orange);
--theme-accent-rgb: var(--color-orange-rgb);
--theme-accent-opacity: 0.1;
--theme-divider: var(--color-gray-100);
--theme-text: var(--color-gray-800);
--theme-text-light: var(--color-gray-600);
--theme-text-lighter: var(--color-gray-400);
--theme-bg: var(--color-white);
--theme-bg-offset: var(--color-gray-100);
--theme-bg-accent: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity));
--theme-code-inline-bg: var(--color-gray-100);
--theme-code-text: var(--color-gray-100);
--theme-code-bg: var(--color-gray-700);
}
body {
background: var(--theme-bg);
color: var(--theme-text);
background: var(--theme-bg);
color: var(--theme-text);
}
:root.theme-dark {
color-scheme: dark;
--theme-accent-opacity: 0.3;
--theme-divider: var(--color-gray-900);
--theme-text: var(--color-gray-200);
--theme-text-light: var(--color-gray-400);
--theme-text-lighter: var(--color-gray-600);
--theme-bg: var(--color-black);
--theme-bg-offset: var(--color-gray-900);
--theme-code-inline-bg: var(--color-gray-800);
--theme-code-text: var(--color-gray-200);
--theme-code-bg: var(--color-gray-900);
color-scheme: dark;
--theme-accent-opacity: 0.3;
--theme-divider: var(--color-gray-900);
--theme-text: var(--color-gray-200);
--theme-text-light: var(--color-gray-400);
--theme-text-lighter: var(--color-gray-600);
--theme-bg: var(--color-black);
--theme-bg-offset: var(--color-gray-900);
--theme-code-inline-bg: var(--color-gray-800);
--theme-code-text: var(--color-gray-200);
--theme-code-bg: var(--color-gray-900);
}
::selection {
color: var(--theme-accent);
background-color: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity));
color: var(--theme-accent);
background-color: rgba(var(--theme-accent-rgb), var(--theme-accent-opacity));
}
* {
box-sizing: border-box;
margin: 0;
box-sizing: border-box;
margin: 0;
}
:root {
--user-font-scale: 1rem - 16px;
--max-width: calc(100% - 2rem);
--user-font-scale: 1rem - 16px;
--max-width: calc(100% - 2rem);
}
@media (min-width: 50em) {
:root {
--max-width: 40em;
}
:root {
--max-width: 40em;
}
}
body {
font-family: var(--font-body);
font-size: 1rem;
font-size: clamp(0.875rem, 0.4626rem + 1.0309vw + var(--user-font-scale), 1.125rem);
line-height: 1.625;
font-family: var(--font-body);
font-size: 1rem;
font-size: clamp(0.875rem, 0.4626rem + 1.0309vw + var(--user-font-scale), 1.125rem);
line-height: 1.625;
}
.wrapper {
margin-left: auto;
margin-right: auto;
max-width: 65em;
padding-left: 2rem;
padding-right: 2rem;
width: 100%;
margin-left: auto;
margin-right: auto;
max-width: 65em;
padding-left: 2rem;
padding-right: 2rem;
width: 100%;
}
nav ul {
list-style: none;
padding: 0;
list-style: none;
padding: 0;
}
/* Typography */
:is(h1, h2, h3, h4, h5, h6) {
margin-bottom: 1.38rem;
font-weight: 400;
line-height: 1.3;
margin-bottom: 1.38rem;
font-weight: 400;
line-height: 1.3;
}
:is(h1, h2) {
max-width: 40ch;
max-width: 40ch;
}
:is(h2, h3):not(:first-child) {
margin-top: 3rem;
margin-top: 3rem;
}
h1 {
font-size: clamp(2.488rem, 1.924rem + 1.41vw, 3.052rem);
font-size: clamp(2.488rem, 1.924rem + 1.41vw, 3.052rem);
}
h2 {
font-size: clamp(2.074rem, 1.707rem + 0.9175vw, 2.441rem);
font-size: clamp(2.074rem, 1.707rem + 0.9175vw, 2.441rem);
}
h3 {
font-size: clamp(1.728rem, 1.503rem + 0.5625vw, 1.953rem);
font-size: clamp(1.728rem, 1.503rem + 0.5625vw, 1.953rem);
}
h4 {
font-size: clamp(1.44rem, 1.317rem + 0.3075vw, 1.563rem);
font-size: clamp(1.44rem, 1.317rem + 0.3075vw, 1.563rem);
}
h5 {
font-size: clamp(1.2rem, 1.15rem + 0.125vw, 1.25rem);
font-size: clamp(1.2rem, 1.15rem + 0.125vw, 1.25rem);
}
p {
color: var(--theme-text-light);
color: var(--theme-text-light);
}
small,
.text_small {
font-size: 0.833rem;
font-size: 0.833rem;
}
a {
color: var(--theme-accent);
font-weight: 400;
text-underline-offset: 0.08em;
text-decoration: none;
align-items: center;
gap: 0.5rem;
color: var(--theme-accent);
font-weight: 400;
text-underline-offset: 0.08em;
text-decoration: none;
align-items: center;
gap: 0.5rem;
}
a > code:not([class*='language']) {
position: relative;
color: var(--theme-accent);
background: transparent;
text-underline-offset: var(--padding-block);
position: relative;
color: var(--theme-accent);
background: transparent;
text-underline-offset: var(--padding-block);
}
a > code:not([class*='language'])::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
background: var(--theme-accent);
opacity: var(--theme-accent-opacity);
border-radius: var(--border-radius);
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
background: var(--theme-accent);
opacity: var(--theme-accent-opacity);
border-radius: var(--border-radius);
}
a:hover,
a:focus {
text-decoration: underline;
text-decoration: underline;
}
a:focus {
outline: 2px solid currentColor;
outline-offset: 0.25em;
outline: 2px solid currentColor;
outline-offset: 0.25em;
}
strong {
font-weight: 600;
color: inherit;
font-weight: 600;
color: inherit;
}
/* Supporting Content */
code:not([class*='language']) {
--border-radius: 3px;
--padding-block: 0.2rem;
--padding-inline: 0.33rem;
--border-radius: 3px;
--padding-block: 0.2rem;
--padding-inline: 0.33rem;
font-family: var(--font-mono);
font-size: 0.85em;
color: inherit;
background-color: var(--theme-code-inline-bg);
padding: var(--padding-block) var(--padding-inline);
margin: calc(var(--padding-block) * -1) -0.125em;
border-radius: var(--border-radius);
word-break: break-word;
font-family: var(--font-mono);
font-size: 0.85em;
color: inherit;
background-color: var(--theme-code-inline-bg);
padding: var(--padding-block) var(--padding-inline);
margin: calc(var(--padding-block) * -1) -0.125em;
border-radius: var(--border-radius);
word-break: break-word;
}
pre > code:not([class*='language']) {
background-color: transparent;
padding: 0;
margin: 0;
border-radius: 0;
color: inherit;
background-color: transparent;
padding: 0;
margin: 0;
border-radius: 0;
color: inherit;
}
pre {
position: relative;
background-color: var(--theme-code-bg);
color: var(--theme-code-text);
--padding-block: 1rem;
--padding-inline: 2rem;
padding: var(--padding-block) var(--padding-inline);
padding-right: calc(var(--padding-inline) * 2);
margin-left: calc(50vw - var(--padding-inline));
transform: translateX(-50vw);
position: relative;
background-color: var(--theme-code-bg);
color: var(--theme-code-text);
--padding-block: 1rem;
--padding-inline: 2rem;
padding: var(--padding-block) var(--padding-inline);
padding-right: calc(var(--padding-inline) * 2);
margin-left: calc(50vw - var(--padding-inline));
transform: translateX(-50vw);
line-height: 1.414;
width: calc(100vw + (var(--padding-inline) * 2));
max-width: calc(100% + (var(--padding-inline) * 2));
overflow-y: hidden;
overflow-x: auto;
line-height: 1.414;
width: calc(100vw + (var(--padding-inline) * 2));
max-width: calc(100% + (var(--padding-inline) * 2));
overflow-y: hidden;
overflow-x: auto;
}
@media (min-width: 37.75em) {
pre {
--padding-inline: 1.25rem;
border-radius: 8px;
}
pre {
--padding-inline: 1.25rem;
border-radius: 8px;
}
}
.flex {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
img.cover {
width: 100%;
max-height: 50vh;
object-fit: cover;
width: 100%;
max-height: 50vh;
object-fit: cover;
}
blockquote {
font-size: 1.5rem;
--padding-block: 1rem;
--padding-inline: 1.25rem;
--color: var(--theme-divider);
font-size: 1.5rem;
--padding-block: 1rem;
--padding-inline: 1.25rem;
--color: var(--theme-divider);
display: flex;
flex-direction: column;
display: flex;
flex-direction: column;
padding: var(--padding-block) var(--padding-inline);
margin-left: calc(var(--padding-inline) * -1);
margin-right: calc(var(--padding-inline) * -1);
padding: var(--padding-block) var(--padding-inline);
margin-left: calc(var(--padding-inline) * -1);
margin-right: calc(var(--padding-inline) * -1);
background: transparent;
border-left: calc(var(--padding-inline) / 2) solid var(--color);
border-radius: 0;
background: transparent;
border-left: calc(var(--padding-inline) / 2) solid var(--color);
border-radius: 0;
}
blockquote .source {
font-weight: 500;
color: var(--color);
font-size: 1rem;
font-weight: 500;
color: var(--color);
font-size: 1rem;
}

View file

@ -8,6 +8,6 @@
// @ts-check
export default /** @type {import('astro').AstroUserConfig} */ ({
// Comment out "renderers: []" to enable Astro's default component support.
renderers: [],
// Comment out "renderers: []" to enable Astro's default component support.
renderers: [],
});

View file

@ -1,29 +1,24 @@
---
import * as Component from '@example/my-component'
import * as Component from '@example/my-component';
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Welcome to Astro</title>
<style global>
h {
display: block;
font-size: 2em;
font-weight: bold;
margin-block: 0.67em;
}
</style>
</head>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Welcome to Astro</title>
<style global>
h {
display: block;
font-size: 2em;
font-weight: bold;
margin-block: 0.67em;
}
</style>
</head>
<body>
<Component.Heading>
Welcome to Astro
</Component.Heading>
<Component.Button>
Plain Button
</Component.Button>
</body>
<body>
<Component.Heading>Welcome to Astro</Component.Heading>
<Component.Button>Plain Button</Component.Button>
</body>
</html>

View file

@ -1,15 +1,13 @@
---
export interface Props extends Record<any, any> {
type?: string
type?: string;
}
const {
type,
...props
} = {
...Astro.props
} as Props
const { type, ...props } = {
...Astro.props,
} as Props;
props.type = type || 'button'
props.type = type || 'button';
---
<button {...props}><slot /></button>

View file

@ -1,18 +1,15 @@
---
export interface Props extends Record<any, any> {
level?: number | string
role?: string
level?: number | string;
role?: string;
}
const {
level,
role,
...props
} = {
...Astro.props
} as Props
const { level, role, ...props } = {
...Astro.props,
} as Props;
props.role = role || 'heading'
props['aria-level'] = level || '1'
props.role = role || 'heading';
props['aria-level'] = level || '1';
---
<h {...props}><slot /></h>

View file

@ -8,10 +8,10 @@
// @ts-check
export default /** @type {import('astro').AstroUserConfig} */ ({
renderers: [
// Enable the Preact renderer to support Preact JSX components.
'@astrojs/renderer-preact',
// Enable the React renderer, for the Algolia search component
'@astrojs/renderer-react',
],
renderers: [
// Enable the Preact renderer to support Preact JSX components.
'@astrojs/renderer-preact',
// Enable the React renderer, for the Algolia search component
'@astrojs/renderer-react',
],
});

View file

@ -1,3 +1,3 @@
Array.from(document.getElementsByTagName('pre')).forEach((element) => {
element.setAttribute('tabindex', '0');
element.setAttribute('tabindex', '0');
});

View file

@ -1,151 +1,149 @@
---
// fetch all commits for just this page's path
const path = "docs/" + Astro.props.path;
const path = 'docs/' + Astro.props.path;
const url = `https://api.github.com/repos/withastro/astro/commits?path=${path}`;
const commitsURL = `https://github.com/withastro/astro/commits/main/${path}`;
async function getCommits(url) {
try {
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN;
if (!token) {
throw new Error(
'Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.'
);
}
try {
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN;
if (!token) {
throw new Error('Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.');
}
const auth = `Basic ${Buffer.from(token, "binary").toString("base64")}`;
const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`;
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: auth,
"User-Agent": "astro-docs/1.0",
},
});
const res = await fetch(url, {
method: 'GET',
headers: {
Authorization: auth,
'User-Agent': 'astro-docs/1.0',
},
});
const data = await res.json();
const data = await res.json();
if (!res.ok) {
throw new Error(
`Request to fetch commits failed. Reason: ${res.statusText}
if (!res.ok) {
throw new Error(
`Request to fetch commits failed. Reason: ${res.statusText}
Message: ${data.message}`
);
}
);
}
return data;
} catch (e) {
console.warn(`[error] /src/components/AvatarList.astro
return data;
} catch (e) {
console.warn(`[error] /src/components/AvatarList.astro
${e?.message ?? e}`);
return new Array();
}
return new Array();
}
}
function removeDups(arr) {
if (!arr) {
return new Array();
}
let map = new Map();
if (!arr) {
return new Array();
}
let map = new Map();
for (let item of arr) {
let author = item.author;
// Deduplicate based on author.id
map.set(author.id, { login: author.login, id: author.id });
}
for (let item of arr) {
let author = item.author;
// Deduplicate based on author.id
map.set(author.id, { login: author.login, id: author.id });
}
return Array.from(map.values());
return Array.from(map.values());
}
const data = await getCommits(url);
const unique = removeDups(data);
const recentContributors = unique.slice(0, 3); // only show avatars for the 3 most recent contributors
const additionalContributors = unique.length - recentContributors.length; // list the rest of them as # of extra contributors
---
<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
<div class="contributors">
<ul class="avatar-list" style={`--avatar-count: ${recentContributors.length}`}>
{recentContributors.map((item) => (
<li><a href={`https://github.com/${item.login}`}><img alt={`Contributor ${item.login}`} title={`Contributor ${item.login}`} width="64" height="64" src={`https://avatars.githubusercontent.com/u/${item.id}`}/></a></li>
))}
</ul>
{additionalContributors > 0 && <span><a href={commitsURL}>{`and ${additionalContributors} additional contributor${additionalContributors > 1 ? 's' : ''}.`}</a></span>}
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
<ul class="avatar-list" style={`--avatar-count: ${recentContributors.length}`}>
{recentContributors.map((item) => (
<li>
<a href={`https://github.com/${item.login}`}>
<img alt={`Contributor ${item.login}`} title={`Contributor ${item.login}`} width="64" height="64" src={`https://avatars.githubusercontent.com/u/${item.id}`} />
</a>
</li>
))}
</ul>
{additionalContributors > 0 && (
<span>
<a href={commitsURL}>{`and ${additionalContributors} additional contributor${additionalContributors > 1 ? 's' : ''}.`}</a>
</span>
)}
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
</div>
<style>
.avatar-list {
--avatar-size: 2.5rem;
--avatar-count: 3;
.avatar-list {
--avatar-size: 2.5rem;
--avatar-count: 3;
display: grid;
list-style: none;
/* Default to displaying most of the avatar to
display: grid;
list-style: none;
/* Default to displaying most of the avatar to
enable easier access on touch devices, ensuring
the WCAG touch target size is met or exceeded */
grid-template-columns: repeat(
var(--avatar-count),
max(44px, calc(var(--avatar-size) / 1.15))
);
/* `padding` matches added visual dimensions of
grid-template-columns: repeat(var(--avatar-count), max(44px, calc(var(--avatar-size) / 1.15)));
/* `padding` matches added visual dimensions of
the `box-shadow` to help create a more accurate
computed component size */
padding: 0.08em;
font-size: var(--avatar-size);
}
padding: 0.08em;
font-size: var(--avatar-size);
}
@media (any-hover: hover) and (any-pointer: fine) {
.avatar-list {
/* We create 1 extra cell to enable the computed
@media (any-hover: hover) and (any-pointer: fine) {
.avatar-list {
/* We create 1 extra cell to enable the computed
width to match the final visual width */
grid-template-columns: repeat(
calc(var(--avatar-count) + 1),
calc(var(--avatar-size) / 1.75)
);
}
}
grid-template-columns: repeat(calc(var(--avatar-count) + 1), calc(var(--avatar-size) / 1.75));
}
}
.avatar-list li {
width: var(--avatar-size);
height: var(--avatar-size);
}
.avatar-list li {
width: var(--avatar-size);
height: var(--avatar-size);
}
.avatar-list li:hover ~ li a,
.avatar-list li:focus-within ~ li a {
transform: translateX(33%);
}
.avatar-list li:hover ~ li a,
.avatar-list li:focus-within ~ li a {
transform: translateX(33%);
}
.avatar-list img,
.avatar-list a {
display: block;
border-radius: 50%;
}
.avatar-list img,
.avatar-list a {
display: block;
border-radius: 50%;
}
.avatar-list a {
transition: transform 180ms ease-in-out;
}
.avatar-list a {
transition: transform 180ms ease-in-out;
}
.avatar-list img {
width: 100%;
height: 100%;
object-fit: cover;
background-color: #fff;
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
}
.avatar-list img {
width: 100%;
height: 100%;
object-fit: cover;
background-color: #fff;
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
}
.avatar-list a:focus {
outline: 2px solid transparent;
/* Double-layer trick to work for dark and light backgrounds */
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
}
.avatar-list a:focus {
outline: 2px solid transparent;
/* Double-layer trick to work for dark and light backgrounds */
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
}
.contributors {
display: flex;
align-items: center;
}
.contributors {
display: flex;
align-items: center;
}
.contributors > * + * {
margin-left: .75rem;
}
.contributors > * + * {
margin-left: 0.75rem;
}
</style>

View file

@ -4,13 +4,13 @@ const { path } = Astro.props;
---
<footer>
<AvatarList path={path} />
<AvatarList {path} />
</footer>
<style>
footer {
margin-top: auto;
padding: 2rem 0;
border-top: 3px solid var(--theme-divider);
}
footer {
margin-top: auto;
padding: 2rem 0;
border-top: 3px solid var(--theme-divider);
}
</style>

View file

@ -1,11 +1,11 @@
<!-- Global Metadata -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="alternate icon" type="image/x-icon" href="/favicon.ico" />
<link rel="sitemap" href="/sitemap.xml"/>
<link rel="sitemap" href="/sitemap.xml" />
<!-- Global CSS -->
<link rel="stylesheet" href={Astro.resolve('../styles/theme.css')} />
@ -13,22 +13,22 @@
<link rel="stylesheet" href={Astro.resolve('../styles/index.css')} />
<!-- Preload Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap" rel="stylesheet" />
<!-- Scrollable a11y code helper -->
<script type="module" src="/make-scrollable-code-focusable.js" />
<script type="module" src="/make-scrollable-code-focusable.js"></script>
<!-- This is intentionally inlined to avoid FOUC -->
<script>
const root = document.documentElement;
const theme = localStorage.getItem('theme');
if (theme === 'dark' || (!theme) && window.matchMedia('(prefers-color-scheme: dark)').matches) {
root.classList.add('theme-dark');
} else {
root.classList.remove('theme-dark');
}
const root = document.documentElement;
const theme = localStorage.getItem('theme');
if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
root.classList.add('theme-dark');
} else {
root.classList.remove('theme-dark');
}
</script>
<!-- Global site tag (gtag.js) - Google Analytics -->

View file

@ -1,36 +1,37 @@
---
import {SITE, OPEN_GRAPH} from '../config.ts';
import { SITE, OPEN_GRAPH } from '../config.ts';
export interface Props {
content: any,
site: any,
canonicalURL: URL | string,
};
content: any;
site: any;
canonicalURL: URL | string;
}
const { content = {}, canonicalURL } = Astro.props;
const formattedContentTitle = content.title ? `${content.title} 🚀 ${SITE.title}` : SITE.title;
const imageSrc = content?.image?.src ?? OPEN_GRAPH.image.src;
const canonicalImageSrc = new URL(imageSrc, Astro.site);
const imageAlt = content?.image?.alt ?? OPEN_GRAPH.image.alt;
---
<!-- Page Metadata -->
<link rel="canonical" href={canonicalURL}/>
<link rel="canonical" href={canonicalURL} />
<!-- OpenGraph Tags -->
<meta property="og:title" content={formattedContentTitle}/>
<meta property="og:type" content="article"/>
<meta property="og:url" content={canonicalURL}/>
<meta property="og:locale" content={content.ogLocale ?? SITE.defaultLanguage}/>
<meta property="og:image" content={canonicalImageSrc}/>
<meta property="og:image:alt" content={imageAlt}/>
<meta name="description" property="og:description" content={content.description ? content.description : SITE.description}/>
<meta property="og:site_name" content={SITE.title}/>
<meta property="og:title" content={formattedContentTitle} />
<meta property="og:type" content="article" />
<meta property="og:url" content={canonicalURL} />
<meta property="og:locale" content={content.ogLocale ?? SITE.defaultLanguage} />
<meta property="og:image" content={canonicalImageSrc} />
<meta property="og:image:alt" content={imageAlt} />
<meta name="description" property="og:description" content={content.description ? content.description : SITE.description} />
<meta property="og:site_name" content={SITE.title} />
<!-- Twitter Tags -->
<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:site" content={OPEN_GRAPH.twitter}/>
<meta name="twitter:title" content={formattedContentTitle}/>
<meta name="twitter:description" content={content.description ? content.description : SITE.description}/>
<meta name="twitter:image" content={canonicalImageSrc}/>
<meta name="twitter:image:alt" content={imageAlt}/>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content={OPEN_GRAPH.twitter} />
<meta name="twitter:title" content={formattedContentTitle} />
<meta name="twitter:description" content={content.description ? content.description : SITE.description} />
<meta name="twitter:image" content={canonicalImageSrc} />
<meta name="twitter:image:alt" content={imageAlt} />
<!--
TODO: Add json+ld data, maybe https://schema.org/APIReference makes sense?

View file

@ -1,18 +1,27 @@
---
const {size} = Astro.props;
const { size } = Astro.props;
---
<svg class="logo" width={size} height={size} viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
#flame {
fill: var(--theme-text-accent);
}
#a {
fill: var(--theme-text-accent);
}
</style>
<title>Logo</title>
<path id="a" fill-rule="evenodd" clip-rule="evenodd"
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z" />
<path id="flame" fill-rule="evenodd" clip-rule="evenodd"
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z" />
<style>
#flame {
fill: var(--theme-text-accent);
}
#a {
fill: var(--theme-text-accent);
}
</style>
<title>Logo</title>
<path
id="a"
fill-rule="evenodd"
clip-rule="evenodd"
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
></path>
<path
id="flame"
fill-rule="evenodd"
clip-rule="evenodd"
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
></path>
</svg>

View file

@ -5,128 +5,133 @@ import AstroLogo from './AstroLogo.astro';
import SkipToContent from './SkipToContent.astro';
import SidebarToggle from './SidebarToggle.tsx';
import LanguageSelect from './LanguageSelect.tsx';
import Search from "./Search.tsx";
import Search from './Search.tsx';
const {currentPage} = Astro.props;
const { currentPage } = Astro.props;
const lang = currentPage && getLanguageFromURL(currentPage);
---
<style>
header {
z-index: 11;
height: var(--theme-navbar-height);
width: 100%;
background-color: var(--theme-navbar-bg);
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
position: sticky;
top: 0;
}
.logo {
display: flex;
overflow: hidden;
width: 30px;
font-size: 2rem;
flex-shrink: 0;
font-weight: 600;
line-height: 1;
color: hsla(var(--color-base-white), 100%, 1);
gap: 0.25em;
z-index: -1;
}
.logo a {
padding: 0.5em 0.25em;
margin: -0.5em -0.25em;
text-decoration: none;
font-weight: bold;
}
.logo a {
transition: color 100ms ease-out;
color: var(--theme-text);
}
.logo a:hover,
.logo a:focus {
color: var(--theme-text-accent);
}
.logo h1 {
font: inherit;
color: inherit;
margin: 0;
}
.nav-wrapper {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 1em;
width: 100%;
max-width: 82em;
padding: 0 1rem;
}
@media (min-width: 50em) {
header {
position: static;
padding: 2rem 0rem;
}
.logo {
width: auto;
margin: 0;
z-index: 0;
}
.menu-toggle {
display: none;
}
.logo {
width: auto;
}
}
/** Style Algolia */
:root {
--docsearch-primary-color: var(--theme-accent);
--docsearch-logo-color: var(--theme-text);
}
.search-item {
display: none;
position: relative;
z-index: 10;
flex-grow: 1;
padding-right: 0.7rem;
display: flex;
max-width: 200px;
}
:global(.search-item > *) {
flex-grow: 1;
}
@media (min-width: 50em) {
.search-item {
max-width: 400px;
}
}
</style>
<header>
<SkipToContent />
<nav class="nav-wrapper" title="Top Navigation">
<div class="menu-toggle">
<SidebarToggle client:idle/>
</div>
<div class="logo flex">
<AstroLogo size={40} />
<a href="/">
<h1>Documentation</h1>
</a>
</div>
<div style="flex-grow: 1;"></div>
{KNOWN_LANGUAGE_CODES.length > 1 && <LanguageSelect lang={lang} client:idle />}
{CONFIG.ALGOLIA && <div class="search-item"><Search client:idle /></div>}
</nav>
<SkipToContent />
<nav class="nav-wrapper" title="Top Navigation">
<div class="menu-toggle">
<SidebarToggle client:idle />
</div>
<div class="logo flex">
<AstroLogo size={40} />
<a href="/">
<h1>Documentation</h1>
</a>
</div>
<div style="flex-grow: 1;"></div>
{KNOWN_LANGUAGE_CODES.length > 1 && <LanguageSelect lang={lang} client:idle />}
{CONFIG.ALGOLIA && (
<div class="search-item">
<Search client:idle />
</div>
)}
</nav>
</header>
<style>
header {
z-index: 11;
height: var(--theme-navbar-height);
width: 100%;
background-color: var(--theme-navbar-bg);
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
position: sticky;
top: 0;
}
.logo {
display: flex;
overflow: hidden;
width: 30px;
font-size: 2rem;
flex-shrink: 0;
font-weight: 600;
line-height: 1;
color: hsla(var(--color-base-white), 100%, 1);
gap: 0.25em;
z-index: -1;
}
.logo a {
padding: 0.5em 0.25em;
margin: -0.5em -0.25em;
text-decoration: none;
font-weight: bold;
}
.logo a {
transition: color 100ms ease-out;
color: var(--theme-text);
}
.logo a:hover,
.logo a:focus {
color: var(--theme-text-accent);
}
.logo h1 {
font: inherit;
color: inherit;
margin: 0;
}
.nav-wrapper {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 1em;
width: 100%;
max-width: 82em;
padding: 0 1rem;
}
@media (min-width: 50em) {
header {
position: static;
padding: 2rem 0rem;
}
.logo {
width: auto;
margin: 0;
z-index: 0;
}
.menu-toggle {
display: none;
}
.logo {
width: auto;
}
}
/** Style Algolia */
:root {
--docsearch-primary-color: var(--theme-accent);
--docsearch-logo-color: var(--theme-text);
}
.search-item {
display: none;
position: relative;
z-index: 10;
flex-grow: 1;
padding-right: 0.7rem;
display: flex;
max-width: 200px;
}
:global(.search-item > *) {
flex-grow: 1;
}
@media (min-width: 50em) {
.search-item {
max-width: 400px;
}
}
</style>

View file

@ -1,47 +1,47 @@
.language-select {
flex-grow: 1;
width: 48px;
box-sizing: border-box;
margin: 0;
padding: 0.33em 0.5em;
overflow: visible;
font-weight: 500;
font-size: 1rem;
font-family: inherit;
line-height: inherit;
background-color: var(--theme-bg);
border-color: var(--theme-text-lighter);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
outline: 0;
cursor: pointer;
transition-timing-function: ease-out;
transition-duration: 0.2s;
transition-property: border-color, color;
-webkit-font-smoothing: antialiased;
padding-left: 30px;
padding-right: 1rem;
flex-grow: 1;
width: 48px;
box-sizing: border-box;
margin: 0;
padding: 0.33em 0.5em;
overflow: visible;
font-weight: 500;
font-size: 1rem;
font-family: inherit;
line-height: inherit;
background-color: var(--theme-bg);
border-color: var(--theme-text-lighter);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
outline: 0;
cursor: pointer;
transition-timing-function: ease-out;
transition-duration: 0.2s;
transition-property: border-color, color;
-webkit-font-smoothing: antialiased;
padding-left: 30px;
padding-right: 1rem;
}
.language-select-wrapper .language-select:hover,
.language-select-wrapper .language-select:focus {
color: var(--theme-text);
border-color: var(--theme-text-light);
color: var(--theme-text);
border-color: var(--theme-text-light);
}
.language-select-wrapper {
color: var(--theme-text-light);
position: relative;
color: var(--theme-text-light);
position: relative;
}
.language-select-wrapper > svg {
position: absolute;
top: 7px;
left: 10px;
pointer-events: none;
position: absolute;
top: 7px;
left: 10px;
pointer-events: none;
}
@media (min-width: 50em) {
.language-select {
width: 100%;
}
.language-select {
width: 100%;
}
}

View file

@ -4,35 +4,35 @@ import './LanguageSelect.css';
import { KNOWN_LANGUAGES, langPathRegex } from '../../languages';
const LanguageSelect: FunctionalComponent<{ lang: string }> = ({ lang }) => {
return (
<div class="language-select-wrapper">
<svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88.6 77.3" height="1.2em" width="1.2em">
<path fill="currentColor" d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z" />
<path
fill="currentColor"
d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z"
/>
</svg>
<select
class="language-select"
value={lang}
onChange={(e) => {
const newLang = e.target.value;
let actualDest = window.location.pathname.replace(langPathRegex, '/');
if (actualDest == '/') actualDest = `/introduction`;
window.location.pathname = '/' + newLang + actualDest;
}}
>
{Object.keys(KNOWN_LANGUAGES).map((key) => {
return (
<option value={KNOWN_LANGUAGES[key]}>
<span>{key}</span>
</option>
);
})}
</select>
</div>
);
return (
<div class="language-select-wrapper">
<svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88.6 77.3" height="1.2em" width="1.2em">
<path fill="currentColor" d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z" />
<path
fill="currentColor"
d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z"
/>
</svg>
<select
class="language-select"
value={lang}
onChange={(e) => {
const newLang = e.target.value;
let actualDest = window.location.pathname.replace(langPathRegex, '/');
if (actualDest == '/') actualDest = `/introduction`;
window.location.pathname = '/' + newLang + actualDest;
}}
>
{Object.keys(KNOWN_LANGUAGES).map((key) => {
return (
<option value={KNOWN_LANGUAGES[key]}>
<span>{key}</span>
</option>
);
})}
</select>
</div>
);
};
export default LanguageSelect;

View file

@ -1,69 +1,69 @@
/** Style Algolia */
:root {
--docsearch-primary-color: var(--theme-accent);
--docsearch-logo-color: var(--theme-text);
--docsearch-primary-color: var(--theme-accent);
--docsearch-logo-color: var(--theme-text);
}
.search-input {
flex-grow: 1;
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 0.33em 0.5em;
overflow: visible;
font-weight: 500;
font-size: 1rem;
font-family: inherit;
line-height: inherit;
background-color: var(--theme-divider);
border-color: var(--theme-divider);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
outline: 0;
cursor: pointer;
transition-timing-function: ease-out;
transition-duration: 0.2s;
transition-property: border-color, color;
-webkit-font-smoothing: antialiased;
flex-grow: 1;
box-sizing: border-box;
width: 100%;
margin: 0;
padding: 0.33em 0.5em;
overflow: visible;
font-weight: 500;
font-size: 1rem;
font-family: inherit;
line-height: inherit;
background-color: var(--theme-divider);
border-color: var(--theme-divider);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
outline: 0;
cursor: pointer;
transition-timing-function: ease-out;
transition-duration: 0.2s;
transition-property: border-color, color;
-webkit-font-smoothing: antialiased;
}
.search-input:hover,
.search-input:focus {
color: var(--theme-text);
border-color: var(--theme-text-light);
color: var(--theme-text);
border-color: var(--theme-text-light);
}
.search-input:hover::placeholder,
.search-input:focus::placeholder {
color: var(--theme-text-light);
color: var(--theme-text-light);
}
.search-input::placeholder {
color: var(--theme-text-light);
color: var(--theme-text-light);
}
.search-hint {
position: absolute;
top: 7px;
right: 19px;
padding: 3px 5px;
display: none;
display: none;
align-items: center;
justify-content: center;
letter-spacing: 0.125em;
font-size: 13px;
font-family: var(--font-mono);
pointer-events: none;
border-color: var(--theme-text-lighter);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
line-height: 14px;
position: absolute;
top: 7px;
right: 19px;
padding: 3px 5px;
display: none;
display: none;
align-items: center;
justify-content: center;
letter-spacing: 0.125em;
font-size: 13px;
font-family: var(--font-mono);
pointer-events: none;
border-color: var(--theme-text-lighter);
color: var(--theme-text-light);
border-style: solid;
border-width: 1px;
border-radius: 0.25rem;
line-height: 14px;
}
@media (min-width: 50em) {
.search-hint {
display: flex;
}
.search-hint {
display: flex;
}
}
/* ------------------------------------------------------------ *\
@ -71,6 +71,6 @@
\* ------------------------------------------------------------ */
.DocSearch-Modal .DocSearch-Hit a {
box-shadow: none;
border: 1px solid var(--theme-accent);
box-shadow: none;
border: 1px solid var(--theme-accent);
}

View file

@ -7,71 +7,71 @@ import '@docsearch/css/dist/style.css';
import './Search.css';
export default function Search() {
const [isOpen, setIsOpen] = useState(false);
const searchButtonRef = useRef();
const [initialQuery, setInitialQuery] = useState(null);
const [isOpen, setIsOpen] = useState(false);
const searchButtonRef = useRef();
const [initialQuery, setInitialQuery] = useState(null);
const onOpen = useCallback(() => {
setIsOpen(true);
}, [setIsOpen]);
const onOpen = useCallback(() => {
setIsOpen(true);
}, [setIsOpen]);
const onClose = useCallback(() => {
setIsOpen(false);
}, [setIsOpen]);
const onClose = useCallback(() => {
setIsOpen(false);
}, [setIsOpen]);
const onInput = useCallback(
(e) => {
setIsOpen(true);
setInitialQuery(e.key);
},
[setIsOpen, setInitialQuery]
);
const onInput = useCallback(
(e) => {
setIsOpen(true);
setInitialQuery(e.key);
},
[setIsOpen, setInitialQuery]
);
useDocSearchKeyboardEvents({
isOpen,
onOpen,
onClose,
onInput,
searchButtonRef,
});
useDocSearchKeyboardEvents({
isOpen,
onOpen,
onClose,
onInput,
searchButtonRef,
});
return (
<>
<button type="button" ref={searchButtonRef} onClick={onOpen} className="search-input">
<svg width="24" height="24" fill="none">
<path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
<span>Search</span>
<span className="search-hint">
<span className="sr-only">Press </span>
<kbd>/</kbd>
<span className="sr-only"> to search</span>
</span>
</button>
{isOpen &&
createPortal(
<DocSearchModal
initialQuery={initialQuery}
initialScrollY={window.scrollY}
onClose={onClose}
indexName={(CONFIG as any).ALGOLIA.indexName}
apiKey={(CONFIG as any).ALGOLIA.apiKey}
transformItems={(items) => {
return items.map((item) => {
// We transform the absolute URL into a relative URL to
// work better on localhost, preview URLS.
const a = document.createElement('a');
a.href = item.url;
const hash = a.hash === '#overview' ? '' : a.hash;
return {
...item,
url: `${a.pathname}${hash}`,
};
});
}}
/>,
document.body
)}
</>
);
return (
<>
<button type="button" ref={searchButtonRef} onClick={onOpen} className="search-input">
<svg width="24" height="24" fill="none">
<path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
<span>Search</span>
<span className="search-hint">
<span className="sr-only">Press </span>
<kbd>/</kbd>
<span className="sr-only"> to search</span>
</span>
</button>
{isOpen &&
createPortal(
<DocSearchModal
initialQuery={initialQuery}
initialScrollY={window.scrollY}
onClose={onClose}
indexName={(CONFIG as any).ALGOLIA.indexName}
apiKey={(CONFIG as any).ALGOLIA.apiKey}
transformItems={(items) => {
return items.map((item) => {
// We transform the absolute URL into a relative URL to
// work better on localhost, preview URLS.
const a = document.createElement('a');
a.href = item.url;
const hash = a.hash === '#overview' ? '' : a.hash;
return {
...item,
url: `${a.pathname}${hash}`,
};
});
}}
/>,
document.body
)}
</>
);
}

View file

@ -3,25 +3,25 @@ import { h, Fragment } from 'preact';
import { useState, useEffect } from 'preact/hooks';
const MenuToggle: FunctionalComponent = () => {
const [sidebarShown, setSidebarShown] = useState(false);
const [sidebarShown, setSidebarShown] = useState(false);
useEffect(() => {
const body = document.getElementsByTagName('body')[0];
if (sidebarShown) {
body.classList.add('mobile-sidebar-toggle');
} else {
body.classList.remove('mobile-sidebar-toggle');
}
}, [sidebarShown]);
useEffect(() => {
const body = document.getElementsByTagName('body')[0];
if (sidebarShown) {
body.classList.add('mobile-sidebar-toggle');
} else {
body.classList.remove('mobile-sidebar-toggle');
}
}, [sidebarShown]);
return (
<button type="button" aria-pressed={sidebarShown ? 'true' : 'false'} id="menu-toggle" onClick={() => setSidebarShown(!sidebarShown)}>
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
<span className="sr-only">Toggle sidebar</span>
</button>
);
return (
<button type="button" aria-pressed={sidebarShown ? 'true' : 'false'} id="menu-toggle" onClick={() => setSidebarShown(!sidebarShown)}>
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
<span className="sr-only">Toggle sidebar</span>
</button>
);
};
export default MenuToggle;

View file

@ -1,21 +1,22 @@
<style>
.skiplink,
.skiplink:focus,
.skiplink:focus-visible {
position: absolute;
padding: 0.25em;
font-size: larger;
top: 0;
left: 0;
right: 0;
z-index: 9;
display: block;
text-align: center;
background-color: var(--theme-text-accent);
color: var(--theme-bg);
border-radius: 0.25em;
outline: var(--theme-bg) solid 1px;
outline-offset: 0;
}
</style>
<a href="#article" class="sr-only skiplink"><span>Skip to Content</span></a>
<style>
.skiplink,
.skiplink:focus,
.skiplink:focus-visible {
position: absolute;
padding: 0.25em;
font-size: larger;
top: 0;
left: 0;
right: 0;
z-index: 9;
display: block;
text-align: center;
background-color: var(--theme-text-accent);
color: var(--theme-bg);
border-radius: 0.25em;
outline: var(--theme-bg) solid 1px;
outline-offset: 0;
}
</style>

View file

@ -1,109 +1,111 @@
---
import { getLanguageFromURL } from '../../languages.ts';
import { SIDEBAR } from '../../config.ts';
const {currentPage} = Astro.props;
const { currentPage } = Astro.props;
const currentPageMatch = currentPage.slice(1);
const langCode = getLanguageFromURL(currentPage);
// SIDEBAR is a flat array. Group it by sections to properly render.
const sidebarSections = SIDEBAR[langCode].reduce((col, item) => {
if (item.header) {
col.push({...item, children: []});
} else {
col[col.length-1].children.push(item);
}
return col;
if (item.header) {
col.push({ ...item, children: [] });
} else {
col[col.length - 1].children.push(item);
}
return col;
}, []);
---
<nav aria-labelledby="grid-left">
<ul class="nav-groups">
{sidebarSections.map(section => (
<li>
<div class="nav-group">
<h2 class="nav-group-title">{section.text}</h2>
<ul>
{section.children.map(child => (
<li class="nav-link"><a href={`${Astro.site.pathname}${child.link}`} aria-current={`${currentPageMatch === child.link ? 'page' : 'false'}`}>{child.text}</a></li>
))}
</ul>
</div>
</li>
))}
</ul>
<ul class="nav-groups">
{sidebarSections.map((section) => (
<li>
<div class="nav-group">
<h2 class="nav-group-title">{section.text}</h2>
<ul>
{section.children.map((child) => (
<li class="nav-link">
<a href={`${Astro.site.pathname}${child.link}`} aria-current={`${currentPageMatch === child.link ? 'page' : 'false'}`}>
{child.text}
</a>
</li>
))}
</ul>
</div>
</li>
))}
</ul>
</nav>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
var target = document.querySelector('[aria-current="page"]');
if (target && (target.offsetTop > (window.innerHeight - 100))) {
document.querySelector('.nav-groups').scrollTop = target.offsetTop;
}
});
window.addEventListener('DOMContentLoaded', (event) => {
var target = document.querySelector('[aria-current="page"]');
if (target && target.offsetTop > window.innerHeight - 100) {
document.querySelector('.nav-groups').scrollTop = target.offsetTop;
}
});
</script>
<style>
nav {
width: 100%;
margin-right: 1rem;
}
.nav-groups {
height: 100%;
padding: 2rem 0;
overflow-x: visible;
overflow-y: auto;
max-height: 100vh;
}
nav {
width: 100%;
margin-right: 1rem;
}
.nav-groups {
height: 100%;
padding: 2rem 0;
overflow-x: visible;
overflow-y: auto;
max-height: 100vh;
}
.nav-groups > li + li {
margin-top: 2rem;
}
.nav-groups > li + li {
margin-top: 2rem;
}
.nav-groups > :first-child {
padding-top: var(--doc-padding);
}
.nav-groups > :first-child {
padding-top: var(--doc-padding);
}
.nav-groups > :last-child {
padding-bottom: 2rem;
margin-bottom: var(--theme-navbar-height);
}
.nav-groups > :last-child {
padding-bottom: 2rem;
margin-bottom: var(--theme-navbar-height);
}
.nav-group-title {
font-size: 1.0rem;
font-weight: 700;
padding: 0.1rem 1rem;
text-transform: uppercase;
margin-bottom: 0.5rem;
}
.nav-group-title {
font-size: 1rem;
font-weight: 700;
padding: 0.1rem 1rem;
text-transform: uppercase;
margin-bottom: 0.5rem;
}
.nav-link a {
font-size: 1.0rem;
margin: 1px;
padding: 0.3rem 1rem;
font: inherit;
color: inherit;
text-decoration: none;
display: block;
}
.nav-link a:hover,
.nav-link a:focus {
background-color: var(--theme-bg-hover);
}
.nav-link a {
font-size: 1rem;
margin: 1px;
padding: 0.3rem 1rem;
font: inherit;
color: inherit;
text-decoration: none;
display: block;
}
.nav-link a:hover,
.nav-link a:focus {
background-color: var(--theme-bg-hover);
}
.nav-link a[aria-current="page"] {
color: var(--theme-text-accent);
background-color: var(--theme-bg-accent);
font-weight: 600;
}
.nav-link a[aria-current='page'] {
color: var(--theme-text-accent);
background-color: var(--theme-bg-accent);
font-weight: 600;
}
:global(:root.theme-dark) .nav-link a[aria-current="page"] {
color: hsla(var(--color-base-white), 100%, 1);
}
@media (min-width: 50em) {
.nav-groups {
padding: 0;
}
}
:global(:root.theme-dark) .nav-link a[aria-current='page'] {
color: hsla(var(--color-base-white), 100%, 1);
}
@media (min-width: 50em) {
.nav-groups {
padding: 0;
}
}
</style>

View file

@ -2,41 +2,43 @@
import MoreMenu from '../RightSidebar/MoreMenu.astro';
import TableOfContents from '../RightSidebar/TableOfContents.tsx';
const {content, githubEditUrl} = Astro.props;
const { content, githubEditUrl } = Astro.props;
const title = content.title;
const headers = content.astro.headers;
---
<style>
.content {
padding: 0;
max-width: 75ch;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.content > section {
margin-bottom: 4rem;
}
.block {
display: block;
}
@media (min-width: 50em) {
.sm\:hidden {
display: none;
}
}
</style>
<article id="article" class="content">
<section class="main-section">
<h1 class="content-title" id="overview">{title}</h1>
<nav class="block sm:hidden">
<TableOfContents client:media="(max-width: 50em)" headers={headers} />
</nav>
<slot />
</section>
<nav class="block sm:hidden">
<MoreMenu editHref={githubEditUrl}/>
</nav>
<section class="main-section">
<h1 class="content-title" id="overview">{title}</h1>
<nav class="block sm:hidden">
<TableOfContents client:media="(max-width: 50em)" {headers} />
</nav>
<slot />
</section>
<nav class="block sm:hidden">
<MoreMenu editHref={githubEditUrl} />
</nav>
</article>
<style>
.content {
padding: 0;
max-width: 75ch;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.content > section {
margin-bottom: 4rem;
}
.block {
display: block;
}
@media (min-width: 50em) {
.sm\:hidden {
display: none;
}
}
</style>

View file

@ -1,68 +1,70 @@
---
import ThemeToggleButton from './ThemeToggleButton.tsx';
import * as CONFIG from '../../config';
const {editHref} = Astro.props;
const showMoreSection = (CONFIG.COMMUNITY_INVITE_URL || editHref);
const { editHref } = Astro.props;
const showMoreSection = CONFIG.COMMUNITY_INVITE_URL || editHref;
---
<style>
.edit-on-github {
text-decoration: none;
font: inherit;
color: inherit;
font-size: 1rem;
}
</style>
{showMoreSection && <h2 class="heading">More</h2>}
<ul>
{editHref &&
<li class={`header-link depth-2`}>
<a class="edit-on-github" href={editHref} target="_blank">
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="pen"
class="svg-inline--fa fa-pen fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
height="1em"
width="1em"
>
<path
fill="currentColor"
d="M290.74 93.24l128.02 128.02-277.99 277.99-114.14 12.6C11.35 513.54-1.56 500.62.14 485.34l12.7-114.22 277.9-277.88zm207.2-19.06l-60.11-60.11c-18.75-18.75-49.16-18.75-67.91 0l-56.55 56.55 128.02 128.02 56.55-56.55c18.75-18.76 18.75-49.16 0-67.91z"
></path>
</svg>
<span>Edit this page</span>
</a>
</li>
}
{CONFIG.COMMUNITY_INVITE_URL &&
<li class={`header-link depth-2`}>
<a href={CONFIG.COMMUNITY_INVITE_URL} target="_blank">
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="comment-alt"
class="svg-inline--fa fa-comment-alt fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
height="1em"
width="1em"
>
<path
fill="currentColor"
d="M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 9.8 11.2 15.5 19.1 9.7L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64z"
></path>
</svg>
<span>Join our community</span>
</a>
</li>
}
{editHref && (
<li class={`header-link depth-2`}>
<a class="edit-on-github" href={editHref} target="_blank">
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="pen"
class="svg-inline--fa fa-pen fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
height="1em"
width="1em"
>
<path
fill="currentColor"
d="M290.74 93.24l128.02 128.02-277.99 277.99-114.14 12.6C11.35 513.54-1.56 500.62.14 485.34l12.7-114.22 277.9-277.88zm207.2-19.06l-60.11-60.11c-18.75-18.75-49.16-18.75-67.91 0l-56.55 56.55 128.02 128.02 56.55-56.55c18.75-18.76 18.75-49.16 0-67.91z"
></path>
</svg>
<span>Edit this page</span>
</a>
</li>
)}
{CONFIG.COMMUNITY_INVITE_URL && (
<li class={`header-link depth-2`}>
<a href={CONFIG.COMMUNITY_INVITE_URL} target="_blank">
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="comment-alt"
class="svg-inline--fa fa-comment-alt fa-w-16"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
height="1em"
width="1em"
>
<path
fill="currentColor"
d="M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 9.8 11.2 15.5 19.1 9.7L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64z"
></path>
</svg>
<span>Join our community</span>
</a>
</li>
)}
</ul>
<div style="margin: 2rem 0; text-align: center;">
<ThemeToggleButton client:visible />
<ThemeToggleButton client:visible />
</div>
<style>
.edit-on-github {
text-decoration: none;
font: inherit;
color: inherit;
font-size: 1rem;
}
</style>

View file

@ -1,25 +1,27 @@
---
import TableOfContents from './TableOfContents.tsx';
import MoreMenu from './MoreMenu.astro';
const {content, githubEditUrl} = Astro.props;
const { content, githubEditUrl } = Astro.props;
const headers = content.astro.headers;
---
<style>
.sidebar-nav {
width: 100%;
position: sticky;
top: 0;
}
.sidebar-nav-inner {
height: 100%;
padding: 0;
padding-top: var(--doc-padding);
overflow: auto;
}
</style>
<nav class="sidebar-nav" aria-labelledby="grid-right">
<div class="sidebar-nav-inner">
<TableOfContents client:media="(min-width: 50em)" headers={headers} />
<MoreMenu editHref={githubEditUrl} />
</div>
<div class="sidebar-nav-inner">
<TableOfContents client:media="(min-width: 50em)" {headers} />
<MoreMenu editHref={githubEditUrl} />
</div>
</nav>
<style>
.sidebar-nav {
width: 100%;
position: sticky;
top: 0;
}
.sidebar-nav-inner {
height: 100%;
padding: 0;
padding-top: var(--doc-padding);
overflow: auto;
}
</style>

View file

@ -3,43 +3,43 @@ import { h, Fragment } from 'preact';
import { useState, useEffect, useRef } from 'preact/hooks';
const TableOfContents: FunctionalComponent<{ headers: any[] }> = ({ headers = [] }) => {
const itemOffsets = useRef([]);
const [activeId, setActiveId] = useState<string>(undefined);
const itemOffsets = useRef([]);
const [activeId, setActiveId] = useState<string>(undefined);
useEffect(() => {
const getItemOffsets = () => {
const titles = document.querySelectorAll('article :is(h1, h2, h3, h4)');
itemOffsets.current = Array.from(titles).map((title) => ({
id: title.id,
topOffset: title.getBoundingClientRect().top + window.scrollY,
}));
};
useEffect(() => {
const getItemOffsets = () => {
const titles = document.querySelectorAll('article :is(h1, h2, h3, h4)');
itemOffsets.current = Array.from(titles).map((title) => ({
id: title.id,
topOffset: title.getBoundingClientRect().top + window.scrollY,
}));
};
getItemOffsets();
window.addEventListener('resize', getItemOffsets);
getItemOffsets();
window.addEventListener('resize', getItemOffsets);
return () => {
window.removeEventListener('resize', getItemOffsets);
};
}, []);
return () => {
window.removeEventListener('resize', getItemOffsets);
};
}, []);
return (
<>
<h2 class="heading">On this page</h2>
<ul>
<li class={`header-link depth-2 ${activeId === 'overview' ? 'active' : ''}`.trim()}>
<a href="#overview">Overview</a>
</li>
{headers
.filter(({ depth }) => depth > 1 && depth < 4)
.map((header) => (
<li class={`header-link depth-${header.depth} ${activeId === header.slug ? 'active' : ''}`.trim()}>
<a href={`#${header.slug}`}>{header.text}</a>
</li>
))}
</ul>
</>
);
return (
<>
<h2 class="heading">On this page</h2>
<ul>
<li class={`header-link depth-2 ${activeId === 'overview' ? 'active' : ''}`.trim()}>
<a href="#overview">Overview</a>
</li>
{headers
.filter(({ depth }) => depth > 1 && depth < 4)
.map((header) => (
<li class={`header-link depth-${header.depth} ${activeId === header.slug ? 'active' : ''}`.trim()}>
<a href={`#${header.slug}`}>{header.text}</a>
</li>
))}
</ul>
</>
);
};
export default TableOfContents;

View file

@ -1,37 +1,37 @@
.theme-toggle {
display: inline-flex;
align-items: center;
gap: 0.25em;
padding: 0.33em 0.67em;
border-radius: 99em;
background-color: var(--theme-code-inline-bg);
display: inline-flex;
align-items: center;
gap: 0.25em;
padding: 0.33em 0.67em;
border-radius: 99em;
background-color: var(--theme-code-inline-bg);
}
.theme-toggle > label:focus-within {
outline: 2px solid transparent;
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
outline: 2px solid transparent;
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
}
.theme-toggle > label {
color: var(--theme-code-inline-text);
position: relative;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.5;
color: var(--theme-code-inline-text);
position: relative;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.5;
}
.theme-toggle .checked {
color: var(--theme-accent);
opacity: 1;
color: var(--theme-accent);
opacity: 1;
}
input[name='theme-toggle'] {
position: absolute;
opacity: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
position: absolute;
opacity: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
}

View file

@ -6,66 +6,66 @@ import './ThemeToggleButton.css';
const themes = ['light', 'dark'];
const icons = [
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
<path
fillRule="evenodd"
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
clipRule="evenodd"
/>
</svg>,
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>,
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
<path
fillRule="evenodd"
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
clipRule="evenodd"
/>
</svg>,
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>,
];
const ThemeToggle: FunctionalComponent = () => {
const [theme, setTheme] = useState(() => {
if (import.meta.env.SSR) {
return undefined;
}
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
});
const [theme, setTheme] = useState(() => {
if (import.meta.env.SSR) {
return undefined;
}
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
return localStorage.getItem('theme');
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
});
useEffect(() => {
const root = document.documentElement;
if (theme === 'light') {
root.classList.remove('theme-dark');
} else {
root.classList.add('theme-dark');
}
}, [theme]);
useEffect(() => {
const root = document.documentElement;
if (theme === 'light') {
root.classList.remove('theme-dark');
} else {
root.classList.add('theme-dark');
}
}, [theme]);
return (
<div class="theme-toggle">
{themes.map((t, i) => {
const icon = icons[i];
const checked = t === theme;
return (
<label className={checked ? ' checked' : ''}>
{icon}
<input
type="radio"
name="theme-toggle"
checked={checked}
value={t}
title={`Use ${t} theme`}
aria-label={`Use ${t} theme`}
onChange={() => {
localStorage.setItem('theme', t);
setTheme(t);
}}
/>
</label>
);
})}
</div>
);
return (
<div class="theme-toggle">
{themes.map((t, i) => {
const icon = icons[i];
const checked = t === theme;
return (
<label className={checked ? ' checked' : ''}>
{icon}
<input
type="radio"
name="theme-toggle"
checked={checked}
value={t}
title={`Use ${t} theme`}
aria-label={`Use ${t} theme`}
onChange={() => {
localStorage.setItem('theme', t);
setTheme(t);
}}
/>
</label>
);
})}
</div>
);
};
export default ThemeToggle;

View file

@ -1,19 +1,19 @@
export const SITE = {
title: 'Your Documentation Website',
description: 'Your website description.',
defaultLanguage: 'en_US',
title: 'Your Documentation Website',
description: 'Your website description.',
defaultLanguage: 'en_US',
};
export const OPEN_GRAPH = {
image: {
src: 'https://github.com/withastro/astro/blob/main/assets/social/banner.jpg?raw=true',
alt: 'astro logo on a starry expanse of space,' + ' with a purple saturn-like planet floating in the right foreground',
},
twitter: 'astrodotbuild',
image: {
src: 'https://github.com/withastro/astro/blob/main/assets/social/banner.jpg?raw=true',
alt: 'astro logo on a starry expanse of space,' + ' with a purple saturn-like planet floating in the right foreground',
},
twitter: 'astrodotbuild',
};
export const KNOWN_LANGUAGES = {
English: 'en',
English: 'en',
};
// Uncomment this to add an "Edit this page" button to every page of documentation.
@ -30,14 +30,14 @@ export const KNOWN_LANGUAGES = {
// }
export const SIDEBAR = {
en: [
{ text: '', header: true },
{ text: 'Section Header', header: true },
{ text: 'Introduction', link: 'en/introduction' },
{ text: 'Page 2', link: 'en/page-2' },
{ text: 'Page 3', link: 'en/page-3' },
en: [
{ text: '', header: true },
{ text: 'Section Header', header: true },
{ text: 'Introduction', link: 'en/introduction' },
{ text: 'Page 2', link: 'en/page-2' },
{ text: 'Page 3', link: 'en/page-3' },
{ text: 'Another Section', header: true },
{ text: 'Page 4', link: 'en/page-4' },
],
{ text: 'Another Section', header: true },
{ text: 'Page 4', link: 'en/page-4' },
],
};

View file

@ -5,6 +5,6 @@ export const KNOWN_LANGUAGE_CODES = Object.values(KNOWN_LANGUAGES);
export const langPathRegex = /\/([a-z]{2}-?[A-Z]{0,2})\//;
export function getLanguageFromURL(pathname: string) {
const langCodeMatch = pathname.match(langPathRegex);
return langCodeMatch ? langCodeMatch[1] : 'en';
const langCodeMatch = pathname.match(langPathRegex);
return langCodeMatch ? langCodeMatch[1] : 'en';
}

View file

@ -1,122 +1,122 @@
---
import HeadCommon from "../components/HeadCommon.astro";
import HeadSEO from "../components/HeadSEO.astro";
import HeadCommon from '../components/HeadCommon.astro';
import HeadSEO from '../components/HeadSEO.astro';
import Header from '../components/Header/Header.astro';
import Footer from '../components/Footer/Footer.astro';
import PageContent from '../components/PageContent/PageContent.astro';
import LeftSidebar from '../components/LeftSidebar/LeftSidebar.astro';
import RightSidebar from '../components/RightSidebar/RightSidebar.astro';
import * as CONFIG from "../config";
import * as CONFIG from '../config';
const { content = {} } = Astro.props;
const currentPage = Astro.request.url.pathname;
const currentFile = `src/pages${currentPage.replace(/\/$/, "")}.md`;
const githubEditUrl = CONFIG.GITHUB_EDIT_URL && (CONFIG.GITHUB_EDIT_URL + currentFile);
const currentFile = `src/pages${currentPage.replace(/\/$/, '')}.md`;
const githubEditUrl = CONFIG.GITHUB_EDIT_URL && CONFIG.GITHUB_EDIT_URL + currentFile;
---
<html dir={content.dir ?? 'ltr'} lang={content.lang ?? 'en-us'} class="initial">
<head>
<HeadCommon />
<HeadSEO {content} canonicalURL={Astro.request.canonicalURL} />
<title>{content.title ? `${content.title} 🚀 ${CONFIG.SITE.title}` : CONFIG.SITE.title}</title>
<style>
body {
width: 100%;
display: grid;
grid-template-rows: var(--theme-navbar-height) 1fr;
--gutter: 0.5rem;
--doc-padding: 2rem;
}
.layout {
display: grid;
grid-auto-flow: column;
grid-template-columns:
minmax(var(--gutter), 1fr)
minmax(0, var(--max-width))
minmax(var(--gutter), 1fr);
overflow-x: hidden;
}
.layout :global(> *) {
width: 100%;
height: 100%;
}
.grid-sidebar {
height: 100vh;
position: sticky;
top: 0;
padding: 0;
}
#grid-left {
position: fixed;
background-color: var(--theme-bg);
z-index: 10;
display: none;
}
#grid-main {
padding: var(--doc-padding) var(--gutter);
grid-column: 2;
display: flex;
flex-direction: column;
height: 100%;
}
#grid-right {
display: none;
}
:global(.mobile-sidebar-toggle) {
overflow: hidden;
}
:global(.mobile-sidebar-toggle) #grid-left {
display: block;
top: 2rem;
}
@media (min-width: 50em) {
.layout {
overflow: initial;
grid-template-columns:
20rem
minmax(0, var(--max-width));
gap: 1em;
}
#grid-left {
display: flex;
padding-left: 2rem;
position: sticky;
grid-column: 1;
}
}
<head>
<HeadCommon />
<HeadSEO {content} canonicalURL={Astro.request.canonicalURL} />
<title>{content.title ? `${content.title} 🚀 ${CONFIG.SITE.title}` : CONFIG.SITE.title}</title>
<style>
body {
width: 100%;
display: grid;
grid-template-rows: var(--theme-navbar-height) 1fr;
--gutter: 0.5rem;
--doc-padding: 2rem;
}
.layout {
display: grid;
grid-auto-flow: column;
grid-template-columns:
minmax(var(--gutter), 1fr)
minmax(0, var(--max-width))
minmax(var(--gutter), 1fr);
overflow-x: hidden;
}
.layout :global(> *) {
width: 100%;
height: 100%;
}
.grid-sidebar {
height: 100vh;
position: sticky;
top: 0;
padding: 0;
}
#grid-left {
position: fixed;
background-color: var(--theme-bg);
z-index: 10;
display: none;
}
#grid-main {
padding: var(--doc-padding) var(--gutter);
grid-column: 2;
display: flex;
flex-direction: column;
height: 100%;
}
#grid-right {
display: none;
}
:global(.mobile-sidebar-toggle) {
overflow: hidden;
}
:global(.mobile-sidebar-toggle) #grid-left {
display: block;
top: 2rem;
}
@media (min-width: 50em) {
.layout {
overflow: initial;
grid-template-columns:
20rem
minmax(0, var(--max-width));
gap: 1em;
}
#grid-left {
display: flex;
padding-left: 2rem;
position: sticky;
grid-column: 1;
}
}
@media (min-width: 72em) {
.layout {
grid-template-columns:
20rem
minmax(0, var(--max-width))
18rem;
padding-left: 0;
padding-right: 0;
margin: 0 auto;
}
#grid-right {
grid-column: 3;
display: flex;
}
}
</style>
</head>
@media (min-width: 72em) {
.layout {
grid-template-columns:
20rem
minmax(0, var(--max-width))
18rem;
padding-left: 0;
padding-right: 0;
margin: 0 auto;
}
#grid-right {
grid-column: 3;
display: flex;
}
}
</style>
</head>
<body>
<Header currentPage={currentPage} />
<main class="layout">
<aside id="grid-left" class="grid-sidebar" title="Site Navigation">
<LeftSidebar currentPage={currentPage} />
</aside>
<div id="grid-main">
<PageContent content={content} githubEditUrl={githubEditUrl}>
<slot />
</PageContent>
</div>
<aside id="grid-right" class="grid-sidebar" title="Table of Contents">
<RightSidebar content={content} githubEditUrl={githubEditUrl} />
</aside>
</main>
</body>
<body>
<Header {currentPage} />
<main class="layout">
<aside id="grid-left" class="grid-sidebar" title="Site Navigation">
<LeftSidebar {currentPage} />
</aside>
<div id="grid-main">
<PageContent {content} {githubEditUrl}>
<slot />
</PageContent>
</div>
<aside id="grid-right" class="grid-sidebar" title="Table of Contents">
<RightSidebar {content} {githubEditUrl} />
</aside>
</main>
</body>
</html>

View file

@ -1,5 +1,5 @@
<script>
// Redirect your homepage to the first page of documentation.
// If you have a landing page, remove this script and add it here!
window.location.pathname = `/en/introduction`;
// Redirect your homepage to the first page of documentation.
// If you have a landing page, remove this script and add it here!
window.location.pathname = `/en/introduction`;
</script>

View file

@ -1,29 +1,29 @@
.language-css > code,
.language-sass > code,
.language-scss > code {
color: #fd9170;
color: #fd9170;
}
[class*='language-'] .namespace {
opacity: 0.7;
opacity: 0.7;
}
.token.plain-text,
[class*='language-bash'] span.token,
[class*='language-shell'] span.token {
color: hsla(var(--color-gray-90), 1);
color: hsla(var(--color-gray-90), 1);
}
[class*='language-bash'] span.token,
[class*='language-shell'] span.token {
font-style: bold;
font-style: bold;
}
.token.prolog,
.token.comment,
[class*='language-bash'] span.token.comment,
[class*='language-shell'] span.token.comment {
color: hsla(var(--color-gray-70), 1);
color: hsla(var(--color-gray-70), 1);
}
.token.selector,
@ -33,7 +33,7 @@
.token.variable,
.token.entity,
.token.deleted {
color: #fa5e5b;
color: #fa5e5b;
}
.token.boolean,
@ -46,7 +46,7 @@
.token.hexcode,
.token.class-name,
.token.attr-name {
color: hsla(var(--color-yellow), 1);
color: hsla(var(--color-yellow), 1);
}
.token.atrule,
@ -56,41 +56,41 @@
.token.pseudo-class,
.token.pseudo-element,
.token.string {
color: hsla(var(--color-green), 1);
color: hsla(var(--color-green), 1);
}
.token.symbol,
.token.function,
.token.id,
.token.important {
color: hsla(var(--color-blue), 1);
color: hsla(var(--color-blue), 1);
}
.token.important,
.token.id {
font-weight: bold;
font-weight: bold;
}
.token.cdata,
.token.char,
.token.property {
color: #23b1af;
color: #23b1af;
}
.token.inserted {
color: hsla(var(--color-green), 1);
color: hsla(var(--color-green), 1);
}
.token.keyword {
color: #ff657c;
font-style: italic;
color: #ff657c;
font-style: italic;
}
.token.operator {
color: hsla(var(--color-gray-70), 1);
color: hsla(var(--color-gray-70), 1);
}
.token.attr-value .token.attr-equals,
.token.punctuation {
color: hsla(var(--color-gray-80), 1);
color: hsla(var(--color-gray-80), 1);
}

View file

@ -1,46 +1,46 @@
* {
box-sizing: border-box;
margin: 0;
box-sizing: border-box;
margin: 0;
}
/* Global focus outline reset */
*:focus:not(:focus-visible) {
outline: none;
outline: none;
}
:root {
--user-font-scale: 1rem - 16px;
--max-width: calc(100% - 1rem);
--user-font-scale: 1rem - 16px;
--max-width: calc(100% - 1rem);
}
@media (min-width: 50em) {
:root {
--max-width: 46em;
}
:root {
--max-width: 46em;
}
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
font-family: var(--font-body);
font-size: 1rem;
font-size: clamp(0.9rem, 0.75rem + 0.375vw + var(--user-font-scale), 1rem);
line-height: 1.5;
max-width: 100vw;
display: flex;
flex-direction: column;
min-height: 100vh;
font-family: var(--font-body);
font-size: 1rem;
font-size: clamp(0.9rem, 0.75rem + 0.375vw + var(--user-font-scale), 1rem);
line-height: 1.5;
max-width: 100vw;
}
nav ul {
list-style: none;
padding: 0;
list-style: none;
padding: 0;
}
.content > section > * + * {
margin-top: 1.25rem;
margin-top: 1.25rem;
}
.content > section > :first-child {
margin-top: 0;
margin-top: 0;
}
/* Typography */
@ -50,339 +50,339 @@ h3,
h4,
h5,
h6 {
margin-bottom: 1rem;
font-weight: bold;
line-height: 1;
margin-bottom: 1rem;
font-weight: bold;
line-height: 1;
}
h1,
h2 {
max-width: 40ch;
max-width: 40ch;
}
:is(h2, h3):not(:first-child) {
margin-top: 3rem;
margin-top: 3rem;
}
:is(h4, h5, h6):not(:first-child) {
margin-top: 2rem;
margin-top: 2rem;
}
h1 {
font-size: 3.25rem;
font-weight: 800;
font-size: 3.25rem;
font-weight: 800;
}
h2 {
font-size: 2.5rem;
font-size: 2.5rem;
}
h3 {
font-size: 1.75rem;
font-size: 1.75rem;
}
h4 {
font-size: 1.3rem;
font-size: 1.3rem;
}
h5 {
font-size: 1rem;
font-size: 1rem;
}
p {
line-height: 1.65em;
line-height: 1.65em;
}
.content ul {
line-height: 1.1em;
line-height: 1.1em;
}
p,
.content ul {
color: var(--theme-text-light);
color: var(--theme-text-light);
}
small,
.text_small {
font-size: 0.833rem;
font-size: 0.833rem;
}
a {
color: var(--theme-text-accent);
font-weight: 400;
text-underline-offset: 0.08em;
align-items: center;
gap: 0.5rem;
color: var(--theme-text-accent);
font-weight: 400;
text-underline-offset: 0.08em;
align-items: center;
gap: 0.5rem;
}
article > section :is(ul, ol) > * + * {
margin-top: 0.75rem;
margin-top: 0.75rem;
}
article > section nav :is(ul, ol) > * + * {
margin-top: inherit;
margin-top: inherit;
}
article > section li > :is(p, pre, blockquote):not(:first-child) {
margin-top: 1rem;
margin-top: 1rem;
}
article > section :is(ul, ol) {
padding-left: 1em;
padding-left: 1em;
}
article > section nav :is(ul, ol) {
padding-left: inherit;
padding-left: inherit;
}
article > section nav {
margin-top: 1rem;
margin-bottom: 2rem;
margin-top: 1rem;
margin-bottom: 2rem;
}
article > section ::marker {
font-weight: bold;
color: var(--theme-text-light);
font-weight: bold;
color: var(--theme-text-light);
}
article > section iframe {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
}
a > code:not([class*='language']) {
position: relative;
color: var(--theme-text-accent);
background: transparent;
text-underline-offset: var(--padding-block);
position: relative;
color: var(--theme-text-accent);
background: transparent;
text-underline-offset: var(--padding-block);
}
a > code:not([class*='language'])::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
background: var(--theme-accent);
opacity: var(--theme-accent-opacity);
border-radius: var(--border-radius);
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
background: var(--theme-accent);
opacity: var(--theme-accent-opacity);
border-radius: var(--border-radius);
}
a:hover,
a:focus {
text-decoration: underline;
text-decoration: underline;
}
a:focus {
outline: 2px solid currentColor;
outline-offset: 0.25em;
outline: 2px solid currentColor;
outline-offset: 0.25em;
}
strong {
font-weight: 600;
color: inherit;
font-weight: 600;
color: inherit;
}
/* Supporting Content */
code {
font-family: var(--font-mono);
font-size: 0.85em;
font-family: var(--font-mono);
font-size: 0.85em;
}
code:not([class*='language']) {
--border-radius: 3px;
--padding-block: 0.2rem;
--padding-inline: 0.4rem;
color: var(--theme-code-inline-text);
background-color: var(--theme-code-inline-bg);
padding: var(--padding-block) var(--padding-inline);
margin: calc(var(--padding-block) * -1) -0.125em;
border-radius: var(--border-radius);
box-shadow: 0 2px 1px 0 rgba(0, 0, 0, 0.08);
word-break: break-word;
--border-radius: 3px;
--padding-block: 0.2rem;
--padding-inline: 0.4rem;
color: var(--theme-code-inline-text);
background-color: var(--theme-code-inline-bg);
padding: var(--padding-block) var(--padding-inline);
margin: calc(var(--padding-block) * -1) -0.125em;
border-radius: var(--border-radius);
box-shadow: 0 2px 1px 0 rgba(0, 0, 0, 0.08);
word-break: break-word;
}
pre > code:not([class*='language']) {
background-color: transparent;
padding: 0;
margin: 0;
border-radius: 0;
color: inherit;
background-color: transparent;
padding: 0;
margin: 0;
border-radius: 0;
color: inherit;
}
pre > code {
font-size: 1em;
font-size: 1em;
}
table,
pre {
position: relative;
--padding-block: 1rem;
--padding-inline: 2rem;
padding: var(--padding-block) var(--padding-inline);
padding-right: calc(var(--padding-inline) * 2);
margin-left: calc(var(--padding-inline) * -1);
margin-right: calc(var(--padding-inline) * -1);
font-family: var(--font-mono);
position: relative;
--padding-block: 1rem;
--padding-inline: 2rem;
padding: var(--padding-block) var(--padding-inline);
padding-right: calc(var(--padding-inline) * 2);
margin-left: calc(var(--padding-inline) * -1);
margin-right: calc(var(--padding-inline) * -1);
font-family: var(--font-mono);
line-height: 1.5;
font-size: 0.85em;
overflow-y: hidden;
overflow-x: auto;
line-height: 1.5;
font-size: 0.85em;
overflow-y: hidden;
overflow-x: auto;
}
table {
width: 100%;
padding: var(--padding-block) 0;
margin: 0;
border-collapse: collapse;
width: 100%;
padding: var(--padding-block) 0;
margin: 0;
border-collapse: collapse;
}
/* Zebra striping */
tr:nth-of-type(odd) {
background: var(--theme-bg-hover);
background: var(--theme-bg-hover);
}
th {
background: var(--color-black);
color: var(--theme-color);
font-weight: bold;
background: var(--color-black);
color: var(--theme-color);
font-weight: bold;
}
td,
th {
padding: 6px;
text-align: left;
padding: 6px;
text-align: left;
}
pre {
background-color: var(--theme-code-bg);
color: var(--theme-code-text);
background-color: var(--theme-code-bg);
color: var(--theme-code-text);
}
blockquote code:not([class*='language']) {
background-color: var(--theme-bg);
background-color: var(--theme-bg);
}
@media (min-width: 37.75em) {
pre {
--padding-inline: 1.25rem;
border-radius: 8px;
margin-left: 0;
margin-right: 0;
}
pre {
--padding-inline: 1.25rem;
border-radius: 8px;
margin-left: 0;
margin-right: 0;
}
}
blockquote {
margin: 2rem 0;
padding: 1.25em 1.5rem;
border-left: 3px solid var(--theme-text-light);
background-color: var(--theme-bg-offset);
border-radius: 0 0.25rem 0.25rem 0;
line-height: 1.7;
margin: 2rem 0;
padding: 1.25em 1.5rem;
border-left: 3px solid var(--theme-text-light);
background-color: var(--theme-bg-offset);
border-radius: 0 0.25rem 0.25rem 0;
line-height: 1.7;
}
img {
max-width: 100%;
max-width: 100%;
}
.flex {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
button {
display: flex;
align-items: center;
justify-items: center;
gap: 0.25em;
padding: 0.33em 0.67em;
border: 0;
background: var(--theme-bg);
display: flex;
font-size: 1rem;
align-items: center;
gap: 0.25em;
border-radius: 99em;
color: var(--theme-text);
background-color: var(--theme-bg);
display: flex;
align-items: center;
justify-items: center;
gap: 0.25em;
padding: 0.33em 0.67em;
border: 0;
background: var(--theme-bg);
display: flex;
font-size: 1rem;
align-items: center;
gap: 0.25em;
border-radius: 99em;
color: var(--theme-text);
background-color: var(--theme-bg);
}
h2.heading {
font-size: 1rem;
font-weight: 700;
padding: 0.1rem 1rem;
text-transform: uppercase;
margin-bottom: 0.5rem;
font-size: 1rem;
font-weight: 700;
padding: 0.1rem 1rem;
text-transform: uppercase;
margin-bottom: 0.5rem;
}
.header-link {
font-size: 1rem;
padding: 0.1rem 0 0.1rem 1rem;
border-left: 4px solid var(--theme-divider);
font-size: 1rem;
padding: 0.1rem 0 0.1rem 1rem;
border-left: 4px solid var(--theme-divider);
}
.header-link:hover,
.header-link:focus {
border-left-color: var(--theme-accent);
color: var(--theme-accent);
border-left-color: var(--theme-accent);
color: var(--theme-accent);
}
.header-link:focus-within {
color: var(--theme-text-light);
border-left-color: hsla(var(--color-gray-40), 1);
color: var(--theme-text-light);
border-left-color: hsla(var(--color-gray-40), 1);
}
.header-link svg {
opacity: 0.6;
opacity: 0.6;
}
.header-link:hover svg {
opacity: 0.8;
opacity: 0.8;
}
.header-link a {
display: inline-flex;
gap: 0.5em;
width: 100%;
padding: 0.15em 0 0.15em 0;
display: inline-flex;
gap: 0.5em;
width: 100%;
padding: 0.15em 0 0.15em 0;
}
.header-link.depth-3 {
padding-left: 2rem;
padding-left: 2rem;
}
.header-link.depth-4 {
padding-left: 3rem;
padding-left: 3rem;
}
.header-link a {
font: inherit;
color: inherit;
text-decoration: none;
font: inherit;
color: inherit;
text-decoration: none;
}
/* Screenreader Only Text */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.focus\:not-sr-only:focus,
.focus\:not-sr-only:focus-visible {
position: static;
width: auto;
height: auto;
padding: 0;
margin: 0;
overflow: visible;
clip: auto;
white-space: normal;
position: static;
width: auto;
height: auto;
padding: 0;
margin: 0;
overflow: visible;
clip: auto;
white-space: normal;
}
:target {
scroll-margin: calc(var(--theme-sidebar-offset, 5rem) + 2rem) 0 2rem;
scroll-margin: calc(var(--theme-sidebar-offset, 5rem) + 2rem) 0 2rem;
}

View file

@ -1,10 +1,10 @@
:root {
--font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
--font-body: system-ui, var(--font-fallback);
--font-mono: 'IBM Plex Mono', Consolas, 'Andale Mono WT', 'Andale Mono', 'Lucida Console', 'Lucida Sans Typewriter', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono',
'Liberation Mono', 'Nimbus Mono L', Monaco, 'Courier New', Courier, monospace;
--font-fallback: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
--font-body: system-ui, var(--font-fallback);
--font-mono: 'IBM Plex Mono', Consolas, 'Andale Mono WT', 'Andale Mono', 'Lucida Console', 'Lucida Sans Typewriter', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono',
'Liberation Mono', 'Nimbus Mono L', Monaco, 'Courier New', Courier, monospace;
/*
/*
* Variables with --color-base prefix define
* the hue, and saturation values to be used for
* hsla colors.
@ -15,109 +15,109 @@
*
*/
--color-base-white: 0, 0%;
--color-base-black: 240, 100%;
--color-base-gray: 215, 14%;
--color-base-blue: 212, 100%;
--color-base-blue-dark: 212, 72%;
--color-base-green: 158, 79%;
--color-base-orange: 22, 100%;
--color-base-purple: 269, 79%;
--color-base-red: 351, 100%;
--color-base-yellow: 41, 100%;
--color-base-white: 0, 0%;
--color-base-black: 240, 100%;
--color-base-gray: 215, 14%;
--color-base-blue: 212, 100%;
--color-base-blue-dark: 212, 72%;
--color-base-green: 158, 79%;
--color-base-orange: 22, 100%;
--color-base-purple: 269, 79%;
--color-base-red: 351, 100%;
--color-base-yellow: 41, 100%;
/*
/*
* Color palettes are made using --color-base
* variables, along with a lightness value to
* define different variants.
*
*/
--color-gray-5: var(--color-base-gray), 5%;
--color-gray-10: var(--color-base-gray), 10%;
--color-gray-20: var(--color-base-gray), 20%;
--color-gray-30: var(--color-base-gray), 30%;
--color-gray-40: var(--color-base-gray), 40%;
--color-gray-50: var(--color-base-gray), 50%;
--color-gray-60: var(--color-base-gray), 60%;
--color-gray-70: var(--color-base-gray), 70%;
--color-gray-80: var(--color-base-gray), 80%;
--color-gray-90: var(--color-base-gray), 90%;
--color-gray-95: var(--color-base-gray), 95%;
--color-gray-5: var(--color-base-gray), 5%;
--color-gray-10: var(--color-base-gray), 10%;
--color-gray-20: var(--color-base-gray), 20%;
--color-gray-30: var(--color-base-gray), 30%;
--color-gray-40: var(--color-base-gray), 40%;
--color-gray-50: var(--color-base-gray), 50%;
--color-gray-60: var(--color-base-gray), 60%;
--color-gray-70: var(--color-base-gray), 70%;
--color-gray-80: var(--color-base-gray), 80%;
--color-gray-90: var(--color-base-gray), 90%;
--color-gray-95: var(--color-base-gray), 95%;
--color-blue: var(--color-base-blue), 61%;
--color-blue-dark: var(--color-base-blue-dark), 39%;
--color-green: var(--color-base-green), 42%;
--color-orange: var(--color-base-orange), 50%;
--color-purple: var(--color-base-purple), 54%;
--color-red: var(--color-base-red), 54%;
--color-yellow: var(--color-base-yellow), 59%;
--color-blue: var(--color-base-blue), 61%;
--color-blue-dark: var(--color-base-blue-dark), 39%;
--color-green: var(--color-base-green), 42%;
--color-orange: var(--color-base-orange), 50%;
--color-purple: var(--color-base-purple), 54%;
--color-red: var(--color-base-red), 54%;
--color-yellow: var(--color-base-yellow), 59%;
}
:root {
color-scheme: light;
--theme-accent: hsla(var(--color-blue), 1);
--theme-text-accent: hsla(var(--color-blue), 1);
--theme-accent-opacity: 0.15;
--theme-divider: hsla(var(--color-gray-95), 1);
--theme-text: hsla(var(--color-gray-10), 1);
--theme-text-light: hsla(var(--color-gray-40), 1);
/* @@@: not used anywhere */
--theme-text-lighter: hsla(var(--color-gray-80), 1);
--theme-bg: hsla(var(--color-base-white), 100%, 1);
--theme-bg-hover: hsla(var(--color-gray-95), 1);
--theme-bg-offset: hsla(var(--color-gray-90), 1);
--theme-bg-accent: hsla(var(--color-blue), var(--theme-accent-opacity));
--theme-code-inline-bg: hsla(var(--color-gray-95), 1);
--theme-code-inline-text: var(--theme-text);
--theme-code-bg: hsla(217, 19%, 27%, 1);
--theme-code-text: hsla(var(--color-gray-95), 1);
--theme-navbar-bg: hsla(var(--color-base-white), 100%, 1);
--theme-navbar-height: 6rem;
--theme-selection-color: hsla(var(--color-blue), 1);
--theme-selection-bg: hsla(var(--color-blue), var(--theme-accent-opacity));
color-scheme: light;
--theme-accent: hsla(var(--color-blue), 1);
--theme-text-accent: hsla(var(--color-blue), 1);
--theme-accent-opacity: 0.15;
--theme-divider: hsla(var(--color-gray-95), 1);
--theme-text: hsla(var(--color-gray-10), 1);
--theme-text-light: hsla(var(--color-gray-40), 1);
/* @@@: not used anywhere */
--theme-text-lighter: hsla(var(--color-gray-80), 1);
--theme-bg: hsla(var(--color-base-white), 100%, 1);
--theme-bg-hover: hsla(var(--color-gray-95), 1);
--theme-bg-offset: hsla(var(--color-gray-90), 1);
--theme-bg-accent: hsla(var(--color-blue), var(--theme-accent-opacity));
--theme-code-inline-bg: hsla(var(--color-gray-95), 1);
--theme-code-inline-text: var(--theme-text);
--theme-code-bg: hsla(217, 19%, 27%, 1);
--theme-code-text: hsla(var(--color-gray-95), 1);
--theme-navbar-bg: hsla(var(--color-base-white), 100%, 1);
--theme-navbar-height: 6rem;
--theme-selection-color: hsla(var(--color-blue), 1);
--theme-selection-bg: hsla(var(--color-blue), var(--theme-accent-opacity));
}
body {
background: var(--theme-bg);
color: var(--theme-text);
background: var(--theme-bg);
color: var(--theme-text);
}
:root.theme-dark {
color-scheme: dark;
--theme-accent-opacity: 0.15;
--theme-accent: hsla(var(--color-blue), 1);
--theme-text-accent: hsla(var(--color-blue), 1);
--theme-divider: hsla(var(--color-gray-10), 1);
--theme-text: hsla(var(--color-gray-90), 1);
--theme-text-light: hsla(var(--color-gray-80), 1);
color-scheme: dark;
--theme-accent-opacity: 0.15;
--theme-accent: hsla(var(--color-blue), 1);
--theme-text-accent: hsla(var(--color-blue), 1);
--theme-divider: hsla(var(--color-gray-10), 1);
--theme-text: hsla(var(--color-gray-90), 1);
--theme-text-light: hsla(var(--color-gray-80), 1);
/* @@@: not used anywhere */
--theme-text-lighter: hsla(var(--color-gray-40), 1);
--theme-bg: hsla(215, 28%, 17%, 1);
--theme-bg-hover: hsla(var(--color-gray-40), 1);
--theme-bg-offset: hsla(var(--color-gray-5), 1);
--theme-code-inline-bg: hsla(var(--color-gray-10), 1);
--theme-code-inline-text: hsla(var(--color-base-white), 100%, 1);
--theme-code-bg: hsla(var(--color-gray-5), 1);
--theme-code-text: hsla(var(--color-base-white), 100%, 1);
--theme-navbar-bg: hsla(215, 28%, 17%, 1);
--theme-selection-color: hsla(var(--color-base-white), 100%, 1);
--theme-selection-bg: hsla(var(--color-purple), var(--theme-accent-opacity));
/* @@@: not used anywhere */
--theme-text-lighter: hsla(var(--color-gray-40), 1);
--theme-bg: hsla(215, 28%, 17%, 1);
--theme-bg-hover: hsla(var(--color-gray-40), 1);
--theme-bg-offset: hsla(var(--color-gray-5), 1);
--theme-code-inline-bg: hsla(var(--color-gray-10), 1);
--theme-code-inline-text: hsla(var(--color-base-white), 100%, 1);
--theme-code-bg: hsla(var(--color-gray-5), 1);
--theme-code-text: hsla(var(--color-base-white), 100%, 1);
--theme-navbar-bg: hsla(215, 28%, 17%, 1);
--theme-selection-color: hsla(var(--color-base-white), 100%, 1);
--theme-selection-bg: hsla(var(--color-purple), var(--theme-accent-opacity));
/* DocSearch [Algolia] */
--docsearch-modal-background: var(--theme-bg);
--docsearch-searchbox-focus-background: var(--theme-divider);
--docsearch-footer-background: var(--theme-divider);
--docsearch-text-color: var(--theme-text);
--docsearch-hit-background: var(--theme-divider);
--docsearch-hit-shadow: none;
--docsearch-hit-color: var(--theme-text);
--docsearch-footer-shadow: inset 0 2px 10px #000;
--docsearch-modal-shadow: inset 0 0 8px #000;
/* DocSearch [Algolia] */
--docsearch-modal-background: var(--theme-bg);
--docsearch-searchbox-focus-background: var(--theme-divider);
--docsearch-footer-background: var(--theme-divider);
--docsearch-text-color: var(--theme-text);
--docsearch-hit-background: var(--theme-divider);
--docsearch-hit-shadow: none;
--docsearch-hit-color: var(--theme-text);
--docsearch-footer-shadow: inset 0 2px 10px #000;
--docsearch-modal-shadow: inset 0 0 8px #000;
}
::selection {
color: var(--theme-selection-color);
background-color: var(--theme-selection-bg);
color: var(--theme-selection-color);
background-color: var(--theme-selection-bg);
}

View file

@ -2,8 +2,8 @@ import { imagetools } from 'vite-imagetools';
// @ts-check
export default /** @type {import('astro').AstroUserConfig} */ ({
renderers: ['@astrojs/renderer-vue'],
vite: {
plugins: [imagetools()],
},
renderers: ['@astrojs/renderer-vue'],
vite: {
plugins: [imagetools()],
},
});

View file

@ -1,20 +1,20 @@
<script>
export default {
data() {
return {
greeting: 'Hello World!',
};
},
data() {
return {
greeting: 'Hello World!',
};
},
};
</script>
<template>
<p class="greeting">{{ greeting }}</p>
<p class="greeting">{{ greeting }}</p>
</template>
<style>
.greeting {
color: red;
font-weight: bold;
color: red;
font-weight: bold;
}
</style>

View file

@ -5,28 +5,30 @@ import Greeting from '../components/Greeting.vue';
---
<html>
<head>
<title>Demo app</title>
<style>
h1 { color: salmon; }
</style>
</head>
<body>
<section>
<h1>Images</h1>
<head>
<title>Demo app</title>
<style>
h1 {
color: salmon;
}
</style>
</head>
<body>
<section>
<h1>Images</h1>
<h2>Imported in JS</h2>
<img src={imgUrl} />
</section>
<h2>Imported in JS</h2>
<img src={imgUrl} />
</section>
<section>
<h1>Component CSS</h1>
<Greeting />
</section>
<section>
<h1>Component CSS</h1>
<Greeting />
</section>
<section>
<h1>ImageTools</h1>
<img src={grayscaleUrl} />
</section>
</body>
<section>
<h1>ImageTools</h1>
<img src={grayscaleUrl} />
</section>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show more