hexo-theme-lnote 1.2.3

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.
Files changed (145) hide show
  1. package/README.md +123 -0
  2. package/_config.yml +19 -0
  3. package/config/links.yml +63 -0
  4. package/config/svg.yml +34 -0
  5. package/languages/de.yml +69 -0
  6. package/languages/en.yml +69 -0
  7. package/languages/eo.yml +69 -0
  8. package/languages/es.yml +69 -0
  9. package/languages/ja.yml +69 -0
  10. package/languages/ru.yml +69 -0
  11. package/languages/zh-CN.yml +69 -0
  12. package/languages/zh-HK.yml +69 -0
  13. package/languages/zh-TW.yml +69 -0
  14. package/layout/404.ejs +8 -0
  15. package/layout/_partials/archive-list.ejs +17 -0
  16. package/layout/_partials/category-chains.ejs +19 -0
  17. package/layout/_partials/category-list.ejs +62 -0
  18. package/layout/_partials/comments/changyan.ejs +11 -0
  19. package/layout/_partials/comments/cusdis.ejs +25 -0
  20. package/layout/_partials/comments/discuss.ejs +17 -0
  21. package/layout/_partials/comments/disqus.ejs +32 -0
  22. package/layout/_partials/comments/giscus.ejs +36 -0
  23. package/layout/_partials/comments/gitalk.ejs +19 -0
  24. package/layout/_partials/comments/livere.ejs +10 -0
  25. package/layout/_partials/comments/remark42.ejs +29 -0
  26. package/layout/_partials/comments/twikoo.ejs +25 -0
  27. package/layout/_partials/comments/utterances.ejs +27 -0
  28. package/layout/_partials/comments/valine.ejs +23 -0
  29. package/layout/_partials/comments/waline.ejs +24 -0
  30. package/layout/_partials/comments.ejs +8 -0
  31. package/layout/_partials/css.ejs +10 -0
  32. package/layout/_partials/footer/beian.ejs +33 -0
  33. package/layout/_partials/footer/statistics.ejs +39 -0
  34. package/layout/_partials/footer.ejs +7 -0
  35. package/layout/_partials/head.ejs +46 -0
  36. package/layout/_partials/header/banner.ejs +24 -0
  37. package/layout/_partials/header/navigation.ejs +57 -0
  38. package/layout/_partials/header.ejs +4 -0
  39. package/layout/_partials/markdown-plugins.ejs +24 -0
  40. package/layout/_partials/paginator.ejs +14 -0
  41. package/layout/_partials/plugins/analytics.ejs +75 -0
  42. package/layout/_partials/plugins/anchorjs.ejs +39 -0
  43. package/layout/_partials/plugins/code-widget.ejs +7 -0
  44. package/layout/_partials/plugins/encrypt.ejs +18 -0
  45. package/layout/_partials/plugins/fancybox.ejs +11 -0
  46. package/layout/_partials/plugins/highlight.ejs +13 -0
  47. package/layout/_partials/plugins/math.ejs +51 -0
  48. package/layout/_partials/plugins/mermaid.ejs +4 -0
  49. package/layout/_partials/plugins/nprogress.ejs +8 -0
  50. package/layout/_partials/plugins/typed.ejs +20 -0
  51. package/layout/_partials/post/category-bar.ejs +18 -0
  52. package/layout/_partials/post/copyright.ejs +50 -0
  53. package/layout/_partials/post/css.ejs +4 -0
  54. package/layout/_partials/post/meta-bottom.ejs +16 -0
  55. package/layout/_partials/post/meta-top.ejs +28 -0
  56. package/layout/_partials/post/scripts.ejs +8 -0
  57. package/layout/_partials/post/sidebar-left.ejs +1 -0
  58. package/layout/_partials/post/sidebar-right.ejs +3 -0
  59. package/layout/_partials/post/toc.ejs +7 -0
  60. package/layout/_partials/scripts.ejs +10 -0
  61. package/layout/_partials/search.ejs +19 -0
  62. package/layout/about.ejs +22 -0
  63. package/layout/archive.ejs +10 -0
  64. package/layout/categories.ejs +20 -0
  65. package/layout/category.ejs +12 -0
  66. package/layout/index.ejs +61 -0
  67. package/layout/layout.ejs +60 -0
  68. package/layout/links.ejs +31 -0
  69. package/layout/page.ejs +15 -0
  70. package/layout/post.ejs +77 -0
  71. package/layout/tag.ejs +12 -0
  72. package/layout/tags.ejs +26 -0
  73. package/package.json +70 -0
  74. package/scripts/index.js +1 -0
  75. package/source/css/_functions/base.styl +8 -0
  76. package/source/css/_mixins/base.styl +23 -0
  77. package/source/css/_pages/_about/about.styl +32 -0
  78. package/source/css/_pages/_archive/archive.styl +32 -0
  79. package/source/css/_pages/_base/_widget/anchorjs.styl +8 -0
  80. package/source/css/_pages/_base/_widget/banner.styl +29 -0
  81. package/source/css/_pages/_base/_widget/board.styl +11 -0
  82. package/source/css/_pages/_base/_widget/code-widget.styl +36 -0
  83. package/source/css/_pages/_base/_widget/copyright.styl +90 -0
  84. package/source/css/_pages/_base/_widget/footer.styl +65 -0
  85. package/source/css/_pages/_base/_widget/footnote.styl +25 -0
  86. package/source/css/_pages/_base/_widget/header.styl +173 -0
  87. package/source/css/_pages/_base/_widget/modal.styl +100 -0
  88. package/source/css/_pages/_base/_widget/navlink.styl +16 -0
  89. package/source/css/_pages/_base/_widget/ngrogress.styl +12 -0
  90. package/source/css/_pages/_base/_widget/noscript.styl +12 -0
  91. package/source/css/_pages/_base/_widget/pagination.styl +23 -0
  92. package/source/css/_pages/_base/_widget/qrcode.styl +17 -0
  93. package/source/css/_pages/_base/_widget/scroll-btn.styl +48 -0
  94. package/source/css/_pages/_base/_widget/text.styl +19 -0
  95. package/source/css/_pages/_base/_widget/toc.styl +75 -0
  96. package/source/css/_pages/_base/base.styl +68 -0
  97. package/source/css/_pages/_base/color-schema.styl +75 -0
  98. package/source/css/_pages/_base/inline.styl +51 -0
  99. package/source/css/_pages/_base/keyframes.styl +31 -0
  100. package/source/css/_pages/_base/print.styl +38 -0
  101. package/source/css/_pages/_category/category-bar.styl +58 -0
  102. package/source/css/_pages/_category/category-chain.styl +6 -0
  103. package/source/css/_pages/_category/category-list.styl +62 -0
  104. package/source/css/_pages/_index/index.styl +75 -0
  105. package/source/css/_pages/_links/links.styl +79 -0
  106. package/source/css/_pages/_post/comment.styl +27 -0
  107. package/source/css/_pages/_post/highlight.styl +75 -0
  108. package/source/css/_pages/_post/markdown.styl +96 -0
  109. package/source/css/_pages/_post/post-page.styl +179 -0
  110. package/source/css/_pages/_post/post-tag.styl +29 -0
  111. package/source/css/_pages/_tag/tag.styl +9 -0
  112. package/source/css/_pages/_tag/tags.styl +9 -0
  113. package/source/css/_pages/pages.styl +8 -0
  114. package/source/css/_variables/base.styl +72 -0
  115. package/source/css/gitalk.css +546 -0
  116. package/source/css/main.styl +19 -0
  117. package/source/img/avatar.png +0 -0
  118. package/source/img/default.jpg +0 -0
  119. package/source/img/default1.jpg +0 -0
  120. package/source/img/default2.jpg +0 -0
  121. package/source/img/default3.jpg +0 -0
  122. package/source/img/default4.jpg +0 -0
  123. package/source/img/default5.jpg +0 -0
  124. package/source/img/default6.jpg +0 -0
  125. package/source/img/default7.jpg +0 -0
  126. package/source/img/default8.jpg +0 -0
  127. package/source/img/docs.png +0 -0
  128. package/source/img/loading.gif +0 -0
  129. package/source/img/police_beian.png +0 -0
  130. package/source/js/color-schema.js +279 -0
  131. package/source/js/events.js +72 -0
  132. package/source/js/img-lazyload.js +10 -0
  133. package/source/js/local-search.js +70 -0
  134. package/source/js/post/copying-code.js +34 -0
  135. package/source/js/post/enable.js +8 -0
  136. package/source/js/post/img-swipe-bf.js +47 -0
  137. package/source/js/post/img-swipe.js +35 -0
  138. package/source/js/post/mermaiding.js +13 -0
  139. package/source/js/post/play-imgs.js +59 -0
  140. package/source/js/post/toc.js +24 -0
  141. package/source/js/post/view-imgs.js +27 -0
  142. package/source/js/utils.js +245 -0
  143. package/source/xml/local-search.xml +45 -0
  144. package/templates/footer.ejs +13 -0
  145. package/templates/noun.vue +18 -0
