feat(documentation): svelte app as document generator (#566)
* check in full site application * rm unused assets components * change base css * i18n * new doc workflow * fix crosslink to doc in github * nav, console link, assets, console brand * edit configjs server * rm go struct references * cleanup input output bindings * working dir * export path * always trigger * rel paths * cname * rev workdir * fix fallbacklanguage, home on large screens * remove mit from site
53
.github/workflows/docs.yml
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
name: Docs
|
||||
on: push
|
||||
# push:
|
||||
# paths:
|
||||
# - 'site/**'
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
jobs:
|
||||
builddocs:
|
||||
name: Build Doc Frontend
|
||||
runs-on: ubuntu-18.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./site
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Install and Build
|
||||
run: |
|
||||
npm install
|
||||
npx sapper export --legacy
|
||||
- name: Archive Production Artifact
|
||||
uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: export
|
||||
path: site/__sapper__/export
|
||||
deploydocs:
|
||||
name: Deploy
|
||||
needs: builddocs
|
||||
runs-on: ubuntu-latest
|
||||
# defaults:
|
||||
# run:
|
||||
# working-directory: ./site
|
||||
# if: github.ref == 'refs/heads/master'
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@master
|
||||
- name: Download Artifact
|
||||
uses: actions/download-artifact@master
|
||||
with:
|
||||
name: export
|
||||
path: site/__sapper__/export
|
||||
- name: Add CNAME file
|
||||
run: echo "docs.zitadel.ch" > site/__sapper__/export/CNAME
|
||||
- name: Deploy
|
||||
uses: JamesIves/github-pages-deploy-action@releases/v3
|
||||
with:
|
||||
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
||||
BRANCH: gh-pages
|
||||
FOLDER: site/__sapper__/export
|
||||
CLEAN: true
|
5
site/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
yarn-error.log
|
||||
/cypress/screenshots/
|
||||
/__sapper__/
|
18
site/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
## Getting started
|
||||
|
||||
Caos Site is a github action that generates a static page out of markdown files. It uses marked.js in combination with highlight.js to compile and style markdown.
|
||||
The documentiation is built according to the structure of a docs `folder`[Folder](https://github.com/caos/site/tree/master/docs) located at root of the targeted repository.
|
||||
|
||||
## Running locally
|
||||
|
||||
Set up the project:
|
||||
|
||||
```bash
|
||||
npm i
|
||||
```
|
||||
|
||||
Start the server with `npm run dev`, and navigate to [localhost:3000](http://localhost:3000).
|
||||
|
||||
### Honorable Mentions
|
||||
|
||||
This project was created with the help of some components from [svelte](https://github.com/sveltejs/svelte)([MIT](https://github.com/sveltejs/svelte/blob/master/LICENSE)) as well as [site-kit](https://github.com/sveltejs/site-kit)([MIT](https://github.com/sveltejs/site-kit/blob/master/LICENSE)).
|
18
site/appveyor.yml
Normal file
@ -0,0 +1,18 @@
|
||||
version: "{build}"
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf false
|
||||
|
||||
build: off
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
# node.js
|
||||
- nodejs_version: stable
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
- npm install cypress
|
||||
- npm install
|
4
site/config.js
Normal file
@ -0,0 +1,4 @@
|
||||
export const SLUG_PRESERVE_UNICODE = false;
|
||||
export const SLUG_SEPARATOR = '_';
|
||||
export const SLUG_LANG = 'en';
|
||||
export const LANGUAGES = ['de', 'en'];
|
4
site/cypress.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:3000",
|
||||
"video": false
|
||||
}
|
5
site/cypress/fixtures/example.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
19
site/cypress/integration/spec.js
Normal file
@ -0,0 +1,19 @@
|
||||
describe('Sapper template app', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/')
|
||||
});
|
||||
|
||||
it('has the correct <h1>', () => {
|
||||
cy.contains('h1', 'Great success!')
|
||||
});
|
||||
|
||||
it('navigates to /about', () => {
|
||||
cy.get('nav a').contains('about').click();
|
||||
cy.url().should('include', '/about');
|
||||
});
|
||||
|
||||
it('navigates to /blog', () => {
|
||||
cy.get('nav a').contains('blog').click();
|
||||
cy.url().should('include', '/blog');
|
||||
});
|
||||
});
|
17
site/cypress/plugins/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
25
site/cypress/support/commands.js
Normal file
@ -0,0 +1,25 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
20
site/cypress/support/index.js
Normal file
@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
8
site/docs/get_started/00-introduction.de.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
title: Einführung
|
||||
---
|
||||
|
||||
### Bevor es los geh't
|
||||
|
||||
> Dies ist eine frühe Version unseres Dokumentgenerators. Es können noch einige Dinge ändern, bis wir Version 1.0 erreichen.
|
||||
|
8
site/docs/get_started/00-introduction.en.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
### Before we begin
|
||||
|
||||
> This is an early version of our documentation. Some things may change until we hit version 1.0.
|
||||
> This Documentation is and always will be a WIP, and will therefore be updated frequently.
|
14
site/docs/get_started/01-capabilities.de.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Wie fange ich an?
|
||||
description: Dieses Dokument beschreibt die Schlüsselfähigkeiten und führt in verschiedene Startszenarien ein
|
||||
---
|
||||
|
||||
<!-- ## Wo fange ich mit der Zitadel-Authentifizierung an? -->
|
||||
|
||||
### I already have an authentication system
|
||||
|
||||
Wenn Ihre App bereits über eine Anmeldeimplementierung verfügt und Sie diese zur Authentifizierung für Zitadel-Backend-Diensten verwenden möchten, lesen Sie unsere `Migrationsanleitung`.
|
||||
|
||||
### Ich möchte mein Authentifizierungssystem mit Zitadel erstellen
|
||||
|
||||
Wenn Sie eine neue App erstellen oder einer vorhandenen App eine Anmeldung hinzufügen, verfügt Zitadel über Bibliotheken und Dienste, mit denen Sie die sichere Authentifizierung implementieren können, ohne das Authentifizierungs-Backend selbst erstellen zu müssen. Die Zitadel-Authentifizierung ist eine vollständige Backend-Lösung, die die Anmeldung mit Kennwörtern und weiteren Faktoren zur verbesserten Sicherheit ermöglicht
|
14
site/docs/get_started/01-capabilities.en.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Where to start?
|
||||
description: This document explains zitadels key capabilities
|
||||
---
|
||||
|
||||
<!-- ## Where to start? -->
|
||||
|
||||
### I already have an authentication system
|
||||
|
||||
If your app already has a sign-in implementation and you want to use it to authenticate with Zitadel backend services, read our `migration documentation`.
|
||||
|
||||
### I want to build my authentication system with Zitadel
|
||||
|
||||
If you're building a new app or adding sign-in to an existing app, Zitadel has libraries and services that can help you implement secure authentication without having to build the authentication backend yourself. Zitadel Authentication is a complete backend solution for signing in with passwords and additional Factors for enhanced Security.
|
32
site/docs/get_started/02-go-structs.de.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Go structs
|
||||
---
|
||||
|
||||
### Go structures
|
||||
|
||||
You can reference go struct tables from our go struct generator.
|
||||
Provide a `doc_assets` folder with all generated files in it.
|
||||
Make sure that the `.md` file consists of no other than the table itself and metadata which defines name and description of the struct
|
||||
|
||||
|
||||
| Attribute | Description | Default | Collection |
|
||||
| --------------------------- | ------------------------------------------------------------------------------- | ------- | ---------- |
|
||||
| boomVersion | Version of BOOM which should be reconciled | | |
|
||||
| forceApply | Relative folder path where the currentstate is written to | | |
|
||||
| currentStatePath | Flag if --force should be used by apply of resources | | |
|
||||
| preApply | Spec for the yaml-files applied before applications | | |
|
||||
| postApply | Spec for the yaml-files applied after applicatio | | |
|
||||
| prometheus-operator | Spec for the Prometheus-Operator , | | |
|
||||
| logging-operator | Spec for the Banzaicloud Logging-Operator , | | |
|
||||
| prometheus-node-exporter | Spec for the Prometheus-Node-Exporter , | | |
|
||||
| prometheus-systemd-exporter | Spec for the Prometheus-Systemd-Exporter , | | |
|
||||
| grafana | Spec for the Grafana , [ | | |
|
||||
| ambassador | Spec for the Ambassador , | | |
|
||||
| kube-state-metrics | Spec for the Kube-State-Metrics , | | |
|
||||
| argocd | Spec for the Argo-CD , | | |
|
||||
| prometheus | Spec for the Prometheus instance , | | |
|
||||
| loki | Spec for the Loki instance , | | |
|
||||
|
||||
#### References
|
||||
|
||||
To reference a table ...
|
32
site/docs/get_started/02-go-structs.en.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Go structs
|
||||
---
|
||||
|
||||
### Go structures
|
||||
|
||||
You can reference go struct tables from our go struct generator.
|
||||
Provide a `doc_assets` folder with all generated files in it.
|
||||
Make sure that the `.md` file consists of no other than the table itself and metadata which defines name and description of the struct
|
||||
|
||||
|
||||
| Attribute | Description | Default | Collection |
|
||||
| --------------------------- | ------------------------------------------------------------------------------- | ------- | ---------- |
|
||||
| boomVersion | Version of BOOM which should be reconciled | | |
|
||||
| forceApply | Relative folder path where the currentstate is written to | | |
|
||||
| currentStatePath | Flag if --force should be used by apply of resources | | |
|
||||
| preApply | Spec for the yaml-files applied before applications | | |
|
||||
| postApply | Spec for the yaml-files applied after applicatio | | |
|
||||
| prometheus-operator | Spec for the Prometheus-Operator , | | |
|
||||
| logging-operator | Spec for the Banzaicloud Logging-Operator , | | |
|
||||
| prometheus-node-exporter | Spec for the Prometheus-Node-Exporter , | | |
|
||||
| prometheus-systemd-exporter | Spec for the Prometheus-Systemd-Exporter , | | |
|
||||
| grafana | Spec for the Grafana , [ | | |
|
||||
| ambassador | Spec for the Ambassador , | | |
|
||||
| kube-state-metrics | Spec for the Kube-State-Metrics , | | |
|
||||
| argocd | Spec for the Argo-CD , | | |
|
||||
| prometheus | Spec for the Prometheus instance , | | |
|
||||
| loki | Spec for the Loki instance , | | |
|
||||
|
||||
#### References
|
||||
|
||||
To reference a table ...
|
5
site/docs/get_started/03-concluding.de.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
title: Abschliessendes
|
||||
---
|
||||
|
||||
Das war unsere Dokumentation
|
5
site/docs/get_started/03-concluding.en.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
title: Concluding
|
||||
---
|
||||
|
||||
This was our documentation
|
16
site/docs/get_started/seo.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"tags": [
|
||||
{
|
||||
"name": "twitter:title",
|
||||
"content":"Docs demo page"
|
||||
},
|
||||
{
|
||||
"name": "twitter:description",
|
||||
"content":"Docs demo page description"
|
||||
},
|
||||
{
|
||||
"name": "Description",
|
||||
"content":"Docs demo page description"
|
||||
}
|
||||
]
|
||||
}
|
3086
site/package-lock.json
generated
Normal file
44
site/package.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "site",
|
||||
"description": "site",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "sapper dev",
|
||||
"build": "sapper build --legacy",
|
||||
"export": "sapper export --legacy",
|
||||
"start": "node __sapper__/build",
|
||||
"cy:run": "cypress run",
|
||||
"cy:open": "cypress open",
|
||||
"test": "run-p --race dev cy:run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polka/send": "^0.4.0",
|
||||
"@sindresorhus/slugify": "^1.1.0",
|
||||
"compression": "^1.7.4",
|
||||
"golden-fleece": "^1.0.9",
|
||||
"highlight.js": "^10.1.2",
|
||||
"marked": "^1.1.1",
|
||||
"polka": "^0.5.2",
|
||||
"sirv": "^0.4.2",
|
||||
"svelte-i18n": "^3.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.9.0",
|
||||
"@babel/preset-env": "^7.9.0",
|
||||
"@babel/runtime": "^7.9.2",
|
||||
"@rollup/plugin-commonjs": "^14.0.0",
|
||||
"@rollup/plugin-json": "^4.0.3",
|
||||
"@rollup/plugin-node-resolve": "^8.0.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^2.15.0",
|
||||
"rollup-plugin-babel": "^4.4.0",
|
||||
"rollup-plugin-livereload": "^1.3.0",
|
||||
"rollup-plugin-replace": "^2.2.0",
|
||||
"rollup-plugin-svelte": "^5.2.0",
|
||||
"rollup-plugin-terser": "^6.1.0",
|
||||
"sapper": "^0.27.14",
|
||||
"svelte": "^3.20.1"
|
||||
}
|
||||
}
|
97
site/rollup.config.js
Normal file
@ -0,0 +1,97 @@
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import json from '@rollup/plugin-json';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import babel from 'rollup-plugin-babel';
|
||||
import replace from 'rollup-plugin-replace';
|
||||
import svelte from 'rollup-plugin-svelte';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import config from 'sapper/config/rollup.js';
|
||||
|
||||
import pkg from './package.json';
|
||||
|
||||
const mode = process.env.NODE_ENV;
|
||||
const dev = mode === 'development';
|
||||
const legacy = !!process.env.SAPPER_LEGACY_BUILD;
|
||||
|
||||
const onwarn = (warning, onwarn) => (warning.code === 'CIRCULAR_DEPENDENCY' && /[/\\]@sapper[/\\]/.test(warning.message)) || onwarn(warning);
|
||||
|
||||
export default {
|
||||
client: {
|
||||
input: config.client.input(),
|
||||
output: config.client.output(),
|
||||
plugins: [
|
||||
replace({
|
||||
'process.browser': true,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode)
|
||||
}),
|
||||
svelte({
|
||||
dev,
|
||||
hydratable: true,
|
||||
emitCss: true
|
||||
}),
|
||||
resolve(),
|
||||
commonjs(),
|
||||
|
||||
legacy && babel({
|
||||
extensions: ['.js', '.mjs', '.html', '.svelte'],
|
||||
runtimeHelpers: true,
|
||||
exclude: ['node_modules/@babel/**'],
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
targets: '> 0.25%, not dead'
|
||||
}]
|
||||
],
|
||||
plugins: [
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
['@babel/plugin-transform-runtime', {
|
||||
useESModules: true
|
||||
}]
|
||||
]
|
||||
}),
|
||||
|
||||
!dev && terser({
|
||||
module: true
|
||||
}),
|
||||
|
||||
json()
|
||||
],
|
||||
onwarn,
|
||||
},
|
||||
|
||||
server: {
|
||||
input: config.server.input(),
|
||||
output: config.server.output(),
|
||||
plugins: [
|
||||
replace({
|
||||
'process.browser': false,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode)
|
||||
}),
|
||||
svelte({
|
||||
generate: 'ssr',
|
||||
dev
|
||||
}),
|
||||
resolve(),
|
||||
commonjs(),
|
||||
json()
|
||||
],
|
||||
external: Object.keys(pkg.dependencies).concat(
|
||||
require('module').builtinModules || Object.keys(process.binding('natives'))
|
||||
),
|
||||
onwarn,
|
||||
},
|
||||
|
||||
serviceworker: {
|
||||
input: config.serviceworker.input(),
|
||||
output: config.serviceworker.output(),
|
||||
plugins: [
|
||||
resolve(),
|
||||
replace({
|
||||
'process.browser': true,
|
||||
'process.env.NODE_ENV': JSON.stringify(mode)
|
||||
}),
|
||||
commonjs(),
|
||||
!dev && terser()
|
||||
],
|
||||
onwarn,
|
||||
},
|
||||
};
|
11
site/src/client.js
Normal file
@ -0,0 +1,11 @@
|
||||
import '../static/base.css';
|
||||
|
||||
import * as sapper from '@sapper/app';
|
||||
|
||||
import { startClient } from './i18n.js';
|
||||
|
||||
startClient();
|
||||
|
||||
sapper.start({
|
||||
target: document.querySelector('#sapper')
|
||||
});
|
121
site/src/components/CodeTable.svelte
Normal file
@ -0,0 +1,121 @@
|
||||
<script>
|
||||
let tabs = [
|
||||
{lang: 'yaml', content:"main: halllo"},
|
||||
{lang: 'js', content:"console.log();"},
|
||||
{lang: 'html', content:"<p>hello</p>"},
|
||||
]
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.pc-tab > input,
|
||||
.pc-tab section > div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#tab1:checked ~ section .tab1,
|
||||
#tab2:checked ~ section .tab2,
|
||||
#tab3:checked ~ section .tab3 {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#tab1:checked ~ nav .tab1,
|
||||
#tab2:checked ~ nav .tab2,
|
||||
#tab3:checked ~ nav .tab3 {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* Visual Styles */
|
||||
*, *:after, *:before {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.pc-tab {
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.pc-tab ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.pc-tab ul li label {
|
||||
float: left;
|
||||
padding: 10px 25px;
|
||||
border: 1px solid #8795a1;
|
||||
border-bottom: 0;
|
||||
background: #212224;
|
||||
}
|
||||
.pc-tab ul li:first-child label {
|
||||
border-top-left-radius: 8px;
|
||||
}
|
||||
|
||||
.pc-tab ul li:last-child label {
|
||||
border-top-right-radius: 8px;
|
||||
}
|
||||
.pc-tab ul li label:hover {
|
||||
background: #ffffff20;
|
||||
}
|
||||
.pc-tab ul li label:active {
|
||||
background: #ffffff30;
|
||||
}
|
||||
.pc-tab ul li:not(:last-child) label {
|
||||
border-right-width: 0;
|
||||
}
|
||||
.pc-tab section {
|
||||
clear: both;
|
||||
}
|
||||
.pc-tab section div {
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
border: 1px solid #8795a1;
|
||||
background: #1e1e1e;
|
||||
line-height: 1.5em;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
#tab1:checked ~ nav .tab1 label,
|
||||
#tab2:checked ~ nav .tab2 label,
|
||||
#tab3:checked ~ nav .tab3 label {
|
||||
background: #1e1e1e;
|
||||
position: relative;
|
||||
color: white;
|
||||
}
|
||||
#tab1:checked ~ nav .tab1 label:after,
|
||||
#tab2:checked ~ nav .tab2 label:after,
|
||||
#tab3:checked ~ nav .tab3 label:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
background: #1e1e1e;
|
||||
left: 0;
|
||||
bottom: -1px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="pc-tab">
|
||||
<input checked id="tab1" type="radio" name="pct" />
|
||||
<input id="tab2" type="radio" name="pct" />
|
||||
<input id="tab3" type="radio" name="pct" />
|
||||
<nav>
|
||||
<ul>
|
||||
{#each tabs as { lang }, i}
|
||||
<li class="tab{i+1}">
|
||||
<label for="tab{i+1}">{lang}</label>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
{#each tabs as { lang, content }, i}
|
||||
<div class="tab{i+1}">
|
||||
{content}
|
||||
</div>
|
||||
{/each}
|
||||
</section>
|
||||
</div>
|
428
site/src/components/Docs.svelte
Normal file
@ -0,0 +1,428 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import GuideContents from "./GuideContents.svelte"; // TODO rename
|
||||
import Icon from "./Icon.svelte";
|
||||
import manifest from '../../static/manifest.json';
|
||||
export let owner = "caos";
|
||||
export let project = "zitadel/site";
|
||||
export let path = "/docs";
|
||||
export let dir = "";
|
||||
export let edit_title = "edit this section";
|
||||
export let sections;
|
||||
let active_section;
|
||||
|
||||
let container;
|
||||
let aside;
|
||||
let show_contents = false;
|
||||
|
||||
onMount(() => {
|
||||
// don't update `active_section` for headings above level 4, see _sections.js
|
||||
const anchors = container.querySelectorAll("[id]:not([data-scrollignore])");
|
||||
|
||||
let positions;
|
||||
|
||||
const onresize = () => {
|
||||
const { top } = container.getBoundingClientRect();
|
||||
positions = [].map.call(anchors, anchor => {
|
||||
return anchor.getBoundingClientRect().top - top;
|
||||
});
|
||||
};
|
||||
|
||||
let last_id = window.location.hash.slice(1);
|
||||
|
||||
const onscroll = () => {
|
||||
const top = -window.scrollY;
|
||||
|
||||
let i = anchors.length;
|
||||
while (i--) {
|
||||
if (positions[i] + top < 40) {
|
||||
const anchor = anchors[i];
|
||||
const { id } = anchor;
|
||||
|
||||
if (id !== last_id) {
|
||||
active_section = id;
|
||||
last_id = id;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("scroll", onscroll, true);
|
||||
window.addEventListener("resize", onresize, true);
|
||||
|
||||
// wait for fonts to load...
|
||||
const timeouts = [setTimeout(onresize, 1000), setTimeout(onscroll, 5000)];
|
||||
|
||||
onresize();
|
||||
onscroll();
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("scroll", onscroll, true);
|
||||
window.removeEventListener("resize", onresize, true);
|
||||
|
||||
timeouts.forEach(timeout => clearTimeout(timeout));
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
aside {
|
||||
position: fixed;
|
||||
background-color: var(--side-nav-back);
|
||||
left: 0.8rem;
|
||||
bottom: 0.8rem;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
border-radius: .5rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid #8795a1;
|
||||
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.1);
|
||||
transition: width 0.2s, height 0.2s;
|
||||
}
|
||||
|
||||
aside button {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 3.4rem;
|
||||
height: 3.4rem;
|
||||
}
|
||||
|
||||
aside.open {
|
||||
width: calc(100vw - 3rem);
|
||||
height: calc(100vh - var(--nav-h) - 3rem);
|
||||
}
|
||||
|
||||
aside.open::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: calc(100% - 2rem);
|
||||
height: 2em;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
aside::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 1.9em;
|
||||
width: calc(100% - 2rem);
|
||||
height: 2em;
|
||||
/* background: linear-gradient(
|
||||
to bottom,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.7) 50%,
|
||||
rgba(255, 255, 255, 1) 100%
|
||||
); */
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: absolute;
|
||||
font-family: var(--font);
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 4em 1.6rem 2em 3.2rem;
|
||||
bottom: 2em;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: var(--top-offset) var(--side-nav);
|
||||
tab-size: 2;
|
||||
-moz-tab-size: 2;
|
||||
}
|
||||
|
||||
@media (min-width: 832px) {
|
||||
/* can't use vars in @media :( */
|
||||
aside {
|
||||
display: block;
|
||||
width: var(--sidebar-w);
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
background-color: var(--side-nav-back);
|
||||
color: white;
|
||||
}
|
||||
|
||||
aside.open::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
aside::after {
|
||||
content: "";
|
||||
bottom: 0;
|
||||
height: var(--top-offset);
|
||||
/* background: linear-gradient(
|
||||
to bottom,
|
||||
rgba(103, 103, 120, 0) 0%,
|
||||
rgba(103, 103, 120, 0.7) 50%,
|
||||
rgba(103, 103, 120, 1) 100%
|
||||
); */
|
||||
}
|
||||
|
||||
aside button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
padding: var(--top-offset) 0 6.4rem 3.2rem;
|
||||
font-family: var(--font);
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
bottom: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-left: calc(var(--sidebar-w) + var(--side-nav));
|
||||
}
|
||||
|
||||
.content :global(.side-by-side) {
|
||||
display: grid;
|
||||
grid-template-columns: calc(50% - 0.5em) calc(50% - 0.5em);
|
||||
grid-gap: 1em;
|
||||
}
|
||||
|
||||
.content :global(.side-by-side) :global(.code) {
|
||||
padding: 1em 0;
|
||||
}
|
||||
}
|
||||
|
||||
.content h2 {
|
||||
margin-top: 8rem;
|
||||
padding: 2rem 1.6rem 4rem 0.2rem;
|
||||
border-top: var(--border-w) solid #6767785b; /* based on --second */
|
||||
color: var(--text);
|
||||
line-height: 1;
|
||||
font-size: var(--h3);
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.content section:first-of-type > h2 {
|
||||
margin-top: -8rem;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.content :global(h4) {
|
||||
margin: 2em 0 1em 0;
|
||||
}
|
||||
|
||||
.content :global(.offset-anchor) {
|
||||
position: relative;
|
||||
display: block;
|
||||
top: calc(-1 * (var(--nav-h) + var(--top-offset) - 1rem));
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.content :global(.anchor) {
|
||||
position: absolute;
|
||||
display: block;
|
||||
/* TODO replace link icon */
|
||||
/* background: url(../icons/link.svg) 0 50% no-repeat; */
|
||||
background-size: 1em 1em;
|
||||
width: 1.4em;
|
||||
height: 1em;
|
||||
left: -1.3em;
|
||||
opacity: 0;
|
||||
color: white;
|
||||
transition: opacity 0.2s;
|
||||
border: none !important; /* TODO get rid of linkify */
|
||||
}
|
||||
|
||||
.content :global(.anchor) :global(i) {
|
||||
color: #8795a1;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.content :global(h2):hover :global(.anchor),
|
||||
.content :global(h3):hover :global(.anchor),
|
||||
.content :global(h4):hover :global(.anchor),
|
||||
.content :global(h5):hover :global(.anchor),
|
||||
.content :global(h6):hover :global(.anchor) {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.content :global(h5) :global(.anchor),
|
||||
.content :global(h6) :global(.anchor) {
|
||||
top: 0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.content :global(h3),
|
||||
.content :global(h3 > code) {
|
||||
margin: 6.4rem 0 0 0;
|
||||
padding: 2rem 1.6rem 5.6rem 0.2rem;
|
||||
color: var(--text);
|
||||
border-top: var(--border-w) solid #6767781f; /* based on --second */
|
||||
background: transparent;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.content :global(h3):first-of-type {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* avoid doubled border-top */
|
||||
.content :global(h3 > code) {
|
||||
border-radius: 0 0 0 0;
|
||||
border: none;
|
||||
font-size: inherit;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.content :global(h4),
|
||||
.content :global(h4 > code) {
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
font-size: 2.4rem;
|
||||
color: var(--text);
|
||||
margin: 6.4rem 0 1.6rem 0;
|
||||
padding-left: 0;
|
||||
background: transparent;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.content :global(h4 > em) {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.content :global(h5) {
|
||||
font-size: 2.4rem;
|
||||
margin: 2em 0 0.5em 0;
|
||||
}
|
||||
|
||||
.content :global(code) {
|
||||
padding: 0.3rem 0.8rem 0.3rem;
|
||||
margin: 0 0.2rem;
|
||||
top: -0.1rem;
|
||||
background: var(--back-api);
|
||||
}
|
||||
|
||||
.content :global(pre) :global(code) {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
top: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.content :global(pre) {
|
||||
margin: 0 0 2em 0;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.content :global(.icon) {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
stroke: currentColor;
|
||||
stroke-width: 2;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.content :global(table) {
|
||||
margin: 0 0 2em 0;
|
||||
}
|
||||
|
||||
section > :global(.code-block) > :global(pre) {
|
||||
display: inline-block;
|
||||
/* background: var(--back-api); */
|
||||
color: white;
|
||||
padding: 0.3rem 0.8rem;
|
||||
margin: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
section > :global(.code-block) > :global(pre.language-markup) {
|
||||
padding: 0.3rem 0.8rem 0.2rem;
|
||||
background: var(--back-api);
|
||||
}
|
||||
|
||||
section > :global(p) {
|
||||
max-width: var(--linemax);
|
||||
}
|
||||
|
||||
section :global(p) {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: var(--h5);
|
||||
float: right;
|
||||
pointer-events: all;
|
||||
color: var(--prime);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* no linkify on these */
|
||||
small a {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
small a:before {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
section :global(blockquote) {
|
||||
color: #e91e63;
|
||||
border: 2px solid var(--flash);
|
||||
}
|
||||
|
||||
section :global(blockquote) :global(code) {
|
||||
background: hsl(204, 100%, 95%) !important;
|
||||
color: #e91e63;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div bind:this={container} class="content listify">
|
||||
{#each sections as section}
|
||||
<section data-id={section.slug}>
|
||||
<h2>
|
||||
<span class="offset-anchor" id={section.slug} />
|
||||
<!-- svelte-ignore a11y-missing-content -->
|
||||
<a href="{dir}#{section.slug}" class="anchor" aria-hidden />
|
||||
|
||||
{@html section.metadata.title}
|
||||
<small>
|
||||
<a
|
||||
href="https://github.com/{owner}/{project}/edit/master{path}/{dir}/{section.file}"
|
||||
title={edit_title}>
|
||||
<Icon name="las la-external-link-alt" size="24px" />
|
||||
</a>
|
||||
</small>
|
||||
</h2>
|
||||
|
||||
{@html section.html}
|
||||
</section>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<aside bind:this={aside} class="sidebar-container" class:open={show_contents}>
|
||||
<div class="sidebar" on:click={() => (show_contents = false)}>
|
||||
<!-- scroll container -->
|
||||
<GuideContents {dir} {sections} {active_section} {show_contents} />
|
||||
</div>
|
||||
|
||||
<button on:click={() => (show_contents = !show_contents)}>
|
||||
<Icon name={show_contents ? 'las la-window-close' : 'las la-bars'} />
|
||||
</button>
|
||||
</aside>
|
142
site/src/components/GuideContents.svelte
Normal file
@ -0,0 +1,142 @@
|
||||
<script>
|
||||
import { afterUpdate } from 'svelte';
|
||||
import Icon from './Icon.svelte';
|
||||
import CodeTable from './CodeTable.svelte';
|
||||
export let dir = '';
|
||||
export let sections = [];
|
||||
export let active_section = null;
|
||||
export let show_contents;
|
||||
export let prevent_sidebar_scroll = false;
|
||||
|
||||
let ul;
|
||||
|
||||
afterUpdate(() => {
|
||||
// bit of a hack — prevent sidebar scrolling if
|
||||
// TOC is open on mobile, or scroll came from within sidebar
|
||||
if (prevent_sidebar_scroll || show_contents && window.innerWidth < 832) return;
|
||||
|
||||
const active = ul.querySelector('.active');
|
||||
|
||||
if (active) {
|
||||
const { top, bottom } = active.getBoundingClientRect();
|
||||
|
||||
const min = 200;
|
||||
const max = window.innerHeight - 200;
|
||||
|
||||
if (top > max) {
|
||||
ul.parentNode.scrollBy({
|
||||
top: top - max,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
} else if (bottom < min) {
|
||||
ul.parentNode.scrollBy({
|
||||
top: bottom - min,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.reference-toc li {
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
margin: 0 0 4rem 0;
|
||||
}
|
||||
|
||||
a {
|
||||
position: relative;
|
||||
transition: color 0.2s;
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
color: var(--dark-text);
|
||||
}
|
||||
|
||||
.section {
|
||||
display: block;
|
||||
padding: 0 0 .8rem 0;
|
||||
font-size: var(--h6);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.subsection {
|
||||
display: block;
|
||||
font-size: 1.6rem;
|
||||
font-family: var(--font);
|
||||
padding: 0 0 0.6em 0;
|
||||
}
|
||||
|
||||
.section:hover,
|
||||
.subsection:hover,
|
||||
.active {
|
||||
color: var(--flash);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.subsection[data-level="4"] {
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
position: absolute;
|
||||
top: -.2rem;
|
||||
right: 2.4rem;
|
||||
}
|
||||
|
||||
@media (min-width: 832px) {
|
||||
a {
|
||||
color: var(--sidebar-text);
|
||||
}
|
||||
|
||||
a:hover,
|
||||
.section:hover,
|
||||
.subsection:hover,
|
||||
.active {
|
||||
color: #5282c1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<ul
|
||||
bind:this={ul}
|
||||
class="reference-toc"
|
||||
on:mouseenter="{() => prevent_sidebar_scroll = true}"
|
||||
on:mouseleave="{() => prevent_sidebar_scroll = false}"
|
||||
>
|
||||
{#each sections as section}
|
||||
<li>
|
||||
<a class="section" class:active="{section.slug === active_section}" href="{dir}#{section.slug}">
|
||||
{@html section.metadata.title}
|
||||
|
||||
{#if section.slug === active_section}
|
||||
<div class="icon-container">
|
||||
<Icon name="las la-arrow-right" />
|
||||
</div>
|
||||
{/if}
|
||||
</a>
|
||||
|
||||
{#each section.subsections as subsection}
|
||||
<!-- see <script> below: on:click='scrollTo(event, subsection.slug)' -->
|
||||
<a
|
||||
class="subsection"
|
||||
class:active="{subsection.slug === active_section}"
|
||||
href="{dir}#{subsection.slug}"
|
||||
data-level="{subsection.level}"
|
||||
>
|
||||
{@html subsection.title}
|
||||
|
||||
{#if subsection.slug === active_section}
|
||||
<div class="icon-container">
|
||||
<Icon name="las la-arrow-right" />
|
||||
</div>
|
||||
{/if}
|
||||
</a>
|
||||
{/each}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
20
site/src/components/Icon.svelte
Normal file
@ -0,0 +1,20 @@
|
||||
<script>
|
||||
export let name;
|
||||
export let size = '20px';
|
||||
</script>
|
||||
|
||||
<style>
|
||||
:global(i) {
|
||||
font-size: 20px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
-o-object-fit: contain;
|
||||
object-fit: contain;
|
||||
-webkit-transform-origin: center center;
|
||||
transform-origin: center center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i class={name} style="font-size: {size}; height: {size};"><use xlink:href="#{name}" /></i>
|
65
site/src/components/LanguageSwitcher.svelte
Normal file
@ -0,0 +1,65 @@
|
||||
<script context="module">
|
||||
import { setCookie } from '../modules/cookie.js';
|
||||
import { docLanguages } from '../modules/language-store.js'
|
||||
import {LANGUAGES} from '../../config.js';
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { locale } from 'svelte-i18n';
|
||||
import { startClient } from '../i18n.js';
|
||||
|
||||
let group= $locale;
|
||||
|
||||
$:setLocale(group);
|
||||
function setLocale(language) {
|
||||
if (typeof window !== 'undefined') {
|
||||
locale.set(language);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--deep-blue: #1e3470;
|
||||
--speed3: cubic-bezier(0.26, 0.48, 0.08, 0.9);
|
||||
--height: 30px;
|
||||
}
|
||||
|
||||
.language-switcher {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.language-switcher input {
|
||||
appearance: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.language-switcher .select {
|
||||
height: var(--height);
|
||||
width: var(--height);
|
||||
border-radius: 50vw;
|
||||
font-size: calc(var(--height) / 2.5);
|
||||
color: #fff;
|
||||
mix-blend-mode: difference;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.language-switcher .current {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="language-switcher">
|
||||
{#each LANGUAGES as lang}
|
||||
<label class="select {lang == group ? 'current' : 'notcurrent'}">
|
||||
<input type=radio bind:group value={lang}>
|
||||
{lang.toUpperCase()}
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
168
site/src/components/Nav.svelte
Normal file
@ -0,0 +1,168 @@
|
||||
<script>
|
||||
import LanguageSwitcher from './LanguageSwitcher.svelte'
|
||||
import NavItem from './NavItem.svelte'
|
||||
import { onMount, setContext } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import Icon from './Icon.svelte';
|
||||
export let segment;
|
||||
export let logo;
|
||||
export let title;
|
||||
import { _ } from 'svelte-i18n';
|
||||
const current = writable(null);
|
||||
setContext('nav', current);
|
||||
let visible = true;
|
||||
|
||||
let hash_changed = false;
|
||||
function handle_hashchange() {
|
||||
hash_changed = true;
|
||||
}
|
||||
let last_scroll = 0;
|
||||
function handle_scroll() {
|
||||
const scroll = window.pageYOffset;
|
||||
if (!hash_changed) {
|
||||
visible = (scroll < 50 || scroll < last_scroll);
|
||||
}
|
||||
last_scroll = scroll;
|
||||
hash_changed = false;
|
||||
}
|
||||
$: $current = segment;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
header {
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100vw;
|
||||
height: var(--nav-h);
|
||||
padding: 0 3rem;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 -0.4rem 0.9rem 0.2rem rgba(0,0,0,.5);
|
||||
z-index: 100;
|
||||
user-select: none;
|
||||
transform: translate(0,calc(-100% - 1rem));
|
||||
transition: transform 0.2s;
|
||||
backdrop-filter: saturate(100%) blur(10px);
|
||||
}
|
||||
header.visible {
|
||||
transform: none;
|
||||
}
|
||||
nav {
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: var(--nav-h);
|
||||
padding: 0 3rem 0 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
transform: none;
|
||||
transition: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.fill-space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.home {
|
||||
width: 200px;
|
||||
line-height: 22px;
|
||||
font-size: 22px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.home:hover {
|
||||
color: inherit;
|
||||
text-decoration:none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.home img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
border-bottom: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
@media (min-width: 400px) {
|
||||
.home {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
a img {
|
||||
max-height: 40px;
|
||||
}
|
||||
|
||||
.switcher-wrapper {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 8px;
|
||||
border: 1px solid hsla(0,0%,100%,.12);
|
||||
box-shadow: 0 0 0 0 rgba(0,0,0,.2), 0 0 0 0 rgba(0,0,0,.14), 0 0 0 0 rgba(0,0,0,.12);
|
||||
padding: 0 15px;
|
||||
height: 36px;
|
||||
color: var(--prime);
|
||||
transition: background-color .2 ease;
|
||||
margin: 0 1rem;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #5282c110;
|
||||
}
|
||||
button:active {
|
||||
background-color: #5282c120;
|
||||
}
|
||||
|
||||
button span {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:window on:hashchange={handle_hashchange} on:scroll={handle_scroll} />
|
||||
|
||||
<header class:visible="{visible}">
|
||||
<nav>
|
||||
<a
|
||||
rel="prefetch"
|
||||
href="."
|
||||
class="home"
|
||||
title="{title}"
|
||||
>
|
||||
{#if logo}
|
||||
<img src={logo} alt={title} />
|
||||
{:else if title}
|
||||
{title}
|
||||
{/if}
|
||||
</a>
|
||||
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<a href='https://console.zitadel.ch'><button>
|
||||
<span>{$_('toconsole')}</span>
|
||||
</button>
|
||||
</a>
|
||||
|
||||
<NavItem external="https://github.com/caos" title="GitHub Repo">
|
||||
<Icon name="lab la-github" size="24px"></Icon>
|
||||
</NavItem>
|
||||
|
||||
<div class="switcher-wrapper">
|
||||
<LanguageSwitcher></LanguageSwitcher>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
30
site/src/components/NavItem.svelte
Normal file
@ -0,0 +1,30 @@
|
||||
<style>
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--text);
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
export let segment = null;
|
||||
export let external = null;
|
||||
export let title = '';
|
||||
const current = getContext('nav');
|
||||
</script>
|
||||
|
||||
{#if external}
|
||||
<a href={external}><slot></slot></a>
|
||||
{:else}
|
||||
<a rel="prefetch" alt="{title}" href={segment}><slot></slot></a>
|
||||
{/if}
|
15
site/src/components/Section.svelte
Normal file
@ -0,0 +1,15 @@
|
||||
<style>
|
||||
section {
|
||||
position: relative;
|
||||
margin: 10rem auto;
|
||||
padding: 0 var(--side-nav);
|
||||
max-width: 120rem;
|
||||
}
|
||||
section :global(h3) {
|
||||
color: var(--text);
|
||||
}
|
||||
</style>
|
||||
|
||||
<section>
|
||||
<slot></slot>
|
||||
</section>
|
82
site/src/components/Split.svelte
Normal file
@ -0,0 +1,82 @@
|
||||
<style>
|
||||
.split {
|
||||
display: grid;
|
||||
grid-row-gap: 1em;
|
||||
grid-template-areas:
|
||||
"one"
|
||||
"two"
|
||||
"three"
|
||||
"what"
|
||||
"how";
|
||||
}
|
||||
|
||||
.split :global(p) {
|
||||
font-size: var(--h5);
|
||||
}
|
||||
|
||||
.how {
|
||||
/* needed to prevent the <pre> from
|
||||
breaking the grid layout */
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.how :global(.cta) :global(a) {
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
background-color: var(--prime);
|
||||
padding: 0.5em 1.8em 0.5em 1em;
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.how :global(.cta) :global(a)::after {
|
||||
right: 0.5em;
|
||||
top: 0.75em;
|
||||
}
|
||||
|
||||
.what {
|
||||
margin: 2em 0 0 0;
|
||||
}
|
||||
|
||||
.how :global(.cta) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.split {
|
||||
grid-column-gap: 1em;
|
||||
grid-row-gap: 1em;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-areas:
|
||||
"one two"
|
||||
"three how"
|
||||
"what what";
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.split {
|
||||
grid-column-gap: 1em;
|
||||
grid-row-gap: 5em;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
grid-template-areas:
|
||||
"one one two two three three"
|
||||
"what what what how how how";
|
||||
}
|
||||
|
||||
.what {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="split">
|
||||
<div class="what" style="grid-area: what;">
|
||||
<slot name="what"></slot>
|
||||
</div>
|
||||
|
||||
<div class="how" style="grid-area: how;">
|
||||
<slot name="how"></slot>
|
||||
</div>
|
||||
</div>
|
71
site/src/i18n.js
Normal file
@ -0,0 +1,71 @@
|
||||
import { getLocaleFromNavigator, init, locale as $locale, register } from 'svelte-i18n';
|
||||
|
||||
import { getCookie, setCookie } from './modules/cookie.js';
|
||||
|
||||
export const INIT_OPTIONS = {
|
||||
fallbackLocale: 'en',
|
||||
initialLocale: 'en',
|
||||
loadingDelay: 200,
|
||||
formats: {},
|
||||
warnOnMissingMessages: true,
|
||||
};
|
||||
|
||||
let currentLocale = null;
|
||||
|
||||
register('en', () => import('./messages/en.json'));
|
||||
register('de', () => import('./messages/de.json'));
|
||||
|
||||
$locale.subscribe((value) => {
|
||||
if (value == null) return;
|
||||
|
||||
currentLocale = value;
|
||||
|
||||
// if running in the client, save the language preference in a cookie
|
||||
if (typeof window !== 'undefined') {
|
||||
setCookie('locale', value);
|
||||
}
|
||||
});
|
||||
|
||||
// initialize the i18n library in client
|
||||
export function startClient() {
|
||||
init({
|
||||
...INIT_OPTIONS,
|
||||
initialLocale: getCookie('locale') || getLocaleFromNavigator(),
|
||||
});
|
||||
}
|
||||
|
||||
const DOCUMENT_REGEX = /^([^.?#@]+)?([?#](.+)?)?$/;
|
||||
// initialize the i18n library in the server and returns its middleware
|
||||
export function i18nMiddleware() {
|
||||
// initialLocale will be set by the middleware
|
||||
init(INIT_OPTIONS);
|
||||
|
||||
return (req, res, next) => {
|
||||
const isDocument = DOCUMENT_REGEX.test(req.originalUrl);
|
||||
// get the initial locale only for a document request
|
||||
if (!isDocument) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
let locale = getCookie('locale', req.headers.cookie);
|
||||
|
||||
// no cookie, let's get the first accepted language
|
||||
if (locale == null) {
|
||||
if (req.headers['accept-language']) {
|
||||
const headerLang = req.headers['accept-language'].split(',')[0].trim();
|
||||
if (headerLang.length > 1) {
|
||||
locale = headerLang;
|
||||
}
|
||||
} else {
|
||||
locale = INIT_OPTIONS.initialLocale || INIT_OPTIONS.fallbackLocale;
|
||||
}
|
||||
}
|
||||
|
||||
if (locale != null && locale !== currentLocale) {
|
||||
$locale.set(locale);
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
8
site/src/messages/de.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"title": "Zitadel Identity and Access Management",
|
||||
"description":"Die meisten Apps müssen die Identität eines Benutzers kennen. Wenn Sie die Identität eines Benutzers kennen, kann eine App Benutzerdaten sicher speichern und auf allen Geräten des Benutzers dieselbe personalisierte Erfahrung bieten.",
|
||||
"description2":"Die Zitadel-Authentifizierung bietet Backend-Dienste, benutzerfreundliche SDKs und vorgefertigte UI-Bibliotheken zur Authentifizierung von Benutzern bei Ihrer App. Es unterstützt die Authentifizierung mithilfe von Passwörtern und bietet weitere Sicherheitsmechanismen, wie einen zweiten Faktor über OTP um einen sicheren Zugang zu gewährleisten.",
|
||||
"description3":"Zitadel nutzt Industriestandards wie OAuth 2.0 und OpenID Connect, sodass sie problemlos in Ihr benutzerdefiniertes Backend integriert werden kann.",
|
||||
"button":"Erfahren Sie wie sie starten",
|
||||
"toconsole":"Zur Zitadel Konsole"
|
||||
}
|
8
site/src/messages/en.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"title": "Zitadel Identity and Access Management",
|
||||
"description":"Most apps need to know the identity of a user. Knowing a user's identity allows an app to securely save user data in the cloud and provide the same personalized experience across all of the user's devices.",
|
||||
"description2":"Zitadel Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using passwords and uses additional Security, like a second Factor over OTP ensure a safe access.",
|
||||
"description3":"Zitadel Authentication leverages industry standards like OAuth 2.0 and OpenID Connect, so it can be easily integrated with your custom backend.",
|
||||
"button":"Learn how to get started",
|
||||
"toconsole":"Go to zitadel console"
|
||||
}
|
33
site/src/modules/cookie.js
Normal file
@ -0,0 +1,33 @@
|
||||
export function getCookie(name, cookies) {
|
||||
if (cookies == null) {
|
||||
if (typeof window === 'undefined') {
|
||||
return undefined;
|
||||
}
|
||||
cookies = document.cookie;
|
||||
}
|
||||
|
||||
const kv = cookies.split(';').find((part) => part.trim().startsWith(name));
|
||||
|
||||
if (!kv) return undefined;
|
||||
|
||||
const cookieValue = kv.split('=')[1];
|
||||
if (!cookieValue) return undefined;
|
||||
|
||||
return decodeURIComponent(cookieValue.trim());
|
||||
}
|
||||
|
||||
export function setCookie(name, value, options = {}) {
|
||||
if (options.expires instanceof Date) {
|
||||
options.expires = options.expires.toUTCString();
|
||||
}
|
||||
|
||||
let updatedCookie = {
|
||||
[encodeURIComponent(name)]: encodeURIComponent(value),
|
||||
sameSite: 'strict',
|
||||
...options,
|
||||
};
|
||||
|
||||
document.cookie = Object.entries(updatedCookie)
|
||||
.map((kv) => kv.join('='))
|
||||
.join(';');
|
||||
}
|
8
site/src/modules/language-store.js
Normal file
@ -0,0 +1,8 @@
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const docLanguages = writable(['de', 'en']);
|
||||
|
||||
export function storeValue(lngs) {
|
||||
console.log('lngs: ' + lngs);
|
||||
docLanguages.set(lngs);
|
||||
}
|
26
site/src/routes/[slug].json.js
Normal file
@ -0,0 +1,26 @@
|
||||
import send from '@polka/send';
|
||||
import { locale } from 'svelte-i18n';
|
||||
|
||||
import { LANGUAGES } from '../../config.js';
|
||||
import { INIT_OPTIONS } from '../i18n.js';
|
||||
import generate_docs from '../utils/generate_docs.js';
|
||||
|
||||
let json;
|
||||
|
||||
export function get(req, res) {
|
||||
if (!json || process.env.NODE_ENV !== 'production') {
|
||||
const { slug } = req.params;
|
||||
locale.subscribe(localecode => {
|
||||
console.log('sublocale: ' + localecode, LANGUAGES);
|
||||
if (!LANGUAGES.includes(localecode)) {
|
||||
console.log(INIT_OPTIONS);
|
||||
localecode = INIT_OPTIONS.initialLocale || 'en';
|
||||
}
|
||||
json = JSON.stringify(generate_docs('docs/', slug, localecode)); // TODO it errors if I send the non-stringified value
|
||||
});
|
||||
}
|
||||
|
||||
send(res, 200, json, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
}
|
26
site/src/routes/[slug].svelte
Normal file
@ -0,0 +1,26 @@
|
||||
<script context="module">
|
||||
export async function preload({params}) {
|
||||
const {lang, slug} = params;
|
||||
const sections = await this.fetch(`${slug}.json`).then(r => r.json());
|
||||
const tags = [];
|
||||
return { sections, slug, tags };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import manifest from '../../static/manifest.json';
|
||||
import Docs from "../components/Docs.svelte";
|
||||
export let slug;
|
||||
export let sections;
|
||||
export let tags;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{manifest.name} • {slug}</title>
|
||||
|
||||
{#each tags as { name, content }, i}
|
||||
<meta name={name} content={content} />
|
||||
{/each}
|
||||
</svelte:head>
|
||||
|
||||
<Docs {sections} project="zitadel/site" dir="{slug}"/>
|
71
site/src/routes/_error.svelte
Normal file
@ -0,0 +1,71 @@
|
||||
<script>
|
||||
const dev = process.env.NODE_ENV === 'development';
|
||||
|
||||
export let status;
|
||||
export let error;
|
||||
|
||||
// we don't want to use <svelte:window bind:online> here,
|
||||
// because we only care about the online state when
|
||||
// the page first loads
|
||||
let online = typeof navigator !== 'undefined'
|
||||
? navigator.onLine
|
||||
: true;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
padding: var(--top-offset) var(--side-nav) 6rem var(--side-nav);
|
||||
}
|
||||
|
||||
h1, p { margin: 0 auto }
|
||||
|
||||
h1 {
|
||||
font-size: 2.8em;
|
||||
font-weight: 300;
|
||||
margin: 0 0 0.5em 0;
|
||||
}
|
||||
|
||||
p { margin: 1em auto }
|
||||
|
||||
.error {
|
||||
background-color: #da106e;
|
||||
color: white;
|
||||
padding: 12px 16px;
|
||||
font: 600 16px/1.7 var(--font);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* @media (min-width: 480px) {
|
||||
h1 { font-size: 4em }
|
||||
} */
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>{status}</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="container">
|
||||
{#if online}
|
||||
<h1>Yikes!</h1>
|
||||
|
||||
{#if error.message}
|
||||
<p class="error">{status}: {error.message}</p>
|
||||
{:else}
|
||||
<p class="error">Encountered a {status} error</p>
|
||||
{/if}
|
||||
|
||||
{#if dev && error.stack}
|
||||
<pre>{error.stack}</pre>
|
||||
{:else}
|
||||
{#if status >= 500}
|
||||
<p>Please try reloading the page.</p>
|
||||
{/if}
|
||||
|
||||
<p>If the error persists, let us know or raise an issue on <a href="https://github.com/caos/site">GitHub</a>. Thanks!</p>
|
||||
{/if}
|
||||
{:else}
|
||||
<h1>It looks like you're offline</h1>
|
||||
|
||||
<p>Reload the page once you've found the internet.</p>
|
||||
{/if}
|
||||
</div>
|
25
site/src/routes/_layout.svelte
Normal file
@ -0,0 +1,25 @@
|
||||
<script>
|
||||
import { stores } from "@sapper/app";
|
||||
import Icon from "../components/Icon.svelte";
|
||||
import Nav from "../components/Nav.svelte";
|
||||
import NavItem from "../components/NavItem.svelte";
|
||||
import manifest from '../../static/manifest.json';
|
||||
|
||||
export let segment;
|
||||
const { page } = stores();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
main {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
padding: var(--nav-h) 0 0 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<Nav {segment} title="{manifest.name}" logo="logos/zitadel-logo-oneline-darkdesign.svg"></Nav>
|
||||
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
57
site/src/routes/index.svelte
Normal file
@ -0,0 +1,57 @@
|
||||
<script context="module">
|
||||
export async function preload(page, session) {
|
||||
const {params} = page;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import Split from "../components/Split.svelte";
|
||||
import Section from '../components/Section.svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h2 {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.caos-back {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
height: 60vh;
|
||||
right: 0;
|
||||
}
|
||||
.section {
|
||||
width: 100%;
|
||||
margin-top: 70vh;
|
||||
min-height: 80vh;
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
.caos-back {
|
||||
right: 0;
|
||||
height: 70vh;
|
||||
}
|
||||
.section {
|
||||
width: 50%;
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>
|
||||
Caos • Documentation
|
||||
</title>
|
||||
</svelte:head>
|
||||
|
||||
<img class="caos-back" src="logos/zitadel-logo-solo-darkdesign.svg" alt="caos logo">
|
||||
|
||||
<Section>
|
||||
<div class="section">
|
||||
<h2>{$_('title')}</h2>
|
||||
<p>{$_('description')}</p>
|
||||
<p>{$_('description2')}</p>
|
||||
<p>{$_('description3')}</p>
|
||||
|
||||
<a href="/get_started" >{$_('button')}</a>
|
||||
</div>
|
||||
</Section>
|
20
site/src/server.js
Normal file
@ -0,0 +1,20 @@
|
||||
import * as sapper from '@sapper/server';
|
||||
import compression from 'compression';
|
||||
import polka from 'polka';
|
||||
import sirv from 'sirv';
|
||||
|
||||
import { i18nMiddleware } from './i18n.js';
|
||||
|
||||
const { PORT, NODE_ENV } = process.env;
|
||||
const dev = NODE_ENV === 'development';
|
||||
|
||||
polka()
|
||||
.use(
|
||||
compression({ threshold: 0 }),
|
||||
sirv('static', { dev }),
|
||||
i18nMiddleware(),
|
||||
sapper.middleware()
|
||||
)
|
||||
.listen(PORT, err => {
|
||||
if (err) console.log('error', err);
|
||||
});
|
82
site/src/service-worker.js
Normal file
@ -0,0 +1,82 @@
|
||||
import { timestamp, files, shell, routes } from '@sapper/service-worker';
|
||||
|
||||
const ASSETS = `cache${timestamp}`;
|
||||
|
||||
// `shell` is an array of all the files generated by the bundler,
|
||||
// `files` is an array of everything in the `static` directory
|
||||
const to_cache = shell.concat(files);
|
||||
const cached = new Set(to_cache);
|
||||
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(
|
||||
caches
|
||||
.open(ASSETS)
|
||||
.then(cache => cache.addAll(to_cache))
|
||||
.then(() => {
|
||||
self.skipWaiting();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(
|
||||
caches.keys().then(async keys => {
|
||||
// delete old caches
|
||||
for (const key of keys) {
|
||||
if (key !== ASSETS) await caches.delete(key);
|
||||
}
|
||||
|
||||
self.clients.claim();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
if (event.request.method !== 'GET' || event.request.headers.has('range')) return;
|
||||
|
||||
const url = new URL(event.request.url);
|
||||
|
||||
// don't try to handle e.g. data: URIs
|
||||
if (!url.protocol.startsWith('http')) return;
|
||||
|
||||
// ignore dev server requests
|
||||
if (url.hostname === self.location.hostname && url.port !== self.location.port) return;
|
||||
|
||||
// always serve static files and bundler-generated assets from cache
|
||||
if (url.host === self.location.host && cached.has(url.pathname)) {
|
||||
event.respondWith(caches.match(event.request));
|
||||
return;
|
||||
}
|
||||
|
||||
// for pages, you might want to serve a shell `service-worker-index.html` file,
|
||||
// which Sapper has generated for you. It's not right for every
|
||||
// app, but if it's right for yours then uncomment this section
|
||||
/*
|
||||
if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) {
|
||||
event.respondWith(caches.match('/service-worker-index.html'));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
if (event.request.cache === 'only-if-cached') return;
|
||||
|
||||
// for everything else, try the network first, falling back to
|
||||
// cache if the user is offline. (If the pages never change, you
|
||||
// might prefer a cache-first approach to a network-first one.)
|
||||
event.respondWith(
|
||||
caches
|
||||
.open(`offline${timestamp}`)
|
||||
.then(async cache => {
|
||||
try {
|
||||
const response = await fetch(event.request);
|
||||
cache.put(event.request, response.clone());
|
||||
return response;
|
||||
} catch(err) {
|
||||
const response = await cache.match(event.request);
|
||||
if (response) return response;
|
||||
|
||||
throw err;
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
99
site/src/template.html
Normal file
@ -0,0 +1,99 @@
|
||||
<!doctype html>
|
||||
<html lang='en' class="theme-default typo-default">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width,initial-scale=1.0'>
|
||||
<meta name='theme-color' content='#159794'>
|
||||
|
||||
%sapper.base%
|
||||
|
||||
<link href=prism.css rel=stylesheet>
|
||||
<link rel='manifest' href='manifest.json'>
|
||||
<link rel='icon' type='image/x-icon' href='icons/favicon.ico'>
|
||||
<link rel="stylesheet"
|
||||
href="https://maxst.icons8.com/vue-static/landings/line-awesome/line-awesome/1.3.0/css/line-awesome.min.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Lato&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Sapper generates a <style> tag containing critical CSS
|
||||
for the current page. CSS for the rest of the app is
|
||||
lazily loaded when it precaches secondary pages -->
|
||||
%sapper.styles%
|
||||
|
||||
<style>
|
||||
.hljs,
|
||||
.hljs-subst {
|
||||
color: #e8eaed;
|
||||
}
|
||||
|
||||
.hljs-comment {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #3dc9b0;
|
||||
}
|
||||
|
||||
.hljs-keyword {
|
||||
color: #ff5370;
|
||||
}
|
||||
|
||||
.hljs-attr {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.hljs-number {
|
||||
color: #3dc9b0;
|
||||
}
|
||||
|
||||
.hljs-type,
|
||||
.hljs-string,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-quote,
|
||||
.hljs-template-tag,
|
||||
.hljs-deletion {
|
||||
color: #298372;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #298372;
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #3dc9b0;
|
||||
}
|
||||
|
||||
.hljs-meta {
|
||||
color: #e8eaed;
|
||||
;
|
||||
}
|
||||
|
||||
.hljs-meta-string {
|
||||
color: #e8eaed;
|
||||
;
|
||||
}
|
||||
|
||||
/* body {
|
||||
background: #212224;
|
||||
} */
|
||||
</style>
|
||||
|
||||
<!-- This contains the contents of the <svelte:head> component, if
|
||||
the current page has one -->
|
||||
%sapper.head%
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- The application will be rendered inside this element,
|
||||
because `app/client.js` references it -->
|
||||
<div id='sapper'>%sapper.html%</div>
|
||||
|
||||
<!-- Sapper creates a <script> tag containing `app/client.js`
|
||||
and anything else it needs to hydrate the app and
|
||||
initialise the router -->
|
||||
%sapper.scripts%
|
||||
</body>
|
||||
|
||||
</html>
|
3
site/src/utils/generate_code_tabs.js
Normal file
@ -0,0 +1,3 @@
|
||||
export default function generate_code_tabs(dirpath, dir) {
|
||||
|
||||
}
|
135
site/src/utils/generate_docs.js
Normal file
@ -0,0 +1,135 @@
|
||||
import fs from 'fs';
|
||||
import hljs from 'highlight.js';
|
||||
import marked from 'marked';
|
||||
import path from 'path';
|
||||
|
||||
import { SLUG_PRESERVE_UNICODE, SLUG_SEPARATOR } from '../../config';
|
||||
import { extract_frontmatter, extract_metadata, langs, link_renderer } from './markdown.js';
|
||||
import { make_session_slug_processor } from './slug';
|
||||
|
||||
const block_types = [
|
||||
'blockquote',
|
||||
'html',
|
||||
'heading',
|
||||
'hr',
|
||||
'list',
|
||||
'listitem',
|
||||
'paragraph',
|
||||
'table',
|
||||
'tablerow',
|
||||
'tablecell'
|
||||
];
|
||||
|
||||
export default function generate_docs(dirpath, dir, lang) {
|
||||
const make_slug = make_session_slug_processor({
|
||||
separator: SLUG_SEPARATOR,
|
||||
preserve_unicode: SLUG_PRESERVE_UNICODE
|
||||
});
|
||||
|
||||
console.log('using language: ' + lang);
|
||||
|
||||
return fs
|
||||
.readdirSync(`${dirpath}${dir}`)
|
||||
.filter((file) => {
|
||||
return file[0] !== '.' && path.extname(file) === '.md' && file.endsWith(`.${lang}.md`);
|
||||
})
|
||||
.map((file) => {
|
||||
const markdown = fs.readFileSync(`${dirpath}${dir}/${file}`, 'utf-8');
|
||||
const { content, metadata } = extract_frontmatter(markdown);
|
||||
const section_slug = make_slug(metadata.title);
|
||||
const subsections = [];
|
||||
|
||||
const renderer = new marked.Renderer();
|
||||
|
||||
let block_open = false;
|
||||
|
||||
renderer.link = link_renderer;
|
||||
|
||||
renderer.hr = (str) => {
|
||||
block_open = true;
|
||||
|
||||
return '<div class="side-by-side"><div class="copy">';
|
||||
};
|
||||
|
||||
// renderer.list = (src) => {
|
||||
// console.log(src);
|
||||
// };
|
||||
|
||||
renderer.code = (source, lang) => {
|
||||
source = source.replace(/^ +/gm, (match) => match.split(' ').join('\t'));
|
||||
|
||||
const lines = source.split('\n');
|
||||
|
||||
const meta = extract_metadata(lines[0], lang);
|
||||
|
||||
let prefix = '';
|
||||
// let class_name = 'code-block';
|
||||
let class_name = '';
|
||||
|
||||
if (meta) {
|
||||
source = lines.slice(1).join('\n');
|
||||
const filename = meta.filename || (lang === 'html' && 'App.svelte');
|
||||
if (filename) {
|
||||
prefix = `<span class='filename'>${prefix} ${filename}</span>`;
|
||||
class_name += ' named';
|
||||
}
|
||||
}
|
||||
|
||||
if (meta && meta.hidden) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const plang = langs[lang];
|
||||
const { value: highlighted } = hljs.highlight(lang, source);
|
||||
|
||||
const html = `<div class='${class_name}'>${prefix}<pre class='language-${plang}'><code>${highlighted}</code></pre></div>`;
|
||||
|
||||
if (block_open) {
|
||||
block_open = false;
|
||||
return `</div><div class="code">${html}</div></div>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
// const slugger = new marked.Slugger();
|
||||
renderer.heading = (text, level, rawtext) => {
|
||||
const slug = level <= 4 && make_slug(rawtext);
|
||||
|
||||
if (level === 3 || level === 4) {
|
||||
const title = text.replace(/<\/?code>/g, '').replace(/\.(\w+)(\((.+)?\))?/, (m, $1, $2, $3) => {
|
||||
if ($3) return `.${$1}(...)`;
|
||||
if ($2) return `.${$1}()`;
|
||||
return `.${$1}`;
|
||||
});
|
||||
|
||||
subsections.push({ slug, title, level });
|
||||
}
|
||||
|
||||
return `
|
||||
<h${level}>
|
||||
<span id="${slug}" class="offset-anchor" ${level > 4 ? 'data-scrollignore' : ''}></span>
|
||||
<a href="${dir}#${slug}" class="anchor" aria-hidden="true"> <i class="las la-link"></i> </a>
|
||||
${text}
|
||||
</h${level}>`;
|
||||
};
|
||||
|
||||
block_types.forEach((type) => {
|
||||
const fn = renderer[type];
|
||||
renderer[type] = function () {
|
||||
return fn.apply(this, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
const html = marked(content, { renderer });
|
||||
const hashes = {};
|
||||
|
||||
return {
|
||||
html: html.replace(/@@(\d+)/g, (m, id) => hashes[id] || m),
|
||||
metadata,
|
||||
subsections,
|
||||
slug: section_slug,
|
||||
file
|
||||
};
|
||||
});
|
||||
}
|
21
site/src/utils/language_extractor.js
Normal file
@ -0,0 +1,21 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
export default function extract_languages(dirpath, dir) {
|
||||
|
||||
const detectedLocales = fs.readdirSync(`${dirpath}${dir}`)
|
||||
.filter(file => path.extname(file) == '.md')
|
||||
.map((file) => {
|
||||
file = file.replace(path.extname(file), '');
|
||||
const arr = file.split('.');
|
||||
const locale = arr.length ? arr[arr.length - 1] : null;
|
||||
if (locale) {
|
||||
return locale;
|
||||
}
|
||||
}).filter(locale => locale !== null);
|
||||
|
||||
const redDetectedLocales = [...new Set(detectedLocales)];
|
||||
|
||||
console.log('detected locales: ' + redDetectedLocales);
|
||||
return redDetectedLocales;
|
||||
}
|
61
site/src/utils/markdown.js
Normal file
@ -0,0 +1,61 @@
|
||||
import * as fleece from 'golden-fleece';
|
||||
|
||||
export function extract_frontmatter(markdown) {
|
||||
const match = /---\r?\n([\s\S]+?)\r?\n---/.exec(markdown);
|
||||
const frontMatter = match[1];
|
||||
const content = markdown.slice(match[0].length);
|
||||
|
||||
const metadata = {};
|
||||
frontMatter.split('\n').forEach((pair) => {
|
||||
const colonIndex = pair.indexOf(':');
|
||||
metadata[pair.slice(0, colonIndex).trim()] = pair.slice(colonIndex + 1).trim();
|
||||
});
|
||||
|
||||
return { metadata, content };
|
||||
}
|
||||
|
||||
export function extract_metadata(line, lang) {
|
||||
try {
|
||||
if (lang === 'html' && line.startsWith('<!--') && line.endsWith('-->')) {
|
||||
console.log(line);
|
||||
return fleece.evaluate(line.slice(4, -3).trim());
|
||||
}
|
||||
|
||||
if (lang === 'codeblock' && line.startsWith('<!--') && line.endsWith('-->')) {
|
||||
console.log(line);
|
||||
return fleece.evaluate(line.slice(4, -3).trim());
|
||||
}
|
||||
|
||||
if (lang === 'js' || (lang === 'json' && line.startsWith('/*') && line.endsWith('*/'))) {
|
||||
return fleece.evaluate(line.slice(2, -2).trim());
|
||||
}
|
||||
} catch (err) {
|
||||
// TODO report these errors, don't just squelch them
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// map lang to language-attributes
|
||||
export const langs = {
|
||||
bash: 'bash',
|
||||
html: 'markup',
|
||||
sv: 'markup',
|
||||
js: 'javascript',
|
||||
css: 'css'
|
||||
};
|
||||
|
||||
// links renderer
|
||||
export function link_renderer(href, title, text) {
|
||||
let target_attr = '';
|
||||
let title_attr = '';
|
||||
|
||||
if (href.startsWith('http')) {
|
||||
target_attr = ' target="_blank"';
|
||||
}
|
||||
|
||||
if (title !== null) {
|
||||
title_attr = ` title="${title}"`;
|
||||
}
|
||||
|
||||
return `<a href="${href}"${target_attr}${title_attr}>${text}</a>`;
|
||||
}
|
84
site/src/utils/slug.js
Normal file
@ -0,0 +1,84 @@
|
||||
import slugify from '@sindresorhus/slugify';
|
||||
|
||||
export const SLUG_PRESERVE_UNICODE = false;
|
||||
export const SLUG_SEPARATOR = '_';
|
||||
|
||||
/* url-safe processor */
|
||||
|
||||
export const urlsafeSlugProcessor = (string, opts) => {
|
||||
const { separator = SLUG_SEPARATOR } = opts || {};
|
||||
|
||||
return slugify(string, {
|
||||
customReplacements: [
|
||||
// runs before any other transformations
|
||||
['$', 'DOLLAR'], // `$destroy` & co
|
||||
['-', 'DASH'] // conflicts with `separator`
|
||||
],
|
||||
separator,
|
||||
decamelize: false,
|
||||
lowercase: false
|
||||
})
|
||||
.replace(/DOLLAR/g, '$')
|
||||
.replace(/DASH/g, '-');
|
||||
};
|
||||
|
||||
/* unicode-preserver processor */
|
||||
|
||||
const alphaNumRegex = /[a-zA-Z0-9]/;
|
||||
const unicodeRegex = /\p{Letter}/u;
|
||||
const isNonAlphaNumUnicode = (string) => !alphaNumRegex.test(string) && unicodeRegex.test(string);
|
||||
|
||||
export const unicodeSafeProcessor = (string, opts) => {
|
||||
const { separator = SLUG_SEPARATOR } = opts || {};
|
||||
|
||||
return string
|
||||
.split('')
|
||||
.reduce(
|
||||
(accum, char, index, array) => {
|
||||
const type = isNonAlphaNumUnicode(char) ? 'pass' : 'process';
|
||||
|
||||
if (index === 0) {
|
||||
accum.current = { type, string: char };
|
||||
} else if (type === accum.current.type) {
|
||||
accum.current.string += char;
|
||||
} else {
|
||||
accum.chunks.push(accum.current);
|
||||
accum.current = { type, string: char };
|
||||
}
|
||||
|
||||
if (index === array.length - 1) {
|
||||
accum.chunks.push(accum.current);
|
||||
}
|
||||
|
||||
return accum;
|
||||
},
|
||||
{ chunks: [], current: { type: '', string: '' } }
|
||||
)
|
||||
.chunks.reduce((accum, chunk) => {
|
||||
const processed = chunk.type === 'process' ? urlsafeSlugProcessor(chunk.string) : chunk.string;
|
||||
|
||||
processed.length > 0 && accum.push(processed);
|
||||
|
||||
return accum;
|
||||
}, [])
|
||||
.join(separator);
|
||||
};
|
||||
|
||||
/* session processor */
|
||||
|
||||
export const make_session_slug_processor = ({
|
||||
preserve_unicode = SLUG_PRESERVE_UNICODE,
|
||||
separator = SLUG_SEPARATOR
|
||||
}) => {
|
||||
const processor = preserve_unicode ? unicodeSafeProcessor : urlsafeSlugProcessor;
|
||||
const seen = new Set();
|
||||
|
||||
return (string) => {
|
||||
const slug = processor(string, { separator });
|
||||
|
||||
if (seen.has(slug)) throw new Error(`Duplicate slug ${slug}`);
|
||||
seen.add(slug);
|
||||
|
||||
return slug;
|
||||
};
|
||||
};
|
557
site/static/base.css
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
-----------------------------------------------
|
||||
vars – css custom-properties
|
||||
|
||||
NOTE
|
||||
- some vars change inside media-queries!
|
||||
- under normal conditions, there's no need to touch these
|
||||
-----------------------------------------------
|
||||
*/
|
||||
:root {
|
||||
--nav-h: 6rem;
|
||||
--top-offset: 6rem;
|
||||
--sidebar-w: 30rem;
|
||||
--sidebar-mid-w: 36rem;
|
||||
--sidebar-large-w: 48rem;
|
||||
--main-width: 80rem;
|
||||
--side-nav: 3.2rem;
|
||||
--side-page: var(--side-nav);
|
||||
|
||||
/* easings */
|
||||
--out-back: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
:root {
|
||||
--side-page: 14vw;
|
||||
--top-offset: 10rem;
|
||||
--side-nav: 4.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* theme vars */
|
||||
.theme-default {
|
||||
--back: #212224;
|
||||
--back-light: transparent;
|
||||
--back-api: #212224;
|
||||
--prime: #5282c1;
|
||||
--second: #e91e63;
|
||||
--flash: #72a2e0;
|
||||
|
||||
--nav-back: #212224;
|
||||
--side-nav-back: #212224;
|
||||
|
||||
--heading: #e8eaed;
|
||||
--text: #eff8ff;
|
||||
--dark-text: #8795a1;
|
||||
--sidebar-text: #eff8ff;
|
||||
--border-w: .3rem; /* border-width */
|
||||
--border-r: .4rem; /* border-radius */
|
||||
}
|
||||
|
||||
/* typo vars */
|
||||
.typo-default {
|
||||
--code-fs: 1.3rem;
|
||||
--h6: 1.4rem;
|
||||
--h5: 1.6rem;
|
||||
--h4: 1.8rem; /* default font-size */
|
||||
--h3: 2.6rem;
|
||||
--h2: 3rem;
|
||||
--h1: 3.2rem;
|
||||
--linemax: 42em; /* max line-length */
|
||||
--lh: 1.5; /* base line-height */
|
||||
}
|
||||
|
||||
body {
|
||||
--font: 'Lato', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
--font-mono: 'Lato', 'Fira Mono', monospace;
|
||||
}
|
||||
|
||||
/* fonts ---------------------------------- */
|
||||
|
||||
@font-face {
|
||||
font-family: 'ailerons';
|
||||
src: local('ailerons'), url('../fonts/ailerons/ailerons.otf') format('opentype');
|
||||
}
|
||||
|
||||
/* base reset ----------------------------- */
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-overflow-style: -ms-autohiding-scrollbar;
|
||||
box-sizing: border-box;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#sapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: inherit;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* link reset ----------------------------- */
|
||||
a {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:active {
|
||||
color: var(--flash);
|
||||
}
|
||||
a:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/*
|
||||
-----------------------------------------------
|
||||
global styles
|
||||
-----------------------------------------------
|
||||
*/
|
||||
|
||||
/* typography ----------------------------- */
|
||||
body {
|
||||
font: 300 var(--h4)/var(--lh) var(--font);
|
||||
background-color: var(--back);
|
||||
color: var(--text);
|
||||
/* default spacing of Overpass is a bit too airy */
|
||||
/* letter-spacing: -.013em; */
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
blockquote {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
color: var(--heading);
|
||||
}
|
||||
|
||||
/* h1, h2, h3, h4, h5, h6 { font-weight: 600 } */
|
||||
h6 {
|
||||
font-size: var(--h6);
|
||||
}
|
||||
h5 {
|
||||
font-size: var(--h5);
|
||||
}
|
||||
h4 {
|
||||
font-size: var(--h4);
|
||||
}
|
||||
h3 {
|
||||
font-size: var(--h3);
|
||||
}
|
||||
h2 {
|
||||
font-size: var(--h2);
|
||||
}
|
||||
h1 {
|
||||
font-size: var(--h1);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
font-family: var(--font);
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
p,
|
||||
ol,
|
||||
ul {
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
.b,
|
||||
b,
|
||||
strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
tt,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font: 400 var(--code-fs)/1.7 var(--font-mono);
|
||||
}
|
||||
|
||||
code {
|
||||
position: relative;
|
||||
border-radius: .3em;
|
||||
white-space: nowrap;
|
||||
color: var(--text);
|
||||
-webkit-font-smoothing: initial;
|
||||
}
|
||||
|
||||
pre code {
|
||||
top: 0;
|
||||
white-space: inherit;
|
||||
background-color: none;
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
font-size: var(--code-fs) !important;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--flash);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* opinionated styles --------------------- */
|
||||
|
||||
li:not(.white) > h2 {
|
||||
color: var(--second);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
position: relative;
|
||||
margin: 1.6rem 0 2.4rem;
|
||||
padding: 2rem 2.4rem 1.8rem 2.4rem;
|
||||
border-radius: var(--border-r);
|
||||
font-family: var(--font);
|
||||
max-width: var(--linemax);
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
font-size: var(--h5);
|
||||
}
|
||||
|
||||
blockquote :last-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* buttons -------------------------------- */
|
||||
button {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: currentColor;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:focus,
|
||||
.btn:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
button[disabled],
|
||||
.btn[disabled],
|
||||
.btn:hover[disabled] {
|
||||
opacity: .55;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
button > svg,
|
||||
.btn > svg {
|
||||
position: relative;
|
||||
top: -.1rem;
|
||||
width: 2rem !important;
|
||||
height: 2rem !important;
|
||||
stroke: currentColor !important;
|
||||
}
|
||||
|
||||
/* reset ------- */
|
||||
.btn {
|
||||
--btn-h: 4rem;
|
||||
--btn-outline: .2rem;
|
||||
--btn-font: var(--font);
|
||||
--btn-calc-h: calc(var(--btn-h) - var(--btn-outline) * 2);
|
||||
--btn-hover: linear-gradient(to top, rgba(0, 0, 0, .07), rgba(0, 0, 0, .07));
|
||||
|
||||
position: relative;
|
||||
margin: 0 .8rem .8rem 0;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
zoom: 1;
|
||||
border: none transparent;
|
||||
font: var(--h4) var(--btn-font);
|
||||
border-radius: var(--border-r);
|
||||
color: currentColor;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* default */
|
||||
.btn {
|
||||
line-height: var(--btn-h);
|
||||
height: var(--btn-h);
|
||||
padding: 0 1.6rem;
|
||||
transition: all .1s;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: scale(.98);
|
||||
mix-blend-mode: multiply;
|
||||
background-image: var(--btn-hover);
|
||||
}
|
||||
|
||||
/* optional */
|
||||
.btn[outline] {
|
||||
line-height: var(--btn-calc-h);
|
||||
height: var(--btn-calc-h);
|
||||
border: var(--btn-outline) solid currentColor;
|
||||
background-color: white;
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
/* links ------------------------------------- */
|
||||
a {
|
||||
position: relative;
|
||||
padding: 0 0 1px 0;
|
||||
border-bottom: 1px solid currentColor;
|
||||
user-select: none;
|
||||
color: var(--prime);
|
||||
transition: color .2s, border .2s, padding .2s;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--flash);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
padding: 0;
|
||||
border-bottom: 2px solid currentColor;
|
||||
}
|
||||
|
||||
a.no-underline {
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* a:hover:not(.disabled) > .icon { stroke: var(--flash) } */
|
||||
|
||||
/* lists ---------------------------------- */
|
||||
.listify ol,
|
||||
.listify ul {
|
||||
--list-padding: 2.9rem;
|
||||
|
||||
list-style: none;
|
||||
color: currentColor;
|
||||
margin-left: var(--list-padding);
|
||||
}
|
||||
|
||||
.listify ol > li,
|
||||
.listify ul > li {
|
||||
max-width: calc(var(--linemax) - var(--list-padding));
|
||||
line-height: 1.5;
|
||||
margin: 0 0 0.4rem 0;
|
||||
}
|
||||
|
||||
.listify ul > li:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
margin-top: 1.1rem;
|
||||
margin-left: -1.8rem;
|
||||
background-color: var(--second);
|
||||
width: .6rem;
|
||||
height: .6rem;
|
||||
border-radius: 2px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.listify ol {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
/* tables --------------------------------- */
|
||||
table {
|
||||
width: 100%;
|
||||
font-size: var(--h5);
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding: 0.4rem 0.8rem 0.4rem 0;
|
||||
}
|
||||
|
||||
td[align='right'] {
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
th[align='right'] {
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
td[align='left'] {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
th[align='left'] {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
table code,
|
||||
table span {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* grid ----------------------------------- */
|
||||
.grid,
|
||||
.grid.half {
|
||||
display: grid;
|
||||
grid-gap: 2.4rem;
|
||||
grid-template-columns: 1fr;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.grid.stretch {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.grid > .cols-2,
|
||||
.grid > .cols-3 {
|
||||
grid-column: span 1;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 840px) {
|
||||
.grid.half,
|
||||
.grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.grid > .cols-2,
|
||||
.grid > .cols-3 {
|
||||
grid-column: span 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1100px) {
|
||||
.grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
.grid > .cols-2 {
|
||||
grid-column: span 2;
|
||||
}
|
||||
.grid > .cols-3 {
|
||||
grid-column: span 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* helper styles -------------------------- */
|
||||
.flex-auto {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.py0 {
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.legend,
|
||||
figcaption,
|
||||
.post aside {
|
||||
max-width: none;
|
||||
margin: 0 auto;
|
||||
padding: 1.6rem 0 0 .8rem;
|
||||
font: 1.2rem/1.6 var(--font-mono);
|
||||
}
|
||||
|
||||
.filename {
|
||||
display: inline-block;
|
||||
padding: 1.6rem 0 0 1rem;
|
||||
font: var(--h6) var(--font-mono);
|
||||
}
|
||||
|
||||
.box {
|
||||
padding: 2.4rem 3.2rem;
|
||||
border-radius: var(--border-r);
|
||||
}
|
||||
|
||||
/* theme colors --------------------------- */
|
||||
.prime {
|
||||
color: var(--prime) !important;
|
||||
}
|
||||
.second {
|
||||
color: var(--second) !important;
|
||||
}
|
||||
.flash {
|
||||
color: var(--flash) !important;
|
||||
}
|
||||
.black {
|
||||
color: black !important;
|
||||
}
|
||||
.white {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.back {
|
||||
background-color: var(--back) !important;
|
||||
}
|
||||
.back-light {
|
||||
background-color: var(--back-light) !important;
|
||||
}
|
||||
.bg-prime {
|
||||
background-color: var(--prime) !important;
|
||||
}
|
||||
.bg-second {
|
||||
background-color: var(--second) !important;
|
||||
}
|
||||
.bg-flash {
|
||||
background-color: var(--flash) !important;
|
||||
}
|
||||
|
||||
/* inputs --------------------------------- */
|
||||
input[type="checkbox"] {
|
||||
/* display: block; */
|
||||
position: relative;
|
||||
height: 1em;
|
||||
width: calc(100% - 0.6em);
|
||||
max-width: 2em;
|
||||
top: -2px;
|
||||
border-radius: 0.5em;
|
||||
-webkit-appearance: none;
|
||||
outline: none;
|
||||
margin: 0 0.6em 0 0;
|
||||
}
|
||||
|
||||
input[type="checkbox"]::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
border-radius: 1em;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: var(--second);
|
||||
/* box-sizing: border-box; */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked::before {
|
||||
background: var(--prime);
|
||||
}
|
||||
|
||||
input[type="checkbox"]::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
border-radius: 1em;
|
||||
background: white;
|
||||
box-shadow: 0 0px 1px rgba(0, 0, 0, .4), 0 4px 2px rgba(0, 0, 0, .1);
|
||||
-webkit-transition: background .2s ease-out, left .2s ease-out;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked::after {
|
||||
left: calc(100% - 9px);
|
||||
}
|
BIN
site/static/fonts/ailerons/ailerons.otf
Normal file
BIN
site/static/fonts/fira-mono/fira-mono-latin-400.woff2
Normal file
BIN
site/static/fonts/roboto/roboto-latin-400.woff2
Normal file
BIN
site/static/fonts/roboto/roboto-latin-400italic.woff2
Normal file
BIN
site/static/fonts/roboto/roboto-latin-500.woff2
Normal file
BIN
site/static/fonts/roboto/roboto-latin-500italic.woff2
Normal file
BIN
site/static/icons/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
site/static/icons/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
site/static/icons/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
site/static/icons/favicon-16x16.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
site/static/icons/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
site/static/icons/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
site/static/icons/mstile-150x150.png
Normal file
After Width: | Height: | Size: 8.7 KiB |
47
site/static/icons/safari-pinned-tab.svg
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="1026.000000pt" height="1026.000000pt" viewBox="0 0 1026.000000 1026.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,1026.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M2786 10150 c-8 -24 -67 -243 -72 -265 -2 -11 -17 -69 -34 -130 -17
|
||||
-60 -59 -218 -94 -350 -36 -132 -89 -332 -119 -445 -31 -113 -67 -248 -81
|
||||
-300 -14 -52 -37 -138 -51 -190 -31 -112 -86 -319 -90 -340 -2 -8 -10 -40 -18
|
||||
-70 -9 -30 -47 -172 -86 -316 -38 -144 -95 -355 -126 -470 -50 -186 -156 -581
|
||||
-185 -689 -6 -22 -15 -56 -20 -75 -8 -29 -175 -651 -184 -685 -2 -5 -6 -23
|
||||
-11 -40 -4 -16 -18 -68 -31 -115 -12 -47 -25 -96 -28 -110 -3 -14 -46 -176
|
||||
-96 -360 -93 -343 -168 -621 -175 -653 -2 -9 -17 -65 -34 -125 -17 -59 -41
|
||||
-150 -55 -202 -13 -52 -63 -239 -110 -415 -48 -176 -102 -381 -122 -455 -20
|
||||
-74 -44 -164 -54 -200 -10 -36 -51 -186 -90 -335 -40 -148 -105 -391 -145
|
||||
-540 -40 -148 -101 -376 -135 -505 -35 -129 -71 -266 -82 -305 -35 -131 -69
|
||||
-260 -73 -279 -3 -10 -16 -60 -31 -110 -14 -50 -28 -99 -30 -109 -2 -10 -6
|
||||
-27 -9 -37 -3 -10 -8 -27 -10 -37 -2 -10 -49 -186 -105 -392 -55 -206 -99
|
||||
-375 -97 -377 1 -2 39 6 82 17 44 12 87 23 95 25 12 3 198 52 260 69 8 2 58
|
||||
16 110 30 52 14 138 37 190 51 52 14 102 28 110 30 8 2 33 8 55 14 22 6 47 12
|
||||
56 14 24 6 279 75 334 91 28 7 138 37 245 65 107 29 209 56 225 61 17 5 82 22
|
||||
145 39 63 17 225 60 360 96 135 36 252 68 260 70 8 1 98 25 200 53 102 27 311
|
||||
83 465 125 377 100 561 150 880 236 105 28 197 53 205 55 26 5 812 215 880
|
||||
235 36 10 126 35 200 54 74 20 221 59 325 87 105 28 197 52 205 54 8 2 58 15
|
||||
110 30 91 25 185 50 350 94 189 49 280 74 340 91 36 11 119 33 185 51 66 17
|
||||
167 44 225 59 138 37 807 216 1080 289 118 32 310 84 425 115 116 30 262 70
|
||||
325 87 63 17 165 44 225 60 61 16 144 38 185 50 41 11 82 22 90 24 8 2 119 31
|
||||
245 65 127 34 237 63 246 65 33 7 104 29 111 34 4 4 -544 558 -1218 1231
|
||||
l-1225 1225 83 38 c473 221 834 631 991 1127 40 127 73 278 82 385 7 74 7 309
|
||||
1 360 -59 472 -225 826 -537 1143 -278 283 -651 473 -1044 532 -44 7 -89 14
|
||||
-100 16 -25 6 -320 5 -360 0 -154 -20 -160 -21 -247 -41 -277 -63 -591 -221
|
||||
-795 -402 -216 -191 -375 -401 -479 -631 l-38 -83 -1227 1227 c-798 798 -1230
|
||||
1223 -1233 1214z m2384 -3623 c0 -36 73 -233 125 -342 46 -93 163 -289 184
|
||||
-305 3 -3 19 -23 36 -45 16 -21 36 -47 45 -55 8 -9 36 -39 61 -66 68 -74 151
|
||||
-147 237 -211 42 -32 79 -61 80 -65 2 -5 8 -8 13 -8 5 0 39 -19 76 -41 124
|
||||
-76 385 -185 487 -203 16 -3 30 -7 32 -8 2 -3 -1095 -301 -1226 -333 -26 -7
|
||||
-231 -61 -335 -90 -55 -15 -107 -28 -115 -30 -8 -2 -59 -15 -113 -30 -54 -16
|
||||
-100 -25 -104 -22 -3 4 -1 23 5 44 5 21 35 133 67 248 56 208 119 445 155 580
|
||||
10 39 44 165 75 280 81 300 86 318 90 335 2 8 27 104 57 212 46 172 67 220 68
|
||||
155z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
99
site/static/logos/zitadel-logo-oneline-darkdesign.svg
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 1005 241" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-483,0)">
|
||||
<g id="zitadel-logo-oneline-darkdesign" transform="matrix(1,0,0,1,483.774,0)">
|
||||
<rect x="0" y="0" width="1003.45" height="241" style="fill:none;"/>
|
||||
<g transform="matrix(1.32803,-0.355844,0.355844,1.32803,-2188.01,-701.671)">
|
||||
<path d="M1493.5,1056.38L1493.5,1037L1496.5,1037L1496.5,1061.62L1426.02,1020.38L1496.5,979.392L1496.5,1004L1493.5,1004L1493.5,984.608L1431.98,1020.39L1493.5,1056.38Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(8.28881,0,0,4.69323,-106816,-204.925)">
|
||||
<g transform="matrix(-0.0429306,-0.282967,0.160219,-0.0758207,12884.5,137.392)">
|
||||
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear1);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,0.0758207,-0.0429306,0.282967,12878.9,10.8747)">
|
||||
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear2);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.117289,0.207146,-0.117289,-0.207146,12943.8,65.7)">
|
||||
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear3);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.160219,-0.0758207,0.0429306,-0.282967,12917.4,132.195)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear4);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.117289,0.207146,0.117289,0.207146,12897.8,5.87512)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear5);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.0429306,-0.282967,-0.160219,0.0758207,12936.8,97.6441)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear6);"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.355844,1.32803,-2189.33,-701.315)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.355844,1.32803,-2177.59,-657.491)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.355844,1.32803,-2169.76,-628.274)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.355844,1.32803,-2271.15,-656.072)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.355844,1.32803,-2197.16,-730.532)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.311363,1.16202,-2068.91,-256.376)">
|
||||
<path d="M1499.26,757.787C1499.26,757.787 1497.37,756.489 1497,755.2C1496.71,754.182 1496.57,750.662 1496.54,750C1496.41,747.303 1499.21,745.644 1499.21,745.644L1490.01,745.835C1490.01,745.835 1493.15,745.713 1493.46,750C1493.51,750.661 1493.23,753.476 1493,755.2C1492.91,756.447 1491.2,757.668 1491.2,757.668L1499.26,757.787Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.311363,1.16202,-2049.34,-183.335)">
|
||||
<path d="M1495,760L1495,744" style="fill:none;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.311363,1.16202,-2049.34,-183.335)">
|
||||
<path d="M1498.27,757.077C1498.27,757.077 1496.71,756.46 1496.65,754.8C1496.65,753.658 1496.64,753.281 1496.65,752.016C1496.62,751.334 1496.59,750.608 1496.65,749.949C1496.78,746.836 1498.5,746.156 1498.5,746.156L1491.46,745.931C1491.46,745.931 1493.37,746.719 1493.65,749.83C1493.71,750.489 1493.69,751.528 1493.65,752.209C1493.64,753.331 1493.64,753.413 1493.65,754.518C1493.68,756.334 1492.58,756.827 1492.58,756.827L1498.27,757.077Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.311363,1.16202,-2147.14,-208.37)">
|
||||
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,0.311363,1.16202,-2147.14,-208.37)">
|
||||
<path d="M1500.86,762.056C1500.86,762.056 1499.86,760.4 1503.09,757.456C1504.91,755.797 1507.33,754.151 1509.98,752.255C1514.82,748.79 1520.68,744.94 1526.52,741.049C1531.45,737.766 1536.38,734.479 1540.82,731.68C1544.52,729.349 1547.85,727.296 1550.54,725.8C1551.07,725.506 1551.6,725.329 1552.05,725.029C1554.73,723.257 1556.85,724.968 1556.85,724.968L1552.23,716.282C1552.23,716.282 1551.99,719.454 1550,720.997C1549.57,721.333 1549.15,721.741 1548.67,722.12C1546.2,724.053 1542.99,726.344 1539.39,728.867C1535.06,731.898 1530.13,735.166 1525.19,738.438C1519.35,742.314 1513.52,746.234 1508.49,749.329C1505.74,751.023 1503.28,752.577 1501.13,753.598C1497.99,755.086 1495.28,753.617 1495.28,753.617L1500.86,762.056Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,-0.311363,-1.16202,-1672.97,1561.28)">
|
||||
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.32803,-0.355844,-0.311363,-1.16202,-1672.97,1561.28)">
|
||||
<path d="M1496.1,754.362C1496.1,754.362 1497.2,755.607 1501.13,753.598C1503.25,752.509 1505.74,751.023 1508.49,749.329C1513.52,746.234 1519.35,742.314 1525.19,738.438C1530.13,735.166 1534.94,731.832 1539.27,728.802C1542.87,726.279 1549.36,722.059 1549.81,721.75C1552.75,719.73 1552.18,718.196 1552.18,718.196L1555.28,724.152C1555.28,724.152 1553.77,722.905 1551.37,724.681C1550.93,725.006 1544.52,729.349 1540.82,731.68C1536.38,734.479 1531.45,737.766 1526.52,741.049C1520.68,744.94 1514.82,748.79 1509.98,752.255C1507.33,754.151 1504.89,755.771 1503.09,757.456C1499.47,760.841 1501.26,763.283 1501.26,763.283L1496.1,754.362Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.299,0,0,1.08306,-3394.18,-2084.88)">
|
||||
<g transform="matrix(94.2338,0,0,94.1776,2827.58,2063)">
|
||||
<path d="M0.449,-0.7L0.177,-0.7C0.185,-0.682 0.197,-0.654 0.2,-0.648C0.205,-0.639 0.216,-0.628 0.239,-0.628L0.32,-0.628C0.332,-0.628 0.336,-0.62 0.334,-0.611L0.128,0L0.389,0C0.412,0 0.422,-0.01 0.427,-0.02L0.45,-0.071L0.255,-0.071C0.245,-0.071 0.239,-0.078 0.242,-0.09L0.449,-0.7Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.2338,0,0,94.1776,2912.39,2063)">
|
||||
<path d="M0.214,-0.7L0.214,-0.015C0.215,-0.01 0.218,0 0.235,0L0.286,0L0.286,-0.672C0.286,-0.684 0.278,-0.7 0.257,-0.7L0.214,-0.7Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.2338,0,0,94.1776,2987.78,2063)">
|
||||
<path d="M0.441,-0.7L0.155,-0.7C0.143,-0.7 0.133,-0.69 0.133,-0.678L0.133,-0.629L0.234,-0.629L0.234,-0.015C0.234,-0.01 0.237,0 0.254,0L0.305,0L0.305,-0.612C0.306,-0.621 0.313,-0.629 0.323,-0.629L0.379,-0.629C0.402,-0.629 0.413,-0.639 0.417,-0.648L0.441,-0.7Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.2338,0,0,94.1776,3067.88,2063)">
|
||||
<path d="M0.422,0L0.343,0L0.28,-0.482L0.217,0L0.138,0L0.244,-0.7L0.283,-0.7C0.313,-0.7 0.318,-0.681 0.321,-0.662L0.422,0Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.2338,0,0,94.1776,3148.92,2063)">
|
||||
<path d="M0.186,-0.7L0.186,0L0.325,0C0.374,0 0.413,-0.039 0.414,-0.088L0.414,-0.612C0.413,-0.661 0.374,-0.7 0.325,-0.7L0.186,-0.7ZM0.343,-0.108C0.343,-0.081 0.325,-0.071 0.305,-0.071L0.258,-0.071L0.258,-0.628L0.305,-0.628C0.325,-0.628 0.343,-0.618 0.343,-0.592L0.343,-0.108Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.2338,0,0,94.1776,3233.73,2063)">
|
||||
<path d="M0.291,-0.071L0.291,-0.314C0.291,-0.323 0.299,-0.331 0.308,-0.331L0.338,-0.331C0.361,-0.331 0.371,-0.341 0.376,-0.35C0.379,-0.356 0.391,-0.385 0.399,-0.403L0.291,-0.403L0.291,-0.611C0.291,-0.621 0.298,-0.628 0.308,-0.628L0.366,-0.628C0.389,-0.628 0.4,-0.639 0.404,-0.648L0.428,-0.7L0.241,-0.7C0.229,-0.7 0.22,-0.691 0.219,-0.68L0.219,0L0.379,0C0.402,0 0.413,-0.01 0.418,-0.019C0.421,-0.025 0.433,-0.053 0.441,-0.071L0.291,-0.071Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.2338,0,0,94.1776,3318.54,2063)">
|
||||
<path d="M0.283,-0.071L0.283,-0.678C0.283,-0.69 0.273,-0.699 0.261,-0.7L0.211,-0.7L0.211,0L0.383,0C0.406,0 0.417,-0.01 0.422,-0.019C0.425,-0.025 0.437,-0.053 0.445,-0.071L0.283,-0.071Z" style="fill:white;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,155.247,-155.247,-41.5984,201.516,76.8392)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(155.247,-41.5984,41.5984,155.247,110.08,195.509)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,-113.649,113.649,-113.649,258.31,215.618)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear4" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-155.247,41.5984,-41.5984,-155.247,220.914,144.546)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear5" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,113.649,113.649,113.649,206.837,124.661)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear6" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,-155.247,-155.247,41.5984,152.054,262.8)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 11 KiB |
74
site/static/logos/zitadel-logo-solo-darkdesign.svg
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 467 467" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g id="zitadel-logo-solo-darkdesign" transform="matrix(0.564847,0,0,0.659318,-1282.85,0)">
|
||||
<rect x="2271.15" y="0" width="826.773" height="708.241" style="fill:none;"/>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5923.46,-2258.26)">
|
||||
<path d="M1493.5,1056.38L1493.5,1037L1496.5,1037L1496.5,1061.62L1426.02,1020.38L1496.5,979.392L1496.5,1004L1493.5,1004L1493.5,984.608L1431.98,1020.39L1493.5,1056.38Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(31.0036,0,0,15.0393,-397275,-666.457)">
|
||||
<g transform="matrix(-0.0429306,-0.282967,0.160219,-0.0758207,12884.5,137.392)">
|
||||
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear1);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,0.0758207,-0.0429306,0.282967,12878.9,10.8747)">
|
||||
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear2);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.117289,0.207146,-0.117289,-0.207146,12943.8,65.7)">
|
||||
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear3);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.160219,-0.0758207,0.0429306,-0.282967,12917.4,132.195)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear4);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.117289,0.207146,0.117289,0.207146,12897.8,5.87512)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear5);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.0429306,-0.282967,-0.160219,0.0758207,12936.8,97.6441)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear6);"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5928.43,-2257.12)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5884.5,-2116.69)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5855.22,-2023.06)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-6234.47,-2112.14)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.331,4.25561,-5957.71,-2350.75)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5477.99,-831.33)">
|
||||
<path d="M1499.26,757.787C1499.26,757.787 1497.37,756.489 1497,755.2C1496.71,754.182 1496.57,750.662 1496.54,750C1496.41,747.303 1499.21,745.644 1499.21,745.644L1490.01,745.835C1490.01,745.835 1493.15,745.713 1493.46,750C1493.51,750.661 1493.23,753.476 1493,755.2C1492.91,756.447 1491.2,757.668 1491.2,757.668L1499.26,757.787Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5404.79,-597.271)">
|
||||
<path d="M1495,760L1495,744" style="fill:none;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5404.79,-597.271)">
|
||||
<path d="M1498.27,757.077C1498.27,757.077 1496.71,756.46 1496.65,754.8C1496.65,753.658 1496.64,753.281 1496.65,752.016C1496.62,751.334 1496.59,750.608 1496.65,749.949C1496.78,746.836 1498.5,746.156 1498.5,746.156L1491.46,745.931C1491.46,745.931 1493.37,746.719 1493.65,749.83C1493.71,750.489 1493.69,751.528 1493.65,752.209C1493.64,753.331 1493.64,753.413 1493.65,754.518C1493.68,756.334 1492.58,756.827 1492.58,756.827L1498.27,757.077Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5770.62,-677.495)">
|
||||
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,1.16463,3.72366,-5770.62,-677.495)">
|
||||
<path d="M1500.86,762.056C1500.86,762.056 1499.86,760.4 1503.09,757.456C1504.91,755.797 1507.33,754.151 1509.98,752.255C1514.82,748.79 1520.68,744.94 1526.52,741.049C1531.45,737.766 1536.38,734.479 1540.82,731.68C1544.52,729.349 1547.85,727.296 1550.54,725.8C1551.07,725.506 1551.6,725.329 1552.05,725.029C1554.73,723.257 1556.85,724.968 1556.85,724.968L1552.23,716.282C1552.23,716.282 1551.99,719.454 1550,720.997C1549.57,721.333 1549.15,721.741 1548.67,722.12C1546.2,724.053 1542.99,726.344 1539.39,728.867C1535.06,731.898 1530.13,735.166 1525.19,738.438C1519.35,742.314 1513.52,746.234 1508.49,749.329C1505.74,751.023 1503.28,752.577 1501.13,753.598C1497.99,755.086 1495.28,753.617 1495.28,753.617L1500.86,762.056Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,-1.16463,-3.72366,-3997,4993.28)">
|
||||
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
|
||||
</g>
|
||||
<g transform="matrix(4.96737,-1.14029,-1.16463,-3.72366,-3997,4993.28)">
|
||||
<path d="M1496.1,754.362C1496.1,754.362 1497.2,755.607 1501.13,753.598C1503.25,752.509 1505.74,751.023 1508.49,749.329C1513.52,746.234 1519.35,742.314 1525.19,738.438C1530.13,735.166 1534.94,731.832 1539.27,728.802C1542.87,726.279 1549.36,722.059 1549.81,721.75C1552.75,719.73 1552.18,718.196 1552.18,718.196L1555.28,724.152C1555.28,724.152 1553.77,722.905 1551.37,724.681C1550.93,725.006 1544.52,729.349 1540.82,731.68C1536.38,734.479 1531.45,737.766 1526.52,741.049C1520.68,744.94 1514.82,748.79 1509.98,752.255C1507.33,754.151 1504.89,755.771 1503.09,757.456C1499.47,760.841 1501.26,763.283 1501.26,763.283L1496.1,754.362Z" style="fill:white;"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,155.247,-155.247,-41.5984,201.516,76.8392)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(155.247,-41.5984,41.5984,155.247,110.08,195.509)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,-113.649,113.649,-113.649,258.31,215.618)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear4" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-155.247,41.5984,-41.5984,-155.247,220.914,144.546)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear5" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,113.649,113.649,113.649,206.837,124.661)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear6" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,-155.247,-155.247,41.5984,152.054,262.8)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 8.1 KiB |
21
site/static/manifest.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"background_color": "#212224",
|
||||
"theme_color": "#e91e63",
|
||||
"name": "Zitadel Docs",
|
||||
"lang": "en",
|
||||
"short_name": "Zitadel Docs",
|
||||
"display": "minimal-ui",
|
||||
"start_url": "/",
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/android-chrome-256x256.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
216
site/static/prism.css
Normal file
@ -0,0 +1,216 @@
|
||||
pre[class*="language-"],
|
||||
code[class*="language-"] {
|
||||
color: #d4d4d4;
|
||||
font-size: 13px;
|
||||
text-shadow: none;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
line-height: 1.5;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
code[class*="language-"]::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
pre[class*="language-"],
|
||||
code[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
background: #2d2e30;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"] {
|
||||
padding: .1em .3em;
|
||||
border-radius: .3em;
|
||||
color: #db4c69;
|
||||
background: #f9f2f4;
|
||||
}
|
||||
/*********************************************************
|
||||
* Tokens
|
||||
*/
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: #6a9955;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #b5cea8;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #d4d4d4;
|
||||
background: #001F40;
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #c586c0;
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: #dcdcaa;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #d16969;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.constant {
|
||||
color: #9CDCFE;
|
||||
}
|
||||
|
||||
.token.class-name {
|
||||
color: #4EC9B0;
|
||||
}
|
||||
|
||||
.token.parameter {
|
||||
color: #9CDCFE;
|
||||
}
|
||||
|
||||
.token.interpolation {
|
||||
color: #9CDCFE;
|
||||
}
|
||||
|
||||
.token.punctuation.interpolation-punctuation {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.boolean {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.property {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.selector {
|
||||
color: #d7ba7d;
|
||||
}
|
||||
|
||||
.token.tag {
|
||||
color: #569cd6;
|
||||
}
|
||||
|
||||
.token.attr-name {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.token.attr-value {
|
||||
color: #ce9178;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
color: #4ec9b0;
|
||||
cursor: unset;
|
||||
}
|
||||
|
||||
.token.namespace {
|
||||
color: #4ec9b0;
|
||||
}
|
||||
/*********************************************************
|
||||
* Language Specific
|
||||
*/
|
||||
pre[class*="language-javascript"],
|
||||
code[class*="language-javascript"] {
|
||||
color: #4ec9b0;
|
||||
}
|
||||
|
||||
pre[class*="language-css"],
|
||||
code[class*="language-css"] {
|
||||
color: #CE9178;
|
||||
}
|
||||
|
||||
pre[class*="language-html"],
|
||||
code[class*="language-html"] {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.language-html .token.punctuation {
|
||||
color: #808080;
|
||||
}
|
||||
/*********************************************************
|
||||
* Line highlighting
|
||||
*/
|
||||
pre[data-line] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
pre[class*="language-"] > code[class*="language-"] {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.line-highlight {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: inherit 0;
|
||||
margin-top: 1em;
|
||||
background: #f7ebc6;
|
||||
box-shadow: inset 5px 0 0 #f7d87c;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
line-height: inherit;
|
||||
white-space: pre;
|
||||
}
|