hexo-theme-linen 1.0.19 → 1.0.21
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/package.json +1 -1
- package/scripts/footnote.js +99 -0
- package/scripts/index.js +1 -0
- package/source/linen-theme/css/linen.scss +23 -2
- package/source/linen-theme/css/mediaquery.scss +1 -3
- package/source/linen-theme/css/vars.scss +3 -0
- package/source/linen-theme/img/icons/backref.svg +1 -0
- package/source/linen-theme/js/linen.js +52 -8
- package/source/linen-theme/js/photoswipe/photoswipe.esm.min.js +0 -13
package/package.json
CHANGED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
hexo.extend.filter.register("before_post_render", function (data) {
|
|
4
|
+
let lines = data.content.split("\n");
|
|
5
|
+
|
|
6
|
+
const footnotes = {};
|
|
7
|
+
const refRegex = /\[\^(.+?)\]/g;
|
|
8
|
+
const defStartRegex = /^\[\^(.+?)\]:\s*(.*)$/;
|
|
9
|
+
|
|
10
|
+
let i = 0;
|
|
11
|
+
|
|
12
|
+
while (i < lines.length) {
|
|
13
|
+
const line = lines[i];
|
|
14
|
+
const defMatch = line.match(defStartRegex);
|
|
15
|
+
|
|
16
|
+
if (defMatch) {
|
|
17
|
+
const id = defMatch[1];
|
|
18
|
+
const firstLine = defMatch[2] || "";
|
|
19
|
+
let blocks = [];
|
|
20
|
+
|
|
21
|
+
if (firstLine.trim()) {
|
|
22
|
+
blocks.push(firstLine);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
i++;
|
|
26
|
+
|
|
27
|
+
while (i < lines.length) {
|
|
28
|
+
const next = lines[i];
|
|
29
|
+
|
|
30
|
+
if (defStartRegex.test(next)) break;
|
|
31
|
+
|
|
32
|
+
if (/^\s{4,}|\t/.test(next)) {
|
|
33
|
+
blocks.push(next.replace(/^\s{4}/, ""));
|
|
34
|
+
i++;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (next.trim() === "") {
|
|
39
|
+
blocks.push("");
|
|
40
|
+
i++;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
footnotes[id] = blocks.join("\n");
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
i++;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
data.content = data.content.replace(
|
|
55
|
+
/^\[\^(.+?)\]:[\s\S]+?(?=\n\[|\n*$)/gm,
|
|
56
|
+
"",
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const refCount = {};
|
|
60
|
+
|
|
61
|
+
data.content = data.content.replace(refRegex, (m, id) => {
|
|
62
|
+
if (!footnotes[id]) return m;
|
|
63
|
+
|
|
64
|
+
refCount[id] = (refCount[id] || 0) + 1;
|
|
65
|
+
const n = refCount[id];
|
|
66
|
+
|
|
67
|
+
return `<sup class="footnote-anchor-wrap" id="fnref-${id}-${n}"><a class="footnote-href" href="#fn-${id}">${id}</a></sup>`;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const keys = Object.keys(footnotes);
|
|
71
|
+
if (keys.length > 0) {
|
|
72
|
+
const list = keys
|
|
73
|
+
.map((id) => {
|
|
74
|
+
const html = footnotes[id]
|
|
75
|
+
.split("\n")
|
|
76
|
+
.map((p) => (p.trim() ? p : ""))
|
|
77
|
+
.join("\n");
|
|
78
|
+
|
|
79
|
+
const backrefs = Array.from({ length: refCount[id] || 0 }, (_, i) => {
|
|
80
|
+
const n = i + 1;
|
|
81
|
+
return `<a href="#fnref-${id}-${n}" class="footnote-backref"></a>`;
|
|
82
|
+
}).join(" ");
|
|
83
|
+
|
|
84
|
+
return `<li id="fn-${id}">${html}${backrefs}</li>`;
|
|
85
|
+
})
|
|
86
|
+
.join("\n");
|
|
87
|
+
|
|
88
|
+
data.content += `
|
|
89
|
+
<hr class="footnotes-sep">
|
|
90
|
+
<section class="footnotes">
|
|
91
|
+
<ol>
|
|
92
|
+
${list}
|
|
93
|
+
</ol>
|
|
94
|
+
</section>
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return data;
|
|
99
|
+
});
|
package/scripts/index.js
CHANGED
|
@@ -5,6 +5,7 @@ require("./custom")(hexo);
|
|
|
5
5
|
require("./hoverTexts")(hexo);
|
|
6
6
|
require("./helpers/tools")(hexo);
|
|
7
7
|
require("./font-version")(hexo);
|
|
8
|
+
require("./footnote")(hexo);
|
|
8
9
|
require("./appendRawMarkdownContent")(hexo);
|
|
9
10
|
require("./addCopyButtonToCodeBlocks")(hexo);
|
|
10
11
|
require('./folded-code-block')(hexo);
|
|
@@ -1675,7 +1675,7 @@ body {
|
|
|
1675
1675
|
.series-nav {
|
|
1676
1676
|
background-color: #f5f5f5;
|
|
1677
1677
|
width: calc(100% - min(6vw, 30px));
|
|
1678
|
-
margin:
|
|
1678
|
+
margin: 0 auto 1em auto;
|
|
1679
1679
|
padding: 1em;
|
|
1680
1680
|
padding-top: 0.65em;
|
|
1681
1681
|
border-radius: 2px;
|
|
@@ -2141,7 +2141,7 @@ html[lang="zh-CN"] {
|
|
|
2141
2141
|
}
|
|
2142
2142
|
|
|
2143
2143
|
#related-posts {
|
|
2144
|
-
|
|
2144
|
+
padding: 0 $commonPadding;
|
|
2145
2145
|
border-top: solid 1px #f5f5f5;
|
|
2146
2146
|
.related-posts-title {
|
|
2147
2147
|
margin: 1em 0;
|
|
@@ -2531,3 +2531,24 @@ ul {
|
|
|
2531
2531
|
}
|
|
2532
2532
|
}
|
|
2533
2533
|
}
|
|
2534
|
+
|
|
2535
|
+
.footnote-anchor-wrap {
|
|
2536
|
+
.footnote-href{
|
|
2537
|
+
color: $green;
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
.footnote-backref{
|
|
2541
|
+
width: 0.8em;
|
|
2542
|
+
height: 0.8em;
|
|
2543
|
+
background-image: url("../img/icons/backref.svg");
|
|
2544
|
+
background-size: contain;
|
|
2545
|
+
display: inline-block;
|
|
2546
|
+
&:not(:first-child) {
|
|
2547
|
+
display: none;
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
.footnotes {
|
|
2551
|
+
ol {
|
|
2552
|
+
padding-left: calc(40px - $commonPadding);
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg t="1776504285799" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4049" width="200" height="200"><path d="M853.312 170.688v384a170.688 170.688 0 0 1-170.624 170.624H294.976L401.664 832l-60.352 60.352-209.664-209.664L341.312 472.96l60.352 60.288L295.04 640h387.712C729.792 640 768 601.792 768 554.688v-384h85.312z" p-id="4050" fill="#0f730c"></path></svg>
|
|
@@ -161,14 +161,30 @@ function copyToClipboard(text) {
|
|
|
161
161
|
copyToClipboard(text);
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
function highlightAnchor(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
164
|
+
function highlightAnchor(
|
|
165
|
+
hash,
|
|
166
|
+
highlightClass = "anchor-highlight",
|
|
167
|
+
element = null,
|
|
168
|
+
) {
|
|
169
|
+
if (element) {
|
|
170
|
+
element.classList.remove(highlightClass);
|
|
171
|
+
void element.offsetWidth;
|
|
172
|
+
element.classList.add(highlightClass);
|
|
173
|
+
setTimeout(() => {
|
|
174
|
+
element.classList.remove(highlightClass);
|
|
175
|
+
}, 4000);
|
|
176
|
+
} else {
|
|
177
|
+
if (!hash) return;
|
|
178
|
+
const id = hash.replace(/^#/, "");
|
|
179
|
+
const el = document.getElementById(id);
|
|
180
|
+
if (el) {
|
|
181
|
+
el.classList.remove(highlightClass);
|
|
182
|
+
void el.offsetWidth;
|
|
183
|
+
el.classList.add(highlightClass);
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
el.classList.remove(highlightClass);
|
|
186
|
+
}, 4000);
|
|
187
|
+
}
|
|
172
188
|
}
|
|
173
189
|
}
|
|
174
190
|
|
|
@@ -272,6 +288,34 @@ function handleClick(e) {
|
|
|
272
288
|
var maskElement = document.getElementById("mask");
|
|
273
289
|
var bodyElement = document.body;
|
|
274
290
|
var donateModal = document.getElementById("donate-modal");
|
|
291
|
+
if(target?.className === 'footnote-href') {
|
|
292
|
+
const footNoteDefinitionId = target.getAttribute("href").substring(1);
|
|
293
|
+
const footNoteDefinitionElement = document.getElementById(footNoteDefinitionId);
|
|
294
|
+
if (footNoteDefinitionElement) {
|
|
295
|
+
footNoteDefinitionElement.scrollIntoView({
|
|
296
|
+
behavior: "smooth",
|
|
297
|
+
block: "start",
|
|
298
|
+
});
|
|
299
|
+
e.preventDefault();
|
|
300
|
+
highlightAnchor(undefined, undefined, footNoteDefinitionElement);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (target?.className === "footnote-backref") {
|
|
305
|
+
const footNoteId = target.getAttribute("href").substring(1);
|
|
306
|
+
const footNoteTextElements = document.querySelectorAll('.footnote-anchor-wrap');
|
|
307
|
+
if (footNoteTextElements.length) {
|
|
308
|
+
footNoteTextElements[0].scrollIntoView({
|
|
309
|
+
behavior: "smooth",
|
|
310
|
+
block: "start",
|
|
311
|
+
});
|
|
312
|
+
e.preventDefault();
|
|
313
|
+
Array.prototype.forEach.call(footNoteTextElements, (el) => {
|
|
314
|
+
highlightAnchor(undefined, undefined, el);
|
|
315
|
+
})
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
275
319
|
if (/content-switch/.test(target.id)) {
|
|
276
320
|
if (document.body.classList.contains("render-raw")) {
|
|
277
321
|
target.innerText = target.dataset.rawcontentlabel;
|
|
@@ -148,19 +148,6 @@ function removeTransitionStyle(el) {
|
|
|
148
148
|
* @returns {Promise<HTMLImageElement | void>}
|
|
149
149
|
*/
|
|
150
150
|
function decodeImage(img) {
|
|
151
|
-
// Skip decode for HDR images to prevent Chrome crashes
|
|
152
|
-
if (img.src && img.src.includes("/hdr/")) {
|
|
153
|
-
if (img.complete) {
|
|
154
|
-
return Promise.resolve(img);
|
|
155
|
-
}
|
|
156
|
-
return new Promise((resolve, reject) => {
|
|
157
|
-
img.onload = () => resolve(img);
|
|
158
|
-
img.onerror = reject;
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
if ("decode" in img) {
|
|
162
|
-
return img.decode().catch(() => {});
|
|
163
|
-
}
|
|
164
151
|
if (img.complete) {
|
|
165
152
|
return Promise.resolve(img);
|
|
166
153
|
}
|