docs: searchable documentation & seo (#911)
* create search field * search trigger, show field on interaction * update deps, fix emitter * crop out html, filtered search, i18h, layout * i18n * catch crtl f * create combindes result store * fix search query, remove store * fixed search on side * fix preload * improve mobile layout, assets * layout optimisations * header * doc nav bar, mobile, new dashboard * toolbar * fix modal * z-index issue, header * hl param * fix lang switch, nav * home, sub section, 18n, layout, assets * develope, docs sublinks * update home, mobile first * fix language switcher * add home seo * fix flex search, dashboard * seo embed, fix docs dropdown * mouse navigation in search * jsonld * seo * fix link * rm section if none * rm unused segment * update lock * remove combined slug * Apply suggestions from code review Co-authored-by: Florian Forster <florian@caos.ch>
35
site/docs/administrate/seo_de.html
Normal file
@ -0,0 +1,35 @@
|
||||
<meta property="description" content="{$_('home_seo.description')}" />
|
||||
|
||||
<meta property="og:url" content="https://docs.zitadel.ch" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="Administration" />
|
||||
<meta property="og:description" content="Erfahren Sie mehr über die Administration von ZITADEL" />
|
||||
<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="Administration" />
|
||||
<meta name="twitter:description" content="Erfahren Sie mehr über die Administration von ZITADEL" />
|
||||
<meta name="twitter:image" content="https://www.zitadel.ch/zitadel-social-preview25.png">
|
||||
|
||||
<script type='application/ld+json'>
|
||||
{
|
||||
"@context" : "http://schema.org/",
|
||||
"@type" : "WebPage",
|
||||
"about": {
|
||||
"name":"Administrations Dokumentation",
|
||||
"description":"Erfahren Sie mehr über die Administration von ZITADEL",
|
||||
},
|
||||
"author": {
|
||||
"name":"caos AG",
|
||||
"address":"Teufener Strasse 19, 9000 St.Gallen",
|
||||
"email":"hi@caos.ch"
|
||||
},
|
||||
"copyrightYear":"2020",
|
||||
"creator": {
|
||||
"name":"caos AG",
|
||||
"address":"Teufener Strasse 19, 9000 St.Gallen",
|
||||
"email":"hi@caos.ch"
|
||||
},
|
||||
}
|
||||
</script>
|
35
site/docs/administrate/seo_en.html
Normal file
@ -0,0 +1,35 @@
|
||||
<meta property="description" content="How to administrate ZITADEL" />
|
||||
|
||||
<meta property="og:url" content="https://docs.zitadel.ch" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="Administration Documentation" />
|
||||
<meta property="og:description" content="How to administrate ZITADEL" />
|
||||
<meta property="og:image" content="https://www.zitadel.ch/zitadel-social-preview25.png" />
|
||||
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@zitadel_ch">
|
||||
<meta name="twitter:title" content="Administration Documentation" />
|
||||
<meta name="twitter:description" content="How to administrate ZITADEL" />
|
||||
<meta name="twitter:image" content="https://www.zitadel.ch/zitadel-social-preview25.png">
|
||||
|
||||
<script type='application/ld+json'>
|
||||
{
|
||||
"@context" : "http://schema.org/",
|
||||
"@type" : "WebPage",
|
||||
"about": {
|
||||
"name":"Administration Documentation",
|
||||
"description":"How to administrate ZITADEL",
|
||||
},
|
||||
"author": {
|
||||
"name":"caos AG",
|
||||
"address":"Teufener Strasse 19, 9000 St.Gallen",
|
||||
"email":"hi@caos.ch"
|
||||
},
|
||||
"copyrightYear":"2020",
|
||||
"creator": {
|
||||
"name":"caos AG",
|
||||
"address":"Teufener Strasse 19, 9000 St.Gallen",
|
||||
"email":"hi@caos.ch"
|
||||
},
|
||||
}
|
||||
</script>
|
1607
site/package-lock.json
generated
@ -16,18 +16,18 @@
|
||||
"@sindresorhus/slugify": "^1.1.0",
|
||||
"compression": "^1.7.4",
|
||||
"golden-fleece": "^1.0.9",
|
||||
"highlight.js": "^10.1.2",
|
||||
"marked": "^1.1.1",
|
||||
"highlight.js": "^10.3.1",
|
||||
"marked": "^1.2.2",
|
||||
"polka": "^0.5.2",
|
||||
"sirv": "^1.0.7",
|
||||
"svelte-i18n": "^3.0.4"
|
||||
"svelte-i18n": "^3.1.0",
|
||||
"sirv": "^1.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/core": "^7.12.3",
|
||||
"@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",
|
||||
"@babel/preset-env": "^7.12.1",
|
||||
"@babel/runtime": "^7.12.1",
|
||||
"@rollup/plugin-commonjs": "^16.0.0",
|
||||
"@rollup/plugin-json": "^4.0.3",
|
||||
"@rollup/plugin-node-resolve": "^10.0.0",
|
||||
@ -36,7 +36,7 @@
|
||||
"rollup-plugin-babel": "^4.4.0",
|
||||
"rollup-plugin-livereload": "^2.0.0",
|
||||
"rollup-plugin-replace": "^2.2.0",
|
||||
"rollup-plugin-svelte": "^6.0.1",
|
||||
"rollup-plugin-svelte": "^6.1.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"sapper": "^0.28.10",
|
||||
"svelte": "^3.29.4"
|
||||
|
51
site/src/components/Button.svelte
Normal file
@ -0,0 +1,51 @@
|
||||
<script>
|
||||
export let selected = false;
|
||||
</script>
|
||||
<style>
|
||||
button {
|
||||
background: inherit;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--prime);
|
||||
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: 40px;
|
||||
color: white;
|
||||
transition: background-color .2 ease;
|
||||
outline: none;
|
||||
min-width: 120px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button[selected] {
|
||||
background-color: var(--prime);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button[selected]:hover {
|
||||
background-color: var(--prime);
|
||||
opacity: .9;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button[selected]:active {
|
||||
background-color: var(--prime);
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #e91e6310;
|
||||
}
|
||||
button:active {
|
||||
background-color: #e91e6320;
|
||||
}
|
||||
|
||||
button :global(span) {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<button {selected}>
|
||||
<slot />
|
||||
</button>
|
@ -4,17 +4,32 @@
|
||||
import Icon from "./Icon.svelte";
|
||||
import manifest from '../../static/manifest.json';
|
||||
export let owner = "caos";
|
||||
export let project = "zitadel";
|
||||
export let path = "site/docs";
|
||||
export let path = "docs";
|
||||
export let dir = "";
|
||||
export let edit_title = "edit this section";
|
||||
export let sections;
|
||||
import SearchSelector from './SearchSelector.svelte';
|
||||
import SearchTrigger from './SearchTrigger.svelte';
|
||||
import LanguageSwitcher from './LanguageSwitcher.svelte';
|
||||
let searchEnabled = false;
|
||||
let active_section;
|
||||
|
||||
let container;
|
||||
let aside;
|
||||
let show_contents = false;
|
||||
|
||||
function handleSearch(event) {
|
||||
searchEnabled = !event.detail.closed;
|
||||
}
|
||||
|
||||
function handleKeydown(event) {
|
||||
const isCtrlKey = navigator.platform.indexOf('Mac') > -1 ? event.metaKey : event.ctrlKey
|
||||
if ((event.keyCode == 114) || (isCtrlKey && event.keyCode == 70)) {
|
||||
event.preventDefault();
|
||||
searchEnabled = !searchEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// don't update `active_section` for headings above level 4, see _sections.js
|
||||
const anchors = container.querySelectorAll("[id]:not([data-scrollignore])");
|
||||
@ -73,8 +88,8 @@
|
||||
background-color: var(--side-nav-back);
|
||||
left: 0.8rem;
|
||||
bottom: 0.8rem;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
width: 3.4rem; /* size to match button */
|
||||
height: 3.4rem; /* size to match button */
|
||||
border-radius: .5rem;
|
||||
overflow: hidden;
|
||||
border: 1px solid #8795a1;
|
||||
@ -91,8 +106,8 @@
|
||||
}
|
||||
|
||||
aside.open {
|
||||
width: calc(100vw - 3rem);
|
||||
height: calc(100vh - var(--nav-h) - 3rem);
|
||||
width: calc(100vw - 1.5rem);
|
||||
height: calc(100vh - var(--nav-h) - 9rem);
|
||||
}
|
||||
|
||||
aside.open::before {
|
||||
@ -100,7 +115,7 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: calc(100% - 2rem);
|
||||
width: 100%;
|
||||
height: 2em;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
@ -110,15 +125,15 @@
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 1.9em;
|
||||
width: calc(100% - 2rem);
|
||||
height: 2em;
|
||||
/* background: linear-gradient(
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 3em;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.7) 50%,
|
||||
rgba(255, 255, 255, 1) 100%
|
||||
); */
|
||||
#1a1f3600 0%,
|
||||
#1a1f3680 50%,
|
||||
#1a1f36 100%
|
||||
);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@ -132,6 +147,41 @@
|
||||
bottom: 2em;
|
||||
}
|
||||
|
||||
.sidebar :global(.language-switcher) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
aside.open .sidebar .home {
|
||||
display: none;
|
||||
}
|
||||
|
||||
aside .sidebar :global(.search-trigger) {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
aside.open .sidebar :global(.search-trigger) {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
|
||||
background-color: #00000010;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: #00000010;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background-color: #6c8eef30;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
@ -145,8 +195,8 @@
|
||||
aside {
|
||||
display: block;
|
||||
width: var(--sidebar-w);
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
height: calc(100vh - var(--searchbar-space));
|
||||
top: var(--searchbar-space); /* space for searchbar */
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
box-shadow: none;
|
||||
@ -164,20 +214,18 @@
|
||||
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;
|
||||
}
|
||||
|
||||
aside .sidebar :global(.search-trigger) {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
padding: var(--top-offset) 0 6.4rem 0;
|
||||
padding: 1em .5rem 6.4rem 0;
|
||||
font-family: var(--font);
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
@ -185,6 +233,37 @@
|
||||
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;
|
||||
}
|
||||
|
||||
.sidebar :global(.search-trigger) {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-left: calc(var(--sidebar-w) + var(--side-nav));
|
||||
}
|
||||
@ -233,9 +312,9 @@
|
||||
display: block;
|
||||
/* TODO replace link icon */
|
||||
/* background: url(../icons/link.svg) 0 50% no-repeat; */
|
||||
background-size: 1em 1em;
|
||||
width: 1.4em;
|
||||
height: 1em;
|
||||
background-size: 30px 30px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
left: -1.3em;
|
||||
opacity: 0;
|
||||
color: white;
|
||||
@ -245,7 +324,7 @@
|
||||
|
||||
.content :global(.anchor) :global(i) {
|
||||
color: #8795a1;
|
||||
font-size: 24px;
|
||||
/* font-size: 24px; */
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@ -394,6 +473,8 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:window on:keydown={handleKeydown}/>
|
||||
|
||||
<div bind:this={container} class="content listify">
|
||||
{#each sections as section}
|
||||
<section data-id={section.slug}>
|
||||
@ -405,7 +486,7 @@
|
||||
{@html section.metadata.title}
|
||||
<small>
|
||||
<a
|
||||
href="https://github.com/{owner}/{project}/edit/master{path}/{dir}/{section.file}"
|
||||
href="https://github.com/{owner}/zitadel/edit/master/site/{path}/{dir}/{section.file}"
|
||||
title={edit_title}>
|
||||
<Icon name="las la-external-link-alt" size="24px" />
|
||||
</a>
|
||||
@ -419,11 +500,23 @@
|
||||
|
||||
<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)}>
|
||||
<Icon name={show_contents ? 'las la-window-close' : 'las la-bars'} />
|
||||
<Icon name={show_contents ? 'las la-times' : 'las la-bars'} />
|
||||
</button>
|
||||
</aside>
|
||||
|
||||
{#if searchEnabled == true}
|
||||
<SearchSelector on:close={handleSearch} {sections} slug={dir}></SearchSelector>
|
||||
{/if}
|
172
site/src/components/DocsHeader.svelte
Normal file
@ -0,0 +1,172 @@
|
||||
<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}
|
@ -6,7 +6,7 @@
|
||||
export let sections = [];
|
||||
export let active_section = null;
|
||||
export let show_contents;
|
||||
export let prevent_sidebar_scroll = false;
|
||||
export let prevent_sidebar_scroll = false;
|
||||
|
||||
let ul;
|
||||
|
||||
@ -97,7 +97,6 @@
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
margin-right: 1rem;
|
||||
margin-left: .5rem;
|
||||
color: white;
|
||||
}
|
||||
@ -111,7 +110,7 @@
|
||||
.section:hover,
|
||||
.subsection:hover,
|
||||
.active {
|
||||
color: #5282c1;
|
||||
color: var(--prime);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -14,6 +14,7 @@
|
||||
object-fit: contain;
|
||||
-webkit-transform-origin: center center;
|
||||
transform-origin: center center;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script context="module">
|
||||
import { setCookie } from '../modules/cookie.js';
|
||||
import { goto } from '@sapper/app';
|
||||
import { docLanguages } from '../modules/language-store.js'
|
||||
import {LANGUAGES} from '../../config.js';
|
||||
</script>
|
||||
@ -10,56 +11,50 @@
|
||||
|
||||
let group= $locale;
|
||||
|
||||
$:setLocale(group);
|
||||
function setLocale(language) {
|
||||
function reload(language) {
|
||||
if (typeof window !== 'undefined') {
|
||||
locale.set(language);
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--deep-blue: #1e3470;
|
||||
--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;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.language-switcher input {
|
||||
appearance: none;
|
||||
display: none;
|
||||
z-index: 1;
|
||||
width: var(--sidebar-w);
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.language-switcher .select {
|
||||
button {
|
||||
height: var(--height);
|
||||
width: var(--height);
|
||||
border-radius: 50vw;
|
||||
font-size: calc(var(--height) / 2.5);
|
||||
color: #fff;
|
||||
mix-blend-mode: difference;
|
||||
margin: .5rem 1rem;
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.language-switcher .current {
|
||||
background-color: white;
|
||||
color: black;
|
||||
button.current {
|
||||
color: var(--prime);
|
||||
}
|
||||
</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>
|
||||
<button on:click="{() => reload(lang)}" class="{lang == group ? 'current': ''}">{lang == 'de'? 'Deutsch' : 'English'}</button>
|
||||
{/each}
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import LanguageSwitcher from './LanguageSwitcher.svelte'
|
||||
import NavItem from './NavItem.svelte'
|
||||
import { onMount, setContext } from 'svelte';
|
||||
import { setContext } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import Icon from './Icon.svelte';
|
||||
export let segment;
|
||||
@ -31,7 +31,8 @@
|
||||
<style>
|
||||
header {
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@ -70,10 +71,10 @@
|
||||
}
|
||||
|
||||
.home {
|
||||
width: 200px;
|
||||
line-height: 22px;
|
||||
font-size: 22px;
|
||||
display: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.home:hover {
|
||||
@ -81,10 +82,6 @@
|
||||
text-decoration:none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.home img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
@ -93,10 +90,9 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 400px) {
|
||||
.home {
|
||||
display: inline-block;
|
||||
}
|
||||
.home span {
|
||||
color: var(--second);
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
a img {
|
||||
@ -105,10 +101,6 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.switcher-wrapper {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -117,22 +109,35 @@
|
||||
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);
|
||||
color: white;
|
||||
transition: background-color .2 ease;
|
||||
margin: 0 1rem;
|
||||
min-width: 120px;
|
||||
/* background: #2a2f45; */
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #5282c110;
|
||||
background-color: var(--back-hover);
|
||||
}
|
||||
button:active {
|
||||
background-color: #5282c120;
|
||||
background-color: var(--back-hover);
|
||||
}
|
||||
|
||||
button span {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.show-on-desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 832px) {
|
||||
.show-on-desktop {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -151,21 +156,26 @@
|
||||
{:else if title}
|
||||
{title}
|
||||
{/if}
|
||||
<span>DOCS</span>
|
||||
</a>
|
||||
|
||||
<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>{$_('toconsole')}</span>
|
||||
</button>
|
||||
</a>
|
||||
<a href='https://console.zitadel.ch'>
|
||||
<button>
|
||||
<span>{$_('login')}</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>
|
||||
<a href='https://accounts.zitadel.ch/register'>
|
||||
<button style="border-color: var(--second); margin-left: 0;">
|
||||
<span>{$_('register')}</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
@ -2,10 +2,11 @@
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--text);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
|
236
site/src/components/SearchSelector.svelte
Normal file
@ -0,0 +1,236 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
export let sections;
|
||||
export let slug;
|
||||
|
||||
let filteredResults = [];
|
||||
|
||||
let selectedIndex = 0;
|
||||
|
||||
$: selectIndex(selectedIndex);
|
||||
|
||||
function init(el){
|
||||
el.focus()
|
||||
}
|
||||
|
||||
function handleKeydown(event) {
|
||||
console.log(event)
|
||||
if (event) {
|
||||
if (event.keyCode == 37 || event.keyCode == 38) {
|
||||
if (selectedIndex > 0) {
|
||||
event.preventDefault();
|
||||
selectedIndex --;
|
||||
}
|
||||
}
|
||||
else if (event.keyCode == 39 || event.keyCode == 40) {
|
||||
event.preventDefault();
|
||||
selectedIndex ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectIndex(index) {
|
||||
console.log(index);
|
||||
const el = document.getElementById(index);
|
||||
if (el) {
|
||||
console.log('focus: '+ el);
|
||||
el.focus();
|
||||
}
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let searchValue = '';
|
||||
|
||||
$: executeQuery(searchValue);
|
||||
|
||||
function executeQuery(value) {
|
||||
const toSearchFor = value.toLowerCase();
|
||||
const filteredSections = sections.filter(section => {
|
||||
const slugContainsValue = section.slug.toLowerCase().includes(toSearchFor);
|
||||
const htmlContainsValue = section.html.replace(/<[^>]*>?/gm, '').toLowerCase().includes(toSearchFor);
|
||||
return slugContainsValue || htmlContainsValue;
|
||||
}).map(section => {
|
||||
// const removedHtml = section.html.replace(/<[^>]*>?/gm, '');
|
||||
// const foundIndex = removedHtml.indexOf(toSearchFor);
|
||||
// const subhtml = section.html.substring(foundIndex, (removedHtml.length - 1) - foundIndex > 150 ? 150 : removedHtml.length - 1)
|
||||
return {
|
||||
title: section.slug,
|
||||
slug: section.slug,
|
||||
}
|
||||
});
|
||||
|
||||
const filteredSubSections = sections.map(section => {
|
||||
return section.subsections.map(sub => {
|
||||
return {parent: section.slug, ...sub};
|
||||
});
|
||||
}).flat().filter(subsection => {
|
||||
if (subsection.slug) {
|
||||
const slugContainsValue = subsection.slug.toLowerCase().includes(toSearchFor);
|
||||
const titleContainsValue = subsection.title.toLowerCase().includes(toSearchFor);
|
||||
return slugContainsValue || titleContainsValue;
|
||||
}
|
||||
});
|
||||
|
||||
filteredResults = filteredSections.concat(filteredSubSections);
|
||||
console.log(filteredResults);
|
||||
}
|
||||
|
||||
function closeSearch() {
|
||||
dispatch('close', {
|
||||
closed: true,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #ffffff30;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.search-field {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
z-index: 100;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, .12);
|
||||
background-color: #2a2f45;
|
||||
border-radius: 8px;
|
||||
position: fixed;
|
||||
top: 20%;
|
||||
left: 50%;
|
||||
padding: 1rem;
|
||||
transform: translateX(-50%);
|
||||
display: relative;
|
||||
}
|
||||
|
||||
.search-field .search-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #ffffff10;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.search-field .search-line i {
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 45px;
|
||||
box-sizing: border-box;
|
||||
padding-inline-start: 10px;
|
||||
outline: none;
|
||||
display: inline-block;
|
||||
text-align: start;
|
||||
background-color: inherit;
|
||||
cursor: text;
|
||||
padding: 1px 20px;
|
||||
border-radius: 8px;
|
||||
margin: .5rem;
|
||||
transform: all .2 linear;
|
||||
font-size: 1.5rem;
|
||||
color: white;
|
||||
border: none;
|
||||
}
|
||||
|
||||
input::placeholder {
|
||||
font-size: 14px;
|
||||
color: var(--grey-text);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.result-d {
|
||||
color: var(--grey);
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
font-size: 1.3rem;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.result-list {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.result-list .result-item {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
margin: 2px 0;
|
||||
border-bottom: none;
|
||||
height: 77px;
|
||||
max-height: 80px;
|
||||
}
|
||||
|
||||
.result-list .result-item:hover {
|
||||
background-color: #556cd680;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.result-list .result-item:focus {
|
||||
background-color: #556cd6;
|
||||
}
|
||||
|
||||
.text {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.result-list .result-item .title{
|
||||
margin: 0;
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.result-list .result-item .title .second-param {
|
||||
color: var(--grey-text);
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
.result-list .result-item .desc{
|
||||
color: var(--grey-text);
|
||||
margin: 0;
|
||||
font-size: 1.3rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:window on:keydown={handleKeydown}/>
|
||||
|
||||
<div on:click="{closeSearch}" class="overlay"></div>
|
||||
<div class="search-field">
|
||||
<div class="search-line">
|
||||
<i class="las la-search"></i>
|
||||
<input placeholder="{$_('search_input_placeholder')}" bind:value={searchValue} use:init>
|
||||
</div>
|
||||
<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}">
|
||||
<div class="text">
|
||||
{#if result.level > 2}
|
||||
<p class="title">{result.title}<span class="second-param">{result.parent}</span></p>
|
||||
{:else}
|
||||
<p class="title">{result.slug}</p>
|
||||
{/if}
|
||||
<p class="desc" style="color: #85d996;">{slug}#{result.slug}</p>
|
||||
<p class="desc">{result.html || result.slug}</p>
|
||||
</div>
|
||||
<i class="las la-link"></i>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
64
site/src/components/SearchTrigger.svelte
Normal file
@ -0,0 +1,64 @@
|
||||
<script>
|
||||
import {onMount} from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
let buttonname = '';
|
||||
|
||||
onMount(() => {
|
||||
buttonname = navigator.platform.indexOf('Mac') > -1 ? 'Cmd': 'Ctrl';
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
button {
|
||||
height: 20px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--grey-text);
|
||||
margin: 1rem 2rem;
|
||||
background-color: #2a2f45;
|
||||
border: 1px solid #ffffff20;
|
||||
height: 35px;
|
||||
padding: 0 1rem;
|
||||
width: calc(100% - 4rem);
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
top: 80px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #373d58;
|
||||
}
|
||||
|
||||
button i {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
button span {
|
||||
font-size: 1.3rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.fill-space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.strg {
|
||||
font-size: 1.3rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 832px) {
|
||||
button {
|
||||
width: calc(var(--sidebar-w) - 4rem);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<button on:click class="search-trigger">
|
||||
<i class="las la-search"></i>
|
||||
<span>{$_('search_button_holder')}</span>
|
||||
<span class="fill-space"></span>
|
||||
<span class="strg">{buttonname || 'Ctrl'} F</span>
|
||||
</button>
|
@ -3,14 +3,48 @@
|
||||
"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",
|
||||
"integratelink": "Sichern Sie Ihre Applikationen und Schnittstellen",
|
||||
"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",
|
||||
"developlink":"Entwickeln",
|
||||
"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":"Architektur und Technologien",
|
||||
"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":"Dokumentation",
|
||||
"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",
|
||||
"toconsole":"ZITADEL Console öffnen"
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -3,13 +3,47 @@
|
||||
"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",
|
||||
"integratelink": "Secure your applications and apis with ZITADEL",
|
||||
"administratelink": "Administrate ZITADEL",
|
||||
"developlink":"Develop with the ZITADEL api's",
|
||||
"docslink":"ZITADEL Documentations",
|
||||
"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",
|
||||
"toconsole":"Open ZITADEL Console"
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,19 +4,33 @@ 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';
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
// });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,32 +1,42 @@
|
||||
<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 };
|
||||
const {docs, seo} = await this.fetch(`${slug}.json`).then(r => r.json());
|
||||
return { sections: docs, 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';
|
||||
export let tags;
|
||||
import { initPhotoSwipeFromDOM } from '../utils/photoswipe.js';
|
||||
import SearchSelector from '../components/SearchSelector.svelte';
|
||||
|
||||
onMount(() => {
|
||||
initPhotoSwipeFromDOM('.zitadel-gallery');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@media (min-width: 832px) {
|
||||
:global(main) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<svelte:head>
|
||||
<title>{manifest.name} • {slug}</title>
|
||||
|
||||
{#each tags as { name, content }, i}
|
||||
<meta name={name} content={content} />
|
||||
{/each}
|
||||
{ @html seo}
|
||||
</svelte:head>
|
||||
|
||||
<Docs {sections} project="zitadel/site" dir="{slug}"/>
|
||||
<DocsHeader {slug}></DocsHeader>
|
||||
<Docs {sections} project="zitadel/site" dir="{slug}"/>
|
||||
|
||||
<!-- <SearchSelector></SearchSelector> -->
|
@ -5,11 +5,16 @@
|
||||
import NavItem from "../components/NavItem.svelte";
|
||||
import manifest from '../../static/manifest.json';
|
||||
import PhotoSwipe from '../components/PhotoSwipe.svelte';
|
||||
|
||||
export let segment;
|
||||
const { page } = stores();
|
||||
</script>
|
||||
|
||||
<script context="module">
|
||||
import { waitLocale } from 'svelte-i18n';
|
||||
export async function preload(page) {
|
||||
return waitLocale();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
main {
|
||||
position: relative;
|
||||
@ -19,7 +24,7 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<Nav {segment} title="{manifest.name}" logo="logos/zitadel-logo-light.svg"></Nav>
|
||||
<!-- <Nav {segment} title="{manifest.name}" logo="logos/zitadel-logo-light.svg"></Nav> -->
|
||||
|
||||
<main>
|
||||
<slot />
|
||||
|
@ -7,33 +7,175 @@
|
||||
<script>
|
||||
import Split from "../components/Split.svelte";
|
||||
import Section from '../components/Section.svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
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);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h2 {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.caos-back {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
height: 60vh;
|
||||
max-height: 500px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.section {
|
||||
width: 100%;
|
||||
margin-top: 70vh;
|
||||
min-height: 80vh;
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
.section .caos-back {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.subsection {
|
||||
display: block;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.subsection .getstarted-btn {
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.doc-container .doc {
|
||||
padding: 1.5rem;
|
||||
background: #2a2f45;
|
||||
border-radius: 10px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.doc-container .doc img{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.doc-container .doc .text{
|
||||
top: 180px;
|
||||
}
|
||||
|
||||
.doc-container .doc .text p{
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.doc-container .doc .text h4 {
|
||||
font-size: 20px;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.doc-container .doc .text .section{
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.doc-container .doc a {
|
||||
display: block;
|
||||
font-size: 1.5rem;
|
||||
border: none;
|
||||
margin-bottom: 1rem;
|
||||
padding: 0;
|
||||
font-weight: 700;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.doc-container .doc a i {
|
||||
color: var(--prime);
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.doc-container .doc a:hover {
|
||||
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;
|
||||
}
|
||||
|
||||
.sectionlinks .link {
|
||||
font-size: 15px;
|
||||
font-size: 13px !important;
|
||||
margin-bottom: 4px !important;
|
||||
border: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.caos-back {
|
||||
right: 0;
|
||||
height: 70vh;
|
||||
}
|
||||
.section {
|
||||
width: 50%;
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.section .left,
|
||||
.section .caos-back {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.section .caos-back {
|
||||
display: block;
|
||||
margin: 50px;
|
||||
}
|
||||
|
||||
.doc-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -1rem;
|
||||
}
|
||||
|
||||
.doc-container .doc {
|
||||
display: flex;
|
||||
margin: 1rem;
|
||||
max-width: 500px;
|
||||
flex: 1 0 auto;
|
||||
max-height: 350px;
|
||||
}
|
||||
|
||||
.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>
|
||||
@ -42,25 +184,170 @@
|
||||
<title>
|
||||
ZITADEL • Documentation
|
||||
</title>
|
||||
</svelte:head>
|
||||
<title>{$_('title')}</title>
|
||||
<meta property="description" content="{$_('home_seo.description')}" />
|
||||
|
||||
<img class="caos-back" src="logos/zitadel-logo-solo-darkdesign.svg" alt="caos logo">
|
||||
<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: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: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">
|
||||
<h2>{$_('title')}</h2>
|
||||
<p>{$_('description')}</p>
|
||||
<p>{$_('description2')}</p>
|
||||
<p>{$_('description3')}</p>
|
||||
|
||||
<ul style="list-style-type: none;">
|
||||
<li><a href="/start" >{$_('startlink')}</a></li>
|
||||
<li><a href="/integrate" >{$_('integratelink')}</a></li>
|
||||
<li><a href="/administrate" >{$_('administratelink')}</a></li>
|
||||
<li><a href="/develop" >{$_('developlink')}</a></li>
|
||||
<li><a href="/documentation" >{$_('docslink')}</a></li>
|
||||
<li><a href="/use" >{$_('uselink')}</a></li>
|
||||
</ul>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<a href="/start" class="getstarted-btn">
|
||||
<Button selected style="margin: 2rem 0;">
|
||||
{$_('startlink')}
|
||||
<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>
|
||||
|
||||
{#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>
|
||||
<!-- {:else if $locale == 'de'}
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<p class="section">{$_('inthissection')}</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>
|
||||
</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>
|
||||
|
||||
<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}
|
||||
</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>
|
||||
|
||||
<img src="img/personal2.png" alt="Develop" />
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
@ -51,10 +51,6 @@ export default function generate_docs(dirpath, dir, lang) {
|
||||
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'));
|
||||
|
||||
|
9
site/src/utils/generate_seo.js
Normal file
@ -0,0 +1,9 @@
|
||||
import fs from 'fs';
|
||||
|
||||
export default function generate_docs(dirpath, dir, lang) {
|
||||
try {
|
||||
return fs.readFileSync(`${dirpath}${dir}/seo_${lang}.html`, 'utf-8');
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
};
|
@ -9,7 +9,8 @@
|
||||
*/
|
||||
:root {
|
||||
--nav-h: 6rem;
|
||||
--top-offset: 6rem;
|
||||
--top-offset: 10rem;
|
||||
--searchbar-space: 140px;
|
||||
--sidebar-w: 30rem;
|
||||
--sidebar-mid-w: 36rem;
|
||||
--sidebar-large-w: 48rem;
|
||||
@ -32,11 +33,12 @@
|
||||
/* theme vars */
|
||||
.theme-default {
|
||||
--back: #1a1f36;
|
||||
--back-hover: #242b4b;
|
||||
--back-light: transparent;
|
||||
--back-api: #1a1f36;
|
||||
--prime: #5282c1;
|
||||
--prime: #6c8eef;
|
||||
--second: #ff2069;
|
||||
--flash: #72a2e0;
|
||||
--flash: #8fa6e7;
|
||||
|
||||
--nav-back: #1a1f36;
|
||||
--side-nav-back: #1a1f36;
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 7.7 KiB |
@ -1,47 +1,12 @@
|
||||
<?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>
|
||||
<?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 16 16" 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,-1928,0)">
|
||||
<g transform="matrix(1,-0,-0,1,1928,-0)">
|
||||
<use xlink:href="#_Image1" x="0.062" y="0" width="15.938px" height="16px" transform="matrix(0.996144,0,0,1,0,0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<image id="_Image1" width="16px" height="16px" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABUElEQVQ4jZ2SPy9DURjGn3up6XklZm53jJLGpokaaLUfwmIR6Rfo/QQSCR0MPkGlxGBhEaOZxMgkJgPJfQ7pMZSb/rkoJznLOfn98rxPXuAPx8czweBbODocrUJW/5egC/ME4vrg31CkDHgN4jHECcjeIE4Fh6evIyXwcVTuwjYBGSDmIFsYaQQfRxWI7S5MdK81IV79OoKPowoSa8Mx9wkCYhPiVtA68D8m8HG0ngHvZ8FDCXwjX4V4NADvQdzOgvsS+Ea+lsKJfcH3kLUgG/+uq6AHbqWwS0sDRHjxBbJLiOcQLyC7DW+qHgAC38gHEDchW4NYhCN7Jb5H1CN9hGMxfCjc9XewUcshsQIcVyCWvGwR4hgGJY5AYvXwaXb3x03sFHcmIS5BVoJYgjiXihzPwueo/Osq9wmj62mIy3BcQWKLcJz/C98vC9+DDnz4AV15qEiGMu6oAAAAAElFTkSuQmCC"/>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
site/static/img/develop2.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
site/static/img/personal2.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
site/static/img/projects2.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
site/static/img/usermanual.png
Normal file
After Width: | Height: | Size: 85 KiB |