hexo-theme-gnix 6.0.2 → 6.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/layout/comment/twikoo.jsx +5 -5
- package/layout/common/article_cover.jsx +2 -6
- package/layout/common/head.jsx +6 -2
- package/layout/common/plugins.jsx +2 -2
- package/layout/common/scripts.jsx +17 -4
- package/layout/layout.jsx +5 -1
- package/layout/plugin/swup.jsx +8 -2
- package/layout/search/insight.jsx +1 -1
- package/package.json +1 -1
- package/source/css/default.css +45 -29
- package/source/css/optional/mermaid.css +123 -0
- package/source/js/host/swup/scripts-plugin.umd.min.js +2 -0
- package/source/js/main.js +63 -4
- package/source/js/mdit/mermaid.js +169 -0
- /package/source/js/{shiki → mdit}/shiki.js +0 -0
|
@@ -8,10 +8,9 @@ const {
|
|
|
8
8
|
class Twikoo extends Component {
|
|
9
9
|
render() {
|
|
10
10
|
const { envId, region, lang, jsUrl } = this.props;
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
`;
|
|
11
|
+
const configJs = `window.twikooConfig = { envId: '${envId}', ${
|
|
12
|
+
region ? `region: ${JSON.stringify(region)},` : ""
|
|
13
|
+
} ${lang ? `lang: ${JSON.stringify(lang)},` : ""} };`;
|
|
15
14
|
const lazy_load_css_script = lazy_load_css("/css/twikoo.css");
|
|
16
15
|
return (
|
|
17
16
|
<Fragment>
|
|
@@ -19,7 +18,8 @@ twikoo.init(window.twikooConfig);
|
|
|
19
18
|
<script
|
|
20
19
|
dangerouslySetInnerHTML={{ __html: lazy_load_css_script }}
|
|
21
20
|
></script>
|
|
22
|
-
<script
|
|
21
|
+
<script dangerouslySetInnerHTML={{ __html: configJs }}></script>
|
|
22
|
+
<script defer src={jsUrl}></script>
|
|
23
23
|
</Fragment>
|
|
24
24
|
);
|
|
25
25
|
}
|
|
@@ -10,13 +10,9 @@ module.exports = class extends Component {
|
|
|
10
10
|
|
|
11
11
|
return (
|
|
12
12
|
<a href={url_for(page.link || page.path)} class="cover-image">
|
|
13
|
+
<img class="cover-lqip" src={lqip_src} alt="placeholder" />
|
|
13
14
|
<img
|
|
14
|
-
class="cover-
|
|
15
|
-
src={lqip_src}
|
|
16
|
-
alt="placeholder"
|
|
17
|
-
/>
|
|
18
|
-
<img
|
|
19
|
-
class="fill"
|
|
15
|
+
class="cover-origin"
|
|
20
16
|
src={cover}
|
|
21
17
|
alt={page.title || cover}
|
|
22
18
|
srcset={imageSrcset}
|
package/layout/common/head.jsx
CHANGED
|
@@ -125,7 +125,10 @@ module.exports = class extends Component {
|
|
|
125
125
|
|
|
126
126
|
return (
|
|
127
127
|
<head>
|
|
128
|
-
<script
|
|
128
|
+
<script
|
|
129
|
+
data-swup-ignore-script
|
|
130
|
+
dangerouslySetInnerHTML={{ __html: themeInitScript }}
|
|
131
|
+
></script>
|
|
129
132
|
<meta charset="utf-8" />
|
|
130
133
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
131
134
|
{noIndex ? <meta name="robots" content="noindex" /> : null}
|
|
@@ -217,7 +220,7 @@ module.exports = class extends Component {
|
|
|
217
220
|
onload="this.onload=null;this.rel='stylesheet'"
|
|
218
221
|
/>
|
|
219
222
|
{/* Maple Mono CN */}
|
|
220
|
-
<link rel="preconnect" href="https://fontsapi.zeoseven.com"/>
|
|
223
|
+
<link rel="preconnect" href="https://fontsapi.zeoseven.com" />
|
|
221
224
|
<link
|
|
222
225
|
rel="preload"
|
|
223
226
|
as="style"
|
|
@@ -234,6 +237,7 @@ module.exports = class extends Component {
|
|
|
234
237
|
/>
|
|
235
238
|
{adsenseClientId ? (
|
|
236
239
|
<script
|
|
240
|
+
data-swup-ignore-script
|
|
237
241
|
data-ad-client={adsenseClientId}
|
|
238
242
|
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
|
|
239
243
|
async
|
|
@@ -12,8 +12,8 @@ module.exports = class extends Component {
|
|
|
12
12
|
return (
|
|
13
13
|
<Fragment>
|
|
14
14
|
{Object.keys(plugins).map((name) => {
|
|
15
|
-
// plugin is not enabled
|
|
16
|
-
if (!plugins[name]) {
|
|
15
|
+
// plugin is not enabled or is 'swup' (which is now built-in)
|
|
16
|
+
if (!plugins[name] || name === "swup") {
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
19
|
const Plugin = loadComponent(`plugin/${name}`);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const { Component, Fragment } = require("../../include/util/common");
|
|
2
2
|
const Plugins = require("./plugins");
|
|
3
|
+
const Swup = require("../plugin/swup");
|
|
3
4
|
|
|
4
5
|
module.exports = class extends Component {
|
|
5
6
|
render() {
|
|
@@ -14,18 +15,30 @@ module.exports = class extends Component {
|
|
|
14
15
|
helper={helper}
|
|
15
16
|
head={false}
|
|
16
17
|
/>
|
|
18
|
+
<Swup head={false} />
|
|
17
19
|
<script
|
|
20
|
+
data-swup-ignore-script
|
|
18
21
|
defer
|
|
19
22
|
src="/js/host/iconify-icon/3.0.2/iconify-icon.min.js"
|
|
20
23
|
></script>
|
|
21
|
-
<script defer src="/js/theme-selector.js"></script>
|
|
22
24
|
<script
|
|
25
|
+
data-swup-ignore-script
|
|
26
|
+
defer
|
|
27
|
+
src="/js/theme-selector.js"
|
|
28
|
+
></script>
|
|
29
|
+
<script
|
|
30
|
+
data-swup-ignore-script
|
|
23
31
|
defer
|
|
24
32
|
src="/js/host/medium-zoom/dist/medium-zoom.min.js"
|
|
25
33
|
></script>
|
|
26
|
-
<script defer src="/js/
|
|
27
|
-
<script defer src="/js/main.js"></script>
|
|
28
|
-
<script
|
|
34
|
+
<script data-swup-ignore-script defer src="/js/mdit/shiki.js"></script>
|
|
35
|
+
<script data-swup-ignore-script defer src="/js/main.js"></script>
|
|
36
|
+
<script
|
|
37
|
+
data-swup-ignore-script
|
|
38
|
+
async
|
|
39
|
+
src="/js/instant-page.min.js"
|
|
40
|
+
type="module"
|
|
41
|
+
></script>
|
|
29
42
|
</Fragment>
|
|
30
43
|
);
|
|
31
44
|
}
|
package/layout/layout.jsx
CHANGED
|
@@ -19,7 +19,11 @@ module.exports = class extends Component {
|
|
|
19
19
|
<Navbar config={config} helper={helper} page={page} />
|
|
20
20
|
<ThemeSelector />
|
|
21
21
|
<section class="section">
|
|
22
|
-
<div
|
|
22
|
+
<div
|
|
23
|
+
class="main-content transition-fade"
|
|
24
|
+
id="swup"
|
|
25
|
+
dangerouslySetInnerHTML={{ __html: body }}
|
|
26
|
+
></div>
|
|
23
27
|
</section>
|
|
24
28
|
<Footer site={site} config={config} helper={helper} />
|
|
25
29
|
<Scripts site={site} config={config} helper={helper} page={page} />
|
package/layout/plugin/swup.jsx
CHANGED
|
@@ -10,10 +10,12 @@ class Swup extends Component {
|
|
|
10
10
|
const swup = new Swup({
|
|
11
11
|
containers: ["#swup"],
|
|
12
12
|
cache: true,
|
|
13
|
+
native: true,
|
|
13
14
|
plugins: [
|
|
14
15
|
new SwupHeadPlugin({
|
|
15
16
|
persistTags: true
|
|
16
|
-
})
|
|
17
|
+
}),
|
|
18
|
+
new SwupScriptsPlugin()
|
|
17
19
|
]
|
|
18
20
|
});
|
|
19
21
|
`;
|
|
@@ -21,7 +23,11 @@ const swup = new Swup({
|
|
|
21
23
|
<Fragment>
|
|
22
24
|
<script src="/js/host/swup/Swup.umd.min.js"></script>
|
|
23
25
|
<script src="/js/host/swup/head-plugin.umd.min.js"></script>
|
|
24
|
-
<script
|
|
26
|
+
<script src="/js/host/swup/scripts-plugin.umd.min.js"></script>
|
|
27
|
+
<script
|
|
28
|
+
data-swup-ignore-script
|
|
29
|
+
dangerouslySetInnerHTML={{ __html: swupScript }}
|
|
30
|
+
></script>
|
|
25
31
|
</Fragment>
|
|
26
32
|
);
|
|
27
33
|
}
|
package/package.json
CHANGED
package/source/css/default.css
CHANGED
|
@@ -1244,18 +1244,20 @@ section {
|
|
|
1244
1244
|
margin-bottom: 0.25rem;
|
|
1245
1245
|
}
|
|
1246
1246
|
|
|
1247
|
-
.licensing-meta
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1247
|
+
.licensing-meta {
|
|
1248
|
+
.level-item {
|
|
1249
|
+
margin-right: 1.5rem;
|
|
1250
|
+
font-size: 0.75rem;
|
|
1251
|
+
}
|
|
1251
1252
|
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
}
|
|
1253
|
+
iconify-icon {
|
|
1254
|
+
font-size: 1.5em;
|
|
1255
|
+
vertical-align: bottom;
|
|
1256
|
+
}
|
|
1256
1257
|
|
|
1257
|
-
|
|
1258
|
-
|
|
1258
|
+
a {
|
|
1259
|
+
color: inherit;
|
|
1260
|
+
}
|
|
1259
1261
|
}
|
|
1260
1262
|
|
|
1261
1263
|
/* #endregion Licensing */
|
|
@@ -1274,12 +1276,12 @@ section {
|
|
|
1274
1276
|
opacity: 0;
|
|
1275
1277
|
visibility: hidden;
|
|
1276
1278
|
display: flex;
|
|
1277
|
-
}
|
|
1278
1279
|
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1280
|
+
&.show {
|
|
1281
|
+
opacity: 1;
|
|
1282
|
+
visibility: visible;
|
|
1283
|
+
backdrop-filter: blur(5px);
|
|
1284
|
+
}
|
|
1283
1285
|
}
|
|
1284
1286
|
|
|
1285
1287
|
input.searchbox-input {
|
|
@@ -1359,6 +1361,7 @@ input.searchbox-input {
|
|
|
1359
1361
|
|
|
1360
1362
|
.searchbox-result-preview {
|
|
1361
1363
|
color: var(--subtext0);
|
|
1364
|
+
margin-top: 0.25em;
|
|
1362
1365
|
}
|
|
1363
1366
|
|
|
1364
1367
|
.searchbox-result-preview,
|
|
@@ -1369,14 +1372,8 @@ input.searchbox-input {
|
|
|
1369
1372
|
text-overflow: ellipsis;
|
|
1370
1373
|
}
|
|
1371
1374
|
|
|
1372
|
-
.searchbox-result-preview {
|
|
1373
|
-
margin-top: 0.25em;
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
1375
|
/* #endregion Search */
|
|
1377
1376
|
|
|
1378
|
-
/* #region Article Cover */
|
|
1379
|
-
|
|
1380
1377
|
.cover-image {
|
|
1381
1378
|
position: relative;
|
|
1382
1379
|
display: block;
|
|
@@ -1384,7 +1381,14 @@ input.searchbox-input {
|
|
|
1384
1381
|
border-radius: var(--radius) var(--radius) 0 0;
|
|
1385
1382
|
height: 380px;
|
|
1386
1383
|
|
|
1387
|
-
|
|
1384
|
+
img {
|
|
1385
|
+
display: block;
|
|
1386
|
+
width: 100%;
|
|
1387
|
+
height: 100%;
|
|
1388
|
+
object-fit: cover;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
.cover-lqip {
|
|
1388
1392
|
position: absolute;
|
|
1389
1393
|
top: 0;
|
|
1390
1394
|
left: 0;
|
|
@@ -1392,17 +1396,29 @@ input.searchbox-input {
|
|
|
1392
1396
|
filter: blur(10px);
|
|
1393
1397
|
}
|
|
1394
1398
|
|
|
1395
|
-
.
|
|
1399
|
+
.cover-origin {
|
|
1396
1400
|
position: relative;
|
|
1397
1401
|
z-index: 2;
|
|
1398
1402
|
}
|
|
1399
1403
|
}
|
|
1400
1404
|
|
|
1401
|
-
.
|
|
1402
|
-
|
|
1403
|
-
width: 100%;
|
|
1404
|
-
height: 100%;
|
|
1405
|
-
object-fit: cover;
|
|
1405
|
+
/* html.is-changing .transition-fade {
|
|
1406
|
+
view-transition-name: main;
|
|
1406
1407
|
}
|
|
1407
1408
|
|
|
1408
|
-
|
|
1409
|
+
::view-transition-old(main) {
|
|
1410
|
+
animation: fade 0.5s ease-in-out both;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
::view-transition-new(main) {
|
|
1414
|
+
animation: fade 0.5s ease-in-out both reverse;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
@keyframes fade {
|
|
1418
|
+
from {
|
|
1419
|
+
opacity: 1;
|
|
1420
|
+
}
|
|
1421
|
+
to {
|
|
1422
|
+
opacity: 0;
|
|
1423
|
+
}
|
|
1424
|
+
} */
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
.mermaid-container {
|
|
2
|
+
margin: 1em 0;
|
|
3
|
+
position: relative;
|
|
4
|
+
}
|
|
5
|
+
.mermaid-wrapper {
|
|
6
|
+
border: 1px solid var(--surface0);
|
|
7
|
+
border-radius: 6px;
|
|
8
|
+
overflow: hidden;
|
|
9
|
+
position: relative;
|
|
10
|
+
background: var(--mantle);
|
|
11
|
+
}
|
|
12
|
+
.mermaid-toolbar {
|
|
13
|
+
position: absolute;
|
|
14
|
+
top: 8px;
|
|
15
|
+
right: 8px;
|
|
16
|
+
z-index: 20;
|
|
17
|
+
display: flex;
|
|
18
|
+
gap: 4px;
|
|
19
|
+
opacity: 0;
|
|
20
|
+
transition: opacity 0.2s ease;
|
|
21
|
+
}
|
|
22
|
+
.mermaid-wrapper:hover .mermaid-toolbar {
|
|
23
|
+
opacity: 1;
|
|
24
|
+
}
|
|
25
|
+
.mermaid-view-container {
|
|
26
|
+
position: relative;
|
|
27
|
+
width: 100%;
|
|
28
|
+
height: 100%;
|
|
29
|
+
min-height: 200px;
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
cursor: grab;
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
}
|
|
35
|
+
.mermaid-view-container:active {
|
|
36
|
+
cursor: grabbing;
|
|
37
|
+
}
|
|
38
|
+
.mermaid-content {
|
|
39
|
+
width: 100%;
|
|
40
|
+
flex: 1;
|
|
41
|
+
display: flex;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
align-items: center;
|
|
44
|
+
padding: 20px;
|
|
45
|
+
box-sizing: border-box;
|
|
46
|
+
transform-origin: center;
|
|
47
|
+
transition: transform 0.2s ease;
|
|
48
|
+
}
|
|
49
|
+
.mermaid-viewer-grid-panel {
|
|
50
|
+
position: absolute;
|
|
51
|
+
bottom: 8px;
|
|
52
|
+
right: 8px;
|
|
53
|
+
z-index: 10;
|
|
54
|
+
opacity: 0;
|
|
55
|
+
transition: opacity 0.2s ease;
|
|
56
|
+
display: grid;
|
|
57
|
+
grid-template-rows: repeat(3, 1fr);
|
|
58
|
+
gap: 4px;
|
|
59
|
+
}
|
|
60
|
+
.mermaid-wrapper:hover .mermaid-viewer-grid-panel {
|
|
61
|
+
opacity: 1;
|
|
62
|
+
}
|
|
63
|
+
.mermaid-viewer-grid-panel .grid-row {
|
|
64
|
+
display: grid;
|
|
65
|
+
grid-template-columns: repeat(3, 1fr);
|
|
66
|
+
gap: 4px;
|
|
67
|
+
}
|
|
68
|
+
.mermaid-viewer-grid-panel .empty-cell {
|
|
69
|
+
width: 32px;
|
|
70
|
+
height: 32px;
|
|
71
|
+
}
|
|
72
|
+
.btn {
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
width: 32px;
|
|
77
|
+
height: 32px;
|
|
78
|
+
background: var(--base);
|
|
79
|
+
border: 1px solid var(--surface0);
|
|
80
|
+
border-radius: 6px;
|
|
81
|
+
cursor: pointer;
|
|
82
|
+
transition: all 0.2s ease;
|
|
83
|
+
backdrop-filter: blur(4px);
|
|
84
|
+
color: var(--text);
|
|
85
|
+
padding: 0;
|
|
86
|
+
}
|
|
87
|
+
.btn:hover {
|
|
88
|
+
transform: scale(1.05);
|
|
89
|
+
}
|
|
90
|
+
.btn:active {
|
|
91
|
+
transform: scale(0.95);
|
|
92
|
+
}
|
|
93
|
+
.btn svg {
|
|
94
|
+
fill: currentColor;
|
|
95
|
+
}
|
|
96
|
+
.mermaid-loading {
|
|
97
|
+
display: flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
justify-content: center;
|
|
100
|
+
position: absolute;
|
|
101
|
+
top: 0;
|
|
102
|
+
left: 0;
|
|
103
|
+
width: 100%;
|
|
104
|
+
height: 100%;
|
|
105
|
+
color: #586069;
|
|
106
|
+
font-style: italic;
|
|
107
|
+
background: rgba(255, 255, 255, 0.5);
|
|
108
|
+
z-index: 5;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@media (max-width: 768px) {
|
|
112
|
+
.mermaid-wrapper {
|
|
113
|
+
border-radius: 3px;
|
|
114
|
+
}
|
|
115
|
+
.mermaid-toolbar,
|
|
116
|
+
.mermaid-viewer-grid-panel {
|
|
117
|
+
opacity: 1;
|
|
118
|
+
}
|
|
119
|
+
.btn {
|
|
120
|
+
width: 28px;
|
|
121
|
+
height: 28px;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t||self).SwupScriptsPlugin=e()}(this,function(){function t(){return t=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},t.apply(this,arguments)}const e=t=>String(t).split(".").map(t=>String(parseInt(t||"0",10))).concat(["0","0"]).slice(0,3).join(".");class n{constructor(){this.isSwupPlugin=!0,this.swup=void 0,this.version=void 0,this.requires={},this.handlersToUnregister=[]}mount(){}unmount(){this.handlersToUnregister.forEach(t=>t()),this.handlersToUnregister=[]}_beforeMount(){if(!this.name)throw new Error("You must define a name of plugin when creating a class.")}_afterUnmount(){}_checkRequirements(){return"object"!=typeof this.requires||Object.entries(this.requires).forEach(([t,n])=>{if(!function(t,n,r){const o=function(t,e){var n;if("swup"===t)return null!=(n=e.version)?n:"";{var r;const n=e.findPlugin(t);return null!=(r=null==n?void 0:n.version)?r:""}}(t,r);return!!o&&((t,n)=>n.every(n=>{const[,r,o]=n.match(/^([\D]+)?(.*)$/)||[];var s,i;return((t,e)=>{const n={"":t=>0===t,">":t=>t>0,">=":t=>t>=0,"<":t=>t<0,"<=":t=>t<=0};return(n[e]||n[""])(t)})((i=o,s=e(s=t),i=e(i),s.localeCompare(i,void 0,{numeric:!0})),r||">=")}))(o,n)}(t,n=Array.isArray(n)?n:[n],this.swup)){const e=`${t} ${n.join(", ")}`;throw new Error(`Plugin version mismatch: ${this.name} requires ${e}`)}}),!0}on(t,e,n={}){var r;e=!(r=e).name.startsWith("bound ")||r.hasOwnProperty("prototype")?e.bind(this):e;const o=this.swup.hooks.on(t,e,n);return this.handlersToUnregister.push(o),o}once(e,n,r={}){return this.on(e,n,t({},r,{once:!0}))}before(e,n,r={}){return this.on(e,n,t({},r,{before:!0}))}replace(e,n,r={}){return this.on(e,n,t({},r,{replace:!0}))}off(t,e){return this.swup.hooks.off(t,e)}}return class extends n{constructor(t){void 0===t&&(t={}),super(),this.name="SwupScriptsPlugin",this.requires={swup:">=4"},this.defaults={head:!0,body:!0,optin:!1},this.options=void 0,this.options={...this.defaults,...t}}mount(){this.on("content:replace",this.runScripts)}runScripts(){const{head:t,body:e,optin:n}=this.options,r=this.getScope({head:t,body:e});if(!r)return;const o=Array.from(r.querySelectorAll(n?"script[data-swup-reload-script]":"script:not([data-swup-ignore-script])"));o.forEach(t=>this.runScript(t)),this.swup.log(`Executed ${o.length} scripts.`)}runScript(t){const e=document.createElement("script");for(const{name:n,value:r}of t.attributes)e.setAttribute(n,r);return e.textContent=t.textContent,t.replaceWith(e),e}getScope(t){let{head:e,body:n}=t;return e&&n?document:e?document.head:n?document.body:null}}});
|
|
2
|
+
//# sourceMappingURL=index.umd.js.map
|
package/source/js/main.js
CHANGED
|
@@ -111,17 +111,75 @@ function handleKeyDown(e) {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
function handleMermaid() {
|
|
115
|
+
const containers = document.querySelectorAll(".mermaid-container");
|
|
116
|
+
if (containers.length === 0) return;
|
|
117
|
+
|
|
118
|
+
const cssUrl = "/css/optional/mermaid.css";
|
|
119
|
+
const adapterUrl = "/js/mdit/mermaid.js";
|
|
120
|
+
|
|
121
|
+
if (!document.querySelector(`link[href="${cssUrl}"]`)) {
|
|
122
|
+
const link = document.createElement("link");
|
|
123
|
+
link.rel = "stylesheet";
|
|
124
|
+
link.href = cssUrl;
|
|
125
|
+
document.head.appendChild(link);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const runInit = () => {
|
|
129
|
+
const isNight = document.documentElement.classList.contains("night");
|
|
130
|
+
const theme = isNight ? "dark" : "default";
|
|
131
|
+
const libUrl = "/js/host/mermaid/mermaid.min.js";
|
|
132
|
+
|
|
133
|
+
containers.forEach((container, index) => {
|
|
134
|
+
if (!container.id) {
|
|
135
|
+
container.id = `mermaid-${Date.now()}-${index}`;
|
|
136
|
+
}
|
|
137
|
+
if (window.initMermaidDiagram) {
|
|
138
|
+
window.initMermaidDiagram(container.id, libUrl, theme, {});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
if (window.initMermaidDiagram) {
|
|
144
|
+
runInit();
|
|
145
|
+
} else {
|
|
146
|
+
const existingScript = document.querySelector(
|
|
147
|
+
`script[src="${adapterUrl}"]`,
|
|
148
|
+
);
|
|
149
|
+
if (existingScript) {
|
|
150
|
+
existingScript.addEventListener("load", runInit);
|
|
151
|
+
} else {
|
|
152
|
+
const script = document.createElement("script");
|
|
153
|
+
script.src = adapterUrl;
|
|
154
|
+
script.onload = runInit;
|
|
155
|
+
document.head.appendChild(script);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
114
160
|
// #endregion
|
|
115
161
|
|
|
116
162
|
function initLogic() {
|
|
117
163
|
initializeTabs();
|
|
164
|
+
handleMermaid();
|
|
118
165
|
mediumZoom(".article img", {
|
|
119
166
|
background: "hsla(from var(--mantle) / 0.9)",
|
|
120
167
|
});
|
|
121
168
|
if (document.getElementById("twikoo")) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
169
|
+
const initTwikoo = () => {
|
|
170
|
+
if (window.twikoo && window.twikooConfig) {
|
|
171
|
+
window.twikoo.init(window.twikooConfig);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
if (typeof twikoo !== "undefined") {
|
|
176
|
+
initTwikoo();
|
|
177
|
+
} else {
|
|
178
|
+
const script = document.querySelector('script[src*="twikoo.all.min.js"]');
|
|
179
|
+
if (script) {
|
|
180
|
+
script.addEventListener("load", initTwikoo);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
125
183
|
}
|
|
126
184
|
}
|
|
127
185
|
|
|
@@ -131,7 +189,8 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
131
189
|
|
|
132
190
|
// Re-initialize on page changes when using swup
|
|
133
191
|
if (typeof swup !== "undefined") {
|
|
134
|
-
swup.hooks.on("page:view", () => {
|
|
192
|
+
swup.hooks.on("page:view", (visit) => {
|
|
193
|
+
console.log("New page loaded:", visit.to.url);
|
|
135
194
|
initLogic();
|
|
136
195
|
});
|
|
137
196
|
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
const instances = new Map();
|
|
3
|
+
let mermaidPromise = null;
|
|
4
|
+
const loadMermaid = (jsUrl) => {
|
|
5
|
+
if (mermaidPromise) return mermaidPromise;
|
|
6
|
+
if (window.mermaid) {
|
|
7
|
+
mermaidPromise = Promise.resolve(window.mermaid);
|
|
8
|
+
return mermaidPromise;
|
|
9
|
+
}
|
|
10
|
+
return (mermaidPromise = new Promise((resolve, reject) => {
|
|
11
|
+
const script = document.createElement("script");
|
|
12
|
+
script.src = jsUrl;
|
|
13
|
+
script.onload = () => resolve(window.mermaid);
|
|
14
|
+
script.onerror = reject;
|
|
15
|
+
document.head.appendChild(script);
|
|
16
|
+
}));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const renderDiagram = async (id, code, container, themeVariables) => {
|
|
20
|
+
const content = container.querySelector(".mermaid-content");
|
|
21
|
+
const mermaid = await mermaidPromise;
|
|
22
|
+
if (!content || !mermaid) return;
|
|
23
|
+
|
|
24
|
+
// Initialize with current theme
|
|
25
|
+
mermaid.initialize({
|
|
26
|
+
startOnLoad: false,
|
|
27
|
+
theme: document.documentElement.classList.contains("night")
|
|
28
|
+
? "dark"
|
|
29
|
+
: "default",
|
|
30
|
+
darkMode: document.documentElement.classList.contains("night"),
|
|
31
|
+
themeVariables,
|
|
32
|
+
securityLevel: "strict",
|
|
33
|
+
fontSize: 16,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
content.innerHTML = "";
|
|
38
|
+
const { svg } = await mermaid.render(`${id}-svg`, code);
|
|
39
|
+
content.insertAdjacentHTML("beforeend", svg);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error("Mermaid rendering error:", error);
|
|
42
|
+
content.innerHTML = `<p style="color: red;">Failed to render diagram: ${error.message}</p>`;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
class PanZoomHandler {
|
|
47
|
+
constructor(container) {
|
|
48
|
+
this.container = container;
|
|
49
|
+
this.content = container.querySelector(".mermaid-content");
|
|
50
|
+
this.viewContainer = container.querySelector(".mermaid-view-container");
|
|
51
|
+
this.scale = 1;
|
|
52
|
+
this.tx = 0;
|
|
53
|
+
this.ty = 0;
|
|
54
|
+
this.isDragging = false;
|
|
55
|
+
this.startX = 0;
|
|
56
|
+
this.startY = 0;
|
|
57
|
+
this.initEvents();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
apply() {
|
|
61
|
+
if (this.content) {
|
|
62
|
+
this.content.style.transform = `scale(${this.scale}) translate(${this.tx}px, ${this.ty}px)`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
initEvents() {
|
|
67
|
+
// Toolbar & Grid Panel
|
|
68
|
+
this.container.addEventListener("click", (e) => {
|
|
69
|
+
const btn = e.target.closest("button");
|
|
70
|
+
if (!btn) return;
|
|
71
|
+
const cl = btn.classList;
|
|
72
|
+
|
|
73
|
+
if (cl.contains("zoom-in")) this.scale = Math.min(this.scale * 1.2, 5);
|
|
74
|
+
else if (cl.contains("zoom-out"))
|
|
75
|
+
this.scale = Math.max(this.scale / 1.2, 0.2);
|
|
76
|
+
else if (cl.contains("reset")) {
|
|
77
|
+
this.scale = 1;
|
|
78
|
+
this.tx = 0;
|
|
79
|
+
this.ty = 0;
|
|
80
|
+
} else if (cl.contains("up")) this.ty += 40;
|
|
81
|
+
else if (cl.contains("down")) this.ty -= 40;
|
|
82
|
+
else if (cl.contains("left")) this.tx += 40;
|
|
83
|
+
else if (cl.contains("right")) this.tx -= 40;
|
|
84
|
+
else if (cl.contains("copy-code")) this.copyCode(btn);
|
|
85
|
+
|
|
86
|
+
this.apply();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Dragging
|
|
90
|
+
if (this.viewContainer) {
|
|
91
|
+
this.viewContainer.addEventListener("mousedown", (e) => {
|
|
92
|
+
this.isDragging = true;
|
|
93
|
+
this.startX = e.clientX - this.tx;
|
|
94
|
+
this.startY = e.clientY - this.ty;
|
|
95
|
+
this.viewContainer.style.cursor = "grabbing";
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
window.addEventListener("mousemove", (e) => {
|
|
100
|
+
if (!this.isDragging) return;
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
this.tx = e.clientX - this.startX;
|
|
103
|
+
this.ty = e.clientY - this.startY;
|
|
104
|
+
this.apply();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
window.addEventListener("mouseup", () => {
|
|
108
|
+
if (this.isDragging) {
|
|
109
|
+
this.isDragging = false;
|
|
110
|
+
if (this.viewContainer) this.viewContainer.style.cursor = "grab";
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
copyCode(btn) {
|
|
116
|
+
const codeEl = this.container.querySelector(".mermaid-code");
|
|
117
|
+
if (!codeEl) return;
|
|
118
|
+
navigator.clipboard.writeText(codeEl.textContent).then(() => {
|
|
119
|
+
const originalTitle = btn.getAttribute("title");
|
|
120
|
+
btn.setAttribute("title", "Copied!");
|
|
121
|
+
setTimeout(() => btn.setAttribute("title", originalTitle), 2000);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const pruneInstances = () => {
|
|
127
|
+
for (const [id, { container }] of instances) {
|
|
128
|
+
if (!document.body.contains(container)) {
|
|
129
|
+
instances.delete(id);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
window.initMermaidDiagram = (id, jsUrl, _theme, themeVariables) => {
|
|
135
|
+
const container = document.getElementById(id);
|
|
136
|
+
if (!container) return;
|
|
137
|
+
|
|
138
|
+
pruneInstances();
|
|
139
|
+
if (instances.has(id)) return;
|
|
140
|
+
|
|
141
|
+
const codeEl = container.querySelector(".mermaid-code");
|
|
142
|
+
if (!codeEl) return;
|
|
143
|
+
|
|
144
|
+
new PanZoomHandler(container);
|
|
145
|
+
instances.set(id, { container, code: codeEl.textContent, themeVariables });
|
|
146
|
+
|
|
147
|
+
loadMermaid(jsUrl).then(() => {
|
|
148
|
+
renderDiagram(id, codeEl.textContent, container, themeVariables);
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Theme Observer
|
|
153
|
+
const observer = new MutationObserver((mutations) => {
|
|
154
|
+
const isThemeChange = mutations.some(
|
|
155
|
+
(m) => m.type === "attributes" && m.attributeName === "class",
|
|
156
|
+
);
|
|
157
|
+
if (isThemeChange) {
|
|
158
|
+
pruneInstances();
|
|
159
|
+
instances.forEach(({ container, code, themeVariables }, id) => {
|
|
160
|
+
renderDiagram(id, code, container, themeVariables);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
observer.observe(document.documentElement, {
|
|
166
|
+
attributes: true,
|
|
167
|
+
attributeFilter: ["class"],
|
|
168
|
+
});
|
|
169
|
+
})();
|
|
File without changes
|