diff --git a/website/__a11y__/test-utils.ts b/website/__a11y__/test-utils.ts index e5b934aef..ea95e653b 100644 --- a/website/__a11y__/test-utils.ts +++ b/website/__a11y__/test-utils.ts @@ -21,35 +21,18 @@ const config: Config = { i18n: { // A list of slugs to exclude from the sitemap for the default locale. // By default, all slugs for the default locale are included. - exclude: [ - 'components/using-components', - 'getting-started', - 'guides/customization', - 'guides/i18n', - 'guides/overriding-components', - 'guides/pages', - 'guides/project-structure', - 'guides/route-data', - 'guides/site-search', - 'manual-setup', - 'reference/frontmatter', - 'reference/overrides', - 'reference/plugins', - 'reference/route-data', - ], + exclude: [], // Locale-specific included slugs (non-default locale slugs are excluded by default). - locales: { - // N.B. If adding more locales here, also update the changed files filters in - // `.github/workflows/ci.yml` to ensure tests run when files for those locales change. - ja: ['guides/route-data', 'reference/frontmatter'], - }, + locales: {}, }, // A list of violation to ignore. ignore: [{ id: 'landmark-unique', nodeMatcher: landmarkUniqueNodeMatcher }], sitemap: { url: 'http://localhost:4321/sitemap-index.xml', replace: { - query: 'https://starlight.astro.build', + // The sitemap lists production URLs (astro.config.mjs `site`); rewrite + // them onto the local preview server under test. + query: 'https://actionbase.io', value: 'http://localhost:4321', }, }, diff --git a/website/astro.config.mjs b/website/astro.config.mjs index 4ebca1324..ab7443592 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -2,11 +2,9 @@ import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; import starlightLinksValidator from 'starlight-links-validator'; -import markdocGrammar from './grammars/markdoc.tmLanguage.json'; import starlightLlmsTxt from 'starlight-llms-txt'; import mermaid from 'astro-mermaid'; import { remarkHeadingId } from 'remark-custom-heading-id'; -import starlightUtils from '@lorenzo_lewis/starlight-utils'; export const locales = { root: { label: 'English', lang: 'en' }, @@ -85,8 +83,23 @@ export default defineConfig({ editLink: { baseUrl: 'https://github.com/kakao/actionbase/edit/main/website/', }, - social: [], + social: [{ icon: 'github', label: 'GitHub', href: 'https://github.com/kakao/actionbase' }], head: [ + { + tag: 'link', + attrs: { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, + }, + { + tag: 'link', + attrs: { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true }, + }, + { + tag: 'link', + attrs: { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Cormorant:wght@500;600;700&family=Manrope:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;700&display=swap', + }, + }, { tag: 'script', attrs: { async: true, src: `https://www.googletagmanager.com/gtag/js?id=${GA_ID}` }, @@ -113,81 +126,54 @@ export default defineConfig({ locales, sidebar: [ { - label: 'Nav', - items: [ - { label: 'Docs', slug: 'introduction' }, - { - label: 'GitHub', - link: 'https://github.com/kakao/actionbase', - attrs: { class: 'nav-external', target: '_blank', rel: 'noopener' }, - }, - ], - }, - { - label: 'Main', - items: [ - { - label: 'Getting Started', - items: ['introduction', 'quick-start', 'faq', 'for-rdb-users', 'llms-txt'], - }, - { - label: 'Design', - autogenerate: { directory: 'design' }, - }, - { - label: 'Guides', - autogenerate: { directory: 'guides' }, - }, - { - label: 'Provisioning', - autogenerate: { directory: 'provisioning' }, - }, - { - label: 'Operations', - autogenerate: { directory: 'operations' }, - }, - { - label: 'Internals', - autogenerate: { directory: 'internals' }, - }, - { - label: 'API References', - autogenerate: { directory: 'api-references' }, - }, - { - label: 'Project', - autogenerate: { directory: 'project' }, - }, - 'community', - ], + label: 'Getting Started', + collapsed: true, + items: ['introduction', 'quick-start', 'faq', 'for-rdb-users', 'llms-txt'], }, + { label: 'Design', collapsed: true, autogenerate: { directory: 'design' } }, + { label: 'Guides', collapsed: true, autogenerate: { directory: 'guides' } }, + { label: 'Provisioning', collapsed: true, autogenerate: { directory: 'provisioning' } }, + { label: 'Operations', collapsed: true, autogenerate: { directory: 'operations' } }, + { label: 'Internals', collapsed: true, autogenerate: { directory: 'internals' } }, + { label: 'API References', collapsed: true, autogenerate: { directory: 'api-references' } }, + { label: 'Project', collapsed: true, autogenerate: { directory: 'project' } }, { label: 'Stories', + collapsed: true, items: [ 'stories', - { label: 'Use Cases', autogenerate: { directory: 'stories/use-cases' } }, - { label: 'Engineering', autogenerate: { directory: 'stories/engineering' } }, - { label: 'How We Survived', autogenerate: { directory: 'stories/how-we-survived' } }, - { label: 'Vision', autogenerate: { directory: 'stories/vision' } }, + { label: 'Use Cases', collapsed: true, autogenerate: { directory: 'stories/use-cases' } }, + { label: 'Engineering', collapsed: true, autogenerate: { directory: 'stories/engineering' } }, + { label: 'How We Survived', collapsed: true, autogenerate: { directory: 'stories/how-we-survived' } }, + { label: 'Vision', collapsed: true, autogenerate: { directory: 'stories/vision' } }, ], }, + 'community', ], components: { Head: './src/components/Head.astro', PageSidebar: './src/components/PageSidebar.astro', + ThemeSelect: './src/components/ThemeSelect.astro', + Footer: './src/components/Footer.astro', }, - expressiveCode: { shiki: { langs: [markdocGrammar] } }, - plugins: [ - starlightUtils({ - multiSidebar: { - switcherStyle: 'horizontalList', - }, - navLinks: { - leading: { - useSidebarLabelled: 'Nav', - }, + expressiveCode: { + // A single dark theme keeps code blocks on the terminal surface in both + // light and dark site themes, matching the design mocks. + themes: ['github-dark'], + styleOverrides: { + borderRadius: '10px', + borderColor: 'transparent', + codeBackground: '#1b1c2b', + frames: { + editorBackground: '#1b1c2b', + terminalBackground: '#1b1c2b', + editorActiveTabBackground: '#1b1c2b', + terminalTitlebarBackground: '#1b1c2b', + shadowColor: 'transparent', }, - }), + }, + }, + plugins: [ starlightLinksValidator({ errorOnFallbackPages: false, }), diff --git a/website/grammars/README.md b/website/grammars/README.md deleted file mode 100644 index 8a74cb944..000000000 --- a/website/grammars/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Starlight Docs Grammars - -This directory contains additional grammars for the Starlight documentation website. - -## Grammars - -The following additional grammars are generated and available for use: - -- [Markdoc](https://github.com/markdoc/language-server) - -## Usage - -To generate the grammars from their source files, run: - -```sh -pnpm grammars -``` - -To include the grammars in the Starlight documentation website, update the `expressiveCode.shiki.langs` array in the `astro.config.mjs` file: - -```diff -starlight({ - expressiveCode: { - shiki: { - langs: [ - JSON.parse( - fs.readFileSync('./grammars/existing.tmLanguage.json', 'utf-8'), -+ fs.readFileSync('./grammars/new.tmLanguage.json', 'utf-8'), - ), - ], - }, - }, -}); -``` diff --git a/website/grammars/generate.mjs b/website/grammars/generate.mjs deleted file mode 100644 index 5b930a403..000000000 --- a/website/grammars/generate.mjs +++ /dev/null @@ -1,74 +0,0 @@ -// @ts-check - -import fs from 'node:fs/promises'; - -const markdown = { - repo: 'shikijs/textmate-grammars-themes', - tmLanguagePath: 'packages/tm-grammars/grammars/markdown.json', -}; - -const markdoc = { - repo: 'markdoc/language-server', - // We don't need the Markdoc grammar, only the Markdoc Markdown grammar. - // tmLanguagePath: 'syntaxes/markdoc.tmLanguage.json', - markdownTmLanguagePath: 'syntaxes/markdoc.markdown.tmLanguage.json', -}; - -/** - * Download a TextMate grammar file from a GitHub repository. - * @param {string} repo - * @param {string} path - */ -async function fetchTmLanguage(repo, path) { - const url = `https://raw.githubusercontent.com/${repo}/main/${path}`; - const response = await fetch(url); - const data = await response.json(); - return data; -} - -// Download the TextMate grammar files for Markdown. -const markdownTmLanguage = await fetchTmLanguage(markdown.repo, markdown.tmLanguagePath); - -// Download the TextMate grammar files for Markdoc Markdown. -const markdocMarkdownTmLanguage = await fetchTmLanguage( - markdoc.repo, - markdoc.markdownTmLanguagePath -); - -// Reference: https://macromates.com/manual/en/language_grammars - -// Update the name and scope name for the Markdoc grammar. -markdownTmLanguage.name = 'markdoc'; -markdownTmLanguage.scopeName = 'text.html.markdoc'; - -// Merge the Markdown and Markdoc Markdown grammar repositories. -markdownTmLanguage.repository = { - ...markdownTmLanguage.repository, - ...markdocMarkdownTmLanguage.repository, -}; - -// Include the Markdoc Markdown grammar rules at the beginning of the Markdown grammar. -for (const rule of Object.keys(markdocMarkdownTmLanguage.repository)) { - // Skip shortcut rules as they break syntax highlighting of child content that includes dots in - // words and we don't ever use them. - if (rule === 'shortcut') continue; - - markdownTmLanguage.repository.block.patterns.unshift({ include: `#${rule}` }); - markdownTmLanguage.repository.inline.patterns.unshift({ include: `#${rule}` }); -} - -// Write the grammar to a file. -await fs.writeFile( - './grammars/markdoc.tmLanguage.json', - JSON.stringify( - markdownTmLanguage, - (key, value) => { - // The `applyEndPatternLast` property should be a boolean and not a number. - if (key === 'applyEndPatternLast') return Boolean(value); - return value; - }, - 2 - ) -); - -console.log('Markdoc grammar generated successfully.'); diff --git a/website/grammars/markdoc.tmLanguage.json b/website/grammars/markdoc.tmLanguage.json deleted file mode 100644 index 7089fd499..000000000 --- a/website/grammars/markdoc.tmLanguage.json +++ /dev/null @@ -1,3142 +0,0 @@ -{ - "displayName": "Markdown", - "name": "markdoc", - "patterns": [ - { - "include": "#frontMatter" - }, - { - "include": "#block" - } - ], - "repository": { - "ampersand": { - "comment": "Markdown will convert this for us. We match it so that the HTML grammar will not mark it up as invalid.", - "match": "&(?!([a-zA-Z0-9]+|#\\d+|#x[0-9a-fA-F]+);)", - "name": "meta.other.valid-ampersand.markdown" - }, - "block": { - "patterns": [ - { - "include": "#tag" - }, - { - "include": "#attribute" - }, - { - "include": "#separator" - }, - { - "include": "#heading" - }, - { - "include": "#blockquote" - }, - { - "include": "#lists" - }, - { - "include": "#fenced_code_block" - }, - { - "include": "#raw_block" - }, - { - "include": "#link-def" - }, - { - "include": "#html" - }, - { - "include": "#table" - }, - { - "include": "#paragraph" - } - ] - }, - "blockquote": { - "begin": "(^|\\G)[ ]{0,3}(>) ?", - "captures": { - "2": { - "name": "punctuation.definition.quote.begin.markdown" - } - }, - "name": "markup.quote.markdown", - "patterns": [ - { - "include": "#block" - } - ], - "while": "(^|\\G)\\s*(>) ?" - }, - "bold": { - "begin": "(?(\\*\\*(?=\\w)|(?]*+>|(?`+)([^`]|(?!(?(?!`))`)*+\\k|\\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+|\\[((?[^\\[\\]\\\\]|\\\\.|\\[\\g*+\\])*+\\](([ ]?\\[[^\\]]*+\\])|(\\([ \\t]*+?[ \\t]*+((?['\"])(.*?)\\k<title>)?\\))))|(?!(?<=\\S)\\k<open>).)++(?<=\\S)(?=__\\b|\\*\\*)\\k<open>)", - "captures": { - "1": { - "name": "punctuation.definition.bold.markdown" - } - }, - "end": "(?<=\\S)(\\1)", - "name": "markup.bold.markdown", - "patterns": [ - { - "applyEndPatternLast": true, - "begin": "(?=<[^>]*?>)", - "end": "(?<=>)", - "patterns": [ - { - "include": "text.html.derivative" - } - ] - }, - { - "include": "#escape" - }, - { - "include": "#ampersand" - }, - { - "include": "#bracket" - }, - { - "include": "#raw" - }, - { - "include": "#bold" - }, - { - "include": "#italic" - }, - { - "include": "#image-inline" - }, - { - "include": "#link-inline" - }, - { - "include": "#link-inet" - }, - { - "include": "#link-email" - }, - { - "include": "#image-ref" - }, - { - "include": "#link-ref-literal" - }, - { - "include": "#link-ref" - }, - { - "include": "#link-ref-shortcut" - }, - { - "include": "#strikethrough" - } - ] - }, - "bracket": { - "comment": "Markdown will convert this for us. We match it so that the HTML grammar will not mark it up as invalid.", - "match": "<(?![a-zA-Z/?$!])", - "name": "meta.other.valid-bracket.markdown" - }, - "escape": { - "match": "\\\\[-`*_#+.!(){}\\[\\]\\\\>]", - "name": "constant.character.escape.markdown" - }, - "fenced_code_block": { - "patterns": [ - { - "include": "#fenced_code_block_css" - }, - { - "include": "#fenced_code_block_basic" - }, - { - "include": "#fenced_code_block_ini" - }, - { - "include": "#fenced_code_block_java" - }, - { - "include": "#fenced_code_block_lua" - }, - { - "include": "#fenced_code_block_makefile" - }, - { - "include": "#fenced_code_block_perl" - }, - { - "include": "#fenced_code_block_r" - }, - { - "include": "#fenced_code_block_ruby" - }, - { - "include": "#fenced_code_block_php" - }, - { - "include": "#fenced_code_block_sql" - }, - { - "include": "#fenced_code_block_vs_net" - }, - { - "include": "#fenced_code_block_xml" - }, - { - "include": "#fenced_code_block_xsl" - }, - { - "include": "#fenced_code_block_yaml" - }, - { - "include": "#fenced_code_block_dosbatch" - }, - { - "include": "#fenced_code_block_clojure" - }, - { - "include": "#fenced_code_block_coffee" - }, - { - "include": "#fenced_code_block_c" - }, - { - "include": "#fenced_code_block_cpp" - }, - { - "include": "#fenced_code_block_diff" - }, - { - "include": "#fenced_code_block_dockerfile" - }, - { - "include": "#fenced_code_block_git_commit" - }, - { - "include": "#fenced_code_block_git_rebase" - }, - { - "include": "#fenced_code_block_go" - }, - { - "include": "#fenced_code_block_groovy" - }, - { - "include": "#fenced_code_block_pug" - }, - { - "include": "#fenced_code_block_js" - }, - { - "include": "#fenced_code_block_js_regexp" - }, - { - "include": "#fenced_code_block_json" - }, - { - "include": "#fenced_code_block_jsonc" - }, - { - "include": "#fenced_code_block_less" - }, - { - "include": "#fenced_code_block_objc" - }, - { - "include": "#fenced_code_block_swift" - }, - { - "include": "#fenced_code_block_scss" - }, - { - "include": "#fenced_code_block_perl6" - }, - { - "include": "#fenced_code_block_powershell" - }, - { - "include": "#fenced_code_block_python" - }, - { - "include": "#fenced_code_block_julia" - }, - { - "include": "#fenced_code_block_regexp_python" - }, - { - "include": "#fenced_code_block_rust" - }, - { - "include": "#fenced_code_block_scala" - }, - { - "include": "#fenced_code_block_shell" - }, - { - "include": "#fenced_code_block_ts" - }, - { - "include": "#fenced_code_block_tsx" - }, - { - "include": "#fenced_code_block_csharp" - }, - { - "include": "#fenced_code_block_fsharp" - }, - { - "include": "#fenced_code_block_dart" - }, - { - "include": "#fenced_code_block_handlebars" - }, - { - "include": "#fenced_code_block_markdown" - }, - { - "include": "#fenced_code_block_log" - }, - { - "include": "#fenced_code_block_erlang" - }, - { - "include": "#fenced_code_block_elixir" - }, - { - "include": "#fenced_code_block_latex" - }, - { - "include": "#fenced_code_block_bibtex" - }, - { - "include": "#fenced_code_block_twig" - }, - { - "include": "#fenced_code_block_unknown" - } - ] - }, - "fenced_code_block_basic": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(html|htm|shtml|xhtml|inc|tmpl|tpl)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.html", - "patterns": [ - { - "include": "text.html.basic" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_bibtex": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(bibtex)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.bibtex", - "patterns": [ - { - "include": "text.bibtex" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_c": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(c|h)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.c", - "patterns": [ - { - "include": "source.c" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_clojure": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(clj|cljs|clojure)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.clojure", - "patterns": [ - { - "include": "source.clojure" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_coffee": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(coffee|Cakefile|coffee.erb)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.coffee", - "patterns": [ - { - "include": "source.coffee" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_cpp": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(cpp|c\\+\\+|cxx)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.cpp source.cpp", - "patterns": [ - { - "include": "source.cpp" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_csharp": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(cs|csharp|c#)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.csharp", - "patterns": [ - { - "include": "source.cs" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_css": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(css|css.erb)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.css", - "patterns": [ - { - "include": "source.css" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_dart": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(dart)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.dart", - "patterns": [ - { - "include": "source.dart" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_diff": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(patch|diff|rej)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.diff", - "patterns": [ - { - "include": "source.diff" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_dockerfile": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(dockerfile|Dockerfile)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.dockerfile", - "patterns": [ - { - "include": "source.dockerfile" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_dosbatch": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(bat|batch)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.dosbatch", - "patterns": [ - { - "include": "source.batchfile" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_elixir": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(elixir)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.elixir", - "patterns": [ - { - "include": "source.elixir" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_erlang": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(erlang)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.erlang", - "patterns": [ - { - "include": "source.erlang" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_fsharp": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(fs|fsharp|f#)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.fsharp", - "patterns": [ - { - "include": "source.fsharp" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_git_commit": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(COMMIT_EDITMSG|MERGE_MSG)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.git_commit", - "patterns": [ - { - "include": "text.git-commit" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_git_rebase": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(git-rebase-todo)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.git_rebase", - "patterns": [ - { - "include": "text.git-rebase" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_go": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(go|golang)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.go", - "patterns": [ - { - "include": "source.go" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_groovy": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(groovy|gvy)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.groovy", - "patterns": [ - { - "include": "source.groovy" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_handlebars": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(handlebars|hbs)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.handlebars", - "patterns": [ - { - "include": "text.html.handlebars" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_ini": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(ini|conf)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.ini", - "patterns": [ - { - "include": "source.ini" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_java": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(java|bsh)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.java", - "patterns": [ - { - "include": "source.java" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_js": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(js|jsx|javascript|es6|mjs|cjs|dataviewjs|\\{\\.js.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.javascript", - "patterns": [ - { - "include": "source.js" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_js_regexp": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(regexp)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.js_regexp", - "patterns": [ - { - "include": "source.js.regexp" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_json": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(json|json5|sublime-settings|sublime-menu|sublime-keymap|sublime-mousemap|sublime-theme|sublime-build|sublime-project|sublime-completions)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.json", - "patterns": [ - { - "include": "source.json" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_jsonc": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(jsonc)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.jsonc", - "patterns": [ - { - "include": "source.json.comments" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_julia": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(julia|\\{\\.julia.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.julia", - "patterns": [ - { - "include": "source.julia" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_latex": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(latex|tex)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.latex", - "patterns": [ - { - "include": "text.tex.latex" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_less": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(less)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.less", - "patterns": [ - { - "include": "source.css.less" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_log": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(log)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.log", - "patterns": [ - { - "include": "text.log" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_lua": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(lua)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.lua", - "patterns": [ - { - "include": "source.lua" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_makefile": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(Makefile|makefile|GNUmakefile|OCamlMakefile)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.makefile", - "patterns": [ - { - "include": "source.makefile" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_markdown": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(markdown|md)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.markdown", - "patterns": [ - { - "include": "text.html.markdown" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_objc": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(objectivec|objective-c|mm|objc|obj-c|m|h)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.objc", - "patterns": [ - { - "include": "source.objc" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_perl": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(perl|pl|pm|pod|t|PL|psgi|vcl)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.perl", - "patterns": [ - { - "include": "source.perl" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_perl6": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(perl6|p6|pl6|pm6|nqp)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.perl6", - "patterns": [ - { - "include": "source.perl.6" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_php": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(php|php3|php4|php5|phpt|phtml|aw|ctp)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.php", - "patterns": [ - { - "include": "text.html.basic" - }, - { - "include": "source.php" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_powershell": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(powershell|ps1|psm1|psd1|pwsh)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.powershell", - "patterns": [ - { - "include": "source.powershell" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_pug": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(jade|pug)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.pug", - "patterns": [ - { - "include": "text.pug" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_python": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(python|py|py3|rpy|pyw|cpy|SConstruct|Sconstruct|sconstruct|SConscript|gyp|gypi|\\{\\.python.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.python", - "patterns": [ - { - "include": "source.python" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_r": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(R|r|s|S|Rprofile|\\{\\.r.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.r", - "patterns": [ - { - "include": "source.r" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_regexp_python": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(re)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.regexp_python", - "patterns": [ - { - "include": "source.regexp.python" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_ruby": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(ruby|rb|rbx|rjs|Rakefile|rake|cgi|fcgi|gemspec|irbrc|Capfile|ru|prawn|Cheffile|Gemfile|Guardfile|Hobofile|Vagrantfile|Appraisals|Rantfile|Berksfile|Berksfile.lock|Thorfile|Puppetfile)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.ruby", - "patterns": [ - { - "include": "source.ruby" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_rust": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(rust|rs|\\{\\.rust.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.rust", - "patterns": [ - { - "include": "source.rust" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_scala": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(scala|sbt)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.scala", - "patterns": [ - { - "include": "source.scala" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_scss": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(scss)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.scss", - "patterns": [ - { - "include": "source.css.scss" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_shell": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(shell|sh|bash|zsh|bashrc|bash_profile|bash_login|profile|bash_logout|.textmate_init|\\{\\.bash.+?\\})((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.shellscript", - "patterns": [ - { - "include": "source.shell" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_sql": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(sql|ddl|dml)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.sql", - "patterns": [ - { - "include": "source.sql" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_swift": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(swift)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.swift", - "patterns": [ - { - "include": "source.swift" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_ts": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(typescript|ts)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.typescript", - "patterns": [ - { - "include": "source.ts" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_tsx": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(tsx)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.typescriptreact", - "patterns": [ - { - "include": "source.tsx" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_twig": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(twig)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.twig", - "patterns": [ - { - "include": "source.twig" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_unknown": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?=([^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown" - }, - "fenced_code_block_vs_net": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(vb)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.vs_net", - "patterns": [ - { - "include": "source.asp.vb.net" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_xml": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(xml|xsd|tld|jsp|pt|cpt|dtml|rss|opml)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.xml", - "patterns": [ - { - "include": "text.xml" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_xsl": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(xsl|xslt)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.xsl", - "patterns": [ - { - "include": "text.xml.xsl" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "fenced_code_block_yaml": { - "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(yaml|yml)((\\s+|:|,|\\{|\\?)[^`]*)?$)", - "beginCaptures": { - "3": { - "name": "punctuation.definition.markdown" - }, - "4": { - "name": "fenced_code.block.language.markdown" - }, - "5": { - "name": "fenced_code.block.language.attributes.markdown" - } - }, - "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", - "endCaptures": { - "3": { - "name": "punctuation.definition.markdown" - } - }, - "name": "markup.fenced_code.block.markdown", - "patterns": [ - { - "begin": "(^|\\G)(\\s*)(.*)", - "contentName": "meta.embedded.block.yaml", - "patterns": [ - { - "include": "source.yaml" - } - ], - "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)" - } - ] - }, - "frontMatter": { - "applyEndPatternLast": true, - "begin": "\\A(?=(-{3,}))", - "end": "^ {,3}\\1-*[ \\t]*$|^[ \\t]*\\.{3}$", - "endCaptures": { - "0": { - "name": "punctuation.definition.end.frontmatter" - } - }, - "patterns": [ - { - "begin": "\\A(-{3,})(.*)$", - "beginCaptures": { - "1": { - "name": "punctuation.definition.begin.frontmatter" - }, - "2": { - "name": "comment.frontmatter" - } - }, - "contentName": "meta.embedded.block.frontmatter", - "patterns": [ - { - "include": "source.yaml" - } - ], - "while": "^(?! {,3}\\1-*[ \\t]*$|[ \\t]*\\.{3}$)" - } - ] - }, - "heading": { - "captures": { - "1": { - "patterns": [ - { - "captures": { - "1": { - "name": "punctuation.definition.heading.markdown" - }, - "2": { - "name": "entity.name.section.markdown", - "patterns": [ - { - "include": "#inline" - }, - { - "include": "text.html.derivative" - } - ] - }, - "3": { - "name": "punctuation.definition.heading.markdown" - } - }, - "match": "(#{6})\\s+(.*?)(?:\\s+(#+))?\\s*$", - "name": "heading.6.markdown" - }, - { - "captures": { - "1": { - "name": "punctuation.definition.heading.markdown" - }, - "2": { - "name": "entity.name.section.markdown", - "patterns": [ - { - "include": "#inline" - }, - { - "include": "text.html.derivative" - } - ] - }, - "3": { - "name": "punctuation.definition.heading.markdown" - } - }, - "match": "(#{5})\\s+(.*?)(?:\\s+(#+))?\\s*$", - "name": "heading.5.markdown" - }, - { - "captures": { - "1": { - "name": "punctuation.definition.heading.markdown" - }, - "2": { - "name": "entity.name.section.markdown", - "patterns": [ - { - "include": "#inline" - }, - { - "include": "text.html.derivative" - } - ] - }, - "3": { - "name": "punctuation.definition.heading.markdown" - } - }, - "match": "(#{4})\\s+(.*?)(?:\\s+(#+))?\\s*$", - "name": "heading.4.markdown" - }, - { - "captures": { - "1": { - "name": "punctuation.definition.heading.markdown" - }, - "2": { - "name": "entity.name.section.markdown", - "patterns": [ - { - "include": "#inline" - }, - { - "include": "text.html.derivative" - } - ] - }, - "3": { - "name": "punctuation.definition.heading.markdown" - } - }, - "match": "(#{3})\\s+(.*?)(?:\\s+(#+))?\\s*$", - "name": "heading.3.markdown" - }, - { - "captures": { - "1": { - "name": "punctuation.definition.heading.markdown" - }, - "2": { - "name": "entity.name.section.markdown", - "patterns": [ - { - "include": "#inline" - }, - { - "include": "text.html.derivative" - } - ] - }, - "3": { - "name": "punctuation.definition.heading.markdown" - } - }, - "match": "(#{2})\\s+(.*?)(?:\\s+(#+))?\\s*$", - "name": "heading.2.markdown" - }, - { - "captures": { - "1": { - "name": "punctuation.definition.heading.markdown" - }, - "2": { - "name": "entity.name.section.markdown", - "patterns": [ - { - "include": "#inline" - }, - { - "include": "text.html.derivative" - } - ] - }, - "3": { - "name": "punctuation.definition.heading.markdown" - } - }, - "match": "(#{1})\\s+(.*?)(?:\\s+(#+))?\\s*$", - "name": "heading.1.markdown" - } - ] - } - }, - "match": "(?:^|\\G)[ ]{0,3}(#{1,6}\\s+(.*?)(\\s+#{1,6})?\\s*)$", - "name": "markup.heading.markdown" - }, - "heading-setext": { - "patterns": [ - { - "match": "^(={3,})(?=[ \\t]*$\\n?)", - "name": "markup.heading.setext.1.markdown" - }, - { - "match": "^(-{3,})(?=[ \\t]*$\\n?)", - "name": "markup.heading.setext.2.markdown" - } - ] - }, - "html": { - "patterns": [ - { - "begin": "(^|\\G)\\s*(<!--)", - "captures": { - "1": { - "name": "punctuation.definition.comment.html" - }, - "2": { - "name": "punctuation.definition.comment.html" - } - }, - "end": "(-->)", - "name": "comment.block.html" - }, - { - "begin": "(?i)(^|\\G)\\s*(?=<(script|style|pre)(\\s|$|>)(?!.*?</(script|style|pre)>))", - "end": "(?i)(.*)((</)(script|style|pre)(>))", - "endCaptures": { - "1": { - "patterns": [ - { - "include": "text.html.derivative" - } - ] - }, - "2": { - "name": "meta.tag.structure.$4.end.html" - }, - "3": { - "name": "punctuation.definition.tag.begin.html" - }, - "4": { - "name": "entity.name.tag.html" - }, - "5": { - "name": "punctuation.definition.tag.end.html" - } - }, - "patterns": [ - { - "begin": "(\\s*|$)", - "patterns": [ - { - "include": "text.html.derivative" - } - ], - "while": "(?i)^(?!.*</(script|style|pre)>)" - } - ] - }, - { - "begin": "(?i)(^|\\G)\\s*(?=</?[a-zA-Z]+[^\\s/>]*(\\s|$|/?>))", - "patterns": [ - { - "include": "text.html.derivative" - } - ], - "while": "^(?!\\s*$)" - }, - { - "begin": "(^|\\G)\\s*(?=(<[a-zA-Z0-9\\-](/?>|\\s.*?>)|</[a-zA-Z0-9\\-]>)\\s*$)", - "patterns": [ - { - "include": "text.html.derivative" - } - ], - "while": "^(?!\\s*$)" - } - ] - }, - "image-inline": { - "captures": { - "1": { - "name": "punctuation.definition.link.description.begin.markdown" - }, - "2": { - "name": "string.other.link.description.markdown" - }, - "4": { - "name": "punctuation.definition.link.description.end.markdown" - }, - "5": { - "name": "punctuation.definition.metadata.markdown" - }, - "7": { - "name": "punctuation.definition.link.markdown" - }, - "8": { - "name": "markup.underline.link.image.markdown" - }, - "9": { - "name": "punctuation.definition.link.markdown" - }, - "10": { - "name": "markup.underline.link.image.markdown" - }, - "12": { - "name": "string.other.link.description.title.markdown" - }, - "13": { - "name": "punctuation.definition.string.begin.markdown" - }, - "14": { - "name": "punctuation.definition.string.end.markdown" - }, - "15": { - "name": "string.other.link.description.title.markdown" - }, - "16": { - "name": "punctuation.definition.string.begin.markdown" - }, - "17": { - "name": "punctuation.definition.string.end.markdown" - }, - "18": { - "name": "string.other.link.description.title.markdown" - }, - "19": { - "name": "punctuation.definition.string.begin.markdown" - }, - "20": { - "name": "punctuation.definition.string.end.markdown" - }, - "21": { - "name": "punctuation.definition.metadata.markdown" - } - }, - "match": "(!\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])(\\()[ \\t]*((<)((?:\\\\[<>]|[^<>\\n])*)(>)|((?<url>(?>[^\\s()]+)|\\(\\g<url>*\\))*))[ \\t]*(?:((\\().+?(\\)))|((\").+?(\"))|((').+?(')))?\\s*(\\))", - "name": "meta.image.inline.markdown" - }, - "image-ref": { - "captures": { - "1": { - "name": "punctuation.definition.link.description.begin.markdown" - }, - "2": { - "name": "string.other.link.description.markdown" - }, - "4": { - "name": "punctuation.definition.link.description.end.markdown" - }, - "5": { - "name": "punctuation.definition.constant.markdown" - }, - "6": { - "name": "constant.other.reference.link.markdown" - }, - "7": { - "name": "punctuation.definition.constant.markdown" - } - }, - "match": "(!\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])[ ]?(\\[)(.*?)(\\])", - "name": "meta.image.reference.markdown" - }, - "inline": { - "patterns": [ - { - "include": "#tag" - }, - { - "include": "#attribute" - }, - { - "include": "#ampersand" - }, - { - "include": "#bracket" - }, - { - "include": "#bold" - }, - { - "include": "#italic" - }, - { - "include": "#raw" - }, - { - "include": "#strikethrough" - }, - { - "include": "#escape" - }, - { - "include": "#image-inline" - }, - { - "include": "#image-ref" - }, - { - "include": "#link-email" - }, - { - "include": "#link-inet" - }, - { - "include": "#link-inline" - }, - { - "include": "#link-ref" - }, - { - "include": "#link-ref-literal" - }, - { - "include": "#link-ref-shortcut" - } - ] - }, - "italic": { - "begin": "(?<open>(\\*(?=\\w)|(?<!\\w)\\*|(?<!\\w)\\b_))(?=\\S)(?=(<[^>]*+>|(?<raw>`+)([^`]|(?!(?<!`)\\k<raw>(?!`))`)*+\\k<raw>|\\\\[\\\\`*_{}\\[\\]()#.!+\\->]?+|\\[((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+\\](([ ]?\\[[^\\]]*+\\])|(\\([ \\t]*+<?(.*?)>?[ \\t]*+((?<title>['\"])(.*?)\\k<title>)?\\))))|\\k<open>\\k<open>|(?!(?<=\\S)\\k<open>).)++(?<=\\S)(?=_\\b|\\*)\\k<open>)", - "captures": { - "1": { - "name": "punctuation.definition.italic.markdown" - } - }, - "end": "(?<=\\S)(\\1)((?!\\1)|(?=\\1\\1))", - "name": "markup.italic.markdown", - "patterns": [ - { - "applyEndPatternLast": true, - "begin": "(?=<[^>]*?>)", - "end": "(?<=>)", - "patterns": [ - { - "include": "text.html.derivative" - } - ] - }, - { - "include": "#escape" - }, - { - "include": "#ampersand" - }, - { - "include": "#bracket" - }, - { - "include": "#raw" - }, - { - "include": "#bold" - }, - { - "include": "#image-inline" - }, - { - "include": "#link-inline" - }, - { - "include": "#link-inet" - }, - { - "include": "#link-email" - }, - { - "include": "#image-ref" - }, - { - "include": "#link-ref-literal" - }, - { - "include": "#link-ref" - }, - { - "include": "#link-ref-shortcut" - }, - { - "include": "#strikethrough" - } - ] - }, - "link-def": { - "captures": { - "1": { - "name": "punctuation.definition.constant.markdown" - }, - "2": { - "name": "constant.other.reference.link.markdown" - }, - "3": { - "name": "punctuation.definition.constant.markdown" - }, - "4": { - "name": "punctuation.separator.key-value.markdown" - }, - "5": { - "name": "punctuation.definition.link.markdown" - }, - "6": { - "name": "markup.underline.link.markdown" - }, - "7": { - "name": "punctuation.definition.link.markdown" - }, - "8": { - "name": "markup.underline.link.markdown" - }, - "9": { - "name": "string.other.link.description.title.markdown" - }, - "10": { - "name": "punctuation.definition.string.begin.markdown" - }, - "11": { - "name": "punctuation.definition.string.end.markdown" - }, - "12": { - "name": "string.other.link.description.title.markdown" - }, - "13": { - "name": "punctuation.definition.string.begin.markdown" - }, - "14": { - "name": "punctuation.definition.string.end.markdown" - }, - "15": { - "name": "string.other.link.description.title.markdown" - }, - "16": { - "name": "punctuation.definition.string.begin.markdown" - }, - "17": { - "name": "punctuation.definition.string.end.markdown" - } - }, - "match": "\\s*(\\[)([^]]+?)(\\])(:)[ \\t]*(?:(<)((?:\\\\[<>]|[^<>\\n])*)(>)|(\\S+?))[ \\t]*(?:((\\().+?(\\)))|((\").+?(\"))|((').+?(')))?\\s*$", - "name": "meta.link.reference.def.markdown" - }, - "link-email": { - "captures": { - "1": { - "name": "punctuation.definition.link.markdown" - }, - "2": { - "name": "markup.underline.link.markdown" - }, - "4": { - "name": "punctuation.definition.link.markdown" - } - }, - "match": "(<)((?:mailto:)?[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)(>)", - "name": "meta.link.email.lt-gt.markdown" - }, - "link-inet": { - "captures": { - "1": { - "name": "punctuation.definition.link.markdown" - }, - "2": { - "name": "markup.underline.link.markdown" - }, - "3": { - "name": "punctuation.definition.link.markdown" - } - }, - "match": "(<)((?:https?|ftp)://.*?)(>)", - "name": "meta.link.inet.markdown" - }, - "link-inline": { - "captures": { - "1": { - "name": "punctuation.definition.link.title.begin.markdown" - }, - "2": { - "name": "string.other.link.title.markdown", - "patterns": [ - { - "include": "#raw" - }, - { - "include": "#bold" - }, - { - "include": "#italic" - }, - { - "include": "#strikethrough" - }, - { - "include": "#image-inline" - } - ] - }, - "4": { - "name": "punctuation.definition.link.title.end.markdown" - }, - "5": { - "name": "punctuation.definition.metadata.markdown" - }, - "7": { - "name": "punctuation.definition.link.markdown" - }, - "8": { - "name": "markup.underline.link.markdown" - }, - "9": { - "name": "punctuation.definition.link.markdown" - }, - "10": { - "name": "markup.underline.link.markdown" - }, - "12": { - "name": "string.other.link.description.title.markdown" - }, - "13": { - "name": "punctuation.definition.string.begin.markdown" - }, - "14": { - "name": "punctuation.definition.string.end.markdown" - }, - "15": { - "name": "string.other.link.description.title.markdown" - }, - "16": { - "name": "punctuation.definition.string.begin.markdown" - }, - "17": { - "name": "punctuation.definition.string.end.markdown" - }, - "18": { - "name": "string.other.link.description.title.markdown" - }, - "19": { - "name": "punctuation.definition.string.begin.markdown" - }, - "20": { - "name": "punctuation.definition.string.end.markdown" - }, - "21": { - "name": "punctuation.definition.metadata.markdown" - } - }, - "match": "(\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])(\\()[ \\t]*((<)((?:\\\\[<>]|[^<>\\n])*)(>)|((?<url>(?>[^\\s()]+)|\\(\\g<url>*\\))*))[ \\t]*(?:((\\()[^()]*(\\)))|((\")[^\"]*(\"))|((')[^']*(')))?\\s*(\\))", - "name": "meta.link.inline.markdown" - }, - "link-ref": { - "captures": { - "1": { - "name": "punctuation.definition.link.title.begin.markdown" - }, - "2": { - "name": "string.other.link.title.markdown", - "patterns": [ - { - "include": "#raw" - }, - { - "include": "#bold" - }, - { - "include": "#italic" - }, - { - "include": "#strikethrough" - }, - { - "include": "#image-inline" - } - ] - }, - "4": { - "name": "punctuation.definition.link.title.end.markdown" - }, - "5": { - "name": "punctuation.definition.constant.begin.markdown" - }, - "6": { - "name": "constant.other.reference.link.markdown" - }, - "7": { - "name": "punctuation.definition.constant.end.markdown" - } - }, - "match": "(?<![\\]\\\\])(\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])(\\[)([^\\]]*+)(\\])", - "name": "meta.link.reference.markdown" - }, - "link-ref-literal": { - "captures": { - "1": { - "name": "punctuation.definition.link.title.begin.markdown" - }, - "2": { - "name": "string.other.link.title.markdown" - }, - "4": { - "name": "punctuation.definition.link.title.end.markdown" - }, - "5": { - "name": "punctuation.definition.constant.begin.markdown" - }, - "6": { - "name": "punctuation.definition.constant.end.markdown" - } - }, - "match": "(?<![\\]\\\\])(\\[)((?<square>[^\\[\\]\\\\]|\\\\.|\\[\\g<square>*+\\])*+)(\\])[ ]?(\\[)(\\])", - "name": "meta.link.reference.literal.markdown" - }, - "link-ref-shortcut": { - "captures": { - "1": { - "name": "punctuation.definition.link.title.begin.markdown" - }, - "2": { - "name": "string.other.link.title.markdown" - }, - "3": { - "name": "punctuation.definition.link.title.end.markdown" - } - }, - "match": "(?<![\\]\\\\])(\\[)((?:[^\\s\\[\\]\\\\]|\\\\[\\[\\]])+?)((?<!\\\\)\\])", - "name": "meta.link.reference.markdown" - }, - "list_paragraph": { - "begin": "(^|\\G)(?=\\S)(?![*+->]\\s|\\d+\\.\\s)", - "name": "meta.paragraph.markdown", - "patterns": [ - { - "include": "#inline" - }, - { - "include": "text.html.derivative" - }, - { - "include": "#heading-setext" - } - ], - "while": "(^|\\G)(?!\\s*$|#|[ ]{0,3}([-*_>][ ]{2,}){3,}[ \\t]*$\\n?|[ ]{0,3}[*+->]|[ ]{0,3}\\d+\\.)" - }, - "lists": { - "patterns": [ - { - "begin": "(^|\\G)([ ]{0,3})([*+-])([ \\t])", - "beginCaptures": { - "3": { - "name": "punctuation.definition.list.begin.markdown" - } - }, - "comment": "Currently does not support un-indented second lines.", - "name": "markup.list.unnumbered.markdown", - "patterns": [ - { - "include": "#block" - }, - { - "include": "#list_paragraph" - } - ], - "while": "((^|\\G)([ ]{2,4}|\\t))|(^[ \\t]*$)" - }, - { - "begin": "(^|\\G)([ ]{0,3})(\\d+[\\.)])([ \\t])", - "beginCaptures": { - "3": { - "name": "punctuation.definition.list.begin.markdown" - } - }, - "name": "markup.list.numbered.markdown", - "patterns": [ - { - "include": "#block" - }, - { - "include": "#list_paragraph" - } - ], - "while": "((^|\\G)([ ]{2,4}|\\t))|(^[ \\t]*$)" - } - ] - }, - "paragraph": { - "begin": "(^|\\G)[ ]{0,3}(?=[^ \\t\\n])", - "name": "meta.paragraph.markdown", - "patterns": [ - { - "include": "#inline" - }, - { - "include": "text.html.derivative" - }, - { - "include": "#heading-setext" - } - ], - "while": "(^|\\G)((?=\\s*[-=]{3,}\\s*$)|[ ]{4,}(?=[^ \\t\\n]))" - }, - "raw": { - "captures": { - "1": { - "name": "punctuation.definition.raw.markdown" - }, - "3": { - "name": "punctuation.definition.raw.markdown" - } - }, - "match": "(`+)((?:[^`]|(?!(?<!`)\\1(?!`))`)*+)(\\1)", - "name": "markup.inline.raw.string.markdown" - }, - "raw_block": { - "begin": "(^|\\G)([ ]{4}|\\t)", - "name": "markup.raw.block.markdown", - "while": "(^|\\G)([ ]{4}|\\t)" - }, - "separator": { - "match": "(^|\\G)[ ]{0,3}([\\*\\-_])([ ]{0,2}\\2){2,}[ \\t]*$\\n?", - "name": "meta.separator.markdown" - }, - "strikethrough": { - "captures": { - "1": { - "name": "punctuation.definition.strikethrough.markdown" - }, - "2": { - "patterns": [ - { - "applyEndPatternLast": true, - "begin": "(?=<[^>]*?>)", - "end": "(?<=>)", - "patterns": [ - { - "include": "text.html.derivative" - } - ] - }, - { - "include": "#escape" - }, - { - "include": "#ampersand" - }, - { - "include": "#bracket" - }, - { - "include": "#raw" - }, - { - "include": "#bold" - }, - { - "include": "#italic" - }, - { - "include": "#image-inline" - }, - { - "include": "#link-inline" - }, - { - "include": "#link-inet" - }, - { - "include": "#link-email" - }, - { - "include": "#image-ref" - }, - { - "include": "#link-ref-literal" - }, - { - "include": "#link-ref" - }, - { - "include": "#link-ref-shortcut" - } - ] - }, - "3": { - "name": "punctuation.definition.strikethrough.markdown" - } - }, - "match": "(?<!\\\\)(~{2,})((?:[^~]|(?!(?<![~\\\\])\\1(?!~))~)*+)(\\1)", - "name": "markup.strikethrough.markdown" - }, - "table": { - "begin": "(^|\\G)(\\|)(?=[^|].+\\|\\s*$)", - "beginCaptures": { - "2": { - "name": "punctuation.definition.table.markdown" - } - }, - "name": "markup.table.markdown", - "patterns": [ - { - "match": "\\|", - "name": "punctuation.definition.table.markdown" - }, - { - "captures": { - "1": { - "name": "punctuation.separator.table.markdown" - } - }, - "match": "(?<=\\|)\\s*(:?-+:?)\\s*(?=\\|)" - }, - { - "captures": { - "1": { - "patterns": [ - { - "include": "#inline" - } - ] - } - }, - "match": "(?<=\\|)\\s*(?=\\S)((\\\\\\||[^|])+)(?<=\\S)\\s*(?=\\|)" - } - ], - "while": "(^|\\G)(?=\\|)" - }, - "shortcut": { - "match": "(\\$|\\.|#)([-_:a-zA-Z0-9]+)", - "name": "string.other.markdoc-shortcut" - }, - "attribute": { - "match": "([-_a-zA-Z0-9]+)(=)", - "captures": { - "1": { - "name": "entity.other.attribute-name" - }, - "2": { - "name": "punctuation.definition.tag.equal.markdoc" - } - } - }, - "tag": { - "name": "punctuation.definition.tag", - "begin": "({%)\\s*/?([-_a-zA-Z0-9]+)?", - "end": "\\s*/?\\s*%}", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.markdoc" - }, - "2": { - "name": "entity.name.tag" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.end.markdoc" - } - }, - "patterns": [ - { - "include": "#attribute" - }, - { - "include": "#shortcut" - }, - { - "include": "source.json" - } - ] - } - }, - "scopeName": "text.html.markdoc" -} diff --git a/website/package-lock.json b/website/package-lock.json index 2006b7533..54b7ed573 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -1,22 +1,17 @@ { - "name": "starlight-docs", + "name": "actionbase-website", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "starlight-docs", + "name": "actionbase-website", "version": "0.0.1", "dependencies": { - "@astro-community/astro-embed-youtube": "^0.5.6", "@astrojs/starlight": "^0.36.3", - "@lorenzo_lewis/starlight-utils": "^0.3.2", "@lucide/astro": "^0.562.0", - "@types/culori": "^2.1.1", "astro": "^5.6.1", "astro-mermaid": "^1.1.0", - "culori": "^4.0.1", - "js-yaml": "^4.1.0", "mermaid": "^11.12.2", "remark-custom-heading-id": "^2.0.0", "sharp": "^0.34.2", @@ -25,7 +20,6 @@ "devDependencies": { "@eslint/js": "^9.17.0", "@playwright/test": "^1.45.0", - "@types/js-yaml": "^4.0.9", "axe-playwright": "^2.0.3", "eslint": "^9.17.0", "globals": "^15.14.0", @@ -48,18 +42,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@astro-community/astro-embed-youtube": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/@astro-community/astro-embed-youtube/-/astro-embed-youtube-0.5.9.tgz", - "integrity": "sha512-8Uk2SKbyZVb+jxwqSAMoEpQo+063XYwCI3yRy9cbkyHpu09mDabGZNTF5XrL8CKr3NtR5haBkeYK/kSuKUkJ/g==", - "license": "MIT", - "dependencies": { - "lite-youtube-embed": "^0.3.4" - }, - "peerDependencies": { - "astro": "^2.0.0 || ^3.0.0-beta || ^4.0.0-beta || ^5.0.0-beta" - } - }, "node_modules/@astrojs/compiler": { "version": "2.13.0", "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.0.tgz", @@ -1287,19 +1269,6 @@ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, - "node_modules/@lorenzo_lewis/starlight-utils": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@lorenzo_lewis/starlight-utils/-/starlight-utils-0.3.2.tgz", - "integrity": "sha512-9GCZLyfIUTkXuE39jHjcCSwnOzm6hSGnC8DrHlo2imegiZmZSdG0eBMA/sTb/shLkvCzE2SGCaKM+EwIeO6oDw==", - "license": "MIT", - "dependencies": { - "astro-integration-kit": "^0.18.0" - }, - "peerDependencies": { - "@astrojs/starlight": ">=0.32.0", - "astro": ">=5" - } - }, "node_modules/@lucide/astro": { "version": "0.562.0", "resolved": "https://registry.npmjs.org/@lucide/astro/-/astro-0.562.0.tgz", @@ -1896,12 +1865,6 @@ "@types/responselike": "^1.0.0" } }, - "node_modules/@types/culori": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@types/culori/-/culori-2.1.1.tgz", - "integrity": "sha512-NzLYD0vNHLxTdPp8+RlvGbR2NfOZkwxcYGFwxNtm+WH2NuUNV8785zv1h0sulFQ5aFQ9n/jNDUuJeo3Bh7+oFA==", - "license": "MIT" - }, "node_modules/@types/d3": { "version": "7.4.3", "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", @@ -2757,18 +2720,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/ast-types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", - "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/astring": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", @@ -2876,25 +2827,6 @@ "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0" } }, - "node_modules/astro-integration-kit": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/astro-integration-kit/-/astro-integration-kit-0.18.0.tgz", - "integrity": "sha512-Z0QW5IQjosuKQDEGYYkvUX6EhEtrmE4/oViqWz23QveV8U7AuyFsTdg00WRNPevWZl/5a4lLUeDpv4bCRynRRg==", - "license": "MIT", - "dependencies": { - "pathe": "^1.1.2", - "recast": "^0.23.7" - }, - "peerDependencies": { - "astro": "^4.12.0 || ^5.0.0" - } - }, - "node_modules/astro-integration-kit/node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "license": "MIT" - }, "node_modules/astro-mermaid": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/astro-mermaid/-/astro-mermaid-1.1.0.tgz", @@ -3529,15 +3461,6 @@ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", "license": "CC0-1.0" }, - "node_modules/culori": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/culori/-/culori-4.0.2.tgz", - "integrity": "sha512-1+BhOB8ahCn4O0cep0Sh2l9KCOfOdY+BXJnKMHFFzDEouSr/el18QwXEMRlOj9UY5nCeA8UN3a/82rUWRBeyBw==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/cytoscape": { "version": "3.33.1", "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", @@ -4594,19 +4517,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/esquery": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", @@ -5928,12 +5838,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lite-youtube-embed": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/lite-youtube-embed/-/lite-youtube-embed-0.3.4.tgz", - "integrity": "sha512-aXgxpwK7AIW58GEbRzA8EYaY4LWvF3FKak6B9OtSJmuNyLhX2ouD4cMTxz/yR5HFInhknaYd2jLWOTRTvT8oAw==", - "license": "Apache-2.0" - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -7909,31 +7813,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/recast": { - "version": "0.23.11", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", - "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", - "license": "MIT", - "dependencies": { - "ast-types": "^0.16.1", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tiny-invariant": "^1.3.3", - "tslib": "^2.0.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/recast/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/recma-build-jsx": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", @@ -9098,12 +8977,6 @@ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", "license": "MIT" }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", - "license": "MIT" - }, "node_modules/tinyexec": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", diff --git a/website/package.json b/website/package.json index d14786b32..0a5461801 100644 --- a/website/package.json +++ b/website/package.json @@ -1,5 +1,5 @@ { - "name": "starlight-docs", + "name": "actionbase-website", "private": true, "type": "module", "version": "0.0.1", @@ -10,24 +10,18 @@ "build": "astro build", "preview": "astro preview", "typecheck": "tsc --noEmit", - "linkcheck": "CHECK_LINKS=true pnpm build", + "linkcheck": "npm run build", "astro": "astro", - "grammars": "node grammars/generate.mjs", "format": "prettier --write .", "format:check": "prettier --check .", "lint": "eslint .", "lint:fix": "eslint --fix ." }, "dependencies": { - "@astro-community/astro-embed-youtube": "^0.5.6", "@astrojs/starlight": "^0.36.3", - "@lorenzo_lewis/starlight-utils": "^0.3.2", "@lucide/astro": "^0.562.0", - "@types/culori": "^2.1.1", "astro": "^5.6.1", - "js-yaml": "^4.1.0", "astro-mermaid": "^1.1.0", - "culori": "^4.0.1", "mermaid": "^11.12.2", "remark-custom-heading-id": "^2.0.0", "sharp": "^0.34.2", @@ -39,7 +33,6 @@ "axe-playwright": "^2.0.3", "eslint": "^9.17.0", "globals": "^15.14.0", - "@types/js-yaml": "^4.0.9", "prettier": "^3.4.2", "sitemapper": "^3.2.12", "starlight-links-validator": "^0.14.0", diff --git a/website/playwright.config.ts b/website/playwright.config.ts index 882efd3d5..933ce0810 100644 --- a/website/playwright.config.ts +++ b/website/playwright.config.ts @@ -16,7 +16,7 @@ export default defineConfig({ timeout: 180 * 1_000, webServer: [ { - command: 'pnpm run build && pnpm run preview', + command: 'npm run build && npm run preview', reuseExistingServer: !process.env['CI'], stdout: 'pipe', // The timeout of the single build step ran before the accessibility tests. diff --git a/website/public/_headers b/website/public/_headers index b96951c80..dd70badcb 100644 --- a/website/public/_headers +++ b/website/public/_headers @@ -1,4 +1,4 @@ +# GitHub Pages ignores this file (Netlify/Cloudflare convention); kept correct +# in case the site ever moves to a host that honors it. /_astro/* - Cache-Control: public - Cache-Control: max-age=0 - Cache-Control: immutable + Cache-Control: public, max-age=31536000, immutable diff --git a/website/public/_redirects b/website/public/_redirects deleted file mode 100644 index 1e26cc686..000000000 --- a/website/public/_redirects +++ /dev/null @@ -1,15 +0,0 @@ -# Proxy to Phat Houston from our Product Hunt launch — site operated by Otterlord -/ph/* https://astro-houston-ph.pages.dev/ph/:splat 200 - -# Moved content -/zh/* /zh-cn/:splat -/showcase/ /resources/showcase/ -/:lang/showcase/ /:lang/resources/showcase/ - -# Component docs -/guides/components/ /components/using-components/ -/:lang/guides/components/ /:lang/components/using-components/ - -# Translated 404s -/:lang/* /:lang/404/ 404 -/* /404/ 404 diff --git a/website/public/hero.svg b/website/public/hero.svg deleted file mode 100644 index bf2ca0413..000000000 --- a/website/public/hero.svg +++ /dev/null @@ -1 +0,0 @@ -<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 800 801" xmlns="http://www.w3.org/2000/svg"><path d="m5304 6695c243-29 445-78 640-156 261-105 434-234 646-481 62-72 116-118 247-207 51-35 108-77 126-94 148-139 210-422 142-652-41-138-66-176-215-325-75-74-160-166-190-203-110-138-212-191-516-271-249-65-349-100-467-164-249-135-431-309-579-555-67-111-92-193-93-297 0-109 33-189 98-235 129-93 255-160 491-262 618-267 958-550 1162-968 52.337-107.376 232.316-487.868 40-710-26-30-26-30-18 15 2.633 16.459 7.838 161.674 3.375 240.25-1.125 19.809-14.243 35.242-16.375 37.75-1.917 2.092-26.445 28.849-28.779 20.73-1.35-4.693-6.221-21.633-6.221-60.73-1-130-61-319-112-347-24-14-32-13-82 2-4.766 1.537-55.503 17.904-55.855 28.263-.378 11.146 17.796 35.929 19.855 38.737 33 47 52 111 53 185 1.086 70.578-22.279 134.84-32 135-7.451.123-18.973-62.423-20-68-18.044-98.768-82.324-210.727-108.906-220.548-21.407-7.909-100.27 87.37-124.094 138.548-14 30-42 115-62 189-40 147-67 205-130 279-116 136-266 209-565 273-146 31-392 37-608 14-221-24-306-15-430 44-56.786 27.159-74.086 42.845-83 48l15 30c75 108 189 410 199 528 5 70 5 70-14 46-11-13-45-72-55-98-45-119-127-262-268-463-79.454-112.909-351.372-395.771-383.916-404.649-15.213-4.15-21.753 3.519-22.973 4.95-10.284 12.058-33.481 57.543-36.111 62.699-25 49-25 49 39 120 227 255 400 523 727 1122 262 479 367 633 569 836 223 223 457 363 755 454 62 18 172 45 246 60 255 50 260 53 398 188 27.416 26.713 96.549 135.985 91.28 170.282-5.836 37.986-40.403 88.31-61.28 95.718-60 21-117 14-172-23-233-154-493-199-759-132-231.045 59.726-215.294 112.096-197.998 118.551 20.558 7.673 109.772-22.437 118.998-25.551 69-23 147-41 211-49 303-35 638 96 731 287 17.399 34.797 27.5 118.498 24.318 168.52-.187 2.935 1.165 34.952-33.318 70.48-19 20-74 56-122 81-66 34-97 57-130 97-143 176-197 212-440 293-256 85-266 91-323 210-52 108-105 166-194 211-52 26-66 29-157 28-79 0-112-5-158-23-80-31-165-112-211-201-29-54-46-75-75-90-21-10-127-37-237-60-109-23-236-54-281-69-275-94-508-318-629-605-84-197-123-405-131-697-7-248 7-406 59-654 126-605 147-810 114-1131-20-204-21-420-1-544 31-191 120-402 244-580 194-279 384-466 529-520 31-12 119-33 195-46 219-39 336-91 424-189 24.433-26.76 89.071-130.876 92.685-152.234.813-4.805-7.134-9.135-51.685 32.234-69 60-139 93-207 97-72 4-75-13-9-47 107-55 152-98 207-196 39-71 39-92-1-123-43.037-31.879-112.564-55.358-114-56-2.973 27.2 2.123 141.202-142 239-41 28-141 53-182 45-41-9-38-21 9-29 57.212-9.393 183.87-117.098 213.165-213.089 10.936-35.836 12.206-50.097-25.181-51.036-303.371-7.619-634.741 99.622-758.984 154.125-455 201-948 620-1280 1085-128 180-186 276-273 455-20.547 42.358-16.529 44.046-223.453 544.4-3.783 9.148-6.145 7.558-10.547 16.6-1.734-34.853-2.871-34.749.991-69.368 2.194-19.671 19.299-173.023 37.009-244.632 57-222 179-510 275-647 16-23-2-13-69 39-917.434 711.172-1475.18 1332.438-1699 1640-62.483 85.436-226.566 348.174-226.147 373.617.027 1.616 4.901 10.765 12.046 15.463 21.234 13.96 148.034 52 161.101 55.92 374 112 628 227 877 399 351 242 595 498 956 1004 234 328 386 527 515 675 105 119 128 150 143 200 30 94 71 166 124 217 97 93 179 129 346 151 95 12 136 24 252 71 511 208 912 278 1328 229zm-1689-379c-113-28-202-102-257-213-44-89-51-211-18-314 25-76 82-163 144-216 28-26 46-33 77-33 34 0 41 4 50 28 17 44 4 96-52 206-43 87-52 112-52 158 0 83 45 149 125 182 54 23 102 20 208-14 90-28 178-38 214-24 12 4 16 20 16 54 0 45-3 51-42 85-115 99-270 136-413 101zm2990-516c-74-13-129-35-191-76-63-42-76-62-72-107 5-52 44-56 164-15 96 32 104 33 259 33 160 0 160 0 163 39 4 47-20 76-86 104-56 24-168 34-237 22zm326-383c-11-19-66-76-121-127-121-111-142-147-148-254-8-128 29-173 139-169 67 2 105 19 147 68 74 84 107 186 107 335 0 142-12 173-66 178-32 3-39-1-58-31zm-1663 576c77.267-36.6 165.787-185.732 64.4-315.832-100.705-129.224-314.39-78.607-351.675 84.969-35.37 155.17 130.848 302.124 287.275 230.863zm-89.666-46.334c-15-10.001-18.334-20.834-18.334-57.503 0-55.836 20.001-79.171 67.504-79.171 42.502 0 55.836 6.667 70.003 34.169 31.668 60.003.834 115.839-64.17 115.839-20.001 0-45.002-5.834-55.003-13.334z" transform="matrix(.117874 0 0 -.120845 -54.618425 825.014547)"/><g fill="#fff" fill-rule="nonzero"><path d="m4900 6823c-522.892-39.139-950.018-231.635-1077.77-279.56-65.118-24.427-124.542-31.172-142.23-33.44-162-19-285-71-383-160-64-59-107-129-145-237-32-89-38-97-157-229-106-118-213-256-434-564-345-479-492-653-721-854-193-169-333-266-545-377-210-110-404-184-624-239-110-28-150-48-178-88-37-56-39-110-8-173 83-162 276-442 421-609 314-361 643-679 1184-1144 14-12 120-95 235-186 256-200 618-505 780-656 145-135 277-245 416-346 282-205 598-348 928-419 136-29 377-37 491-15 159 30 258 103 296 220 21 61 14 211-11 271-56 133-153 231-305 306-88 43-136 57-298 84-87 14-160 32-185 45-67 35-169 122-256 220-80 89-202 246-200 258 0 4 21 24 47 46 77 63 142 127 232 227 46 52 85 96 87 98 1 2 35-12 75-32 155-75 299-91 573-62 267 28 506 12 686-46 251-80 397-223 445-434 31-138 54-202 92-260 69-106 189-207 291-246 46-17 72-20 146-17 77 4 99 9 154 37 129 66 211 191 233 355 43 321-176 793-515 1112-219 206-389 307-906 540-263 118-414 213-446 280-74 156 181 541 498 751 157 103 286 155 575 228 269 69 377 126 517 272 55 58 156 162 225 232 133 134 182 209 230 351 28 81 39 301 21 406-40 238-127 362-372 529-81 56-129 100-235 216-136 149-229 228-364 312-210 129-512 238-786 282-166 27-432 39-584 28zm404-128c243-29 445-78 640-156 261-105 434-234 646-481 62-72 116-118 247-207 51-35 108-77 126-94 148-139 210-422 142-652-41-138-66-176-215-325-75-74-160-166-190-203-110-138-212-191-516-271-249-65-349-100-467-164-249-135-431-309-579-555-67-111-92-193-93-297 0-109 33-189 98-235 129-93 255-160 491-262 618-267 958-550 1162-968 52.337-107.376 232.316-487.868 40-710-26-30-26-30-18 15 2.633 16.459 7.838 161.674 3.375 240.25-1.125 19.809-14.243 35.242-16.375 37.75-1.917 2.092-26.445 28.849-28.779 20.73-1.35-4.693-6.221-21.633-6.221-60.73-1-130-61-319-112-347-24-14-32-13-82 2-4.766 1.537-55.503 17.904-55.855 28.263-.378 11.146 17.796 35.929 19.855 38.737 33 47 52 111 53 185 1.086 70.578-22.279 134.84-32 135-7.451.123-18.973-62.423-20-68-18.044-98.768-82.324-210.727-108.906-220.548-21.407-7.909-100.27 87.37-124.094 138.548-14 30-42 115-62 189-40 147-67 205-130 279-116 136-266 209-565 273-146 31-392 37-608 14-221-24-306-15-430 44-56.786 27.159-74.086 42.845-83 48l15 30c75 108 189 410 199 528 5 70 5 70-14 46-11-13-45-72-55-98-45-119-127-262-268-463-79.454-112.909-351.372-395.771-383.916-404.649-15.213-4.15-21.753 3.519-22.973 4.95-10.284 12.058-33.481 57.543-36.111 62.699-25 49-25 49 39 120 227 255 400 523 727 1122 262 479 367 633 569 836 223 223 457 363 755 454 62 18 172 45 246 60 255 50 260 53 398 188 27.416 26.713 96.549 135.985 91.28 170.282-5.836 37.986-40.403 88.31-61.28 95.718-60 21-117 14-172-23-233-154-493-199-759-132-231.045 59.726-215.294 112.096-197.998 118.551 20.558 7.673 109.772-22.437 118.998-25.551 69-23 147-41 211-49 303-35 638 96 731 287 17.399 34.797 27.5 118.498 24.318 168.52-.187 2.935 1.165 34.952-33.318 70.48-19 20-74 56-122 81-66 34-97 57-130 97-143 176-197 212-440 293-256 85-266 91-323 210-52 108-105 166-194 211-52 26-66 29-157 28-79 0-112-5-158-23-80-31-165-112-211-201-29-54-46-75-75-90-21-10-127-37-237-60-109-23-236-54-281-69-275-94-508-318-629-605-84-197-123-405-131-697-7-248 7-406 59-654 126-605 147-810 114-1131-20-204-21-420-1-544 31-191 120-402 244-580 194-279 384-466 529-520 31-12 119-33 195-46 219-39 336-91 424-189 24.433-26.76 89.071-130.876 92.685-152.234.813-4.805-7.134-9.135-51.685 32.234-69 60-139 93-207 97-72 4-75-13-9-47 107-55 152-98 207-196 39-71 39-92-1-123-43.037-31.879-112.564-55.358-114-56-2.973 27.2 2.123 141.202-142 239-41 28-141 53-182 45-41-9-38-21 9-29 57.212-9.393 183.87-117.098 213.165-213.089 10.936-35.836 12.206-50.097-25.181-51.036-303.371-7.619-634.741 99.622-758.984 154.125-455 201-948 620-1280 1085-128 180-186 276-273 455-20.547 42.358-16.529 44.046-223.453 544.4-3.783 9.148-6.145 7.558-10.547 16.6-1.734-34.853-2.871-34.749.991-69.368 2.194-19.671 19.299-173.023 37.009-244.632 57-222 179-510 275-647 16-23-2-13-69 39-917.434 711.172-1475.18 1332.438-1699 1640-62.483 85.436-226.566 348.174-226.147 373.617.027 1.616 4.901 10.765 12.046 15.463 21.234 13.96 148.034 52 161.101 55.92 374 112 628 227 877 399 351 242 595 498 956 1004 234 328 386 527 515 675 105 119 128 150 143 200 30 94 71 166 124 217 97 93 179 129 346 151 95 12 136 24 252 71 511 208 912 278 1328 229zm-36-702c77.267-36.6 165.787-185.732 64.4-315.832-100.705-129.224-314.39-78.607-351.675 84.969-35.37 155.17 130.848 302.124 287.275 230.863z" transform="matrix(.1178742 0 0 -.1208447 -54.618425 825.014297)"/><path d="m3615 6316c-113-28-202-102-257-213-44-89-51-211-18-314 25-76 82-163 144-216 28-26 46-33 77-33 34 0 41 4 50 28 17 44 4 96-52 206-43 87-52 112-52 158 0 83 45 149 125 182 54 23 102 20 208-14 90-28 178-38 214-24 12 4 16 20 16 54 0 45-3 51-42 85-115 99-270 136-413 101z" transform="matrix(.1178742 0 0 -.1208447 -54.618425 825.014297)"/><path d="m6605 5800c-74-13-129-35-191-76-63-42-76-62-72-107 5-52 44-56 164-15 96 32 104 33 259 33 160 0 160 0 163 39 4 47-20 76-86 104-56 24-168 34-237 22z" transform="matrix(.1178742 0 0 -.1208447 -54.618425 825.014297)"/><path d="m6931 5417c-11-19-66-76-121-127-121-111-142-147-148-254-8-128 29-173 139-169 67 2 105 19 147 68 74 84 107 186 107 335 0 142-12 173-66 178-32 3-39-1-58-31z" transform="matrix(.1178742 0 0 -.1208447 -54.618425 825.014297)"/><path d="m5172 5964c-18-12-22-25-22-69 0-67 24-95 81-95 51 0 67 8 84 41 38 72 1 139-77 139-24 0-54-7-66-16z" transform="matrix(.0982340008 0 0 -.10070955609 47.70941395029 707.0205651624)"/></g></svg> \ No newline at end of file diff --git a/website/public/robots.txt b/website/public/robots.txt new file mode 100644 index 000000000..71bd7b851 --- /dev/null +++ b/website/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://actionbase.io/sitemap-index.xml diff --git a/website/public/images/guides/social-media/00-screen-layout.png b/website/src/assets/guides/social-media/00-screen-layout.png similarity index 100% rename from website/public/images/guides/social-media/00-screen-layout.png rename to website/src/assets/guides/social-media/00-screen-layout.png diff --git a/website/public/images/guides/social-media/01-welcome.png b/website/src/assets/guides/social-media/01-welcome.png similarity index 100% rename from website/public/images/guides/social-media/01-welcome.png rename to website/src/assets/guides/social-media/01-welcome.png diff --git a/website/public/images/guides/social-media/02-zipdoki-intro.png b/website/src/assets/guides/social-media/02-zipdoki-intro.png similarity index 100% rename from website/public/images/guides/social-media/02-zipdoki-intro.png rename to website/src/assets/guides/social-media/02-zipdoki-intro.png diff --git a/website/public/images/guides/social-media/03-set-up.png b/website/src/assets/guides/social-media/03-set-up.png similarity index 100% rename from website/public/images/guides/social-media/03-set-up.png rename to website/src/assets/guides/social-media/03-set-up.png diff --git a/website/public/images/guides/social-media/04-load-sample-data.png b/website/src/assets/guides/social-media/04-load-sample-data.png similarity index 100% rename from website/public/images/guides/social-media/04-load-sample-data.png rename to website/src/assets/guides/social-media/04-load-sample-data.png diff --git a/website/public/images/guides/social-media/05-select-database.png b/website/src/assets/guides/social-media/05-select-database.png similarity index 100% rename from website/public/images/guides/social-media/05-select-database.png rename to website/src/assets/guides/social-media/05-select-database.png diff --git a/website/public/images/guides/social-media/06-explore-the-data.png b/website/src/assets/guides/social-media/06-explore-the-data.png similarity index 100% rename from website/public/images/guides/social-media/06-explore-the-data.png rename to website/src/assets/guides/social-media/06-explore-the-data.png diff --git a/website/public/images/guides/social-media/07-follows.png b/website/src/assets/guides/social-media/07-follows.png similarity index 100% rename from website/public/images/guides/social-media/07-follows.png rename to website/src/assets/guides/social-media/07-follows.png diff --git a/website/public/images/guides/social-media/08-create-follows-table.png b/website/src/assets/guides/social-media/08-create-follows-table.png similarity index 100% rename from website/public/images/guides/social-media/08-create-follows-table.png rename to website/src/assets/guides/social-media/08-create-follows-table.png diff --git a/website/public/images/guides/social-media/09-follow-a-user.png b/website/src/assets/guides/social-media/09-follow-a-user.png similarity index 100% rename from website/public/images/guides/social-media/09-follow-a-user.png rename to website/src/assets/guides/social-media/09-follow-a-user.png diff --git a/website/public/images/guides/social-media/10-check-follow-status.png b/website/src/assets/guides/social-media/10-check-follow-status.png similarity index 100% rename from website/public/images/guides/social-media/10-check-follow-status.png rename to website/src/assets/guides/social-media/10-check-follow-status.png diff --git a/website/public/images/guides/social-media/11-count-followers.png b/website/src/assets/guides/social-media/11-count-followers.png similarity index 100% rename from website/public/images/guides/social-media/11-count-followers.png rename to website/src/assets/guides/social-media/11-count-followers.png diff --git a/website/public/images/guides/social-media/12-list-followers.png b/website/src/assets/guides/social-media/12-list-followers.png similarity index 100% rename from website/public/images/guides/social-media/12-list-followers.png rename to website/src/assets/guides/social-media/12-list-followers.png diff --git a/website/public/images/guides/social-media/13-likes.png b/website/src/assets/guides/social-media/13-likes.png similarity index 100% rename from website/public/images/guides/social-media/13-likes.png rename to website/src/assets/guides/social-media/13-likes.png diff --git a/website/public/images/guides/social-media/14-like-a-post.png b/website/src/assets/guides/social-media/14-like-a-post.png similarity index 100% rename from website/public/images/guides/social-media/14-like-a-post.png rename to website/src/assets/guides/social-media/14-like-a-post.png diff --git a/website/public/images/guides/social-media/15-check-like-status.png b/website/src/assets/guides/social-media/15-check-like-status.png similarity index 100% rename from website/public/images/guides/social-media/15-check-like-status.png rename to website/src/assets/guides/social-media/15-check-like-status.png diff --git a/website/public/images/guides/social-media/16-and-more.png b/website/src/assets/guides/social-media/16-and-more.png similarity index 100% rename from website/public/images/guides/social-media/16-and-more.png rename to website/src/assets/guides/social-media/16-and-more.png diff --git a/website/public/images/guides/social-media/17-feed.png b/website/src/assets/guides/social-media/17-feed.png similarity index 100% rename from website/public/images/guides/social-media/17-feed.png rename to website/src/assets/guides/social-media/17-feed.png diff --git a/website/public/images/guides/social-media/18-all-done.png b/website/src/assets/guides/social-media/18-all-done.png similarity index 100% rename from website/public/images/guides/social-media/18-all-done.png rename to website/src/assets/guides/social-media/18-all-done.png diff --git a/website/public/images/guides/social-media/19-try-it-yourself.png b/website/src/assets/guides/social-media/19-try-it-yourself.png similarity index 100% rename from website/public/images/guides/social-media/19-try-it-yourself.png rename to website/src/assets/guides/social-media/19-try-it-yourself.png diff --git a/website/src/assets/hero.webp b/website/src/assets/hero.webp deleted file mode 100644 index aa6b05d39..000000000 Binary files a/website/src/assets/hero.webp and /dev/null differ diff --git a/website/src/assets/landing-page.css b/website/src/assets/landing-page.css new file mode 100644 index 000000000..bbab7d571 --- /dev/null +++ b/website/src/assets/landing-page.css @@ -0,0 +1,1367 @@ +/* Landing page styles (global) — imported by src/pages/index.astro. + The docs skin lives separately in landing.css. */ + +:root { + --accent: #5d5fef; + --accent-hover: #4749d0; + --accent-2: #a9aaf5; + --accent-fill: rgba(93, 95, 239, 0.12); + + --btn-text: #ffffff; + + /* terminal / code — identical in both themes */ + --term-bg: #1b1c2b; + --term-text: #e6e7f2; + --term-prompt: #a9aaf5; + --term-banner: #d9a94e; + --term-dot: #33354a; + --out-ok: #7fd1b0; + --out-dim: #9092ab; + --out-err: #e0a06a; + + --font-head: 'Cormorant', Georgia, serif; + --font-body: 'Manrope', system-ui, sans-serif; + --font-mono: 'JetBrains Mono', ui-monospace, monospace; + + --maxw: 1280px; + --gutter: 34px; +} + +:root[data-theme='light'] { + /* AA text-on-page-bg variants of the accent (the raw --accent fails + 4.5:1 as small text on both page backgrounds). */ + --accent-text: #4749d0; + --accent-text-hover: #3a3cb8; + --ink: #20223a; + --body: #4e5168; + --muted: #61657c; + --line-soft: rgba(32, 34, 58, 0.12); + --line-mid: rgba(32, 34, 58, 0.16); + --line-24: rgba(32, 34, 58, 0.24); + --line-strong: rgba(32, 34, 58, 0.28); + --surf-card: rgba(255, 255, 255, 0.85); + --surf-soft: rgba(255, 255, 255, 0.62); + --surf-panel: rgba(255, 255, 255, 0.5); + --surf-foot: rgba(230, 232, 240, 0.7); + --grid-line: rgba(32, 34, 58, 0.05); + --page-bg: linear-gradient(180deg, #f3f5f8 0%, #e9ecf1 100%); + --page-bg-solid: #f3f5f8; +} + +:root[data-theme='dark'] { + --accent-text: #a9aaf5; + --accent-text-hover: #c6c7fa; + --ink: #ecedf6; + --body: #b4b7cc; + --muted: #9da0b7; + --line-soft: rgba(255, 255, 255, 0.1); + --line-mid: rgba(255, 255, 255, 0.16); + --line-24: rgba(255, 255, 255, 0.22); + --line-strong: rgba(255, 255, 255, 0.26); + --surf-card: rgba(255, 255, 255, 0.05); + --surf-soft: rgba(255, 255, 255, 0.04); + --surf-panel: rgba(255, 255, 255, 0.03); + --surf-foot: rgba(0, 0, 0, 0.28); + --grid-line: rgba(255, 255, 255, 0.05); + --page-bg: linear-gradient(180deg, #141520 0%, #0e0f17 100%); + --page-bg-solid: #141520; +} + +* { + box-sizing: border-box; +} +html, +body { + margin: 0; + padding: 0; + /* Carry the page gradient up to the root so over-scroll (rubber-band) + never flashes the white canvas, and disable the bounce as well. */ + background: var(--page-bg); + background-attachment: fixed; + overscroll-behavior: none; +} +html { + background-color: var(--page-bg-solid); +} +body { + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} + +.page { + min-height: 100vh; + color: var(--ink); + font-family: var(--font-body); + background: var(--page-bg); +} + +a { + color: var(--accent-text); + text-decoration: none; +} +a:hover { + color: var(--accent-text-hover); +} +:focus-visible { + outline: 2px solid var(--accent-text); + outline-offset: 2px; +} + +.skip-link { + position: absolute; + top: -100px; + left: var(--gutter); + z-index: 10; + padding: 10px 16px; + background: var(--accent); + color: var(--btn-text); + font-size: 14px; + font-weight: 600; +} +.skip-link:focus { + top: 8px; + color: var(--btn-text); +} +::selection { + background: var(--accent); + color: #fff; +} + +.accent { + color: var(--accent); +} + +/* nav */ +.nav { + display: flex; + justify-content: space-between; + align-items: center; + padding: 22px var(--gutter); + max-width: var(--maxw); + margin: 0 auto; +} +.brand { + display: flex; + align-items: center; + color: var(--ink); +} +.brand-logo { + height: 26px; + width: auto; + display: block; +} +:root[data-theme='light'] .brand-logo-dark { + display: none; +} +:root[data-theme='dark'] .brand-logo-light { + display: none; +} +.nav-links { + display: flex; + align-items: center; + gap: 10px; + font-size: 14px; + font-weight: 600; + color: var(--body); +} +.nav-links a { + color: var(--body); +} +.nav-links a:hover { + color: var(--ink); +} +.nav-text-link { + display: inline-flex; + align-items: center; + min-height: 44px; + padding: 0 6px; +} +.gh-link { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + min-width: 44px; + height: 44px; + border-radius: 999px; + border: 1px solid var(--line-mid); + color: var(--body); +} +.gh-link.has-count { + padding: 0 15px; +} +.gh-count { + font-family: var(--font-mono); + font-size: 11.5px; + font-weight: 500; + letter-spacing: 0.04em; +} +.gh-link:hover { + border-color: var(--ink); + color: var(--ink); +} +.gh-icon { + display: block; + width: 18px; + height: 18px; +} +.theme-toggle { + display: flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + border-radius: 999px; + border: 1px solid var(--line-mid); + background: transparent; + color: var(--body); + cursor: pointer; + font-size: 14px; +} +.theme-toggle:hover { + border-color: var(--line-strong); +} +:root[data-theme='dark'] .theme-icon-moon, +:root[data-theme='light'] .theme-icon-sun { + display: none; +} + +/* hero */ +.hero { + max-width: var(--maxw); + margin: 0 auto; + padding: 48px var(--gutter) 40px; + display: grid; + grid-template-columns: minmax(420px, 1fr) minmax(380px, 520px); + gap: 56px; + align-items: center; +} +.hero-copy { + max-width: 1000px; +} +.hero-art { + margin: 0; +} +.hero-art svg { + width: 100%; + height: auto; + display: block; +} +@media (max-width: 1080px) { + .hero { + display: block; + } + .hero-art { + display: none; + } +} + +/* Shared drafting-style figure caption (hero art, graph, architecture). */ +.fig-cap { + display: flex; + align-items: center; + gap: 10px; + margin: 14px 0 0; + font-family: var(--font-mono); + font-size: 10px; + font-weight: 500; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--muted); +} +.fig-cap::before { + content: ''; + width: 34px; + height: 1px; + background: var(--line-strong); + flex: none; +} + +/* hero art */ +.ha-glow-in { + stop-color: var(--accent); + stop-opacity: 0.07; +} +.ha-glow-out { + stop-color: var(--accent); + stop-opacity: 0; +} +.ha-corners path, +.ha-marks path { + fill: none; + stroke: var(--ink); + stroke-width: 0.8; + opacity: 0.18; +} +.ha-edges path { + fill: none; + stroke: var(--ink); + stroke-width: 1; + opacity: 0.4; +} +.ha-edges path.faint { + stroke-dasharray: 2 4; + opacity: 0.25; +} +.ha-edges path.is-accent { + stroke: var(--accent-text); + stroke-width: 1.5; + opacity: 1; +} +.ha-arrow { + fill: var(--ink); + stroke: none; + opacity: 0.4; +} +.ha-arrow.is-accent-fill { + fill: var(--accent-text); + opacity: 1; +} +.ha-chip rect { + fill: none; + stroke: var(--accent-text); + stroke-width: 0.9; +} +.ha-chip text { + font-family: var(--font-mono); + font-size: 9.5px; + letter-spacing: 0.08em; + fill: var(--accent-text); +} +.ha-microlabel { + font-family: var(--font-mono); + font-size: 8px; + letter-spacing: 0.14em; + fill: var(--muted); +} +.ha-note circle { + fill: var(--ink); + opacity: 0.55; +} +.ha-note path { + fill: none; + stroke: var(--ink); + stroke-width: 0.7; + opacity: 0.3; +} +.ha-note text { + font-family: var(--font-mono); + font-size: 8.5px; + letter-spacing: 0.06em; + fill: var(--muted); +} +.ha-construction circle { + fill: none; + stroke: var(--accent-text); + stroke-width: 0.6; + stroke-dasharray: 3 4; + opacity: 0.45; +} +.ha-construction path { + fill: none; + stroke: var(--accent-text); + stroke-width: 0.7; + opacity: 0.45; +} +.ha-dot { + fill: var(--ink); + stroke: none; +} +.ha-dot.is-accent { + fill: var(--accent-text); +} +.ha-ring { + fill: none; + stroke: var(--ink); + stroke-width: 0.7; + opacity: 0.45; +} +.ha-ring.is-accent { + stroke: var(--accent-text); + opacity: 0.7; +} +.ha-name { + font-family: var(--font-head); + font-style: italic; + font-weight: 600; + font-size: 24px; + fill: var(--ink); +} +.ha-name.sm { + font-size: 20px; +} +.ha-type { + font-family: var(--font-mono); + font-size: 7.5px; + letter-spacing: 0.16em; + fill: var(--muted); +} +/* "Try it" section: [console | graph] over a horizontal control bar */ +.demo { + max-width: var(--maxw); + margin: 0 auto; + padding: 60px var(--gutter) 20px; +} +.demo-head { + display: flex; + align-items: baseline; + justify-content: space-between; + gap: 16px; + margin-bottom: 22px; +} +.demo-head h2 { + font-family: var(--font-head); + font-weight: 700; + font-size: 34px; + letter-spacing: -0.02em; + margin: 0; +} +.demo-reset { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 7px; + min-height: 44px; + background: none; + border: 1px solid var(--line-mid); + padding: 8px 13px; + font-family: var(--font-mono); + font-size: 11px; + letter-spacing: 0.06em; + color: var(--accent-text); + cursor: pointer; +} +.demo-reset:hover { + border-color: var(--accent); +} +.demo-panels { + display: grid; + grid-template-columns: 1.5fr 1fr; + gap: 24px; + align-items: stretch; + margin-bottom: 20px; +} +.demo-controls { + display: flex; + flex-direction: column; + gap: 14px; +} +.tabs { + display: flex; + gap: 4px; + border-bottom: 1px solid var(--line-soft); +} +.tab { + margin-bottom: -1px; + padding: 8px 14px; + background: none; + border: none; + border-bottom: 2px solid transparent; + font-family: var(--font-mono); + font-size: 12px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--muted); + cursor: pointer; +} +.tab.active { + color: var(--ink); + border-bottom-color: var(--accent); +} +.tab-panel[hidden] { + display: none; +} +.soon-heading { + display: none; +} +.title { + font-family: var(--font-head); + font-weight: 700; + font-size: 60px; + line-height: 1; + letter-spacing: -0.03em; + margin: 0 0 22px; + text-wrap: balance; +} +.lede { + font-size: 19px; + line-height: 1.58; + color: var(--body); + margin: 0 0 34px; + text-wrap: pretty; +} +.cta-row { + display: flex; + gap: 14px; + align-items: center; +} +.btn { + display: inline-flex; + align-items: center; + font-weight: 700; + font-size: 15px; +} +.btn-primary { + padding: 14px 26px; + background: var(--accent); + color: var(--btn-text); +} +.btn-primary:hover { + background: var(--accent-hover); + color: var(--btn-text); +} +.btn-outline { + padding: 13px 24px; + border: 1.5px solid var(--line-strong); + color: var(--ink); +} +.btn-outline:hover { + color: var(--ink); + border-color: var(--ink); +} +/* edge-state graph — dotted board, card nodes, animated active edges */ +.graph { + margin: 0; + display: flex; + flex-direction: column; + background-image: radial-gradient(var(--grid-line) 1.3px, transparent 1.3px); + background-size: 22px 22px; +} +.graph-svg { + width: 100%; + height: auto; + margin: auto 0; + max-height: 320px; + overflow: visible; +} +.gnode rect { + fill: var(--surf-card); + stroke: var(--line-mid); + stroke-width: 1.2; + transition: + stroke 0.3s, + opacity 0.3s, + filter 0.3s; +} +.gn-name { + fill: var(--ink); + font-family: var(--font-body); + font-weight: 700; + font-size: 14px; + text-anchor: middle; + transition: fill 0.3s; +} +.gn-type { + fill: var(--muted); + font-family: var(--font-mono); + font-size: 7.5px; + letter-spacing: 0.14em; + text-transform: uppercase; + text-anchor: middle; +} +.gedge line { + stroke: var(--line-mid); + stroke-width: 1.6; + stroke-linecap: round; + transition: + stroke 0.3s, + stroke-width 0.3s, + opacity 0.3s; +} +.gedge-label { + fill: var(--muted); + font-family: var(--font-mono); + font-size: 7px; + letter-spacing: 0.04em; + text-anchor: middle; + transition: fill 0.3s; +} +.gedge.on .gedge-label { + fill: var(--accent-text); +} +/* count numbering: the label becomes the ordinal (1, 2, …) on each edge */ +.gedge-label.num { + fill: var(--accent-text); + font-size: 10px; + font-weight: 700; +} +/* reactive states, toggled from the console */ +.gnode.dim, +.gedge.dim { + opacity: 0.28; +} +.gedge.on line { + stroke: var(--accent); + stroke-width: 2.2; + stroke-dasharray: 7 5; + animation: dashmove 0.55s linear infinite; +} +@keyframes dashmove { + to { + stroke-dashoffset: -12; + } +} +.gnode.on rect { + stroke: var(--accent); + stroke-width: 1.6; + filter: drop-shadow(0 6px 16px rgba(93, 95, 239, 0.34)); +} +.gnode.on .gn-name { + fill: var(--accent-text); +} +/* console */ +.console { + margin: 0; +} +/* Shared frame for the three demo cells (console, graph, controls) so + they read as one set; the dark console just sits inside its panel. */ +.panel { + padding: 20px; + background: var(--surf-soft); + border: 1px solid var(--line-soft); +} +.term { + background: var(--term-bg); + box-shadow: inset 0 2px 12px rgba(0, 0, 0, 0.55); +} +.term-bar { + display: flex; + align-items: center; + gap: 8px; + padding: 11px 14px; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); +} +.dot { + width: 9px; + height: 9px; + border-radius: 50%; + background: #3a3330; +} +.term-title { + margin-left: 8px; + font-family: var(--font-mono); + font-size: 11px; + color: #8a8ca0; +} +.term-body { + padding: 16px; + height: 294px; + /* Block scroll container so content keeps its natural height and + overflows (a flex column would instead shrink the banner to fit). + overflow:hidden means the user can't scroll or drag it — only the JS + below moves it, pinning the view to the bottom after each command so + the prompt stays put and the banner scrolls off. user-select:none + stops drag-selection inside the console. */ + overflow: hidden; + user-select: none; + font-family: var(--font-mono); + font-size: 12.5px; + /* terminal-tight leading so table borders (| ---) connect like the real CLI */ + line-height: 1.35; + color: var(--term-text); +} +.banner { + display: inline-block; + margin: 0 0 10px; + padding: 8px 14px 10px; + /* CSS stand-in for the CLI's ╭─╮ box-drawing frame (see frontmatter). */ + border: 1px solid var(--term-banner); + border-radius: 8px; + /* Otter body = default terminal foreground; gold runs opt in via .g. */ + color: var(--term-text); + font-family: var(--font-mono); + font-size: 9px; + /* Verified against renders: 1.1 keeps the figlet rows cohesive; + ≥1.2 opens gaps between rows. */ + line-height: 1.1; + white-space: pre; + overflow: hidden; +} +.banner .g { + color: var(--term-banner); +} +.line { + display: flex; + gap: 8px; +} +.line .prompt { + color: var(--accent-2); + flex: none; +} +.l { + white-space: pre-wrap; + word-break: break-word; +} +.l-cmd, +.l-out { + color: var(--term-text); +} +.l-ok { + color: var(--out-ok); +} +.l-dim, +.l-sys { + color: var(--out-dim); +} +.l-err { + color: var(--out-err); +} +.input-row { + display: flex; + gap: 8px; + align-items: center; + margin-top: 2px; +} +.input-row .prompt { + color: var(--accent-2); + flex: none; +} +.term-cursor { + display: inline-block; + width: 7px; + height: 15px; + background: var(--term-text); + animation: term-blink 1.1s steps(1) infinite; +} +@keyframes term-blink { + 50% { + opacity: 0; + } +} +@media (prefers-reduced-motion: reduce) { + .term-cursor, + .gedge.on line { + animation: none; + } +} +.term-hint { + color: var(--out-dim); +} +.presets { + display: flex; + flex-direction: column; + gap: 8px; +} +.preset { + position: relative; + display: flex; + flex-direction: column; + gap: 3px; + text-align: left; + background: var(--surf-card); + border: 1px solid var(--line-mid); + border-radius: 8px; + padding: 9px 11px; + cursor: pointer; + transition: + border-color 0.15s ease, + transform 0.15s ease, + box-shadow 0.15s ease; +} +.preset-cmd { + font-family: var(--font-mono); + font-size: 11px; + color: var(--body); +} +/* run affordance: make the rows read as executable buttons */ +.preset-cmd::before { + content: '▸'; + margin-right: 9px; + color: var(--accent-text); + opacity: 0.55; +} +.preset:disabled .preset-cmd::before { + opacity: 0.25; +} +.preset-desc { + font-family: var(--font-body); + font-size: 11px; + color: var(--muted); +} +.preset:hover:not(:disabled) { + border-color: var(--accent); + transform: translateY(-1px); + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1); +} +.preset:hover:not(:disabled) .preset-cmd::before { + opacity: 1; +} +.preset:disabled { + opacity: 0.4; + cursor: not-allowed; +} +.preset.active { + border-color: var(--accent); + background: var(--accent-fill); +} +.preset.active .preset-cmd { + color: var(--accent-text); +} +/* teaser: query ops that aren't shipped yet, shown disabled with a TBD tag */ +.preset-soon { + padding-right: 46px; +} +.preset-soon:disabled { + opacity: 0.6; +} +.tbd { + position: absolute; + top: 8px; + right: 10px; + font-size: 9px; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--muted); + border: 1px solid var(--line-mid); + padding: 1px 5px; +} + +/* trust band */ +.band { + border-top: 1px solid var(--line-soft); + border-bottom: 1px solid var(--line-soft); + background: var(--surf-soft); +} +.band-inner { + max-width: var(--maxw); + margin: 0 auto; + padding: 30px var(--gutter); + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 20px; +} +.band-statement { + margin: 0; + font-family: var(--font-head); + font-weight: 500; + font-size: 24px; + line-height: 1.3; + color: var(--ink); +} +.band-facts { + display: flex; +} +.fact { + font-family: var(--font-mono); + font-size: 10px; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--muted); + padding: 2px 16px; + border-left: 1px solid var(--line-mid); +} +.fact:first-child { + border-left: 0; +} + +/* sections */ +.section { + max-width: var(--maxw); + margin: 0 auto; + padding: 74px var(--gutter) 44px; +} +.section-head { + display: flex; + align-items: baseline; + gap: 16px; + margin-bottom: 38px; +} +.section-head h2 { + font-family: var(--font-head); + font-weight: 700; + font-size: 34px; + letter-spacing: -0.02em; + margin: 0; +} +.kicker { + font-family: var(--font-mono); + font-size: 12px; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--muted); +} + +/* feature cards */ +.feature-section { + padding-top: 72px; +} +.feature-group + .feature-group { + margin-top: 34px; +} +.feature-group-label { + display: block; + margin-bottom: 12px; + font-family: var(--font-mono); + font-size: 11px; + font-weight: 700; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--muted); +} +.features { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; +} +.card { + /* Vertical stripes only — no grid crosslines, no gradient wash. */ + background-color: var(--surf-soft); + background-image: linear-gradient(90deg, var(--grid-line) 1px, transparent 1px); + background-size: 28px 100%; + border: 1px solid var(--line-soft); + padding: 24px 22px; + min-height: 148px; + box-shadow: 0 16px 34px -26px rgba(35, 37, 75, 0.4); +} +.card-primary { + border-top: 2px solid var(--accent); +} +.card-secondary { + min-height: 132px; + background-image: none; + box-shadow: none; +} +.card-num { + display: block; + font-family: var(--font-mono); + font-size: 12px; + letter-spacing: 0.1em; + color: var(--accent-text); + margin-bottom: 12px; +} +.card h3 { + margin: 0 0 8px; + font-size: 16px; + font-weight: 700; + letter-spacing: -0.01em; +} +.card p { + margin: 0; + font-size: 14px; + line-height: 1.5; + color: var(--body); + text-wrap: pretty; +} + +/* architecture */ +.arch { + padding-top: 26px; + padding-bottom: 74px; +} +.arch-panel { + border: 1px solid var(--line-mid); + background: var(--surf-soft); + padding: 32px; + display: flex; + flex-direction: column; + align-items: center; +} +.arch-svg { + width: 100%; + max-width: 720px; + height: auto; + display: block; +} +.arch-box { + fill: var(--surf-card); + stroke: var(--line-mid); + stroke-width: 1; +} +.arch-box-accent { + stroke: var(--accent); + stroke-width: 2; +} +.arch-t { + fill: var(--ink); + font-family: var(--font-mono); + font-weight: 700; + font-size: 13px; + text-anchor: middle; +} +.arch-t-accent { + fill: var(--accent-text); +} +.arch-req { + fill: var(--accent-text); + font-family: var(--font-mono); + font-weight: 700; + font-size: 11px; + text-anchor: middle; +} +.arch-sub { + fill: var(--muted); + font-family: var(--font-mono); + font-size: 9.5px; + text-anchor: middle; +} +.arch-line { + fill: none; + stroke: var(--line-strong); + stroke-width: 1.5; +} +.arch-lbl { + fill: var(--muted); + font-family: var(--font-mono); + font-size: 9px; + letter-spacing: 0.1em; + text-anchor: middle; +} +.arch-lbl-rest { + text-anchor: start; +} + +/* quick start */ +.quickstart { + border-top: 1px solid var(--line-soft); + background: var(--surf-panel); +} +.quickstart-inner { + max-width: var(--maxw); + margin: 0 auto; + padding: 74px var(--gutter); +} +.steps { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 20px; +} +.step { + display: flex; + flex-direction: column; + min-width: 0; +} +.step-head { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 12px; + min-height: 36px; +} +.step-num { + font-family: var(--font-mono); + font-weight: 700; + font-size: 15px; + color: var(--accent-text); +} +.step-label { + font-size: 14px; + font-weight: 700; +} +.code-wrap { + display: flex; + flex: 1; + min-width: 0; + overflow: hidden; + border-radius: 10px; + background: var(--term-bg); +} +.code { + margin: 0; + flex: 1; + min-width: 0; + background: transparent; + color: var(--term-text); + padding: 14px; + font-family: var(--font-mono); + font-size: 12px; + line-height: 1.6; + white-space: pre; + overflow-x: auto; +} +.copy-code { + margin-left: auto; + display: inline-flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + border: 1px solid var(--line-mid); + border-radius: 6px; + background: var(--surf-soft); + color: var(--body); + cursor: pointer; +} +.copy-code:hover { + color: var(--ink); + border-color: var(--line-strong); +} +.copy-code .check-icon { + display: none; +} +.copy-code.copied { + color: var(--out-ok); +} +.copy-code.copied .copy-icon { + display: none; +} +.copy-code.copied .check-icon { + display: block; +} +.quickstart-more { + margin: 24px 0 0; + font-size: 14px; + color: var(--body); +} +/* In-paragraph links must not rely on colour alone (WCAG 1.4.1). */ +.quickstart-more a { + text-decoration: underline; + text-underline-offset: 3px; +} + +/* CTA */ +.cta { + border-top: 1px solid var(--line-soft); +} +.cta-inner { + max-width: var(--maxw); + margin: 0 auto; + padding: 90px var(--gutter); + text-align: center; +} +.cta-inner h2 { + font-family: var(--font-head); + font-weight: 700; + font-size: 48px; + letter-spacing: -0.03em; + margin: 0 0 14px; +} +.cta-inner p { + font-size: 18px; + color: var(--body); + margin: 0 auto 34px; + max-width: 46ch; + text-wrap: pretty; +} +.cta-center { + justify-content: center; +} + +/* footer */ +.footer { + border-top: 1px solid var(--line-soft); + background: var(--surf-foot); +} +.footer-inner { + max-width: var(--maxw); + margin: 0 auto; + padding: var(--gutter); + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 16px; + font-family: var(--font-mono); + font-size: 12px; + color: var(--muted); +} +.footer-links { + display: flex; + align-items: center; + gap: 22px; +} +.footer-links a { + color: var(--muted); +} +.footer-links a:hover { + color: var(--ink); +} + +/* On desktop the console fills its panel row to match the graph height. + Its content is taken out of flow (absolute) so running commands never + grows the cell — the body just clips (overflow:hidden) and auto-scrolls. + Mobile keeps the fixed body height. */ +@media (min-width: 901px) { + .term-fill { + position: relative; + } + .term-fill [data-console] { + position: absolute; + inset: 0; + display: flex; + flex-direction: column; + } + .term-fill .term { + flex: 1 1 0; + min-height: 0; + display: flex; + flex-direction: column; + } + .term-fill .term-body { + flex: 1 1 0; + min-height: 0; + height: auto; + } + /* full-width rows: command on the left, dimmed description on the right */ + .preset { + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: 16px; + } + .preset-desc { + text-align: right; + } +} + +/* responsive */ +/* Stack the console/graph earlier than the global breakpoint so the wide + result tables never get squeezed while side-by-side. */ +@media (max-width: 1080px) { + .demo-panels { + grid-template-columns: 1fr; + } +} +@media (max-width: 900px) { + :root { + --gutter: 24px; + } + .title { + font-size: 44px; + } + .demo { + display: flex; + flex-direction: column; + } + .demo-head { + order: 0; + } + .demo-controls { + order: 1; + margin-bottom: 24px; + } + .demo-panels { + order: 2; + min-width: 0; + margin-bottom: 0; + } + .demo-panels > *, + .console, + .term-fill, + .term-fill [data-console], + .term { + width: 100%; + min-width: 0; + max-width: 100%; + } + .graph { + order: 1; + } + .console { + order: 2; + overflow: hidden; + } + /* Keep runnable commands directly before the visualization. */ + .tabs { + display: none; + } + .tab-panel[data-panel='soon'] { + display: none !important; + } + .features, + .steps { + grid-template-columns: minmax(0, 1fr); + } +} +@media (max-width: 700px) { + .band-inner { + align-items: flex-start; + flex-direction: column; + } + .band-facts { + flex-wrap: wrap; + } + .fact { + padding-left: 0; + padding-right: 16px; + border-left: 0; + } + .arch-panel { + padding: 14px; + /* Don't scale the drawing below legibility — keep its text size and + let the panel scroll sideways instead. */ + overflow-x: auto; + align-items: flex-start; + } + .arch-svg { + min-width: 620px; + } +} +@media (max-width: 560px) { + :root { + --gutter: 20px; + } + .nav { + padding-block: 18px; + } + .brand-logo { + height: 22px; + } + .nav-links { + gap: 4px; + font-size: 13px; + } + .gh-link { + display: none; + } + .hero { + padding-top: 38px; + } + .title { + font-size: 36px; + } + .lede { + font-size: 17px; + } + .demo { + padding-top: 52px; + } + .demo-head { + align-items: center; + } + .demo-head h2 { + font-size: 31px; + } + .term-body { + height: 240px; + padding: 14px; + font-size: 11px; + } + .banner { + display: none; + } + .input-row { + flex-wrap: wrap; + } + .preset { + min-height: 52px; + } + .section-head { + align-items: flex-start; + flex-direction: column; + gap: 8px; + } + .feature-group + .feature-group { + margin-top: 26px; + } + .card { + min-height: 0; + } + .code { + font-size: 11px; + white-space: pre-wrap; + overflow-wrap: anywhere; + } + .cta-inner h2 { + font-size: 34px; + } + .footer-inner { + padding-block: 24px; + } +} +@media (max-width: 360px) { + .nav-stories { + display: none; + } +} diff --git a/website/src/assets/landing.css b/website/src/assets/landing.css index 22619e285..c9a585233 100644 --- a/website/src/assets/landing.css +++ b/website/src/assets/landing.css @@ -1,39 +1,181 @@ +/* + * Docs theme — Iris accent + Cloud backgrounds, matched to the marketing + * landing (src/pages/index.astro, which ships its own styles). This file only + * reskins the Starlight-powered docs by overriding its CSS custom properties, + * plus a few targeted component rules. Page structure is left to Starlight. + */ + +/* ---------- Palette + type tokens ---------- */ + :root { - --purple-hsl: 255, 60%, 60%; - --overlay-blurple: hsla(var(--purple-hsl), 0.2); + /* dark (default) */ + --sl-color-white: #ecedf6; + --sl-color-gray-1: #d7d9e6; + --sl-color-gray-2: #b4b7cc; /* body text */ + --sl-color-gray-3: #9da0b7; /* muted */ + --sl-color-gray-4: #6a6d84; + --sl-color-gray-5: #3a3c4d; + --sl-color-gray-6: #23252f; + --sl-color-gray-7: #1a1b24; + --sl-color-black: #0e0f17; + + --sl-color-accent-low: rgba(93, 95, 239, 0.24); + --sl-color-accent: #5d5fef; + --sl-color-accent-high: #a9aaf5; + --sl-color-text-accent: #a9aaf5; + + --sl-color-hairline: rgba(255, 255, 255, 0.1); + --sl-color-hairline-light: rgba(255, 255, 255, 0.16); + --sl-color-hairline-shade: rgba(255, 255, 255, 0.06); + --sl-color-bg-inline-code: rgba(255, 255, 255, 0.08); + --sl-color-bg-nav: rgba(18, 19, 28, 0.82); + --sl-color-bg-sidebar: transparent; + + --ab-page-bg: linear-gradient(180deg, #141520 0%, #0e0f17 100%); + --ab-page-bg-solid: #141520; + --ab-accent-fill: rgba(93, 95, 239, 0.18); + + --sl-font: 'Manrope', system-ui, -apple-system, sans-serif; + --sl-font-mono: 'JetBrains Mono', ui-monospace, monospace; + --ab-font-head: 'Cormorant', Georgia, serif; } :root[data-theme='light'] { - --purple-hsl: 255, 85%, 65%; + --sl-color-white: #20223a; /* headings */ + --sl-color-black: #ffffff; /* light surface (search button, overlays) */ + --sl-color-gray-1: #2c2f45; + --sl-color-gray-2: #4e5168; /* body */ + --sl-color-gray-3: #61657c; /* muted — 4.28:1 at #6f7389 failed AA on the page bg */ + --sl-color-gray-4: #9aa0b3; + --sl-color-gray-5: #d6dae1; + --sl-color-gray-6: #e9ecf1; + --sl-color-gray-7: #f3f5f8; + + --sl-color-accent-low: rgba(93, 95, 239, 0.12); + --sl-color-accent: #5d5fef; + --sl-color-accent-high: #4749d0; + --sl-color-text-accent: #5d5fef; + + --sl-color-hairline: rgba(32, 34, 58, 0.12); + --sl-color-hairline-light: rgba(32, 34, 58, 0.16); + --sl-color-hairline-shade: rgba(32, 34, 58, 0.08); + --sl-color-bg-inline-code: rgba(32, 34, 58, 0.07); + --sl-color-bg-nav: rgba(255, 255, 255, 0.82); + --sl-color-bg-sidebar: transparent; + + --ab-page-bg: linear-gradient(180deg, #f3f5f8 0%, #e9ecf1 100%); + --ab-page-bg-solid: #f3f5f8; + --ab-accent-fill: rgba(93, 95, 239, 0.12); } -[data-has-hero] .page { - background: - linear-gradient(215deg, var(--overlay-blurple), transparent 40%), - radial-gradient(var(--overlay-blurple), transparent 40%) no-repeat -60vw -40vh / 105vw 200vh, - radial-gradient(var(--overlay-blurple), transparent 65%) no-repeat 50% calc(100% + 20rem) / - 60rem 30rem; +/* ---------- Base ---------- */ + +/* Put the page gradient on <html> too so over-scroll (rubber-banding) never + flashes the white root background behind the fixed body background. */ +html, +body { + background: var(--ab-page-bg); + background-attachment: fixed; + /* Kill the rubber-band bounce so dragging past the top/bottom never exposes + the white root canvas behind the content. */ + overscroll-behavior: none; } -[data-has-hero] header { - border-bottom: 1px solid transparent; - background-color: transparent; - -webkit-backdrop-filter: blur(16px); - backdrop-filter: blur(16px); +/* Belt-and-braces: if any bounce still shows, it paints the root's solid + background-color (never the fixed gradient image), so keep it non-white. */ +html { + background-color: var(--ab-page-bg-solid); } -[data-has-hero] .hero > img { - filter: drop-shadow(0 0 3rem var(--overlay-blurple)); +:is(h1, h2, h3, h4, h5, h6), +.sl-markdown-content :is(h1, h2, h3, h4, h5, h6) { + font-family: var(--ab-font-head); + letter-spacing: -0.02em; } -/* Smaller hero image on mobile */ -@media (max-width: 768px) { - [data-has-hero] .hero > img { - max-width: 150px; - } +/* ---------- Header (sticky, translucent, blurred) ---------- */ + +.header { + /* Share the page's fixed background gradient so the header and body read as + one continuous surface (the body uses --ab-page-bg, not a flat colour). */ + background: var(--ab-page-bg); + background-attachment: fixed; } -/* Icon row component */ +/* ---------- Sidebar ---------- */ + +.sidebar-content .group-label .large, +.sidebar-content ul.top-level > li > a.large { + font-family: var(--sl-font-mono); + font-size: 0.6875rem; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--sl-color-gray-3); +} + +/* Active sidebar item: flat accent highlight, no rounded pill or left bar. */ +.sidebar-content a { + border-radius: 0; +} +/* Slightly smaller item links (top-level labels keep their own .large size). */ +.sidebar-content a:not(.large) { + font-size: 0.8125rem; +} +.sidebar-content a[aria-current='page'] { + color: var(--sl-color-accent); + background: rgba(93, 95, 239, 0.14); + font-weight: 700; +} + +/* ---------- Right rail (on this page) ---------- */ + +.right-sidebar a[aria-current='true'] { + color: var(--sl-color-text-accent); + font-weight: 700; +} +.right-sidebar a:not([aria-current='true']) { + color: var(--sl-color-gray-2); +} + +/* ---------- Callouts (minimal: mono label + bottom hairline) ---------- */ + +.starlight-aside { + background: transparent; + border: 0; + border-bottom: 1px solid var(--sl-color-hairline); + border-radius: 0; + padding: 0.25rem 0 1rem; +} + +.starlight-aside__title { + font-family: var(--sl-font-mono); + font-size: 0.6875rem; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.starlight-aside__icon { + display: none; +} + +/* ---------- Prev / next cards ---------- */ + +.pagination-links a { + border-radius: 10px; + border: 1px solid var(--sl-color-hairline); + /* Transparent so the cards sit on the page gradient instead of flashing a + near-white nav surface; a subtle tint only on hover. */ + background: transparent; +} +.pagination-links a:hover { + border-color: var(--sl-color-accent); + background: var(--ab-accent-fill); +} + +/* ---------- Retained utilities ---------- */ + +/* Icon row component (quick-start guide) */ .icon-row { display: inline-flex; align-items: center; @@ -64,23 +206,64 @@ display: none; } -/* Align nav links vertically when shields.io badge is present */ -ul:has(.nav-external) { +/* GitHub social icon as a round bordered button, matching the theme toggle + (and the landing nav) so the header controls read as one set. */ +/* no divider bar before the theme toggle */ +.social-icons::after { + display: none !important; +} +.social-icons a { + display: flex; align-items: center; + justify-content: center; + gap: 8px; + padding: 0; + min-width: 44px; + width: auto; + height: 44px; + border-radius: 999px; + border: 1px solid var(--sl-color-hairline-light); + color: var(--sl-color-gray-2); + /* Starlight underlines header links; the star count must not inherit it. */ + text-decoration: none; } - -.gh-badge { - height: 1.35rem; - display: block; - position: relative; - top: 1px; +.social-icons a.has-count { + padding: 0 15px; +} +.social-icons a .gh-count { + font-family: var(--sl-font-mono); + font-size: 11.5px; + font-weight: 500; + letter-spacing: 0.04em; +} +.social-icons a:hover { + border-color: var(--sl-color-white); + color: var(--sl-color-gray-2); +} +.social-icons a svg { + width: 18px !important; + height: 18px !important; } -:root[data-theme='light'] .gh-badge { - filter: invert(0.88); +/* Drop the rule between the page title and the body (the line under each h1) */ +.content-panel + .content-panel { + border-top: 0 !important; } /* WIP items in sidebar */ .sidebar-wip { opacity: 0.5; } + +/* Drop the vertical divider between content and the on-this-page rail (keep + the menu↔content one) so the footer band reads across both. */ +.right-sidebar { + border-inline-start: 0 !important; +} + +/* Docs header logo: the shared wordmark SVG is wide/short, and Starlight renders + it at 40px by default — size it down to match the landing nav (26px). */ +.site-title img { + height: 26px !important; + width: auto !important; +} diff --git a/website/src/assets/logo-dark.svg b/website/src/assets/logo-dark.svg index fc5352992..661fe4a63 100644 --- a/website/src/assets/logo-dark.svg +++ b/website/src/assets/logo-dark.svg @@ -1 +1 @@ -<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 168 40" xmlns="http://www.w3.org/2000/svg"><g fill="#fff" fill-rule="nonzero"><g transform="matrix(1.888683 0 0 1.888683 -48.407348 18.08733)"><path d="m49.23-2.043h1.584v6.612h-1.584v-.972c-.216.392-.506.682-.87.87s-.77.282-1.218.282h-.012c-.368 0-.712-.064-1.032-.192s-.6-.316-.84-.564-.43-.558-.57-.93-.21-.806-.21-1.302v-.996c0-.488.07-.918.21-1.29s.33-.684.57-.936.52-.442.84-.57.664-.192 1.032-.192h.012c.448 0 .854.088 1.218.264s.654.448.87.816zm-1.608 5.496c.2 0 .398-.04.594-.12s.368-.202.516-.366.268-.366.36-.606.138-.524.138-.852v-.492c0-.32-.046-.6-.138-.84s-.212-.442-.36-.606-.32-.286-.516-.366-.394-.12-.594-.12h-.012c-.44 0-.808.15-1.104.45s-.444.77-.444 1.41v.66c0 .632.148 1.098.444 1.398s.664.45 1.104.45z"/><path d="m55.338 4.761c-.416 0-.812-.068-1.188-.204s-.708-.338-.996-.606-.516-.6-.684-.996-.252-.85-.252-1.362v-.648c0-.512.084-.966.252-1.362s.396-.73.684-1.002.62-.476.996-.612.772-.204 1.188-.204h.012c.432 0 .83.068 1.194.204s.682.326.954.57.484.536.636.876.236.71.252 1.11h-1.488c-.008-.224-.054-.424-.138-.6s-.196-.326-.336-.45-.3-.22-.48-.288-.374-.102-.582-.102h-.012c-.2 0-.392.036-.576.108s-.348.178-.492.318-.26.316-.348.528-.132.454-.132.726v1.008c0 .272.044.512.132.72s.204.384.348.528.308.252.492.324.376.108.576.108h.012c.208 0 .402-.034.582-.102s.34-.164.48-.288.252-.274.336-.45.13-.372.138-.588h1.488c-.016.4-.1.768-.252 1.104s-.364.624-.636.864-.59.428-.954.564-.762.204-1.194.204z"/><path d="m65.346 2.289c0 .4-.07.752-.21 1.056s-.33.562-.57.774-.518.372-.834.48-.646.162-.99.162h-.024c-.352 0-.682-.054-.99-.162s-.576-.268-.804-.48-.41-.476-.546-.792-.204-.682-.204-1.098v-2.76h-1.068v-1.236h1.068v-1.896h1.572v1.896h2.784v1.236h-2.784v2.82c0 .4.11.704.33.912s.47.312.75.312h.012c.28 0 .528-.104.744-.312s.324-.512.324-.912z"/><path d="m67.002-2.979c-.264 0-.49-.092-.678-.276s-.282-.412-.282-.684.094-.5.282-.684.414-.276.678-.276c.256 0 .478.092.666.276s.282.412.282.684-.094.5-.282.684-.41.276-.666.276zm-.792 7.548v-6.612h1.572v6.612z"/><path d="m72.27 4.761c-.416 0-.814-.068-1.194-.204s-.714-.336-1.002-.6-.516-.592-.684-.984-.252-.844-.252-1.356v-.684c0-.52.084-.978.252-1.374s.396-.726.684-.99.622-.464 1.002-.6.778-.204 1.194-.204h.012c.416 0 .812.068 1.188.204s.708.336.996.6.516.594.684.99c.168.396.252.854.252 1.374v.684c0 .512-.084.964-.252 1.356s-.396.72-.684.984-.62.464-.996.6-.772.204-1.188.204zm.012-1.308c.2 0 .392-.036.576-.108s.348-.18.492-.324.258-.32.342-.528.126-.448.126-.72v-1.008c0-.272-.042-.514-.126-.726s-.198-.388-.342-.528-.308-.246-.492-.318-.376-.108-.576-.108h-.012c-.2 0-.392.036-.576.108s-.348.178-.492.318-.26.316-.348.528-.132.454-.132.726v1.008c0 .272.044.512.132.72s.204.384.348.528.308.252.492.324.376.108.576.108z"/><path d="m80.454-2.235c.344 0 .664.058.96.174s.556.286.78.51.4.502.528.834.192.718.192 1.158v4.128h-1.572v-3.936c0-.536-.132-.93-.396-1.182s-.596-.378-.996-.378h-.012c-.2 0-.392.036-.576.108s-.348.184-.492.336-.26.346-.348.582-.132.518-.132.846v3.624h-1.584v-6.612h1.584v.876c.232-.376.526-.648.882-.816s.746-.252 1.17-.252z"/><path d="m88.242-2.223c.368 0 .712.064 1.032.192s.6.318.84.57.43.564.57.936.21.802.21 1.29v.996c0 .496-.07.93-.21 1.302s-.33.682-.57.93-.52.436-.84.564-.664.192-1.032.192h-.012c-.448 0-.852-.086-1.212-.258s-.652-.446-.876-.822v.9h-1.584v-9.084h1.584v3.456c.224-.392.516-.684.876-.876s.764-.288 1.212-.288zm1.068 3.168c0-.64-.148-1.11-.444-1.41s-.664-.45-1.104-.45h-.012c-.208 0-.408.04-.6.12s-.362.202-.51.366-.268.366-.36.606-.138.52-.138.84v.492c0 .328.046.612.138.852s.212.442.36.606.318.286.51.366.392.12.6.12h.012c.44 0 .808-.15 1.104-.45s.444-.766.444-1.398z"/><path d="m96.75-2.043h1.584v6.612h-1.584v-.972c-.216.392-.506.682-.87.87s-.77.282-1.218.282h-.012c-.368 0-.712-.064-1.032-.192s-.6-.316-.84-.564-.43-.558-.57-.93-.21-.806-.21-1.302v-.996c0-.488.07-.918.21-1.29s.33-.684.57-.936.52-.442.84-.57.664-.192 1.032-.192h.012c.448 0 .854.088 1.218.264s.654.448.87.816zm-1.608 5.496c.2 0 .398-.04.594-.12s.368-.202.516-.366.268-.366.36-.606.138-.524.138-.852v-.492c0-.32-.046-.6-.138-.84s-.212-.442-.36-.606-.32-.286-.516-.366-.394-.12-.594-.12h-.012c-.44 0-.808.15-1.104.45s-.444.77-.444 1.41v.66c0 .632.148 1.098.444 1.398s.664.45 1.104.45z"/><path d="m102.51 4.761c-.424 0-.814-.056-1.17-.168s-.66-.272-.912-.48-.448-.456-.588-.744-.21-.608-.21-.96h1.44c.016.136.062.272.138.408s.18.258.312.366.288.194.468.258.386.096.618.096h.012c.36 0 .638-.07.834-.21s.294-.314.294-.522c0-.184-.064-.338-.192-.462s-.372-.226-.732-.306l-.96-.24c-.264-.064-.52-.146-.768-.246s-.466-.226-.654-.378-.34-.334-.456-.546-.174-.462-.174-.75c0-.312.062-.598.186-.858s.3-.484.528-.672.506-.332.834-.432.696-.15 1.104-.15h.012c.408 0 .778.056 1.11.168s.618.272.858.48.426.456.558.744.198.608.198.96h-1.428c-.016-.144-.06-.282-.132-.414s-.168-.252-.288-.36-.26-.194-.42-.258-.34-.096-.54-.096h-.012c-.336 0-.594.074-.774.222s-.27.322-.27.522c0 .176.074.324.222.444s.386.22.714.3l.972.24c.288.064.558.148.81.252s.468.234.648.39.322.344.426.564.156.482.156.786c0 .32-.068.606-.204.858s-.324.466-.564.642-.53.312-.87.408-.714.144-1.122.144z"/><path d="m109.482-2.235c.408 0 .794.066 1.158.198s.684.33.96.594.496.594.66.99c.164.396.246.858.246 1.386v.732h-4.668v.12c0 .288.044.54.132.756s.21.396.366.54.336.254.54.33.422.114.654.114h.012c.416 0 .76-.1 1.032-.3s.428-.48.468-.84h1.464c-.032.304-.12.6-.264.888s-.342.542-.594.762-.556.396-.912.528-.758.198-1.206.198h-.024c-.448 0-.866-.068-1.254-.204s-.73-.338-1.026-.606-.528-.6-.696-.996-.252-.85-.252-1.362v-.648c0-.512.086-.966.258-1.362s.404-.73.696-1.002.632-.476 1.02-.612.794-.204 1.218-.204zm-.024 1.248c-.208 0-.406.036-.594.108s-.358.18-.51.324-.274.32-.366.528-.142.448-.15.72h3.132c0-.288-.04-.538-.12-.75s-.188-.386-.324-.522-.294-.238-.474-.306-.374-.102-.582-.102z"/></g><g transform="matrix(.00370667695 0 0 -.0038399133 .98588821333 34.38053708181)"><path d="m4900 6823c-522.892-39.139-950.018-231.635-1077.77-279.56-65.118-24.427-124.542-31.172-142.23-33.44-162-19-285-71-383-160-64-59-107-129-145-237-32-89-38-97-157-229-106-118-213-256-434-564-345-479-492-653-721-854-193-169-333-266-545-377-210-110-404-184-624-239-110-28-150-48-178-88-37-56-39-110-8-173 83-162 276-442 421-609 314-361 643-679 1184-1144 14-12 120-95 235-186 256-200 618-505 780-656 145-135 277-245 416-346 282-205 598-348 928-419 136-29 377-37 491-15 159 30 258 103 296 220 21 61 14 211-11 271-56 133-153 231-305 306-88 43-136 57-298 84-87 14-160 32-185 45-67 35-169 122-256 220-80 89-202 246-200 258 0 4 21 24 47 46 77 63 142 127 232 227 46 52 85 96 87 98 1 2 35-12 75-32 155-75 299-91 573-62 267 28 506 12 686-46 251-80 397-223 445-434 31-138 54-202 92-260 69-106 189-207 291-246 46-17 72-20 146-17 77 4 99 9 154 37 129 66 211 191 233 355 43 321-176 793-515 1112-219 206-389 307-906 540-263 118-414 213-446 280-74 156 181 541 498 751 157 103 286 155 575 228 269 69 377 126 517 272 55 58 156 162 225 232 133 134 182 209 230 351 28 81 39 301 21 406-40 238-127 362-372 529-81 56-129 100-235 216-136 149-229 228-364 312-210 129-512 238-786 282-166 27-432 39-584 28zm404-128c243-29 445-78 640-156 261-105 434-234 646-481 62-72 116-118 247-207 51-35 108-77 126-94 148-139 210-422 142-652-41-138-66-176-215-325-75-74-160-166-190-203-110-138-212-191-516-271-249-65-349-100-467-164-249-135-431-309-579-555-67-111-92-193-93-297 0-109 33-189 98-235 129-93 255-160 491-262 618-267 958-550 1162-968 52.337-107.376 232.316-487.868 40-710-26-30-26-30-18 15 2.633 16.459 7.838 161.674 3.375 240.25-1.125 19.809-14.243 35.242-16.375 37.75-1.917 2.092-26.445 28.849-28.779 20.73-1.35-4.693-6.221-21.633-6.221-60.73-1-130-61-319-112-347-24-14-32-13-82 2-4.766 1.537-55.503 17.904-55.855 28.263-.378 11.146 17.796 35.929 19.855 38.737 33 47 52 111 53 185 1.086 70.578-22.279 134.84-32 135-7.451.123-18.973-62.423-20-68-18.044-98.768-82.324-210.727-108.906-220.548-21.407-7.909-100.27 87.37-124.094 138.548-14 30-42 115-62 189-40 147-67 205-130 279-116 136-266 209-565 273-146 31-392 37-608 14-221-24-306-15-430 44-56.786 27.159-74.086 42.845-83 48l15 30c75 108 189 410 199 528 5 70 5 70-14 46-11-13-45-72-55-98-45-119-127-262-268-463-79.454-112.909-351.372-395.771-383.916-404.649-15.213-4.15-21.753 3.519-22.973 4.95-10.284 12.058-33.481 57.543-36.111 62.699-25 49-25 49 39 120 227 255 400 523 727 1122 262 479 367 633 569 836 223 223 457 363 755 454 62 18 172 45 246 60 255 50 260 53 398 188 27.416 26.713 96.549 135.985 91.28 170.282-5.836 37.986-40.403 88.31-61.28 95.718-60 21-117 14-172-23-233-154-493-199-759-132-231.045 59.726-215.294 112.096-197.998 118.551 20.558 7.673 109.772-22.437 118.998-25.551 69-23 147-41 211-49 303-35 638 96 731 287 17.399 34.797 27.5 118.498 24.318 168.52-.187 2.935 1.165 34.952-33.318 70.48-19 20-74 56-122 81-66 34-97 57-130 97-143 176-197 212-440 293-256 85-266 91-323 210-52 108-105 166-194 211-52 26-66 29-157 28-79 0-112-5-158-23-80-31-165-112-211-201-29-54-46-75-75-90-21-10-127-37-237-60-109-23-236-54-281-69-275-94-508-318-629-605-84-197-123-405-131-697-7-248 7-406 59-654 126-605 147-810 114-1131-20-204-21-420-1-544 31-191 120-402 244-580 194-279 384-466 529-520 31-12 119-33 195-46 219-39 336-91 424-189 24.433-26.76 89.071-130.876 92.685-152.234.813-4.805-7.134-9.135-51.685 32.234-69 60-139 93-207 97-72 4-75-13-9-47 107-55 152-98 207-196 39-71 39-92-1-123-43.037-31.879-112.564-55.358-114-56-2.973 27.2 2.123 141.202-142 239-41 28-141 53-182 45-41-9-38-21 9-29 57.212-9.393 183.87-117.098 213.165-213.089 10.936-35.836 12.206-50.097-25.181-51.036-303.371-7.619-634.741 99.622-758.984 154.125-455 201-948 620-1280 1085-128 180-186 276-273 455-20.547 42.358-16.529 44.046-223.453 544.4-3.783 9.148-6.145 7.558-10.547 16.6-1.734-34.853-2.871-34.749.991-69.368 2.194-19.671 19.299-173.023 37.009-244.632 57-222 179-510 275-647 16-23-2-13-69 39-917.434 711.172-1475.18 1332.438-1699 1640-62.483 85.436-226.566 348.174-226.147 373.617.027 1.616 4.901 10.765 12.046 15.463 21.234 13.96 148.034 52 161.101 55.92 374 112 628 227 877 399 351 242 595 498 956 1004 234 328 386 527 515 675 105 119 128 150 143 200 30 94 71 166 124 217 97 93 179 129 346 151 95 12 136 24 252 71 511 208 912 278 1328 229zm-36-702c77.267-36.6 165.787-185.732 64.4-315.832-100.705-129.224-314.39-78.607-351.675 84.969-35.37 155.17 130.848 302.124 287.275 230.863z"/><path d="m3615 6316c-113-28-202-102-257-213-44-89-51-211-18-314 25-76 82-163 144-216 28-26 46-33 77-33 34 0 41 4 50 28 17 44 4 96-52 206-43 87-52 112-52 158 0 83 45 149 125 182 54 23 102 20 208-14 90-28 178-38 214-24 12 4 16 20 16 54 0 45-3 51-42 85-115 99-270 136-413 101z"/><path d="m6605 5800c-74-13-129-35-191-76-63-42-76-62-72-107 5-52 44-56 164-15 96 32 104 33 259 33 160 0 160 0 163 39 4 47-20 76-86 104-56 24-168 34-237 22z"/><path d="m6931 5417c-11-19-66-76-121-127-121-111-142-147-148-254-8-128 29-173 139-169 67 2 105 19 147 68 74 84 107 186 107 335 0 142-12 173-66 178-32 3-39-1-58-31z"/></g><path d="m5172 5964c-18-12-22-25-22-69 0-67 24-95 81-95 51 0 67 8 84 41 38 72 1 139-77 139-24 0-54-7-66-16z" transform="matrix(.00308941791 0 0 -.00320079518 4.20380425956 30.63085393656)"/></g></svg> \ No newline at end of file +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="9.64 6.08 155.19 23.76" xmlns="http://www.w3.org/2000/svg"><g fill="#fff" fill-rule="nonzero"><g transform="matrix(1.888683 0 0 1.888683 -48.407348 18.08733)"><path d="m49.23-2.043h1.584v6.612h-1.584v-.972c-.216.392-.506.682-.87.87s-.77.282-1.218.282h-.012c-.368 0-.712-.064-1.032-.192s-.6-.316-.84-.564-.43-.558-.57-.93-.21-.806-.21-1.302v-.996c0-.488.07-.918.21-1.29s.33-.684.57-.936.52-.442.84-.57.664-.192 1.032-.192h.012c.448 0 .854.088 1.218.264s.654.448.87.816zm-1.608 5.496c.2 0 .398-.04.594-.12s.368-.202.516-.366.268-.366.36-.606.138-.524.138-.852v-.492c0-.32-.046-.6-.138-.84s-.212-.442-.36-.606-.32-.286-.516-.366-.394-.12-.594-.12h-.012c-.44 0-.808.15-1.104.45s-.444.77-.444 1.41v.66c0 .632.148 1.098.444 1.398s.664.45 1.104.45z"/><path d="m55.338 4.761c-.416 0-.812-.068-1.188-.204s-.708-.338-.996-.606-.516-.6-.684-.996-.252-.85-.252-1.362v-.648c0-.512.084-.966.252-1.362s.396-.73.684-1.002.62-.476.996-.612.772-.204 1.188-.204h.012c.432 0 .83.068 1.194.204s.682.326.954.57.484.536.636.876.236.71.252 1.11h-1.488c-.008-.224-.054-.424-.138-.6s-.196-.326-.336-.45-.3-.22-.48-.288-.374-.102-.582-.102h-.012c-.2 0-.392.036-.576.108s-.348.178-.492.318-.26.316-.348.528-.132.454-.132.726v1.008c0 .272.044.512.132.72s.204.384.348.528.308.252.492.324.376.108.576.108h.012c.208 0 .402-.034.582-.102s.34-.164.48-.288.252-.274.336-.45.13-.372.138-.588h1.488c-.016.4-.1.768-.252 1.104s-.364.624-.636.864-.59.428-.954.564-.762.204-1.194.204z"/><path d="m65.346 2.289c0 .4-.07.752-.21 1.056s-.33.562-.57.774-.518.372-.834.48-.646.162-.99.162h-.024c-.352 0-.682-.054-.99-.162s-.576-.268-.804-.48-.41-.476-.546-.792-.204-.682-.204-1.098v-2.76h-1.068v-1.236h1.068v-1.896h1.572v1.896h2.784v1.236h-2.784v2.82c0 .4.11.704.33.912s.47.312.75.312h.012c.28 0 .528-.104.744-.312s.324-.512.324-.912z"/><path d="m67.002-2.979c-.264 0-.49-.092-.678-.276s-.282-.412-.282-.684.094-.5.282-.684.414-.276.678-.276c.256 0 .478.092.666.276s.282.412.282.684-.094.5-.282.684-.41.276-.666.276zm-.792 7.548v-6.612h1.572v6.612z"/><path d="m72.27 4.761c-.416 0-.814-.068-1.194-.204s-.714-.336-1.002-.6-.516-.592-.684-.984-.252-.844-.252-1.356v-.684c0-.52.084-.978.252-1.374s.396-.726.684-.99.622-.464 1.002-.6.778-.204 1.194-.204h.012c.416 0 .812.068 1.188.204s.708.336.996.6.516.594.684.99c.168.396.252.854.252 1.374v.684c0 .512-.084.964-.252 1.356s-.396.72-.684.984-.62.464-.996.6-.772.204-1.188.204zm.012-1.308c.2 0 .392-.036.576-.108s.348-.18.492-.324.258-.32.342-.528.126-.448.126-.72v-1.008c0-.272-.042-.514-.126-.726s-.198-.388-.342-.528-.308-.246-.492-.318-.376-.108-.576-.108h-.012c-.2 0-.392.036-.576.108s-.348.178-.492.318-.26.316-.348.528-.132.454-.132.726v1.008c0 .272.044.512.132.72s.204.384.348.528.308.252.492.324.376.108.576.108z"/><path d="m80.454-2.235c.344 0 .664.058.96.174s.556.286.78.51.4.502.528.834.192.718.192 1.158v4.128h-1.572v-3.936c0-.536-.132-.93-.396-1.182s-.596-.378-.996-.378h-.012c-.2 0-.392.036-.576.108s-.348.184-.492.336-.26.346-.348.582-.132.518-.132.846v3.624h-1.584v-6.612h1.584v.876c.232-.376.526-.648.882-.816s.746-.252 1.17-.252z"/><path d="m88.242-2.223c.368 0 .712.064 1.032.192s.6.318.84.57.43.564.57.936.21.802.21 1.29v.996c0 .496-.07.93-.21 1.302s-.33.682-.57.93-.52.436-.84.564-.664.192-1.032.192h-.012c-.448 0-.852-.086-1.212-.258s-.652-.446-.876-.822v.9h-1.584v-9.084h1.584v3.456c.224-.392.516-.684.876-.876s.764-.288 1.212-.288zm1.068 3.168c0-.64-.148-1.11-.444-1.41s-.664-.45-1.104-.45h-.012c-.208 0-.408.04-.6.12s-.362.202-.51.366-.268.366-.36.606-.138.52-.138.84v.492c0 .328.046.612.138.852s.212.442.36.606.318.286.51.366.392.12.6.12h.012c.44 0 .808-.15 1.104-.45s.444-.766.444-1.398z"/><path d="m96.75-2.043h1.584v6.612h-1.584v-.972c-.216.392-.506.682-.87.87s-.77.282-1.218.282h-.012c-.368 0-.712-.064-1.032-.192s-.6-.316-.84-.564-.43-.558-.57-.93-.21-.806-.21-1.302v-.996c0-.488.07-.918.21-1.29s.33-.684.57-.936.52-.442.84-.57.664-.192 1.032-.192h.012c.448 0 .854.088 1.218.264s.654.448.87.816zm-1.608 5.496c.2 0 .398-.04.594-.12s.368-.202.516-.366.268-.366.36-.606.138-.524.138-.852v-.492c0-.32-.046-.6-.138-.84s-.212-.442-.36-.606-.32-.286-.516-.366-.394-.12-.594-.12h-.012c-.44 0-.808.15-1.104.45s-.444.77-.444 1.41v.66c0 .632.148 1.098.444 1.398s.664.45 1.104.45z"/><path d="m102.51 4.761c-.424 0-.814-.056-1.17-.168s-.66-.272-.912-.48-.448-.456-.588-.744-.21-.608-.21-.96h1.44c.016.136.062.272.138.408s.18.258.312.366.288.194.468.258.386.096.618.096h.012c.36 0 .638-.07.834-.21s.294-.314.294-.522c0-.184-.064-.338-.192-.462s-.372-.226-.732-.306l-.96-.24c-.264-.064-.52-.146-.768-.246s-.466-.226-.654-.378-.34-.334-.456-.546-.174-.462-.174-.75c0-.312.062-.598.186-.858s.3-.484.528-.672.506-.332.834-.432.696-.15 1.104-.15h.012c.408 0 .778.056 1.11.168s.618.272.858.48.426.456.558.744.198.608.198.96h-1.428c-.016-.144-.06-.282-.132-.414s-.168-.252-.288-.36-.26-.194-.42-.258-.34-.096-.54-.096h-.012c-.336 0-.594.074-.774.222s-.27.322-.27.522c0 .176.074.324.222.444s.386.22.714.3l.972.24c.288.064.558.148.81.252s.468.234.648.39.322.344.426.564.156.482.156.786c0 .32-.068.606-.204.858s-.324.466-.564.642-.53.312-.87.408-.714.144-1.122.144z"/><path d="m109.482-2.235c.408 0 .794.066 1.158.198s.684.33.96.594.496.594.66.99c.164.396.246.858.246 1.386v.732h-4.668v.12c0 .288.044.54.132.756s.21.396.366.54.336.254.54.33.422.114.654.114h.012c.416 0 .76-.1 1.032-.3s.428-.48.468-.84h1.464c-.032.304-.12.6-.264.888s-.342.542-.594.762-.556.396-.912.528-.758.198-1.206.198h-.024c-.448 0-.866-.068-1.254-.204s-.73-.338-1.026-.606-.528-.6-.696-.996-.252-.85-.252-1.362v-.648c0-.512.086-.966.258-1.362s.404-.73.696-1.002.632-.476 1.02-.612.794-.204 1.218-.204zm-.024 1.248c-.208 0-.406.036-.594.108s-.358.18-.51.324-.274.32-.366.528-.142.448-.15.72h3.132c0-.288-.04-.538-.12-.75s-.188-.386-.324-.522-.294-.238-.474-.306-.374-.102-.582-.102z"/></g><g id="otter" transform="translate(8.0248 -0.3158) scale(0.87488)"><g transform="matrix(.00370667695 0 0 -.0038399133 .98588821333 34.38053708181)"><path d="m4900 6823c-522.892-39.139-950.018-231.635-1077.77-279.56-65.118-24.427-124.542-31.172-142.23-33.44-162-19-285-71-383-160-64-59-107-129-145-237-32-89-38-97-157-229-106-118-213-256-434-564-345-479-492-653-721-854-193-169-333-266-545-377-210-110-404-184-624-239-110-28-150-48-178-88-37-56-39-110-8-173 83-162 276-442 421-609 314-361 643-679 1184-1144 14-12 120-95 235-186 256-200 618-505 780-656 145-135 277-245 416-346 282-205 598-348 928-419 136-29 377-37 491-15 159 30 258 103 296 220 21 61 14 211-11 271-56 133-153 231-305 306-88 43-136 57-298 84-87 14-160 32-185 45-67 35-169 122-256 220-80 89-202 246-200 258 0 4 21 24 47 46 77 63 142 127 232 227 46 52 85 96 87 98 1 2 35-12 75-32 155-75 299-91 573-62 267 28 506 12 686-46 251-80 397-223 445-434 31-138 54-202 92-260 69-106 189-207 291-246 46-17 72-20 146-17 77 4 99 9 154 37 129 66 211 191 233 355 43 321-176 793-515 1112-219 206-389 307-906 540-263 118-414 213-446 280-74 156 181 541 498 751 157 103 286 155 575 228 269 69 377 126 517 272 55 58 156 162 225 232 133 134 182 209 230 351 28 81 39 301 21 406-40 238-127 362-372 529-81 56-129 100-235 216-136 149-229 228-364 312-210 129-512 238-786 282-166 27-432 39-584 28zm404-128c243-29 445-78 640-156 261-105 434-234 646-481 62-72 116-118 247-207 51-35 108-77 126-94 148-139 210-422 142-652-41-138-66-176-215-325-75-74-160-166-190-203-110-138-212-191-516-271-249-65-349-100-467-164-249-135-431-309-579-555-67-111-92-193-93-297 0-109 33-189 98-235 129-93 255-160 491-262 618-267 958-550 1162-968 52.337-107.376 232.316-487.868 40-710-26-30-26-30-18 15 2.633 16.459 7.838 161.674 3.375 240.25-1.125 19.809-14.243 35.242-16.375 37.75-1.917 2.092-26.445 28.849-28.779 20.73-1.35-4.693-6.221-21.633-6.221-60.73-1-130-61-319-112-347-24-14-32-13-82 2-4.766 1.537-55.503 17.904-55.855 28.263-.378 11.146 17.796 35.929 19.855 38.737 33 47 52 111 53 185 1.086 70.578-22.279 134.84-32 135-7.451.123-18.973-62.423-20-68-18.044-98.768-82.324-210.727-108.906-220.548-21.407-7.909-100.27 87.37-124.094 138.548-14 30-42 115-62 189-40 147-67 205-130 279-116 136-266 209-565 273-146 31-392 37-608 14-221-24-306-15-430 44-56.786 27.159-74.086 42.845-83 48l15 30c75 108 189 410 199 528 5 70 5 70-14 46-11-13-45-72-55-98-45-119-127-262-268-463-79.454-112.909-351.372-395.771-383.916-404.649-15.213-4.15-21.753 3.519-22.973 4.95-10.284 12.058-33.481 57.543-36.111 62.699-25 49-25 49 39 120 227 255 400 523 727 1122 262 479 367 633 569 836 223 223 457 363 755 454 62 18 172 45 246 60 255 50 260 53 398 188 27.416 26.713 96.549 135.985 91.28 170.282-5.836 37.986-40.403 88.31-61.28 95.718-60 21-117 14-172-23-233-154-493-199-759-132-231.045 59.726-215.294 112.096-197.998 118.551 20.558 7.673 109.772-22.437 118.998-25.551 69-23 147-41 211-49 303-35 638 96 731 287 17.399 34.797 27.5 118.498 24.318 168.52-.187 2.935 1.165 34.952-33.318 70.48-19 20-74 56-122 81-66 34-97 57-130 97-143 176-197 212-440 293-256 85-266 91-323 210-52 108-105 166-194 211-52 26-66 29-157 28-79 0-112-5-158-23-80-31-165-112-211-201-29-54-46-75-75-90-21-10-127-37-237-60-109-23-236-54-281-69-275-94-508-318-629-605-84-197-123-405-131-697-7-248 7-406 59-654 126-605 147-810 114-1131-20-204-21-420-1-544 31-191 120-402 244-580 194-279 384-466 529-520 31-12 119-33 195-46 219-39 336-91 424-189 24.433-26.76 89.071-130.876 92.685-152.234.813-4.805-7.134-9.135-51.685 32.234-69 60-139 93-207 97-72 4-75-13-9-47 107-55 152-98 207-196 39-71 39-92-1-123-43.037-31.879-112.564-55.358-114-56-2.973 27.2 2.123 141.202-142 239-41 28-141 53-182 45-41-9-38-21 9-29 57.212-9.393 183.87-117.098 213.165-213.089 10.936-35.836 12.206-50.097-25.181-51.036-303.371-7.619-634.741 99.622-758.984 154.125-455 201-948 620-1280 1085-128 180-186 276-273 455-20.547 42.358-16.529 44.046-223.453 544.4-3.783 9.148-6.145 7.558-10.547 16.6-1.734-34.853-2.871-34.749.991-69.368 2.194-19.671 19.299-173.023 37.009-244.632 57-222 179-510 275-647 16-23-2-13-69 39-917.434 711.172-1475.18 1332.438-1699 1640-62.483 85.436-226.566 348.174-226.147 373.617.027 1.616 4.901 10.765 12.046 15.463 21.234 13.96 148.034 52 161.101 55.92 374 112 628 227 877 399 351 242 595 498 956 1004 234 328 386 527 515 675 105 119 128 150 143 200 30 94 71 166 124 217 97 93 179 129 346 151 95 12 136 24 252 71 511 208 912 278 1328 229zm-36-702c77.267-36.6 165.787-185.732 64.4-315.832-100.705-129.224-314.39-78.607-351.675 84.969-35.37 155.17 130.848 302.124 287.275 230.863z"/><path d="m3615 6316c-113-28-202-102-257-213-44-89-51-211-18-314 25-76 82-163 144-216 28-26 46-33 77-33 34 0 41 4 50 28 17 44 4 96-52 206-43 87-52 112-52 158 0 83 45 149 125 182 54 23 102 20 208-14 90-28 178-38 214-24 12 4 16 20 16 54 0 45-3 51-42 85-115 99-270 136-413 101z"/><path d="m6605 5800c-74-13-129-35-191-76-63-42-76-62-72-107 5-52 44-56 164-15 96 32 104 33 259 33 160 0 160 0 163 39 4 47-20 76-86 104-56 24-168 34-237 22z"/><path d="m6931 5417c-11-19-66-76-121-127-121-111-142-147-148-254-8-128 29-173 139-169 67 2 105 19 147 68 74 84 107 186 107 335 0 142-12 173-66 178-32 3-39-1-58-31z"/></g><path d="m5172 5964c-18-12-22-25-22-69 0-67 24-95 81-95 51 0 67 8 84 41 38 72 1 139-77 139-24 0-54-7-66-16z" transform="matrix(.00308941791 0 0 -.00320079518 4.20380425956 30.63085393656)"/></g></g></svg> \ No newline at end of file diff --git a/website/src/assets/logo-light.svg b/website/src/assets/logo-light.svg index 4e2fd9055..7bcd3d998 100644 --- a/website/src/assets/logo-light.svg +++ b/website/src/assets/logo-light.svg @@ -1 +1 @@ -<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 168 40" xmlns="http://www.w3.org/2000/svg"><g fill="#23262d"><g fill-rule="nonzero" transform="matrix(1.888683 0 0 1.888683 -48.407348 18.08733)"><path d="m49.23-2.043h1.584v6.612h-1.584v-.972c-.216.392-.506.682-.87.87s-.77.282-1.218.282h-.012c-.368 0-.712-.064-1.032-.192s-.6-.316-.84-.564-.43-.558-.57-.93-.21-.806-.21-1.302v-.996c0-.488.07-.918.21-1.29s.33-.684.57-.936.52-.442.84-.57.664-.192 1.032-.192h.012c.448 0 .854.088 1.218.264s.654.448.87.816zm-1.608 5.496c.2 0 .398-.04.594-.12s.368-.202.516-.366.268-.366.36-.606.138-.524.138-.852v-.492c0-.32-.046-.6-.138-.84s-.212-.442-.36-.606-.32-.286-.516-.366-.394-.12-.594-.12h-.012c-.44 0-.808.15-1.104.45s-.444.77-.444 1.41v.66c0 .632.148 1.098.444 1.398s.664.45 1.104.45z"/><path d="m55.338 4.761c-.416 0-.812-.068-1.188-.204s-.708-.338-.996-.606-.516-.6-.684-.996-.252-.85-.252-1.362v-.648c0-.512.084-.966.252-1.362s.396-.73.684-1.002.62-.476.996-.612.772-.204 1.188-.204h.012c.432 0 .83.068 1.194.204s.682.326.954.57.484.536.636.876.236.71.252 1.11h-1.488c-.008-.224-.054-.424-.138-.6s-.196-.326-.336-.45-.3-.22-.48-.288-.374-.102-.582-.102h-.012c-.2 0-.392.036-.576.108s-.348.178-.492.318-.26.316-.348.528-.132.454-.132.726v1.008c0 .272.044.512.132.72s.204.384.348.528.308.252.492.324.376.108.576.108h.012c.208 0 .402-.034.582-.102s.34-.164.48-.288.252-.274.336-.45.13-.372.138-.588h1.488c-.016.4-.1.768-.252 1.104s-.364.624-.636.864-.59.428-.954.564-.762.204-1.194.204z"/><path d="m65.346 2.289c0 .4-.07.752-.21 1.056s-.33.562-.57.774-.518.372-.834.48-.646.162-.99.162h-.024c-.352 0-.682-.054-.99-.162s-.576-.268-.804-.48-.41-.476-.546-.792-.204-.682-.204-1.098v-2.76h-1.068v-1.236h1.068v-1.896h1.572v1.896h2.784v1.236h-2.784v2.82c0 .4.11.704.33.912s.47.312.75.312h.012c.28 0 .528-.104.744-.312s.324-.512.324-.912z"/><path d="m67.002-2.979c-.264 0-.49-.092-.678-.276s-.282-.412-.282-.684.094-.5.282-.684.414-.276.678-.276c.256 0 .478.092.666.276s.282.412.282.684-.094.5-.282.684-.41.276-.666.276zm-.792 7.548v-6.612h1.572v6.612z"/><path d="m72.27 4.761c-.416 0-.814-.068-1.194-.204s-.714-.336-1.002-.6-.516-.592-.684-.984-.252-.844-.252-1.356v-.684c0-.52.084-.978.252-1.374s.396-.726.684-.99.622-.464 1.002-.6.778-.204 1.194-.204h.012c.416 0 .812.068 1.188.204s.708.336.996.6.516.594.684.99c.168.396.252.854.252 1.374v.684c0 .512-.084.964-.252 1.356s-.396.72-.684.984-.62.464-.996.6-.772.204-1.188.204zm.012-1.308c.2 0 .392-.036.576-.108s.348-.18.492-.324.258-.32.342-.528.126-.448.126-.72v-1.008c0-.272-.042-.514-.126-.726s-.198-.388-.342-.528-.308-.246-.492-.318-.376-.108-.576-.108h-.012c-.2 0-.392.036-.576.108s-.348.178-.492.318-.26.316-.348.528-.132.454-.132.726v1.008c0 .272.044.512.132.72s.204.384.348.528.308.252.492.324.376.108.576.108z"/><path d="m80.454-2.235c.344 0 .664.058.96.174s.556.286.78.51.4.502.528.834.192.718.192 1.158v4.128h-1.572v-3.936c0-.536-.132-.93-.396-1.182s-.596-.378-.996-.378h-.012c-.2 0-.392.036-.576.108s-.348.184-.492.336-.26.346-.348.582-.132.518-.132.846v3.624h-1.584v-6.612h1.584v.876c.232-.376.526-.648.882-.816s.746-.252 1.17-.252z"/><path d="m88.242-2.223c.368 0 .712.064 1.032.192s.6.318.84.57.43.564.57.936.21.802.21 1.29v.996c0 .496-.07.93-.21 1.302s-.33.682-.57.93-.52.436-.84.564-.664.192-1.032.192h-.012c-.448 0-.852-.086-1.212-.258s-.652-.446-.876-.822v.9h-1.584v-9.084h1.584v3.456c.224-.392.516-.684.876-.876s.764-.288 1.212-.288zm1.068 3.168c0-.64-.148-1.11-.444-1.41s-.664-.45-1.104-.45h-.012c-.208 0-.408.04-.6.12s-.362.202-.51.366-.268.366-.36.606-.138.52-.138.84v.492c0 .328.046.612.138.852s.212.442.36.606.318.286.51.366.392.12.6.12h.012c.44 0 .808-.15 1.104-.45s.444-.766.444-1.398z"/><path d="m96.75-2.043h1.584v6.612h-1.584v-.972c-.216.392-.506.682-.87.87s-.77.282-1.218.282h-.012c-.368 0-.712-.064-1.032-.192s-.6-.316-.84-.564-.43-.558-.57-.93-.21-.806-.21-1.302v-.996c0-.488.07-.918.21-1.29s.33-.684.57-.936.52-.442.84-.57.664-.192 1.032-.192h.012c.448 0 .854.088 1.218.264s.654.448.87.816zm-1.608 5.496c.2 0 .398-.04.594-.12s.368-.202.516-.366.268-.366.36-.606.138-.524.138-.852v-.492c0-.32-.046-.6-.138-.84s-.212-.442-.36-.606-.32-.286-.516-.366-.394-.12-.594-.12h-.012c-.44 0-.808.15-1.104.45s-.444.77-.444 1.41v.66c0 .632.148 1.098.444 1.398s.664.45 1.104.45z"/><path d="m102.51 4.761c-.424 0-.814-.056-1.17-.168s-.66-.272-.912-.48-.448-.456-.588-.744-.21-.608-.21-.96h1.44c.016.136.062.272.138.408s.18.258.312.366.288.194.468.258.386.096.618.096h.012c.36 0 .638-.07.834-.21s.294-.314.294-.522c0-.184-.064-.338-.192-.462s-.372-.226-.732-.306l-.96-.24c-.264-.064-.52-.146-.768-.246s-.466-.226-.654-.378-.34-.334-.456-.546-.174-.462-.174-.75c0-.312.062-.598.186-.858s.3-.484.528-.672.506-.332.834-.432.696-.15 1.104-.15h.012c.408 0 .778.056 1.11.168s.618.272.858.48.426.456.558.744.198.608.198.96h-1.428c-.016-.144-.06-.282-.132-.414s-.168-.252-.288-.36-.26-.194-.42-.258-.34-.096-.54-.096h-.012c-.336 0-.594.074-.774.222s-.27.322-.27.522c0 .176.074.324.222.444s.386.22.714.3l.972.24c.288.064.558.148.81.252s.468.234.648.39.322.344.426.564.156.482.156.786c0 .32-.068.606-.204.858s-.324.466-.564.642-.53.312-.87.408-.714.144-1.122.144z"/><path d="m109.482-2.235c.408 0 .794.066 1.158.198s.684.33.96.594.496.594.66.99c.164.396.246.858.246 1.386v.732h-4.668v.12c0 .288.044.54.132.756s.21.396.366.54.336.254.54.33.422.114.654.114h.012c.416 0 .76-.1 1.032-.3s.428-.48.468-.84h1.464c-.032.304-.12.6-.264.888s-.342.542-.594.762-.556.396-.912.528-.758.198-1.206.198h-.024c-.448 0-.866-.068-1.254-.204s-.73-.338-1.026-.606-.528-.6-.696-.996-.252-.85-.252-1.362v-.648c0-.512.086-.966.258-1.362s.404-.73.696-1.002.632-.476 1.02-.612.794-.204 1.218-.204zm-.024 1.248c-.208 0-.406.036-.594.108s-.358.18-.51.324-.274.32-.366.528-.142.448-.15.72h3.132c0-.288-.04-.538-.12-.75s-.188-.386-.324-.522-.294-.238-.474-.306-.374-.102-.582-.102z"/></g><path d="m5304.009 6694.985c243-28.999 445.001-77.999 640.001-155.999 261.001-105 434.001-234 646.001-480.999 62-72 116-118 247.001-206.999 51-35 108-77 126-94 148-139 210-421.999 142-651.999-41-137.999-66-175.999-215-324.999-75-74-160.001-165.999-190.001-202.999-110-138-212-191-516.001-271-249-64.999-349-99.999-467-163.999-249.001-135-431.001-308.999-579.001-554.999-67-111-92-192.999-93-296.999 0-109 33-189 98-235 129-92.999 255-159.999 491.001-261.999 618.001-266.999 958.001-549.998 1162.002-967.997 52.337-107.376 232.316-487.867 40-709.999-26-30-26-30-18 15 2.633 16.459 7.838 161.674 3.375 240.25-1.125 19.809-14.243 35.242-16.375 37.75-1.917 2.092-26.445 28.849-28.78 20.73-1.35-4.693-6.221-21.633-6.221-60.73-1-130-61-319-112-346.999-24-14-32-13-82 2-4.766 1.537-55.503 17.903-55.855 28.262-.378 11.146 17.796 35.929 19.855 38.737 33 47 52 111 53 185 1.086 70.578-22.279 134.84-32 135-7.451.123-18.973-62.423-20-68-18.044-98.768-82.324-210.727-108.906-220.548-21.407-7.909-100.27 87.37-124.094 138.548-14 30-42 115-62 188.999-40 147-67.001 205-130.001 279-116 135.999-266 208.999-565.001 272.999-146 31-392 37-608.001 14-221-24-306-15-430 44-56.786 27.159-74.086 42.845-83 48l15 30c75 107.999 189 409.999 199 527.998 5 70 5 70-14 46-11-13-45-71.999-55-97.999-45-119-127-262-268.001-462.999-79.454-112.909-351.372-395.77-383.916-404.648-15.213-4.15-21.753 3.519-22.973 4.95-10.284 12.058-33.481 57.543-36.111 62.699-25 48.999-25 48.999 39 119.999 227 255 400 522.999 727.001 1121.997 262 478.999 367 632.999 569.001 835.998 223 223 457.001 363 755.001 453.999 62 18 172 45 246.001 60 255 50 260 53 398 188 27.416 26.713 96.549 135.984 91.28 170.281-5.836 37.986-40.403 88.31-61.28 95.718-60 21-117 14-172-23-233-154-493.001-198.999-759.001-132-231.046 59.726-215.295 112.096-197.999 118.551 20.558 7.673 109.773-22.437 118.999-25.551 69-23 147-41 211-49 303-35 638.001 96 731.001 287 17.399 34.796 27.5 118.497 24.318 168.519-.187 2.935 1.165 34.952-33.318 70.48-19 20-74 56-122 81-66 34-97 57-130 97-143.001 175.999-197.001 211.999-440.001 292.999-256 85-266.001 91-323.001 209.999-52 108-105 166-194 211-52 26-66 29-157 28-79 0-112-5-158-23-80.001-31-165.001-112-211.001-201-29-54-46-75-75-90-21-10-127-36.999-237-59.999-109.001-23-236.001-54-281.001-69-275-94-508.001-317.999-629.001-604.999-84-196.999-123-404.999-131-696.998-7-247.999 7-405.999 59-653.998 126-604.999 147-809.998 114-1130.998-20-203.999-21-419.999-1-543.998 31-191 120-401.999 244.001-579.999 194-278.999 384-465.999 529-519.998 31.001-12 119.001-33 195.001-46 219-39 336-91 424.001-189 24.433-26.76 89.071-130.876 92.685-152.234.813-4.804-7.134-9.134-51.685 32.234-69.001 60-139.001 93-207.001 97-72 4-75-13-9-47 107-55 152-97.999 207.001-195.999 39-71 39-92-1-123-43.037-31.879-112.565-55.358-114.001-56-2.973 27.2 2.123 141.202-142 239-41 28-141 52.999-182 45-41-9-38-21 9-29 57.212-9.393 183.87-117.098 213.165-213.089 10.936-35.836 12.206-50.097-25.181-51.036-303.371-7.619-634.742 99.622-758.985 154.125-455.001 200.999-948.002 619.998-1280.002 1084.997-128.001 180-186.001 275.999-273.001 454.999-20.547 42.358-16.529 44.046-223.453 544.399-3.783 9.148-6.145 7.558-10.547 16.6-1.734-34.853-2.871-34.749.991-69.368 2.194-19.671 19.299-173.023 37.009-244.632 57-221.999 179-509.998 275-646.998 16-23-2-13-69 39-917.435 711.17-1475.182 1332.435-1699.003 1639.996-62.483 85.436-226.566 348.173-226.147 373.616.027 1.616 4.901 10.765 12.046 15.463 21.234 13.96 148.034 52 161.101 55.92 374.001 111.999 628.001 226.999 877.002 398.999 351 241.999 595.001 497.999 956.001 1003.997 234.001 327.999 386.001 526.999 515.001 674.999 105 118.999 128 149.999 143.001 199.999 30 94 71 166 124 217 97 92.999 179 128.999 346 150.999 95 12 136.001 24 252.001 71 511.001 208 912.001 277.999 1328.002 228.999zm-1689.003-378.999c-113-28-202-101.999-257-212.999-44-89-51-211-18-313.999 25-76 82-163 144-216 28-26 46-33 77-33 34 0 41 4 50 28 17 44 4 96-52 206-43 87-52 111.999-52 157.999 0 83 45 149 125 182 54 23 102 20 208.001-14 90-28 178-38 214-24 12 4 16 20 16 54 0 45-3 51-42 85-115 98.999-270.001 135.999-413.001 100.999zm3316.006-898.997c-11-19-66-76-121-127-121.001-111-142.001-147-148.001-253.999-8-128 29-173 139.001-169 67 2 105 19 147 68 74 84 107 185.999 107 334.999 0 142-12 173-66 178-32 3-39-1-58-31zm-326.001 382.999c-74-13-129-35-191-76-63-42-76-62-72-107 5-52 44-56 164-15 96 32 104 33 259 33 160.001 0 160.001 0 163.001 39 4 47-20 76-86 104-56 24-168.001 34-237.001 22zm-1337.002 192.999c77.267-36.6 165.787-185.731 64.4-315.831-100.705-129.224-314.39-78.607-351.676 84.969-35.37 155.169 130.849 302.123 287.276 230.862zm-89.648-46.313c-15.001-10.001-18.335-20.835-18.335-57.503 0-55.837 20.001-79.171 67.504-79.171 42.503 0 55.837 6.667 70.004 34.168 31.669 60.003.834 115.84-64.17 115.84-20.001 0-45.003-5.834-55.003-13.334z" transform="matrix(.003707 0 0 -.00384 .985888 34.380553)"/></g></svg> \ No newline at end of file +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="9.61 6.08 155.22 23.76" xmlns="http://www.w3.org/2000/svg"><g fill="#23262d"><g fill-rule="nonzero" transform="matrix(1.888683 0 0 1.888683 -48.407348 18.08733)"><path d="m49.23-2.043h1.584v6.612h-1.584v-.972c-.216.392-.506.682-.87.87s-.77.282-1.218.282h-.012c-.368 0-.712-.064-1.032-.192s-.6-.316-.84-.564-.43-.558-.57-.93-.21-.806-.21-1.302v-.996c0-.488.07-.918.21-1.29s.33-.684.57-.936.52-.442.84-.57.664-.192 1.032-.192h.012c.448 0 .854.088 1.218.264s.654.448.87.816zm-1.608 5.496c.2 0 .398-.04.594-.12s.368-.202.516-.366.268-.366.36-.606.138-.524.138-.852v-.492c0-.32-.046-.6-.138-.84s-.212-.442-.36-.606-.32-.286-.516-.366-.394-.12-.594-.12h-.012c-.44 0-.808.15-1.104.45s-.444.77-.444 1.41v.66c0 .632.148 1.098.444 1.398s.664.45 1.104.45z"/><path d="m55.338 4.761c-.416 0-.812-.068-1.188-.204s-.708-.338-.996-.606-.516-.6-.684-.996-.252-.85-.252-1.362v-.648c0-.512.084-.966.252-1.362s.396-.73.684-1.002.62-.476.996-.612.772-.204 1.188-.204h.012c.432 0 .83.068 1.194.204s.682.326.954.57.484.536.636.876.236.71.252 1.11h-1.488c-.008-.224-.054-.424-.138-.6s-.196-.326-.336-.45-.3-.22-.48-.288-.374-.102-.582-.102h-.012c-.2 0-.392.036-.576.108s-.348.178-.492.318-.26.316-.348.528-.132.454-.132.726v1.008c0 .272.044.512.132.72s.204.384.348.528.308.252.492.324.376.108.576.108h.012c.208 0 .402-.034.582-.102s.34-.164.48-.288.252-.274.336-.45.13-.372.138-.588h1.488c-.016.4-.1.768-.252 1.104s-.364.624-.636.864-.59.428-.954.564-.762.204-1.194.204z"/><path d="m65.346 2.289c0 .4-.07.752-.21 1.056s-.33.562-.57.774-.518.372-.834.48-.646.162-.99.162h-.024c-.352 0-.682-.054-.99-.162s-.576-.268-.804-.48-.41-.476-.546-.792-.204-.682-.204-1.098v-2.76h-1.068v-1.236h1.068v-1.896h1.572v1.896h2.784v1.236h-2.784v2.82c0 .4.11.704.33.912s.47.312.75.312h.012c.28 0 .528-.104.744-.312s.324-.512.324-.912z"/><path d="m67.002-2.979c-.264 0-.49-.092-.678-.276s-.282-.412-.282-.684.094-.5.282-.684.414-.276.678-.276c.256 0 .478.092.666.276s.282.412.282.684-.094.5-.282.684-.41.276-.666.276zm-.792 7.548v-6.612h1.572v6.612z"/><path d="m72.27 4.761c-.416 0-.814-.068-1.194-.204s-.714-.336-1.002-.6-.516-.592-.684-.984-.252-.844-.252-1.356v-.684c0-.52.084-.978.252-1.374s.396-.726.684-.99.622-.464 1.002-.6.778-.204 1.194-.204h.012c.416 0 .812.068 1.188.204s.708.336.996.6.516.594.684.99c.168.396.252.854.252 1.374v.684c0 .512-.084.964-.252 1.356s-.396.72-.684.984-.62.464-.996.6-.772.204-1.188.204zm.012-1.308c.2 0 .392-.036.576-.108s.348-.18.492-.324.258-.32.342-.528.126-.448.126-.72v-1.008c0-.272-.042-.514-.126-.726s-.198-.388-.342-.528-.308-.246-.492-.318-.376-.108-.576-.108h-.012c-.2 0-.392.036-.576.108s-.348.178-.492.318-.26.316-.348.528-.132.454-.132.726v1.008c0 .272.044.512.132.72s.204.384.348.528.308.252.492.324.376.108.576.108z"/><path d="m80.454-2.235c.344 0 .664.058.96.174s.556.286.78.51.4.502.528.834.192.718.192 1.158v4.128h-1.572v-3.936c0-.536-.132-.93-.396-1.182s-.596-.378-.996-.378h-.012c-.2 0-.392.036-.576.108s-.348.184-.492.336-.26.346-.348.582-.132.518-.132.846v3.624h-1.584v-6.612h1.584v.876c.232-.376.526-.648.882-.816s.746-.252 1.17-.252z"/><path d="m88.242-2.223c.368 0 .712.064 1.032.192s.6.318.84.57.43.564.57.936.21.802.21 1.29v.996c0 .496-.07.93-.21 1.302s-.33.682-.57.93-.52.436-.84.564-.664.192-1.032.192h-.012c-.448 0-.852-.086-1.212-.258s-.652-.446-.876-.822v.9h-1.584v-9.084h1.584v3.456c.224-.392.516-.684.876-.876s.764-.288 1.212-.288zm1.068 3.168c0-.64-.148-1.11-.444-1.41s-.664-.45-1.104-.45h-.012c-.208 0-.408.04-.6.12s-.362.202-.51.366-.268.366-.36.606-.138.52-.138.84v.492c0 .328.046.612.138.852s.212.442.36.606.318.286.51.366.392.12.6.12h.012c.44 0 .808-.15 1.104-.45s.444-.766.444-1.398z"/><path d="m96.75-2.043h1.584v6.612h-1.584v-.972c-.216.392-.506.682-.87.87s-.77.282-1.218.282h-.012c-.368 0-.712-.064-1.032-.192s-.6-.316-.84-.564-.43-.558-.57-.93-.21-.806-.21-1.302v-.996c0-.488.07-.918.21-1.29s.33-.684.57-.936.52-.442.84-.57.664-.192 1.032-.192h.012c.448 0 .854.088 1.218.264s.654.448.87.816zm-1.608 5.496c.2 0 .398-.04.594-.12s.368-.202.516-.366.268-.366.36-.606.138-.524.138-.852v-.492c0-.32-.046-.6-.138-.84s-.212-.442-.36-.606-.32-.286-.516-.366-.394-.12-.594-.12h-.012c-.44 0-.808.15-1.104.45s-.444.77-.444 1.41v.66c0 .632.148 1.098.444 1.398s.664.45 1.104.45z"/><path d="m102.51 4.761c-.424 0-.814-.056-1.17-.168s-.66-.272-.912-.48-.448-.456-.588-.744-.21-.608-.21-.96h1.44c.016.136.062.272.138.408s.18.258.312.366.288.194.468.258.386.096.618.096h.012c.36 0 .638-.07.834-.21s.294-.314.294-.522c0-.184-.064-.338-.192-.462s-.372-.226-.732-.306l-.96-.24c-.264-.064-.52-.146-.768-.246s-.466-.226-.654-.378-.34-.334-.456-.546-.174-.462-.174-.75c0-.312.062-.598.186-.858s.3-.484.528-.672.506-.332.834-.432.696-.15 1.104-.15h.012c.408 0 .778.056 1.11.168s.618.272.858.48.426.456.558.744.198.608.198.96h-1.428c-.016-.144-.06-.282-.132-.414s-.168-.252-.288-.36-.26-.194-.42-.258-.34-.096-.54-.096h-.012c-.336 0-.594.074-.774.222s-.27.322-.27.522c0 .176.074.324.222.444s.386.22.714.3l.972.24c.288.064.558.148.81.252s.468.234.648.39.322.344.426.564.156.482.156.786c0 .32-.068.606-.204.858s-.324.466-.564.642-.53.312-.87.408-.714.144-1.122.144z"/><path d="m109.482-2.235c.408 0 .794.066 1.158.198s.684.33.96.594.496.594.66.99c.164.396.246.858.246 1.386v.732h-4.668v.12c0 .288.044.54.132.756s.21.396.366.54.336.254.54.33.422.114.654.114h.012c.416 0 .76-.1 1.032-.3s.428-.48.468-.84h1.464c-.032.304-.12.6-.264.888s-.342.542-.594.762-.556.396-.912.528-.758.198-1.206.198h-.024c-.448 0-.866-.068-1.254-.204s-.73-.338-1.026-.606-.528-.6-.696-.996-.252-.85-.252-1.362v-.648c0-.512.086-.966.258-1.362s.404-.73.696-1.002.632-.476 1.02-.612.794-.204 1.218-.204zm-.024 1.248c-.208 0-.406.036-.594.108s-.358.18-.51.324-.274.32-.366.528-.142.448-.15.72h3.132c0-.288-.04-.538-.12-.75s-.188-.386-.324-.522-.294-.238-.474-.306-.374-.102-.582-.102z"/></g><g id="otter" transform="translate(7.4776 -0.9994) scale(0.90862)"><path d="m5304.009 6694.985c243-28.999 445.001-77.999 640.001-155.999 261.001-105 434.001-234 646.001-480.999 62-72 116-118 247.001-206.999 51-35 108-77 126-94 148-139 210-421.999 142-651.999-41-137.999-66-175.999-215-324.999-75-74-160.001-165.999-190.001-202.999-110-138-212-191-516.001-271-249-64.999-349-99.999-467-163.999-249.001-135-431.001-308.999-579.001-554.999-67-111-92-192.999-93-296.999 0-109 33-189 98-235 129-92.999 255-159.999 491.001-261.999 618.001-266.999 958.001-549.998 1162.002-967.997 52.337-107.376 232.316-487.867 40-709.999-26-30-26-30-18 15 2.633 16.459 7.838 161.674 3.375 240.25-1.125 19.809-14.243 35.242-16.375 37.75-1.917 2.092-26.445 28.849-28.78 20.73-1.35-4.693-6.221-21.633-6.221-60.73-1-130-61-319-112-346.999-24-14-32-13-82 2-4.766 1.537-55.503 17.903-55.855 28.262-.378 11.146 17.796 35.929 19.855 38.737 33 47 52 111 53 185 1.086 70.578-22.279 134.84-32 135-7.451.123-18.973-62.423-20-68-18.044-98.768-82.324-210.727-108.906-220.548-21.407-7.909-100.27 87.37-124.094 138.548-14 30-42 115-62 188.999-40 147-67.001 205-130.001 279-116 135.999-266 208.999-565.001 272.999-146 31-392 37-608.001 14-221-24-306-15-430 44-56.786 27.159-74.086 42.845-83 48l15 30c75 107.999 189 409.999 199 527.998 5 70 5 70-14 46-11-13-45-71.999-55-97.999-45-119-127-262-268.001-462.999-79.454-112.909-351.372-395.77-383.916-404.648-15.213-4.15-21.753 3.519-22.973 4.95-10.284 12.058-33.481 57.543-36.111 62.699-25 48.999-25 48.999 39 119.999 227 255 400 522.999 727.001 1121.997 262 478.999 367 632.999 569.001 835.998 223 223 457.001 363 755.001 453.999 62 18 172 45 246.001 60 255 50 260 53 398 188 27.416 26.713 96.549 135.984 91.28 170.281-5.836 37.986-40.403 88.31-61.28 95.718-60 21-117 14-172-23-233-154-493.001-198.999-759.001-132-231.046 59.726-215.295 112.096-197.999 118.551 20.558 7.673 109.773-22.437 118.999-25.551 69-23 147-41 211-49 303-35 638.001 96 731.001 287 17.399 34.796 27.5 118.497 24.318 168.519-.187 2.935 1.165 34.952-33.318 70.48-19 20-74 56-122 81-66 34-97 57-130 97-143.001 175.999-197.001 211.999-440.001 292.999-256 85-266.001 91-323.001 209.999-52 108-105 166-194 211-52 26-66 29-157 28-79 0-112-5-158-23-80.001-31-165.001-112-211.001-201-29-54-46-75-75-90-21-10-127-36.999-237-59.999-109.001-23-236.001-54-281.001-69-275-94-508.001-317.999-629.001-604.999-84-196.999-123-404.999-131-696.998-7-247.999 7-405.999 59-653.998 126-604.999 147-809.998 114-1130.998-20-203.999-21-419.999-1-543.998 31-191 120-401.999 244.001-579.999 194-278.999 384-465.999 529-519.998 31.001-12 119.001-33 195.001-46 219-39 336-91 424.001-189 24.433-26.76 89.071-130.876 92.685-152.234.813-4.804-7.134-9.134-51.685 32.234-69.001 60-139.001 93-207.001 97-72 4-75-13-9-47 107-55 152-97.999 207.001-195.999 39-71 39-92-1-123-43.037-31.879-112.565-55.358-114.001-56-2.973 27.2 2.123 141.202-142 239-41 28-141 52.999-182 45-41-9-38-21 9-29 57.212-9.393 183.87-117.098 213.165-213.089 10.936-35.836 12.206-50.097-25.181-51.036-303.371-7.619-634.742 99.622-758.985 154.125-455.001 200.999-948.002 619.998-1280.002 1084.997-128.001 180-186.001 275.999-273.001 454.999-20.547 42.358-16.529 44.046-223.453 544.399-3.783 9.148-6.145 7.558-10.547 16.6-1.734-34.853-2.871-34.749.991-69.368 2.194-19.671 19.299-173.023 37.009-244.632 57-221.999 179-509.998 275-646.998 16-23-2-13-69 39-917.435 711.17-1475.182 1332.435-1699.003 1639.996-62.483 85.436-226.566 348.173-226.147 373.616.027 1.616 4.901 10.765 12.046 15.463 21.234 13.96 148.034 52 161.101 55.92 374.001 111.999 628.001 226.999 877.002 398.999 351 241.999 595.001 497.999 956.001 1003.997 234.001 327.999 386.001 526.999 515.001 674.999 105 118.999 128 149.999 143.001 199.999 30 94 71 166 124 217 97 92.999 179 128.999 346 150.999 95 12 136.001 24 252.001 71 511.001 208 912.001 277.999 1328.002 228.999zm-1689.003-378.999c-113-28-202-101.999-257-212.999-44-89-51-211-18-313.999 25-76 82-163 144-216 28-26 46-33 77-33 34 0 41 4 50 28 17 44 4 96-52 206-43 87-52 111.999-52 157.999 0 83 45 149 125 182 54 23 102 20 208.001-14 90-28 178-38 214-24 12 4 16 20 16 54 0 45-3 51-42 85-115 98.999-270.001 135.999-413.001 100.999zm3316.006-898.997c-11-19-66-76-121-127-121.001-111-142.001-147-148.001-253.999-8-128 29-173 139.001-169 67 2 105 19 147 68 74 84 107 185.999 107 334.999 0 142-12 173-66 178-32 3-39-1-58-31zm-326.001 382.999c-74-13-129-35-191-76-63-42-76-62-72-107 5-52 44-56 164-15 96 32 104 33 259 33 160.001 0 160.001 0 163.001 39 4 47-20 76-86 104-56 24-168.001 34-237.001 22zm-1337.002 192.999c77.267-36.6 165.787-185.731 64.4-315.831-100.705-129.224-314.39-78.607-351.676 84.969-35.37 155.169 130.849 302.123 287.276 230.862zm-89.648-46.313c-15.001-10.001-18.335-20.835-18.335-57.503 0-55.837 20.001-79.171 67.504-79.171 42.503 0 55.837 6.667 70.004 34.168 31.669 60.003.834 115.84-64.17 115.84-20.001 0-45.003-5.834-55.003-13.334z" transform="matrix(.003707 0 0 -.00384 .985888 34.380553)"/></g></g></svg> \ No newline at end of file diff --git a/website/src/assets/robots.txt b/website/src/assets/robots.txt deleted file mode 100644 index 0081d7a6f..000000000 --- a/website/src/assets/robots.txt +++ /dev/null @@ -1,4 +0,0 @@ -User-agent: * -Allow: / - -Sitemap: https://starlight.astro.build/sitemap-index.xml diff --git a/website/src/components/Footer.astro b/website/src/components/Footer.astro new file mode 100644 index 000000000..a3439e5ea --- /dev/null +++ b/website/src/components/Footer.astro @@ -0,0 +1,49 @@ +--- +// Keeps Starlight's footer (pagination, last-updated, edit link) and appends a +// mono footer bar matching the landing, for a consistent close on every page. +import StarlightFooter from '@astrojs/starlight/components/Footer.astro'; +--- + +<StarlightFooter /> + +<div class="ab-footer"> + <span>© 2026 Kakao Corp. · Apache-2.0</span> + <a href="https://github.com/kakao/actionbase" target="_blank" rel="noopener">GitHub</a> +</div> + +<style> + .ab-footer { + /* Span from the nav-menu divider (left) to the viewport edge (right) so the + bar's top rule meets the vertical divider with no gap, and never covers + the menu itself. (+scrollbar correction so the left edge lands on the + divider.) */ + margin-left: calc(50% - 50vw + var(--sl-sidebar-width) + 31px); + margin-right: calc(50% - 50vw); + box-sizing: border-box; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 1rem; + margin-top: 2.5rem; + padding: 1.25rem clamp(1.5rem, 4vw, 4rem); + border-top: 1px solid var(--sl-color-hairline); + font-family: var(--sl-font-mono); + font-size: 0.75rem; + color: var(--sl-color-gray-3); + } + .ab-footer a { + color: var(--sl-color-gray-3); + } + .ab-footer a:hover { + color: var(--sl-color-text-accent); + } + @media (max-width: 50rem) { + .ab-footer { + width: 100%; + margin-left: 0; + margin-right: 0; + padding: 1.25rem 0; + } + } +</style> diff --git a/website/src/components/Head.astro b/website/src/components/Head.astro index ac0e64211..e62f3b0c4 100644 --- a/website/src/components/Head.astro +++ b/website/src/components/Head.astro @@ -8,41 +8,38 @@ import StarlightHead from '@astrojs/starlight/components/Head.astro'; <link rel="icon" class="js-site-favicon" href="/favicon.svg" type="image/svg+xml"> +<!-- Keep the favicon in sync with the effective theme (html[data-theme]), + which Starlight sets before paint and both theme toggles update. --> <script is:inline> - (function() { + (function () { const updateFavicon = () => { - const isDark = - localStorage.theme === 'dark' || - (!localStorage.theme && window.matchMedia('(prefers-color-scheme: dark)').matches); - + const isDark = document.documentElement.dataset.theme === 'dark'; const favicon = document.querySelector('.js-site-favicon'); - if (favicon) { - favicon.href = isDark ? '/favicon-dark.svg' : '/favicon.svg'; - } + if (favicon) favicon.href = isDark ? '/favicon-dark.svg' : '/favicon.svg'; }; - updateFavicon(); - + window.addEventListener('theme-change', updateFavicon); window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateFavicon); })(); </script> -<script> - const BADGE_URL = 'https://img.shields.io/github/stars/kakao/actionbase?style=flat&logo=github&label=&color=rgba(0%2C0%2C0%2C0)&labelColor=rgba(0%2C0%2C0%2C0)'; - - function render() { - document.querySelectorAll('.nav-external').forEach((el) => { - if (el.querySelector('.gh-badge')) return; - const img = document.createElement('img'); - img.src = BADGE_URL; - img.alt = 'GitHub stars'; - img.className = 'gh-badge'; - img.loading = 'lazy'; - el.textContent = ''; - el.appendChild(img); - }); - } - - render(); - document.addEventListener('astro:after-swap', render); +<!-- Live GitHub star count in the header's GitHub pill, matching the landing + nav. Fails silently (rate limits, offline), leaving the plain icon. --> +<script is:inline> + window.addEventListener('DOMContentLoaded', () => { + const link = document.querySelector('.social-icons a[href*="github.com"]'); + if (!link) return; + fetch('https://api.github.com/repos/kakao/actionbase') + .then((r) => (r.ok ? r.json() : null)) + .then((repo) => { + const count = repo && repo.stargazers_count; + if (typeof count !== 'number') return; + const el = document.createElement('span'); + el.className = 'gh-count'; + el.textContent = count >= 1000 ? `★ ${(count / 1000).toFixed(1).replace(/\.0$/, '')}k` : `★ ${count}`; + link.prepend(el); + link.classList.add('has-count'); + }) + .catch(() => {}); + }); </script> diff --git a/website/src/components/ThemeSelect.astro b/website/src/components/ThemeSelect.astro new file mode 100644 index 000000000..fd08b6540 --- /dev/null +++ b/website/src/components/ThemeSelect.astro @@ -0,0 +1,52 @@ +--- +// Round light/dark toggle, replacing Starlight's dropdown so the docs header +// matches the landing. Reads/writes the shared `starlight-theme` key and the +// `<html data-theme>` attribute, so the choice carries across both surfaces. +// SVG icons (not ☾/☀ glyphs) so no font fallback can turn them into emoji; +// they swap via CSS on html[data-theme]. +import { Moon, Sun } from '@lucide/astro'; +--- + +<button type="button" class="theme-toggle" aria-label="Toggle color theme" data-theme-toggle> + <Moon class="theme-icon-moon" size={16} aria-hidden="true" /> + <Sun class="theme-icon-sun" size={16} aria-hidden="true" /> +</button> + +<style> + /* Match the landing nav toggle exactly: transparent fill, hairline ring. */ + .theme-toggle { + display: inline-flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + border-radius: 999px; + border: 1px solid var(--sl-color-hairline-light); + background: transparent; + color: var(--sl-color-gray-2); + cursor: pointer; + } + .theme-toggle:hover { + border-color: var(--sl-color-gray-4); + } + :global(:root[data-theme='dark']) .theme-toggle :global(.theme-icon-moon), + :global(:root[data-theme='light']) .theme-toggle :global(.theme-icon-sun) { + display: none; + } +</style> + +<script> + const root = document.documentElement; + document.querySelectorAll('[data-theme-toggle]').forEach((btn) => { + btn.addEventListener('click', () => { + const next = root.dataset.theme === 'dark' ? 'light' : 'dark'; + root.dataset.theme = next; + try { + localStorage.setItem('starlight-theme', next); + } catch { + /* ignore */ + } + window.dispatchEvent(new Event('theme-change')); + }); + }); +</script> diff --git a/website/src/components/about-astro.astro b/website/src/components/about-astro.astro deleted file mode 100644 index 665d11258..000000000 --- a/website/src/components/about-astro.astro +++ /dev/null @@ -1,48 +0,0 @@ ---- -interface Props { - title: string; -} - -const { title } = Astro.props; ---- - -<article class="sl-flex" aria-labelledby="about-astro-heading"> - <small id="about-astro-heading"> - {title} - <span class="sr-only">Astro</span> - </small> - <svg - aria-hidden="true" - xmlns="http://www.w3.org/2000/svg" - viewBox="0 0 301 79" - fill="var(--sl-color-white)" - > - <path - d="M20.8 66.8c-3.6-3.2-4.6-10-3.1-15 2.5 3.2 6.1 4.2 9.8 4.7 5.7.9 11.3.6 16.5-2l1.9-1.1a9 9 0 0 1 .4 4.3 12 12 0 0 1-5 8.5l-3.6 2.4c-3.6 2.4-4.6 5.3-3.2 9.4l.1.5c-1.8-.8-3.2-2-4.2-3.6-1-1.7-1.6-3.5-1.6-5.5 0-1 0-2-.2-3-.3-2.3-1.4-3.3-3.4-3.4a4 4 0 0 0-4.3 3.3l-.1.5ZM.5 51s10.5-5 21-5l8-24.6c.3-1.2 1.2-2 2.2-2 1 0 1.8.8 2.1 2l8 24.5c12.5 0 21 5.1 21 5.1L45 2.4C44.4.9 43.6 0 42.4 0H21c-1.2 0-2 1-2.6 2.4L.5 51Zm111-7c0 4.3-5.4 6.8-12.8 6.8-4.9 0-6.6-1.2-6.6-3.7 0-2.6 2.1-3.9 7-3.9 4.3 0 8 .1 12.4.6v.2Zm0-5.4a56 56 0 0 0-11.4-1c-14 0-20.5 3.4-20.5 11 0 8 4.5 11 14.9 11 8.8 0 14.7-2.2 17-7.6h.3l-.2 3.6c0 2.8.5 3 2.8 3h10.9c-.6-1.6-1-6.3-1-10.4l.2-12c0-9.1-5.4-14.8-22.4-14.8a83 83 0 0 0-21.7 3C81 27 82 32 82.3 35.2c5.3-2.5 13-3.6 18.8-3.6 8.2 0 10.4 1.9 10.4 5.6v1.5Zm29.8 7.9c-1.5.2-3.5.2-5.5.2-2.2 0-4.2-.1-5.6-.3V48c0 7.5 4.9 11.8 22 11.8 16.3 0 21.6-4.3 21.6-11.8 0-7.2-3.5-10.8-19-11.5-11.9-.6-13-1.9-13-3.4 0-1.7 1.6-2.6 9.6-2.6 8.3 0 10.6 1.1 10.6 3.5v.6a120.9 120.9 0 0 1 11 0l.1-1.4c0-8.8-7.3-11.7-21.5-11.7-15.9 0-21.3 4-21.3 11.5 0 6.8 4.3 11 19.6 11.7 11.3.4 12.5 1.6 12.5 3.4 0 1.8-1.8 2.7-9.7 2.7-9 0-11.4-1.3-11.4-3.9v-.3ZM193.2 15c-4.3 4-12 8-16.3 9v8.5l4 .1-.1 12.8c0 8 4.2 14 17.2 14 5.5 0 9.1-.7 13.7-1.6-.5-3-1-7.4-1.2-10.8-2.7.9-6.1 1.3-10 1.3-5.2 0-7.3-1.4-7.3-5.5v-10l17.5.2c0-3 0-7.6.2-10.6-5.7.2-12.1.2-17.4.2l.1-7.6h-.4Zm35.3 15.8.1-8.4h-11.8a752.4 752.4 0 0 1 0 36.2h13.5c-.2-3.5-.3-9.6-.3-14.7 0-8.1 3.3-10.5 10.8-10.5 3.5 0 6 .5 8.2 1.2 0-3 .6-9 1-11.6-2.3-.6-4.7-1-7.7-1-6.5-.1-11.2 2.5-13.4 8.8h-.4Zm59 9.5c0 6.5-4.7 9.6-12.1 9.6-7.4 0-12.1-2.9-12.1-9.6 0-6.7 4.8-9.2 12-9.2 7.4 0 12.2 2.7 12.2 9.2Zm12.3-.3c0-13-10.1-18.8-24.4-18.8-14.4 0-24.2 5.8-24.2 18.8s9.1 20 24.1 20c15.1 0 24.5-7 24.5-19.9Z" - > - </path> - </svg> - <slot /> -</article> - -<style> - article { - max-width: 40rem; - margin-inline: auto; - padding-block: 5rem; - flex-direction: column; - align-items: center; - text-align: center; - gap: 0.5rem; - } - article > :global(*) { - max-width: 50ch; - margin-top: 0 !important; - } - small { - color: var(--sl-color-gray-3); - } - svg { - width: 15rem; - } -</style> diff --git a/website/src/components/component-preview.astro b/website/src/components/component-preview.astro deleted file mode 100644 index 41d71815f..000000000 --- a/website/src/components/component-preview.astro +++ /dev/null @@ -1,49 +0,0 @@ ---- -import { Tabs, TabItem } from '@astrojs/starlight/components'; - -const showContentTypeTabs = Astro.slots.has('markdoc'); ---- - -<figure> - { - showContentTypeTabs ? ( - <Tabs syncKey="content-type"> - <TabItem label="MDX"> - <slot /> - </TabItem> - <TabItem label="Markdoc"> - <slot name="markdoc" /> - </TabItem> - </Tabs> - ) : ( - <slot /> - ) - } - <div class="preview"> - <figcaption>{Astro.locals.t('component.preview')}</figcaption> - <div class="preview-content"><slot name="preview" /></div> - </div> -</figure> - -<style> - :global(.sl-markdown-content) .preview { - border: 1px solid var(--sl-color-gray-5); - border-top: none; - margin-top: 0; - } - - .preview:only-child { - border-top: 1px solid var(--sl-color-gray-5); - } - - figcaption { - font-size: var(--sl-text-sm); - font-weight: 600; - padding: 0.5rem 1rem 0; - } - - :global(.sl-markdown-content) .preview-content { - margin-top: 0; - padding: 1rem; - } -</style> diff --git a/website/src/components/fluid-grid.astro b/website/src/components/fluid-grid.astro deleted file mode 100644 index 2be8b70e4..000000000 --- a/website/src/components/fluid-grid.astro +++ /dev/null @@ -1,22 +0,0 @@ ---- -interface Props { - minColumnWidth?: string; - gap?: string; -} -const { minColumnWidth, gap } = Astro.props; ---- - -<ul class="fluid-grid"><slot /></ul> - -<style define:vars={{ minColumnWidth, gap }}> - .fluid-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--minColumnWidth, 11rem)), 1fr)); - gap: var(--gap, 1rem); - list-style: none; - padding: 0; - } - .fluid-grid > :global(*) { - margin-top: 0 !important; - } -</style> diff --git a/website/src/components/icons-list.astro b/website/src/components/icons-list.astro deleted file mode 100644 index 193c0cc6e..000000000 --- a/website/src/components/icons-list.astro +++ /dev/null @@ -1,77 +0,0 @@ ---- -import { Icon } from '@astrojs/starlight/components'; -import { Icons, type StarlightIcon } from '@astrojs/starlight/components'; - -interface Props { - labels?: { - copied?: string; - }; -} - -const { copied = 'Copied!' } = Astro.props.labels ?? {}; - -const icons = Object.keys(Icons) as StarlightIcon[]; ---- - -<div class="icons-grid" data-label-copied={copied}> - { - icons.map((icon) => { - return ( - <button class="icon-preview" aria-label={`Copy ${icon} icon to clipboard`} data-name={icon}> - <Icon name={icon} size="1.5rem" /> - <span aria-live="polite">{icon}</span> - </button> - ); - }) - } -</div> - -<script> - const iconGrid = document.querySelector<HTMLDivElement>('.icons-grid'); - const copiedLabel = document.querySelector<HTMLDivElement>('.icons-grid')?.dataset.labelCopied!; - iconGrid?.addEventListener('click', (event) => { - if (!(event.target instanceof Element)) return; - const icon = event.target.closest('.icon-preview'); - if (!(icon instanceof HTMLButtonElement)) return; - const iconName = icon.dataset.name!; - navigator.clipboard.writeText(iconName); - - const iconLabel = icon.querySelector('[aria-live]'); - if (iconLabel) { - iconLabel.textContent = copiedLabel; - setTimeout(() => { - iconLabel.textContent = iconName; - }, 1000); - } - }); -</script> - -<style> - .icons-grid { - display: grid; - gap: 1rem; - grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); - } - - .icons-grid .icon-preview { - align-items: center; - justify-content: center; - text-align: center; - border: 1px solid var(--sl-color-gray-5); - display: flex; - flex-direction: column; - font-size: var(--sl-text-sm); - gap: 0.25rem; - margin: 0; - overflow-wrap: anywhere; - padding: 0.75rem; - background: none; - } - - .icon-preview:hover, - .icon-preview:focus { - cursor: pointer; - border: 1px solid var(--sl-color-gray-3); - background: var(--sl-color-gray-7, var(--sl-color-gray-6)); - } -</style> diff --git a/website/src/components/landing/ArchDiagram.astro b/website/src/components/landing/ArchDiagram.astro new file mode 100644 index 000000000..3322b479b --- /dev/null +++ b/website/src/components/landing/ArchDiagram.astro @@ -0,0 +1,46 @@ +--- +// Both paths converge on one wide Storage Backend. Kafka sits on the write +// side only (WAL in, CDC out); the read path (Query doc) is a direct lookup. +const storageNode = { name: 'Storage Backend', sub: 'state · index · count — HBase / SlateDB' }; +--- + +<div class="arch-panel"> + <svg + class="arch-svg" + viewBox="0 0 620 448" + role="img" + aria-label="Client to Actionbase; write path through Kafka and read path through GET/COUNT/SCAN converge on one storage backend, which streams back out through Kafka." + > + <!-- connectors (broken around labels so lines never cross text) --> + <path + class="arch-line" + d="M310 52 V80 M310 124 V152 M155 152 H465 M155 152 V180 M465 152 V196 M465 228 V286 M155 226 V286 M155 334 V390" + /> + <!-- flow labels --> + <text class="arch-lbl arch-lbl-rest" x="328" y="69">REST · HTTP</text> + <text class="arch-lbl" x="155" y="145">WRITE PATH</text> + <text class="arch-lbl" x="465" y="145">READ PATH</text> + <!-- read requests: an operation on the path, not a component --> + <text class="arch-req" x="465" y="207">GET · COUNT · SCAN</text> + <text class="arch-sub" x="465" y="220">direct read</text> + <!-- nodes --> + <rect class="arch-box" x="255" y="12" width="110" height="40" rx="6" /> + <text class="arch-t" x="310" y="37">Client</text> + + <rect class="arch-box arch-box-accent" x="240" y="80" width="140" height="44" rx="6" /> + <text class="arch-t arch-t-accent" x="310" y="107">Actionbase</text> + + <rect class="arch-box" x="88" y="180" width="134" height="46" rx="6" /> + <text class="arch-t" x="155" y="201">Kafka</text> + <text class="arch-sub" x="155" y="216">write WAL</text> + + <rect class="arch-box" x="85" y="286" width="450" height="48" rx="6" /> + <text class="arch-t" x="310" y="307">{storageNode.name}</text> + <text class="arch-sub" x="310" y="322">{storageNode.sub}</text> + + <rect class="arch-box" x="88" y="390" width="134" height="44" rx="6" /> + <text class="arch-t" x="155" y="411">Kafka</text> + <text class="arch-sub" x="155" y="426">write CDC</text> + </svg> + <div class="fig-cap">Fig. 03 — write / read paths</div> +</div> diff --git a/website/src/components/landing/DemoSection.astro b/website/src/components/landing/DemoSection.astro new file mode 100644 index 000000000..749f1c6d3 --- /dev/null +++ b/website/src/components/landing/DemoSection.astro @@ -0,0 +1,164 @@ +--- +// Live console + edge graph. A self-contained command parser in the page +// script (index.astro) drives both panels via [data-*] hooks. +import { RotateCcw } from '@lucide/astro'; + +// ASCII otter banner, coloured to mirror the real CLI welcome art (ANSI 33): +// the otter body stays the default terminal foreground; the frame, the heart, +// the right-hand info labels and the "Actionbase" wordmark are gold. Each line +// is a list of [text, gold?] segments — concatenated they reproduce the raw +// art, and gold runs are wrapped in a <span class="g"> at build time. +const G = true; +const bannerSegs = [ + [[' _____________', false]], + [[' __/ ___ \\ Welcome to Actionbase! v0.2.1', false]], + [[' _/\\ ____/ \\____\\_', false]], + [[' / \\/ _/ @ \\_', false], ['♥/', G], ['\\ ', false], ['Actionbase standalone:8080', G]], + [[' / / | |', false]], + [[' _/ / ___/ \\/ ', false], ['proxy', G], [' off', false]], + [[' / | ______/ ', false], ['debug', G], [' off', false]], + [[' __/ | /', false]], + [[' ___/ \\ _/', false]], + [[' | /\\__', false]], + [[' | / \\__', false], [' _ _ _ _', G]], + [[' | /______ \\', false], [' / \\ ___| |_(_) ___ _ __ | |__ __ _ ___ ___', G]], + [[" \\ \\_ \\ \\", false], [" / _ \\ / __| __| |/ _ \\| '_ \\| '_ \\ / _` / __|/ _ \\", G]], + [[" \\__ \\__ |_|", false], [" / ___ \\ (__| |_| | (_) | | | | |_) | (_| \\__ \\ __/", G]], + [[' \\____\\', false], [' /_/ \\_\\___|\\__|_|\\___/|_| |_|_.__/ \\__,_|___/\\___|', G]], +]; +const escHtml = (s) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); +const goldSpan = (s) => `<span class="g">${escHtml(s)}</span>`; +// The real CLI draws its frame with box-drawing chars, but the Google Fonts +// JetBrains Mono subset lacks U+2500-257F, so those glyphs fall back to the +// system mono whose advance differs — the frame ends up ~2px wider than the +// art. A CSS border reproduces the gold frame pixel-exactly instead. +const banner = bannerSegs + .map((segs) => segs.map(([t, g]) => (g ? goldSpan(t) : escHtml(t))).join('')) + .join('\n'); + +const presets = [ + { cmd: 'get --source Alice --target Phone', desc: 'Fetch a single edge' }, + { cmd: 'scan --index recent --start Bob --direction OUT', desc: 'List edges, newest first' }, + { cmd: 'count --start Phone --direction IN', desc: 'Count edges on a node' }, +]; + +// Teaser for query operations that exist internally but aren't shipped yet — +// shown disabled ("TBD") to hint at what's coming. topk covers issue #369 +// shapes 2 (Target|Window) and 4 (Target|Filter,Window). +const soon = [ + { cmd: 'agg --start Phone --direction IN --by hour --last 1d', desc: 'Aggregate edges over time' }, + { cmd: 'topk --target product --edge purchase --last 1w', desc: 'Trending items this week' }, + { cmd: 'topk --start Bob --target product --edge purchase --last 1y', desc: "A user's recent purchases" }, + { cmd: 'multihop --start Alice --path follow,wish', desc: "Friends' wishes, across hops" }, +]; +--- + +<section class="demo"> + <div class="demo-head"> + <h2>Interactive demo</h2> + <button type="button" class="demo-reset" data-reset> + <RotateCcw size={15} aria-hidden="true" /> + <span>Reset</span> + </button> + </div> + <div class="demo-panels"> + <figure class="console term-fill"> + <div data-console> + <div class="term"> + <div class="term-bar"> + <span class="dot"></span><span class="dot"></span><span class="dot"></span> + <span class="term-title">actionbase cli</span> + </div> + <div class="term-body"> + <pre class="banner" set:html={banner}></pre> + <div data-lines role="log" aria-live="polite"> + <div class="line"><span class="l l-sys">actionbase standalone · server :8080 · CLI ready</span></div> + <div class="line"><span class="l l-sys">preset 'likes' loaded — 3 edges</span></div> + <div class="line"><span class="l l-sys">Alice → Phone Bob → Laptop Bob → Phone</span></div> + <div class="line"><span class="l l-dim">click a command below to run it ↓</span></div> + </div> + <div class="input-row"> + <span class="prompt">actionbase(likes:likes)></span> + <span class="term-cursor" aria-hidden="true"></span> + <span class="term-hint">click a command below ↓</span> + </div> + </div> + </div> + </div> + </figure> + + <figure class="graph panel"> + <svg class="graph-svg" viewBox="0 0 340 250" role="img" aria-label="Edge state graph" data-graph> + <g class="gedge" data-edge="alice-phone" data-src="alice" data-dst="phone"> + <line x1="118" y1="72" x2="222" y2="66" /> + <text class="gedge-label" x="168" y="61">likes</text> + </g> + <g class="gedge" data-edge="bob-phone" data-src="bob" data-dst="phone"> + <line x1="118" y1="176" x2="222" y2="72" /> + <text class="gedge-label" x="150" y="120">likes</text> + </g> + <g class="gedge" data-edge="bob-laptop" data-src="bob" data-dst="laptop"> + <line x1="118" y1="180" x2="222" y2="184" /> + <text class="gedge-label" x="168" y="176">likes</text> + </g> + <g class="gnode gnode-user" data-node="alice"> + <rect x="24" y="52" width="94" height="40" rx="9" /> + <text class="gn-name" x="71" y="70">Alice</text> + <text class="gn-type" x="71" y="83">user</text> + </g> + <g class="gnode gnode-user" data-node="bob"> + <rect x="24" y="156" width="94" height="40" rx="9" /> + <text class="gn-name" x="71" y="174">Bob</text> + <text class="gn-type" x="71" y="187">user</text> + </g> + <g class="gnode gnode-item" data-node="phone"> + <rect x="222" y="46" width="94" height="40" rx="9" /> + <text class="gn-name" x="269" y="64">Phone</text> + <text class="gn-type" x="269" y="77">item</text> + </g> + <g class="gnode gnode-item" data-node="laptop"> + <rect x="222" y="164" width="94" height="40" rx="9" /> + <text class="gn-name" x="269" y="182">Laptop</text> + <text class="gn-type" x="269" y="195">item</text> + </g> + </svg> + <figcaption class="fig-cap">Fig. 02 — live edge state</figcaption> + </figure> + </div> + + <div class="demo-controls"> + <!-- Toggle buttons, not ARIA tabs: the full tabs pattern needs + tabpanel wiring + arrow-key navigation, which two buttons + don't earn. aria-pressed conveys the state instead. --> + <div class="tabs" data-tabs> + <button type="button" class="tab active" data-tab="supported" aria-pressed="true"> + Supported + </button> + <button type="button" class="tab" data-tab="soon" aria-pressed="false"> + Coming soon + </button> + </div> + <div class="tab-panel" data-panel="supported"> + <div class="presets"> + {presets.map((p, i) => ( + <button type="button" class="preset" data-step={i} data-cmd={p.cmd}> + <span class="preset-cmd">{p.cmd}</span> + <span class="preset-desc">{p.desc}</span> + </button> + ))} + </div> + </div> + <div class="tab-panel" data-panel="soon" hidden> + <span class="soon-heading">Coming soon</span> + <div class="presets"> + {soon.map((p) => ( + <button type="button" class="preset preset-soon" disabled> + <span class="preset-cmd">{p.cmd}</span> + <span class="preset-desc">{p.desc}</span> + <span class="tbd">TBD</span> + </button> + ))} + </div> + </div> + </div> +</section> diff --git a/website/src/components/landing/HeroArt.astro b/website/src/components/landing/HeroArt.astro new file mode 100644 index 000000000..d94f515fb --- /dev/null +++ b/website/src/components/landing/HeroArt.astro @@ -0,0 +1,99 @@ +--- +// Signature motif: the interaction graph drawn in the site's drafting +// language — sparse editorial field, blueprint-style annotations. +// Styles live in src/assets/landing-page.css (.ha-* rules). +--- + +<figure class="hero-art" aria-hidden="true"> + <svg viewBox="0 0 560 440" role="presentation"> + <defs> + <radialGradient id="ha-glow" cx="0.62" cy="0.4" r="0.55"> + <stop offset="0" class="ha-glow-in" /> + <stop offset="1" class="ha-glow-out" /> + </radialGradient> + </defs> + <rect x="0" y="0" width="560" height="440" fill="url(#ha-glow)" /> + + <!-- drawing-frame corner ticks --> + <g class="ha-corners"> + <path d="M14 26 V14 H26" /><path d="M534 14 H546 V26" /> + <path d="M14 414 V426 H26" /><path d="M546 414 V426 H534" /> + </g> + + <!-- registration marks --> + <g class="ha-marks"> + <path d="M84 214 h10 M89 209 v10" /><path d="M494 60 h10 M499 55 v10" /> + <path d="M228 46 h10 M233 41 v10" /><path d="M508 392 h10 M513 387 v10" /> + <path d="M64 386 h10 M69 381 v10" /> + </g> + + <!-- edges --> + <g class="ha-edges"> + <path d="M158 132 C 240 130 300 138 384 158" class="is-accent" /> + <path d="M142 296 C 230 268 300 210 380 172" /> + <path d="M142 300 C 250 300 350 300 442 306" /> + <path d="M316 374 C 360 352 410 326 446 316" /> + <path d="M398 170 C 430 210 442 250 448 296" class="faint" /> + <path d="M384 158 L375.5 159.2 L377.0 153.0 Z" class="ha-arrow is-accent-fill" /> + <path d="M380 172 L374.2 178.3 L371.4 172.5 Z" class="ha-arrow" /> + <path d="M442 306 L433.8 308.7 L434.2 302.3 Z" class="ha-arrow" /> + <path d="M446 316 L439.2 321.2 L437.4 315.0 Z" class="ha-arrow" /> + </g> + + <!-- edge label chip + microlabel --> + <g class="ha-chip"> + <rect x="244" y="118" width="52" height="20" rx="10" /> + <text x="270" y="132" text-anchor="middle">likes</text> + </g> + <text x="284" y="246" class="ha-microlabel" transform="rotate(-24 284 246)">follows</text> + + <!-- leader note off the accent edge (drafting annotation) --> + <g class="ha-note"> + <circle cx="328" cy="147" r="2" /> + <path d="M328 147 L352 96 H460" /> + <text x="354" y="78">version 1784793660730</text> + <text x="354" y="90">props {'{'} createdAt: t₀ {'}'}</text> + </g> + + <!-- construction ring around the hot item --> + <g class="ha-construction"> + <circle cx="394" cy="164" r="30" /> + <path d="M394 126 v8 M394 194 v8 M356 164 h8 M424 164 h8" /> + </g> + + <!-- user nodes --> + <g class="ha-node"> + <circle cx="148" cy="130" r="7" class="ha-dot" /> + <circle cx="148" cy="130" r="13" class="ha-ring" /> + <text x="128" y="106" class="ha-name">Alice</text> + <text x="129" y="152" class="ha-type">USER</text> + </g> + <g class="ha-node"> + <circle cx="132" cy="298" r="7" class="ha-dot" /> + <circle cx="132" cy="298" r="13" class="ha-ring" /> + <text x="112" y="274" class="ha-name">Bob</text> + <text x="113" y="320" class="ha-type">USER</text> + </g> + <g class="ha-node"> + <circle cx="306" cy="378" r="6" class="ha-dot" /> + <circle cx="306" cy="378" r="11" class="ha-ring" /> + <text x="286" y="414" class="ha-name sm">Mina</text> + <text x="330" y="382" class="ha-type">USER</text> + </g> + + <!-- item nodes --> + <g class="ha-node"> + <circle cx="394" cy="164" r="9" class="ha-dot is-accent" /> + <circle cx="394" cy="164" r="17" class="ha-ring is-accent" /> + <text x="428" y="156" class="ha-name">Phone</text> + <text x="429" y="174" class="ha-type">ITEM · 1.2M EDGES IN</text> + </g> + <g class="ha-node"> + <circle cx="452" cy="308" r="7" class="ha-dot" /> + <circle cx="452" cy="308" r="13" class="ha-ring" /> + <text x="472" y="304" class="ha-name sm">Laptop</text> + <text x="473" y="322" class="ha-type">ITEM</text> + </g> + </svg> + <figcaption class="fig-cap">Fig. 01 — who → what → target</figcaption> +</figure> diff --git a/website/src/components/media-card.astro b/website/src/components/media-card.astro deleted file mode 100644 index a9395f03f..000000000 --- a/website/src/components/media-card.astro +++ /dev/null @@ -1,48 +0,0 @@ ---- -interface Props { - href?: string | undefined; -} -const { href } = Astro.props; -const El = href ? 'a' : 'span'; ---- - -<li class="not-content sl-flex"> - <El class="media-card sl-flex" {href}> - <div class="media"><slot name="media" /></div> - <slot /> - </El> -</li> - -<style> - .media-card { - flex-direction: column; - border: 1px solid var(--sl-color-gray-5); - border-radius: 0.5rem; - overflow: hidden; - text-decoration: none; - box-shadow: var(--sl-shadow-sm); - width: 100%; - } - a:hover { - border-color: var(--sl-color-gray-2); - background-color: var(--sl-color-gray-7, var(--sl-color-gray-6)); - } - - .media { - border-bottom: 1px solid var(--sl-color-gray-5); - } - - .media :global(img) { - display: block; - width: 100%; - height: auto; - aspect-ratio: 16 / 9; - object-fit: cover; - } - - .media-card :global(.title) { - color: var(--sl-color-white); - font-weight: 600; - line-height: var(--sl-line-height-headings); - } -</style> diff --git a/website/src/components/showcase-card.astro b/website/src/components/showcase-card.astro deleted file mode 100644 index 2ca38fdb4..000000000 --- a/website/src/components/showcase-card.astro +++ /dev/null @@ -1,49 +0,0 @@ ---- -import type { ImageMetadata } from 'astro'; -import { Image } from 'astro:assets'; -import MediaCard from './media-card.astro'; -import { AstroError } from 'astro/errors'; - -interface Props { - href: string; - title: string; - thumbnail: string; -} -const { href, title } = Astro.props; - -const thumbnails = import.meta.glob<{ default: ImageMetadata }>( - '../assets/showcase/*{.png,.jpg,.jpeg,.webp,.avif}' -); -const thumbnail = thumbnails[`../assets/showcase/${Astro.props.thumbnail}`]; -if (!thumbnail) { - throw new Error(`Could not resolve showcase thumbnail: ${Astro.props.thumbnail}`); -} -const src = (await thumbnail()).default; - -if (src.width !== 800 || src.height !== 450) { - let fileName = src.src.split('/').pop(); - const queryIndex = fileName?.indexOf('?'); - if (queryIndex !== undefined && queryIndex > -1) { - fileName = fileName?.slice(0, queryIndex); - } - throw new AstroError( - 'Showcase images must be **800×450px**', - `Dimensions of **${src.width}×${src.height}px** found for showcase image \`${fileName || src.src}\`\n\n` + - `For best results:\n\n` + - `1. Take a screenshot of the site using a browser resized to **1280×720px**. The responsive view in dev tools can be helpful for this.\n\n` + - `2. Resize the screenshot to **800×450px** and make sure it is saved as a PNG. An online tool like [Squoosh](https://squoosh.app/) can help here.\n\n` + - `See more details in the [Starlight contributing guide](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#showcase)\n` - ); -} ---- - -<MediaCard {href}> - <Image slot="media" {src} alt="" width="560" /> - <p class="title">{title}</p> -</MediaCard> - -<style> - .title { - padding: 0.75rem 1rem; - } -</style> diff --git a/website/src/components/showcase-sites.astro b/website/src/components/showcase-sites.astro deleted file mode 100644 index f3eea86cb..000000000 --- a/website/src/components/showcase-sites.astro +++ /dev/null @@ -1,216 +0,0 @@ ---- -import Card from './showcase-card.astro'; -import FluidGrid from './fluid-grid.astro'; ---- - -<FluidGrid> - <Card title="Athena OS" href="https://athenaos.org" thumbnail="www.athenaos.org.png" /> - <Card title="pls" href="https://pls.cli.rs/" thumbnail="pls.cli.rs.png" /> - <Card title="capo.js" href="https://rviscomi.github.io/capo.js/" thumbnail="capo.js.png" /> - <Card - title="Web Monetization API" - href="https://webmonetization.org/docs/" - thumbnail="webmonetization.org.png" - /> - <Card - title="QBCore Docs" - href="https://brycerussell.github.io/qbcore-docs/" - thumbnail="brycerussell.github.io-qbcore-docs.png" - /> - <Card title="har.fyi" href="https://har.fyi/" thumbnail="har.fyi.png" /> - <Card title="xs-dev docs" href="https://xs-dev.js.org" thumbnail="xs-dev.js.org.png" /> - <Card title="Felicity" href="https://felicity.pages.dev/" thumbnail="felicity.pages.dev.png" /> - <Card - title="NgxEditor" - href="https://sibiraj-s.github.io/ngx-editor/" - thumbnail="sibiraj-s.github.io-ngx-editor.png" - /> - <Card title="Terrateam Docs" href="https://terrateam.io/docs" thumbnail="terrateam.io-docs.png" /> - <Card - title="Obytes Starter" - href="https://starter.obytes.com" - thumbnail="starter.obytes.com.jpg" - /> - <Card - title="Kanri" - href="https://www.kanriapp.com/getting-started/what-is-kanri/" - thumbnail="kanriapp.com.png" - /> - <Card title="Refact" href="https://docs.refact.ai/" thumbnail="refact.ai.png" /> - <Card - title="Some drops of PHP Book" - href="https://drops-of-php.hi-folks.dev/" - thumbnail="drops-of-php.hi-folks.dev.png" - /> - <Card title="Nostalgist.js" href="https://nostalgist.js.org/" thumbnail="nostalgist.js.org.png" /> - <Card - title="AI Prompt Snippets" - href="https://ai-prompt-snippets.vercel.app/" - thumbnail="ai-prompt-snippets.png" - /> - <Card - title="Folks Router" - href="https://folksrouter.io/docs/introduction" - thumbnail="folksrouter.io.png" - /> - <Card - title="React Awesome Reveal" - href="https://react-awesome-reveal.morello.dev/" - thumbnail="react-awesome-reveal.morello.dev.png" - /> - <Card - title="Ethereum Follow Protocol" - href="https://docs.ethfollow.xyz/" - thumbnail="docs.ethfollow.xyz.png" - /> - <Card title="Knip" href="https://knip.dev" thumbnail="knip.dev.png" /> - <Card title="secco" href="https://secco.lekoarts.de" thumbnail="secco.lekoarts.de.png" /> - <Card - title="SiteOne Crawler" - href="https://crawler.siteone.io/?utm_source=starlight-docs" - thumbnail="crawler.siteone.io.png" - /> - <Card title="Mr. Robøt" href="https://docs.mrrobot.app" thumbnail="docs.mrrobot.app.png" /> - <Card title="Open SaaS Docs" href="https://docs.opensaas.sh/" thumbnail="opensaas.sh.png" /> - <Card - title="Astro Snipcart" - href="https://astro-snipcart.vercel.app/" - thumbnail="astro-snipcart.png" - /> - <Card title="oneRepo" href="https://onerepo.tools" thumbnail="onerepo.tools.png" /> - <Card title="Flojoy" href="https://docs.flojoy.ai" thumbnail="docs.flojoy.ai.png" /> - <Card title="AstroNvim" href="https://docs.astronvim.com" thumbnail="docs.astronvim.com.png" /> - <Card - title="ScreenshotOne Docs" - href="https://screenshotone.com/docs/" - thumbnail="screenshotone.com.png" - /> - <Card title="DipSway" href="https://api.dipsway.com" thumbnail="api.dipsway.com.png" /> - <Card title="RunsOn" href="https://runs-on.com" thumbnail="runs-on.com.png" /> - <Card title="SST Ion" href="https://ion.sst.dev/" thumbnail="ion.sst.dev.png" /> - <Card - title="Font Awesome" - href="https://docs.fontawesome.com/" - thumbnail="docs.fontawesome.com.png" - /> - <Card title="TrueCharts" href="https://truecharts.org/" thumbnail="truecharts.org.png" /> - <Card title="Kinde" href="https://docs.kinde.com/" thumbnail="kinde.com.png" /> - <Card title="DMNO" href="https://dmno.dev" thumbnail="dmno.dev.png" /> - <Card title="EspansoEdit" href="https://ee.qqv.com.au" thumbnail="ee.qqv.com.au.png" /> - <Card title="TutorialKit" href="https://tutorialkit.dev/" thumbnail="tutorialkit.dev.png" /> - <Card - title="The Dev Health OS" - href="https://www.devhealthos.com/" - thumbnail="www.devhealthos.com.png" - /> - <Card - title="FeedbackSpark" - href="https://feedbackspark.com/docs/" - thumbnail="feedbackspark.com.png" - /> - <Card - title="QuotesDomain" - href="https://www.quotesdomain.com/" - thumbnail="quotesdomain.com.png" - /> - <Card title="Saasfly" href="https://document.saasfly.io/" thumbnail="document.saasfly.io.png" /> - <Card - title="freeCodeCamp" - href="https://contribute.freecodecamp.org/intro/" - thumbnail="contribute.freecodecamp.org.png" - /> - <Card - title="Style Dictionary" - href="https://styledictionary.com/" - thumbnail="styledictionary.com.png" - /> - <Card title="CodeSweetly" href="https://codesweetly.com/" thumbnail="codesweetly.com.png" /> - <Card title="grpcmd" href="https://grpc.md/docs/" thumbnail="grpc.md.png" /> - <Card - title="Pokemon Database" - href="https://pokemon-siace.netlify.app/" - thumbnail="pokemon-siace.netlify.app.png" - /> - <Card - title="Cloudflare Docs" - href="https://developers.cloudflare.com/" - thumbnail="developers.cloudflare.com.png" - /> - <Card title="Open {re}Source" href="https://openresource.dev" thumbnail="openresource.dev.png" /> - <Card - title="Orbit CSS" - href="https://zumerlab.github.io/orbit-docs/" - thumbnail="zumerlab.github.io.orbit-docs.png" - /> - <Card - title="LaunchFast" - href="https://www.launchfa.st/documentation" - thumbnail="launchfa.st.png" - /> - <Card title="Capgo" href="https://capgo.app/docs" thumbnail="capgo.app.png" /> - <Card - title="React Bricks" - href="https://docs.reactbricks.com" - thumbnail="docs.reactbricks.com.png" - /> - <Card title="emoji-blast" href="https://emojiblast.dev" thumbnail="docs.emojiblast.dev.png" /> - <Card - title="Text To Table Converter" - href="https://texttotableconverter.com" - thumbnail="texttotableconverter.com.png" - /> - <Card - title="Isomorphic Validation" - href="https://itihon.github.io/isomorphic-validation/" - thumbnail="itihon.github.io-isomorphic-validation.png" - /> - <Card - title="Accessible Astro" - href="https://accessible-astro.incluud.dev" - thumbnail="accessible-astro.incluud.dev.png" - /> - <Card title="Learn AISO" href="https://learnaiso.com" thumbnail="learnaiso.com.png" /> - <Card title="PaperMC Docs" href="https://docs.papermc.io" thumbnail="docs.papermc.io.png" /> - <Card title="Bingo" href="https://create.bingo" thumbnail="create.bingo.png" /> - <Card title="OctoGuide" href="https://octo.guide" thumbnail="octo.guide.png" /> - <Card - title="Sonar" - href="https://sonar-team.github.io/doc/" - thumbnail="sonar-team.github.io.png" - /> - <Card title="Cookie API" href="https://docs.cookie-api.com" thumbnail="docs.cookie-api.com.png" /> - <Card title="Fluid DnD" href="https://fluid-dnd.netlify.app/" thumbnail="fluid-dnd.png" /> - <Card title="PyDocs" href="https://www.pydocs.site/en" thumbnail="www.pydocs.site.png" /> - <Card title="Fomr" href="https://fomr.io/help" thumbnail="fomr.io.png" /> - <Card - title="The Jotter | Bag of Tricks" - href="https://events-3bg.pages.dev/jotter" - thumbnail="events-3bg.pages.dev.png" - /> - <Card title="@vtbag" href="https://vtbag.dev" thumbnail="vtbag.dev.png" /> - <Card title="vlt docs" href="https://docs.vlt.sh/" thumbnail="docs.vlt.sh.png" /> - <Card - title="sharp" - href="https://sharp.pixelplumbing.com/" - thumbnail="sharp.pixelplumbing.com.png" - /> - <Card title="Netlify Docs" href="https://docs.netlify.com" thumbnail="docs.netlify.com.png" /> - <Card - title="Open AI Agents SDK" - href="https://openai.github.io/openai-agents-js/" - thumbnail="openai.github.io.png" - /> - <Card title="opencode" href="https://opencode.ai/docs" thumbnail="opencode.ai.png" /> - <Card title="Scalekit Docs" href="https://docs.scalekit.com/" thumbnail="docs.scalekit.com.png" /> - <Card title="Aptos Docs" href="https://aptos.dev" thumbnail="aptos.dev.png" /> - <Card title="OmniPrint Docs" href="https://omni-byte.com/docs/" thumbnail="omni-byte.com.png" /> - <Card title="Academeez" href="https://www.academeez.com/" thumbnail="academeez.com.png" /> - <Card title="openstatus Docs" href="https://docs.openstatus.dev" thumbnail="openstatus.dev.png" /> - <Card title="Saucer" href="https://saucer.app" thumbnail="saucer.app.png" /> - <Card title="lychee" href="https://lychee.cli.rs/" thumbnail="lychee.cli.rs.png" /> - <Card title="Biome" href="https://biomejs.dev/" thumbnail="biomejs.dev.png" /> - <Card title="aspire.dev" href="https://aspire.dev/" thumbnail="aspire.dev.png" /> - <Card title="bettercap" href="https://www.bettercap.org/" thumbnail="bettercap.org.png" /> - <Card title="modestbench" href="https://modestbench.dev/" thumbnail="modestbench.dev.png" /> - <Card title="LavaMoat" href="https://lavamoat.github.io/" thumbnail="lavamoat.github.io.png" /> -</FluidGrid> diff --git a/website/src/components/sidebar-preview.astro b/website/src/components/sidebar-preview.astro deleted file mode 100644 index c5a1fcb6a..000000000 --- a/website/src/components/sidebar-preview.astro +++ /dev/null @@ -1,60 +0,0 @@ ---- -import type { - AutoSidebarGroup, - SidebarItem, - InternalSidebarLinkItem, -} from '@astrojs/starlight/schemas/sidebar'; -import SidebarSublist from '@astrojs/starlight/components/SidebarSublist.astro'; -import type { Badge } from '@astrojs/starlight/schemas/badge'; -import type { SidebarEntry } from '@astrojs/starlight/utils/routing/types'; - -interface Props { - config: SidebarConfig; -} - -type SidebarConfig = (Exclude<SidebarItem, AutoSidebarGroup | InternalSidebarLinkItem> & { - badge?: Badge; -})[]; - -const { config } = Astro.props; - -function makeEntries(items: SidebarConfig): SidebarEntry[] { - return items.map((item) => { - if ('link' in item) { - return { - type: 'link', - label: item.label, - // Empty hrefs are used to represent internal links that do not exist in the Starlight - // docs. Using a non-existing anchor link like `#_` will not trigger a page reload or any - // scrolling. - href: item.link.length > 0 ? item.link : '#_', - isCurrent: false, - badge: item.badge, - attrs: item.attrs ?? {}, - }; - } - - return { - type: 'group', - label: item.label, - entries: makeEntries(item.items as SidebarConfig), - collapsed: item.collapsed, - badge: item.badge, - }; - }); -} ---- - -<div class="sidebar-preview not-content"> - <SidebarSublist sublist={makeEntries(config)} /> -</div> - -<style> - .sidebar-preview { - background-color: var(--sl-color-bg-sidebar); - border: 1px solid var(--sl-color-gray-5); - padding: 1rem var(--sl-sidebar-pad-x); - /* Matches `var(--sl-sidebar-width)`, but hardcoded to avoid being overridden when printing the page. */ - max-width: 18.75rem; - } -</style> diff --git a/website/src/components/social-links-type.astro b/website/src/components/social-links-type.astro deleted file mode 100644 index d60e20716..000000000 --- a/website/src/components/social-links-type.astro +++ /dev/null @@ -1,10 +0,0 @@ ---- -import { getRelativeLocaleUrl } from 'astro:i18n'; -const href = getRelativeLocaleUrl(Astro.currentLocale ?? 'en', '/reference/icons/'); ---- - -<code> - <Fragment set:text="Array<{" /> - label: string; icon: <a {href}>StarlightIcon</a>; href: string - <Fragment set:text="}>" /> -</code> diff --git a/website/src/components/testimonial-grid.astro b/website/src/components/testimonial-grid.astro deleted file mode 100644 index d8fc4ea84..000000000 --- a/website/src/components/testimonial-grid.astro +++ /dev/null @@ -1,39 +0,0 @@ ---- -interface Props { - title: string; -} - -const { title } = Astro.props; ---- - -<div class="testimonial-wrapper not-content" data-pagefind-ignore> - <h2 class="testimonial-grid-title">{title}</h2> - <ul class="testimonial-grid"> - <slot /> - </ul> -</div> - -<style> - .testimonial-wrapper { - margin-block: 7rem 2.5rem !important; - font-size: clamp(var(--sl-text-sm), calc(0.5rem + 1vw), var(--sl-text-body)); - } - .testimonial-grid-title { - text-align: center; - font-size: var(--sl-text-h3); - font-weight: 600; - color: var(--sl-color-white); - line-height: var(--sl-line-height-headings); - } - .testimonial-grid { - margin-top: 2.5rem; - display: grid; - gap: 5em; - padding-inline-start: 0; - } - @media (min-width: 50rem) { - .testimonial-grid { - grid-template-columns: 1fr 1fr; - } - } -</style> diff --git a/website/src/components/testimonial.astro b/website/src/components/testimonial.astro deleted file mode 100644 index 4ba4fd00b..000000000 --- a/website/src/components/testimonial.astro +++ /dev/null @@ -1,90 +0,0 @@ ---- -import type { ImageMetadata } from 'astro'; -import { Image } from 'astro:assets'; - -interface Props { - handle: string; - name: string; - cite: string; -} - -const { name, handle, cite } = Astro.props; - -const avatars = import.meta.glob<{ default: ImageMetadata }>('../assets/testimonials/*.jpg'); -const avatar = avatars[`../assets/testimonials/${handle}.jpg`]; -if (!avatar) { - throw new Error(`Could not resolve testimonial avatar for @${handle}`); -} -const src = (await avatar()).default; ---- - -<li class="testimonial"> - <blockquote class="quote" cite={cite}> - <slot /> - </blockquote> - <div class="footer"> - <Image class="avatar" height="96" width="96" {src} alt="" /> - <div> - <p class="name">{name}</p> - <a href={cite} class="handle">@{handle}</a> - </div> - </div> -</li> - -<style> - .testimonial { - display: flex; - flex-direction: column; - gap: 1.5em; - } - @media (min-width: 50rem) { - .testimonial { - gap: 2em; - } - } - .quote { - position: relative; - padding-inline-start: 1.5em; - } - .quote::before { - position: absolute; - content: ''; - inset-block: 0.5em; - inset-inline-start: 0; - border-inline-start: 1px solid var(--sl-color-text-accent); - } - .quote > :global(* + *) { - margin-top: 0.75em; - } - - .footer { - display: flex; - gap: 1rem; - align-items: center; - } - .avatar { - --outline-color: rgba(255, 255, 255, 0.33); - outline: 1px solid var(--outline-color); - outline-offset: -1px; - border-radius: 99rem; - width: 4em; - height: 4em; - } - :global([data-theme='light']) .avatar { - --outline-color: rgba(23, 25, 30, 0.33); - } - - .name { - font-weight: 600; - font-size: var(--sl-text-h4); - color: var(--sl-color-white); - line-height: var(--sl-line-height-headings); - } - .handle { - text-underline-offset: 4px; - color: var(--sl-color-text-accent); - } - .handle:hover { - color: var(--sl-color-white); - } -</style> diff --git a/website/src/components/theme-designer.astro b/website/src/components/theme-designer.astro deleted file mode 100644 index ed13418ed..000000000 --- a/website/src/components/theme-designer.astro +++ /dev/null @@ -1,160 +0,0 @@ ---- -import { TabItem, Tabs } from '@astrojs/starlight/components'; -import ColorEditor, { type Props as EditorProps } from './theme-designer/color-editor.astro'; -import ContrastLevel, { - type Props as ContrastLevelProps, -} from './theme-designer/contrast-level.astro'; -import Presets, { type Props as PresetsProps } from './theme-designer/presets.astro'; -import Preview from './theme-designer/preview.astro'; - -interface Props { - labels: { - presets: PresetsProps['labels']; - contrast: ContrastLevelProps['labels']; - editor: EditorProps['labels'] & { accentColor: string; grayColor: string }; - preview: Record< - 'darkMode' | 'lightMode' | 'bodyText' | 'linkText' | 'dimText' | 'inlineCode', - string - >; - }; -} -const { - labels: { presets, contrast, editor, preview }, -} = Astro.props; ---- - -<Presets labels={presets} /> - -<ContrastLevel labels={contrast} /> - -<div> - <theme-designer> - <div class="sl-flex controls not-content"> - <ColorEditor key="accent" legend={editor.accentColor} labels={editor} /> - <ColorEditor key="gray" legend={editor.grayColor} labels={editor} /> - </div> - - <div class="preview" data-accent-preview> - <Preview labels={preview} data-dark /> - <Preview labels={preview} data-light /> - </div> - - <Tabs> - <TabItem label="CSS"> - <slot name="css-docs" /> - <pre - class="generated-code" - tabindex="0"><code style="background-color: var(--astro-code-color-background);color: var(--sl-color-text)" data-theme-css /></pre> - </TabItem> - <TabItem label="Tailwind"> - <slot name="tailwind-docs" /> - <pre - class="generated-code" - tabindex="0"><code style="background-color: var(--astro-code-color-background);color: var(--sl-color-text)" data-theme-tailwind /></pre> - </TabItem> - </Tabs> - </theme-designer> -</div> - -<script> - import { getPalettes } from './theme-designer/color-lib'; - import { store, minimumContrast } from './theme-designer/store'; - - class ThemeDesigner extends HTMLElement { - #stylesheet = new CSSStyleSheet(); - - constructor() { - super(); - // Add our stylesheet to the document. - document.adoptedStyleSheets = [...document.adoptedStyleSheets, this.#stylesheet]; - // Update theme palettes on user input. - const onInput = () => this.#update(); - store.accent.subscribe(onInput); - store.gray.subscribe(onInput); - minimumContrast.subscribe(onInput); - } - - #update() { - const palettes = getPalettes({ - accent: store.accent.get(), - gray: store.gray.get(), - minimumContrast: minimumContrast.get(), - }); - this.#updatePreview(palettes); - this.#updateStylesheet(palettes); - this.#updateTailwindConfig(palettes); - } - - /** Apply the generated palettes to the style attributes of the in-content preview panes. */ - #updatePreview({ dark, light }: ReturnType<typeof getPalettes>) { - const previews = this.querySelectorAll<HTMLDivElement>('[data-accent-preview] > *'); - previews.forEach((preview) => { - const theme = 'dark' in preview.dataset ? dark : light; - Object.entries(theme).forEach(([key, color]) => { - preview.style.setProperty(`--sl-color-${key}`, color); - }); - }); - } - - /** Convert a color palette into a string of CSS rules. */ - #paletteToRules(palette: ReturnType<typeof getPalettes>['dark' | 'light']) { - return Object.entries(palette) - .map(([key, color]) => `--sl-color-${key}: ${color};`) - .join('\n\t'); - } - - /** Update the CSS stylesheet applied to the current page and offered to users to copy. */ - #updateStylesheet({ dark, light }: ReturnType<typeof getPalettes>) { - const styles = `/* Dark mode colors. */ -:root {\n\t${this.#paletteToRules(dark)}\n} -/* Light mode colors. */ -:root[data-theme='light'] {\n\t${this.#paletteToRules(light)}\n}`; - this.#stylesheet.replaceSync(styles); - const codePreview = this.querySelector('[data-theme-css]'); - if (codePreview) codePreview.innerHTML = styles; - } - - #updateTailwindConfig({ dark, light }: ReturnType<typeof getPalettes>) { - const config = `/* Generated accent color palettes. */ ---color-accent-200: ${dark['accent-high']}; ---color-accent-600: ${light.accent}; ---color-accent-900: ${light['accent-high']}; ---color-accent-950: ${dark['accent-low']}; -/* Generated gray color palettes. */ ---color-gray-100: ${light['gray-7']}; ---color-gray-200: ${light['gray-6']}; ---color-gray-300: ${light['gray-5']}; ---color-gray-400: ${light['gray-4']}; ---color-gray-500: ${light['gray-3']}; ---color-gray-700: ${light['gray-2']}; ---color-gray-800: ${light['gray-1']}; ---color-gray-900: ${light.white};`; - const codePreview = this.querySelector('[data-theme-tailwind]'); - if (codePreview) codePreview.innerHTML = config; - } - } - - customElements.define('theme-designer', ThemeDesigner); -</script> - -<style> - .controls { - flex-wrap: wrap; - gap: 1.5rem; - } - .controls > :global(*) { - flex: 1 1; - } - .preview { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 1.5rem; - } - - .generated-code { - height: 16rem; - background-color: var(--astro-code-color-background); - overflow: auto scroll; - user-select: all; - } -</style> diff --git a/website/src/components/theme-designer/atom.ts b/website/src/components/theme-designer/atom.ts deleted file mode 100644 index 774137640..000000000 --- a/website/src/components/theme-designer/atom.ts +++ /dev/null @@ -1,35 +0,0 @@ -class Atom<T> { - #v: T; - #subscribers = new Map<(v: T) => void, (v: T) => void>(); - #notify = () => this.#subscribers.forEach((cb) => cb(this.#v)); - constructor(init: T) { - this.#v = init; - } - get(): T { - return this.#v; - } - set(v: T): void { - this.#v = v; - this.#notify(); - } - subscribe(cb: (v: T) => void): () => boolean { - cb(this.#v); - this.#subscribers.set(cb, cb); - return () => this.#subscribers.delete(cb); - } -} - -type MapStore<T> = Atom<T> & { setKey: (key: keyof T, value: T[typeof key]) => void }; - -export function map<T extends Record<string, unknown>>(value: T): MapStore<T> { - const atom = new Atom(value) as MapStore<T>; - atom.setKey = (key: keyof T, value: T[typeof key]) => { - const curr = atom.get(); - if (curr[key] !== value) atom.set({ ...curr, [key]: value }); - }; - return atom; -} - -export function atom<T>(value: T): Atom<T> { - return new Atom(value); -} diff --git a/website/src/components/theme-designer/color-editor.astro b/website/src/components/theme-designer/color-editor.astro deleted file mode 100644 index e91557ed3..000000000 --- a/website/src/components/theme-designer/color-editor.astro +++ /dev/null @@ -1,93 +0,0 @@ ---- -import { oklchToHex } from './color-lib'; -import { store } from './store'; -import ValueSlider from './value-slider.astro'; - -export interface Props { - key: keyof typeof store; - legend: string; - labels: Record<'pickColor' | 'hue' | 'chroma', string>; -} -const { key, legend, labels } = Astro.props; -const { hue, chroma } = store[key].get(); -const initialColor = oklchToHex(52, chroma, hue); ---- - -<color-editor data-key={key}> - <fieldset> - <legend>{legend}</legend> - <label class="color-picker"> - <span class="sr-only">{labels.pickColor}</span> - <input type="color" value={initialColor} /> - </label> - <div class="sliders"> - <ValueSlider label={labels.hue} storeKey={key} type="hue" /> - <ValueSlider label={labels.chroma} storeKey={key} type="chroma" /> - </div> - </fieldset> -</color-editor> - -<script> - import { oklch, oklchToHex } from './color-lib'; - import { store } from './store'; - - export class ColorEditor extends HTMLElement { - #store = store[this.dataset.key as keyof typeof store]; - #colorInput = this.querySelector<HTMLInputElement>('input[type="color"]')!; - - constructor() { - super(); - // Update color on user input. - this.#store.subscribe(({ chroma, hue }) => { - this.#colorInput.value = oklchToHex(52, chroma, hue); - }); - this.#colorInput.addEventListener('input', (e) => { - if (!(e.target instanceof HTMLInputElement)) return; - const old = this.#store.get(); - const { c, h } = { ...oklch(e.target.value) }; - this.#store.set({ hue: h ?? old.hue, chroma: c ?? old.chroma }); - }); - } - } - customElements.define('color-editor', ColorEditor); -</script> - -<style> - fieldset { - border: 1px solid var(--sl-color-gray-5); - background-color: var(--sl-color-gray-7, var(--sl-color-gray-6)); - padding: 1rem; - color: var(--sl-color-white); - } - legend { - float: left; - float: inline-start; - font-weight: 600; - } - .color-picker { - float: right; - float: inline-end; - } - .sliders { - clear: both; - } - input[type='color'] { - border: 0; - background: transparent; - height: 2em; - width: 3rem; - cursor: pointer; - --swatch-border: var(--sl-color-gray-3); - } - input[type='color']:hover { - --swatch-border: var(--sl-color-gray-1); - } - input[type='color']::-webkit-color-swatch { - border: 1px solid var(--swatch-border); - border-radius: 0.5rem; - } - input[type='color']::-moz-color-swatch { - border: 1px solid var(--swatch-border); - border-radius: 0.5rem; - } -</style> diff --git a/website/src/components/theme-designer/color-lib.ts b/website/src/components/theme-designer/color-lib.ts deleted file mode 100644 index 018f56f1f..000000000 --- a/website/src/components/theme-designer/color-lib.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { - clampChroma, - formatHex, - modeLrgb, - modeOklch, - modeRgb, - useMode, - wcagContrast, - type Oklch, -} from 'culori/fn'; - -const rgb = useMode(modeRgb); -export const oklch = useMode(modeOklch); -// We need to initialise LRGB support for culori’s `wcagContrast()` method. -useMode(modeLrgb); - -/** Convert a culori OKLCH color object to an RGB hex code. */ -const oklchColorToHex = (okLchColor: Oklch) => { - const rgbColor = rgb(clampChroma(okLchColor, 'oklch')); - return formatHex(rgbColor); -}; -/** Construct a culori OKLCH color object from LCH parameters. */ -const oklchColorFromParts = (l: number, c: number, h: number) => oklch(`oklch(${l}% ${c} ${h})`)!; -/** Convert OKLCH parameters to an RGB hex code. */ -export const oklchToHex = (l: number, c: number, h: number) => - oklchColorToHex(oklchColorFromParts(l, c, h)); - -/** - * Ensure a text colour passes a contrast threshold against a specific background colour. - * If necessary, colours will be darkened/lightened to increase contrast until the threshold is passed. - * - * @param text The text colour to adjust if necessary. - * @param bg The background colour to test contrast against. - * @param threshold The minimum contrast ratio required. Defaults to `4.5` to meet WCAG AA standards. - * @returns The adjusted text colour as a culori OKLCH color object. - */ -const contrastColor = (text: Oklch, bg: Oklch, threshold = 4.5): Oklch => { - /** Clone of the input foreground colour to mutate. */ - const fgColor = { ...text }; - // Brighten text in dark mode, darken text in light mode. - const increment = fgColor.l > bg.l ? 0.005 : -0.005; - while (wcagContrast(fgColor, bg) < threshold && fgColor.l < 100 && fgColor.l > 0) { - fgColor.l += increment; - } - return fgColor; -}; - -/** Generate dark and light palettes based on user-selected hue and chroma values. */ -export function getPalettes(config: { - accent: { hue: number; chroma: number }; - gray: { hue: number; chroma: number }; - minimumContrast?: number; -}) { - const { - accent: { hue: ah, chroma: ac }, - gray: { hue: gh, chroma: gc }, - minimumContrast: mc, - } = config; - - const palettes = { - dark: { - // Accents - 'accent-low': oklchColorFromParts(25.94, ac / 3, ah), - accent: oklchColorFromParts(52.28, ac, ah), - 'accent-high': oklchColorFromParts(83.38, ac / 3, ah), - // Grays - white: oklchColorFromParts(100, 0, 0), - 'gray-1': oklchColorFromParts(94.77, gc / 2.5, gh), - 'gray-2': oklchColorFromParts(81.34, gc / 2, gh), - 'gray-3': oklchColorFromParts(63.78, gc, gh), - 'gray-4': oklchColorFromParts(46.01, gc, gh), - 'gray-5': oklchColorFromParts(34.09, gc, gh), - 'gray-6': oklchColorFromParts(27.14, gc, gh), - black: oklchColorFromParts(20.94, gc / 2, gh), - }, - light: { - // Accents - 'accent-low': oklchColorFromParts(87.81, ac / 4, ah), - accent: oklchColorFromParts(52.95, ac, ah), - 'accent-high': oklchColorFromParts(31.77, ac / 2, ah), - // Grays - white: oklchColorFromParts(20.94, gc / 2, gh), - 'gray-1': oklchColorFromParts(27.14, gc, gh), - 'gray-2': oklchColorFromParts(34.09, gc, gh), - 'gray-3': oklchColorFromParts(46.01, gc, gh), - 'gray-4': oklchColorFromParts(63.78, gc, gh), - 'gray-5': oklchColorFromParts(81.34, gc / 2, gh), - 'gray-6': oklchColorFromParts(94.77, gc / 2.5, gh), - 'gray-7': oklchColorFromParts(97.35, gc / 5, gh), - black: oklchColorFromParts(100, 0, 0), - }, - }; - - // Ensure text shades have sufficient contrast against common background colours. - - // Dark mode: - // `gray-2` is used against `gray-5` in inline code snippets. - palettes.dark['gray-2'] = contrastColor(palettes.dark['gray-2'], palettes.dark['gray-5'], mc); - // `gray-3` is used in the table of contents. - palettes.dark['gray-3'] = contrastColor(palettes.dark['gray-3'], palettes.dark.black, mc); - - // Light mode: - // `accent` is used for links and link buttons and can be slightly under 7:1 for some hues. - palettes.light.accent = contrastColor(palettes.light.accent, palettes.light['gray-6'], mc); - // `gray-2` is used against `gray-6` in inline code snippets. - palettes.light['gray-2'] = contrastColor(palettes.light['gray-2'], palettes.light['gray-6'], mc); - // `gray-3` is used in the table of contents. - palettes.light['gray-3'] = contrastColor(palettes.light['gray-3'], palettes.light.black, mc); - - // Convert the palette from OKLCH to RGB hex codes. - return { - dark: Object.fromEntries( - Object.entries(palettes.dark).map(([key, color]) => [key, oklchColorToHex(color)]) - ) as Record<keyof typeof palettes.dark, string>, - light: Object.fromEntries( - Object.entries(palettes.light).map(([key, color]) => [key, oklchColorToHex(color)]) - ) as Record<keyof typeof palettes.light, string>, - }; -} - -/* -This is the default Starlight color palette in OKLCH. -Used as a reference when designing the algorithm for mapping -user hue and chroma pairs to a similar palette. - -Dark mode: - accent lo oklch(25.94% 0.09 273.5) - accent oklch(52.28% 0.266 268.7) - accent hi oklch(83.38% 0.084 279.5) - - white oklch(100% 0 0) - gray-1 oklch(94.77% 0.008 278.19) - gray-2 oklch(81.34% 0.011 274.87) - gray-3 oklch(63.78% 0.019 265.84) - gray-4 oklch(46.01% 0.021 270.93) - gray-5 oklch(34.09% 0.017 267.07) - gray-6 oklch(27.14% 0.015 267.03) - black oklch(20.94% 0.01 268.4) - -Light mode: - accent lo oklch(87.81% 0.056 280.2) - accent oklch(52.95% 0.243 270.2) - accent hi oklch(31.77% 0.177 267.2) - - white oklch(20.94% 0.01 268.4) - gray-1 oklch(27.14% 0.015 267.03) - gray-2 oklch(34.09% 0.017 267.07) - gray-3 oklch(46.01% 0.021 270.93) - gray-4 oklch(63.78% 0.019 265.84) - gray-5 oklch(81.34% 0.011 274.87) - gray-6 oklch(94.77% 0.008 278.19) - gray-7 oklch(97.35% 0.004 286.32) - black oklch(100% 0 0) -*/ diff --git a/website/src/components/theme-designer/contrast-level.astro b/website/src/components/theme-designer/contrast-level.astro deleted file mode 100644 index 6d89eb50c..000000000 --- a/website/src/components/theme-designer/contrast-level.astro +++ /dev/null @@ -1,86 +0,0 @@ ---- -export interface Props { - labels: { - label: string; - }; -} -const { labels = { label: 'WCAG Contrast Level' } } = Astro.props; ---- - -<contrast-level-toggle class="sl-flex"> - <fieldset class="not-content"> - <legend>{labels.label}</legend> - <div class="sl-flex"> - <label class="sl-flex"> - <input type="radio" name="contrast-level" value="4.5" checked /> - AA - </label> - <label class="sl-flex"> - <input type="radio" name="contrast-level" value="7" /> - AAA - </label> - </div> - </fieldset> -</contrast-level-toggle> - -<script> - import { minimumContrast } from './store'; - - class ContrastLevelToggle extends HTMLElement { - #fieldset = this.querySelector('fieldset')!; - constructor() { - super(); - this.#fieldset.addEventListener('input', (e) => { - if (e.target instanceof HTMLInputElement) { - const contrast = parseFloat(e.target.value); - minimumContrast.set(contrast); - } - }); - } - } - - customElements.define('contrast-level-toggle', ContrastLevelToggle); -</script> - -<style> - fieldset { - border: 0; - padding: 0; - } - fieldset > * { - float: left; - float: inline-start; - vertical-align: middle; - } - legend { - color: var(--sl-color-white); - margin-inline-end: 0.75rem; - } - label { - align-items: center; - padding: 0.25rem 0.75rem; - gap: 0.375rem; - background-color: var(--sl-color-gray-6); - font-size: var(--sl-text-xs); - cursor: pointer; - } - label:has(:focus-visible) { - outline: 2px solid; - outline-offset: -4px; - } - label:first-child { - border-start-start-radius: 99rem; - border-end-start-radius: 99rem; - } - label:last-child { - border-start-end-radius: 99rem; - border-end-end-radius: 99rem; - } - label:has(:checked) { - color: var(--sl-color-black); - background-color: var(--sl-color-text-accent); - } - input:focus-visible { - outline: none; - } -</style> diff --git a/website/src/components/theme-designer/palette.astro b/website/src/components/theme-designer/palette.astro deleted file mode 100644 index 0b4e1d0b8..000000000 --- a/website/src/components/theme-designer/palette.astro +++ /dev/null @@ -1,41 +0,0 @@ ---- -interface Props { - light?: boolean; -} ---- - -<div class="not-content"> - <div class="palette"> - { - Astro.props.light ? ( - <div class="circle" style="--bg:var(--sl-color-accent)" /> - ) : ( - <div class="circle" style="--bg:var(--sl-color-accent-high)" /> - ) - } - <div style="--bg:var(--sl-color-black)"></div> - <div style="--bg:var(--sl-color-white)"></div> - <div style="--bg:var(--sl-color-gray-1)"></div> - <div style="--bg:var(--sl-color-gray-2)"></div> - <div style="--bg:var(--sl-color-gray-3)"></div> - <div style="--bg:var(--sl-color-gray-4)"></div> - <div style="--bg:var(--sl-color-gray-5)"></div> - <div style="--bg:var(--sl-color-gray-6)"></div> - {Astro.props.light && <div style="--bg:var(--sl-color-gray-7)" />} - </div> -</div> - -<style> - .palette { - display: grid; - grid-template-columns: repeat(10, 1fr); - } - .palette > * { - aspect-ratio: 1; - background-color: var(--bg); - } - - .circle { - border-radius: 50%; - } -</style> diff --git a/website/src/components/theme-designer/presets.astro b/website/src/components/theme-designer/presets.astro deleted file mode 100644 index b0c8d73d2..000000000 --- a/website/src/components/theme-designer/presets.astro +++ /dev/null @@ -1,98 +0,0 @@ ---- -import { Icon } from '@astrojs/starlight/components'; -import { getPalettes } from './color-lib'; -import { presets } from './store'; - -export interface Props { - labels: Record<keyof typeof presets, string> & { - label: string; - random: string; - }; -} -const { labels } = Astro.props; - -const resolvedPresets = Object.entries(presets).map(([key, preset]) => { - const palette = getPalettes(preset); - const label = labels[key as keyof typeof presets]; - return [key, { ...palette, label }] as const; -}); ---- - -<preset-picker class="sl-flex not-content"> - <span class="label">{labels.label}</span> - { - resolvedPresets.map(([key, { label, dark, light }]) => ( - <button - data-preset={key} - style={{ - '--dark-bg': dark['accent-high'], - '--light-bg': light.accent, - '--dark-text': dark['accent-low'], - '--light-text': light.black, - }} - > - {label} - </button> - )) - } - <button data-random>{labels.random}<Icon name="random" size="1rem" /></button> -</preset-picker> - -<style> - preset-picker { - flex-wrap: wrap; - align-items: center; - gap: 0.75rem; - } - - .label { - color: var(--sl-color-white); - } - - [data-preset], - [data-random] { - border: 0; - border-radius: 99rem; - min-width: 4.5rem; - display: flex; - gap: 0.25rem; - align-items: center; - justify-content: center; - padding: 0.25rem 0.75rem; - background-color: var(--dark-bg, var(--sl-color-white)); - color: var(--dark-text, var(--sl-color-black)); - font-size: var(--sl-text-xs); - cursor: pointer; - } - button:focus-visible { - outline: 2px solid; - outline-offset: -4px; - } - :global([data-theme='light']) [data-preset] { - background-color: var(--light-bg); - color: var(--light-text); - } - button > :global(*) { - /* We want all clicks to go to the button, not child elements. */ - pointer-events: none; - } -</style> - -<script> - import { usePreset, useRandom } from './store'; - - class PresetPicker extends HTMLElement { - constructor() { - super(); - this.addEventListener('click', (e) => { - if (e.target instanceof HTMLButtonElement) { - const name = e.target.dataset.preset; - if (name) usePreset(name); - if ('random' in e.target.dataset) useRandom(); - } - }); - } - } - - customElements.define('preset-picker', PresetPicker); -</script> diff --git a/website/src/components/theme-designer/preview.astro b/website/src/components/theme-designer/preview.astro deleted file mode 100644 index d5bfdb7d2..000000000 --- a/website/src/components/theme-designer/preview.astro +++ /dev/null @@ -1,53 +0,0 @@ ---- -import type { HTMLAttributes } from 'astro/types'; -import Palette from './palette.astro'; - -interface Props extends HTMLAttributes<'div'> { - labels: { - lightMode: string; - darkMode: string; - bodyText: string; - linkText: string; - dimText: string; - inlineCode: string; - }; -} -const { labels, ...attrs } = Astro.props; -const light = 'data-light' in attrs; -const linkColor = light ? '--sl-color-accent' : '--sl-color-accent-high'; -const codeBg = light ? '--sl-color-gray-6' : '--sl-color-gray-5'; ---- - -<div class="preview-card" {...attrs}> - <h4>{light ? labels.lightMode : labels.darkMode}</h4> - <p> - {labels.bodyText}{' '} - <span class="link" style={`color:var(${linkColor})`}>{labels.linkText}</span>{' '} - <span class="dim">{labels.dimText}</span>{' '} - <code style={`--sl-color-bg-inline-code:var(${codeBg})`}>{labels.inlineCode}</code> - </p> - <Palette {light} /> -</div> - -<style> - .preview-card { - margin: 0 !important; - border: 1px solid var(--sl-color-gray-5); - padding: 1rem; - background-color: var(--sl-color-black); - } - - p { - margin-top: 0.5em !important; - font-size: var(--sl-text-sm); - color: var(--sl-color-gray-2); - } - - .link { - text-decoration: underline; - } - - .dim { - color: var(--sl-color-gray-3); - } -</style> diff --git a/website/src/components/theme-designer/store.ts b/website/src/components/theme-designer/store.ts deleted file mode 100644 index 207d82dd6..000000000 --- a/website/src/components/theme-designer/store.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { atom, map } from './atom'; - -export const presets = { - ocean: { - accent: { hue: 240, chroma: 0.27 }, - gray: { hue: 220, chroma: 0.025 }, - }, - forest: { - accent: { hue: 140, chroma: 0.27 }, - gray: { hue: 140, chroma: 0.03 }, - }, - oxide: { - accent: { hue: 30, chroma: 0.27 }, - gray: { hue: 30, chroma: 0.02 }, - }, - nebula: { - accent: { hue: 320, chroma: 0.27 }, - gray: { hue: 305, chroma: 0.07 }, - }, - default: { - accent: { hue: 269, chroma: 0.27 }, - gray: { hue: 270, chroma: 0.016 }, - }, -}; - -export const store = { - accent: map(presets.default.accent), - gray: map(presets.default.gray), -}; -export const minimumContrast = atom(4.5); - -export const usePreset = (name: string) => { - if (name in presets) { - const { accent, gray } = presets[name as keyof typeof presets]; - store.accent.set(accent); - store.gray.set(gray); - } -}; - -const MAX_CHROMA = 0.27; - -export const useRandom = () => { - store.accent.set({ hue: randomHue(), chroma: MAX_CHROMA - randomChroma() }); - store.gray.set({ hue: randomHue(), chroma: randomChroma() }); -}; - -const randomHue = () => Math.round(Math.random() * 360); -const randomChroma = () => Math.pow(Math.random(), 3) * MAX_CHROMA; diff --git a/website/src/components/theme-designer/value-slider.astro b/website/src/components/theme-designer/value-slider.astro deleted file mode 100644 index 796a4ad49..000000000 --- a/website/src/components/theme-designer/value-slider.astro +++ /dev/null @@ -1,62 +0,0 @@ ---- -import { store } from './store'; - -interface Props { - label: string; - storeKey: keyof typeof store; - type: 'hue' | 'chroma'; -} -const { label, storeKey, type } = Astro.props; - -const { max, step } = { hue: { max: 360, step: 1 }, chroma: { max: 0.27, step: 0.001 } }[type]; -const value = store[storeKey].get()[type]; ---- - -<value-slider data-store={storeKey} data-type={type}> - <label> - <span>{label}</span> - <input type="range" {max} {step} {value} /> - <span class="value">{value}</span> - </label> -</value-slider> - -<script> - import { store } from './store'; - - class ValueSlider extends HTMLElement { - #input = this.querySelector('input')!; - #output = this.querySelector<HTMLSpanElement>('.value')!; - #store = store[this.dataset.store as keyof typeof store]; - #type = this.dataset.type as 'hue' | 'chroma'; - #formatter = new Intl.NumberFormat(document.documentElement.lang || 'en'); - - constructor() { - super(); - this.#input.addEventListener('input', () => - this.#store.setKey(this.#type, this.#input.valueAsNumber) - ); - this.#store.subscribe((v) => { - const newValue = v[this.#type]; - this.#input.value = String(newValue); - this.#output.innerText = this.#formatter.format(newValue); - }); - } - } - customElements.define('value-slider', ValueSlider); -</script> - -<style> - label { - display: grid; - grid-template-columns: auto 1fr 2.5rem; - align-items: center; - gap: 0.75rem; - } - input { - min-width: 5rem; - } - .value { - font-size: var(--sl-text-sm); - color: var(--sl-color-gray-2); - } -</style> diff --git a/website/src/components/theme-grid.astro b/website/src/components/theme-grid.astro deleted file mode 100644 index 64f4f9d33..000000000 --- a/website/src/components/theme-grid.astro +++ /dev/null @@ -1,221 +0,0 @@ ---- -import { Icon } from '@astrojs/starlight/components'; -import FluidGrid from './fluid-grid.astro'; -import MediaCard from './media-card.astro'; -import ThemeImage from './theme-image.astro'; - -interface Props { - labels: { - /** Accessible label for the theme toggle. */ - legend: string; - /** Accessible label for the dark color scheme variant. */ - dark: string; - /** Accessible label for the light color scheme variant. */ - light: string; - }; - themes: Array<{ - /** The name of this theme. */ - title: string; - /** A short description of this theme. */ - description: string; - /** URL for this theme’s website. Ideally should link to a demo site showing off the theme. */ - href: string; - previews: { - /** Image filename as found in `src/assets/themes/`, e.g. `ion-light.png`. */ - light: string; - /** Image filename as found in `src/assets/themes/`, e.g. `ion-dark.png`. */ - dark: string; - }; - }>; -} - -const { labels, themes } = Astro.props; ---- - -<starlight-theme-preview data-theme-preview="dark"> - <fieldset class="not-content sl-flex"> - { - /* `<legend>` is a pain to position, so we visually hide it and use an `aria-hidden` duplicate - for the visual representation. See https://adrianroselli.com/2022/07/use-legend-and-fieldset.html */ - } - <legend class="sr-only">{labels.legend}</legend> - <strong aria-hidden="true">{labels.legend}</strong> - { - (['dark', 'light'] as const).map((variant) => ( - <label class:list={['sl-flex', variant]} for={`${variant}-input`}> - <span class="radio"> - <Icon name="approve-check" /> - </span> - <span>{labels[variant]}</span> - <input - id={`${variant}-input`} - class="sr-only" - name="preview-theme" - value={variant} - type="radio" - checked={variant === 'dark'} - /> - </label> - )) - } - {/* If the currently active theme is light mode, default to showing the light mode previews. */} - <script is:inline> - // @ts-nocheck - const theme = document.documentElement.dataset.theme || 'dark'; - const input = document.querySelector(`input[value="${theme}"]`); - if (input) input.checked = true; - const customEl = document.querySelector('starlight-theme-preview'); - if (customEl) customEl.dataset.themePreview = theme; - </script> - </fieldset> - - <FluidGrid minColumnWidth="25rem" gap="clamp(1rem, calc(0.75rem + 1vw), 1.5rem)"> - { - themes.map( - async ({ title, description, href, previews }) => - previews && ( - <MediaCard {href}> - <div class="preview-images" slot="media" aria-hidden="true"> - <ThemeImage src={previews.light} class="light" /> - <ThemeImage src={previews.dark} class="dark" /> - </div> - <div class="meta sl-flex"> - <p class="title">{title}</p> - <p class="description" set:html={description} /> - </div> - </MediaCard> - ) - ) - } - </FluidGrid> -</starlight-theme-preview> - -<script> - customElements.define( - 'starlight-theme-preview', - class ThemePreview extends HTMLElement { - constructor() { - super(); - this.querySelector('fieldset')?.addEventListener('change', ({ target }) => { - if (target instanceof HTMLInputElement) { - this.dataset.themePreview = target.value; - } - }); - } - } - ); -</script> - -<style> - starlight-theme-preview { - --transition-time: 0.25s; - display: block; - } - - fieldset { - /* Snappier transitions for the form controls. */ - --transition-time: 0.15s; - - /* Stick the control bar to bottom of the nav bar on scroll. */ - position: sticky; - top: var(--sl-nav-height); - z-index: var(--sl-z-index-toc); - /* Pull the bar out so it is full width on small screens. */ - margin-inline: calc(-1 * var(--sl-nav-pad-x)); - padding: var(--sl-nav-pad-y) var(--sl-nav-pad-x); - /* Internal layout and styles. */ - gap: 1rem; - align-items: center; - justify-content: end; - border: 1px solid var(--sl-color-hairline); - font-size: var(--sl-text-sm); - background-color: var(--sl-color-bg-nav); - box-shadow: var(--sl-shadow-md); - } - @media (min-width: 50rem) and (max-width: 72rem) { - /* Medium-width screens need a custom value to avoid x-axis overflow. */ - fieldset { - margin-inline: -1rem; - } - } - - label { - align-items: center; - gap: 0.375rem; - color: var(--sl-color-gray-3); - transition: color var(--transition-time) ease-in-out; - } - label:hover, - label:has(:checked) { - color: var(--sl-color-white); - } - - .radio { - display: grid; - place-content: center; - border: 1px solid var(--sl-color-gray-5); - border-radius: 100%; - width: 1.5rem; - height: 1.5rem; - background-color: #000; - color: #fff; - transition: transform var(--transition-time) ease-in-out; - } - label:not(:has(:checked)):hover .radio { - transform: scale(1.15); - } - .light .radio { - background-color: #fff; - color: #000; - } - - /* Show the input’s focus ring on the label. */ - label:has(:focus-visible) { - outline: auto; - outline-offset: 2px; - } - - /* Show check mark icon only when input is checked. */ - label svg { - opacity: 0; - transition: opacity var(--transition-time) ease-in-out; - } - label:has(:checked) svg { - opacity: 1; - } - - /* Stack light/dark images in the same grid row and column. */ - .preview-images { - display: grid; - grid-template-columns: 1fr; - } - .preview-images > * { - grid-area: 1 / 1; - } - - /* Fade out the preview image that isn’t currently selected. */ - img { - transition: opacity var(--transition-time) ease-in-out; - } - [data-theme-preview='dark'] img.light { - opacity: 0; - } - [data-theme-preview='light'] img.dark { - opacity: 0; - } - - .meta { - padding: 1rem; - flex-direction: column; - gap: 0.5rem; - } - - .title { - font-size: var(--sl-text-lg); - } - - .description { - color: var(--sl-color-gray-3); - line-height: 1.5; - } -</style> diff --git a/website/src/components/theme-image.astro b/website/src/components/theme-image.astro deleted file mode 100644 index 8cb10289f..000000000 --- a/website/src/components/theme-image.astro +++ /dev/null @@ -1,37 +0,0 @@ ---- -import { AstroError } from 'astro/errors'; -import { Image } from 'astro:assets'; - -interface Props { - src: string; - class: 'light' | 'dark'; -} - -const thumbnails = import.meta.glob<{ default: ImageMetadata }>( - '../assets/themes/*{.png,.jpg,.jpeg,.webp,.avif}' -); - -const thumbnail = thumbnails[`../assets/themes/${Astro.props.src}`]; -if (!thumbnail) { - throw new Error(`Could not resolve showcase thumbnail: ${Astro.props.src}`); -} -const src = (await thumbnail()).default; - -if (src.width !== 1280 || src.height !== 720) { - let fileName = src.src.split('/').pop(); - const queryIndex = fileName?.indexOf('?'); - if (queryIndex !== undefined && queryIndex > -1) { - fileName = fileName?.slice(0, queryIndex); - } - throw new AstroError( - 'Theme screenshots must be **1280×720px**', - `Dimensions of **${src.width}×${src.height}px** found for theme image \`${fileName || src.src}\`\n\n` + - `For best results:\n\n` + - `1. Take a screenshot of the site using a browser resized to **1280×720px**. The responsive view in dev tools can be helpful for this.\n\n` + - `2. Resize the screenshot to **1280×720px** if necessary and make sure it is saved as a PNG. An online tool like [Squoosh](https://squoosh.app/) can help here.\n\n` + - `See more details in the [Starlight contributing guide](https://github.com/withastro/starlight/blob/main/CONTRIBUTING.md#themes)\n` - ); -} ---- - -<Image {src} alt="" width="960" class={Astro.props.class} /> diff --git a/website/src/components/youtube-card.astro b/website/src/components/youtube-card.astro deleted file mode 100644 index cc751f3bf..000000000 --- a/website/src/components/youtube-card.astro +++ /dev/null @@ -1,34 +0,0 @@ ---- -import { YouTube } from '@astro-community/astro-embed-youtube'; -import MediaCard from './media-card.astro'; - -export interface Props { - href: string; - title: string; - description?: string; -} -const { href, title, description } = Astro.props; ---- - -<MediaCard> - <YouTube slot="media" id={href} /> - <div class="meta sl-flex"> - <p class="title">{title}</p> - {description && <p class="description" set:html={description} />} - </div> -</MediaCard> - -<style> - .meta { - padding: 1rem; - flex-direction: column; - gap: 0.5rem; - } - .title { - font-size: var(--sl-text-lg); - } - .description { - color: var(--sl-color-gray-3); - line-height: 1.5; - } -</style> diff --git a/website/src/components/youtube-grid.astro b/website/src/components/youtube-grid.astro deleted file mode 100644 index 27c8f961c..000000000 --- a/website/src/components/youtube-grid.astro +++ /dev/null @@ -1,12 +0,0 @@ ---- -import FluidGrid from './fluid-grid.astro'; -import YoutubeCard, { type Props as CardProps } from './youtube-card.astro'; - -interface Props { - videos: CardProps[]; -} ---- - -<FluidGrid minColumnWidth="16rem"> - {Astro.props.videos.map((video) => <YoutubeCard {...video} />)} -</FluidGrid> diff --git a/website/src/content.config.ts b/website/src/content.config.ts index 5526ca4ae..6c1603ca5 100644 --- a/website/src/content.config.ts +++ b/website/src/content.config.ts @@ -1,6 +1,6 @@ import { defineCollection, z } from 'astro:content'; -import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders'; -import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; export const collections = { docs: defineCollection({ @@ -14,12 +14,4 @@ export const collections = { }), }), }), - i18n: defineCollection({ - loader: i18nLoader(), - schema: i18nSchema({ - extend: z.object({ - 'component.preview': z.string().optional(), - }), - }), - }), }; diff --git a/website/src/content/docs/guides/build-your-social-media-app.mdx b/website/src/content/docs/guides/build-your-social-media-app.mdx index 7bba6f8f8..fe6e1edff 100644 --- a/website/src/content/docs/guides/build-your-social-media-app.mdx +++ b/website/src/content/docs/guides/build-your-social-media-app.mdx @@ -79,7 +79,7 @@ This guide has an interactive component that runs locally. A popup will walk you through each step. If something goes wrong, click <span class="icon-row"><RefreshCcw size={14} /> **Restart**</span> in the top-left corner. - ![Screen layout](/images/guides/social-media/00-screen-layout.png) + ![Screen layout](../../../assets/guides/social-media/00-screen-layout.png) 4. **Open in your browser** @@ -113,7 +113,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </li> </ul> - ![Welcome](/images/guides/social-media/01-welcome.png) + ![Welcome](../../../assets/guides/social-media/01-welcome.png) 2. **You are @zipdoki** @@ -121,7 +121,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro **Tip:** Press **Enter** to proceed. - ![Zipdoki intro](/images/guides/social-media/02-zipdoki-intro.png) + ![Zipdoki intro](../../../assets/guides/social-media/02-zipdoki-intro.png) 3. **Set Up** @@ -136,7 +136,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </li> </ul> - ![Set Up](/images/guides/social-media/03-set-up.png) + ![Set Up](../../../assets/guides/social-media/03-set-up.png) 4. **Load Sample Data** @@ -155,7 +155,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro load preset build-your-social-app ``` - ![Load sample data](/images/guides/social-media/04-load-sample-data.png) + ![Load sample data](../../../assets/guides/social-media/04-load-sample-data.png) 5. **Select Database** @@ -171,7 +171,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro use database social ``` - ![Select database](/images/guides/social-media/05-select-database.png) + ![Select database](../../../assets/guides/social-media/05-select-database.png) 6. **Explore the Data** @@ -188,7 +188,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro Browse around before we add new interactions. - ![Explore the Data](/images/guides/social-media/06-explore-the-data.png) + ![Explore the Data](../../../assets/guides/social-media/06-explore-the-data.png) 7. **Follows** @@ -206,7 +206,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </li> </ul> - ![Follows](/images/guides/social-media/07-follows.png) + ![Follows](../../../assets/guides/social-media/07-follows.png) 8. **Create Follows Table** @@ -218,7 +218,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </li> </ul> - ![Create Follows Table](/images/guides/social-media/08-create-follows-table.png) + ![Create Follows Table](../../../assets/guides/social-media/08-create-follows-table.png) 9. **Follow a User** @@ -255,7 +255,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </details> - ![Follow a User](/images/guides/social-media/09-follow-a-user.png) + ![Follow a User](../../../assets/guides/social-media/09-follow-a-user.png) 10. **Check Follow Status** @@ -280,7 +280,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </details> - ![Check Follow Status](/images/guides/social-media/10-check-follow-status.png) + ![Check Follow Status](../../../assets/guides/social-media/10-check-follow-status.png) 11. **Count Followers** @@ -305,7 +305,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </details> - ![Count Followers](/images/guides/social-media/11-count-followers.png) + ![Count Followers](../../../assets/guides/social-media/11-count-followers.png) 12. **List Followers** @@ -330,7 +330,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </details> - ![List Followers](/images/guides/social-media/12-list-followers.png) + ![List Followers](../../../assets/guides/social-media/12-list-followers.png) 13. **Likes** @@ -342,7 +342,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </li> </ul> - ![Likes](/images/guides/social-media/13-likes.png) + ![Likes](../../../assets/guides/social-media/13-likes.png) 14. **Like a Post** @@ -379,7 +379,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </details> - ![Like a Post](/images/guides/social-media/14-like-a-post.png) + ![Like a Post](../../../assets/guides/social-media/14-like-a-post.png) 15. **Check Like Status** @@ -404,7 +404,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </details> - ![Check Like Status](/images/guides/social-media/15-check-like-status.png) + ![Check Like Status](../../../assets/guides/social-media/15-check-like-status.png) 16. **And More** @@ -421,7 +421,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro Same pattern, same simplicity. - ![And More](/images/guides/social-media/16-and-more.png) + ![And More](../../../assets/guides/social-media/16-and-more.png) 17. **Feed** @@ -438,7 +438,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro This is the core pattern behind most social apps. - ![Feed](/images/guides/social-media/17-feed.png) + ![Feed](../../../assets/guides/social-media/17-feed.png) 18. **All Done!** @@ -458,7 +458,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro </li> </ul> - ![All Done](/images/guides/social-media/18-all-done.png) + ![All Done](../../../assets/guides/social-media/18-all-done.png) 19. **Try It Yourself** @@ -467,7 +467,7 @@ From here, continue in the **web browser**. The interactive guide walks you thro - **Check your feed** - See posts from people you follow - **Like posts** - Interact with content in your feed - ![Try it yourself](/images/guides/social-media/19-try-it-yourself.png) + ![Try it yourself](../../../assets/guides/social-media/19-try-it-yourself.png) </Steps> diff --git a/website/src/content/docs/index.mdx b/website/src/content/docs/index.mdx deleted file mode 100644 index 020b03c30..000000000 --- a/website/src/content/docs/index.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Actionbase -head: - - tag: title - content: Actionbase -description: A database for serving user interactions at scale. -template: splash -editUrl: false -lastUpdated: false -hero: - title: Actionbase - tagline: One database for user-user (follows), user-item (likes), and item-item (related items) interactions — precomputed at write time, served as simple lookups - image: - file: ~/assets/hero.webp - actions: - - text: Get started - icon: right-arrow - link: introduction/ - - text: View on GitHub - icon: external - variant: minimal - link: https://github.com/kakao/actionbase ---- - -import { CardGrid, Card } from '@astrojs/starlight/components'; - -<CardGrid stagger> - <Card title="Pre-computed Reads" icon="star"> - Writes do the work. Reads return what's already computed. - </Card> - <Card title="U2U · U2I · I2I" icon="heart"> - One model for user–user, user–item, and item–item interactions. - </Card> - <Card title="REST API" icon="forward-slash"> - Simple writes, fast reads — all via HTTP. - </Card> - <Card title="CDC Built-in" icon="seti:pipeline"> - Stream changes for downstream pipelines. - </Card> - <Card title="Battle-tested" icon="rocket"> - Serving over a million requests per minute at Kakao. - </Card> -</CardGrid> diff --git a/website/src/content/docs/stories/index.mdx b/website/src/content/docs/stories/index.mdx index 1e8e6d670..ab99f4369 100644 --- a/website/src/content/docs/stories/index.mdx +++ b/website/src/content/docs/stories/index.mdx @@ -4,7 +4,6 @@ description: Real-world patterns from production deployments at Kakao sidebar: label: Overview order: 0 -tableOfContents: false --- import CategoryDirectoryList from '../../../components/CategoryDirectoryList.astro'; diff --git a/website/src/content/i18n/en.json b/website/src/content/i18n/en.json deleted file mode 100644 index e856b05d9..000000000 --- a/website/src/content/i18n/en.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "component.preview": "Preview" -} diff --git a/website/src/content/i18n/ko.json b/website/src/content/i18n/ko.json deleted file mode 100644 index a0704ff29..000000000 --- a/website/src/content/i18n/ko.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "component.preview": "미리보기" -} diff --git a/website/src/pages/index.astro b/website/src/pages/index.astro new file mode 100644 index 000000000..d0b8dcc2d --- /dev/null +++ b/website/src/pages/index.astro @@ -0,0 +1,518 @@ +--- +import logoLight from '../assets/logo-light.svg?url'; +import logoDark from '../assets/logo-dark.svg?url'; +import { Check, Copy, Moon, Sun } from '@lucide/astro'; +import HeroArt from '../components/landing/HeroArt.astro'; +import DemoSection from '../components/landing/DemoSection.astro'; +import ArchDiagram from '../components/landing/ArchDiagram.astro'; +import '../assets/landing-page.css'; + +// Standalone marketing landing. Kept outside Starlight's content collection so +// the bespoke chrome (marginalia, hero console, architecture flow) has full +// layout control; theme state still syncs with Starlight via the shared +// `starlight-theme` localStorage key and `<html data-theme>` attribute. + +const GA_ID = 'G-2PY5JXRJ5J'; +const site = 'https://actionbase.io/'; +const pageTitle = 'Actionbase — A database for user interactions at scale'; +const description = + 'Actionbase serves follows, likes, and views as precomputed lookups — one model for ' + + 'user–user, user–item, and item–item interactions, in production at Kakao at over a ' + + 'million requests per minute.'; +const ogUrl = new URL('og.png?v=1', site).href; +const ogImageAlt = + 'Actionbase is a production-proven OLTP database serving tens of millions of users across Kakao.'; +const repo = 'https://github.com/kakao/actionbase'; + +const primaryFeatures = [ + { title: 'Pre-computed Reads', desc: 'Writes do the work. Reads return what’s already computed.' }, + { title: 'U2U · U2I · I2I', desc: 'One model for user–user, user–item, and item–item interactions.' }, + { title: 'Battle-tested', desc: 'Over a million requests per minute in stable production at Kakao.' }, +]; + +const platformFeatures = [ + { title: 'REST API', desc: 'Simple writes, fast reads — all via HTTP.' }, + { title: 'CDC Built-in', desc: 'Stream changes for downstream pipelines.' }, + { title: 'Pluggable Storage', desc: 'A minimal storage abstraction — HBase today, SlateDB planned.' }, +]; + +const steps = [ + { n: '1', label: 'Run', code: 'docker run -it \\\n ghcr.io/kakao/actionbase:standalone' }, + { n: '2', label: 'Load sample data', code: 'load preset likes' }, + { + n: '3', + label: 'Query — just read', + code: 'get --source Alice --target Phone\nscan --index recent --start Bob --direction OUT\ncount --start Phone --direction IN', + }, +]; + +--- + +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <title>{pageTitle} + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ +
+
+

+ Precomputed at write time, served as simple lookups +

+

+ One database for user–user (follows), user–item (likes), and item–item (related + items) interactions. +

+ +
+ + +
+ + +
+
+

+ Serving over a million requests per minute, in production at Kakao. +

+
+ Apache-2.0 + REST · CDC + HBase / SlateDB +
+
+
+ + + + + +
+
+

Why Actionbase

+ Built for interaction data +
+
+ Core advantages +
+ { + primaryFeatures.map((f, i) => ( +
+ {String(i + 1).padStart(2, '0')} +

{f.title}

+

{f.desc}

+
+ )) + } +
+
+
+ Platform capabilities +
+ { + platformFeatures.map((f, i) => ( +
+ {String(i + 4).padStart(2, '0')} +

{f.title}

+

{f.desc}

+
+ )) + } +
+
+
+ + +
+
+

Architecture

+ Client → Actionbase → storage & stream +
+ +
+ + +
+
+
+

Quick start

+ Three steps +
+
+ { + steps.map((s) => ( +
+
+ {s.n} + {s.label} + +
+
+
{s.code}
+
+
+ )) + } +
+

+ See the Quick Start, or + Build Your Social Media App to go deeper. +

+
+
+ + +
+
+

Start building

+

+ The reference covers concepts, architecture, and hands-on guides — from a single write to a + million reads per minute. +

+ +
+
+
+ + + +
+ + + +