documentation site (#81)
* init static site * add index * changes footer * remove search * add docs workflows * remove unused pages
23
.github/workflows/docs.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
name: docs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Deploy to gh-pages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: 'ayrat555/docs-site'
|
||||
submodules: 'recursive'
|
||||
- run: |
|
||||
git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
|
||||
- run: |
|
||||
git config --global user.email "ayratin555@gmail.com"
|
||||
git config --global user.name "Ayrat Badykov"
|
||||
git add . && git commit -m "Commit copied files"
|
||||
- name: Deploy docs
|
||||
run: |
|
||||
source ./docs/deploy.sh && build && deploy
|
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "docs/themes/adidoks"]
|
||||
path = docs/themes/adidoks
|
||||
url = https://github.com/aaranxu/adidoks.git
|
112
docs/config.toml
Normal file
|
@ -0,0 +1,112 @@
|
|||
# The URL the site will be built for
|
||||
base_url = "https://adidoks.netlify.com"
|
||||
title = "Fang"
|
||||
description = "Fang is a background task processing for Rust. It uses Postgres DB as a task queue."
|
||||
|
||||
# The site theme to use.
|
||||
theme = "adidoks"
|
||||
|
||||
# The default language; used in feeds and search index
|
||||
# Note: the search index doesn't support Chinese/Japanese/Korean Languages
|
||||
default_language = "en"
|
||||
|
||||
# Whether to automatically compile all Sass files in the sass directory
|
||||
compile_sass = true
|
||||
|
||||
# Whether to generate a feed file for the site
|
||||
generate_feed = true
|
||||
|
||||
# When set to "true", the generated HTML files are minified.
|
||||
minify_html = false
|
||||
|
||||
# The taxonomies to be rendered for the site and their configuration.
|
||||
taxonomies = [
|
||||
{name = "authors"}, # Basic definition: no feed or pagination
|
||||
]
|
||||
|
||||
# Whether to build a search index to be used later on by a JavaScript library
|
||||
# When set to "true", a search index is built from the pages and section
|
||||
# content for `default_language`.
|
||||
build_search_index = false
|
||||
|
||||
[search]
|
||||
# Whether to include the title of the page/section in the index
|
||||
include_title = true
|
||||
# Whether to include the description of the page/section in the index
|
||||
include_description = false
|
||||
# Whether to include the rendered content of the page/section in the index
|
||||
include_content = true
|
||||
|
||||
[markdown]
|
||||
# Whether to do syntax highlighting.
|
||||
# Theme can be customised by setting the `highlight_theme`
|
||||
# variable to a theme supported by Zola
|
||||
highlight_code = true
|
||||
|
||||
[extra]
|
||||
# Put all your custom variables here
|
||||
author = "Airat Badykov, Pepe Márquez"
|
||||
github = "https://github.com/ayrat555/fang"
|
||||
|
||||
# If running on netlify.app site, set to true
|
||||
is_netlify = true
|
||||
|
||||
# Set HTML file language
|
||||
language_code = "en-US"
|
||||
|
||||
# Set theme-color meta tag for Chrome browser
|
||||
theme_color = "#fff"
|
||||
|
||||
# More about site's title
|
||||
title_separator = "|" # set as |, -, _, etc
|
||||
title_addition = "Modern Documentation Theme"
|
||||
|
||||
|
||||
# Set date format in blog publish metadata
|
||||
timeformat = "%B %e, %Y" # e.g. June 14, 2021
|
||||
timezone = "America/New_York"
|
||||
|
||||
# Edit page on reposity or not
|
||||
edit_page = false
|
||||
docs_repo = "https://github.com/aaranxu/adidoks"
|
||||
repo_branch = "main"
|
||||
|
||||
## Math settings
|
||||
# options: true, false. Enable math support globally,
|
||||
# default: false. You can always enable math on a per page.
|
||||
math = false
|
||||
library = "katex" # options: "katex", "mathjax". default is "katex".
|
||||
|
||||
## Open Graph + Twitter Cards
|
||||
[extra.open]
|
||||
enable = true
|
||||
# this image will be used as fallback if a page has no image of its own
|
||||
image = "doks.png"
|
||||
twitter_site = "aaranxu"
|
||||
twitter_creator = "aaranxu"
|
||||
facebook_author = "ichunyun"
|
||||
facebook_publisher = "ichunyun"
|
||||
og_locale = "en_US"
|
||||
|
||||
## JSON-LD
|
||||
[extra.schema]
|
||||
type = "Organization"
|
||||
logo = "logo-doks.png"
|
||||
twitter = "https://twitter.com/aaranxu"
|
||||
linked_in = ""
|
||||
github = "https://github.com/aaranxu"
|
||||
section = "blog" # see config.extra.main~url
|
||||
## Sitelinks Search Box
|
||||
site_links_search_box = false
|
||||
|
||||
|
||||
[[extra.menu.social]]
|
||||
name = "GitHub"
|
||||
pre = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-github"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>'
|
||||
url = "https://github.com/ayrat555/fang"
|
||||
post = "v0.1.0"
|
||||
weight = 20
|
||||
|
||||
# Footer contents
|
||||
[extra.footer]
|
||||
info = 'Built with ❤️ by <a href="https://github.com/ayrat555">Ayrat Badykov</a> and <a href="https://github.com/pxp9">Pepe Márquez</a>'
|
43
docs/content/_index.md
Normal file
|
@ -0,0 +1,43 @@
|
|||
+++
|
||||
title = "FANG"
|
||||
|
||||
|
||||
# The homepage contents
|
||||
[extra]
|
||||
lead = '<b>Fang</b> is a background task processing for Rust. It uses Postgres DB as a task queue.'
|
||||
url = "/docs/getting-started/introduction/"
|
||||
url_button = "Get started"
|
||||
repo_version = "GitHub v0.9.0"
|
||||
repo_license = "Open-source MIT License."
|
||||
repo_url = "https://github.com/ayrat555/fang"
|
||||
|
||||
# Menu items
|
||||
[[extra.menu.main]]
|
||||
name = "Docs"
|
||||
section = "docs"
|
||||
url = "/docs/getting-started/introduction/"
|
||||
weight = 10
|
||||
|
||||
[[extra.menu.main]]
|
||||
name = "Blog"
|
||||
section = "blog"
|
||||
url = "/blog/"
|
||||
weight = 20
|
||||
|
||||
|
||||
[[extra.list]]
|
||||
title = "Async and threaded workers"
|
||||
content = "Workers can be started in threads (threaded workers) or tokio tasks (async workers)"
|
||||
|
||||
[[extra.list]]
|
||||
title = "Scheduled tasks"
|
||||
content = "Tasks can be scheduled at any time in the future"
|
||||
|
||||
[[extra.list]]
|
||||
title = "Periodic (CRON) tasks"
|
||||
content = "Tasks can be scheduled use cron schedules"
|
||||
|
||||
[[extra.list]]
|
||||
title = "Unique tasks"
|
||||
content = "Tasks are not duplicated in the queue if they are unique"
|
||||
+++
|
32
docs/deploy.sh
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
BRANCH="gh-pages"
|
||||
|
||||
build() {
|
||||
echo "Starting building..."
|
||||
|
||||
cd docs
|
||||
|
||||
sudo snap install --edge zola
|
||||
zola build
|
||||
mv public /tmp/public
|
||||
cd ..
|
||||
}
|
||||
|
||||
deploy() {
|
||||
echo "Starting deploying..."
|
||||
git config --global url."https://".insteadOf git://
|
||||
git config --global url."https://github.com/".insteadOf git@github.com:
|
||||
|
||||
git checkout ${BRANCH}
|
||||
cp -vr /tmp/public/* .
|
||||
git config user.name "GitHub Actions"
|
||||
git config user.email "github-actions-bot@users.noreply.github.com"
|
||||
rm -rf docs
|
||||
git add .
|
||||
git commit -m "Deploy new version docs"
|
||||
git push --force "https://${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" ${BRANCH}
|
||||
|
||||
echo "Deploy complete"
|
||||
}
|
2
docs/public/_headers
Normal file
|
@ -0,0 +1,2 @@
|
|||
/*
|
||||
Access-Control-Allow-Origin: *
|
BIN
docs/public/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
docs/public/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
docs/public/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 5 KiB |
6
docs/public/bootstrap/scss/bootstrap-grid.css
vendored
Normal file
7
docs/public/bootstrap/scss/bootstrap-reboot.css
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*!
|
||||
* Bootstrap Reboot v5.0.0-beta3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,*::before,*::after{box-sizing:border-box}@media (prefers-reduced-motion: no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h6,h5,h4,h3,h2,h1{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width: 1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width: 1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width: 1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width: 1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-bs-original-title]{text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr /* rtl:ignore */;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role="button"]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button:not(:disabled),[type="button"]:not(:disabled),[type="reset"]:not(:disabled),[type="submit"]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width: 1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type="search"]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important}
|
6
docs/public/bootstrap/scss/bootstrap-utilities.css
vendored
Normal file
6
docs/public/bootstrap/scss/bootstrap.css
vendored
Normal file
BIN
docs/public/doks.png
Normal file
After Width: | Height: | Size: 8 KiB |
1
docs/public/doks.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E1E8ED" d="M32.415 9.586l-9-9C23.054.225 22.553 0 22 0c-1.104 0-1.999.896-2 2 0 .552.224 1.053.586 1.415l-3.859 3.859 9 9 3.859-3.859c.362.361.862.585 1.414.585 1.104 0 2.001-.896 2-2 0-.552-.224-1.052-.585-1.414z"/><path fill="#CCD6DD" d="M22 0H7C4.791 0 3 1.791 3 4v28c0 2.209 1.791 4 4 4h22c2.209 0 4-1.791 4-4V11h-9c-1 0-2-1-2-2V0z"/><path fill="#99AAB5" d="M22 0h-2v9c0 2.209 1.791 4 4 4h9v-2h-9c-1 0-2-1-2-2V0zm-5 8c0 .552-.448 1-1 1H8c-.552 0-1-.448-1-1s.448-1 1-1h8c.552 0 1 .448 1 1zm0 4c0 .552-.448 1-1 1H8c-.552 0-1-.448-1-1s.448-1 1-1h8c.552 0 1 .448 1 1zm12 4c0 .552-.447 1-1 1H8c-.552 0-1-.448-1-1s.448-1 1-1h20c.553 0 1 .448 1 1zm0 4c0 .553-.447 1-1 1H8c-.552 0-1-.447-1-1 0-.553.448-1 1-1h20c.553 0 1 .447 1 1zm0 4c0 .553-.447 1-1 1H8c-.552 0-1-.447-1-1 0-.553.448-1 1-1h20c.553 0 1 .447 1 1zm0 4c0 .553-.447 1-1 1H8c-.552 0-1-.447-1-1 0-.553.448-1 1-1h20c.553 0 1 .447 1 1z"/></svg>
|
After Width: | Height: | Size: 972 B |
BIN
docs/public/favicon-16x16.png
Normal file
After Width: | Height: | Size: 416 B |
BIN
docs/public/favicon-32x32.png
Normal file
After Width: | Height: | Size: 773 B |
BIN
docs/public/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-500.woff
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-500.woff2
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-500italic.woff
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-500italic.woff2
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-700.woff
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-700.woff2
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-700italic.woff
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-700italic.woff2
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-italic.woff
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-italic.woff2
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-regular.woff
vendored
Normal file
BIN
docs/public/fonts/vendor/jost/jost-v4-latin-regular.woff2
vendored
Normal file
146
docs/public/index.js
Normal file
|
@ -0,0 +1,146 @@
|
|||
var suggestions = document.getElementById('suggestions');
|
||||
var userinput = document.getElementById('userinput');
|
||||
|
||||
document.addEventListener('keydown', inputFocus);
|
||||
|
||||
function inputFocus(e) {
|
||||
|
||||
if (e.keyCode === 191 ) {
|
||||
e.preventDefault();
|
||||
userinput.focus();
|
||||
}
|
||||
|
||||
if (e.keyCode === 27 ) {
|
||||
userinput.blur();
|
||||
suggestions.classList.add('d-none');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.addEventListener('click', function(event) {
|
||||
|
||||
var isClickInsideElement = suggestions.contains(event.target);
|
||||
|
||||
if (!isClickInsideElement) {
|
||||
suggestions.classList.add('d-none');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
Source:
|
||||
- https://dev.to/shubhamprakash/trap-focus-using-javascript-6a3
|
||||
*/
|
||||
|
||||
document.addEventListener('keydown',suggestionFocus);
|
||||
|
||||
function suggestionFocus(e){
|
||||
|
||||
const focusableSuggestions= suggestions.querySelectorAll('a');
|
||||
const focusable= [...focusableSuggestions];
|
||||
const index = focusable.indexOf(document.activeElement);
|
||||
|
||||
let nextIndex = 0;
|
||||
|
||||
if (e.keyCode === 38) {
|
||||
e.preventDefault();
|
||||
nextIndex= index > 0 ? index-1 : 0;
|
||||
focusableSuggestions[nextIndex].focus();
|
||||
}
|
||||
else if (e.keyCode === 40) {
|
||||
e.preventDefault();
|
||||
nextIndex= index+1 < focusable.length ? index+1 : index;
|
||||
focusableSuggestions[nextIndex].focus();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Source:
|
||||
- https://github.com/nextapps-de/flexsearch#index-documents-field-search
|
||||
- https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html
|
||||
*/
|
||||
|
||||
(function(){
|
||||
|
||||
var index = new FlexSearch({
|
||||
preset: 'score',
|
||||
cache: true,
|
||||
doc: {
|
||||
id: 'id',
|
||||
field: [
|
||||
'title',
|
||||
'description',
|
||||
'content',
|
||||
],
|
||||
store: [
|
||||
'href',
|
||||
'title',
|
||||
'description',
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
var docs = [
|
||||
{{ range $index, $page := (where .Site.Pages "Section" "docs") -}}
|
||||
{
|
||||
id: {{ $index }},
|
||||
href: "{{ .RelPermalink | relURL }}",
|
||||
title: {{ .Title | jsonify }},
|
||||
description: {{ .Params.description | jsonify }},
|
||||
content: {{ .Content | jsonify }}
|
||||
},
|
||||
{{ end -}}
|
||||
];
|
||||
|
||||
index.add(docs);
|
||||
|
||||
userinput.addEventListener('input', show_results, true);
|
||||
suggestions.addEventListener('click', accept_suggestion, true);
|
||||
|
||||
function show_results(){
|
||||
|
||||
var value = this.value;
|
||||
var results = index.search(value, 5);
|
||||
var entry, childs = suggestions.childNodes;
|
||||
var i = 0, len = results.length;
|
||||
|
||||
suggestions.classList.remove('d-none');
|
||||
|
||||
results.forEach(function(page) {
|
||||
|
||||
entry = document.createElement('div');
|
||||
|
||||
entry.innerHTML = '<a href><span></span><span></span></a>';
|
||||
|
||||
a = entry.querySelector('a'),
|
||||
t = entry.querySelector('span:first-child'),
|
||||
d = entry.querySelector('span:nth-child(2)');
|
||||
|
||||
a.href = page.href;
|
||||
t.textContent = page.title;
|
||||
d.textContent = page.description;
|
||||
|
||||
suggestions.appendChild(entry);
|
||||
|
||||
});
|
||||
|
||||
while(childs.length > len){
|
||||
|
||||
suggestions.removeChild(childs[i])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function accept_suggestion(){
|
||||
|
||||
while(suggestions.lastChild){
|
||||
|
||||
suggestions.removeChild(suggestions.lastChild);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}());
|
14
docs/public/js/main.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Set darkmode
|
||||
document.getElementById('mode').addEventListener('click', () => {
|
||||
|
||||
document.body.classList.toggle('dark');
|
||||
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
|
||||
|
||||
});
|
||||
|
||||
// enforce local storage setting but also fallback to user-agent preferences
|
||||
if (localStorage.getItem('theme') === 'dark' || (!localStorage.getItem('theme') && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
|
||||
|
||||
document.body.classList.add('dark');
|
||||
|
||||
}
|
317
docs/public/js/search.js
Normal file
|
@ -0,0 +1,317 @@
|
|||
var suggestions = document.getElementById('suggestions');
|
||||
var userinput = document.getElementById('userinput');
|
||||
|
||||
document.addEventListener('keydown', inputFocus);
|
||||
|
||||
function inputFocus(e) {
|
||||
|
||||
if (e.keyCode === 191
|
||||
&& document.activeElement.tagName !== "INPUT"
|
||||
&& document.activeElement.tagName !== "TEXTAREA") {
|
||||
e.preventDefault();
|
||||
userinput.focus();
|
||||
}
|
||||
|
||||
if (e.keyCode === 27 ) {
|
||||
userinput.blur();
|
||||
suggestions.classList.add('d-none');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
document.addEventListener('click', function(event) {
|
||||
|
||||
var isClickInsideElement = suggestions.contains(event.target);
|
||||
|
||||
if (!isClickInsideElement) {
|
||||
suggestions.classList.add('d-none');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
Source:
|
||||
- https://dev.to/shubhamprakash/trap-focus-using-javascript-6a3
|
||||
*/
|
||||
|
||||
document.addEventListener('keydown',suggestionFocus);
|
||||
|
||||
function suggestionFocus(e){
|
||||
const focusableSuggestions= suggestions.querySelectorAll('a');
|
||||
if (suggestions.classList.contains('d-none')
|
||||
|| focusableSuggestions.length === 0) {
|
||||
return;
|
||||
}
|
||||
const focusable= [...focusableSuggestions];
|
||||
const index = focusable.indexOf(document.activeElement);
|
||||
|
||||
let nextIndex = 0;
|
||||
|
||||
if (e.keyCode === 38) {
|
||||
e.preventDefault();
|
||||
nextIndex= index > 0 ? index-1 : 0;
|
||||
focusableSuggestions[nextIndex].focus();
|
||||
}
|
||||
else if (e.keyCode === 40) {
|
||||
e.preventDefault();
|
||||
nextIndex= index+1 < focusable.length ? index+1 : index;
|
||||
focusableSuggestions[nextIndex].focus();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Source:
|
||||
- https://github.com/nextapps-de/flexsearch#index-documents-field-search
|
||||
- https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html
|
||||
- http://elasticlunr.com/
|
||||
- https://github.com/getzola/zola/blob/master/docs/static/search.js
|
||||
*/
|
||||
(function(){
|
||||
var index = elasticlunr.Index.load(window.searchIndex);
|
||||
userinput.addEventListener('input', show_results, true);
|
||||
suggestions.addEventListener('click', accept_suggestion, true);
|
||||
|
||||
function show_results(){
|
||||
var value = this.value.trim();
|
||||
var options = {
|
||||
bool: "OR",
|
||||
fields: {
|
||||
title: {boost: 2},
|
||||
body: {boost: 1},
|
||||
}
|
||||
};
|
||||
var results = index.search(value, options);
|
||||
|
||||
var entry, childs = suggestions.childNodes;
|
||||
var i = 0, len = results.length;
|
||||
var items = value.split(/\s+/);
|
||||
suggestions.classList.remove('d-none');
|
||||
|
||||
results.forEach(function(page) {
|
||||
if (page.doc.body !== '') {
|
||||
entry = document.createElement('div');
|
||||
|
||||
entry.innerHTML = '<a href><span></span><span></span></a>';
|
||||
|
||||
a = entry.querySelector('a'),
|
||||
t = entry.querySelector('span:first-child'),
|
||||
d = entry.querySelector('span:nth-child(2)');
|
||||
a.href = page.ref;
|
||||
t.textContent = page.doc.title;
|
||||
d.innerHTML = makeTeaser(page.doc.body, items);
|
||||
|
||||
suggestions.appendChild(entry);
|
||||
}
|
||||
});
|
||||
|
||||
while(childs.length > len){
|
||||
suggestions.removeChild(childs[i])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function accept_suggestion(){
|
||||
|
||||
while(suggestions.lastChild){
|
||||
|
||||
suggestions.removeChild(suggestions.lastChild);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Taken from mdbook
|
||||
// The strategy is as follows:
|
||||
// First, assign a value to each word in the document:
|
||||
// Words that correspond to search terms (stemmer aware): 40
|
||||
// Normal words: 2
|
||||
// First word in a sentence: 8
|
||||
// Then use a sliding window with a constant number of words and count the
|
||||
// sum of the values of the words within the window. Then use the window that got the
|
||||
// maximum sum. If there are multiple maximas, then get the last one.
|
||||
// Enclose the terms in <b>.
|
||||
function makeTeaser(body, terms) {
|
||||
var TERM_WEIGHT = 40;
|
||||
var NORMAL_WORD_WEIGHT = 2;
|
||||
var FIRST_WORD_WEIGHT = 8;
|
||||
var TEASER_MAX_WORDS = 30;
|
||||
|
||||
var stemmedTerms = terms.map(function (w) {
|
||||
return elasticlunr.stemmer(w.toLowerCase());
|
||||
});
|
||||
var termFound = false;
|
||||
var index = 0;
|
||||
var weighted = []; // contains elements of ["word", weight, index_in_document]
|
||||
|
||||
// split in sentences, then words
|
||||
var sentences = body.toLowerCase().split(". ");
|
||||
for (var i in sentences) {
|
||||
var words = sentences[i].split(/[\s\n]/);
|
||||
var value = FIRST_WORD_WEIGHT;
|
||||
for (var j in words) {
|
||||
|
||||
var word = words[j];
|
||||
|
||||
if (word.length > 0) {
|
||||
for (var k in stemmedTerms) {
|
||||
if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {
|
||||
value = TERM_WEIGHT;
|
||||
termFound = true;
|
||||
}
|
||||
}
|
||||
weighted.push([word, value, index]);
|
||||
value = NORMAL_WORD_WEIGHT;
|
||||
}
|
||||
|
||||
index += word.length;
|
||||
index += 1; // ' ' or '.' if last word in sentence
|
||||
}
|
||||
|
||||
index += 1; // because we split at a two-char boundary '. '
|
||||
}
|
||||
|
||||
if (weighted.length === 0) {
|
||||
if (body.length !== undefined && body.length > TEASER_MAX_WORDS * 10) {
|
||||
return body.substring(0, TEASER_MAX_WORDS * 10) + '...';
|
||||
} else {
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
var windowWeights = [];
|
||||
var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);
|
||||
// We add a window with all the weights first
|
||||
var curSum = 0;
|
||||
for (var i = 0; i < windowSize; i++) {
|
||||
curSum += weighted[i][1];
|
||||
}
|
||||
windowWeights.push(curSum);
|
||||
|
||||
for (var i = 0; i < weighted.length - windowSize; i++) {
|
||||
curSum -= weighted[i][1];
|
||||
curSum += weighted[i + windowSize][1];
|
||||
windowWeights.push(curSum);
|
||||
}
|
||||
|
||||
// If we didn't find the term, just pick the first window
|
||||
var maxSumIndex = 0;
|
||||
if (termFound) {
|
||||
var maxFound = 0;
|
||||
// backwards
|
||||
for (var i = windowWeights.length - 1; i >= 0; i--) {
|
||||
if (windowWeights[i] > maxFound) {
|
||||
maxFound = windowWeights[i];
|
||||
maxSumIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var teaser = [];
|
||||
var startIndex = weighted[maxSumIndex][2];
|
||||
for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) {
|
||||
var word = weighted[i];
|
||||
if (startIndex < word[2]) {
|
||||
// missing text from index to start of `word`
|
||||
teaser.push(body.substring(startIndex, word[2]));
|
||||
startIndex = word[2];
|
||||
}
|
||||
|
||||
// add <em/> around search terms
|
||||
if (word[1] === TERM_WEIGHT) {
|
||||
teaser.push("<b>");
|
||||
}
|
||||
|
||||
startIndex = word[2] + word[0].length;
|
||||
// Check the string is ascii characters or not
|
||||
var re = /^[\x00-\xff]+$/
|
||||
if (word[1] !== TERM_WEIGHT && word[0].length >= 12 && !re.test(word[0])) {
|
||||
// If the string's length is too long, it maybe a Chinese/Japance/Korean article
|
||||
// if using substring method directly, it may occur error codes on emoji chars
|
||||
var strBefor = body.substring(word[2], startIndex);
|
||||
var strAfter = substringByByte(strBefor, 12);
|
||||
teaser.push(strAfter);
|
||||
} else {
|
||||
teaser.push(body.substring(word[2], startIndex));
|
||||
}
|
||||
|
||||
if (word[1] === TERM_WEIGHT) {
|
||||
teaser.push("</b>");
|
||||
}
|
||||
}
|
||||
teaser.push("…");
|
||||
return teaser.join("");
|
||||
}
|
||||
}());
|
||||
|
||||
|
||||
// Get substring by bytes
|
||||
// If using JavaScript inline substring method, it will return error codes
|
||||
// Source: https://www.52pojie.cn/thread-1059814-1-1.html
|
||||
function substringByByte(str, maxLength) {
|
||||
var result = "";
|
||||
var flag = false;
|
||||
var len = 0;
|
||||
var length = 0;
|
||||
var length2 = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var code = str.codePointAt(i).toString(16);
|
||||
if (code.length > 4) {
|
||||
i++;
|
||||
if ((i + 1) < str.length) {
|
||||
flag = str.codePointAt(i + 1).toString(16) == "200d";
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
len += getByteByHex(code);
|
||||
if (i == str.length - 1) {
|
||||
length += len;
|
||||
if (length <= maxLength) {
|
||||
result += str.substr(length2, i - length2 + 1);
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (len != 0) {
|
||||
length += len;
|
||||
length += getByteByHex(code);
|
||||
if (length <= maxLength) {
|
||||
result += str.substr(length2, i - length2 + 1);
|
||||
length2 = i + 1;
|
||||
} else {
|
||||
break
|
||||
}
|
||||
len = 0;
|
||||
continue;
|
||||
}
|
||||
length += getByteByHex(code);
|
||||
if (length <= maxLength) {
|
||||
if (code.length <= 4) {
|
||||
result += str[i]
|
||||
} else {
|
||||
result += str[i - 1] + str[i]
|
||||
}
|
||||
length2 = i + 1;
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get the string bytes from binary
|
||||
function getByteByBinary(binaryCode) {
|
||||
// Binary system, starts with `0b` in ES6
|
||||
// Octal number system, starts with `0` in ES5 and starts with `0o` in ES6
|
||||
// Hexadecimal, starts with `0x` in both ES5 and ES6
|
||||
var byteLengthDatas = [0, 1, 2, 3, 4];
|
||||
var len = byteLengthDatas[Math.ceil(binaryCode.length / 8)];
|
||||
return len;
|
||||
}
|
||||
|
||||
// Get the string bytes from hexadecimal
|
||||
function getByteByHex(hexCode) {
|
||||
return getByteByBinary(parseInt(hexCode, 16).toString(2));
|
||||
}
|
BIN
docs/public/logo-doks.png
Normal file
After Width: | Height: | Size: 20 KiB |
6
docs/public/main.css
Normal file
10
docs/public/plugins/elasticlunr.min.js
vendored
Normal file
1
docs/public/site.webmanifest
Normal file
|
@ -0,0 +1 @@
|
|||
{"name":"Zola Theme AdiDoks","short_name":"AdiDoks","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#fff","background_color":"#fff","display":"standalone"}
|
1
docs/themes/adidoks
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 5c698271c460046034605b743a15196b12e32887
|