hexo-theme-lnote 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
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
+ })()