@@ -0,0 +1,279 @@
1
+ /* global LNote */
2
+
3
+ /**
4
+ * Modified from https://blog.skk.moe/post/hello-darkmode-my-old-friend/
5
+ */
6
+ (function(window, document) {
7
+ var rootElement = document.documentElement;
8
+ var colorSchemaStorageKey = 'Lnote_Color_Scheme';
9
+ var colorSchemaMediaQueryKey = '--color-mode';
10
+ var userColorSchemaAttributeName = 'data-bs-theme';
11
+ var defaultColorSchemaAttributeName = 'data-default-color-scheme';
12
+ var colorToggleButtonSelector = '#color-toggle-btn';
13
+ var colorToggleIconSelector = '#color-toggle-icon';
14
+
15
+ function setLS(k, v) {
16
+ try {
17
+ localStorage.setItem(k, v);
18
+ } catch (e) {}
19
+ }
20
+
21
+ function removeLS(k) {
22
+ try {
23
+ localStorage.removeItem(k);
24
+ } catch (e) {}
25
+ }
26
+
27
+ function getLS(k) {
28
+ try {
29
+ return localStorage.getItem(k);
30
+ } catch (e) {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ function getSchemaFromHTML() {
36
+ var res = rootElement.getAttribute(defaultColorSchemaAttributeName);
37
+ if (typeof res === 'string') {
38
+ return res.replace(/["'\s]/g, '');
39
+ }
40
+ return null;
41
+ }
42
+
43
+ function getSchemaFromCSSMediaQuery() {
44
+ var res = getComputedStyle(rootElement).getPropertyValue(
45
+ colorSchemaMediaQueryKey
46
+ );
47
+ if (typeof res === 'string') {
48
+ return res.replace(/["'\s]/g, '');
49
+ }
50
+ return null;
51
+ }
52
+
53
+ function resetSchemaAttributeAndLS() {
54
+ rootElement.setAttribute(userColorSchemaAttributeName, getDefaultColorSchema());
55
+ removeLS(colorSchemaStorageKey);
56
+ }
57
+
58
+ var validColorSchemaKeys = {
59
+ dark : true,
60
+ light: true
61
+ };
62
+
63
+ function getDefaultColorSchema() {
64
+ // 取默认字段的值
65
+ var schema = getSchemaFromHTML();
66
+ // 如果明确指定了 schema 则返回
67
+ if (validColorSchemaKeys[schema]) {
68
+ return schema;
69
+ }
70
+ // 默认优先按 prefers-color-scheme
71
+ schema = getSchemaFromCSSMediaQuery();
72
+ if (validColorSchemaKeys[schema]) {
73
+ return schema;
74
+ }
75
+ // 否则按本地时间是否大于 18 点或凌晨 0 ~ 6 点
76
+ var hours = new Date().getHours();
77
+ if (hours >= 18 || (hours >= 0 && hours <= 6)) {
78
+ return 'dark';
79
+ }
80
+ return 'light';
81
+ }
82
+
83
+ function applyCustomColorSchemaSettings(schema) {
84
+ // 接受从「开关」处传来的模式,或者从 localStorage 读取,否则按默认设置值
85
+ var current = schema || getLS(colorSchemaStorageKey) || getDefaultColorSchema();
86
+
87
+ if (current === getDefaultColorSchema()) {
88
+ // 当用户切换的显示模式和默认模式相同时,则恢复为自动模式
89
+ resetSchemaAttributeAndLS();
90
+ } else if (validColorSchemaKeys[current]) {
91
+ rootElement.setAttribute(
92
+ userColorSchemaAttributeName,
93
+ current
94
+ );
95
+ } else {
96
+ // 特殊情况重置
97
+ resetSchemaAttributeAndLS();
98
+ return;
99
+ }
100
+
101
+ // 根据当前模式设置图标
102
+ setButtonIcon(current);
103
+
104
+ // 设置代码高亮
105
+ setHighlightCSS(current);
106
+
107
+ // 设置其他应用
108
+ setApplications(current);
109
+ }
110
+
111
+ var invertColorSchemaObj = {
112
+ dark : 'light',
113
+ light: 'dark'
114
+ };
115
+
116
+ function getIconClass(scheme) {
117
+ return 'icon-' + scheme;
118
+ }
119
+
120
+ function toggleCustomColorSchema() {
121
+ var currentSetting = getLS(colorSchemaStorageKey);
122
+
123
+ if (validColorSchemaKeys[currentSetting]) {
124
+ // 从 localStorage 中读取模式,并取相反的模式
125
+ currentSetting = invertColorSchemaObj[currentSetting];
126
+ } else if (currentSetting === null) {
127
+ // 当 localStorage 中没有相关值,或者 localStorage 抛了 Error
128
+ // 先按照按钮的状态进行切换
129
+ var iconElement = document.querySelector(colorToggleIconSelector);
130
+ if (iconElement) {
131
+ currentSetting = iconElement.getAttribute('data');
132
+ }
133
+ if (!iconElement || !validColorSchemaKeys[currentSetting]) {
134
+ // 当 localStorage 中没有相关值,或者 localStorage 抛了 Error,则读取默认值并切换到相反的模式
135
+ currentSetting = invertColorSchemaObj[getSchemaFromCSSMediaQuery()];
136
+ }
137
+ } else {
138
+ return;
139
+ }
140
+ // 将相反的模式写入 localStorage
141
+ setLS(colorSchemaStorageKey, currentSetting);
142
+
143
+ return currentSetting;
144
+ }
145
+
146
+ function setButtonIcon(schema) {
147
+ if (validColorSchemaKeys[schema]) {
148
+ // 切换图标
149
+ var icon = getIconClass('dark');
150
+ if (schema) {
151
+ icon = getIconClass(schema);
152
+ }
153
+ var iconElement = document.querySelector(colorToggleIconSelector);
154
+ if (iconElement) {
155
+ iconElement.setAttribute(
156
+ 'class',
157
+ 'iconfont ' + icon
158
+ );
159
+ iconElement.setAttribute(
160
+ 'data',
161
+ invertColorSchemaObj[schema]
162
+ );
163
+ } else {
164
+ // 如果图标不存在则说明图标还没加载出来,等到页面全部加载再尝试切换
165
+ LNote.utils.waitElementLoaded(colorToggleIconSelector, function() {
166
+ var iconElement = document.querySelector(colorToggleIconSelector);
167
+ if (iconElement) {
168
+ iconElement.setAttribute(
169
+ 'class',
170
+ 'iconfont ' + icon
171
+ );
172
+ iconElement.setAttribute(
173
+ 'data',
174
+ invertColorSchemaObj[schema]
175
+ );
176
+ }
177
+ });
178
+ }
179
+ if (document.documentElement.getAttribute('data-bs-theme')) {
180
+ var color = getComputedStyle(document.documentElement).getPropertyValue('--navbar-bg-color').trim()
181
+ document.querySelector('meta[name="theme-color"]').setAttribute('content', color)
182
+ }
183
+ }
184
+ }
185
+
186
+ function setHighlightCSS(schema) {
187
+ // 启用对应的代码高亮的样式
188
+ var lightCss = document.getElementById('highlight-css');
189
+ var darkCss = document.getElementById('highlight-css-dark');
190
+ if (schema === 'dark') {
191
+ if (darkCss) {
192
+ darkCss.removeAttribute('disabled');
193
+ }
194
+ if (lightCss) {
195
+ lightCss.setAttribute('disabled', '');
196
+ }
197
+ } else {
198
+ if (lightCss) {
199
+ lightCss.removeAttribute('disabled');
200
+ }
201
+ if (darkCss) {
202
+ darkCss.setAttribute('disabled', '');
203
+ }
204
+ }
205
+
206
+ setTimeout(function() {
207
+ // 设置代码块组件样式
208
+ document.querySelectorAll('.markdown-body pre').forEach((pre) => {
209
+ var cls = LNote.utils.getBackgroundLightness(pre) >= 0 ? 'code-widget-light' : 'code-widget-dark';
210
+ var widget = pre.querySelector('.code-widget-light, .code-widget-dark');
211
+ if (widget) {
212
+ widget.classList.remove('code-widget-light', 'code-widget-dark');
213
+ widget.classList.add(cls);
214
+ }
215
+ });
216
+ }, 200);
217
+ }
218
+
219
+ function setApplications(schema) {
220
+ // 设置 remark42 评论主题
221
+ if (window.REMARK42) {
222
+ window.REMARK42.changeTheme(schema);
223
+ }
224
+
225
+ // 设置 cusdis 评论主题
226
+ if (window.CUSDIS) {
227
+ window.CUSDIS.setTheme(schema);
228
+ }
229
+
230
+ // 设置 utterances 评论主题
231
+ var utterances = document.querySelector('.utterances-frame');
232
+ if (utterances) {
233
+ var utterancesTheme = schema === 'dark' ? window.UtterancesThemeDark : window.UtterancesThemeLight;
234
+ const message = {
235
+ type : 'set-theme',
236
+ theme: utterancesTheme
237
+ };
238
+ utterances.contentWindow.postMessage(message, 'https://utteranc.es');
239
+ }
240
+
241
+ // 设置 giscus 评论主题
242
+ var giscus = document.querySelector('iframe.giscus-frame');
243
+ if (giscus) {
244
+ var giscusTheme = schema === 'dark' ? window.GiscusThemeDark : window.GiscusThemeLight;
245
+ const message = {
246
+ setConfig: {
247
+ theme: giscusTheme,
248
+ }
249
+ };
250
+ giscus.contentWindow.postMessage({ 'giscus': message }, 'https://giscus.app');
251
+ }
252
+ }
253
+
254
+ // 当页面加载时,将显示模式设置为 localStorage 中自定义的值(如果有的话)
255
+ applyCustomColorSchemaSettings();
256
+
257
+ LNote.utils.waitElementLoaded(colorToggleIconSelector, function() {
258
+ applyCustomColorSchemaSettings();
259
+ var button = document.querySelector(colorToggleButtonSelector);
260
+ if (button) {
261
+ // 当用户点击切换按钮时,获得新的显示模式、写入 localStorage、并在页面上生效
262
+ button.addEventListener('click', function() {
263
+ applyCustomColorSchemaSettings(toggleCustomColorSchema());
264
+ });
265
+ var icon = document.querySelector(colorToggleIconSelector);
266
+ if (icon) {
267
+ // 光标悬停在按钮上时,切换图标
268
+ button.addEventListener('mouseenter', function() {
269
+ var current = icon.getAttribute('data');
270
+ icon.classList.replace(getIconClass(invertColorSchemaObj[current]), getIconClass(current));
271
+ });
272
+ button.addEventListener('mouseleave', function() {
273
+ var current = icon.getAttribute('data');
274
+ icon.classList.replace(getIconClass(current), getIconClass(invertColorSchemaObj[current]));
275
+ });
276
+ }
277
+ }
278
+ });
279
+ })(window, document);
@@ -0,0 +1,72 @@
1
+ LNote.events = {
2
+ registerNavbarEvent() {
3
+ const $navbar = document.getElementById('navbar')
4
+ if (!$navbar) {
5
+ return
6
+ }
7
+
8
+ function $navUd() {
9
+ const top = window.scrollY || document.documentElement.scrollTop
10
+ if (top > 0) {
11
+ $navbar.classList.remove('navbar-dark')
12
+ if (top > 50) {
13
+ $navbar.classList.add('top-nav-collapse')
14
+ } else {
15
+ $navbar.classList.remove('top-nav-collapse')
16
+ }
17
+ } else {
18
+ $navbar.classList.add('navbar-dark')
19
+ }
20
+ }
21
+ $navUd()
22
+ LNote.utils.listenScroll($navUd)
23
+
24
+ document
25
+ .getElementById('navbar-toggler-btn')
26
+ .addEventListener('click', (e) => {
27
+ document
28
+ .querySelector('.animated-icon')
29
+ .classList.toggle('open')
30
+ $navbar.classList.toggle('navbar-col-show')
31
+ })
32
+ },
33
+
34
+ /* registerImageLoadedEvent: function () {
35
+ if (!('NProgress' in window)) {
36
+ return
37
+ }
38
+
39
+ var bg = document.getElementById('banner')
40
+ if (bg) {
41
+ var src = bg.style.backgroundImage
42
+ var url = src.match(/\((.*?)\)/)[1].replace(/(['"])/g, '')
43
+ var img = new Image()
44
+ img.onload = function () {
45
+ window.NProgress && window.NProgress.inc(0.2)
46
+ }
47
+ img.src = url
48
+ if (img.complete) {
49
+ img.onload()
50
+ }
51
+ }
52
+
53
+ var notLazyImages = jQuery('main img:not([lazyload])')
54
+ var total = notLazyImages.length
55
+ for (const img of notLazyImages) {
56
+ const old = img.onload
57
+ img.onload = function () {
58
+ old && old()
59
+ window.NProgress && window.NProgress.inc(0.5 / total)
60
+ img.onload = null
61
+ }
62
+ if (img.complete) {
63
+ img.onload()
64
+ }
65
+ }
66
+ }, */
67
+ }
68
+
69
+ document.addEventListener('DOMContentLoaded', function () {
70
+ LNote.events.registerNavbarEvent()
71
+ // LNote.events.registerImageLoadedEvent()
72
+ })
@@ -0,0 +1,10 @@
1
+ /* global LNote, CONFIG */
2
+
3
+ (function(window, document) {
4
+ for (const each of document.querySelectorAll('img[lazyload]')) {
5
+ LNote.utils.waitElementVisible(each, function() {
6
+ each.removeAttribute('srcset');
7
+ each.removeAttribute('lazyload');
8
+ }, 2);
9
+ }
10
+ })(window, document);
@@ -0,0 +1,70 @@
1
+ ;(() => {
2
+ const $modal = document.getElementById('modalSearch')
3
+ const $input = document.getElementById('modalSearchInput')
4
+ const $result = document.getElementById('modalSearchResult')
5
+ let inputThol
6
+
7
+ let dataSource
8
+ function fetchData() {
9
+ if (dataSource != null) {
10
+ return
11
+ }
12
+ $result.innerHTML =
13
+ '<div class="m-auto text-center"><div class="spinner-grow text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>'
14
+ fetch(LNote.root + 'content.json')
15
+ .then((rep) => rep.json())
16
+ .then((res) => (dataSource = res))
17
+ .finally(() => ($result.innerHTML = ''))
18
+ }
19
+
20
+ $modal.addEventListener('show.bs.modal', () => {
21
+ fetchData()
22
+ $input.focus()
23
+ })
24
+
25
+ $modal.addEventListener('hidden.bs.modal', () => {
26
+ console.log('hide')
27
+ })
28
+
29
+ $input.addEventListener('input', (e) => {
30
+ if (dataSource == null) {
31
+ return
32
+ }
33
+ clearTimeout(inputThol)
34
+ inputThol = setTimeout(() => {
35
+ const kw = e.target.value.trim()
36
+ if (kw === '') {
37
+ return
38
+ }
39
+ const matchedList = dataSource.filter((item) => {
40
+ return item.excerpt.includes(kw) || item.title.includes(kw)
41
+ })
42
+ if (matchedList.length > 0) {
43
+ e.target.classList.remove('invalid')
44
+ e.target.classList.add('valid')
45
+ const { root } = LNote
46
+ $result.innerHTML = matchedList
47
+ .map((item) => {
48
+ let { excerpt, title } = item
49
+ if (excerpt.includes(kw)) {
50
+ excerpt = excerpt.replace(
51
+ kw,
52
+ `<span class="text-success-emphasis">${kw}</span>`
53
+ )
54
+ } else if (title.includes(kw)) {
55
+ title = title.replace(
56
+ kw,
57
+ `<span class="text-success-emphasis">${kw}</span>`
58
+ )
59
+ }
60
+
61
+ return `<div><a href="${root}${item.path}" class="fs-5 link-warning">${title}</a><p>${excerpt}</p></div>`
62
+ })
63
+ .join('')
64
+ } else {
65
+ e.target.classList.remove('valid')
66
+ e.target.classList.add('invalid')
67
+ }
68
+ }, 500)
69
+ })
70
+ })()
@@ -0,0 +1,34 @@
1
+ ;(() => {
2
+ if (!'ClipboardJS' in window) {
3
+ return
4
+ }
5
+
6
+ function genSVG(id) {
7
+ return `<svg width="1em" height="1em"><use xlink:href="#${id}"/></svg>`
8
+ }
9
+
10
+ const codes = document.querySelectorAll('.markdown-body .highlight')
11
+ codes.forEach((item) => {
12
+ const btn = document.createElement('button')
13
+ btn.type = 'button'
14
+ btn.classList.add('btn-clipboard')
15
+ btn.title = 'Copy to clipboard'
16
+ btn.innerHTML = genSVG('clipboard')
17
+ item.insertAdjacentElement('afterbegin', btn)
18
+ })
19
+
20
+ const clipboard = new ClipboardJS('.btn-clipboard', {
21
+ target: function (trigger) {
22
+ return trigger.parentNode.getElementsByTagName('code')[0]
23
+ },
24
+ })
25
+ clipboard.on('success', function (e) {
26
+ e.clearSelection()
27
+ e.trigger.innerHTML = genSVG('check')
28
+ e.trigger.title = 'Copied!'
29
+ setTimeout(function () {
30
+ e.trigger.innerHTML = genSVG('clipboard')
31
+ e.trigger.title = 'Copy to clipboard'
32
+ }, 2000)
33
+ })
34
+ })()
@@ -0,0 +1,8 @@
1
+ ;(() => {
2
+ const popoverTriggerList = document.querySelectorAll(
3
+ '[data-bs-toggle="popover"]'
4
+ )
5
+ const popoverList = [...popoverTriggerList].map(
6
+ (popoverTriggerEl) => new bootstrap.Popover(popoverTriggerEl)
7
+ )
8
+ })()
@@ -0,0 +1,47 @@
1
+ ;(() => {
2
+ const imgs = document.querySelectorAll('.markdown-body img')
3
+ const promiseds = Array.prototype.map.call(imgs, (item) => {
4
+ return new Promise((resolve, reject) => {
5
+ const src = item.getAttribute('src')
6
+ const __img = new Image()
7
+ __img.onload = function () {
8
+ const a = document.createElement('a')
9
+ a.href = src
10
+ a.target = '_blank'
11
+ a.setAttribute('data-pswp-src', src)
12
+ a.setAttribute('data-pswp-width', __img.width)
13
+ a.setAttribute('data-pswp-height', __img.height)
14
+ const parentNode = item.parentNode
15
+ parentNode.removeChild(item)
16
+ a.appendChild(item)
17
+ parentNode.appendChild(a)
18
+ resolve()
19
+ }
20
+ __img.onerror = function () {
21
+ reject()
22
+ }
23
+ __img.src = src
24
+ })
25
+ })
26
+
27
+ Promise.allSettled(promiseds).then(() => {
28
+ const lightbox = new PhotoSwipeLightbox({
29
+ gallery: '#board',
30
+ children: 'a[data-pswp-src]',
31
+ pswpModule: () => PhotoSwipe,
32
+ wheelToZoom: true,
33
+ })
34
+ lightbox.init()
35
+ /* lightbox.on('initialLayout', () => {
36
+ $('.pswp').on('contextmenu.fb', function (e) {
37
+ if (e.button == 2) {
38
+ e.preventDefault()
39
+ }
40
+ return true
41
+ })
42
+ }) */
43
+ /* lightbox.on('destroy', () => {
44
+ console.log('destroy');
45
+ }); */
46
+ })
47
+ })()
@@ -0,0 +1,35 @@
1
+ import PhotoSwipeLightbox from 'https://lib.baomitu.com/photoswipe/5.4.2/photoswipe-lightbox.esm.min.js';
2
+
3
+ const imgs = document.querySelectorAll('.markdown-body img')
4
+ const promiseds = Array.prototype.map.call(imgs, (item) => {
5
+ return new Promise((resolve, reject) => {
6
+ const src = item.getAttribute('src')
7
+ const __img = new Image()
8
+ __img.onload = function () {
9
+ const a = document.createElement('a')
10
+ a.href = src
11
+ a.target = '_blank'
12
+ a.setAttribute('data-pswp-src', src)
13
+ a.setAttribute('data-pswp-width', __img.width)
14
+ a.setAttribute('data-pswp-height', __img.height)
15
+ const parentNode = item.parentNode
16
+ parentNode.removeChild(item)
17
+ a.appendChild(item)
18
+ parentNode.appendChild(a)
19
+ resolve()
20
+ }
21
+ __img.onerror = function () {
22
+ reject()
23
+ }
24
+ __img.src = src
25
+ })
26
+ })
27
+ Promise.allSettled(promiseds).then(() => {
28
+ const lightbox = new PhotoSwipeLightbox({
29
+ gallery: '#board',
30
+ children: 'a[data-pswp-src]',
31
+ pswpModule: () => import('//lib.baomitu.com/photoswipe/5.4.2/photoswipe.esm.min.js'),
32
+ wheelToZoom: true,
33
+ })
34
+ lightbox.init()
35
+ })
@@ -0,0 +1,13 @@
1
+ ;(() => {
2
+ if (!'mermaid' in window) {
3
+ return
4
+ }
5
+ let theme = document.documentElement.getAttribute('data-bs-theme')
6
+ if (theme !== 'dark') {
7
+ theme = 'forest'
8
+ }
9
+ mermaid.initialize({
10
+ theme,
11
+ })
12
+ mermaid.init()
13
+ })()
@@ -0,0 +1,59 @@
1
+ (() => {
2
+ jQuery('.markdown-body :not(a) > img, .markdown-body > img').each(function() {
3
+ var $image = jQuery(this);
4
+ var imageUrl = $image.attr('data-src') || $image.attr('src');
5
+ var $imageWrap = $image.wrap(`
6
+ <a class="fancybox fancybox.image" href="${imageUrl}"
7
+ itemscope itemtype="http://schema.org/ImageObject" itemprop="url"></a>`
8
+ ).parent('a');
9
+ if ($imageWrap.length !== 0) {
10
+ if ($image.is('.group-image-container img')) {
11
+ $imageWrap.attr('data-fancybox', 'group').attr('rel', 'group');
12
+ } else {
13
+ $imageWrap.attr('data-fancybox', 'default').attr('rel', 'default');
14
+ }
15
+
16
+ var imageTitle = $image.attr('title') || $image.attr('alt');
17
+ if (imageTitle) {
18
+ $imageWrap.attr('title', imageTitle).attr('data-caption', imageTitle);
19
+ }
20
+ }
21
+ });
22
+
23
+ jQuery.fancybox.defaults.hash = false;
24
+ jQuery('.fancybox').fancybox({
25
+ protect: true,
26
+ loop: false,
27
+ arrows: true,
28
+ infobar: false,
29
+ toolbar: true,
30
+ buttons : [
31
+ // 'slideShow',
32
+ // 'fullScreen',
33
+ // 'thumbs',
34
+ // 'share',
35
+ //'download',
36
+ // 'zoom',
37
+ 'close'
38
+ ],
39
+ dblclickContent: 'zoom',
40
+ btnTpl: {
41
+ arrowLeft: '<button data-fancybox-prev class="fancybox-button fancybox-button--arrow_left" title="{{PREV}}">' +
42
+ '<svg width="18" height="18">' +
43
+ '<use xlink:href="#chevron-left"></use>' +
44
+ '</svg>' +
45
+ '</button>',
46
+ arrowRight : '<button data-fancybox-next class="fancybox-button fancybox-button--arrow_right" title="{{NEXT}}">' +
47
+ '<svg width="18" height="18">' +
48
+ '<use xlink:href="#chevron-right"></use>' +
49
+ '</svg>' +
50
+ '</button>'
51
+ },
52
+ mobile: {
53
+ // protect: false,
54
+ clickSlide: 'close',
55
+ dblclickContent: 'zoom',
56
+ dblclickSlide: 'zoom'
57
+ }
58
+ });
59
+ })()
@@ -0,0 +1,24 @@
1
+ (() => {
2
+ if (!window.tocbot) {
3
+ return
4
+ }
5
+
6
+ window.tocbot.init({
7
+ tocSelector: '#toc-body',
8
+ contentSelector: '.markdown-body',
9
+ linkClass: 'tocbot-link',
10
+ activeLinkClass: 'tocbot-active-link',
11
+ listClass: 'tocbot-list',
12
+ isCollapsedClass: 'tocbot-is-collapsed',
13
+ collapsibleClass: 'tocbot-is-collapsible',
14
+ scrollSmooth: true,
15
+ includeTitleTags: true,
16
+ // headingsOffset: -boardTop,
17
+ headingSelector: 'h1,h2,h3,h4',
18
+ placement: 'right',
19
+ collapseDepth: 0
20
+ })
21
+
22
+ const toc = document.getElementById('toc')
23
+ toc.style.visibility = 'visible'
24
+ })()
@@ -0,0 +1,27 @@
1
+ ;(() => {
2
+ if (!'Viewer' in window) {
3
+ return
4
+ }
5
+ new Viewer(document.getElementById('board'), {
6
+ backdrop: true,
7
+ button: true,
8
+ focus: true,
9
+ fullscreen: true,
10
+ loading: true,
11
+ loop: true,
12
+ keyboard: true,
13
+ moveable: true,
14
+ navbar: false,
15
+ rotatable: true,
16
+ scalable: true,
17
+ slideOnTouch: true,
18
+ title: true,
19
+ toggleOnDblclick: true,
20
+ toolbar: true,
21
+ tooltip: true,
22
+ transition: true,
23
+ zoomable: true,
24
+ zoomOnTouch: true,
25
+ zoomOnWheel: true
26
+ })
27
+ })()