refactor: replace gulp by webpack and npm scripts (#258)

BREAKING CHANGE: We have replaced `gulp` with `webpack` and `npm scripts` to build this theme. If you build it on your own or use build commands during the deployment, you may have to adjust your setup.

BREAKING CHANGE: The `GeekblogIcons` font is using the icon name as Unicode now. As a consequence, you have to replace all references to Icons from this font if you have customized the theme.

BREAKING CHANGE: We have refactored the search integration to split Hugo templates from JavaScript code. To get it working again, you need to adjust the `outputFormats` and `outputs` in your Hugo configuration file, as [documented](https://geekdocs.de/usage/configuration/#site-configuration).
uci-hugo-doc
Robert Kaussow 2022-01-06 13:58:10 +01:00 committed by GitHub
parent 2ac2a9faab
commit 5c5e2d59cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
122 changed files with 18705 additions and 5208 deletions

View File

@ -7,11 +7,20 @@ platform:
arch: amd64
steps:
- name: eslint
image: node:lts
commands:
- npm install > /dev/null
- npm run lint
environment:
FORCE_COLOR: true
NPM_CONFIG_LOGLEVEL: error
- name: assets
image: node:lts
commands:
- npm install > /dev/null
- npx gulp default
- npm run build
environment:
FORCE_COLOR: true
NPM_CONFIG_LOGLEVEL: error
@ -94,7 +103,7 @@ steps:
image: node:lts
commands:
- npm install > /dev/null
- npx gulp default
- npm run build
environment:
FORCE_COLOR: true
NPM_CONFIG_LOGLEVEL: error
@ -172,7 +181,7 @@ steps:
image: node:lts
commands:
- npm install > /dev/null
- npx gulp svg-sprite-list
- npm run svg-sprite-list
- mkdir -p exampleSite/themes/hugo-geekdoc/
- curl -sSL https://github.com/thegeeklab/hugo-geekdoc/releases/latest/download/hugo-geekdoc.tar.gz | tar -xz -C exampleSite/themes/hugo-geekdoc/ --strip-components=1
when:
@ -184,8 +193,8 @@ steps:
image: node:lts
commands:
- npm install > /dev/null
- npx gulp default
- npx gulp svg-sprite-list
- npm run build
- npm run svg-sprite-list
- mkdir exampleSite/themes/ && ln -s $(pwd)/ exampleSite/themes/hugo-geekdoc
environment:
FORCE_COLOR: true
@ -276,6 +285,6 @@ depends_on:
---
kind: signature
hmac: a61d16aa7a47108fbef3836588111f16f52d280497cfe0aab14bcd726728b297
hmac: e715545ce951b15ce1ab5f7d7f107e2ab37aa08e94a681f27646a543d1e6ac3c
...

22
.eslintrc.json Normal file
View File

@ -0,0 +1,22 @@
{
"env": {
"browser": true,
"es6": true,
"amd": true
},
"extends": ["plugin:prettier/recommended"],
"parser": "@babel/eslint-parser",
"parserOptions": {
"sourceType": "module",
"requireConfigFile": false,
"allowImportExportEverywhere": true
},
"plugins": ["prettier"],
"rules": {
"require-await": "warn"
},
"globals": {
"require": false,
"requirejs": false
}
}

29
.gitignore vendored
View File

@ -1,26 +1,21 @@
# local environments
.swp
.env*
dist/
build/
node_modules/
lhci_reports/
exampleSite/themes/
exampleSite/public/
/dist/
/build/
/node_modules/
/lhci_reports/
/exampleSite/themes/
/exampleSite/public/
CHANGELOG.md
# auto-generated files
assets/sprites/
static/*.min.css
static/*.min.css.map
static/js/
static/favicon/
static/fonts/GeekdocIcons.*
static/fonts/KaTeX_*
resources/
exampleSite/resources/
exampleSite/data/sprites/
data/assets.json
/data/
/static/
/assets/sprites/
/resources/
/exampleSite/resources/
/exampleSite/data/sprites/
# testing
.lighthouseci/

View File

@ -2,6 +2,7 @@
ci:
collect:
numberOfRuns: 3
psiStrategy: desktop
staticDistDir: exampleSite/public
url:
- http://localhost/

View File

@ -1,9 +1,8 @@
*.html
.drone.yml
search*.js
_normalize.css
.lighthouseci/
themes/
static/js/
src/favicon/
list.json.json
/.lighthouseci/
/themes/
/static/js/
/src/favicon/
LICENSE

View File

@ -1,4 +1,8 @@
{
"printWidth": 99,
"singleQuote": false,
"semi": false,
"trailingComma": "none",
"overrides": [
{
"files": ["*.html"],

View File

@ -8,10 +8,11 @@
.markdownlint*
.jsbeautify*
.prettier*
.vnu*
.eslintrc*
.chglog
example*
gulp*
webpack*
svgsprite*
package*
node*
local*

View File

@ -1,171 +0,0 @@
'use strict';
{{ $searchDataFile := printf "%s.search-data.json" .Language.Lang }}
{{ $searchData := resources.Get "search-data.json" | resources.ExecuteAsTemplate $searchDataFile . | resources.Minify }}
(function() {
const input = document.querySelector('#gdoc-search-input');
const results = document.querySelector('#gdoc-search-results');
let showParent = {{ if .Site.Params.GeekdocSearchShowParent }}true{{ else }}false{{ end }}
if (input) {
input.addEventListener('focus', init);
input.addEventListener('keyup', search);
}
function init() {
input.removeEventListener('focus', init); // init once
loadScript('{{ index .Site.Data.assets "js/groupBy.min.js" | relURL }}');
loadScript('{{ index .Site.Data.assets "js/flexsearch.min.js" | relURL }}', function() {
const indexCfgDefaults = {
tokenize: 'forward'
}
const indexCfg = {{ with .Scratch.Get "geekdocSearchConfig" }}{{ . | jsonify }}{{ else }}indexCfgDefaults{{ end }};
const dataUrl = '{{ $searchData.RelPermalink }}'
indexCfg.document = {
key: 'id',
index: ['title', 'content'],
store: ['title', 'href', 'parent'],
};
const index = new FlexSearch.Document(indexCfg);
window.geekdocSearchIndex = index;
getJson(dataUrl, function(data) {
data.forEach(obj => {
window.geekdocSearchIndex.add(obj);
});
});
});
}
function search() {
const searchCfg = {
enrich: true,
limit: 10
};
while (results.firstChild) {
results.removeChild(results.firstChild);
}
if (!input.value) {
return results.classList.remove('has-hits');
}
let searchHits = flattenHits(window.geekdocSearchIndex.search(input.value, searchCfg));
if (searchHits.length < 1) {
return results.classList.remove('has-hits');
}
results.classList.add('has-hits');
if (showParent === true) {
searchHits = groupBy(searchHits, hit => hit.parent);
}
const items = [];
if (showParent === true) {
for (const section in searchHits) {
const item = document.createElement('li'),
title = item.appendChild(document.createElement('span')),
subList = item.appendChild(document.createElement('ul'));
title.textContent = section;
createLinks(searchHits[section], subList);
items.push(item);
}
} else {
const item = document.createElement('li'),
title = item.appendChild(document.createElement('span')),
subList = item.appendChild(document.createElement('ul'));
title.textContent = 'Results';
createLinks(searchHits, subList);
items.push(item);
}
items.forEach(item => {
results.appendChild(item);
})
}
/**
* Creates links to given fields and either returns them in an array or attaches them to a target element
* @param {Object} fields Page to which the link should point to
* @param {HTMLElement} target Element to which the links should be attatched
* @returns {Array} If target is not specified, returns an array of built links
*/
function createLinks(pages, target) {
const items = [];
for (const page of pages) {
const item = document.createElement("li"),
entry = item.appendChild(document.createElement("span")),
a = entry.appendChild(document.createElement("a"));
entry.classList.add('flex')
a.href = page.href;
a.textContent = page.title;
a.classList.add('gdoc-search__entry')
if (target) {
target.appendChild(item);
continue
}
items.push(item);
}
return items;
}
function fetchErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
function getJson(src, callback) {
fetch(src)
.then(fetchErrors)
.then(response => response.json())
.then(json => callback(json))
.catch(function(error) {
console.log(error);
});
}
function flattenHits(results) {
const items = [];
const map = new Map();
for (const field of results) {
for (const page of field.result) {
if(!map.has(page.doc.href)){
map.set(page.doc.href, true);
items.push(page.doc);
}
}
}
return items
}
function loadScript(src, callback) {
let script = document.createElement('script');
script.defer = true;
script.async = false;
script.src = src;
script.onload = callback;
document.body.appendChild(script);
}
})();

View File

@ -1,3 +0,0 @@
{
"custom.css": "custom.css"
}

View File

@ -23,9 +23,22 @@ markup:
taxonomies:
tag: tags
outputFormats:
Search:
name: "Search"
mediaType: "application/json"
# generated file: <baseName>.<mediaType."application/feed+json".suffixes[0]> = feed.json
baseName: "searchconfig"
isPlainText: false
rel: "alternate"
isHTML: false
noUgly: true
permalinkable: false
outputs:
home:
- HTML
- SEARCH
page:
- HTML
section:

View File

@ -4,10 +4,12 @@ title: Buttons
Buttons are styled links that can lead to local page or external link.
<!-- prettier-ignore-start -->
```tpl
{{</* button relref="/" [class="...", size="large|regular"] */>}}Get Home{{</* /button */>}}
{{</* button href="https://github.com/thegeeklab/hugo-geekdoc" */>}}Contribute{{</* /button */>}}
```
<!-- prettier-ignore-end -->
## Example

View File

@ -8,12 +8,14 @@ Expand shortcode can help to decrease clutter on screen by hiding part of text.
### Default
<!-- prettier-ignore-start -->
```tpl
{{</* expand */>}}
## Markdown content
Dolor sit, sumo unique ...
{{</* /expand */>}}
```
<!-- prettier-ignore-end -->
{{< expand >}}
@ -24,12 +26,14 @@ Dolor sit, sumo unique argument um no. Gracie nominal id xiv. Romanesque acclima
### With Custom Label
<!-- prettier-ignore-start -->
```tpl
{{</* expand "Custom Label" "..." */>}}
## Markdown content
Dolor sit, sumo unique ...
{{</* /expand */>}}
```
<!-- prettier-ignore-end -->
{{< expand "Custom Label" "..." >}}

View File

@ -5,6 +5,7 @@ title: Hints
Hint shortcode can be used as hint/alerts/notification block.
There are four colors to choose: `info`, `ok`, `warning` and `danger`.
<!-- prettier-ignore-start -->
```tpl
{{</* hint [info|warning|danger] */>}}
**Markdown content**\
@ -12,6 +13,7 @@ Dolor sit, sumo unique argument um no. Gracie nominal id xiv. Romanesque acclima
Ornateness bland it ex enc, est yeti am bongo detract re.
{{</* /hint */>}}
```
<!-- prettier-ignore-end -->
## Example

View File

@ -4,9 +4,11 @@ title: Icons
Simple shortcode to include icons from SVG sprites outside of menus.
<!-- prettier-ignore-start -->
```tpl
{{</* icon "thumbs-up" */>}}
```
<!-- prettier-ignore-end -->
**Example:**

View File

@ -6,9 +6,11 @@ title: Includes
Include shortcode can include files of different types. By specifying a language, the included file will have syntax highlighting.
<!-- prettier-ignore-start -->
```tpl
{{</* include file="relative/path/from/hugo/root" language="go" markdown=[false|true] */>}}
```
<!-- prettier-ignore-end -->
Attributes:
@ -30,9 +32,11 @@ If no other options are specified, files will be rendered as Markdown using the
If you include markdown files that should not get a menu entry, place them outside the content folder or exclude them otherwise.
{{< /hint >}}
<!-- prettier-ignore-start -->
```tpl
{{</* include file="/static/_includes/example.md.part" */>}}
```
<!-- prettier-ignore-end -->
<!-- prettier-ignore-start -->
<!-- spellchecker-disable -->
@ -44,9 +48,13 @@ If you include markdown files that should not get a menu entry, place them outsi
This method can be used to include source code files and keep them automatically up to date.
<!-- prettier-ignore-start -->
```tpl
{{</* include file="config.yaml" language="yaml" options="linenos=table,hl_lines=5-6,linenostart=100" */>}}
```
<!-- prettier-ignore-end -->
Result:
<!-- prettier-ignore-start -->
<!-- spellchecker-disable -->
@ -60,9 +68,11 @@ This method can be used to include source code files and keep them automatically
HTML content will be filtered by the `safeHTML` filter and added to the rendered page output.
<!-- prettier-ignore-start -->
```tpl
{{</* include file="/static/_includes/example.html.part" */>}}
```
<!-- prettier-ignore-end -->
{{< include file="/static/_includes/example.html.part" type="html" >}}

View File

@ -4,6 +4,7 @@ title: Tabs
Tabs let you organize content by context, for example installation instructions for each supported platform.
<!-- prettier-ignore-start -->
```tpl
{{</* tabs "uniqueid" */>}}
{{</* tab "macOS" */>}} # macOS Content {{</* /tab */>}}
@ -11,6 +12,7 @@ Tabs let you organize content by context, for example installation instructions
{{</* tab "Windows" */>}} # Windows Content {{</* /tab */>}}
{{</* /tabs */>}}
```
<!-- prettier-ignore-end -->
## Example

View File

@ -4,9 +4,11 @@ title: ToC-Tree
The `toc-tree` shortcode will generate a Table of Content from a section file tree of your content directory. The root of the resulting ToC will be the page on which you define the shortcode.
<!-- prettier-ignore-start -->
```tpl
{{</* toc-tree */>}}
```
<!-- prettier-ignore-end -->
## Example

View File

@ -4,9 +4,11 @@ title: ToC
Simple wrapper to generate a page Table of Content from a shortcode.
<!-- prettier-ignore-start -->
```tpl
{{</* toc */>}}
```
<!-- prettier-ignore-end -->
{{< toc >}}

View File

@ -32,6 +32,19 @@ enableRobotsTXT = true
startLevel = 1
endLevel = 9
[outputFormats.Search]
name = "Search"
mediaType = "application/json"
baseName = "searchconfig"
isPlainText = false
rel = "alternate"
isHTML = false
noUgly = true
permalinkable = false
[outputs]
home = [ "HTML", "SEARCH" ]
[taxonomies]
tag = "tags"
@ -70,7 +83,8 @@ enableRobotsTXT = true
# You can also specify this parameter per page in front matter.
geekdocEditPath = "edit/main/exampleSite/content"
# (Optional, default true) Enables search function with flexsearch.
# (Optional, default true) Enables search function with flexsearch. To use the search you
# have to ensure `outputFormats` and `outputs` are properly configured as well (see below).
# Index is built on the fly and might slow down your website.
geekdocSearch = false
@ -148,6 +162,23 @@ markup:
taxonomies:
tag: tags
outputFormats:
Search:
name: "Search"
mediaType: "application/json"
# generated file: <baseName>.<mediaType."application/feed+json".suffixes[0]> = feed.json
baseName: "searchconfig"
isPlainText: false
rel: "alternate"
isHTML: false
noUgly: true
permalinkable: false
outputs:
home:
- HTML
- SEARCH
params:
# (Optional, default 6) Set how many table of contents levels to be showed on page.
# Use false to hide ToC, note that 0 will default to 6 (https://gohugo.io/functions/default/)
@ -183,8 +214,9 @@ params:
# You can also specify this parameter per page in front matter.
geekdocEditPath: edit/main/exampleSite/content
# (Optional, default true) Enables search function with flexsearch.
# Index is built on the fly and might slowdown your website.
# (Optional, default true) Enables search function with flexsearch. To use the search you
# have to ensure `outputFormats` and `outputs` are properly configured as well (see below).
# Index is built on the fly and might slow down your website.
geekdocSearch: false
# (Optional, default false) Display search results with the parent folder as prefix. This

View File

@ -69,6 +69,19 @@ To prepare your new site environment just a few steps are required:
[taxonomies]
tag = "tags"
[outputFormats.Search]
name = "Search"
mediaType = "application/json"
baseName = "searchconfig"
isPlainText = false
rel = "alternate"
isHTML = false
noUgly = true
permalinkable = false
[outputs]
home = [ "HTML", "SEARCH" ]
```
5. Test your site.

View File

@ -1,11 +1,11 @@
<div class="flex flex-wrap justify-center">
{{ range .Site.Data.sprites.geekdoc }}
{{ range $key, $value := .Site.Data.sprites.geekdoc }}
<div class="flex flex-grid icon-grid">
<div class="flex align-center justify-center icon-grid__line">
<svg class="icon gdoc_{{ . }}"><use xlink:href="#gdoc_{{ . }}"></use></svg>
<svg class="icon {{ $key }}"><use xlink:href="#{{ $key }}"></use></svg>
</div>
<div class="flex align-center justify-center icon-grid__line icon-grid__line--text">
<span>#gdoc_{{ (replace . "_" "_<wbr>") | safeHTML }}</span>
<span>#{{ (replace $key "_" "_<wbr>") | safeHTML }}</span>
</div>
</div>
{{ end }}

View File

@ -1,344 +0,0 @@
const devBuild = !(
(process.env.NODE_ENV || "prod").trim().toLowerCase() === "prod"
);
const gulp = require("gulp");
const rename = require("gulp-rename");
const { sass } = require("@mr-hope/gulp-sass");
const cleanCSS = require("gulp-clean-css");
const autoprefixer = require("gulp-autoprefixer");
const iconfont = require("gulp-iconfont");
const filelist = require("gulp-filelist");
const uglify = require("gulp-uglify");
const sourcemaps = require("gulp-sourcemaps");
const realFavicon = require("gulp-real-favicon");
const svgSprite = require("gulp-svg-sprite");
const rev = require("gulp-rev");
const replace = require("gulp-replace");
const path = require("path");
const fs = require("fs");
const del = require("del");
const through = require("through2");
var BUILD = "build";
var CSS_BUILD = BUILD + "/assets";
var JS_BUILD = BUILD + "/assets/js";
var FONTS = "static/fonts";
var FAVICON_DATA_FILE = BUILD + "/faviconData.json";
var TIMESTAMP = Math.round(Date.now() / 1000);
function noop() {
return through.obj();
}
gulp.task("sass", function () {
return gulp
.src("src/sass/{main,print,mobile}.scss")
.pipe(devBuild ? sourcemaps.init() : noop())
.pipe(sass().on("error", sass.logError))
.pipe(cleanCSS({ format: "beautify" }))
.pipe(
autoprefixer({
cascade: false,
})
)
.pipe(gulp.dest(CSS_BUILD))
.pipe(cleanCSS())
.pipe(rename({ extname: ".min.css" }))
.pipe(devBuild ? sourcemaps.write(".") : noop())
.pipe(gulp.dest(CSS_BUILD));
});
gulp.task("favicon-svg", function () {
return gulp
.src("src/favicon/favicon-master.svg")
.pipe(rename("favicon.svg"))
.pipe(gulp.dest("static/favicon/"));
});
gulp.task("favicon-generate", function (done) {
realFavicon.generateFavicon(
{
masterPicture: "src/favicon/favicon-master.svg",
dest: "static/favicon",
iconsPath: "/favicon",
design: {
ios: {
pictureAspect: "backgroundAndMargin",
backgroundColor: "#2f333e",
margin: "14%",
assets: {
ios6AndPriorIcons: false,
ios7AndLaterIcons: false,
precomposedIcons: false,
declareOnlyDefaultIcon: true,
},
},
desktopBrowser: {},
windows: {
pictureAspect: "whiteSilhouette",
backgroundColor: "#2f333e",
onConflict: "override",
assets: {
windows80Ie10Tile: false,
windows10Ie11EdgeTiles: {
small: false,
medium: true,
big: false,
rectangle: false,
},
},
},
androidChrome: {
pictureAspect: "shadow",
themeColor: "#2f333e",
manifest: {
display: "standalone",
orientation: "notSet",
onConflict: "override",
declared: true,
},
assets: {
legacyIcon: false,
lowResolutionIcons: false,
},
},
safariPinnedTab: {
pictureAspect: "silhouette",
themeColor: "#2f333e",
},
},
settings: {
scalingAlgorithm: "Mitchell",
errorOnImageTooSmall: false,
readmeFile: false,
htmlCodeFile: false,
usePathAsIs: false,
},
markupFile: FAVICON_DATA_FILE,
},
function () {
done();
}
);
});
gulp.task("favicon-check-update", function (done) {
var currentVersion = JSON.parse(fs.readFileSync(FAVICON_DATA_FILE)).version;
realFavicon.checkForUpdates(currentVersion, function (err) {
if (err) {
throw err;
}
});
done();
});
gulp.task("svg-sprite", function () {
config = {
shape: {
id: {
generator: "gdoc_%s",
},
dimension: {
maxWidth: 28,
maxHeight: 28,
attributes: false,
},
spacing: {
padding: 2,
box: "content",
},
dest: BUILD + "/intermediate-svg",
},
svg: {
xmlDeclaration: false,
rootAttributes: {
class: "svg-sprite",
},
},
mode: {
inline: true,
symbol: {
dest: "assets/sprites/",
sprite: "geekdoc.svg",
bust: false,
},
},
};
return gulp
.src("src/icons/*.svg")
.pipe(svgSprite(config))
.pipe(gulp.dest("."));
});
gulp.task("svg-sprite-list", function () {
config = { removeExtensions: true, flatten: true };
return gulp
.src("src/icons/*.svg")
.pipe(filelist("exampleSite/data/sprites/geekdoc.json", config))
.pipe(gulp.dest("."));
});
gulp.task("iconfont", function () {
var lastUnicode = 0xea01;
var files = fs.readdirSync("src/iconfont");
// Filter files with containing unicode value and set last unicode
files.forEach(function (file) {
var basename = path.basename(file);
var matches = basename.match(/^(?:((?:u[0-9a-f]{4,6},?)+)\-)?(.+)\.svg$/i);
var currentCode = -1;
if (matches && matches[1]) {
currentCode = parseInt(matches[1].split("u")[1], 16);
}
if (currentCode >= lastUnicode) {
lastUnicode = ++currentCode;
}
});
return gulp
.src(["src/iconfont/*.svg"])
.pipe(
iconfont({
startUnicode: lastUnicode,
fontName: "GeekdocIcons",
prependUnicode: true,
normalize: true,
fontHeight: 1001,
centerHorizontally: true,
formats: ["woff", "woff2"],
timestamp: TIMESTAMP,
})
)
.pipe(gulp.dest(FONTS));
});
gulp.task("js", function () {
return gulp
.src(["src/js/*.js"])
.pipe(devBuild ? sourcemaps.init() : noop())
.pipe(uglify())
.pipe(rename({ extname: ".min.js" }))
.pipe(devBuild ? sourcemaps.write(".") : noop())
.pipe(gulp.dest(JS_BUILD));
});
gulp.task("asset-sync-js", function () {
return gulp
.src([
"node_modules/clipboard/dist/clipboard.min.js",
"node_modules/flexsearch/dist/flexsearch.compact.js",
"node_modules/mermaid/dist/mermaid.min.js",
"node_modules/katex/dist/katex.min.js",
"node_modules/katex/dist/contrib/auto-render.min.js",
])
.pipe(replace(/\/\/# sourceMappingURL=.+$/, ""))
.pipe(
rename(function (path) {
path.basename = path.basename.replace(/compact/, "min");
})
)
.pipe(gulp.dest(JS_BUILD));
});
gulp.task("asset-sync-css", function () {
return gulp
.src(["node_modules/katex/dist/katex.min.css"])
.pipe(replace(/\/\/# sourceMappingURL=.+$/, ""))
.pipe(
rename(function (path) {
path.basename = path.basename.replace(/compact/, "min");
})
)
.pipe(gulp.dest(CSS_BUILD));
});
gulp.task("asset-sync-font", function () {
return gulp
.src(["node_modules/katex/dist/fonts/KaTeX_*"])
.pipe(gulp.dest(FONTS));
});
gulp.task("asset-rev", function () {
return gulp
.src(
[
CSS_BUILD + "/*.min.css",
JS_BUILD + "/*.min.js",
JS_BUILD + "/*.compact.js",
],
{
base: BUILD + "/assets",
}
)
.pipe(rev())
.pipe(gulp.dest("static"))
.pipe(
rev.manifest("data/assets-static.json", {
base: "data",
merge: true,
})
)
.pipe(rename("assets.json"))
.pipe(gulp.dest("data"));
});
gulp.task("asset-map", function () {
return gulp
.src([CSS_BUILD + "/*.min.css.map", JS_BUILD + "/*.min.js.map"], {
base: BUILD + "/assets",
})
.pipe(gulp.dest("static"));
});
gulp.task("clean", function () {
return del([
BUILD,
"assets/sprites/",
"static/js/",
"static/favicon/",
"static/*.min.css",
"static/*.css.map",
"data/assets.json",
"resources",
]);
});
/* Task series */
gulp.task(
"asset",
gulp.series("asset-sync-font", "asset-sync-css", "asset-sync-js", "asset-rev")
);
gulp.task("favicon", gulp.series("favicon-svg", "favicon-generate"));
gulp.task("svg", gulp.series("svg-sprite"));
gulp.task(
"default",
gulp.series([
devBuild ? [] : "clean",
"sass",
"js",
"asset",
devBuild ? "asset-map" : [],
"svg",
"iconfont",
"favicon",
])
);
gulp.task("watch", function () {
gulp.series("default")();
gulp.watch(
"src/sass/**/*.*css",
gulp.series("sass", "asset-rev", "asset-map")
);
gulp.watch("src/js/*.js", gulp.series("js", "asset-rev", "asset-map"));
});

View File

@ -1,21 +1,22 @@
<!DOCTYPE html>
<html lang="{{ .Site.Language.Lang }}">
<head>
<head>
{{ partial "head/meta" . }}
<title>Lost? Don't worry</title>
{{ partial "head/favicons" . }}
{{ partial "head/others" . }}
</head>
</head>
<body>
<body>
{{ partial "svg-icon-symbols" . }}
<div class="wrapper">
<input type="checkbox" class="hidden" id="menu-header-control" />
{{ partial "site-header" (dict "Root" . "MenuEnabled" false) }}
<main class="gdoc-error flex-even">
<div class="flex align-center justify-center">
<div class="gdoc-error__icon">
@ -25,8 +26,8 @@
<div class="gdoc-error__line gdoc-error__title">Lost?</div>
<div class="gdoc-error__line gdoc-error__code">Error 404</div>
<div class="gdoc-error__line gdoc-error__help">
Seems like what you are looking for can't be found. Don't worry we can
bring you back to the <a class="gdoc-error__link" href="{{ .Site.BaseURL }}">homepage</a>.
Seems like what you are looking for can't be found. Don't worry we can bring you back
to the <a class="gdoc-error__link" href="{{ .Site.BaseURL }}">homepage</a>.
</div>
</div>
</div>
@ -35,6 +36,5 @@
{{ partial "site-footer" . }}
</div>
</body>
</body>
</html>

View File

@ -1,5 +1,7 @@
{{- $showAnchor := (and (default true .Page.Params.GeekdocAnchor) (default true .Page.Site.Params.GeekdocAnchor)) -}}
<!-- prettier-ignore-start -->
{{- if $showAnchor -}}
<div class="gdoc-page__anchorwrap">
<h{{ .Level }} id="{{ .Anchor | safeURL }}">
@ -16,3 +18,4 @@
</h{{ .Level }}>
</div>
{{- end -}}
<!-- prettier-ignore-end -->

View File

@ -1,2 +1,6 @@
<img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" {{ with .Title}} title="{{ . }}"{{ end }} />
<img
src="{{ .Destination | safeURL }}"
alt="{{ .Text }}"
{{ with .Title }}title="{{ . }}"{{ end }}
/>
{{- /* Drop trailing newlines */ -}}

View File

@ -1,3 +1,8 @@
{{- $raw := or (hasPrefix .Text "<img") (hasPrefix .Text "<figure") -}}
<a class="gdoc-markdown__link{{ if $raw }}--raw{{ end }}" href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}>{{ .Text | safeHTML }}</a>
<a
class="gdoc-markdown__link{{ if $raw }}--raw{{ end }}"
href="{{ .Destination | safeURL }}"
{{ with .Title }}title="{{ . }}"{{ end }}
>{{ .Text | safeHTML }}</a
>
{{- /* Drop trailing newlines */ -}}

View File

@ -1,9 +1,10 @@
<!DOCTYPE html>
<html lang="{{ .Site.Language.Lang }}" class="color-toggle-hidden">
<head>
<head>
{{ partial "head/meta" . }}
<title>{{ if not (eq .Kind "home") }}{{ partial "title" . }} | {{ end }}{{ .Site.Title }}</title>
<title>
{{ if not (eq .Kind "home") }}{{ partial "title" . }} |{{ end }}{{ .Site.Title }}
</title>
{{ partial "head/favicons" . }}
{{ partial "head/rel-me" . }}
@ -11,17 +12,21 @@
{{ partial "head/others" . }}
{{ partial "head/schema" . }}
{{ partial "head/custom" . }}
</head>
</head>
<body itemscope itemtype="https://schema.org/WebPage">
<body itemscope itemtype="https://schema.org/WebPage">
{{ partial "svg-icon-symbols" . }}
<div class="wrapper {{ if default false .Site.Params.GeekdocDarkModeDim }}dark-mode-dim{{ end }}">
<div
class="wrapper {{ if default false .Site.Params.GeekdocDarkModeDim }}dark-mode-dim{{ end }}"
>
<input type="checkbox" class="hidden" id="menu-control" />
<input type="checkbox" class="hidden" id="menu-header-control" />
{{ $navEnabled := default true .Page.Params.GeekdocNav }}
{{ partial "site-header" (dict "Root" . "MenuEnabled" $navEnabled) }}
<main class="container flex flex-even">
{{ if $navEnabled }}
<aside class="gdoc-nav">
@ -29,6 +34,7 @@
</aside>
{{ end }}
<div class="gdoc-page">
{{ template "main" . }}
{{ partial "page-footer" . }}
@ -39,5 +45,5 @@
</div>
{{ partial "foot" . }}
</body>
</body>
</html>

View File

@ -1,7 +1,10 @@
{{ define "main" }}
{{ partial "page-header" . }}
<article class="gdoc-markdown gdoc-markdown__align--{{ default "left" (.Page.Params.GeekdocAlign | lower) }}">
<article
class="gdoc-markdown gdoc-markdown__align--{{ default "left" (.Page.Params.GeekdocAlign | lower) }}"
>
<h1>{{ partial "title" . }}</h1>
{{ partial "content" . }}
</article>

View File

@ -0,0 +1,7 @@
{{- $searchDataFile := printf "%s.searchdata.json" .Language.Lang -}}
{{- $searchData := resources.Get "search/searchdata.json" | resources.ExecuteAsTemplate $searchDataFile . | resources.Minify -}}
{
"dataFile": {{ $searchData.RelPermalink | jsonify }},
"indexConfig": {{ .Site.Params.GeekdocSearchConfig | jsonify }},
"showParent": {{ if .Site.Params.GeekdocSearchShowParent }}true{{ else }}false{{ end }}
}

View File

@ -1,7 +1,10 @@
{{ define "main" }}
{{ partial "page-header" . }}
<article class="gdoc-markdown gdoc-markdown__align--{{ default "left" (.Page.Params.GeekdocAlign | lower) }}">
<article
class="gdoc-markdown gdoc-markdown__align--{{ default "left" (.Page.Params.GeekdocAlign | lower) }}"
>
<h1>{{ partial "title" . }}</h1>
{{ partial "content" . }}
</article>

View File

@ -1,14 +1,3 @@
{{ if default true .Site.Params.GeekdocSearch }}
{{ .Scratch.Set "geekdocSearchConfig" .Site.Params.GeekdocSearchConfig }}
<!-- Remove after https://github.com/gohugoio/hugo/issues/6331 -->
{{ $searchJSFile := printf "js/%s.search.js" .Language.Lang }}
{{ $searchJS := resources.Get "js/search.js" | resources.ExecuteAsTemplate $searchJSFile . | resources.Minify | fingerprint }}
<script defer src="{{ $searchJS.RelPermalink }}"></script>
<script defer src="{{ index (index .Site.Data.assets "search.js") "src" | relURL }}"></script>
{{ end }}
{{ if default true .Site.Params.GeekdocAnchorCopy }}
<script defer src="{{ index .Site.Data.assets "js/clipboard.min.js" | relURL }}"></script>
<script defer src="{{ index .Site.Data.assets "js/clipboard-loader.min.js" | relURL }}"></script>
{{ end }}
<script defer src="{{ index .Site.Data.assets "js/copycode.min.js" | relURL }}"></script>

View File

@ -1,3 +1,13 @@
<link rel="icon" type="image/svg+xml" href="{{ "favicon/favicon.svg" | relURL }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ "favicon/favicon-32x32.png" | relURL }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ "favicon/favicon-16x16.png" | relURL }}">
<link rel="icon" type="image/svg+xml" href="{{ "favicon/favicon.svg" | relURL }}" />
<link
rel="icon"
type="image/png"
sizes="32x32"
href="{{ "favicon/favicon-32x32.png" | relURL }}"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="{{ "favicon/favicon-16x16.png" | relURL }}"
/>

View File

@ -1,13 +1,13 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="light dark" />
{{ $description := default (default .Site.Title .Site.Params.description) (default .Summary .Description) }}
{{ $keywords := default .Site.Params.Keywords .Keywords }}
{{ with $description }}
<meta name="description" content="{{ . }}">
<meta name="description" content="{{ . }}" />
{{ end }}
{{ with $keywords }}
<meta name="keywords" content="{{ delimit . "," }}">
<meta name="keywords" content="{{ delimit . "," }}" />
{{ end }}

View File

@ -1,22 +1,66 @@
<script src="{{ index .Site.Data.assets "js/darkmode.min.js" | relURL }}"></script>
<script src="{{ index (index .Site.Data.assets "bundle.js") "src" | relURL }}"></script>
<link rel="preload" as="font" href="{{ "fonts/Metropolis.woff2" | relURL }}" type="font/woff2" crossorigin="anonymous">
<link rel="preload" as="font" href="{{ "fonts/LiberationSans.woff2" | relURL }}" type="font/woff2" crossorigin="anonymous">
<link
rel="preload"
as="font"
href="{{ "fonts/Metropolis.woff2" | relURL }}"
type="font/woff2"
crossorigin="anonymous"
/>
<link
rel="preload"
as="font"
href="{{ "fonts/LiberationSans.woff2" | relURL }}"
type="font/woff2"
crossorigin="anonymous"
/>
<link rel="preload" href="{{ index .Site.Data.assets "main.min.css" | relURL }}" as="style">
<link rel="stylesheet" href="{{ index .Site.Data.assets "main.min.css" | relURL }}" media="all">
<link
rel="preload"
href="{{ index (index .Site.Data.assets "main.scss") "src" | relURL }}"
as="style"
/>
<link
rel="stylesheet"
href="{{ index (index .Site.Data.assets "main.scss") "src" | relURL }}"
media="all"
/>
<link rel="preload" href="{{ index .Site.Data.assets "mobile.min.css" | relURL }}" as="style">
<link rel="stylesheet" href="{{ index .Site.Data.assets "mobile.min.css" | relURL }}" media="screen and (max-width: 45rem)">
<link
rel="preload"
href="{{ index (index .Site.Data.assets "mobile.scss") "src" | relURL }}"
as="style"
/>
<link
rel="stylesheet"
href="{{ index (index .Site.Data.assets "mobile.scss") "src" | relURL }}"
media="screen and (max-width: 45rem)"
/>
<link rel="preload" href="{{ index .Site.Data.assets "print.min.css" | relURL }}" as="style">
<link rel="stylesheet" href="{{ index .Site.Data.assets "print.min.css" | relURL }}" media="print">
<link
rel="preload"
href="{{ index (index .Site.Data.assets "print.scss") "src" | relURL }}"
as="style"
/>
<link
rel="stylesheet"
href="{{ index (index .Site.Data.assets "print.scss") "src" | relURL }}"
media="print"
/>
<link rel="preload" href="{{ index .Site.Data.assets "custom.css" | relURL }}" as="style">
<link rel="stylesheet" href="{{ index .Site.Data.assets "custom.css" | relURL }}" media="all">
<link
rel="preload"
href="{{ index (index .Site.Data.assets "custom.css") "src" | relURL }}"
as="style"
/>
<link
rel="stylesheet"
href="{{ index (index .Site.Data.assets "custom.css") "src" | relURL }}"
media="all"
/>
{{ if (default false $.Site.Params.GeekdocOverwriteHTMLBase) }}
<base href="{{ .Site.BaseURL }}">
<base href="{{ .Site.BaseURL }}" />
{{ end }}
{{ printf "<!-- %s -->" "Made with Geekdoc theme https://github.com/thegeeklab/hugo-geekdoc" | safeHTML }}

View File

@ -1,6 +1,5 @@
{{ if .IsHome -}}
{{ $thumbnail := default (default "brand.svg" .Site.Params.logo) (index (default slice .Site.Params.images) 0) | absURL }}
<script type="application/ld+json">
{{ $thumbnail := default (default "brand.svg" .Site.Params.logo) (index (default slice .Site.Params.images) 0) | absURL }}<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "WebSite",
@ -10,7 +9,7 @@
"description": "{{ . }}",
{{- end }}
"thumbnailUrl": "{{ $thumbnail }}"
{{- with .Site.Params.GeekblogContentLicense }},
{{- with .Site.Params.GeekdocContentLicense }},
"license": "{{ .name }}"
{{- end }}
}

View File

@ -1,19 +1,22 @@
{{ $current := .current }}
{{ template "menu-file" dict "sect" .source "current" $current "site" $current.Site }}
<!-- template -->
{{ define "menu-file" }}
{{ $current := .current }}
{{ $site := .site }}
{{ $current := .current }}
{{ $site := .site }}
<ul class="gdoc-nav__list">
{{ range sort (default (seq 0) .sect) "weight" }}
<ul class="gdoc-nav__list">
{{ range sort (default (seq 0) .sect) "weight" }}
{{ $current.Scratch.Set "current" $current }}
{{ $current.Scratch.Set "site" $site }}
<li>
{{ $ref := default false .ref }}
{{ if $ref}}
{{ if $ref }}
{{ $site := $current.Scratch.Get "site" }}
{{ $this := $site.GetPage .ref }}
{{ $current := $current.Scratch.Get "current" }}
@ -24,22 +27,47 @@
{{ $id := substr (sha1 $this.Permalink) 0 8 }}
{{ $doCollapse := and (isset . "sub") (or $this.Params.GeekdocCollapseSection (default false .Site.Params.GeekdocCollapseAllSections)) }}
<input
type="checkbox"
{{ if $doCollapse }}
<input type="checkbox" id="{{ printf "navtree-%s" $id }}" class="gdoc-nav__toggle" {{ if or $isCurrent $isAncestor }}checked{{ end }}>
<label for="{{ printf "navtree-%s" $id }}" class="flex justify-between">
class="gdoc-nav__toggle" id="{{ printf "navtree-%s" $id }}"
{{ if or $isCurrent $isAncestor }}checked{{ end }}
{{ else }}
class="hidden"
{{ end }}
/>
<label
{{ if $doCollapse }}
for="{{ printf "navtree-%s" $id }}" class="flex justify-between"
{{ end }}
>
<span class="flex">
{{ if $icon }}<svg class="icon {{ .icon }}"><use xlink:href="#{{ .icon }}"></use></svg>{{ end }}
<a href="{{ if .external }}{{ .ref }}{{ else }}{{ relref $current .ref }}{{ end }}"
class="gdoc-nav__entry {{ if not .external }}{{ if $isCurrent }}is-active{{ end }}{{ end }}">
{{ if $icon }}
<svg class="icon {{ .icon }}"><use xlink:href="#{{ .icon }}"></use></svg>
{{ end }}
<a
href="{{ if .external }}
{{ .ref }}
{{ else }}
{{ relref $current .ref }}
{{ end }}"
class="gdoc-nav__entry {{ if not .external }}
{{ if $isCurrent }}is-active{{ end }}
{{ end }}"
>
{{ .name }}
</a>
</span>
{{ if $doCollapse }}
<svg class="icon gdoc_keyborad_arrow_left"><use xlink:href="#gdoc_keyborad_arrow_left"></use></svg>
<svg class="icon gdoc_keyborad_arrow_down hidden"><use xlink:href="#gdoc_keyborad_arrow_down"></use></svg>
</label>
<svg class="icon gdoc_keyborad_arrow_left">
<use xlink:href="#gdoc_keyborad_arrow_left"></use>
</svg>
<svg class="icon gdoc_keyborad_arrow_down hidden">
<use xlink:href="#gdoc_keyborad_arrow_down"></use>
</svg>
{{ end }}
</label>
{{ else }}
<span class="flex">{{ .name }}</span>
{{ end }}
@ -48,7 +76,6 @@
{{ template "menu-file" dict "sect" . "current" ($current.Scratch.Get "current") "site" ($current.Scratch.Get "site") }}
{{ end }}
</li>
{{ end }}
</ul>
{{ end }}
</ul>
{{ end }}

View File

@ -1,14 +1,15 @@
{{ $current := .current }}
{{ template "menu-extra" dict "sect" .source "current" $current "site" $current.Site "target" .target }}
<!-- template -->
{{ define "menu-extra" }}
{{ $current := .current }}
{{ $site := .site }}
{{ $target := .target }}
{{ $sect := .sect }}
{{ $current := .current }}
{{ $site := .site }}
{{ $target := .target }}
{{ $sect := .sect }}
{{ range sort (default (seq 0) $sect) "weight" }}
{{ range sort (default (seq 0) $sect) "weight" }}
{{ if isset . "ref" }}
{{ $this := $site.GetPage .ref }}
{{ $isCurrent := eq $current $this }}
@ -20,7 +21,14 @@
{{ if eq $target "header" }}
<span>
<a href="{{ if .external }}{{ .ref }}{{ else }}{{ relref $current .ref }}{{ end }}" class="gdoc-header__link">
<a
href="{{ if .external }}
{{ .ref }}
{{ else }}
{{ relref $current .ref }}
{{ end }}"
class="gdoc-header__link"
>
<svg class="icon {{ .icon }}">
<title>{{ .name }}</title>
<use xlink:href="#{{ .icon }}"></use>
@ -29,5 +37,5 @@
</span>
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}

View File

@ -1,10 +1,12 @@
{{ $current := . }}
{{ template "tree-nav" dict "sect" .Site.Home.Sections "current" $current }}
<!-- templates -->
{{ define "tree-nav" }}
{{ $current := .current }}
<ul class="gdoc-nav__list">
{{ $sortBy := (default "title" .current.Site.Params.GeekdocFileTreeSortBy | lower) }}
{{ range .sect.GroupBy "Weight" }}
@ -46,14 +48,28 @@
{{ $id := substr (sha1 .Permalink) 0 8 }}
{{ $doCollapse := and $isParent (or .Params.GeekdocCollapseSection (default false .Site.Params.GeekdocCollapseAllSections)) }}
<li>
<input
type="checkbox"
{{ if $doCollapse }}
<input type="checkbox" id="{{ printf "navtree-%s" $id }}" class="gdoc-nav__toggle" {{ if or $isCurrent $isAncestor }}checked{{ end }}>
<label for="{{ printf "navtree-%s" $id }}" class="flex justify-between">
class="gdoc-nav__toggle" id="{{ printf "navtree-%s" $id }}"
{{ if or $isCurrent $isAncestor }}checked{{ end }}
{{ else }}
class="hidden"
{{ end }}
/>
<label
{{ if $doCollapse }}
for="{{ printf "navtree-%s" $id }}" class="flex justify-between"
{{ end }}
>
{{ if or .Content .Params.GeekdocFlatSection }}
<span class="flex">
<a href="{{ .RelPermalink }}" class="gdoc-nav__entry {{ if eq $current . }}is-active{{ end }}">
<a
href="{{ .RelPermalink }}"
class="gdoc-nav__entry {{ if eq $current . }}is-active{{ end }}"
>
{{ partial "title" . }}
</a>
</span>
@ -61,13 +77,17 @@
<span class="flex">{{ partial "title" . }}</span>
{{ end }}
{{ if $doCollapse }}
<svg class="icon gdoc_keyborad_arrow_left"><use xlink:href="#gdoc_keyborad_arrow_left"></use></svg>
<svg class="icon gdoc_keyborad_arrow_down"><use xlink:href="#gdoc_keyborad_arrow_down"></use></svg>
</label>
<svg class="icon gdoc_keyborad_arrow_left">
<use xlink:href="#gdoc_keyborad_arrow_left"></use>
</svg>
<svg class="icon gdoc_keyborad_arrow_down">
<use xlink:href="#gdoc_keyborad_arrow_down"></use>
</svg>
{{ end }}
</label>
{{ if $isParent }}
{{ template "tree-nav" dict "sect" .Pages "current" $current}}
{{ template "tree-nav" dict "sect" .Pages "current" $current }}
{{ end }}
</li>
{{ end }}

View File

@ -1,6 +1,7 @@
<nav>
{{ partial "search" . }}
<section class="gdoc-nav--main">
<h2>Navigation</h2>
{{ if .Site.Params.GeekdocMenuBundle }}
@ -18,7 +19,12 @@
{{ range $name, $taxonomy := .Site.Taxonomies.tags }}
{{ with $.Site.GetPage (printf "/tags/%s" $name) }}
<li>
<a class="gdoc-nav__entry {{ if eq $currentPage .RelPermalink }} is-active {{ end }}" href="{{ .RelPermalink }}">{{ .Title }}</a>
<a
class="gdoc-nav__entry {{ if eq $currentPage .RelPermalink }}is-active{{ end }}"
href="{{ .RelPermalink }}"
>
{{ .Title }}
</a>
</li>
{{ end }}
{{ end }}
@ -26,6 +32,7 @@
</section>
{{ end }}
<section class="gdoc-nav--more">
{{ if .Site.Data.menu.more.more }}
<h2>More</h2>

View File

@ -17,7 +17,7 @@
{{ $current.Scratch.Set "site" $site }}
{{ $ref := default false .ref }}
{{ if $ref}}
{{ if $ref }}
{{ $site := $current.Scratch.Get "site" }}
{{ $this := $site.GetPage .ref }}
{{ $current := $current.Scratch.Get "current" }}
@ -48,12 +48,24 @@
{{ if $showPrevNext }}
<span class="gdoc-page__nav">
{{ with ($current.Scratch.Get "prevPage") }}
<a class="gdoc-page__nav--prev flex align-center" href="{{.this.RelPermalink}}" title="{{ .name }}"> {{ .name }}</a>
<a
class="gdoc-page__nav--prev flex align-center"
href="{{ .this.RelPermalink }}"
title="{{ .name }}"
>
{{ .name }}
</a>
{{ end }}
</span>
<span class="gdoc-page__nav">
{{ with ($current.Scratch.Get "nextPage") }}
<a class="gdoc-page__nav--next flex align-center" href="{{.this.RelPermalink}}" title="{{ .name }}">{{ .name }} </a>
<a
class="gdoc-page__nav--next flex align-center"
href="{{ .this.RelPermalink }}"
title="{{ .name }}"
>
{{ .name }}
</a>
{{ end }}
</span>
{{ end }}

View File

@ -20,11 +20,18 @@
{{ $showBreadcrumb := (and (default true .Page.Params.GeekdocBreadcrumb) (default true .Site.Params.GeekdocBreadcrumb)) }}
{{ $showEdit := (and ($.Scratch.Get "geekdocFilePath") $geekdocRepo $geekdocEditPath) }}
<div class="gdoc-page__header flex flex-wrap
{{ if $showBreadcrumb }} justify-between {{ else }} justify-end {{ end }}
{{ if not $showEdit }} hidden-mobile {{ end }}
{{ if (and (not $showBreadcrumb) (not $showEdit)) }} hidden {{ end }}" itemprop="breadcrumb">
{{if $showBreadcrumb }}
<div
class="gdoc-page__header flex flex-wrap
{{ if $showBreadcrumb }}
justify-between
{{ else }}
justify-end
{{ end }}
{{ if not $showEdit }}hidden-mobile{{ end }}
{{ if (and (not $showBreadcrumb) (not $showEdit)) }}hidden{{ end }}"
itemprop="breadcrumb"
>
{{ if $showBreadcrumb }}
<div>
<svg class="icon gdoc_path hidden-mobile"><use xlink:href="#gdoc_path"></use></svg>
<ol class="breadcrumb" itemscope itemtype="https://schema.org/BreadcrumbList">
@ -39,7 +46,9 @@
<div>
<span class="editpage">
<svg class="icon gdoc_code"><use xlink:href="#gdoc_code"></use></svg>
<a href="{{ $geekdocRepo }}/{{ path.Join $geekdocEditPath ($.Scratch.Get "geekdocFilePath") }}">
<a
href="{{ $geekdocRepo }}/{{ path.Join $geekdocEditPath ($.Scratch.Get "geekdocFilePath") }}"
>
Edit this page
</a>
</span>

View File

@ -1,8 +1,14 @@
{{ if default true .Site.Params.GeekdocSearch }}
<div class="gdoc-search">
<svg class="icon gdoc_search"><use xlink:href="#gdoc_search"></use></svg>
<input type="text" id="gdoc-search-input" class="gdoc-search__input" placeholder="Search..."
aria-label="Search" maxlength="64" />
<input
type="text"
id="gdoc-search-input"
class="gdoc-search__input"
placeholder="Search..."
aria-label="Search"
maxlength="64"
/>
<div class="gdoc-search__spinner spinner hidden"></div>
<ul id="gdoc-search-results" class="gdoc-search__list"></ul>
</div>

View File

@ -20,7 +20,10 @@
<div class="flex flex-25 justify-end">
<span class="gdoc-footer__item text-right">
<a class="gdoc-footer__link fake-link" href="#" aria-label="Back to top">
<svg class="icon gdoc_keyborad_arrow_up"><use xlink:href="#gdoc_keyborad_arrow_up"></use></svg> <span class="hidden-mobile">Back to top</span>
<svg class="icon gdoc_keyborad_arrow_up">
<use xlink:href="#gdoc_keyborad_arrow_up"></use>
</svg>
<span class="hidden-mobile">Back to top</span>
</a>
</span>
</div>

View File

@ -14,13 +14,17 @@
{{ end }}
<a class="gdoc-header__link" href="{{ .Root.Site.BaseURL }}">
<span class="gdoc-brand flex align-center">
<img class="gdoc-brand__img" src="{{ (default "brand.svg" .Root.Site.Params.GeekdocLogo) | relURL }}" alt="">
<img
class="gdoc-brand__img"
src="{{ (default "brand.svg" .Root.Site.Params.GeekdocLogo) | relURL }}"
alt=""
/>
<span class="gdoc-brand__title">{{ .Root.Site.Title }}</span>
</span>
</a>
<div class="gdoc-menu-header">
<span {{ if .Root.Site.Data.menu.extra.header }}class="gdoc-menu-header__items"{{ end }}>
{{ if .Root.Site.Data.menu.extra.header }}
<span class="gdoc-menu-header__items">
{{ partial "menu-extra" (dict "current" .Root "source" .Root.Site.Data.menu.extra.header "target" "header") }}
{{ end }}
<span id="gdoc-dark-mode">
@ -54,7 +58,9 @@
</svg>
</label>
</span>
{{ end }}
</span>
{{ if .Root.Site.Data.menu.extra.header }}
<label for="menu-header-control" class="gdoc-menu-header__control">
<svg class="icon gdoc_keyborad_arrow_left">
<use xlink:href="#gdoc_keyborad_arrow_left"></use>

View File

@ -1,4 +1,4 @@
{{ range resources.Match "sprites/*.svg" }}
{{ printf "<!-- geekdoc include: %s -->" . | safeHTML }}
{{ .Content | safeHTML }}
{{ printf "<!-- geekdoc include: %s -->" . | safeHTML }}
{{ .Content | safeHTML }}
{{ end }}

View File

@ -9,7 +9,13 @@
</section>
<div class="gdoc-post__readmore">
{{ if .Truncated }}
<a class="flex-inline align-center fake-link" title="Read full post" href="{{ .RelPermalink }}">Read full post</a>
<a
class="flex-inline align-center fake-link"
title="Read full post"
href="{{ .RelPermalink }}"
>
Read full post
</a>
{{ end }}
</div>
@ -54,9 +60,15 @@
{{ end }}
{{ define "post-tag" }}
<span class="gdoc-post__tag">
<span class="gdoc-post__tag">
<span class="gdoc-button">
<a class="gdoc-button__link" href="{{ .page.RelPermalink }}" title="All posts tagged with '{{ .name }}'">{{ .name }}</a>
<a
class="gdoc-button__link"
href="{{ .page.RelPermalink }}"
title="All posts tagged with '{{ .name }}'"
>
{{ .name }}
</a>
</span>
</span>
</span>
{{ end }}

View File

@ -3,7 +3,7 @@
{{ $size := default "regular" (.Get "size" | lower) }}
{{ if not (in (slice "regular" "large") $size) }}
{{ $size = "regular" }}
{{ $size = "regular" }}
{{ end }}
{{ with .Get "href" }}
@ -15,8 +15,13 @@
{{ $ref = relref $ . }}
{{ end }}
<span class="gdoc-button gdoc-button--{{ $size }}{{ with .Get "class" }} {{ . }}{{ end }}">
<a {{ with $ref }} href="{{.}}" {{ end }} {{ with $target }} target="{{.}}" {{ end }} class="gdoc-button__link">
<span class="gdoc-button gdoc-button--{{ $size }}{{ with .Get "class" }}{{ . }}{{ end }}">
<a
{{ with $ref }}href="{{ . }}"{{ end }}
{{ with $target }}target="{{ . }}"{{ end }}
class="gdoc-button__link"
>
{{ $.Inner }}
</a>
</a>
</span>

View File

@ -1,5 +1,5 @@
{{ $id := .Get 0 }}
{{- with $id -}}
<svg class="icon {{ . }}"><use xlink:href="#{{ . }}"></use></svg>
<svg class="icon {{ . }}"><use xlink:href="#{{ . }}"></use></svg>
{{- end -}}

View File

@ -4,26 +4,41 @@
{{ $lazyLoad := default (default true $.Site.Params.GeekdocImageLazyLoading) (.Get "lazy") }}
{{ with $source }}
{{ $caption := default .Title $customAlt }}
{{ $caption := default .Title $customAlt }}
{{ $tiny := (.Resize "320x").RelPermalink }}
{{ $small := (.Resize "600x").RelPermalink }}
{{ $medium := (.Resize "1200x").RelPermalink }}
{{ $large := (.Resize "1800x").RelPermalink }}
{{ $tiny := (.Resize "320x").RelPermalink }}
{{ $small := (.Resize "600x").RelPermalink }}
{{ $medium := (.Resize "1200x").RelPermalink }}
{{ $large := (.Resize "1800x").RelPermalink }}
{{ $size := dict "tiny" $tiny "small" $small "medium" $medium "large" $large }}
{{ $size := dict "tiny" $tiny "small" $small "medium" $medium "large" $large }}
<div class="flex justify-center">
<figure class="gdoc-markdown__figure">
<div class="flex justify-center">
<figure class="gdoc-markdown__figure">
<a class="gdoc-markdown__link--raw" href="{{ .RelPermalink }}">
<picture>
<source {{ with $customSize }}srcset="{{ index $size $customSize }}"{{ else }}srcset="{{ $size.small }} 600w, {{ $size.medium }} 1200w" sizes="100vw"{{ end }} />
<img {{ if $lazyLoad }}loading="lazy" {{ end }}src="{{ $size.large }}" alt="{{ $caption }}" />
<source
{{ with $customSize }}
srcset="{{ index $size $customSize }}"
{{ else }}
srcset="{{ $size.small }} 600w, {{ $size.medium }} 1200w" sizes="100vw"
{{ end }}
/>
<img
{{ if $lazyLoad }}
loading="lazy"
{{ end }}
src="{{ $size.large }}"
alt="{{ $caption }}"
/>
</picture>
</a>
{{ with $caption -}}
<figcaption>{{ . }}{{ with $source.Params.credits }} ({{ . | $.Page.RenderString }}){{ end }}</figcaption>
<figcaption>
{{ . }}{{ with $source.Params.credits }}({{ . | $.Page.RenderString }}){{ end }}
</figcaption>
{{- end }}
</figure>
</div>
</figure>
</div>
{{ end }}

View File

@ -4,14 +4,15 @@
{{ $language := .Get "language" }}
{{ $options :=.Get "options" }}
<div class="gdoc-include">
{{- if (.Get "language") -}}
{{- if (.Get "language") -}}
{{- highlight ($file | readFile) $language (default "linenos=table" $options) -}}
{{- else if eq $type "html" -}}
{{- else if eq $type "html" -}}
{{- $file | readFile | safeHTML -}}
{{- else if eq $type "page" -}}
{{- else if eq $type "page" -}}
{{- with $page }}{{ .Content }}{{ end -}}
{{- else -}}
{{- else -}}
{{- $file | readFile | $.Page.RenderString -}}
{{- end -}}
{{- end -}}
</div>

View File

@ -1,13 +1,14 @@
{{ if not (.Page.Scratch.Get "katex") }}
<!-- Include katext only first time -->
<link rel="stylesheet" href="{{ index .Site.Data.assets "katex.min.css" | relURL }}" />
<script defer src="{{ index .Site.Data.assets "js/katex.min.js" | relURL }}"></script>
<script defer src="{{ index .Site.Data.assets "js/auto-render.min.js" | relURL }}"></script>
<script defer src="{{ index .Site.Data.assets "js/katex-loader.min.js" | relURL }}"></script>
{{ .Page.Scratch.Set "katex" true }}
<!-- Include katext only first time -->
<link
rel="stylesheet"
href="{{ index (index .Site.Data.assets "katex.css") "src" | relURL }}"
/><script defer src="{{ index (index .Site.Data.assets "katex.js") "src" | relURL }}"></script>
{{ .Page.Scratch.Set "katex" true }}
{{ end }}
<span class="gdoc-katex katex{{ with .Get "class" }} {{ . }}{{ end }}">
<span class="gdoc-katex katex{{ with .Get "class" }}{{ . }}{{ end }}">
{{ cond (in .Params "display") "\\[" "\\(" -}}
{{- trim .Inner "\n" -}}
{{- cond (in .Params "display") "\\]" "\\)" }}

View File

@ -1,10 +1,9 @@
{{ if not (.Page.Scratch.Get "mermaid") }}
<!-- Include mermaid only first time -->
<script defer src="{{ index .Site.Data.assets "js/mermaid.min.js" | relURL }}"></script>
<script defer src="{{ index .Site.Data.assets "js/mermaid-loader.min.js" | relURL }}"></script>
{{ .Page.Scratch.Set "mermaid" true }}
<!-- Include mermaid only first time --><script defer src="{{ index (index .Site.Data.assets "mermaid.js") "src" | relURL }}"></script>
{{ .Page.Scratch.Set "mermaid" true }}
{{ end }}
<pre class="gdoc-mermaid mermaid{{ with .Get "class" }} {{ . }}{{ end }}">
<pre class="gdoc-mermaid mermaid{{ with .Get "class" }}{{ printf " %s" . }}{{ end }}">
{{- .Inner -}}
</pre>

View File

@ -9,4 +9,4 @@
{{ .Parent.Scratch.Add $group (dict "Name" $name "Content" .Inner) }}
{{ else }}
{{ errorf "%q: 'tab' shortcode must be inside 'tabs' shortcode" .Page.Path }}
{{ end}}
{{ end }}

View File

@ -2,10 +2,16 @@
{{ $id := .Get 0 }}
{{ $group := printf "tabs-%s" $id }}
<div class="gdoc-tabs">
{{ range $index, $tab := .Scratch.Get $group }}
<input type="radio" class="gdoc-tabs__control hidden" name="{{ $group }}" id="{{ printf "%s-%d" $group $index }}"
{{ if not $index }}checked="checked" {{ end }} />
<input
type="radio"
class="gdoc-tabs__control hidden"
name="{{ $group }}"
id="{{ printf "%s-%d" $group $index }}"
{{ if not $index }}checked="checked"{{ end }}
/>
<label for="{{ printf "%s-%d" $group $index }}" class="gdoc-tabs__label">
{{ $tab.Name }}
</label>

View File

@ -1,11 +1,12 @@
{{ $tocLevels := default (default 6 .Site.Params.GeekdocToC) .Page.Params.GeekdocToC }}
{{ if $tocLevels }}
<div class="gdoc-toc gdoc-toc__level--{{$tocLevels}}">
<div class="gdoc-toc gdoc-toc__level--{{ $tocLevels }}">
{{ template "toc-tree" dict "sect" .Page.Pages }}
</div>
{{ end }}
<!-- templates -->
{{ define "toc-tree" }}
<ul>
@ -15,10 +16,15 @@
<li>
{{ if or .Content .Params.GeekdocFlatSection }}
<span>
<a href="{{ .RelPermalink }}" class="gdoc-toc__entry">{{ partial "title" . }}{{ with .Params.GeekdocDescription }}:</a> {{ . }}{{ else }}</a>{{ end }}
<a href="{{ .RelPermalink }}" class="gdoc-toc__entry">
{{ partial "title" . }}{{ with .Params.GeekdocDescription }}:{{ end }}
</a>
{{ with .Params.GeekdocDescription }}{{ . }}{{ end }}
</span>
{{ else }}
<span>{{ partial "title" . }}{{ with .Params.GeekdocDescription }}: {{ . }}{{ end }}</span>
<span>
{{ partial "title" . }}{{ with .Params.GeekdocDescription }}: {{ . }}{{ end }}
</span>
{{ end }}
{{ $numberOfPages := (add (len .Pages) (len .Sections)) }}

View File

@ -1,5 +1,8 @@
{{ $tocLevels := default (default 6 .Site.Params.GeekdocToC) .Page.Params.GeekdocToC }}
{{ if and $tocLevels .Page.TableOfContents }}
<div class="gdoc-toc gdoc-toc__level--{{$tocLevels}}">{{ .Page.TableOfContents }}<hr></div>
<div class="gdoc-toc gdoc-toc__level--{{ $tocLevels }}">
{{ .Page.TableOfContents }}
<hr />
</div>
{{ end }}

View File

@ -9,7 +9,13 @@
</section>
<div class="gdoc-post__readmore">
{{ if .Truncated }}
<a class="flex-inline align-center fake-link" title="Read full post" href="{{ .RelPermalink }}">Read full post</a>
<a
class="flex-inline align-center fake-link"
title="Read full post"
href="{{ .RelPermalink }}"
>
Read full post
</a>
{{ end }}
</div>
@ -54,9 +60,15 @@
{{ end }}
{{ define "post-tag" }}
<span class="gdoc-post__tag">
<span class="gdoc-post__tag">
<span class="gdoc-button">
<a class="gdoc-button__link" href="{{ .page.RelPermalink }}" title="All posts tagged with '{{ .name }}'">{{ .name }}</a>
<a
class="gdoc-button__link"
href="{{ .page.RelPermalink }}"
title="All posts tagged with '{{ .name }}'"
>
{{ .name }}
</a>
</span>
</span>
</span>
{{ end }}

20912
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,10 +2,23 @@
"name": "geekdoc",
"version": "1.0.0",
"description": "Hugo theme made for documentation",
"main": "gulpfile.js",
"main": "index.js",
"scripts": {
"gulp": "gulp",
"server": "hugo server -D -F -s exampleSite/"
"build": "run-s prep:clean prep:make svg build:webpack",
"build:webpack": "webpack --mode=production",
"build:webpack-devel": "webpack --mode=development",
"start": "run-s prep:clean prep:make svg build:webpack-devel ; run-p start:webpack start:hugo",
"start:webpack": "webpack --mode=development --watch",
"start:build": "webpack --mode=development",
"start:hugo": "hugo server -D -F -s exampleSite/",
"svg": "run-s svg:*",
"svg:sprite": "svg-sprite -C svgsprite.config.json 'src/icons/*.svg'",
"svg:font": "svgtofont --sources build/icons --output build/fonts",
"prep:clean": "shx rm -rf build/ static/",
"prep:clean-all": "shx rm -rf build/ static/ data/ assets/sprites/ exampleSite/data/sprites",
"prep:make": "mkdir -p build/icons build/fonts",
"svg-sprite-list": "run-s prep:make svg ; mkdir -p exampleSite/data/sprites/ ; cp build/fonts/GeekdocIcons.json exampleSite/data/sprites/geekdoc.json",
"lint": "eslint src/js/ --color"
},
"repository": {
"type": "git",
@ -14,34 +27,53 @@
"author": "Robert Kaussow",
"license": "MIT",
"dependencies": {
"ajv": "8.8.2",
"clipboard": "2.0.8",
"flexsearch": "0.7.21",
"katex": "0.15.1",
"mermaid": "8.13.6"
"mermaid": "8.13.8",
"store2": "2.13.1"
},
"devDependencies": {
"@mr-hope/gulp-sass": "2.0.0",
"del": "6.0.0",
"gulp": "4.0.2",
"gulp-autoprefixer": "8.0.0",
"gulp-clean-css": "4.3.0",
"gulp-filelist": "2.0.5",
"gulp-iconfont": "11.0.1",
"gulp-real-favicon": "0.3.2",
"gulp-rename": "2.0.0",
"gulp-replace": "1.1.3",
"gulp-rev": "9.0.0",
"gulp-sourcemaps": "3.0.0",
"gulp-svg-sprite": "1.5.0",
"gulp-uglify": "3.0.2",
"@babel/eslint-parser": "7.16.5",
"autoprefixer": "10.4.1",
"copy-webpack-plugin": "10.2.0",
"css-loader": "6.5.1",
"eslint": "8.5.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-prettier": "4.0.0",
"favicons-webpack-plugin": "5.0.2",
"npm-run-all": "4.1.5",
"postcss-loader": "6.2.1",
"prettier": "2.5.1",
"prettier-plugin-go-template": "0.0.11",
"through2": "4.0.2"
"sass": "1.45.1",
"sass-loader": "12.4.0",
"shx": "0.3.3",
"svg-sprite": "1.5.3",
"svgtofont": "3.13.1",
"webpack": "5.65.0",
"webpack-cli": "4.9.1",
"webpack-manifest-plugin": "4.0.2",
"webpack-remove-empty-scripts": "0.7.2"
},
"browserslist": [
"last 2 version",
"> 5%",
"not dead",
"Firefox ESR"
]
],
"svgtofont": {
"fontName": "GeekdocIcons",
"css": false,
"html": false,
"emptyDist": true,
"useNameAsUnicode": true,
"svgicons2svgfont": {
"fontHeight": 1001,
"normalize": true,
"centerHorizontally": true,
"centerVertically": true
}
}
}

View File

@ -1 +0,0 @@
{"result":{"status":"success"},"favicon":{"package_url":"https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/favicon_package_v0.16.zip","files_urls":["https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/android-chrome-192x192.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/android-chrome-512x512.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/apple-touch-icon.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/browserconfig.xml","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/favicon-16x16.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/favicon-32x32.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/favicon.ico","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/mstile-144x144.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/mstile-150x150.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/mstile-310x150.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/mstile-310x310.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/mstile-70x70.png","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/safari-pinned-tab.svg","https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/package_files/site.webmanifest"],"html_code":"<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/apple-touch-icon.png\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/favicon-32x32.png\">\n<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/favicon-16x16.png\">\n<link rel=\"manifest\" href=\"/site.webmanifest\">\n<link rel=\"mask-icon\" href=\"/safari-pinned-tab.svg\" color=\"#5bbad5\">\n<meta name=\"msapplication-TileColor\" content=\"#2b5797\">\n<meta name=\"msapplication-TileImage\" content=\"/mstile-144x144.png\">\n<meta name=\"theme-color\" content=\"#ffffff\">","compression":"false","overlapping_markups":["link[rel=\"apple-touch-icon\"]","link[rel=\"shortcut\"]","link[rel=\"shortcut icon\"]","link[rel=\"icon\",sizes=\"16x16\"]","link[rel=\"icon\",sizes=\"32x32\"]","meta[name=\"msapplication-TileColor\"]","meta[name=\"msapplication-TileImage\"]","link[rel=\"manifest\"]","meta[name=\"theme-color\"]","link[rel=\"mask-icon\"]"]},"files_location":{"type":"path","path":"/"},"preview_picture_url":"https://realfavicongenerator.net/files/a14c093dfa827ba277aadc2d7a936885d5b564aa/favicon_preview.png","version":"0.16"}

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 37.33 37.33"><path d="M24 10.526v2.947H5.755l8.351 8.421-2.105 2.105-12-12 12-12 2.105 2.105-8.351 8.421H24z"/></svg>

Before

Width:  |  Height:  |  Size: 202 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 37.33 37.33"><path d="M18.035 10.526V6.035L24 12l-5.965 5.965v-4.491H0v-2.947h18.035z"/></svg>

Before

Width:  |  Height:  |  Size: 179 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 37.33 37.33"><path d="M15.268 4.392q.868 0 1.532.638t.664 1.506v17.463l-7.659-3.268-7.608 3.268V6.536q0-.868.664-1.506t1.532-.638h10.876zm4.34 14.144V4.392q0-.868-.638-1.532t-1.506-.664H6.537q0-.868.664-1.532T8.733 0h10.876q.868 0 1.532.664t.664 1.532v17.412z"/></svg>

Before

Width:  |  Height:  |  Size: 353 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 41.33 41.33"><path d="M9.917 24.5a1.75 1.75 0 10-3.501.001 1.75 1.75 0 003.501-.001zm0-21a1.75 1.75 0 10-3.501.001A1.75 1.75 0 009.917 3.5zm11.666 2.333a1.75 1.75 0 10-3.501.001 1.75 1.75 0 003.501-.001zm1.75 0a3.502 3.502 0 01-1.75 3.026c-.055 6.581-4.721 8.039-7.82 9.023-2.898.911-3.846 1.349-3.846 3.117v.474a3.502 3.502 0 011.75 3.026c0 1.932-1.568 3.5-3.5 3.5s-3.5-1.568-3.5-3.5c0-1.294.711-2.424 1.75-3.026V6.526A3.502 3.502 0 014.667 3.5c0-1.932 1.568-3.5 3.5-3.5s3.5 1.568 3.5 3.5a3.502 3.502 0 01-1.75 3.026v9.06c.93-.456 1.914-.766 2.807-1.039 3.391-1.075 5.323-1.878 5.359-5.687a3.502 3.502 0 01-1.75-3.026c0-1.932 1.568-3.5 3.5-3.5s3.5 1.568 3.5 3.5z"/></svg>

Before

Width:  |  Height:  |  Size: 757 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M27.192 28.844V11.192H4.808v17.652h22.384zm0-25.689q1.277 0 2.253.976t.976 2.253v22.459q0 1.277-.976 2.216t-2.253.939H4.808q-1.352 0-2.291-.901t-.939-2.253V6.385q0-1.277.939-2.253t2.291-.976h1.577V.001h3.23v3.155h12.769V.001h3.23v3.155h1.577zm-3.155 11.267v3.155h-3.23v-3.155h3.23zm-6.46 0v3.155h-3.155v-3.155h3.155zm-6.384 0v3.155h-3.23v-3.155h3.23z"/></svg>

Before

Width:  |  Height:  |  Size: 466 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M2.866 28.209h26.269v3.79H2.866v-3.79zm26.268-16.925L16 24.418 2.866 11.284h7.493V.001h11.283v11.283h7.493z"/></svg>

Before

Width:  |  Height:  |  Size: 223 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M28.845 9.615v-3.23L16 14.422 3.155 6.385v3.23L16 17.577zm0-6.46q1.277 0 2.216.977T32 6.385v19.23q0 1.277-.939 2.253t-2.216.977H3.155q-1.277 0-2.216-.977T0 25.615V6.385q0-1.277.939-2.253t2.216-.977h25.69z"/></svg>

Before

Width:  |  Height:  |  Size: 320 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M16 .394c8.833 0 15.999 7.166 15.999 15.999 0 7.062-4.583 13.062-10.937 15.187-.813.146-1.104-.354-1.104-.771 0-.521.021-2.25.021-4.396 0-1.5-.5-2.458-1.083-2.958 3.562-.396 7.312-1.75 7.312-7.896 0-1.75-.625-3.167-1.646-4.291.167-.417.708-2.042-.167-4.25-1.333-.417-4.396 1.646-4.396 1.646a15.032 15.032 0 00-8 0S8.937 6.602 7.603 7.018c-.875 2.208-.333 3.833-.167 4.25-1.021 1.125-1.646 2.542-1.646 4.291 0 6.125 3.729 7.5 7.291 7.896-.458.417-.875 1.125-1.021 2.146-.917.417-3.25 1.125-4.646-1.333-.875-1.521-2.458-1.646-2.458-1.646-1.562-.021-.104.979-.104.979 1.042.479 1.771 2.333 1.771 2.333.938 2.854 5.396 1.896 5.396 1.896 0 1.333.021 2.583.021 2.979 0 .417-.292.917-1.104.771C4.582 29.455-.001 23.455-.001 16.393-.001 7.56 7.165.394 15.998.394zM6.063 23.372c.042-.083-.021-.187-.146-.25-.125-.042-.229-.021-.271.042-.042.083.021.187.146.25.104.062.229.042.271-.042zm.646.709c.083-.062.062-.208-.042-.333-.104-.104-.25-.146-.333-.062-.083.062-.062.208.042.333.104.104.25.146.333.062zm.625.937c.104-.083.104-.25 0-.396-.083-.146-.25-.208-.354-.125-.104.062-.104.229 0 .375s.271.208.354.146zm.875.875c.083-.083.042-.271-.083-.396-.146-.146-.333-.167-.417-.062-.104.083-.062.271.083.396.146.146.333.167.417.062zm1.187.521c.042-.125-.083-.271-.271-.333-.167-.042-.354.021-.396.146s.083.271.271.312c.167.062.354 0 .396-.125zm1.313.104c0-.146-.167-.25-.354-.229-.187 0-.333.104-.333.229 0 .146.146.25.354.229.187 0 .333-.104.333-.229zm1.208-.208c-.021-.125-.187-.208-.375-.187-.187.042-.312.167-.292.312.021.125.187.208.375.167s.312-.167.292-.292z"/></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M16 29.714a1.11 1.11 0 01-.786-.321L4.072 18.643c-.143-.125-4.071-3.714-4.071-8 0-5.232 3.196-8.357 8.535-8.357 3.125 0 6.053 2.464 7.464 3.857 1.411-1.393 4.339-3.857 7.464-3.857 5.339 0 8.535 3.125 8.535 8.357 0 4.286-3.928 7.875-4.089 8.035L16.785 29.392c-.214.214-.5.321-.786.321z"/></svg>

Before

Width:  |  Height:  |  Size: 400 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M24.037 7.963q3.305 0 5.634 2.366T32 16t-2.329 5.671-5.634 2.366h-6.46v-3.08h6.46q2.028 0 3.493-1.465t1.465-3.493-1.465-3.493-3.493-1.465h-6.46v-3.08h6.46zM9.615 17.578v-3.155h12.77v3.155H9.615zM3.005 16q0 2.028 1.465 3.493t3.493 1.465h6.46v3.08h-6.46q-3.305 0-5.634-2.366T0 16.001t2.329-5.671 5.634-2.366h6.46v3.08h-6.46q-2.028 0-3.493 1.465t-1.465 3.493z"/></svg>

Before

Width:  |  Height:  |  Size: 472 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M.001 5.334h31.998v3.583H.001V5.334zm0 12.416v-3.5h31.998v3.5H.001zm0 8.916v-3.583h31.998v3.583H.001z"/></svg>

Before

Width:  |  Height:  |  Size: 217 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 41.33 41.33"><path d="M22.615 19.384l2.894 2.894v1.413H2.49v-1.413l2.894-2.894V12.25q0-3.365 1.716-5.856t4.745-3.231v-1.01q0-.875.606-1.514T13.999 0t1.548.639.606 1.514v1.01q3.029.74 4.745 3.231t1.716 5.856v7.134zM14 27.999q-1.211 0-2.053-.808t-.841-2.019h5.788q0 1.144-.875 1.986T14 27.999z"/></svg>

Before

Width:  |  Height:  |  Size: 385 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 41.33 41.33"><path d="M28 12.62h-9.793V8.414h-2.826v11.173h2.826v-4.206H28V26.62h-9.793v-4.206H12.62v-14H9.794v4.206H.001V1.381h9.793v4.206h8.413V1.381H28V12.62z"/></svg>

Before

Width:  |  Height:  |  Size: 255 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M16 20.023q5.052 0 10.526 2.199t5.473 5.754v4.023H0v-4.023q0-3.555 5.473-5.754t10.526-2.199zM16 16q-3.275 0-5.614-2.339T8.047 8.047t2.339-5.661T16 0t5.614 2.386 2.339 5.661-2.339 5.614T16 16z"/></svg>

Before

Width:  |  Height:  |  Size: 307 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M11.925 20.161q3.432 0 5.834-2.402t2.402-5.834-2.402-5.834-5.834-2.402-5.834 2.402-2.402 5.834 2.402 5.834 5.834 2.402zm10.981 0L32 29.255 29.255 32l-9.094-9.094v-1.458l-.515-.515q-3.26 2.831-7.721 2.831-4.976 0-8.45-3.432T.001 11.925t3.474-8.45 8.45-3.474 8.407 3.474 3.432 8.45q0 1.802-.858 4.075t-1.973 3.646l.515.515h1.458z"/></svg>

Before

Width:  |  Height:  |  Size: 443 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 41.33 41.33"><path d="M22.167 15.166V3.5h-8.166v20.726c.93-.492 2.424-1.349 3.883-2.497 1.95-1.531 4.284-3.919 4.284-6.562zm3.499-13.999v14c0 7.674-10.737 12.523-11.192 12.724-.146.073-.31.109-.474.109s-.328-.036-.474-.109c-.456-.201-11.192-5.049-11.192-12.724v-14C2.334.529 2.863 0 3.501 0H24.5c.638 0 1.167.529 1.167 1.167z"/></svg>

Before

Width:  |  Height:  |  Size: 419 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 41.33 41.33"><path d="M6.606 7.549c0-1.047-.84-1.887-1.887-1.887s-1.887.84-1.887 1.887.84 1.887 1.887 1.887 1.887-.84 1.887-1.887zm15.732 8.493c0 .501-.206.988-.546 1.327l-7.239 7.254c-.354.339-.84.546-1.342.546s-.988-.206-1.327-.546L1.342 14.066C.59 13.329 0 11.899 0 10.852V4.718a1.9 1.9 0 011.887-1.887h6.134c1.047 0 2.477.59 3.229 1.342L21.792 14.7c.339.354.546.84.546 1.342zm5.661 0c0 .501-.206.988-.546 1.327l-7.239 7.254c-.354.339-.84.546-1.342.546-.767 0-1.15-.354-1.651-.87l6.93-6.93c.339-.339.546-.826.546-1.327s-.206-.988-.546-1.342L13.609 4.173c-.752-.752-2.182-1.342-3.229-1.342h3.303c1.047 0 2.477.59 3.229 1.342L27.454 14.7c.339.354.546.84.546 1.342z"/></svg>

Before

Width:  |  Height:  |  Size: 759 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 37.33 37.33"><path d="M5.965 10.526V6.035L0 12l5.965 5.965v-4.491H24v-2.947H5.965z"/></svg>

Before

Width:  |  Height:  |  Size: 176 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M25.875 28.25L22.125 32 6.126 16.001 22.125.002l3.75 3.75-12.25 12.25z"/></svg>

Before

Width:  |  Height:  |  Size: 186 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-6.67 -6.67 45.33 45.33"><path d="M6.125 28.25L18.375 16 6.125 3.75 9.875 0l15.999 15.999L9.875 31.998z"/></svg>

Before

Width:  |  Height:  |  Size: 185 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.67 -2.67 33.33 33.33"><path d="M15.905 13.355c.189 1.444-1.564 2.578-2.784 1.839-1.375-.602-1.375-2.784-.034-3.403 1.151-.705 2.818.223 2.818 1.564zm1.907-.361c-.309-2.44-3.076-4.056-5.328-3.042-1.426.636-2.389 2.148-2.32 3.747.086 2.097 2.08 3.815 4.176 3.626s3.729-2.234 3.472-4.331zm4.108-9.315c-.756-.997-2.045-1.169-3.179-1.358-3.214-.516-6.513-.533-9.727.034-1.066.172-2.269.361-2.939 1.323 1.1 1.031 2.664 1.186 4.073 1.358 2.544.327 5.156.344 7.699.017 1.426-.172 3.008-.309 4.073-1.375zm.979 17.788c-.481 1.684-.206 3.953-1.994 4.932-3.076 1.701-6.806 1.89-10.191 1.289-1.787-.327-3.884-.894-4.864-2.578-.43-1.65-.705-3.334-.98-5.018l.103-.275.309-.155c5.121 3.386 12.288 3.386 17.427 0 .808.241.206 1.22.189 1.805zM26.01 4.951c-.584 3.764-1.255 7.51-1.908 11.257-.189 1.1-1.255 1.719-2.148 2.183-3.214 1.615-6.96 1.89-10.483 1.512-2.389-.258-4.829-.894-6.771-2.389-.911-.705-.911-1.908-1.083-2.922-.602-3.523-1.289-7.046-1.719-10.604.206-1.547 1.942-2.217 3.231-2.698C6.848.654 8.686.362 10.508.19c3.884-.378 7.854-.241 11.618.859 1.341.395 2.784.945 3.695 2.097.412.533.275 1.203.189 1.805z"/></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.67 -2.67 33.33 33.33"><path d="M27.472 12.753L15.247.529a1.803 1.803 0 00-2.55 0l-2.84 2.84 2.137 2.137a2.625 2.625 0 013.501 3.501l3.499 3.499a2.625 2.625 0 11-1.237 1.237l-3.499-3.499c-.083.04-.169.075-.257.106v7.3a2.626 2.626 0 11-1.75 0v-7.3a2.626 2.626 0 01-1.494-3.607L8.62 4.606l-8.09 8.09a1.805 1.805 0 000 2.551l12.225 12.224a1.803 1.803 0 002.55 0l12.168-12.168a1.805 1.805 0 000-2.551z"/></svg>

Before

Width:  |  Height:  |  Size: 481 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.67 -2.67 33.33 33.33"><path d="M1.629 11.034L14 26.888.442 17.048a1.09 1.09 0 01-.39-1.203l1.578-4.811zm7.217 0h10.309l-5.154 15.854zM5.753 1.475l3.093 9.559H1.63l3.093-9.559a.548.548 0 011.031 0zm20.618 9.559l1.578 4.811c.141.437-.016.922-.39 1.203l-13.558 9.84 12.371-15.854zm0 0h-7.216l3.093-9.559a.548.548 0 011.031 0z"/></svg>

Before

Width:  |  Height:  |  Size: 407 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.29 -2.29 32.57 32.57"><path d="M14 21.435q3.079 0 5.257-2.178T21.435 14t-2.178-5.257T14 6.565q-1.51 0-3.079.697 1.917.871 3.108 2.701T15.22 14t-1.191 4.037-3.108 2.701q1.568.697 3.079.697zm9.933-11.559L27.999 14l-4.066 4.124v5.809h-5.809L14 27.999l-4.124-4.066H4.067v-5.809L.001 14l4.066-4.124V4.067h5.809L14 .001l4.124 4.066h5.809v5.809z"/></svg>

Before

Width:  |  Height:  |  Size: 422 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.29 -2.29 32.57 32.57"><path d="M14 21.435q3.079 0 5.257-2.178T21.435 14t-2.178-5.257T14 6.565 8.743 8.743 6.565 14t2.178 5.257T14 21.435zm9.933-3.311v5.809h-5.809L14 27.999l-4.124-4.066H4.067v-5.809L.001 14l4.066-4.124V4.067h5.809L14 .001l4.124 4.066h5.809v5.809L27.999 14z"/></svg>

Before

Width:  |  Height:  |  Size: 357 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.29 -2.29 32.57 32.57"><path d="M16.846 18.938h2.382L15.22 7.785h-2.44L8.772 18.938h2.382l.871-2.44h3.95zm7.087-9.062L27.999 14l-4.066 4.124v5.809h-5.809L14 27.999l-4.124-4.066H4.067v-5.809L.001 14l4.066-4.124V4.067h5.809L14 .001l4.124 4.066h5.809v5.809zm-11.385 4.937L14 10.282l1.452 4.531h-2.904z"/></svg>

Before

Width:  |  Height:  |  Size: 381 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.29 -2.29 32.57 32.57"><path d="M3.281 5.36L14 16.079 24.719 5.36 28 8.641l-14 14-14-14z"/></svg>

Before

Width:  |  Height:  |  Size: 171 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.29 -2.29 32.57 32.57"><path d="M24.719 22.64L14 11.921 3.281 22.64 0 19.359l14-14 14 14z"/></svg>

Before

Width:  |  Height:  |  Size: 172 B

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-2.29 -2.29 32.57 32.57"><path d="M24.003 15.695v8.336c0 .608-.504 1.111-1.111 1.111h-6.669v-6.669h-4.446v6.669H5.108a1.119 1.119 0 01-1.111-1.111v-8.336c0-.035.017-.069.017-.104L14 7.359l9.986 8.232a.224.224 0 01.017.104zm3.873-1.198l-1.077 1.285a.578.578 0 01-.365.191h-.052a.547.547 0 01-.365-.122L14 5.831 1.983 15.851a.594.594 0 01-.417.122.578.578 0 01-.365-.191L.124 14.497a.57.57 0 01.069-.781L12.679 3.314c.729-.608 1.91-.608 2.64 0l4.237 3.543V3.471c0-.313.243-.556.556-.556h3.334c.313 0 .556.243.556.556v7.085l3.803 3.161c.226.191.26.556.069.781z"/></svg>

Before

Width:  |  Height:  |  Size: 638 B

View File

@ -1,21 +1,31 @@
import { applyTheme } from "./darkmode"
import { createCopyButton } from "./copycode.js"
import Clipboard from "clipboard"
;(() => {
applyTheme()
})()
document.addEventListener("DOMContentLoaded", function (event) {
var clipboard = new ClipboardJS(".clip");
let clipboard = new Clipboard(".clip")
clipboard.on("success", function (e) {
const trigger = e.trigger;
const trigger = e.trigger
if (trigger.hasAttribute("data-copy-feedback")) {
trigger.classList.add("gdoc-post__codecopy--success");
trigger.querySelector(".icon.copy").classList.add("hidden");
trigger.querySelector(".icon.check").classList.remove("hidden");
trigger.classList.add("gdoc-post__codecopy--success")
trigger.querySelector(".icon.copy").classList.add("hidden")
trigger.querySelector(".icon.check").classList.remove("hidden")
setTimeout(function () {
trigger.classList.remove("gdoc-post__codecopy--success");
trigger.querySelector(".icon.copy").classList.remove("hidden");
trigger.querySelector(".icon.check").classList.add("hidden");
}, 3000);
trigger.classList.remove("gdoc-post__codecopy--success")
trigger.querySelector(".icon.copy").classList.remove("hidden")
trigger.querySelector(".icon.check").classList.add("hidden")
}, 3000)
}
e.clearSelection();
});
});
e.clearSelection()
})
document.querySelectorAll(".highlight").forEach((highlightDiv) => createCopyButton(highlightDiv))
})

5
src/js/config.js Normal file
View File

@ -0,0 +1,5 @@
export const DARK_MODE = "dark"
export const LIGHT_MODE = "light"
export const AUTO_MODE = "auto"
export const THEME = "hugo-geekdoc"
export const TOGGLE_MODES = [AUTO_MODE, DARK_MODE, LIGHT_MODE]

View File

@ -1,34 +1,23 @@
function createCopyButton(highlightDiv) {
const button = document.createElement("span");
export function createCopyButton(highlightDiv) {
const button = document.createElement("span")
let selector = "pre > code"
if (highlightDiv.querySelector(".lntable")) {
selector = ".lntable .lntd:last-child pre > code";
} else {
selector = "pre > code";
selector = ".lntable .lntd:last-child pre > code"
}
const codeToCopy = highlightDiv.querySelector(selector).innerText.trim();
const codeToCopy = highlightDiv.querySelector(selector).innerText.trim()
button.classList.add(
"flex",
"align-center",
"justify-center",
"clip",
"gdoc-post__codecopy"
);
button.type = "button";
button.classList.add("flex", "align-center", "justify-center", "clip", "gdoc-post__codecopy")
button.type = "button"
button.innerHTML =
'<svg class="icon copy"><use xlink:href="#gdoc_copy"></use></svg>' +
'<svg class="icon check hidden"><use xlink:href="#gdoc_check"></use></svg>';
button.setAttribute("data-clipboard-text", codeToCopy);
button.setAttribute("data-copy-feedback", "Copied!");
button.setAttribute("role", "button");
button.setAttribute("aria-label", "Copy");
'<svg class="icon check hidden"><use xlink:href="#gdoc_check"></use></svg>'
button.setAttribute("data-clipboard-text", codeToCopy)
button.setAttribute("data-copy-feedback", "Copied!")
button.setAttribute("role", "button")
button.setAttribute("aria-label", "Copy")
highlightDiv.classList.add("gdoc-post__codecontainer");
highlightDiv.insertBefore(button, highlightDiv.firstChild);
highlightDiv.classList.add("gdoc-post__codecontainer")
highlightDiv.insertBefore(button, highlightDiv.firstChild)
}
document
.querySelectorAll(".highlight")
.forEach((highlightDiv) => createCopyButton(highlightDiv));

View File

@ -1,51 +1,53 @@
const DARK_MODE = "dark";
const LIGHT_MODE = "light";
const AUTO_MODE = "auto";
const THEME = "hugo-geekdoc";
import Storage from "store2"
const TOGGLE_MODES = [AUTO_MODE, DARK_MODE, LIGHT_MODE];
import { TOGGLE_MODES, THEME, AUTO_MODE } from "./config.js"
(applyTheme = function (init = true) {
let html = document.documentElement;
let currentMode = TOGGLE_MODES.includes(localStorage.getItem(THEME))
? localStorage.getItem(THEME)
: AUTO_MODE;
document.addEventListener("DOMContentLoaded", (event) => {
const darkModeToggle = document.getElementById("gdoc-dark-mode")
html.setAttribute("class", "color-toggle-" + currentMode);
localStorage.setItem(THEME, currentMode);
darkModeToggle.onclick = function () {
let lstore = Storage.namespace(THEME)
let currentMode = lstore.get("color-mode")
let nextMode = toggle(TOGGLE_MODES, currentMode)
lstore.set("color-mode", TOGGLE_MODES[nextMode])
applyTheme(false)
}
})
export function applyTheme(init = true) {
if (Storage.isFake()) return
let lstore = Storage.namespace(THEME)
let html = document.documentElement
let currentMode = TOGGLE_MODES.includes(lstore.get("color-mode"))
? lstore.get("color-mode")
: AUTO_MODE
html.setAttribute("class", "color-toggle-" + currentMode)
lstore.set("color-mode", currentMode)
if (currentMode === AUTO_MODE) {
html.removeAttribute("color-mode");
html.removeAttribute("color-mode")
} else {
html.setAttribute("color-mode", currentMode);
html.setAttribute("color-mode", currentMode)
}
if (!init) {
// Reload required to re-initialise e.g. Mermaid with the new theme and re-parse the Mermaid code blocks.
location.reload();
// Reload required to re-initialise e.g. Mermaid with the new theme
// and re-parse the Mermaid code blocks.
location.reload()
}
})();
document.addEventListener("DOMContentLoaded", (event) => {
const darkModeToggle = document.getElementById("gdoc-dark-mode");
darkModeToggle.onclick = function () {
let currentMode = localStorage.getItem(THEME);
let nextMode = toggle(TOGGLE_MODES, currentMode);
localStorage.setItem(THEME, TOGGLE_MODES[nextMode]);
applyTheme(false);
};
});
}
function toggle(list = [], value) {
current = list.indexOf(value);
max = list.length - 1;
next = 0;
let current = list.indexOf(value)
let max = list.length - 1
let next = 0
if (current < max) {
next = current + 1;
next = current + 1
}
return next;
return next
}

View File

@ -7,30 +7,25 @@
* strings for iteratees.
*/
const groupBy = (e, ...t) => {
export const groupBy = (e, ...t) => {
let r = e.map((e) => t.map((t) => t(e))),
a = {};
a = {}
return (
r.forEach((t, r) => {
let l = (_simpleAt(a, t) || []).concat([e[r]]);
_simpleSet(a, t, l);
let l = (_simpleAt(a, t) || []).concat([e[r]])
_simpleSet(a, t, l)
}),
a
);
)
},
_isPlainObject = (e) =>
null != e && "object" == typeof e && e.constructor == Object,
_isPlainObject = (e) => null != e && "object" == typeof e && e.constructor == Object,
_parsePath = (e) => (Array.isArray(e) ? e : `${e}`.split(".")),
_simpleAt = (e, t) =>
_parsePath(t).reduce(
(e, t) => (null != e && e.hasOwnProperty(t) ? e[t] : void 0),
e
),
_parsePath(t).reduce((e, t) => (null != e && e.hasOwnProperty(t) ? e[t] : void 0), e),
_simpleSet = (e, t, r) =>
_parsePath(t).reduce((e, t, a, l) => {
let s = a === l.length - 1;
let s = a === l.length - 1
return (
(e.hasOwnProperty(t) && (s || _isPlainObject(e[t]))) || (e[t] = {}),
s ? (e[t] = r) : e[t]
);
}, e);
(e.hasOwnProperty(t) && (s || _isPlainObject(e[t]))) || (e[t] = {}), s ? (e[t] = r) : e[t]
)
}, e)

View File

@ -1,3 +0,0 @@
document.addEventListener("DOMContentLoaded", function () {
renderMathInElement(document.body);
});

9
src/js/katex.js Normal file
View File

@ -0,0 +1,9 @@
import "katex/dist/katex.css"
document.addEventListener("DOMContentLoaded", function () {
import("katex/dist/contrib/auto-render")
.then(({ default: renderMathInElement }) => {
renderMathInElement(document.body)
})
.catch((error) => console.error(error))
})

View File

@ -1,23 +0,0 @@
document.addEventListener("DOMContentLoaded", function (event) {
let currentMode = localStorage.getItem(THEME);
let darkModeQuery = window.matchMedia("(prefers-color-scheme: dark)");
let primaryColor = "#ececff";
let darkMode = false;
if (
currentMode === DARK_MODE ||
(currentMode === AUTO_MODE && darkModeQuery.matches)
) {
primaryColor = "#6C617E";
darkMode = true;
}
mermaid.initialize({
flowchart: { useMaxWidth: true },
theme: "base",
themeVariables: {
darkMode: darkMode,
primaryColor: primaryColor,
},
});
});

29
src/js/mermaid.js Normal file
View File

@ -0,0 +1,29 @@
import Storage from "store2"
import { DARK_MODE, THEME, AUTO_MODE } from "./config.js"
document.addEventListener("DOMContentLoaded", function (event) {
let lstore = Storage.namespace(THEME)
let currentMode = lstore.get("color-mode")
let darkModeQuery = window.matchMedia("(prefers-color-scheme: dark)")
let primaryColor = "#ececff"
let darkMode = false
if (currentMode === DARK_MODE || (currentMode === AUTO_MODE && darkModeQuery.matches)) {
primaryColor = "#6C617E"
darkMode = true
}
import("mermaid")
.then(({ default: md }) => {
md.initialize({
flowchart: { useMaxWidth: true },
theme: "base",
themeVariables: {
darkMode: darkMode,
primaryColor: primaryColor
}
})
})
.catch((error) => console.error(error))
})

200
src/js/search.js Normal file
View File

@ -0,0 +1,200 @@
const { groupBy } = require("./groupBy")
const FlexSearch = require("flexsearch")
const Ajv = require("ajv")
document.addEventListener("DOMContentLoaded", function (event) {
const ajv = new Ajv()
const input = document.querySelector("#gdoc-search-input")
const results = document.querySelector("#gdoc-search-results")
const configSchema = {
type: "object",
properties: {
dataFile: {
type: "string"
},
indexConfig: {
type: ["object", "null"]
},
showParent: {
type: "boolean"
}
},
additionalProperties: false
}
getJson("/searchconfig.json", function (searchConfig) {
const configValidate = ajv.compile(configSchema)
const valid = configValidate(searchConfig)
if (!valid)
throw AggregateError(
configValidate.errors.map(
(err) =>
new Error(["Validation error:", err.instancePath, err.keyword, err.message].join(" "))
),
"Schema validation failed"
)
if (input) {
input.addEventListener("focus", () => {
init(input, searchConfig)
})
input.addEventListener("keyup", () => {
search(input, results, searchConfig)
})
}
})
})
function init(input, searchConfig) {
input.removeEventListener("focus", init)
const indexCfgDefaults = {
tokenize: "forward"
}
const indexCfg = searchConfig.indexConfig ? searchConfig.indexConfig : indexCfgDefaults
const dataUrl = searchConfig.dataFile
indexCfg.document = {
key: "id",
index: ["title", "content"],
store: ["title", "href", "parent"]
}
const index = new FlexSearch.Document(indexCfg)
window.geekdocSearchIndex = index
getJson(dataUrl, function (data) {
data.forEach((obj) => {
window.geekdocSearchIndex.add(obj)
})
})
}
function search(input, results, searchConfig) {
const searchCfg = {
enrich: true,
limit: 10
}
while (results.firstChild) {
results.removeChild(results.firstChild)
}
if (!input.value) {
return results.classList.remove("has-hits")
}
let searchHits = flattenHits(window.geekdocSearchIndex.search(input.value, searchCfg))
if (searchHits.length < 1) {
return results.classList.remove("has-hits")
}
results.classList.add("has-hits")
if (searchConfig.showParent === true) {
searchHits = groupBy(searchHits, (hit) => hit.parent)
}
const items = []
if (searchConfig.showParent === true) {
for (const section in searchHits) {
const item = document.createElement("li"),
title = item.appendChild(document.createElement("span")),
subList = item.appendChild(document.createElement("ul"))
title.textContent = section
createLinks(searchHits[section], subList)
items.push(item)
}
} else {
const item = document.createElement("li"),
title = item.appendChild(document.createElement("span")),
subList = item.appendChild(document.createElement("ul"))
title.textContent = "Results"
createLinks(searchHits, subList)
items.push(item)
}
items.forEach((item) => {
results.appendChild(item)
})
}
/**
* Creates links to given fields and either returns them in an array or attaches them to a target element
* @param {Object} fields Page to which the link should point to
* @param {HTMLElement} target Element to which the links should be attatched
* @returns {Array} If target is not specified, returns an array of built links
*/
function createLinks(pages, target) {
const items = []
for (const page of pages) {
const item = document.createElement("li"),
entry = item.appendChild(document.createElement("span")),
a = entry.appendChild(document.createElement("a"))
entry.classList.add("flex")
a.href = page.href
a.textContent = page.title
a.classList.add("gdoc-search__entry")
if (target) {
target.appendChild(item)
continue
}
items.push(item)
}
return items
}
function fetchErrors(response) {
if (!response.ok) {
throw Error("Failed to fetch '" + response.url + "': " + response.statusText)
}
return response
}
function getJson(src, callback) {
fetch(src)
.then(fetchErrors)
.then((response) => response.json())
.then((json) => callback(json))
.catch(function (error) {
if (error instanceof AggregateError) {
console.error(error.message)
error.errors.forEach((element) => {
console.error(element)
})
} else {
console.error(error)
}
})
}
function flattenHits(results) {
const items = []
const map = new Map()
for (const field of results) {
for (const page of field.result) {
if (!map.has(page.doc.href)) {
map.set(page.doc.href, true)
items.push(page.doc)
}
}
}
return items
}

Some files were not shown because too many files have changed in this diff Show More