Merge pull request 'develop' (#14) from develop into main
All checks were successful
Main / build-deploy (push) Successful in 35s

Reviewed-on: #14
This commit is contained in:
Stephan Hadan 2025-02-18 12:50:45 +01:00
commit 109b50a790
22 changed files with 2247 additions and 2 deletions

View file

@ -307,8 +307,8 @@ Ein **Betriebssystem**, auch **OS** (von englisch *operating system*) genannt, i
### Continuous Integration / Continuous Delivery (CI/CD) ### Continuous Integration / Continuous Delivery (CI/CD)
* [GitHub Actions](https://docs.github.com/de/actions) - Mit **GitHub Actions** kannst du deine Softwareentwicklungs-Workflows direkt in Ihrem Repository automatisieren, anpassen und ausführen. Actions wurden ebenso für Forgejo und Gitea implementiert und sind weitestgehendst kompatibel ![im Businesseinsatz][Business Icon] ![im Heimeinsatz][Home Icon] ![favorisiert][Favorite Icon] * [GitHub Actions](https://docs.github.com/de/actions) - Mit **GitHub Actions** kannst du deine Softwareentwicklungs-Workflows direkt in Ihrem Repository automatisieren, anpassen und ausführen. Actions wurden ebenso für [Forgejo](https://forgejo.org/docs/latest/user/actions/) und [Gitea](https://docs.gitea.com/usage/actions/overview) implementiert und sind weitestgehendst kompatibel ![im Businesseinsatz][Business Icon] ![im Heimeinsatz][Home Icon] ![favorisiert][Favorite Icon]
* [GitLab CI]() - Gitlab's integrierte, voll funktionsfähige CI/CD-Lösung. ![im Businesseinsatz][Business Icon] * [GitLab CI](https://docs.gitlab.com/ci/) - Gitlab's integrierte, voll funktionsfähige CI/CD-Lösung. ![im Businesseinsatz][Business Icon]
* [GoCD](https://www.gocd.org/) - **GoCD** ist ein freier & quelloffener CI/CD-Server. Modellieren und visualisieren komplexe Arbeitsabläufe auf einfache Weise. ![im Businesseinsatz][Business Icon] ![favorisiert][Favorite Icon] * [GoCD](https://www.gocd.org/) - **GoCD** ist ein freier & quelloffener CI/CD-Server. Modellieren und visualisieren komplexe Arbeitsabläufe auf einfache Weise. ![im Businesseinsatz][Business Icon] ![favorisiert][Favorite Icon]
* [Jenkins](https://www.jenkins.io/) - **Jenkins** ist ein erweiterbares, webbasiertes Software-System zur kontinuierlichen Integration von Software-Komponenten zu einem Anwendungsprogramm. ![im Businesseinsatz][Business Icon] ![favorisiert][Favorite Icon] * [Jenkins](https://www.jenkins.io/) - **Jenkins** ist ein erweiterbares, webbasiertes Software-System zur kontinuierlichen Integration von Software-Komponenten zu einem Anwendungsprogramm. ![im Businesseinsatz][Business Icon] ![favorisiert][Favorite Icon]
* [Woodpecker CI](https://woodpecker-ci.org/) - **Woodpecker** ist eine einfache, aber leistungsstarke CI/CD-Engine mit großer Erweiterbarkeit. ![im Heimeinsatz][Home Icon] ![favorisiert][Favorite Icon] * [Woodpecker CI](https://woodpecker-ci.org/) - **Woodpecker** ist eine einfache, aber leistungsstarke CI/CD-Engine mit großer Erweiterbarkeit. ![im Heimeinsatz][Home Icon] ![favorisiert][Favorite Icon]
@ -317,6 +317,7 @@ Ein **Betriebssystem**, auch **OS** (von englisch *operating system*) genannt, i
* [Budibase](https://budibase.com/) - **Budibase** ist eine Open-Source-Workflow-Plattform, die Ingenieuren Zeit und Energie für die Entwicklung von Anwendungen spart, die mit jeder Datenquelle integriert werden können und jeden Prozess beschleunigen. ![im Businesseinsatz][Business Icon] * [Budibase](https://budibase.com/) - **Budibase** ist eine Open-Source-Workflow-Plattform, die Ingenieuren Zeit und Energie für die Entwicklung von Anwendungen spart, die mit jeder Datenquelle integriert werden können und jeden Prozess beschleunigen. ![im Businesseinsatz][Business Icon]
* [NocoDB](https://nocodb.com/) - **NocoDB** ist der schnellste und einfachste Weg, Datenbanken online zu erstellen. ![im Heimeinsatz][Home Icon] ![favorisiert][Favorite Icon] * [NocoDB](https://nocodb.com/) - **NocoDB** ist der schnellste und einfachste Weg, Datenbanken online zu erstellen. ![im Heimeinsatz][Home Icon] ![favorisiert][Favorite Icon]
* [Rowy](https://www.rowy.io/) - Rowy ist eine Low-Code-Backend-Plattform. Verwalte Datenbanken über eine tabellenähnliche Benutzeroberfläche und erstelle Cloud-Funktionen in JS/TS, alles in Deinem Browser. ![versuchen][Bulb Icon]
* [SeaTable](https://seatable.io/) - **SeaTable** ist eine No-Code-Plattform, bei der Anwender ohne Programmiererfahrung selbst Geschäftsprozesse entwickeln und umsetzen können. **SeaTable** vereint dabei traditionelle Fähigkeiten einer Tabellenkalkulation wie Excel und ergänzt diese um vielfältige Funktionen zur Prozessautomatisierung und -visualisierung sowie einer vollumfänglichen API. ![im Businesseinsatz][Business Icon] ![im Heimeinsatz][Home Icon] ![favorisiert][Favorite Icon] * [SeaTable](https://seatable.io/) - **SeaTable** ist eine No-Code-Plattform, bei der Anwender ohne Programmiererfahrung selbst Geschäftsprozesse entwickeln und umsetzen können. **SeaTable** vereint dabei traditionelle Fähigkeiten einer Tabellenkalkulation wie Excel und ergänzt diese um vielfältige Funktionen zur Prozessautomatisierung und -visualisierung sowie einer vollumfänglichen API. ![im Businesseinsatz][Business Icon] ![im Heimeinsatz][Home Icon] ![favorisiert][Favorite Icon]
* [Microsoft Power Platform](https://microsoft.com/power-platform/) - **Microsoft Power Platform** ist eine Sammlung von Low-Code-Entwicklungstools, mit denen Benutzer benutzerdefinierte Geschäftsanwendungen erstellen, Arbeitsabläufe automatisieren und Daten analysieren können. Es bietet auch die Integration mit GitHub, Microsoft Azure, Microsoft Dynamics 365 und Microsoft Teams sowie anderen Microsoft- und Drittanbieteranwendungen. ![im Businesseinsatz][Business Icon] * [Microsoft Power Platform](https://microsoft.com/power-platform/) - **Microsoft Power Platform** ist eine Sammlung von Low-Code-Entwicklungstools, mit denen Benutzer benutzerdefinierte Geschäftsanwendungen erstellen, Arbeitsabläufe automatisieren und Daten analysieren können. Es bietet auch die Integration mit GitHub, Microsoft Azure, Microsoft Dynamics 365 und Microsoft Teams sowie anderen Microsoft- und Drittanbieteranwendungen. ![im Businesseinsatz][Business Icon]

View file

@ -17,6 +17,7 @@ menus:
url: https://git.hadan-it.com/public/techstack.hadan.de/issues url: https://git.hadan-it.com/public/techstack.hadan.de/issues
target: __blank target: __blank
theme: theme/default
#sideEffectFiles: #sideEffectFiles:
# - editor-plugin.md # - editor-plugin.md

View file

@ -0,0 +1,49 @@
markdown-style pre > .copied,
markdown-style [class*='language-'] .copied {
display: flex;
position: absolute;
cursor: pointer;
color: #a5afbb;
top: 6px;
right: 6px;
border-radius: 5px;
background: #82828226;
padding: 6px;
font-size: 12px;
transition: all 0.3s;
z-index: 10;
}
markdown-style pre > .copied:not(.active),
markdown-style [class*='language-'] .copied:not(.active) {
visibility: hidden;
}
markdown-style pre:hover > .copied,
markdown-style [class*='language-']:hover .copied {
visibility: visible;
}
markdown-style pre:hover > .copied:hover,
markdown-style [class*='language-']:hover .copied:hover {
background: #4caf50;
color: #fff;
}
markdown-style [class*='language-']:hover .copied:active,
markdown-style pre > .copied.active {
background: #2e9b33;
color: #fff;
}
markdown-style pre > .copied .octicon-copy,
markdown-style [class*='language-'] .copied .octicon-copy {
display: block;
}
markdown-style pre > .copied .octicon-check,
markdown-style [class*='language-'] .copied .octicon-check {
display: none;
}
markdown-style pre > .active .octicon-copy,
markdown-style [class*='language-'] .active .octicon-copy {
display: none;
}
markdown-style pre > .active .octicon-check,
markdown-style [class*='language-'] .active .octicon-check {
display: block;
}

View file

@ -0,0 +1,62 @@
.idoc-demo-warpper {
overflow: hidden;
min-height: 60px;
margin-bottom: 16px;
}
div.idoc-demo-warpper {
position: relative;
background-color: var(--color-canvas-subtle);
border-radius: 6px;
}
div.idoc-demo-warpper > pre {
padding: 16px;
overflow: auto;
display: block;
margin-bottom: 0 !important;
height: 100%;
}
div.idoc-demo-previw {
padding: 10px;
font-size: initial;
line-height: initial;
line-height: initial;
font-family: initial;
overflow: auto;
}
.idoc-demo-previw {
border: 0;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
background-color: var(--color-canvas-subtle);
border: 1px solid var(--color-border-default);
border-radius: 6px;
z-index: 9;
transition: left 0.3s cubic-bezier(1, 0, 1, 0);
}
.idoc-demo-previw.ishiden {
left: -100%;
}
button.idoc-toggle-previw {
user-select: none;
position: absolute;
z-index: 10;
border: transparent;
background-color: var(--color-border-default);
cursor: pointer;
font-size: 12px;
padding: 2px 5px;
border-radius: 3px;
bottom: 5px;
right: 5px;
}
button.idoc-toggle-previw:hover {
color: var(--color-theme-text);
}

338
theme/default/css/main.css Normal file
View file

@ -0,0 +1,338 @@
[data-color-mode*='dark'],
[data-color-mode*='dark'] body {
--color-header-bg: #3a3a3a8f;
--color-header-border: #21262d7a;
--color-hover: #ffffff1c;
--color-hoc-bg: #fffefe08;
--color-border-default: #d0d7de;
--color-accent-fg: #0969da;
--color-accent-emphasis: #0969da;
--color-danger-fg: #d1242f;
--color-danger-emphasis: #cf222e;
--color-attention-fg: #9a6700;
--color-attention-emphasis: #9a6700;
--color-done-fg: #8250df;
--color-done-emphasis: #8250df;
--color-success-fg: #1a7f37;
--color-success-emphasis: #1f883d;
}
[data-color-mode*='light'],
[data-color-mode*='light'] body {
--color-header-bg: #ffffff52;
--color-header-border: #0000001c;
--color-hover: #0000001a;
--color-hoc-bg: #00000008;
--color-border-default: #30363d;
--color-accent-fg: #58a6ff;
--color-accent-emphasis: #1f6feb;
--color-danger-fg: #f85149;
--color-danger-emphasis: #da3633;
--color-attention-fg: #d29922;
--color-attention-emphasis: #9e6a03;
--color-done-fg: #a371f7;
--color-done-emphasis: #8957e5;
--color-success-fg: #3fb950;
--color-success-emphasis: #238636;
}
*,
:after,
:before {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
margin: 0;
font-size: 14px;
font-family: -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
}
a {
text-decoration: none;
color: var(--color-accent-fg);
}
a:hover {
text-decoration: underline;
}
.warpper {
max-width: 960px;
margin: 0 auto;
}
.warpper dark-mode {
font-size: 18px;
}
markdown-style {
min-height: 60vh;
grid-area: main;
margin-bottom: 18px !important;
}
markdown-style img {
background-color: transparent !important;
}
.warpper-content {
padding: 0 20px;
padding-top: 32px;
margin-top: 48px;
display: grid;
grid-template-columns: minmax(0, 3.5fr) minmax(0, 15rem);
grid-template-areas: 'main toc';
grid-gap: 18px;
gap: 18px;
}
.warpper-content.sidebar {
grid-template-columns: 180px minmax(0, 3.5fr) minmax(0, 15rem);
grid-template-areas: 'sidebar main toc';
}
.warpper-content.notocs {
grid-template-columns: minmax(0, 3.5fr);
grid-template-areas: 'main';
}
.warpper-content.sidebar.notocs {
grid-template-columns: 180px minmax(0, 3.5fr);
grid-template-areas: 'sidebar main';
}
nav.tocs .is-position-fixed {
top: 58px !important;
max-height: calc(100% - 68px);
}
nav.tocs {
position: relative;
grid-area: toc;
}
nav.tocs p {
color: var(--color-fg-muted);
margin-bottom: 0;
}
nav.tocs a {
color: var(--color-fg-muted);
display: block;
padding: 0 5px;
}
nav.tocs .inner {
padding: 10px 10px 10px 10px;
background-color: var(--color-hoc-bg);
max-width: 240px;
width: 240px;
}
a.gototop {
position: fixed;
bottom: 10px;
right: 10px;
display: inline-block;
background: var(--color-theme-text);
padding: 5px;
border-radius: 5px;
z-index: 9999;
color: var(--color-theme-bg);
font-size: 10px;
opacity: 0;
transition: all 0.3s;
}
a.gototop:hover {
opacity: 1;
}
.header {
position: fixed;
width: 100%;
background: var(--color-header-bg);
backdrop-filter: saturate(180%) blur(0.4rem);
background-color: var(--color-header-bg);
border-bottom: 1px solid var(--color-header-border);
z-index: 99;
top: 0;
}
.header .inner {
display: flex;
justify-content: space-between;
min-height: 45px;
padding-left: 10px;
padding-right: 10px;
}
.header .logo {
font-weight: bold;
display: flex;
color: var(--color-theme-text);
align-items: center;
}
.header .logo:hover {
text-decoration: none;
}
.header .logo .title {
padding-left: 8px;
display: flex;
}
.header .logo .title sup {
margin-top: -5px;
padding-left: 2px;
font-weight: normal;
color: var(--color-fg-subtle);
}
.header .logo img,
.header .logo svg {
height: 26px;
display: block;
}
.header .content {
display: flex;
align-items: center;
}
.header .menu {
padding: 0;
margin: 0;
display: flex;
list-style: none;
padding-right: 10px;
}
.header .menu li {
display: flex;
align-items: center;
}
.header a {
color: var(--color-theme-text);
font-weight: bold;
}
.header .menu a {
padding: 3px 7px;
font-size: 14px;
border-radius: 2px;
}
.header .menu a.active {
background-color: var(--color-hover);
}
.header .github {
width: 18px;
height: 18px;
margin-right: 8px;
}
section.article-footer {
display: flex;
align-items: center;
font-size: 14px;
justify-content: space-between;
margin-top: 12px;
}
section.article-footer a {
display: flex;
align-items: center;
}
.edit-button {
padding-right: 8px;
}
.edit-button svg {
height: 15px;
margin-right: 6px;
}
section.article-footer .atime {
font-size: 12px;
color: var(--color-fg-muted);
margin-top: 2px;
}
.previous {
display: flex;
align-items: center;
justify-content: space-between;
grid-gap: 12px;
gap: 12px;
background-color: var(--color-canvas-subtle);
padding: 10px;
font-size: 14px;
border-radius: 5px;
margin-top: 26px;
}
.previous a {
display: flex;
align-items: center;
}
.previous a.prev svg {
margin-right: 3px;
}
.previous a.next svg {
margin-left: 3px;
}
.footer {
text-align: center;
border-top: 1px solid var(--color-header-border);
padding: 32px 0 110px 0;
color: var(--color-fg-muted);
font-size: 14px;
}
.markdown-alert {
border-left: 0.25em solid var(--borderColor-default, var(--color-border-default));
color: inherit;
margin-bottom: 16px;
padding: 0.5rem 1em;
}
.markdown-alert > :last-child {
margin-bottom: 0 !important;
}
.markdown-alert .markdown-alert-title {
align-items: center;
display: flex;
font-size: 14px;
font-weight: 500;
line-height: 1;
}
.markdown-alert .markdown-alert-title svg.octicon {
margin-right: 8px !important;
margin-right: var(--base-size-8, 8px) !important;
}
.markdown-alert.markdown-alert-note {
border-left-color: var(--borderColor-accent-emphasis, var(--color-accent-emphasis));
}
.markdown-alert.markdown-alert-note .markdown-alert-title {
color: var(--color-accent-fg);
color: var(--fgColor-accent, var(--color-accent-fg));
}
.markdown-alert.markdown-alert-tip {
border-left-color: var(--borderColor-success-emphasis, var(--color-success-emphasis));
}
.markdown-alert.markdown-alert-tip .markdown-alert-title {
color: var(--color-success-fg);
color: var(--fgColor-success, var(--color-success-fg));
}
.markdown-alert.markdown-alert-important {
border-left-color: var(--borderColor-done-emphasis, var(--color-done-emphasis));
}
.markdown-alert.markdown-alert-important .markdown-alert-title {
color: var(--color-done-fg);
color: var(--fgColor-done, var(--color-done-fg));
}
.markdown-alert.markdown-alert-warning {
border-left-color: var(--borderColor-attention-emphasis, var(--color-attention-emphasis));
}
.markdown-alert.markdown-alert-warning .markdown-alert-title {
color: var(--color-attention-fg);
color: var(--fgColor-attention, var(--color-attention-fg));
}
.markdown-alert.markdown-alert-caution {
border-left-color: var(--borderColor-danger-emphasis, var(--color-danger-emphasis));
}
.markdown-alert.markdown-alert-caution .markdown-alert-title {
color: var(--color-danger-fg);
color: var(--fgColor-danger, var(--color-danger-fg));
}

View file

@ -0,0 +1,52 @@
@media only screen and (min-width: 1024px) {
footer.article-footer,
.warpper {
max-width: 1200px;
}
}
@media screen and (max-width: 900px) {
.warpper-content {
grid-template-columns: minmax(0, 3.5fr);
grid-template-areas: 'main';
}
.warpper-content.sidebar {
grid-template-areas: 'sidebar main';
grid-template-columns: 180px minmax(0, 41rem);
}
nav.tocs {
display: none;
}
}
@media screen and (max-width: 600px) {
.warpper-content {
grid-template-columns: minmax(0, 3.5fr);
grid-template-areas: 'main';
}
.warpper-content.sidebar {
grid-template-areas: 'main';
grid-template-columns: minmax(0, 41rem);
}
nav.tocs,
.sidebar-border {
display: none;
}
}
@media print {
.header,
nav.tocs,
section.article-footer,
.sidebar-border,
.previous,
.footer,
a.gototop {
display: none;
}
.warpper-content {
margin: 0;
padding: 0;
display: initial;
}
}

View file

@ -0,0 +1,41 @@
.sidebar-border {
border-right: 1px solid var(--color-border-muted);
}
aside.sidebar {
min-width: 160px;
margin-left: -5px;
padding-bottom: 20px;
padding-right: 6px;
position: -webkit-sticky;
position: sticky;
top: 56px;
grid-area: sidebar;
overflow: auto;
max-height: calc(100vh - 56px);
padding-bottom: 36px;
}
aside.sidebar label:first-child {
padding-top: 0 !important;
}
aside.sidebar a:first-child {
margin-top: 0 !important;
}
aside.sidebar label {
font-size: 12px;
padding: 5px 0 3px 0;
display: block;
padding-left: 5px !important;
}
aside.sidebar a.active {
color: var(--color-prettylights-syntax-markup-inserted-text);
background-color: var(--color-hover);
}
aside.sidebar a {
display: block;
padding: 3px 5px 3px 5px;
border-radius: 3px;
margin: 3px 0;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}

View file

@ -0,0 +1,52 @@
.tocs {
line-height: 26px;
}
nav.tocs > .inner {
position: sticky;
top: 56px;
overflow: auto;
max-height: calc(100vh - 56px);
}
nav.tocs .inner > .tocs-list {
overflow: hidden;
position: relative;
}
.tocs .tocs-list li {
list-style: none;
}
.tocs-list {
margin: 0;
padding-left: 10px;
}
.tocs-list.is-collapsed {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s cubic-bezier(0, 1, 0, 1);
}
.tocs-list.is-collapsed.is-open {
max-height: 9999px;
transition: max-height 0.3s cubic-bezier(1, 0, 1, 0);
}
.tocs-link {
height: 100%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.tocs-link::before {
background-color: var(--color-border-default);
content: ' ';
display: inline-block;
height: inherit;
left: 0;
margin-top: -1px;
position: absolute;
width: 2px;
}
.tocs-link.is-active-link {
font-weight: 700;
}
.tocs-link.is-active-link::before {
background-color: #54bc4b;
}

40
theme/default/js/copy.js Normal file
View file

@ -0,0 +1,40 @@
/**
* https://github.com/uiwjs/copy-to-clipboard/blob/master/src/main.js
*/
function copyTextToClipboard(text, cb) {
const el = document.createElement('textarea');
el.value = text;
el.setAttribute('readonly', '');
el.style = {
position: 'absolute',
left: '-9999px',
};
document.body.appendChild(el);
const selected = document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;
el.select();
let isCopy = false;
try {
const successful = document.execCommand('copy');
isCopy = !!successful;
} catch (err) {
isCopy = false;
}
document.body.removeChild(el);
if (selected && document.getSelection) {
document.getSelection().removeAllRanges();
document.getSelection().addRange(selected);
}
cb && cb(isCopy);
}
function copied(target, str) {
target.classList.add('active');
const input = target.parentElement.querySelector('input');
if (input) {
copyTextToClipboard(input.value || '', function () {
setTimeout(() => {
target.classList.remove('active');
}, 2000);
});
}
}

View file

@ -0,0 +1,162 @@
/**
* @package @wcj/dark-mode@1.0.14
* Web Component that toggles dark mode 🌒
* Github: https://github.com/jaywcjlove/dark-mode.git
* Website: https://jaywcjlove.github.io/dark-mode
*
* Licensed under the MIT license.
* @license Copyright © 2022. Licensed under the MIT License
* @author kenny wong <wowohoo@qq.com>
*/
const t = document;
const e = '_dark_mode_theme_';
const s = 'permanent';
const o = 'colorschemechange';
const i = 'permanentcolorscheme';
const h = 'light';
const r = 'dark';
const n = (t, e, s = e) => {
Object.defineProperty(t, s, {
enumerable: true,
get() {
const t = this.getAttribute(e);
return t === null ? '' : t;
},
set(t) {
this.setAttribute(e, t);
},
});
};
const c = (t, e, s = e) => {
Object.defineProperty(t, s, {
enumerable: true,
get() {
return this.hasAttribute(e);
},
set(t) {
if (t) {
this.setAttribute(e, '');
} else {
this.removeAttribute(e);
}
},
});
};
class a extends HTMLElement {
static get observedAttributes() {
return ['mode', h, r, s];
}
LOCAL_NANE = e;
constructor() {
super();
this.t();
}
connectedCallback() {
n(this, 'mode');
n(this, r);
n(this, h);
c(this, s);
const a = localStorage.getItem(e);
if (a && [h, r].includes(a)) {
this.mode = a;
this.permanent = true;
}
if (this.permanent && !a) {
localStorage.setItem(e, this.mode);
}
const l = [h, r].includes(a);
if (this.permanent && a) {
this.o();
} else {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
this.mode = r;
this.o();
}
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) {
this.mode = h;
this.o();
}
}
if (!this.permanent && !l) {
window.matchMedia('(prefers-color-scheme: light)').onchange = (t) => {
this.mode = t.matches ? h : r;
this.o();
};
window.matchMedia('(prefers-color-scheme: dark)').onchange = (t) => {
this.mode = t.matches ? r : h;
this.o();
};
}
const d = new MutationObserver((s, h) => {
this.mode = t.documentElement.dataset.colorMode;
if (this.permanent && l) {
localStorage.setItem(e, this.mode);
this.i(i, { permanent: this.permanent });
}
this.h();
this.i(o, { colorScheme: this.mode });
});
d.observe(t.documentElement, { attributes: true });
this.i(o, { colorScheme: this.mode });
this.h();
}
attributeChangedCallback(t, s, o) {
if (t === 'mode' && s !== o && [h, r].includes(o)) {
const t = localStorage.getItem(e);
if (this.mode === t) {
this.mode = o;
this.h();
this.o();
} else if (this.mode && this.mode !== t) {
this.h();
this.o();
}
} else if ((t === h || t === r) && s !== o) {
this.h();
}
if (t === 'permanent' && typeof this.permanent === 'boolean') {
this.permanent ? localStorage.setItem(e, this.mode) : localStorage.removeItem(e);
}
}
o() {
t.documentElement.setAttribute('data-color-mode', this.mode);
}
h() {
this.icon.textContent = this.mode === h ? '🌒' : '🌞';
this.text.textContent = this.mode === h ? this.getAttribute(r) : this.getAttribute(h);
}
t() {
var s = this.attachShadow({ mode: 'open' });
this.label = t.createElement('span');
this.label.setAttribute('class', 'wrapper');
this.label.onclick = () => {
this.mode = this.mode === h ? r : h;
if (this.permanent) {
localStorage.setItem(e, this.mode);
}
this.o();
this.h();
};
s.appendChild(this.label);
this.icon = t.createElement('span');
this.label.appendChild(this.icon);
this.text = t.createElement('span');
this.label.appendChild(this.text);
const o = `\n[data-color-mode*='dark'], [data-color-mode*='dark'] body {\n color-scheme: dark;\n --color-theme-bg: #0d1117;\n --color-theme-text: #c9d1d9;\n background-color: var(--color-theme-bg);\n color: var(--color-theme-text);\n}\n\n[data-color-mode*='light'], [data-color-mode*='light'] body {\n color-scheme: light;\n --color-theme-bg: #fff;\n --color-theme-text: #24292f;\n background-color: var(--color-theme-bg);\n color: var(--color-theme-text);\n}`;
const i = '_dark_mode_style_';
const n = t.getElementById(i);
if (!n) {
var c = t.createElement('style');
c.id = i;
c.textContent = o;
t.head.appendChild(c);
}
var a = t.createElement('style');
a.textContent = `\n .wrapper { cursor: pointer; user-select: none; position: relative; }\n .wrapper > span + span { margin-left: .4rem; }\n `;
s.appendChild(a);
}
i(t, e) {
this.dispatchEvent(new CustomEvent(t, { bubbles: true, composed: true, detail: e }));
}
}
customElements.define('dark-mode', a);

View file

@ -0,0 +1,31 @@
const demo = document.querySelectorAll('.idoc-demo-warpper .idoc-demo-previw');
function getButton(elm, type = 'BUTTON') {
let btn;
do {
elm = elm.nextElementSibling;
if (elm.tagName === type) {
btn = elm;
elm = undefined;
break;
}
} while (elm);
return btn;
}
if (demo && demo.length > 0) {
demo.forEach((item) => {
if (item.previousElementSibling && item.previousElementSibling.tagName === 'INPUT') {
const button = getButton(item);
if (button) {
button.innerHTML = item.classList.contains('ishiden') ? 'Preview' : 'Show Code';
if (item.tagName === 'DIV') {
item.innerHTML = item.previousElementSibling.defaultValue;
}
button.onclick = () => {
item.classList.toggle('ishiden');
button.innerHTML = item.classList.contains('ishiden') ? 'Preview' : 'Show Code';
};
}
}
});
}

View file

@ -0,0 +1,34 @@
(() => {
const targetElement = document.documentElement;
const defaultTheme = targetElement.getAttribute('data-color-mode');
changeGiscusTheme(defaultTheme);
const observer = new MutationObserver((mutationsList, observer) => {
for (const mutation of mutationsList) {
if (mutation.type === 'attributes') {
const value = targetElement.getAttribute('data-color-mode');
changeGiscusTheme(value);
}
}
});
observer.observe(targetElement, {
attributes: true,
attributeOldValue: true,
});
function changeGiscusTheme(theme = 'light') {
const iframe = document.querySelector('.giscus-frame');
if (iframe) {
const config = {
giscus: {
setConfig: {
theme: theme.toLocaleLowerCase(),
},
},
};
iframe.contentWindow.postMessage(config, 'https://giscus.app');
const script = document.querySelector('script[data-script-id="giscus"]');
script.setAttribute('data-theme', theme);
}
}
})();

File diff suppressed because it is too large Load diff

132
theme/default/js/tocbot.js Normal file
View file

@ -0,0 +1,132 @@
(() => {
function debounce(fn, delay = 1000) {
let time = null;
function _debounce(...args) {
if (time !== null) clearTimeout(time);
time = setTimeout(() => fn.apply(this, args), delay);
}
return _debounce;
}
const scrollSmoothOffset = 56;
function updateScroll() {
const heading = document.getElementById(decodeURIComponent(location.hash.replace(/^#/, '')));
if (heading) {
document.scrollingElement.scrollTop = heading.offsetTop - scrollSmoothOffset + 3;
}
}
function preventClickHandle(selector) {
const mdContainer = document.querySelectorAll(selector);
if (mdContainer && mdContainer.length > 0) {
mdContainer.forEach((anchor) => {
anchor.addEventListener('click', (e) => {
e.preventDefault();
location.hash = anchor.getAttribute('href');
updateScroll();
updateAnchor();
tocsCollapse();
});
});
}
}
function tocButton() {
const tocElement = document.querySelector(`a.gototop`);
if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
tocElement.style.opacity = 0.5;
} else {
tocElement.style.opacity = 0;
}
}
function scrollListener(evn) {
const anchors = document.querySelectorAll('markdown-style a.anchor[href*="#"][aria-hidden]');
const scrollTop = evn && evn.target && evn.target.scrollingElement && evn.target.scrollingElement.scrollTop;
let element;
let index = 0;
anchors.forEach((anchor, idx) => {
if (anchor.offsetTop - scrollSmoothOffset < scrollTop || (idx === 0 && anchor.offsetTop > scrollTop)) {
element = anchor;
index = idx;
}
});
tocButton();
if (element) {
const tocElement = document.querySelector(`a.tocs-link[href='${decodeURIComponent(element.hash)}']`);
if (tocElement) {
updateAnchor(tocElement);
tocsCollapse(tocElement);
} else {
const first = document.querySelector('a.tocs-link[href*="#"]');
if (index === 0 && first) {
updateAnchor(first);
tocsCollapse(first);
}
}
}
}
document.addEventListener('scroll', debounce(scrollListener, 30), false);
function updateAnchor(element) {
const anchorContainer = document.querySelectorAll('.tocs aside.inner.toc a.tocs-link');
anchorContainer.forEach((tocanchor) => {
tocanchor.classList.remove('is-active-link');
});
const anchor = element || document.querySelector(`a.tocs-link[href='${decodeURIComponent(location.hash)}']`);
if (anchor) {
anchor.classList.add('is-active-link');
}
}
function tocsCollapse(element) {
const tocContainer = document.querySelector('nav.tocs > aside.inner.toc');
if (element) {
tocContainer.scrollTop = element.offsetTop;
}
const list = document.querySelectorAll('aside.toc ol.tocs-list');
list.forEach((item) => {
item.classList.remove('is-open');
});
if (element && element.nextElementSibling) {
element.nextElementSibling.classList.add('is-open');
}
isOpen(element);
}
function isOpen(element) {
if (!element) {
element = document.querySelector(`a.tocs-link[href='${decodeURIComponent(location.hash)}']`);
}
if (
element &&
element.parentElement &&
element.parentElement.tagName !== 'ASIDE' &&
!element.parentElement.classList.contains('toc')
) {
isOpen(element.parentElement);
if (element.parentElement.classList.contains('is-collapsed')) {
element.parentElement.classList.add('is-open');
}
}
}
preventClickHandle('markdown-style a.anchor[href*="#"][aria-hidden]');
preventClickHandle('.tocs aside.inner.toc a.tocs-link');
function updateSiderBarScroll() {
const siderBar = document.querySelector(".sidebar[role*='navigation']");
const siderAnchor = document.querySelector(".sidebar[role*='navigation'] a[class*='active']");
if (siderAnchor) {
siderBar.scrollTop = siderAnchor.offsetTop;
}
}
const timer = setTimeout(() => {
updateSiderBarScroll();
updateScroll();
updateAnchor();
tocsCollapse();
clearTimeout(timer);
}, 100);
})();

View file

@ -0,0 +1,18 @@
<%- include('partial/header'); %>
<%- include('partial/navigation'); %>
<div <%= element.wrapper %> class="warpper-content warpper <%= chapters && chapters.length > 0 ? 'sidebar' : ''%> <%= tocsTree && tocsTree.length > 0 ? '' : 'notocs'%>">
<%- include('partial/chapters'); %>
<markdown-style theme-auto-switch-disabled>
<%- html %>
<%- giscusScript %>
<% if (giscusScript) { %>
<script src="<%= RELATIVE_PATH %>js/giscus.js?v=<%=idocVersion%>"></script>
<% } %>
<%- include('partial/article-footer'); %>
</markdown-style>
<%- include('partial/tocs'); %>
</div>
<script src="<%= RELATIVE_PATH %>js/demo-preview.js?v=<%=idocVersion%>"></script>
<%- include('partial/footer'); %>

View file

@ -0,0 +1,16 @@
<%- include('previous'); %>
<% if (editButton && editButton.url && editButton.label) { %>
<section class="article-footer">
<a href="<%=editButton.url || '' %>" class="edit-button" target="_blank" rel="noopener noreferrer">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
</svg>
<span><%=editButton.label%></span>
</a>
<% if (fileStat && fileStat.mtimeStr) { %>
<span class="atime"><%= fileStat.mtimeStr %></span>
<% } %>
</section>
<% } %>

View file

@ -0,0 +1,17 @@
<% if (chapters && chapters.length > 0) {%>
<div class="sidebar-border">
<aside class="sidebar" role="navigation">
<div>
<% chapters.forEach((chapter) => { %>
<% if (chapter.isFolder) { %>
<label><%= chapter.label %></label>
<% } else if (chapter.href && /^https?:\/\//.test(chapter.href)) { %>
<a href="<%= chapter.href %>" target="_blank" class="<%- chapter.active ? 'active' : '' %>"><%= chapter.label %></a>
<% } else { %>
<a href="<%= chapter.href %>" class="<%- chapter.active ? 'active' : '' %>"><%= chapter.label %></a>
<% } %>
<% }) %>
</div>
</aside>
</div>
<% } %>

View file

@ -0,0 +1,10 @@
<% if (footer) { %>
<div class="footer warpper" <%= element.wrapper %>>
<%-footer%>
</div>
<% } %>
<script src="<%= RELATIVE_PATH %>js/tocbot.js?v=<%=idocVersion%>"></script>
</body>
</html>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %> <%= site.replace(/<\/?sup>/g, '') %> </title>
<% if (description) { %>
<meta name="description" content="<%= description %>">
<% }%>
<% if (keywords) { %>
<meta name="keywords" content="<%= keywords %>">
<% }%>
<% (meta || []).forEach((val) => { %>
<%- val %>
<% }) %>
<link rel="stylesheet" type="text/css" href="<%= RELATIVE_PATH %>css/main.css?v=<%=idocVersion%>">
<link rel="stylesheet" type="text/css" href="<%= RELATIVE_PATH %>css/tocbot.css?v=<%=idocVersion%>">
<link rel="stylesheet" type="text/css" href="<%= RELATIVE_PATH %>css/media.css?v=<%=idocVersion%>">
<link rel="stylesheet" type="text/css" href="<%= RELATIVE_PATH %>css/sidebar.css?v=<%=idocVersion%>">
<link rel="stylesheet" type="text/css" href="<%= RELATIVE_PATH %>css/copy.css?v=<%=idocVersion%>">
<link rel="stylesheet" type="text/css" href="<%= RELATIVE_PATH %>css/demo-preview.css?v=<%=idocVersion%>">
<% if (favicon.href) { %>
<link rel="icon" href="<%= RELATIVE_PATH %><%=favicon.href%>" type="image/x-icon">
<% } else if (favicon.base64) { %>
<link rel="icon" href="<%=favicon.base64%>" type="image/x-icon">
<% } %>
<script src="<%= RELATIVE_PATH %>js/copy.js?v=<%=idocVersion%>"></script>
<script src="<%= RELATIVE_PATH %>js/dark-mode.js?v=<%=idocVersion%>"></script>
<script src="<%= RELATIVE_PATH %>js/markdown-style.js?v=<%=idocVersion%>"></script>
<script defer src="https://analytics.hadan-it.com/script.js" data-website-id="cdc630d2-d94a-44ff-806e-01dc6cc445f7"></script>
</head>
<body id="idoctotop">
<a href="#idoctotop" class="gototop">top</a>

View file

@ -0,0 +1,29 @@
<header class="header">
<article class="inner warpper" <%= element.wrapper %>>
<a class="logo" href="<%= RELATIVE_PATH %>index.html">
<% if (logo.code) { %>
<%- logo.code %>
<%} else if(logo.href) { %>
<img alt="<%=site%> logo" src="<%= RELATIVE_PATH %><%=logo.href%>">
<%} else if (logo.base64) { %>
<img alt="<%=site%> logo" src="<%=logo.base64%>">
<% } %>
<span class="title"><%-site%></span>
</a>
<div class="content">
<ul class="menu">
<% menus.forEach(function(item) { %>
<li>
<a href="<%= item.url %>" target="<%- item.target || '' %>" class="<%- item.active ? 'active' : '' %>"> <%= item.name %> </a>
</li>
<% }); %>
</ul>
<% if (!!openSource && openSource) { %>
<a href="<%=openSource.url || openSource%>" target="_blank" rel="noopener noreferrer" title="Github" name="Github" class="github">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1L244 40.5a28.9 28.9 0 0 0 -40.8 0l-40.7 40.6 51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.2 199v121.9c25.3 12.5 22.3 41.9 9.1 55a34.3 34.3 0 0 1 -48.6 0c-17.6-17.6-11.1-46.9 11.3-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1a28.9 28.9 0 0 0 0 40.8l195.6 195.6a28.9 28.9 0 0 0 40.8 0l194.7-194.7a28.9 28.9 0 0 0 0-40.8z"/></svg>
</a>
<% } %>
<dark-mode permanent></dark-mode>
</div>
</article>
</header>

View file

@ -0,0 +1,30 @@
<% if ((page.prevPage && page.prevPage.href && page.prevPage.label) || (page.nextPage && page.nextPage.href && page.nextPage.label)) { %>
<div class="previous">
<% if (page.prevPage && page.prevPage.href && page.prevPage.label) { %>
<a class="prev" href="<%= page.prevPage.href %>">
<svg viewBox="0 0 1024 1024" width="16" height="16" fill="currentColor">
<path d="M842.666667 864c-8.533333 0-14.933333-2.133333-21.333334-8.533333l-341.333333-309.333334c-6.4-6.4-10.666667-14.933333-10.666667-23.466666 0-8.533333 4.266667-17.066667 10.666667-23.466667l341.333333-309.333333c12.8-12.8 34.133333-10.666667 44.8 2.133333 12.8 12.8 10.666667 34.133333-2.133333 44.8L548.266667 522.666667l315.733333 285.866666c12.8 10.666667 14.933333 32 2.133333 44.8-6.4 6.4-14.933333 10.666667-23.466666 10.666667z"></path>
<path d="M512 864c-8.533333 0-14.933333-2.133333-21.333333-8.533333L149.333333 546.133333c-6.4-6.4-10.666667-14.933333-10.666666-23.466666 0-8.533333 4.266667-17.066667 10.666666-23.466667L490.666667 189.866667c12.8-12.8 34.133333-10.666667 44.8 2.133333 12.8 12.8 10.666667 34.133333-2.133334 44.8L217.6 522.666667 533.333333 808.533333c12.8 12.8 14.933333 32 2.133334 44.8-6.4 6.4-14.933333 10.666667-23.466667 10.666667z"></path>
</svg>
<span>
<%= page.prevPage.label %>
</span>
</a>
<% } else { %>
<span></span>
<% } %>
<% if (page.nextPage && page.nextPage.href && page.nextPage.label) { %>
<a class="next" href="<%= page.nextPage.href %>">
<span>
<%= page.nextPage.label %>
</span>
<svg viewBox="0 0 1024 1024" width="16" height="16" fill="currentColor">
<path d="M544 522.666667c0-8.533333-4.266667-17.066667-10.666667-23.466667L192 189.866667c-12.8-12.8-34.133333-10.666667-44.8 2.133333-12.8 12.8-10.666667 34.133333 2.133333 44.8l315.733334 285.866667L149.333333 808.533333c-12.8 12.8-14.933333 32-2.133333 44.8 6.4 6.4 14.933333 10.666667 23.466667 10.666667 8.533333 0 14.933333-2.133333 21.333333-8.533333l341.333333-309.333334c6.4-6.4 10.666667-14.933333 10.666667-23.466666z"></path>
<path d="M864 499.2l-341.333333-309.333333c-12.8-12.8-34.133333-10.666667-44.8 2.133333-12.8 12.8-10.666667 34.133333 2.133333 44.8l315.733333 285.866667-315.733333 285.866666c-12.8 12.8-14.933333 32-2.133333 44.8 6.4 6.4 14.933333 10.666667 23.466666 10.666667 8.533333 0 14.933333-2.133333 21.333334-8.533333l341.333333-309.333334c6.4-6.4 10.666667-14.933333 10.666667-23.466666 0-8.533333-4.266667-17.066667-10.666667-23.466667z"></path>
</svg>
</a>
<% } else { %>
<span></span>
<% } %>
</div>
<% } %>

View file

@ -0,0 +1,49 @@
<% if (tocsTree && tocsTree.length > 0) { %>
<nav class="tocs">
<aside class="inner toc">
<ol class="tocs-list">
<% tocsTree.forEach((level2) => { %>
<li>
<a href="#<%= level2.href %>" class="tocs-link"><%= level2.label %></a>
<% if (level2.children && level2.children.length > 0) { %>
<ol class="tocs-list is-collapsed">
<% level2.children.forEach((level3) => { %>
<li>
<a href="#<%= level3.href %>" class="tocs-link"><%= level3.label %></a>
<% if (level3.children && level3.children.length > 0) { %>
<ol class="tocs-list is-collapsed">
<% level3.children.forEach((level4) => { %>
<li>
<a href="#<%= level4.href %>" class="tocs-link"><%= level4.label %></a>
<% if (level4.children && level4.children.length > 0) { %>
<ol class="tocs-list is-collapsed">
<% level4.children.forEach((level5) => { %>
<li>
<a href="#<%= level5.href %>" class="tocs-link"><%= level5.label %></a>
<% if (level5.children && level5.children.length > 0) { %>
<ol class="tocs-list is-collapsed">
<% level5.children.forEach((level6) => { %>
<li>
<a href="#<%= level6.href %>" class="tocs-link"><%= level6.label %></a>
</li>
<% }) %>
</ol>
<% }%>
</li>
<% }) %>
</ol>
<% }%>
</li>
<% }) %>
</ol>
<% }%>
</li>
<% }) %>
</ol>
<% }%>
</li>
<% }) %>
</ol>
</aside>
</nav>
<% } %>