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,12 +1,12 @@
<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>
</div>
<div class="flex align-center justify-center icon-grid__line icon-grid__line--text">
<span>#gdoc_{{ (replace . "_" "_<wbr>") | safeHTML }}</span>
</div>
<div class="flex align-center justify-center icon-grid__line">
<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>#{{ (replace $key "_" "_<wbr>") | safeHTML }}</span>
</div>
</div>
{{ end }}
{{ end }}
</div>

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,40 +1,40 @@
<!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) }}
<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">
<svg class="icon gdoc_cloud_off"><use xlink:href="#gdoc_cloud_off"></use></svg>
</div>
<div class="gdoc-error__message">
<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>.
</div>
</div>
<main class="gdoc-error flex-even">
<div class="flex align-center justify-center">
<div class="gdoc-error__icon">
<svg class="icon gdoc_cloud_off"><use xlink:href="#gdoc_cloud_off"></use></svg>
</div>
<div class="gdoc-error__message">
<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>.
</div>
</main>
</div>
</div>
</main>
{{ partial "site-footer" . }}
{{ 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,33 +12,38 @@
{{ 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 }}">
<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">
{{ partial "menu" . }}
</aside>
{{ 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) }}
<div class="gdoc-page">
{{ template "main" . }}
{{ partial "page-footer" . }}
</div>
</main>
{{ partial "site-footer" . }}
<main class="container flex flex-even">
{{ if $navEnabled }}
<aside class="gdoc-nav">
{{ partial "menu" . }}
</aside>
{{ end }}
<div class="gdoc-page">
{{ template "main" . }}
{{ partial "page-footer" . }}
</div>
</main>
{{ partial "site-footer" . }}
</div>
{{ partial "foot" . }}
</body>
</body>
</html>

View File

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

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

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"
/>