Compare commits
1 commit
main
...
wip-docs-c
Author | SHA1 | Date | |
---|---|---|---|
|
a7a521034e |
46 changed files with 866 additions and 725 deletions
|
@ -9,6 +9,7 @@
|
|||
"preview": "astro preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/docs": "^0.0.1",
|
||||
"@docsearch/react": "^1.0.0-alpha.27"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 731 KiB |
|
@ -1,386 +0,0 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Global focus outline reset */
|
||||
*:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
:root {
|
||||
--user-font-scale: 1rem - 16px;
|
||||
--max-width: calc(100% - 1rem);
|
||||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
: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;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.content > section > * + * {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
.content > section > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-bottom: 1rem;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
max-width: 40ch;
|
||||
}
|
||||
|
||||
:is(h2, h3):not(:first-child) {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
:is(h4, h5, h6):not(:first-child) {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.25rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.65em;
|
||||
}
|
||||
|
||||
.content ul {
|
||||
line-height: 1.1em;
|
||||
}
|
||||
|
||||
p,
|
||||
.content ul {
|
||||
color: var(--theme-text-light);
|
||||
}
|
||||
|
||||
small,
|
||||
.text_small {
|
||||
font-size: 0.833rem;
|
||||
}
|
||||
|
||||
a {
|
||||
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;
|
||||
}
|
||||
|
||||
article > section nav :is(ul, ol) > * + * {
|
||||
margin-top: inherit;
|
||||
}
|
||||
|
||||
article > section li > :is(p, pre, blockquote):not(:first-child) {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
article > section :is(ul, ol) {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
article > section nav :is(ul, ol) {
|
||||
padding-left: inherit;
|
||||
}
|
||||
|
||||
article > section nav {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
article > section ::marker {
|
||||
font-weight: bold;
|
||||
color: var(--theme-text-light);
|
||||
}
|
||||
|
||||
article > section iframe {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: 0.25em;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 600;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Supporting Content */
|
||||
code {
|
||||
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);
|
||||
}
|
||||
|
||||
pre > code:not([class*='language']) {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Zebra striping */
|
||||
tr:nth-of-type(odd) {
|
||||
background: var(--theme-bg-hover);
|
||||
}
|
||||
th {
|
||||
background: var(--color-black);
|
||||
color: var(--theme-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
td,
|
||||
th {
|
||||
padding: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: var(--theme-code-bg);
|
||||
color: var(--theme-code-text);
|
||||
}
|
||||
|
||||
blockquote code:not([class*='language']) {
|
||||
background-color: var(--theme-bg);
|
||||
}
|
||||
|
||||
@media (min-width: 37.75em) {
|
||||
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;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.flex {
|
||||
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);
|
||||
}
|
||||
|
||||
h2.heading {
|
||||
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);
|
||||
}
|
||||
|
||||
.header-link:hover,
|
||||
.header-link:focus {
|
||||
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);
|
||||
}
|
||||
.header-link svg {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.header-link:hover svg {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.header-link a {
|
||||
display: inline-flex;
|
||||
gap: 0.5em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-link.depth-3 {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
.header-link.depth-4 {
|
||||
padding-left: 3rem;
|
||||
}
|
||||
|
||||
.header-link a {
|
||||
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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
:target {
|
||||
scroll-margin: calc(var(--theme-sidebar-offset, 5rem) + 2rem) 0 2rem;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
Array.from(document.getElementsByTagName('pre')).forEach((element) => {
|
||||
element.setAttribute('tabindex', '0');
|
||||
});
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
import AvatarList from './AvatarList.astro';
|
||||
const { path } = Astro.props;
|
||||
---
|
||||
|
||||
<footer>
|
||||
<AvatarList path={path} />
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
margin-top: auto;
|
||||
padding: 2rem 0;
|
||||
border-top: 3px solid var(--theme-divider);
|
||||
}
|
||||
</style>
|
52
examples/docs/src/components/Head.astro
Normal file
52
examples/docs/src/components/Head.astro
Normal file
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
// The <Head /> Component - Responsible for site-wide `<head>` metadata and SEO tags.
|
||||
import * as CONFIG from '../config.ts';
|
||||
export interface Props {
|
||||
/** A markdown content prop. */
|
||||
content?: any;
|
||||
}
|
||||
|
||||
const {content = {}} = Astro.props as Props;
|
||||
const siteTitle: string = CONFIG.SITE.title;
|
||||
const pageTitle: string = content.title ? `${content.title} | ${siteTitle}` : siteTitle;
|
||||
const pageDescription: string = content.description || CONFIG.SITE.description;
|
||||
const lang: string = content.lang || CONFIG.SITE.lang;
|
||||
const imageURL: string = content.image?.url || CONFIG.SITE.image.url;
|
||||
const imageAlt: string = content.image?.alt || CONFIG.SITE.image.alt;
|
||||
const canonicalURL: string = Astro.request.canonicalURL;
|
||||
const twitter: string | undefined = CONFIG.TWITTER;
|
||||
---
|
||||
|
||||
<!-- Global Metadata -->
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="sitemap" href="/sitemap.xml"/>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="alternate icon" type="image/x-icon" href="/favicon.ico" />
|
||||
|
||||
<!-- Page Metadata -->
|
||||
<title>{pageTitle}</title>
|
||||
<link rel="canonical" href={canonicalURL}/>
|
||||
|
||||
<!-- CSS -->
|
||||
<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">
|
||||
|
||||
<!-- OpenGraph Tags -->
|
||||
<meta property="og:title" content={pageTitle}/>
|
||||
<meta property="og:description" content={pageDescription}/>
|
||||
<meta property="og:type" content="article"/>
|
||||
<meta property="og:url" content={canonicalURL}/>
|
||||
<meta property="og:locale" content={lang}/>
|
||||
<meta property="og:image" content={imageURL}/>
|
||||
<meta property="og:image:alt" content={imageAlt}/>
|
||||
<meta property="og:site_name" content={siteTitle}/>
|
||||
|
||||
<!-- Twitter Tags -->
|
||||
{twitter && <meta name="twitter:card" content="summary_large_image"/>}
|
||||
{twitter && <meta name="twitter:site" content={twitter} />}
|
||||
|
||||
<!-- Add custom tags here! -->
|
|
@ -1,40 +0,0 @@
|
|||
<!-- Global Metadata -->
|
||||
<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"/>
|
||||
|
||||
<!-- Global CSS -->
|
||||
<link rel="stylesheet" href="/theme.css" />
|
||||
<link rel="stylesheet" href="/code.css" />
|
||||
<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">
|
||||
|
||||
<!-- Scrollable a11y code helper -->
|
||||
<script type="module" src="/make-scrollable-code-focusable.js" />
|
||||
|
||||
<!-- 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');
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<!-- <script async src="https://www.googletagmanager.com/gtag/js?id=G-TEL60V1WM9"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-TEL60V1WM9');
|
||||
</script> -->
|
|
@ -1,40 +0,0 @@
|
|||
---
|
||||
import {SITE, OPEN_GRAPH} from '../config.ts';
|
||||
export interface Props {
|
||||
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}/>
|
||||
|
||||
<!-- 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 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}/>
|
||||
|
||||
<!--
|
||||
TODO: Add json+ld data, maybe https://schema.org/APIReference makes sense?
|
||||
Docs: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data
|
||||
https://www.npmjs.com/package/schema-dts seems like a great resource for implementing this.
|
||||
Even better, there's a React component that integrates with `schema-dts`: https://github.com/google/react-schemaorg
|
||||
-->
|
|
@ -1,41 +0,0 @@
|
|||
---
|
||||
const {content, githubEditUrl} = Astro.props;
|
||||
const title = content.title;
|
||||
const headers = content.astro.headers;
|
||||
import MoreMenu from '../RightSidebar/MoreMenu.astro';
|
||||
import TableOfContents from '../RightSidebar/TableOfContents.tsx';
|
||||
---
|
||||
<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>
|
||||
</article>
|
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
import TableOfContents from './TableOfContents.jsx';
|
||||
import MoreMenu from './MoreMenu.astro';
|
||||
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>
|
||||
</nav>
|
|
@ -1,15 +1,12 @@
|
|||
export const SITE = {
|
||||
title: 'Your Documentation Website',
|
||||
description: 'Your website description.',
|
||||
defaultLanguage: 'en_US',
|
||||
};
|
||||
|
||||
export const OPEN_GRAPH = {
|
||||
lang: 'en',
|
||||
dir: 'ltr',
|
||||
image: {
|
||||
src: 'https://github.com/snowpackjs/astro/blob/main/assets/social/banner.png?raw=true',
|
||||
alt: 'astro logo on a starry expanse of space,' + ' with a purple saturn-like planet floating in the right foreground',
|
||||
alt: 'The Astro logo over an outerspace background image, with stars and planets.',
|
||||
},
|
||||
twitter: 'astrodotbuild',
|
||||
};
|
||||
|
||||
export const KNOWN_LANGUAGES = {
|
||||
|
@ -17,10 +14,14 @@ export const KNOWN_LANGUAGES = {
|
|||
};
|
||||
|
||||
// Uncomment this to add an "Edit this page" button to every page of documentation.
|
||||
// export const GITHUB_EDIT_URL = `https://github.com/snowpackjs/astro/blob/main/docs/`;
|
||||
// The path of the page content is always appended to this URL.
|
||||
// export const EDIT_URL = `https://github.com/snowpackjs/astro/blob/main/docs/`;
|
||||
|
||||
// Uncomment this to add an "Join our Community" button to every page of documentation.
|
||||
// export const COMMUNITY_INVITE_URL = `https://astro.build/chat`;
|
||||
// export const COMMUNITY_URL = `https://astro.build/chat`;
|
||||
|
||||
// Uncomment this to enable the Twitter SEO meta tag.
|
||||
// export const TWITTER = 'astrodotbuild';
|
||||
|
||||
// Uncomment this to enable site search.
|
||||
// See "Algolia" section of the README for more information.
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
import { KNOWN_LANGUAGES } from './config.js';
|
||||
|
||||
export const KNOWN_LANGUAGE_CODES = Object.values(KNOWN_LANGUAGES);
|
||||
|
||||
export function getLanguageFromURL(pathname: string) {
|
||||
const langCodeMatch = pathname.match(/\/([a-z]{2}-?[A-Z]{0,2})\//);
|
||||
return langCodeMatch ? langCodeMatch[1] : 'en';
|
||||
}
|
|
@ -1,122 +1,38 @@
|
|||
---
|
||||
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.ts";
|
||||
// <MainLayout /> - The main layout for your docs site.
|
||||
// This includes all reusable UI from the '@astrojs/docs' package.
|
||||
// Markdown content will be injected at the `<slot />` component.
|
||||
//
|
||||
// The fastest way to customize this layout is to add new components
|
||||
// to any existing layout "slot". For example, `<Head />` is a custom
|
||||
// component that islives in this project "src/components" directory.
|
||||
// Components will end up in each slot in the order that they appear.
|
||||
//
|
||||
// You can also completely replace layout components like `LeftSidebar`
|
||||
// and `PageContent` with your own UI.
|
||||
|
||||
import {PageLayout, Header, PageContent, LeftSidebar, RightSidebar} from '@astrojs/docs';
|
||||
import Head from '../components/Head.astro';
|
||||
import * as CONFIG from '../config.ts';
|
||||
|
||||
export interface Props {
|
||||
/** A markdown content prop. Automatically provided by Astro. */
|
||||
content?: any;
|
||||
}
|
||||
|
||||
const { content = {} } = Astro.props;
|
||||
const dir = content.dir || CONFIG.SITE.dir;
|
||||
const lang = content.lang || CONFIG.SITE.lang;
|
||||
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 editUrlWithFile = CONFIG.EDIT_URL && (CONFIG.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;
|
||||
}
|
||||
}
|
||||
|
||||
@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>
|
||||
</html>
|
||||
<PageLayout lang={lang} dir={dir}>
|
||||
<Head slot="head" content={content} />
|
||||
<Header slot="header" currentPage={currentPage} lang={lang} languages={CONFIG.KNOWN_LANGUAGES} search={CONFIG.ALGOLIA} />
|
||||
<LeftSidebar slot="left" currentPage={currentPage} navigation={CONFIG.SIDEBAR[lang]} />
|
||||
<PageContent slot="main" content={content}>
|
||||
<slot />
|
||||
</PageContent>
|
||||
<RightSidebar slot="right" content={content} editUrl={editUrlWithFile} inviteUrl={CONFIG.COMMUNITY_URL} />
|
||||
</PageLayout>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
title: Introduction
|
||||
lang: en
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
title: Page 2
|
||||
lang: en
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
title: Page 3
|
||||
lang: en
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
title: Page 4
|
||||
lang: en
|
||||
layout: ../../layouts/MainLayout.astro
|
||||
---
|
||||
|
||||
|
|
170
examples/docs/src/styles/base.css
Normal file
170
examples/docs/src/styles/base.css
Normal file
|
@ -0,0 +1,170 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Global focus outline reset */
|
||||
*:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
:root {
|
||||
--user-font-scale: 1rem - 16px;
|
||||
--max-width: calc(100% - 1rem);
|
||||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
: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;
|
||||
}
|
||||
|
||||
/* Supporting Content */
|
||||
nav ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
.flex {
|
||||
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);
|
||||
}
|
||||
|
||||
/** Headings */
|
||||
h2.heading {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
padding: 0.1rem 1rem;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.header-link {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
padding: 0.1rem 0 0.1rem 0.75rem;
|
||||
margin-left: 0.25rem;
|
||||
border-left: 4px solid var(--theme-divider);
|
||||
}
|
||||
.header-link:hover,
|
||||
.header-link:focus {
|
||||
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);
|
||||
}
|
||||
.header-link svg {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.header-link:hover svg {
|
||||
opacity: 0.8;
|
||||
}
|
||||
.header-link a {
|
||||
display: inline-flex;
|
||||
gap: 0.5em;
|
||||
width: 100%;
|
||||
}
|
||||
.header-link.depth-3 {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
.header-link.depth-4 {
|
||||
padding-left: 3rem;
|
||||
}
|
||||
.header-link a {
|
||||
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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
:target {
|
||||
scroll-margin: calc(var(--theme-sidebar-offset, 5rem) + 2rem) 0 2rem;
|
||||
}
|
||||
|
|
@ -1,3 +1,52 @@
|
|||
/* General */
|
||||
pre {
|
||||
background-color: var(--theme-code-bg);
|
||||
color: var(--theme-code-text);
|
||||
}
|
||||
code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.85em;
|
||||
}
|
||||
blockquote code:not([class*='language']) {
|
||||
background-color: var(--theme-bg);
|
||||
}
|
||||
|
||||
@media (min-width: 37.75em) {
|
||||
pre {
|
||||
--padding-inline: 1.25rem;
|
||||
border-radius: 8px;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
pre > code:not([class*='language']) {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
pre > code {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Syntax Highlighting */
|
||||
.language-css > code,
|
||||
.language-sass > code,
|
||||
.language-scss > code {
|
4
examples/docs/src/styles/index.css
Normal file
4
examples/docs/src/styles/index.css
Normal file
|
@ -0,0 +1,4 @@
|
|||
@import './theme.css';
|
||||
@import './base.css';
|
||||
@import './typography.css';
|
||||
@import './code.css';
|
99
examples/docs/src/styles/typography.css
Normal file
99
examples/docs/src/styles/typography.css
Normal file
|
@ -0,0 +1,99 @@
|
|||
|
||||
/* Typography */
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-bottom: 1rem;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
max-width: 40ch;
|
||||
}
|
||||
|
||||
:is(h2, h3):not(:first-child) {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
:is(h4, h5, h6):not(:first-child) {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.25rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.65em;
|
||||
color: var(--theme-text-light);
|
||||
}
|
||||
|
||||
small,
|
||||
.text_small {
|
||||
font-size: 0.833rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--theme-text-accent);
|
||||
font-weight: 400;
|
||||
text-underline-offset: 0.08em;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
a > code:not([class*='language']) {
|
||||
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);
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: 0.25em;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 600;
|
||||
color: inherit;
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
},
|
||||
"workspaces": [
|
||||
"packages/renderers/*",
|
||||
"packages/components/*",
|
||||
"packages/*",
|
||||
"examples/*",
|
||||
"scripts",
|
||||
|
|
105
packages/components/docs/README.md
Normal file
105
packages/components/docs/README.md
Normal file
|
@ -0,0 +1,105 @@
|
|||
# `@astrojs/docs` - Astro Components Kit
|
||||
|
||||
```
|
||||
npm install @astrojs/docs
|
||||
```
|
||||
|
||||
This package is the component library that powers the Astro `docs` starter template.
|
||||
|
||||
This is only a collection of components. **If you are looking for an already-themed, batteries-included template for your next project, check out the `docs` starter kit via `npm init astro` instead.**
|
||||
|
||||
## What is in this package?
|
||||
|
||||
This package contains several common UI components for documentation websites, including an i18n language selector and an Algolia-powered search bar.
|
||||
|
||||
This package also includes a CSS Grid layout for your site, using a left sidebar for page navigation and a right sidebar for section navigation within each page. The design is responsive to work across desktop and mobile.
|
||||
|
||||
## How to Use This Package
|
||||
|
||||
Because `@astrojs/docs` is a lower-level UI library, you will need to write some code on your end to integrate it. The best way to do that is with a [Page Layout](https://docs.astro.build/core-concepts/layouts) component, like the example below:
|
||||
|
||||
```astro
|
||||
---
|
||||
// Example: src/layouts/MainLayout.astro
|
||||
//
|
||||
// <MainLayout /> - The main layout for your docs site.
|
||||
// This includes all reusable UI from the '@astrojs/docs' package.
|
||||
// Markdown content will be injected at the `<slot />` component.
|
||||
//
|
||||
// To use this layout: set the `layout` in your markdown page's frontmatter.
|
||||
//
|
||||
// The fastest way to customize your layout is to add new components
|
||||
// to any existing layout "slot". For example, `<Head />` is a custom
|
||||
// component that lives in this project "src/components" directory.
|
||||
//
|
||||
// You can also completely replace layout components like `LeftSidebar`
|
||||
// and `PageContent` with your own UI.
|
||||
|
||||
import {PageLayout, Header, PageContent, LeftSidebar, RightSidebar} from '@astrojs/docs';
|
||||
import Head from '../components/Head.astro';
|
||||
import * as CONFIG from '../config.ts';
|
||||
|
||||
const { content = {} } = Astro.props;
|
||||
const dir = content.dir || CONFIG.SITE.dir;
|
||||
const lang = content.lang || CONFIG.SITE.lang;
|
||||
const currentPage = Astro.request.url.pathname;
|
||||
const currentFile = `src/pages${currentPage.replace(/\/$/, "")}.md`;
|
||||
const editUrlWithFile = CONFIG.EDIT_URL && (CONFIG.EDIT_URL + currentFile);
|
||||
---
|
||||
<PageLayout lang={lang} dir={dir}>
|
||||
<Head slot="head" content={content} />
|
||||
<Header slot="header" currentPage={currentPage} lang={lang} languages={CONFIG.KNOWN_LANGUAGES} search={CONFIG.ALGOLIA} />
|
||||
<LeftSidebar slot="left" currentPage={currentPage} navigation={CONFIG.SIDEBAR[lang]} />
|
||||
<PageContent slot="main" content={content}>
|
||||
<slot />
|
||||
</PageContent>
|
||||
<RightSidebar slot="right" content={content} editUrl={editUrlWithFile} inviteUrl={CONFIG.COMMUNITY_URL} />
|
||||
</PageLayout>
|
||||
```
|
||||
|
||||
You can customize any section of the page layout by replacing these components with components of your own. Replacing `<LeftSidebar slot="left" ... />` with `<MySidebar slot="left" />`, for example, will place your `<MySidebar />` component in the left sidebar section of the page layout. Many components can share the same slot, if you'd like to add new UI without removing existing.
|
||||
|
||||
You can control the document `<head>` using the `slot="head"` slot. By default, no elements are added to the page head for you. We recommend placing all `<head>` elements into one (or more) `src/components/Head.astro` component(s) in your project.
|
||||
|
||||
See the `<PageLayout />` documentation below for a list of all supported slots.
|
||||
## Components
|
||||
### All Layout Components
|
||||
|
||||
These components control full pieces of the docs page layout, including sidebars and headers. `<PageLayout />` controls the CSS Grid layout, while the rest control the UI that ends up in each area of the grid. You can use all of them together, or mix-and-match different UI inside of `<PageLayout />`.
|
||||
|
||||
```js
|
||||
import {
|
||||
// The full page layout. See supported slots in the example above.
|
||||
PageLayout,
|
||||
// Individual parts of the default page layout.
|
||||
Header,
|
||||
LeftSidebar,
|
||||
RightSidebar,
|
||||
PageContent,
|
||||
} from '@astrojs/docs';
|
||||
```
|
||||
|
||||
### All Static UI Components
|
||||
|
||||
These components are static and require zero JavaScript to run.
|
||||
|
||||
```js
|
||||
import {
|
||||
AstroLogo,
|
||||
AvatarList,
|
||||
SkipToContent,
|
||||
} from '@astrojs/docs';
|
||||
```
|
||||
### All Dynamic UI Components
|
||||
|
||||
These components may require JavaScript to run. You can include JavaScript automatically by using them with `client:*` directives. Check out Astro's documentation on [Partial Hydration](https://docs.astro.build/core-concepts/component-hydration) for more information.
|
||||
|
||||
```js
|
||||
import {
|
||||
LanguageSelect,
|
||||
Search,
|
||||
SidebarToggle,
|
||||
ThemeToggle,
|
||||
TableOfContents,
|
||||
} from '@astrojs/docs';
|
||||
```
|
17
packages/components/docs/astro.config.mjs
Normal file
17
packages/components/docs/astro.config.mjs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Full Astro Configuration API Documentation:
|
||||
// https://docs.astro.build/reference/configuration-reference
|
||||
|
||||
// @type-check enabled!
|
||||
// VSCode and other TypeScript-enabled text editors will provide auto-completion,
|
||||
// helpful tooltips, and warnings if your exported object is invalid.
|
||||
// You can disable this by removing "@ts-check" and `@type` comments below.
|
||||
|
||||
// @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',
|
||||
],
|
||||
});
|
21
packages/components/docs/package.json
Normal file
21
packages/components/docs/package.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "@astrojs/docs",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview"
|
||||
},
|
||||
"main": "./src/index.js",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@docsearch/react": "^1.0.0-alpha.27"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "^0.20.3"
|
||||
},
|
||||
"snowpack": {
|
||||
"workspaceRoot": "../../.."
|
||||
}
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
---
|
||||
import { getLanguageFromURL, KNOWN_LANGUAGE_CODES } from '../../languages.ts';
|
||||
import * as CONFIG from '../../config.ts';
|
||||
import AstroLogo from './AstroLogo.astro';
|
||||
import SkipToContent from './SkipToContent.astro';
|
||||
import SidebarToggle from './SidebarToggle.tsx';
|
||||
import LanguageSelect from './LanguageSelect.jsx';
|
||||
import Search from "./Search.jsx";
|
||||
|
||||
const {currentPage} = Astro.props;
|
||||
const lang = currentPage && getLanguageFromURL(currentPage);
|
||||
import AstroLogo from '../components/AstroLogo.astro';
|
||||
import SkipToContent from '../components/SkipToContent.astro';
|
||||
import SidebarToggle from '../components/SidebarToggle.js';
|
||||
import LanguageSelect from '../components/LanguageSelect.js';
|
||||
import Search from '../components/Search.js';
|
||||
const {currentPage, lang, languages, search} = Astro.props;
|
||||
---
|
||||
<style>
|
||||
header {
|
||||
|
@ -126,7 +122,12 @@ const lang = currentPage && getLanguageFromURL(currentPage);
|
|||
</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>}
|
||||
{Object.keys(languages).length > 1 && <LanguageSelect lang={lang} options={languages} client:idle />}
|
||||
{search && <div class="search-item">
|
||||
<Search
|
||||
client:idle
|
||||
indexName={search.indexName}
|
||||
apiKey={search.apiKey} />
|
||||
</div>}
|
||||
</nav>
|
||||
</header>
|
|
@ -1,11 +1,8 @@
|
|||
---
|
||||
import { getLanguageFromURL } from '../../languages.ts';
|
||||
import { SIDEBAR } from '../../config.ts';
|
||||
const {currentPage} = Astro.props;
|
||||
const {currentPage, navigation} = 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) => {
|
||||
const sidebarSections = navigation.reduce((col, item) => {
|
||||
if (item.header) {
|
||||
col.push({...item, children: []});
|
||||
} else {
|
80
packages/components/docs/src/PageLayout/PageContent.astro
Normal file
80
packages/components/docs/src/PageLayout/PageContent.astro
Normal file
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
import TableOfContents from '../components/TableOfContents.jsx';
|
||||
const {content} = Astro.props;
|
||||
const title = content.title;
|
||||
const headers = content.astro.headers;
|
||||
---
|
||||
<style>
|
||||
.nav {
|
||||
display: block;
|
||||
margin: 2rem 0 2rem -1rem;
|
||||
}
|
||||
footer {
|
||||
margin-top: auto;
|
||||
padding: 2rem 0;
|
||||
border-top: 3px solid var(--theme-divider);
|
||||
}
|
||||
@media (min-width: 72em) {
|
||||
.sm\:hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style global>
|
||||
.content {
|
||||
padding: 0;
|
||||
max-width: 75ch;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
.content ul {
|
||||
line-height: 1.1em;
|
||||
color: var(--theme-text-light);
|
||||
}
|
||||
.content > section > * + * {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
.content > section > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.content > section :is(ul, ol) > * + * {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
.content > section nav :is(ul, ol) > * + * {
|
||||
margin-top: inherit;
|
||||
}
|
||||
.content > section li > :is(p, pre, blockquote):not(:first-child) {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.content > section :is(ul, ol) {
|
||||
padding-left: 1em;
|
||||
}
|
||||
.content > section nav :is(ul, ol) {
|
||||
padding-left: inherit;
|
||||
}
|
||||
.content > section nav {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.content > section ::marker {
|
||||
font-weight: bold;
|
||||
color: var(--theme-text-light);
|
||||
}
|
||||
.content > section iframe {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
aspect-ratio: 16 / 9;
|
||||
}
|
||||
</style>
|
||||
<article id="article" class="content">
|
||||
<section class="main-section">
|
||||
<h1 class="content-title" id="overview">{title}</h1>
|
||||
<nav class="nav sm:hidden">
|
||||
<TableOfContents client:media="(max-width: 50em)" headers={headers}/>
|
||||
</nav>
|
||||
<slot />
|
||||
</section>
|
||||
</article>
|
115
packages/components/docs/src/PageLayout/PageLayout.astro
Normal file
115
packages/components/docs/src/PageLayout/PageLayout.astro
Normal file
|
@ -0,0 +1,115 @@
|
|||
---
|
||||
const { dir, lang } = Astro.props;
|
||||
---
|
||||
|
||||
<html dir="{dir || 'ltr'}" lang="{lang || 'en'}" class="initial">
|
||||
<head>
|
||||
<slot name="head" />
|
||||
<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;
|
||||
}
|
||||
.grid-sidebar {
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#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%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#grid-right {
|
||||
grid-column: 2;
|
||||
}
|
||||
: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;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<slot name="header" />
|
||||
<main class="layout">
|
||||
<aside id="grid-left" class="grid-sidebar" title="Site Navigation">
|
||||
<slot name="left" />
|
||||
</aside>
|
||||
<div id="grid-main">
|
||||
<slot name="main" />
|
||||
</div>
|
||||
<aside id="grid-right" class="grid-right-sidebar" title="Table of Contents">
|
||||
<slot name="right" />
|
||||
</aside>
|
||||
</main>
|
||||
|
||||
<!-- Scrollable a11y code helper -->
|
||||
<script type="module">
|
||||
Array.from(document.getElementsByTagName('pre')).forEach((element) => {
|
||||
element.setAttribute('tabindex', '0');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
34
packages/components/docs/src/PageLayout/RightSidebar.astro
Normal file
34
packages/components/docs/src/PageLayout/RightSidebar.astro
Normal file
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
import TableOfContents from '../components/TableOfContents.jsx';
|
||||
import MoreMenu from '../components/MoreMenu.astro';
|
||||
const {content, editUrl, inviteUrl} = Astro.props;
|
||||
---
|
||||
<style>
|
||||
.lg\:hidden {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 72em) {
|
||||
.sidebar-nav {
|
||||
width: 100%;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
.sidebar-nav-inner {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
padding-top: var(--doc-padding);
|
||||
overflow: auto;
|
||||
}
|
||||
.lg\:hidden {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<nav class="sidebar-nav" aria-labelledby="grid-right">
|
||||
<div class="sidebar-nav-inner">
|
||||
<div class="lg:hidden" >
|
||||
<TableOfContents client:media="(min-width: 50em)" headers={content.astro.headers} />
|
||||
</div>
|
||||
<MoreMenu editUrl={editUrl} inviteUrl={inviteUrl} />
|
||||
</div>
|
||||
</nav>
|
|
@ -1,8 +1,7 @@
|
|||
---
|
||||
// fetch all commits for just this page's path
|
||||
const path = "docs/" + Astro.props.path;
|
||||
const url = `https://api.github.com/repos/snowpackjs/astro/commits?path=${path}`;
|
||||
const commitsURL = `https://github.com/snowpackjs/astro/commits/main/${path}`;
|
||||
const url = `https://api.github.com/repos/${Astro.props.repo}/commits?path=${Astro.props.file}`;
|
||||
const commitsURL = `https://github.com/${Astro.props.repo}/commits/${Astro.props.branch || 'main'}/${Astro.props.file}`;
|
||||
|
||||
async function getCommits(url) {
|
||||
try {
|
||||
|
@ -34,8 +33,7 @@ async function getCommits(url) {
|
|||
|
||||
return data;
|
||||
} catch (e) {
|
||||
console.warn(`[error] /src/components/AvatarList.astro
|
||||
${e?.message ?? e}`);
|
||||
console.warn(`[error] AvatarList: ${e && e.message || e}`);
|
||||
return new Array();
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
import type { FunctionalComponent } from 'preact';
|
||||
import { h } from 'preact';
|
||||
import type { FunctionalComponent } from 'preact';
|
||||
import './LanguageSelect.css';
|
||||
import { KNOWN_LANGUAGES, langPathRegex } from '../../languages';
|
||||
|
||||
const LanguageSelect: FunctionalComponent<{ lang: string }> = ({ lang }) => {
|
||||
const LanguageSelect: FunctionalComponent<{ lang: string, options: Record<string, string> }> = ({ lang, options }) => {
|
||||
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">
|
||||
|
@ -18,14 +17,12 @@ const LanguageSelect: FunctionalComponent<{ lang: string }> = ({ lang }) => {
|
|||
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;
|
||||
window.location.pathname = '/' + newLang + '/introduction';
|
||||
}}
|
||||
>
|
||||
{Object.keys(KNOWN_LANGUAGES).map((key) => {
|
||||
{Object.keys(options).map((key) => {
|
||||
return (
|
||||
<option value={KNOWN_LANGUAGES[key]}>
|
||||
<option value={options[key]}>
|
||||
<span>{key}</span>
|
||||
</option>
|
||||
);
|
|
@ -1,8 +1,7 @@
|
|||
---
|
||||
import ThemeToggleButton from './ThemeToggleButton.jsx';
|
||||
import * as CONFIG from '../../config.js';
|
||||
const {editHref} = Astro.props;
|
||||
const showMoreSection = (CONFIG.COMMUNITY_INVITE_URL || editHref);
|
||||
import ThemeToggle from './ThemeToggle.astro';
|
||||
const {editUrl, inviteUrl} = Astro.props;
|
||||
const showMoreSection = (inviteUrl || editUrl);
|
||||
---
|
||||
<style>
|
||||
.edit-on-github {
|
||||
|
@ -14,9 +13,9 @@ const showMoreSection = (CONFIG.COMMUNITY_INVITE_URL || editHref);
|
|||
</style>
|
||||
{showMoreSection && <h2 class="heading">More</h2>}
|
||||
<ul>
|
||||
{editHref &&
|
||||
{editUrl &&
|
||||
<li class={`header-link depth-2`}>
|
||||
<a class="edit-on-github" href={editHref} target="_blank">
|
||||
<a class="edit-on-github" href={editUrl} target="_blank">
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
|
@ -38,7 +37,7 @@ const showMoreSection = (CONFIG.COMMUNITY_INVITE_URL || editHref);
|
|||
</a>
|
||||
</li>
|
||||
}
|
||||
{CONFIG.COMMUNITY_INVITE_URL &&
|
||||
{inviteUrl &&
|
||||
<li class={`header-link depth-2`}>
|
||||
<a href="https://astro.build/chat" target="_blank">
|
||||
<svg
|
||||
|
@ -64,5 +63,5 @@ const showMoreSection = (CONFIG.COMMUNITY_INVITE_URL || editHref);
|
|||
}
|
||||
</ul>
|
||||
<div style="margin: 2rem 0; text-align: center;">
|
||||
<ThemeToggleButton client:visible />
|
||||
<ThemeToggle />
|
||||
</div>
|
|
@ -2,11 +2,10 @@
|
|||
import { useState, useCallback, useRef } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { DocSearchModal, useDocSearchKeyboardEvents } from '@docsearch/react';
|
||||
import * as CONFIG from '../../config.js';
|
||||
import '@docsearch/css/dist/style.css';
|
||||
import './Search.css';
|
||||
|
||||
export default function Search() {
|
||||
export default function Search({indexName, apiKey}) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const searchButtonRef = useRef();
|
||||
const [initialQuery, setInitialQuery] = useState(null);
|
||||
|
@ -54,8 +53,8 @@ export default function Search() {
|
|||
initialQuery={initialQuery}
|
||||
initialScrollY={window.scrollY}
|
||||
onClose={onClose}
|
||||
indexName={(CONFIG as any).ALGOLIA.indexName}
|
||||
apiKey={(CONFIG as any).ALGOLIA.apiKey}
|
||||
indexName={indexName}
|
||||
apiKey={apiKey}
|
||||
transformItems={(items) => {
|
||||
return items.map((item) => {
|
||||
// We transform the absolute URL into a relative URL to
|
15
packages/components/docs/src/components/ThemeToggle.astro
Normal file
15
packages/components/docs/src/components/ThemeToggle.astro
Normal file
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
import ThemeToggleButton from './ThemeToggleButton.js';
|
||||
---
|
||||
<!-- This is intentionally inlined to avoid FOUC -->
|
||||
<script hoist>
|
||||
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>
|
||||
|
||||
<ThemeToggleButton client:visible />
|
16
packages/components/docs/src/index.js
Normal file
16
packages/components/docs/src/index.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* Layout Components */
|
||||
export { default as PageLayout } from './PageLayout/PageLayout.astro';
|
||||
export { default as Header } from './PageLayout/Header.astro';
|
||||
export { default as LeftSidebar } from './PageLayout/LeftSidebar.astro';
|
||||
export { default as PageContent } from './PageLayout/PageContent.astro';
|
||||
export { default as RightSidebar } from './PageLayout/RightSidebar.astro';
|
||||
|
||||
/* Reusable UI Components */
|
||||
export { default as AvatarList } from './components/AvatarList.astro';
|
||||
export { default as AstroLogo } from './components/AstroLogo.astro';
|
||||
export { default as SkipToContent } from './components/SkipToContent.astro';
|
||||
export { default as SidebarToggle } from './components/SidebarToggle.jsx';
|
||||
export { default as LanguageSelect } from './components/LanguageSelect.jsx';
|
||||
export { default as Search } from './components/Search.jsx';
|
||||
export { default as ThemeToggle } from './components/ThemeToggle.astro';
|
||||
export { default as TableOfContents } from './components/TableOfContents.jsx';
|
9
packages/components/docs/tsconfig.json
Normal file
9
packages/components/docs/tsconfig.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src"],
|
||||
"compilerOptions": {
|
||||
"target": "ES2019",
|
||||
"module": "CommonJS",
|
||||
"outDir": "./dist"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue