mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-06 09:52:17 +00:00
feat: docs rehaul, fix missing context in console, quickstarts (#1212)
* onboarding components, routing, steps * onboarding component, toc * fix onboarding mixin * header * refactor docs * fix layout * cleanup routing * docs routing * fix conventions * de en routing * docs, guide contents, nav * rem i18n support * fix routing from docs * rollup onwarn changes, preload * update svelte plugin, update rollup config * move docs * revert img style, remove code table * rem de completely * rollup optim, template * angular quickstart, quickstart overview page, update deps * fix link * pack, slug * prefetch binding, hidden links * export log * guards route ch * fix homepage * angular docs * docs * resolve fsh * overview * docs * docs * packages fix race condition * nav, home link * add vue, aspnet * doc optimizations * embed status pal * angular guide * angular guide * dotnet, angular guide * viewbox * typo * block onboarding route for non iam writers * set links from component data * fix: fetch org context in guard, more main cnt (#1192) * change get started guide, fix code blockquotes, typos * flutter guide * h2 spacing * highlight strong * plus * rm start sublinks * add proxy quickstart * regex * prevent outside click, fix project grant write Co-authored-by: Florian Forster <florian@caos.ch> Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
@@ -2,13 +2,6 @@ import '../static/base.css';
|
||||
|
||||
import * as sapper from '@sapper/app';
|
||||
|
||||
import { startClient } from './i18n.js';
|
||||
import { initPhotoSwipeFromDOM } from './utils/photoswipe.js';
|
||||
|
||||
startClient();
|
||||
|
||||
initPhotoSwipeFromDOM('.zitadel-gallery');
|
||||
|
||||
sapper.start({
|
||||
target: document.querySelector('#sapper')
|
||||
});
|
||||
});
|
||||
@@ -1,121 +0,0 @@
|
||||
<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>
|
||||
@@ -1,8 +1,7 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import GuideContents from "./GuideContents.svelte"; // TODO rename
|
||||
import GuideContents from "./GuideContents.svelte";
|
||||
import Icon from "./Icon.svelte";
|
||||
import manifest from '../../static/manifest.json';
|
||||
export let owner = "caos";
|
||||
export let path = "docs";
|
||||
export let project = "zitadel";
|
||||
@@ -11,7 +10,6 @@
|
||||
export let sections;
|
||||
import SearchSelector from './SearchSelector.svelte';
|
||||
import SearchTrigger from './SearchTrigger.svelte';
|
||||
import LanguageSwitcher from './LanguageSwitcher.svelte';
|
||||
let searchEnabled = false;
|
||||
let active_section;
|
||||
|
||||
@@ -137,22 +135,6 @@
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
aside::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 3em;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
#1a1f3600 0%,
|
||||
#1a1f3680 50%,
|
||||
#1a1f36 100%
|
||||
);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: absolute;
|
||||
font-family: var(--font);
|
||||
@@ -167,10 +149,6 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
aside.open .sidebar .home {
|
||||
display: none;
|
||||
}
|
||||
|
||||
aside .sidebar :global(.search-trigger) {
|
||||
visibility: hidden;
|
||||
}
|
||||
@@ -201,7 +179,7 @@
|
||||
.content {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: var(--top-offset) var(--side-nav);
|
||||
padding: calc(var(--top-offset) + 100px) var(--side-nav);
|
||||
tab-size: 2;
|
||||
-moz-tab-size: 2;
|
||||
}
|
||||
@@ -226,12 +204,6 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
aside::after {
|
||||
content: "";
|
||||
bottom: 0;
|
||||
height: var(--top-offset);
|
||||
}
|
||||
|
||||
aside button {
|
||||
display: none;
|
||||
}
|
||||
@@ -249,28 +221,6 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar .home {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: calc(var(--sidebar-w)/2);
|
||||
margin: 2rem 0;
|
||||
transform: translateX(-50%);
|
||||
border-bottom: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 22px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sidebar .home img {
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
.sidebar .home span {
|
||||
margin-left: 3px;
|
||||
color: var(--second);
|
||||
}
|
||||
|
||||
.sidebar :global(.language-switcher) {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
@@ -296,7 +246,7 @@
|
||||
}
|
||||
|
||||
.content h2 {
|
||||
margin-top: 4rem;
|
||||
margin-top: 8rem;
|
||||
padding: 2rem 1.6rem 4rem 0.2rem;
|
||||
border-top: var(--border-w) solid #6767785b; /* based on --second */
|
||||
color: var(--heading);
|
||||
@@ -518,17 +468,10 @@
|
||||
|
||||
<aside bind:this={aside} class="sidebar-container" class:open={show_contents}>
|
||||
<div class="sidebar" on:click={() => (show_contents = false)}>
|
||||
<a rel="prefetch" href="." class="home" title="Zitadel Docs">
|
||||
<img src="logos/zitadel-logo-light.svg" alt="zitadel-logo" />
|
||||
<span>DOCS</span>
|
||||
</a>
|
||||
|
||||
<SearchTrigger on:click={handleSearch}/>
|
||||
|
||||
<!-- scroll container -->
|
||||
<GuideContents {dir} {sections} {active_section} {show_contents} />
|
||||
|
||||
<LanguageSwitcher></LanguageSwitcher>
|
||||
</div>
|
||||
|
||||
<button on:click={() => (show_contents = !show_contents)}>
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
<script>
|
||||
import { stores } from "@sapper/app";
|
||||
import { _ } from 'svelte-i18n';
|
||||
const { page } = stores();
|
||||
let menuOpen = false;
|
||||
export let slug;
|
||||
|
||||
page.subscribe(() => {
|
||||
menuOpen = false;
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.content {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0 var(--side-nav) 0 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
height: var(--nav-h);
|
||||
box-shadow: 0 -0.4rem 0.9rem 0.2rem rgba(0,0,0,.5);
|
||||
backdrop-filter: saturate(100%) blur(10px);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.content .home {
|
||||
width: var(--nav-h);
|
||||
height: var(--nav-h);
|
||||
border: none;
|
||||
object-fit: contain;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.content .fill-space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.content .list-item {
|
||||
margin: 0 15px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
color: var(--prime);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 20px !important;
|
||||
margin-bottom: 22px !important;
|
||||
}
|
||||
|
||||
button.list-item i{
|
||||
color: var(--prime);
|
||||
margin-top: 2px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.content :last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.content .btn-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.content .wrapper #menu {
|
||||
position: absolute;
|
||||
top: calc(var(--nav-h) - 5px);
|
||||
left: 50%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* menu appearance*/
|
||||
#menu {
|
||||
position: relative;
|
||||
color: #999;
|
||||
width: 200px;
|
||||
padding: 10px;
|
||||
margin: auto;
|
||||
border-radius: 8px;
|
||||
background: #2a2f45;
|
||||
box-shadow: 0 1px 8px rgba(0,0,0,0.05);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
#menu:after {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: 85px;
|
||||
content: "";
|
||||
display: block;
|
||||
border-left: 15px solid transparent;
|
||||
border-right: 15px solid transparent;
|
||||
border-bottom: 20px solid #2a2f45;
|
||||
}
|
||||
|
||||
ul, li, li a {
|
||||
list-style: none;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 4px 0;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
li a {
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
li.active a {
|
||||
color: var(--second);
|
||||
}
|
||||
|
||||
.modal-background {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 832px) {
|
||||
.content {
|
||||
position: relative;
|
||||
padding-left: calc(var(--sidebar-w) + var(--side-nav));
|
||||
box-shadow: none;
|
||||
background: none;
|
||||
backdrop-filter: none;
|
||||
z-index: auto;
|
||||
}
|
||||
|
||||
.content .home {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="content">
|
||||
<a class="home" href="." ><img src="logos/zitadel-logo-solo-darkdesign.svg" alt="zitadel logo" /></a>
|
||||
<span class="fill-space"></span>
|
||||
|
||||
<div class="btn-wrapper">
|
||||
<button class="list-item" on:click="{() => menuOpen = !menuOpen}"><i class="las la-bars"></i><span>{$_('references')}</span></button>
|
||||
<div class="wrapper">
|
||||
{#if menuOpen}
|
||||
<div id="menu">
|
||||
<ul>
|
||||
<li class="{slug == 'start' ? 'active' : ''}"><a href="/start" >{$_('startlink')}</a></li>
|
||||
<li class="{slug == 'integrate' ? 'active' : ''}"><a href="/integrate">{$_('integratelink')}</a></li>
|
||||
<li class="{slug == 'administrate' ? 'active' : ''}"><a href="/administrate" >{$_('administratelink')}</a></li>
|
||||
<li class="{slug == 'develop' ? 'active' : ''}"><a href="/develop" >{$_('developlink')}</a></li>
|
||||
<li class="{slug == 'documentation' ? 'active' : ''}"><a href="/documentation" >{$_('docslink')}</a></li>
|
||||
<li class="{slug == 'use' ? 'active' : ''}"><a href="/use" >{$_('uselink')}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a class="list-item" href="https://zitadel.ch" target="_blank">More about ZITADEL</a>
|
||||
<!-- <a class="list-item" href="https://console.zitadel.ch" target="_blank">Sign in</a> -->
|
||||
</div>
|
||||
|
||||
{#if menuOpen}
|
||||
<div class="modal-background" on:click="{() => menuOpen = false}"></div>
|
||||
{/if}
|
||||
@@ -1,8 +1,7 @@
|
||||
<script>
|
||||
import { afterUpdate } from 'svelte';
|
||||
import Icon from './Icon.svelte';
|
||||
import CodeTable from './CodeTable.svelte';
|
||||
export let dir = '';
|
||||
export let dir = '';
|
||||
export let sections = [];
|
||||
export let active_section = null;
|
||||
export let show_contents;
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
<script context="module">
|
||||
import { goto } from '@sapper/app';
|
||||
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;
|
||||
|
||||
function reload(language) {
|
||||
if (typeof window !== 'undefined') {
|
||||
locale.set(language);
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--speed3: cubic-bezier(0.26, 0.48, 0.08, 0.9);
|
||||
--height: 30px;
|
||||
}
|
||||
|
||||
.language-switcher {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
z-index: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
button {
|
||||
height: var(--height);
|
||||
margin: .5rem 1rem;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
button.current {
|
||||
color: var(--grey-text);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="language-switcher">
|
||||
{#each LANGUAGES as lang}
|
||||
<button on:click="{() => reload(lang)}" disabled="{lang == group}" class="{lang == group ? 'current': ''}">{lang == 'de'? 'Deutsch' : 'English'}</button>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -1,17 +1,28 @@
|
||||
<script>
|
||||
import LanguageSwitcher from './LanguageSwitcher.svelte'
|
||||
import NavItem from './NavItem.svelte'
|
||||
import { setContext } from 'svelte';
|
||||
import { onMount, setContext } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import Icon from './Icon.svelte';
|
||||
export let segment;
|
||||
export let logo;
|
||||
export let page;
|
||||
export let title;
|
||||
import { _ } from 'svelte-i18n';
|
||||
export let logo;
|
||||
|
||||
const current = writable(null);
|
||||
setContext('nav', current);
|
||||
let open = false;
|
||||
let visible = true;
|
||||
|
||||
// hide nav whenever we navigate
|
||||
page.subscribe(() => {
|
||||
open = false;
|
||||
});
|
||||
function intercept_touchstart(event) {
|
||||
if (!open) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
open = true;
|
||||
}
|
||||
}
|
||||
// Prevents navbar to show/hide when clicking in docs sidebar
|
||||
let hash_changed = false;
|
||||
function handle_hashchange() {
|
||||
hash_changed = true;
|
||||
@@ -31,14 +42,13 @@
|
||||
<style>
|
||||
header {
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
position: fixed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100vw;
|
||||
height: var(--nav-h);
|
||||
padding: 0 16px;
|
||||
padding: 0 1rem;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 -0.4rem 0.9rem 0.2rem rgba(0,0,0,.5);
|
||||
z-index: 100;
|
||||
@@ -46,6 +56,8 @@
|
||||
transform: translate(0,calc(-100% - 1rem));
|
||||
transition: transform 0.2s;
|
||||
backdrop-filter: saturate(100%) blur(10px);
|
||||
-webkit-backdrop-filter: saturate(100%) blur(10px);
|
||||
background-color: #1b153030;
|
||||
}
|
||||
header.visible {
|
||||
transform: none;
|
||||
@@ -56,49 +68,215 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: var(--nav-h);
|
||||
padding: 0 16px 0 16px;
|
||||
height: var(--nav-h);
|
||||
padding: 0 1rem 0 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
transform: none;
|
||||
background-color: transparent;
|
||||
transform: none;
|
||||
transition: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.fill-space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.home {
|
||||
line-height: 22px;
|
||||
font-size: 22px;
|
||||
|
||||
.home {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 22px;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.home:hover {
|
||||
.home .docs {
|
||||
color: var(--second);
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
a img {
|
||||
max-height: 45px;
|
||||
padding: 0;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.primary {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
ul :global(li),
|
||||
ul :global(.login-button) {
|
||||
display: block;
|
||||
display: none;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
ul :global(li).active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
ul::after {
|
||||
/* prevent clicks from registering if nav is closed */
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
ul.open {
|
||||
padding: 0 0 1em 0;
|
||||
background-color: #20244e;
|
||||
align-self: start;
|
||||
border-bottom-left-radius: .5rem;
|
||||
border-bottom-right-radius: .5rem;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, .12);
|
||||
}
|
||||
|
||||
ul.open :global(li),
|
||||
ul.open :global(.login-button){
|
||||
display: block;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
ul.open::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
ul :global(li) :global(a) {
|
||||
font-weight: 500;
|
||||
padding: 1rem 1rem;
|
||||
border: none;
|
||||
color: inherit;
|
||||
text-decoration:none;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
ul.open :global(li) :global(a) {
|
||||
padding: 1.5rem 1rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul :global(li).active :global(a){
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
ul :global(li).active :global(.bars) {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
ul.open :global(li) :global(.bars) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.primary :global(svg) {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.home {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.home img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* TODO remove global color */
|
||||
ul :global(li).active :global(a) {
|
||||
color: var(--second);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
ul :global(i) {
|
||||
color: var(--second);
|
||||
}
|
||||
|
||||
.modal-background {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
/* background-color: rgba(255, 255, 255, 0.9); */
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
border-bottom: none;
|
||||
transition: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.home span {
|
||||
color: var(--second);
|
||||
margin-left: 3px;
|
||||
.show-if-desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a img {
|
||||
width: 160px;
|
||||
max-height: 45px;
|
||||
padding: 0;
|
||||
@media (min-width: 1040px) {
|
||||
ul {
|
||||
padding: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
ul :global(.login-button) {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
ul.open {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
align-self: initial;
|
||||
}
|
||||
|
||||
ul.open :global(li),
|
||||
ul.open :global(.login-button){
|
||||
display: inline;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.open :global(li) :global(a) {
|
||||
display: inline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
ul :global(li).active :global(.bars) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
ul :global(li).active :global(a){
|
||||
display: inline;
|
||||
}
|
||||
|
||||
ul::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
ul :global(li) {
|
||||
display: inline !important;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
ul :global(li) :global(.bars) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hide-if-desktop {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.show-if-desktop {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
@@ -129,21 +307,11 @@
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.show-on-desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 832px) {
|
||||
.show-on-desktop {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:window on:hashchange={handle_hashchange} on:scroll={handle_scroll} />
|
||||
|
||||
<header class:visible="{visible}">
|
||||
<header class:visible="{visible || open}">
|
||||
<nav>
|
||||
<a
|
||||
rel="prefetch"
|
||||
@@ -156,26 +324,30 @@
|
||||
{:else if title}
|
||||
{title}
|
||||
{/if}
|
||||
<span>DOCS</span>
|
||||
<span class="docs">DOCS</span>
|
||||
</a>
|
||||
|
||||
{#if open}
|
||||
<div class="modal-background hide-if-desktop" on:click="{() => open = false}"></div>
|
||||
{/if}
|
||||
|
||||
<span class="fill-space"></span>
|
||||
<div class="show-on-desktop">
|
||||
<NavItem external="https://zitadel.ch" title="GitHub Repo">
|
||||
{$_('moreabout')}
|
||||
</NavItem>
|
||||
|
||||
<a href='https://console.zitadel.ch'>
|
||||
<button>
|
||||
<span>{$_('login')}</span>
|
||||
</button>
|
||||
</a>
|
||||
<ul
|
||||
class="primary"
|
||||
class:open
|
||||
on:touchstart|capture={intercept_touchstart}
|
||||
on:mouseenter="{() => open = true}"
|
||||
on:mouseleave="{() => open = false}">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
|
||||
<a href='https://accounts.zitadel.ch/register'>
|
||||
<button style="border-color: var(--second); margin-left: 0;">
|
||||
<span>{$_('register')}</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<span class="fill-space show-if-desktop"></span>
|
||||
|
||||
<a class="show-if-desktop" href="https://console.zitadel.ch">
|
||||
<button>
|
||||
<span>LOGIN</span>
|
||||
</button>
|
||||
</a>
|
||||
</nav>
|
||||
</header>
|
||||
@@ -1,31 +1,18 @@
|
||||
<style>
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
export let segment = null;
|
||||
import { getContext } from 'svelte';
|
||||
export let segment = null;
|
||||
export let active = false;
|
||||
export let external = null;
|
||||
export let title = '';
|
||||
export let prefetch = false;
|
||||
const current = getContext('nav');
|
||||
</script>
|
||||
|
||||
{#if external}
|
||||
<a href={external}><slot></slot></a>
|
||||
<li><a href={external}><slot></slot></a></li>
|
||||
{:else}
|
||||
<a rel="prefetch" alt="{title}" href={segment}><slot></slot></a>
|
||||
{#if prefetch}
|
||||
<li class:active="{`${$current}` === segment || active }"><a rel="prefetch" sapper:prefetch href={segment}><i class="bars las la-bars"></i><slot></slot></a></li>
|
||||
{:else}
|
||||
<li class:active="{`${$current}` === segment || active }"><a rel="prefetch" href={segment}><i class="bars las la-bars"></i><slot></slot></a></li>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -1,6 +1,5 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
export let sections;
|
||||
export let slug;
|
||||
@@ -214,9 +213,9 @@
|
||||
<div class="search-field">
|
||||
<div class="search-line">
|
||||
<i class="las la-search"></i>
|
||||
<input placeholder="{$_('search_input_placeholder')}" bind:value={searchValue} use:init>
|
||||
<input placeholder="Search for something" bind:value={searchValue} use:init>
|
||||
</div>
|
||||
<p class="result-d">{$_('search_results')}: </p>
|
||||
<p class="result-d">Search Results: </p>
|
||||
<div tabindex="-1" class="result-list">
|
||||
{#each filteredResults as result, i}
|
||||
<a tabindex="0" class="result-item" href="{slug}#{result.slug}" on:click="{closeSearch}" id="{i}">
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script>
|
||||
import {onMount} from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
let buttonname = '';
|
||||
|
||||
onMount(() => {
|
||||
@@ -58,7 +57,7 @@
|
||||
|
||||
<button on:click class="search-trigger">
|
||||
<i class="las la-search"></i>
|
||||
<span>{$_('search_button_holder')}</span>
|
||||
<span>Search this site</span>
|
||||
<span class="fill-space"></span>
|
||||
<span class="strg">{buttonname || 'Ctrl'} F</span>
|
||||
</button>
|
||||
@@ -1,83 +0,0 @@
|
||||
import { getLocaleFromNavigator, init, locale as $locale, register } from 'svelte-i18n';
|
||||
|
||||
import { LANGUAGES } from '../config.js';
|
||||
import { getCookie, setCookie } from './modules/cookie.js';
|
||||
|
||||
export const INIT_OPTIONS = {
|
||||
fallbackLocale: 'en',
|
||||
initialLocale: 'en',
|
||||
loadingDelay: 200,
|
||||
formats: {},
|
||||
warnOnMissingMessages: true,
|
||||
localeOptions: LANGUAGES,
|
||||
};
|
||||
|
||||
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() {
|
||||
console.log('nav', getLocaleFromNavigator());
|
||||
init({
|
||||
...INIT_OPTIONS,
|
||||
initialLocale: getCookie('locale') || INIT_OPTIONS.localeOptions.find(option => option == cropCountryCode(getLocaleFromNavigator())) || INIT_OPTIONS.initialLocale,
|
||||
});
|
||||
}
|
||||
|
||||
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 headerLngs = req.headers['accept-language'].split(',');
|
||||
const headerLngCodes = headerLngs.map(lng => lng.split(';')[0].trim());
|
||||
const headerLang = headerLngCodes.find(code => {
|
||||
return INIT_OPTIONS.localeOptions.find(option => option == code);
|
||||
});
|
||||
|
||||
if (headerLang) {
|
||||
locale = headerLang;
|
||||
}
|
||||
} else {
|
||||
locale = INIT_OPTIONS.initialLocale || INIT_OPTIONS.fallbackLocale;
|
||||
}
|
||||
}
|
||||
|
||||
if (locale != null && locale !== currentLocale) {
|
||||
$locale.set(locale);
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
function cropCountryCode(code) {
|
||||
return code.split('-')[0].trim();
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"title": "ZITADEL Identity and Access Management",
|
||||
"description":"Die meisten Applikationen müssen die Identität eines Benutzers kennen, um Benutzerdaten sicher zu speichern und auf allen Geräten des Benutzers dieselbe personalisierte Erfahrung zu bieten.",
|
||||
"description2":"Die Authentifizierung von ZITADEL bietet Backend-Dienste, benutzerfreundliche SDKs und vorgefertigte UI-Bibliotheken zur Authentifizierung von Benutzern in Ihrer Applikation. Es unterstützt die Authentifizierung mithilfe von Passwörtern und bietet weitere Sicherheitsmechanismen, wie einen zweiten Faktor beispielsweise über OTP, um einen sicheren Zugang zu gewährleisten.",
|
||||
"description3":"ZITADEL nutzt Industriestandards wie OAuth 2.0 und OpenID Connect, die leicht in Ihr benutzerdefiniertes Backend integriert werden können.",
|
||||
"languagealsoavailable":"Diese Website ist auch verfügbar in",
|
||||
"subheader_title":"Dokumentation",
|
||||
"subheader_description":"Entdecken Sie unsere Anleitungen und Beispiele zur Verwendung von ZITADEL.",
|
||||
"learnmore":"Mehr erfahren",
|
||||
"inthissection":"In dieser Sektion",
|
||||
"startlink": "Erfahren Sie hier, wie Sie starten",
|
||||
"startlink_useorbos":"Verwenden Sie ORBOS, um ZITADEL zu installieren",
|
||||
"startlink_setupapp":"Applikation erstellen",
|
||||
"startlink_desc":"Befolgen Sie diese Anleitung, um mit ZITADEL im Allgemeinen zu beginnen.",
|
||||
"integratelink": "Integration",
|
||||
"integratelink_desc":"Erfahren Sie, wie Sie Ihre Anwendungen integrieren und sichere Applikationen und Schnittstellen erstellen.",
|
||||
"integratelink_spa":"Single Page Applikationen",
|
||||
"integratelink_ssr":"Serverseitig gerenderte Applikationen",
|
||||
"integratelink_nativeapp":"Native Applikationen",
|
||||
"administratelink": "Administrieren",
|
||||
"administratelink_desc":"Erfahren Sie, wie Sie Ihre Daten und Rollenzuordnungen in ZITADEL verwalten",
|
||||
"administratelink_orgs":"Organisationen bearbeiten",
|
||||
"administratelink_projects":"Projekte bearbeiten",
|
||||
"administratelink_apps":"Applikationen bearbeiten",
|
||||
"developlink":"ZITADEL APIs",
|
||||
"developlink_desc":"Erfahren Sie mehr über die ZITADEL-APIs und wie Sie mit ihnen entwickeln können.",
|
||||
"developlink_authapi":"Authentication API",
|
||||
"developlink_mgmtapi":"Management API",
|
||||
"developlink_adminapi":"Admin API",
|
||||
"docslink":"Architektur und Technologien",
|
||||
"docslink_desc":"Erfahren Sie mehr über Konstruktion- und Designprinzipien und eingesetzte Technologien.",
|
||||
"docslink_principles":"Prizipien",
|
||||
"docslink_architecture":"Architektur",
|
||||
"docslink_oidc":"OIDC & OAuth 2.0",
|
||||
"uselink":"Benutzer Handbuch",
|
||||
"uselink_desc":"",
|
||||
"login":"Anmelden",
|
||||
"register":"Registrieren",
|
||||
"moreabout":"Mehr über ZITADEL",
|
||||
"search_results":"Suchergebnisse",
|
||||
"search_input_placeholder":"Suche nach ...",
|
||||
"search_button_holder":"Suche nach allem",
|
||||
"references":"Docs",
|
||||
"home_seo": {
|
||||
"title":"ZITADEL • Documentation",
|
||||
"description":"Erfahren Sie mehr über ZITADEL, das Cloud-Native IAM aus der Schweiz"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"title": "ZITADEL Identity and Access Management",
|
||||
"description":"Most applications need to know the identity of a user allowing to securely store user data in the cloud and provide the same personalised experience across all of the user's devices.",
|
||||
"description2":"ZITADEL's authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users in your applicqtion. It supports authentication using passwords and applies additional security wirh the help of a second factor, for example OTP, to ensure a safe and secure access.",
|
||||
"description3":"ZITADEL's authentication leverages industry standards like OAuth 2.0 and OpenID Connect so that it can be easily integrated in your custom backend.",
|
||||
"languagealsoavailable":"This site is also available in",
|
||||
"subheader_title":"Documentation",
|
||||
"subheader_description":"Explore our guides and examples on how to use ZITADEL.",
|
||||
"learnmore":"Learn more",
|
||||
"inthissection":"In this section",
|
||||
"startlink": "Start using ZITADEL",
|
||||
"startlink_useorbos":"Use ORBOS to install ZITADEL",
|
||||
"startlink_setupapp":"Setup an application",
|
||||
"startlink_desc":"Follow this guide to get started with ZITADEL in general.",
|
||||
"integratelink": "Integration",
|
||||
"integratelink_desc":"Learn how to integrate your applications and build secure workflows and APIs with ZITADEL",
|
||||
"integratelink_spa":"Singe Page Applications",
|
||||
"integratelink_ssr":"Serverside Rendered Applications",
|
||||
"integratelink_nativeapp":"Native Applications",
|
||||
"administratelink": "Administration",
|
||||
"administratelink_desc":"Learn how to manage your data and role associations in ZITADEL",
|
||||
"administratelink_orgs":"Manage Organisations",
|
||||
"administratelink_projects":"Manage Projects",
|
||||
"administratelink_apps":"Manage Applications",
|
||||
"developlink":"ZITADEL APIs",
|
||||
"developlink_desc":"Learn more about the ZITADEL APIs and how you can develope with them.",
|
||||
"docslink":"Architecture and Technologies",
|
||||
"docslink_desc":"Learn more about engineering and design principles, ZITADELs architecture and used technologies.",
|
||||
"developlink_authapi":"Authentication API",
|
||||
"developlink_mgmtapi":"Management API",
|
||||
"developlink_adminapi":"Admin API",
|
||||
"docslink_principles":"Principles",
|
||||
"docslink_architecture":"Architecture",
|
||||
"docslink_oidc":"OIDC & OAuth 2.0",
|
||||
"uselink":"User Manuals",
|
||||
"uselink_desc":"Follow this guide to get started with ZITADEL as a user.",
|
||||
"login":"Login",
|
||||
"register":"Register",
|
||||
"moreabout":"More about ZITADEL",
|
||||
"search_results":"Search Results",
|
||||
"search_input_placeholder":"Search for ...",
|
||||
"search_button_holder":"Search for anything",
|
||||
"references":"Docs",
|
||||
"home_seo": {
|
||||
"title":"ZITADEL • Documentation",
|
||||
"description":"Learn more about the ZITADEL, the cloud native IAM from switzerland."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
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(';');
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const docLanguages = writable(['de', 'en']);
|
||||
|
||||
export function storeValue(lngs) {
|
||||
console.log('lngs: ' + lngs);
|
||||
docLanguages.set(lngs);
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
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';
|
||||
import generate_seo from '../utils/generate_seo.js';
|
||||
|
||||
@@ -11,27 +8,9 @@ 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';
|
||||
}
|
||||
|
||||
const seo = generate_seo('docs/', slug, localecode);
|
||||
|
||||
// import(`../../../docs/${slug}/seo_${localecode}.jsonld`).then((module) => {
|
||||
// const seo = module.meta;
|
||||
// const docs = generate_docs('docs/', slug, localecode);
|
||||
// json = JSON.stringify({ docs, seo }); // TODO it errors if I send the non-stringified value
|
||||
// }).catch(error => {
|
||||
// console.error(error);
|
||||
|
||||
const docs = generate_docs('docs/', slug, localecode);
|
||||
json = JSON.stringify({ docs, seo }); // TODO it errors if I send the non-stringified value
|
||||
// });
|
||||
});
|
||||
const seo = generate_seo(`docs/`, slug);
|
||||
const sections = generate_docs(`docs/`, slug);
|
||||
json = JSON.stringify({ sections, seo }); // TODO it errors if I send the non-stringified value
|
||||
}
|
||||
|
||||
send(res, 200, json, {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<script context="module">
|
||||
export async function preload({params}) {
|
||||
const {lang, slug} = params;
|
||||
const {docs, seo} = await this.fetch(`${slug}.json`).then(r => r.json());
|
||||
return { sections: docs, seo, slug };
|
||||
const { slug } = params;
|
||||
const {sections, seo} = await this.fetch(`${slug}.json`).then(r => r.json());
|
||||
return { sections, seo, slug };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import DocsHeader from '../components/DocsHeader.svelte';
|
||||
import manifest from '../../static/manifest.json';
|
||||
import Docs from "../components/Docs.svelte";
|
||||
export let slug;
|
||||
export let sections;
|
||||
export let seo;
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
import { initPhotoSwipeFromDOM } from '../utils/photoswipe.js';
|
||||
|
||||
@@ -37,5 +37,4 @@
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
<DocsHeader {slug}></DocsHeader>
|
||||
<Docs {sections} dir="{slug}"/>
|
||||
@@ -9,7 +9,9 @@
|
||||
// the page first loads
|
||||
let online = typeof navigator !== 'undefined'
|
||||
? navigator.onLine
|
||||
: true;
|
||||
: true;
|
||||
|
||||
console.error(error);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -61,7 +63,7 @@
|
||||
<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>
|
||||
<p>If the error persists, let us know or raise an issue on <a rel="external" href="https://github.com/caos/site">GitHub</a>. Thanks!</p>
|
||||
{/if}
|
||||
{:else}
|
||||
<h1>It looks like you're offline</h1>
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
<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';
|
||||
import PhotoSwipe from '../components/PhotoSwipe.svelte';
|
||||
const { page } = stores();
|
||||
export let segment;
|
||||
</script>
|
||||
|
||||
<script context="module">
|
||||
import { waitLocale } from 'svelte-i18n';
|
||||
export async function preload(page) {
|
||||
return waitLocale();
|
||||
}
|
||||
import { stores } from "@sapper/app";
|
||||
import Nav from "../components/Nav.svelte";
|
||||
import NavItem from "../components/NavItem.svelte";
|
||||
import PhotoSwipe from '../components/PhotoSwipe.svelte';
|
||||
const { page } = stores();
|
||||
export let segment;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -25,7 +16,18 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<Nav title="Zitadel docs" {segment} {page} logo="logos/zitadel-logo-light.svg">
|
||||
<NavItem segment="start" prefetch>Get started</NavItem>
|
||||
<NavItem segment="quickstarts">Quickstarts</NavItem>
|
||||
<!-- <NavItem segment="guides">Guides</NavItem> -->
|
||||
<NavItem segment="administrate" prefetch>Administrate</NavItem>
|
||||
<NavItem segment="apis" prefetch>APIs</NavItem>
|
||||
<NavItem segment="architecture" prefetch>Architecture</NavItem>
|
||||
<NavItem segment="use" prefetch>Manual</NavItem>
|
||||
</Nav>
|
||||
|
||||
<main>
|
||||
<slot />
|
||||
<PhotoSwipe/>
|
||||
</main>
|
||||
|
||||
<PhotoSwipe/>
|
||||
@@ -1,33 +1,11 @@
|
||||
<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 { _ , locale} from 'svelte-i18n';
|
||||
import LanguageSwitcher from '../components/LanguageSwitcher.svelte';
|
||||
import Nav from '../components/Nav.svelte';
|
||||
export let segment;
|
||||
import {LANGUAGES} from '../../config.js';
|
||||
import Button from '../components/Button.svelte';
|
||||
|
||||
function reload(language) {
|
||||
if (typeof window !== 'undefined') {
|
||||
locale.set(language);
|
||||
}
|
||||
}
|
||||
|
||||
locale.subscribe(l => {
|
||||
console.log(l);
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h2 {
|
||||
margin-bottom: 2rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.section {
|
||||
@@ -60,10 +38,6 @@
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.doc-container .doc img{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.doc-container .doc .text{
|
||||
top: 180px;
|
||||
}
|
||||
@@ -84,9 +58,23 @@
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.doc-container .doc .text .logo-cloud {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.doc-container .doc .text .logo-cloud img {
|
||||
max-width: 60px;
|
||||
max-height: 60px;
|
||||
margin: .5rem;
|
||||
object-fit: contain;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.doc-container .doc a {
|
||||
display: block;
|
||||
font-size: 1.5rem;
|
||||
font-size: 1.7rem;
|
||||
border: none;
|
||||
margin-bottom: 1rem;
|
||||
padding: 0;
|
||||
@@ -103,27 +91,6 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: 0;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
blockquote p {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sublinks {
|
||||
display: block;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.sublinks .sublink {
|
||||
font-size: 15px;
|
||||
margin-right: 2rem;
|
||||
border: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sectionlinks {
|
||||
display: block;
|
||||
margin: 1rem 0;
|
||||
@@ -137,21 +104,25 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
@media screen and (min-width: 899px) {
|
||||
.section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.section .left,
|
||||
.section .left {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.section .caos-back {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.section .caos-back {
|
||||
display: block;
|
||||
margin: 50px;
|
||||
margin: 50px 0 20px 20px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.doc-container {
|
||||
@@ -163,7 +134,6 @@
|
||||
.doc-container .doc {
|
||||
display: flex;
|
||||
margin: 1rem;
|
||||
max-width: 500px;
|
||||
flex: 1 0 auto;
|
||||
max-height: 350px;
|
||||
transition: box-shadow .2 ease;
|
||||
@@ -172,20 +142,6 @@
|
||||
.doc-container .doc:hover {
|
||||
box-shadow: 0 1px 8px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.doc-container .doc img{
|
||||
display: block;
|
||||
width: 180px;
|
||||
height: auto;
|
||||
margin-left: 1rem;
|
||||
object-fit: cover;
|
||||
margin-right: -1.5rem;
|
||||
margin-top: -1.5rem;
|
||||
margin-bottom: -1.5rem;
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
object-position: 0 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -193,165 +149,124 @@
|
||||
<title>
|
||||
ZITADEL • Documentation
|
||||
</title>
|
||||
<title>{$_('title')}</title>
|
||||
<meta property="description" content="{$_('home_seo.description')}" />
|
||||
<title>ZITADEL • Documentation</title>
|
||||
<meta property="description" content="Learn more about the ZITADEL, the cloud native IAM from switzerland." />
|
||||
|
||||
<meta property="og:url" content="https://docs.zitadel.ch" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="{$_('home_seo.title')}" />
|
||||
<meta property="og:description" content="{$_('home_seo.description')}" />
|
||||
<meta property="og:title" content="ZITADEL • Documentation" />
|
||||
<meta property="og:description" content="Learn more about the ZITADEL, the cloud native IAM from switzerland." />
|
||||
<meta property="og:image"
|
||||
content="https://www.zitadel.ch/zitadel-social-preview25.png" />
|
||||
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@caos_ch">
|
||||
<meta name="twitter:title" content="{$_('home_seo.title')}" />
|
||||
<meta name="twitter:description" content="{$_('home_seo.description')}" />
|
||||
<meta name="twitter:title" content="ZITADEL • Documentation" />
|
||||
<meta name="twitter:description" content="Learn more about the ZITADEL, the cloud native IAM from switzerland." />
|
||||
<meta name="twitter:image" content="https://www.zitadel.ch/zitadel-social-preview25.png">
|
||||
</svelte:head>
|
||||
<Nav {segment} title="Zitadel docs" logo="logos/zitadel-logo-light.svg"></Nav>
|
||||
|
||||
<Section>
|
||||
<div class="section">
|
||||
<div class="left">
|
||||
<blockquote>
|
||||
|
||||
<p>{$_('languagealsoavailable')}:
|
||||
{#each LANGUAGES as lang}
|
||||
{#if lang != $locale}
|
||||
<a href="/" on:click="{() => reload(lang)}" class="{lang == $locale ? 'current': ''}">{lang == 'de'? 'Deutsch (WIP)' : 'English'}</a>
|
||||
{/if}
|
||||
{/each}
|
||||
</p>
|
||||
</blockquote>
|
||||
<h2>{$_('title')}</h2>
|
||||
<p>{$_('description')}</p>
|
||||
<p>{$_('description2')}</p>
|
||||
<p>{$_('description3')}</p>
|
||||
<h2>ZITADEL Identity and Access Management</h2>
|
||||
<p>Most applications need to know the identity of a user allowing to securely store user data in the cloud and provide the same personalised experience across all of the user's devices.</p>
|
||||
<p>ZITADEL's authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users in your application. It supports authentication using passwords and applies additional security with the help of a second factor, for example OTP, to ensure a safe and secure access.</p>
|
||||
<p>ZITADEL's authentication leverages industry standards like OAuth 2.0 and OpenID Connect so that it can be easily integrated in your custom backend.</p>
|
||||
</div>
|
||||
<img class="caos-back" src="logos/zitadel-logo-solo-darkdesign.svg" alt="caos logo">
|
||||
</div>
|
||||
|
||||
<div class="subsection">
|
||||
<h3>{$_('startlink')}</h3>
|
||||
<p>{$_('startlink_desc')}</p>
|
||||
<p>Follow this guide to get started with ZITADEL in general.</p>
|
||||
|
||||
<a href="/start" class="getstarted-btn">
|
||||
<Button selected style="margin: 2rem 0;">
|
||||
{$_('startlink')}
|
||||
<a href="start" class="getstarted-btn">
|
||||
<Button selected style="margin: 2rem 0; padding: 16px 25px; height: auto;">
|
||||
Start using ZITADEL
|
||||
<i class="las la-arrow-right"></i>
|
||||
</Button>
|
||||
</a>
|
||||
{#if $locale == 'en'}
|
||||
<div class="sublinks">
|
||||
<a class="sublink" href="start#Use_ORBOS_to_install_ZITADEL">{$_('startlink_useorbos')}</a>
|
||||
<a class="sublink" href="start#Use_ORBOS_to_install_ZITADEL">{$_('startlink_setupapp')}</a>
|
||||
</div>
|
||||
{:else if $locale == 'de'}
|
||||
<div class="sublinks">
|
||||
<a class="sublink" href="start#Use_ORBOS_to_install_ZITADEL">{$_('startlink_useorbos')}</a>
|
||||
<a class="sublink" href="start#Use_ORBOS_to_install_ZITADEL">{$_('startlink_setupapp')}</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="doc-container">
|
||||
<div class="doc">
|
||||
<div class="text">
|
||||
<h4>{$_('integratelink')}</h4>
|
||||
<p>{$_('integratelink_desc')}</p>
|
||||
<a href="/integrate">{$_('learnmore')}<i class="las la-arrow-right"></i></a>
|
||||
<h4>Quickstarts</h4>
|
||||
<p>Learn how to integrate your applications and build secure workflows and APIs with ZITADEL</p>
|
||||
|
||||
{#if $locale == 'en'}
|
||||
<p class="section">{$_('inthissection')}</p>
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="integrate#Single_Page_Application">{$_('integratelink_spa')}</a>
|
||||
<a class="link" href="integrate#Server_Side_Application">{$_('integratelink_ssr')}</a>
|
||||
<a class="link" href="integrate#Mobile_App_Native_App">{$_('integratelink_nativeapp')}</a>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="logo-cloud">
|
||||
<img src="tech/react.png" style="margin: -.5rem;" alt="react" />
|
||||
<img src="tech/angular.svg" alt="angular" />
|
||||
<img style="padding: 1rem;" src="tech/flutter.svg" alt="flutter" />
|
||||
<img src="tech/golang.svg" alt="golang" />
|
||||
<img style="padding: .5rem" src="tech/net.svg" alt="aspnet" />
|
||||
</div>
|
||||
<a href="quickstarts">Learn more<i class="las la-arrow-right"></i></a>
|
||||
|
||||
<p class="section">In this section</p>
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="angular">Single Page Applications (Angular)</a>
|
||||
<a class="link" href="go">Serverside rendered Applications</a>
|
||||
<a class="link" href="flutter">Native Applications (Flutter)</a>
|
||||
</div>
|
||||
</div>
|
||||
<img src="img/develop2.png" alt="Develop" />
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
<div class="text">
|
||||
<h4>{$_('administratelink')}</h4>
|
||||
<p>{$_('administratelink_desc')}</p>
|
||||
<a href="/administrate">{$_('learnmore')}<i class="las la-arrow-right"></i></a>
|
||||
<h4>Administration</h4>
|
||||
<p>Learn how to manage your data and role associations in ZITADEL</p>
|
||||
<a href="administrate">Learn more<i class="las la-arrow-right"></i></a>
|
||||
|
||||
<p class="section">{$_('inthissection')}</p>
|
||||
<p class="section">In this section</p>
|
||||
|
||||
{#if $locale == 'en'}
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="administrate#Organisations">{$_('administratelink_orgs')}</a>
|
||||
<a class="link" href="administrate#Projects">{$_('administratelink_projects')}</a>
|
||||
</div>
|
||||
{:else if $locale == 'de'}
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="administrate#Organisationen">{$_('administratelink_orgs')}</a>
|
||||
<a class="link" href="administrate#Projekte">{$_('administratelink_projects')}</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<img src="img/projects2.png" alt="Develop" />
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
<div class="text">
|
||||
<h4>{$_('developlink')}</h4>
|
||||
<p>{$_('developlink_desc')}</p>
|
||||
<a href="/develop">{$_('learnmore')}<i class="las la-arrow-right"></i></a>
|
||||
|
||||
<p class="section">{$_('inthissection')}</p>
|
||||
|
||||
{#if $locale == 'en'}
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="develop#Authentication_API">{$_('developlink_authapi')}</a>
|
||||
<a class="link" href="develop#Management_API">{$_('developlink_mgmtapi')}</a>
|
||||
<a class="link" href="develop#Admin_API">{$_('developlink_adminapi')}</a>
|
||||
</div>
|
||||
{:else if $locale == 'de'}
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="develop#Authentication_API">{$_('developlink_authapi')}</a>
|
||||
<a class="link" href="develop#Management_API">{$_('developlink_mgmtapi')}</a>
|
||||
<a class="link" href="develop#Admin_API">{$_('developlink_adminapi')}</a>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="administrate#Organizations">Manage Organisations</a>
|
||||
<a class="link" href="administrate#Projects">Manage Projects</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
<div class="text">
|
||||
<h4>{$_('docslink')}</h4>
|
||||
<p>{$_('docslink_desc')}</p>
|
||||
<a href="/documentation" >{$_('learnmore')}<i class="las la-arrow-right"></i></a>
|
||||
<h4>APIs</h4>
|
||||
<i class="las la-code" style="font-size: 100px; height: 100px; color:#6c8eef" ></i>
|
||||
<p>Learn more about our APIs and how to integrate them in your apps.</p>
|
||||
<a href="apis">Learn more<i class="las la-arrow-right"></i></a>
|
||||
|
||||
<p class="section">{$_('inthissection')}</p>
|
||||
{#if $locale == 'en'}
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="documentation#Principles">{$_('docslink_principles')}</a>
|
||||
<a class="link" href="documentation#Architecture">{$_('docslink_architecture')}</a>
|
||||
<a class="link" href="documentation#OpenID_Connect_1_0_and_OAuth_2_0">{$_('docslink_oidc')}</a>
|
||||
</div>
|
||||
{:else if $locale == 'de'}
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="documentation#Prinzipien">{$_('docslink_principles')}</a>
|
||||
<a class="link" href="documentation#Architektur">{$_('docslink_architecture')}</a>
|
||||
<a class="link" href="documentation#OpenID_Connect_1_0_and_OAuth_2_0">{$_('docslink_oidc')}</a>
|
||||
</div>
|
||||
{/if}
|
||||
<p class="section">In this section</p>
|
||||
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="apis#Authentication_API">Authentication API</a>
|
||||
<a class="link" href="apis#Management_API">Management API</a>
|
||||
<a class="link" href="apis#Admin_API">Admin API</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
<div class="text">
|
||||
<h4>{$_('uselink')}</h4>
|
||||
<p>{$_('uselink_desc')}</p>
|
||||
<a href="/use" >{$_('learnmore')}<i class="las la-arrow-right"></i></a>
|
||||
</div>
|
||||
<h4>Architecture and Technologies</h4>
|
||||
<i class="las la-project-diagram" style="font-size: 100px; height: 100px; color:#6c8eef"></i>
|
||||
<p>Learn more about engineering and design principles, ZITADELs architecture and used technologies.</p>
|
||||
<a href="architecture" sapper:prefetch>Learn more<i class="las la-arrow-right"></i></a>
|
||||
|
||||
<img src="img/personal2.png" alt="Develop" />
|
||||
<p class="section">In this section</p>
|
||||
<div class="sectionlinks">
|
||||
<a class="link" href="architecture#Principles">Principles</a>
|
||||
<a class="link" href="architecture#Architecture">Architecture</a>
|
||||
<a class="link" href="architecture#OpenID_Connect_1_0_and_OAuth_2_0">OIDC & OAuth 2.0</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
<div class="text">
|
||||
<h4>User Manuals</h4>
|
||||
<i class="las la-book-reader" style="font-size: 100px; height: 100px; color:#6c8eef"></i>
|
||||
|
||||
<p>Follow this guide to get started with ZITADEL as a user.</p>
|
||||
<a href="use" sapper:prefetch>Learn more<i class="las la-arrow-right"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
59
site/src/routes/quickstarts/_quickstarts.js
Normal file
59
site/src/routes/quickstarts/_quickstarts.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import fs from 'fs';
|
||||
import marked from 'marked';
|
||||
import path from 'path';
|
||||
|
||||
import { SLUG_PRESERVE_UNICODE } from '../../../config';
|
||||
import { highlight } from '../../utils/highlight';
|
||||
import { extract_frontmatter, link_renderer } from '../../utils/markdown.js';
|
||||
import { makeSlugProcessor } from '../../utils/slug';
|
||||
|
||||
const makeSlug = makeSlugProcessor(SLUG_PRESERVE_UNICODE);
|
||||
|
||||
export default function get_quickstarts() {
|
||||
return fs
|
||||
.readdirSync('quickstarts')
|
||||
.map(file => {
|
||||
if (path.extname(file) !== '.md') return;
|
||||
|
||||
const match = /^([0-9]+)-(.+)\.md$/.exec(file);
|
||||
if (!match) throw new Error(`Invalid filename '${file}'`);
|
||||
|
||||
const [, order, slug] = match;
|
||||
|
||||
const markdown = fs.readFileSync(`quickstarts/${file}`, 'utf-8');
|
||||
|
||||
const { content, metadata } = extract_frontmatter(markdown);
|
||||
|
||||
const renderer = new marked.Renderer();
|
||||
|
||||
renderer.link = link_renderer;
|
||||
|
||||
renderer.code = highlight;
|
||||
|
||||
renderer.heading = (text, level, rawtext) => {
|
||||
const fragment = makeSlug(rawtext);
|
||||
|
||||
return `
|
||||
<h${level}>
|
||||
<span id="${fragment}" class="offset-anchor"></span>
|
||||
<a href="quickstarts#${fragment}" class="anchor" aria-hidden="true"></a>
|
||||
${text}
|
||||
</h${level}>`;
|
||||
};
|
||||
|
||||
const answer = marked(
|
||||
content.replace(/^\t+/gm, match => match.split('\t').join(' ')),
|
||||
{ renderer }
|
||||
);
|
||||
|
||||
const fragment = makeSlug(slug);
|
||||
|
||||
return {
|
||||
fragment,
|
||||
order,
|
||||
answer,
|
||||
metadata
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.order - b.order);
|
||||
}
|
||||
25
site/src/routes/quickstarts/index.json.js
Normal file
25
site/src/routes/quickstarts/index.json.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import send from '@polka/send';
|
||||
|
||||
import get_quickstarts from './_quickstarts.js';
|
||||
|
||||
let json;
|
||||
|
||||
export function get(req, res) {
|
||||
if (!json || process.env.NODE_ENV !== 'production') {
|
||||
const qss = get_quickstarts()
|
||||
.map(qs => {
|
||||
return {
|
||||
fragment: qs.fragment,
|
||||
answer: qs.answer,
|
||||
metadata: qs.metadata
|
||||
};
|
||||
});
|
||||
|
||||
json = JSON.stringify(qss);
|
||||
}
|
||||
|
||||
send(res, 200, json, {
|
||||
'Content-Type': 'application/json',
|
||||
'Cache-Control': `max-age=${5 * 60 * 1e3}` // 5 minutes
|
||||
});
|
||||
}
|
||||
154
site/src/routes/quickstarts/index.svelte
Normal file
154
site/src/routes/quickstarts/index.svelte
Normal file
@@ -0,0 +1,154 @@
|
||||
<script context="module">
|
||||
export async function preload() {
|
||||
const qss = await this.fetch(`quickstarts.json`).then(r => r.json());
|
||||
return { qss };
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
const description = "Quickstarts ZITADEL";
|
||||
export let qss;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Quickstarts ZITADEL</title>
|
||||
|
||||
<meta name="twitter:title" content="Quickstarts ZITADEL">
|
||||
<meta name="twitter:description" content={description}>
|
||||
<meta name="Description" content={description}>
|
||||
</svelte:head>
|
||||
|
||||
<div class='quickstarts stretch'>
|
||||
<h1>Quickstarts ZITADEL</h1>
|
||||
{#each qss as qs}
|
||||
{#if qs.metadata.visible == 'true'}
|
||||
<article class='quickstart'>
|
||||
<div>
|
||||
<p class="sub">{qs.metadata.subtitle}</p>
|
||||
<h2>
|
||||
<span id={qs.fragment} class="offset-anchor"></span>
|
||||
<a class="anchor" sapper:prefetch href='quickstarts#{qs.fragment}' title='{qs.title}'><i class="las la-link"></i></a>
|
||||
{qs.metadata.title}
|
||||
</h2>
|
||||
<p>{@html qs.answer}</p>
|
||||
<a class="link" href="{qs.fragment}" sapper:prefetch>Read Quickstart <i class="las la-arrow-right"></i></a>
|
||||
<p class="info">{qs.metadata.date} • {qs.metadata.readingtime}</p>
|
||||
</div>
|
||||
<img src={qs.metadata.img} alt="article img" />
|
||||
</article>
|
||||
{/if}
|
||||
{/each}
|
||||
<p class="disclaimer">See also our Github page <a href="https://github.com/caos/zitadel" rel="external">ZITADEL </a> for questions regarding the sourcecode.</p></div>
|
||||
|
||||
<style>
|
||||
.quickstarts {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: 1em;
|
||||
min-height: calc(100vh - var(--nav-h));
|
||||
padding: var(--top-offset) var(--side-nav) 6rem var(--side-nav);
|
||||
max-width: var(--main-width);
|
||||
margin: 0 auto 0 auto;
|
||||
}
|
||||
|
||||
h2 {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
color: white;
|
||||
max-width: 18em;
|
||||
font-size: var(--h3);
|
||||
font-weight: 400;
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.quickstart {
|
||||
margin: 3.2rem 0 1rem 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.quickstart .anchor {
|
||||
position: absolute;
|
||||
display: block;
|
||||
background-size: 30px 30px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
left: -1.3em;
|
||||
opacity: 0;
|
||||
color: white;
|
||||
transition: opacity 0.2s;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
h2:hover .anchor {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.quickstart img {
|
||||
max-width: 150px;
|
||||
max-height: 150px;
|
||||
object-fit: contain;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.quickstart .sub {
|
||||
font-size: 12px;
|
||||
font-size: bold;
|
||||
text-transform: uppercase;
|
||||
color: var(--second);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.quickstart .info {
|
||||
font-size: 12px;
|
||||
font-size: bold;
|
||||
text-transform: uppercase;
|
||||
color: var(--dark-text);
|
||||
margin: 1rem 0 0 0;
|
||||
}
|
||||
|
||||
.quickstart .link,
|
||||
.quickstart .link i{
|
||||
color: var(--prime);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.quickstart:first-child {
|
||||
margin: 0 0 2rem 0;
|
||||
padding: 0 0 4rem 0;
|
||||
border-bottom: var(--border-w) solid #6767785b; /* based on --second */
|
||||
}
|
||||
.quickstart:first-child h2 {
|
||||
font-size: 4rem;
|
||||
font-weight: 400;
|
||||
color: var(--second);
|
||||
}
|
||||
|
||||
.quickstart p {
|
||||
font-size: var(--h5);
|
||||
max-width: 30em;
|
||||
color: var(--dark-text);
|
||||
}
|
||||
:global(.quickstarts .quickstart ul) {
|
||||
margin-left: 3.2rem;
|
||||
}
|
||||
.quickstarts :global(.anchor) {
|
||||
top: calc((var(--h3) - 24px) / 2);
|
||||
}
|
||||
|
||||
.quickstart:last-child {
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.quickstarts :global(.anchor) {
|
||||
transform: scale(0.6);
|
||||
opacity: 1;
|
||||
left: -1.0em;
|
||||
}
|
||||
}
|
||||
|
||||
.disclaimer {
|
||||
margin-top: 100px;
|
||||
}
|
||||
</style>
|
||||
@@ -3,8 +3,6 @@ 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';
|
||||
|
||||
@@ -12,7 +10,6 @@ polka()
|
||||
.use(
|
||||
compression({ threshold: 0 }),
|
||||
sirv('static', { dev }),
|
||||
i18nMiddleware(),
|
||||
sapper.middleware()
|
||||
)
|
||||
.listen(PORT, err => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { files, routes, shell, timestamp } from '@sapper/service-worker';
|
||||
import { files, shell, timestamp } from '@sapper/service-worker';
|
||||
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
const ASSETS = `cache${timestamp}`;
|
||||
|
||||
// `shell` is an array of all the files generated by the bundler,
|
||||
@@ -51,12 +52,12 @@ self.addEventListener('fetch', event => {
|
||||
// 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 (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;
|
||||
|
||||
@@ -79,4 +80,4 @@ self.addEventListener('fetch', event => {
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -98,7 +98,7 @@
|
||||
|
||||
<!-- Sapper creates a <script> tag containing `app/client.js`
|
||||
and anything else it needs to hydrate the app and
|
||||
initialise the router -->
|
||||
initialise the router -->
|
||||
%sapper.scripts%
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export default function generate_code_tabs(dirpath, dir) {
|
||||
|
||||
}
|
||||
@@ -20,18 +20,16 @@ const block_types = [
|
||||
'tablecell'
|
||||
];
|
||||
|
||||
export default function generate_docs(dirpath, dir, lang) {
|
||||
export default function generate_docs(dirpath, dir) {
|
||||
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`);
|
||||
return file[0] !== '.' && path.extname(file) === '.md' && file.endsWith(`.md`);
|
||||
})
|
||||
.map((file) => {
|
||||
const markdown = fs.readFileSync(`${dirpath}${dir}/${file}`, 'utf-8');
|
||||
@@ -45,7 +43,7 @@ export default function generate_docs(dirpath, dir, lang) {
|
||||
|
||||
renderer.link = link_renderer;
|
||||
|
||||
renderer.hr = (str) => {
|
||||
renderer.hr = () => {
|
||||
block_open = true;
|
||||
|
||||
return '<div class="side-by-side"><div class="copy">';
|
||||
@@ -65,7 +63,9 @@ export default function generate_docs(dirpath, dir, lang) {
|
||||
};
|
||||
|
||||
renderer.code = (source, lang) => {
|
||||
source = source.replace(/^ +/gm, (match) => match.split(' ').join('\t'));
|
||||
source = source.replace(/^ +/gm, match =>
|
||||
match.split(' ').join('\t')
|
||||
);
|
||||
|
||||
const lines = source.split('\n');
|
||||
|
||||
@@ -90,6 +90,11 @@ export default function generate_docs(dirpath, dir, lang) {
|
||||
|
||||
const plang = langs[lang];
|
||||
const { value: highlighted } = hljs.highlight(lang, source);
|
||||
// const highlighted = PrismJS.highlight(
|
||||
// source,
|
||||
// PrismJS.languages[plang],
|
||||
// lang
|
||||
// );
|
||||
|
||||
const html = `<div class='${class_name}'>${prefix}<pre class='language-${plang}'><code>${highlighted}</code></pre></div>`;
|
||||
|
||||
@@ -101,16 +106,17 @@ export default function generate_docs(dirpath, dir, lang) {
|
||||
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}`;
|
||||
});
|
||||
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 });
|
||||
}
|
||||
@@ -118,12 +124,12 @@ export default function generate_docs(dirpath, dir, lang) {
|
||||
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>
|
||||
<a href="${dir}#${slug}" class="anchor" aria-hidden="true"><i class="las la-link"></i></a>
|
||||
${text}
|
||||
</h${level}>`;
|
||||
};
|
||||
|
||||
block_types.forEach((type) => {
|
||||
block_types.forEach(type => {
|
||||
const fn = renderer[type];
|
||||
renderer[type] = function () {
|
||||
return fn.apply(this, arguments);
|
||||
@@ -141,4 +147,4 @@ export default function generate_docs(dirpath, dir, lang) {
|
||||
file
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import fs from 'fs';
|
||||
|
||||
export default function generate_docs(dirpath, dir, lang) {
|
||||
export default function generate_seo(dirpath, dir) {
|
||||
try {
|
||||
return fs.readFileSync(`${dirpath}${dir}/seo_${lang}.html`, 'utf-8');
|
||||
return fs.readFileSync(`${dirpath}${dir}/seo.html`, 'utf-8');
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
|
||||
16
site/src/utils/highlight.js
Normal file
16
site/src/utils/highlight.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'prismjs/components/prism-bash';
|
||||
|
||||
import PrismJS from 'prismjs';
|
||||
|
||||
import { langs } from './markdown.js';
|
||||
|
||||
export function highlight(source, lang) {
|
||||
const plang = langs[lang] || '';
|
||||
const highlighted = plang ? PrismJS.highlight(
|
||||
source,
|
||||
PrismJS.languages[plang],
|
||||
lang
|
||||
) : source.replace(/[&<>]/g, c => ({ '&': '&', '<': '<', '>': '>' })[c]);
|
||||
|
||||
return `<pre class='language-${plang}'><code>${highlighted}</code></pre>`;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -22,7 +22,8 @@ export function initPhotoSwipeFromDOM(gallerySelector) {
|
||||
|
||||
linkEl = figureEl.children[0]; // <a> element
|
||||
|
||||
size = linkEl.getAttribute('data-size').split('x');
|
||||
const dataSize = linkEl.getAttribute('data-size');
|
||||
size = dataSize ? dataSize.split('x') : '1920x1080'.split('x');
|
||||
|
||||
// create slide object
|
||||
item = {
|
||||
|
||||
@@ -1,68 +1,66 @@
|
||||
import slugify from '@sindresorhus/slugify';
|
||||
|
||||
export const SLUG_PRESERVE_UNICODE = false;
|
||||
export const SLUG_SEPARATOR = '_';
|
||||
import { SLUG_SEPARATOR } from '../../config';
|
||||
|
||||
/* url-safe processor */
|
||||
|
||||
export const urlsafeSlugProcessor = (string, opts) => {
|
||||
const { separator = SLUG_SEPARATOR } = opts || {};
|
||||
|
||||
return slugify(string, {
|
||||
customReplacements: [
|
||||
// runs before any other transformations
|
||||
export const urlsafeSlugProcessor = string =>
|
||||
slugify(string, {
|
||||
customReplacements: [ // runs before any other transformations
|
||||
['$', 'DOLLAR'], // `$destroy` & co
|
||||
['-', 'DASH'] // conflicts with `separator`
|
||||
],
|
||||
separator,
|
||||
separator: SLUG_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);
|
||||
const isNonAlphaNumUnicode =
|
||||
string => !alphaNumRegex.test(string) && unicodeRegex.test(string);
|
||||
|
||||
export const unicodeSafeProcessor = (string, opts) => {
|
||||
const { separator = SLUG_SEPARATOR } = opts || {};
|
||||
export const unicodeSafeProcessor = string =>
|
||||
string.split('')
|
||||
.reduce((accum, char, index, array) => {
|
||||
const type = isNonAlphaNumUnicode(char) ? 'pass' : 'process';
|
||||
|
||||
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 === 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);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
};
|
||||
.join(SLUG_SEPARATOR);
|
||||
|
||||
/* processor */
|
||||
|
||||
export const makeSlugProcessor = (preserveUnicode = false) => preserveUnicode
|
||||
? unicodeSafeProcessor
|
||||
: urlsafeSlugProcessor;
|
||||
|
||||
/* session processor */
|
||||
|
||||
@@ -78,7 +76,6 @@ export const make_session_slug_processor = ({
|
||||
|
||||
if (seen.has(slug)) throw new Error(`Duplicate slug ${slug}`);
|
||||
seen.add(slug);
|
||||
|
||||
return slug;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user