hexo-theme-stellar 1.44.0 → 2.0.0-rc.2

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 (377) hide show
  1. package/CHANGELOG.md +63 -5
  2. package/CONTRIBUTING.md +29 -120
  3. package/README.md +66 -73
  4. package/README_EN.md +66 -73
  5. package/_config.yml +890 -743
  6. package/_data/icons.yml +43 -171
  7. package/_data/widgets.yml +1 -1
  8. package/assets/icon-v2-x512.webp +0 -0
  9. package/languages/en.yml +59 -2
  10. package/languages/zh-CN.yml +59 -2
  11. package/languages/zh-TW.yml +59 -2
  12. package/layout/404.ejs +7 -4
  13. package/layout/_partial/comments/artalk/layout.ejs +3 -2
  14. package/layout/_partial/comments/beaudar/layout.ejs +2 -2
  15. package/layout/_partial/comments/giscus/layout.ejs +2 -5
  16. package/layout/_partial/comments/layout.ejs +11 -40
  17. package/layout/_partial/comments/twikoo/layout.ejs +3 -2
  18. package/layout/_partial/comments/utterances/layout.ejs +2 -2
  19. package/layout/_partial/comments/waline/layout.ejs +3 -2
  20. package/layout/_partial/components/collection-item.ejs +30 -13
  21. package/layout/_partial/components/collection.ejs +2 -2
  22. package/layout/_partial/cover/index.ejs +5 -2
  23. package/layout/_partial/cover/wiki_cover.ejs +39 -28
  24. package/layout/_partial/dropdown.ejs +26 -14
  25. package/layout/_partial/head.ejs +96 -69
  26. package/layout/_partial/main/article/contributors.ejs +12 -9
  27. package/layout/_partial/main/article/post_footer.ejs +47 -0
  28. package/layout/_partial/main/article/post_read_next.ejs +22 -0
  29. package/layout/_partial/main/article/post_related.ejs +14 -0
  30. package/layout/_partial/main/article/post_tags.ejs +12 -0
  31. package/layout/_partial/main/article/share.ejs +55 -0
  32. package/layout/_partial/main/footer.ejs +11 -10
  33. package/layout/_partial/main/{navbar/nav_tabs_blog.ejs → listing_nav/blog.ejs} +21 -18
  34. package/layout/_partial/main/listing_nav/wiki.ejs +56 -0
  35. package/layout/_partial/main/navbar/article_banner.ejs +39 -35
  36. package/layout/_partial/main/navbar/breadcrumb/blog.ejs +15 -28
  37. package/layout/_partial/main/navbar/breadcrumb/note.ejs +12 -5
  38. package/layout/_partial/main/navbar/breadcrumb/wiki.ejs +15 -11
  39. package/layout/_partial/main/navbar/dateinfo.ejs +28 -12
  40. package/layout/_partial/main/navbar/ghinfo.ejs +5 -3
  41. package/layout/_partial/main/notebook/note_card.ejs +12 -17
  42. package/layout/_partial/main/notebook/note_tags.ejs +3 -4
  43. package/layout/_partial/main/notebook/notebook_card.ejs +11 -4
  44. package/layout/_partial/main/pin_slider.ejs +48 -43
  45. package/layout/_partial/main/post_list/archive_item.ejs +8 -4
  46. package/layout/_partial/main/post_list/latest_post_card.ejs +10 -4
  47. package/layout/_partial/main/post_list/post_card.ejs +39 -90
  48. package/layout/_partial/main/post_list/topic_card.ejs +7 -5
  49. package/layout/_partial/main/post_list/wiki_card.ejs +16 -13
  50. package/layout/_partial/menubtn.ejs +3 -3
  51. package/layout/_partial/primitives/item.ejs +8 -0
  52. package/layout/_partial/primitives/navigation.ejs +17 -0
  53. package/layout/_partial/primitives/region.ejs +16 -0
  54. package/layout/_partial/primitives/section.ejs +8 -0
  55. package/layout/_partial/primitives/shell.ejs +35 -0
  56. package/layout/_partial/regions/widgets.ejs +84 -0
  57. package/layout/_partial/scripts/defines.ejs +46 -76
  58. package/layout/_partial/scripts/runtime.ejs +55 -0
  59. package/layout/_partial/scripts.ejs +18 -42
  60. package/layout/_partial/search/dialog.ejs +33 -0
  61. package/layout/_partial/search/shortcut.ejs +1 -0
  62. package/layout/_partial/sidebar/brand.ejs +127 -0
  63. package/layout/_partial/sidebar/menu.ejs +59 -14
  64. package/layout/_partial/sidebar/search.ejs +58 -41
  65. package/layout/_partial/widgets/actions.ejs +25 -0
  66. package/layout/_partial/widgets/author.ejs +9 -5
  67. package/layout/_partial/widgets/components/linklist.ejs +1 -2
  68. package/layout/_partial/widgets/ghissues.ejs +7 -10
  69. package/layout/_partial/widgets/ghrepo.ejs +23 -16
  70. package/layout/_partial/widgets/ghuser.ejs +3 -3
  71. package/layout/_partial/widgets/recent.ejs +25 -21
  72. package/layout/_partial/widgets/related.ejs +25 -34
  73. package/layout/_partial/widgets/settings.ejs +17 -0
  74. package/layout/_partial/widgets/tagtree.ejs +18 -10
  75. package/layout/_partial/widgets/toc.ejs +17 -9
  76. package/layout/_partial/widgets/tree.ejs +12 -13
  77. package/layout/archive.ejs +20 -13
  78. package/layout/categories.ejs +4 -3
  79. package/layout/collection-preview.ejs +8 -9
  80. package/layout/index.ejs +32 -43
  81. package/layout/index_topic.ejs +6 -13
  82. package/layout/index_wiki.ejs +17 -34
  83. package/layout/layout.ejs +195 -65
  84. package/layout/notebooks.ejs +3 -3
  85. package/layout/notes.ejs +4 -4
  86. package/layout/page.ejs +95 -50
  87. package/layout/settings.ejs +109 -0
  88. package/layout/tags.ejs +4 -3
  89. package/{THIRD-PARTY-NOTICES.md → legal/THIRD-PARTY-NOTICES.md} +8 -4
  90. package/package.json +28 -6
  91. package/scripts/commands/stellar.js +55 -0
  92. package/scripts/events/index.js +15 -9
  93. package/scripts/events/lib/authors.js +9 -7
  94. package/scripts/events/lib/config-hot-reload.js +65 -0
  95. package/scripts/events/lib/config-schema.js +20 -0
  96. package/scripts/events/lib/config.js +22 -63
  97. package/scripts/events/lib/content-config.js +5 -0
  98. package/scripts/events/lib/doc_tree.js +99 -9
  99. package/scripts/events/lib/links.js +6 -3
  100. package/scripts/events/lib/notebooks.js +200 -8
  101. package/scripts/events/lib/utils.js +4 -4
  102. package/scripts/events/lib/version-check.js +57 -3
  103. package/scripts/filters/index.js +2 -27
  104. package/scripts/filters/lib/img_lazyload.js +4 -126
  105. package/scripts/filters/lib/img_onerror.js +14 -17
  106. package/scripts/filters/lib/page-view-model.js +152 -0
  107. package/scripts/generators/404.js +13 -8
  108. package/scripts/generators/author.js +16 -11
  109. package/scripts/generators/notebooks.js +68 -39
  110. package/scripts/generators/search.js +62 -67
  111. package/scripts/generators/settings.js +43 -0
  112. package/scripts/generators/stellar-icons.js +13 -5
  113. package/scripts/generators/topic.js +24 -13
  114. package/scripts/generators/wiki.js +49 -21
  115. package/scripts/helpers/ai_label.js +6 -12
  116. package/scripts/helpers/brand.js +17 -0
  117. package/scripts/helpers/browser_runtime_manifest.js +12 -0
  118. package/scripts/helpers/caption.js +8 -0
  119. package/scripts/helpers/category_color.js +13 -13
  120. package/scripts/helpers/collection.js +18 -0
  121. package/scripts/helpers/comments_model.js +14 -0
  122. package/scripts/helpers/extension_assets.js +8 -0
  123. package/scripts/helpers/json_ld.js +16 -7
  124. package/scripts/helpers/mdrender.js +3 -9
  125. package/scripts/helpers/menu.js +9 -0
  126. package/scripts/helpers/post_view_model.js +23 -0
  127. package/scripts/helpers/regions.js +37 -0
  128. package/scripts/helpers/scrollreveal.js +7 -7
  129. package/scripts/helpers/search_domain.js +34 -0
  130. package/scripts/helpers/service_provider.js +9 -0
  131. package/scripts/helpers/settings.js +16 -0
  132. package/scripts/helpers/share_action.js +8 -0
  133. package/scripts/helpers/stellar_config.js +12 -0
  134. package/scripts/helpers/stellar_data.js +8 -0
  135. package/scripts/helpers/stellar_info.js +21 -16
  136. package/scripts/helpers/stellar_inject.js +9 -0
  137. package/scripts/helpers/ui_classes.js +12 -0
  138. package/scripts/lib/ai_label.js +14 -11
  139. package/scripts/lib/brand.js +41 -0
  140. package/scripts/lib/browser-runtime.js +115 -0
  141. package/scripts/lib/caption.js +21 -0
  142. package/scripts/lib/collection-pipeline/adapters/notebook.js +62 -0
  143. package/scripts/lib/collection-pipeline/adapters/post.js +20 -0
  144. package/scripts/lib/collection-pipeline/adapters/topic.js +82 -0
  145. package/scripts/lib/collection-pipeline/adapters/wiki.js +20 -0
  146. package/scripts/lib/collection-pipeline/index.js +169 -0
  147. package/scripts/lib/collection-pipeline/registry.js +27 -0
  148. package/scripts/lib/collection-pipeline/shared.js +164 -0
  149. package/scripts/lib/comments.js +60 -0
  150. package/scripts/lib/config-inject.js +20 -0
  151. package/scripts/lib/config-schema.js +1095 -0
  152. package/scripts/lib/content-config.js +157 -0
  153. package/scripts/lib/content-defaults.js +56 -0
  154. package/scripts/lib/content-membership.js +233 -0
  155. package/scripts/lib/contribution-contract.js +165 -0
  156. package/scripts/lib/contribution-registry.js +429 -0
  157. package/scripts/lib/doc_tree.js +46 -44
  158. package/scripts/lib/doctor.js +296 -0
  159. package/scripts/lib/front-matter.js +29 -0
  160. package/scripts/lib/hero-effect-registry.js +262 -0
  161. package/scripts/lib/html-images.js +128 -0
  162. package/scripts/lib/internal-constants.js +152 -0
  163. package/scripts/lib/layout-config.js +62 -0
  164. package/scripts/lib/mdrender_html.js +36 -23
  165. package/scripts/lib/menu.js +36 -0
  166. package/scripts/lib/model-schema.js +90 -0
  167. package/scripts/lib/models/index.js +1542 -0
  168. package/scripts/lib/new-note.js +172 -0
  169. package/scripts/lib/page-view-model-registry.js +103 -0
  170. package/scripts/lib/regions.js +132 -0
  171. package/scripts/lib/runtime-data.js +23 -0
  172. package/scripts/lib/safe-path.js +44 -0
  173. package/scripts/lib/search-domain.js +59 -0
  174. package/scripts/lib/seo.js +10 -10
  175. package/scripts/lib/service-provider.js +12 -0
  176. package/scripts/lib/settings.js +16 -0
  177. package/scripts/lib/share-services.js +96 -0
  178. package/scripts/lib/source-config.js +27 -0
  179. package/scripts/lib/theme-metadata.js +22 -0
  180. package/scripts/lib/ui-capabilities.js +32 -0
  181. package/scripts/lib/widget-registry.js +150 -0
  182. package/scripts/lib/wiki_readme.js +15 -11
  183. package/scripts/schema/config-rules.js +290 -0
  184. package/scripts/schema/config-schema.js +163 -0
  185. package/scripts/schema/content-config-rules.js +264 -0
  186. package/scripts/schema/content-config-schema.js +321 -0
  187. package/scripts/schema/model-schema.js +971 -0
  188. package/scripts/schema/schema-utils.js +48 -0
  189. package/scripts/tags/index.js +2 -3
  190. package/scripts/tags/lib/albums.js +6 -6
  191. package/scripts/tags/lib/banner.js +10 -4
  192. package/scripts/tags/lib/box.js +1 -1
  193. package/scripts/tags/lib/button.js +1 -1
  194. package/scripts/tags/lib/chat.js +9 -31
  195. package/scripts/tags/lib/checkbox.js +6 -1
  196. package/scripts/tags/lib/copy.js +4 -1
  197. package/scripts/tags/lib/dropdown.js +6 -4
  198. package/scripts/tags/lib/emoji.js +5 -10
  199. package/scripts/tags/lib/friends.js +4 -4
  200. package/scripts/tags/lib/gallery.js +7 -7
  201. package/scripts/tags/lib/ghcard.js +5 -3
  202. package/scripts/tags/lib/gist.js +16 -0
  203. package/scripts/tags/lib/grid.js +4 -2
  204. package/scripts/tags/lib/hashtag.js +1 -1
  205. package/scripts/tags/lib/icon.js +1 -1
  206. package/scripts/tags/lib/image.js +1 -1
  207. package/scripts/tags/lib/link.js +6 -3
  208. package/scripts/tags/lib/mark.js +8 -3
  209. package/scripts/tags/lib/md.js +1 -1
  210. package/scripts/tags/lib/note.js +1 -1
  211. package/scripts/tags/lib/okr.js +18 -1
  212. package/scripts/tags/lib/posters.js +6 -6
  213. package/scripts/tags/lib/quot.js +15 -5
  214. package/scripts/tags/lib/rating.js +7 -4
  215. package/scripts/tags/lib/sites.js +8 -6
  216. package/scripts/tags/lib/tip.js +6 -6
  217. package/scripts/tags/lib/toc.js +2 -2
  218. package/scripts/tags/lib/vote.js +8 -5
  219. package/source/css/_appearances/_mixins.styl +258 -0
  220. package/source/css/_appearances/card.styl +30 -0
  221. package/source/css/_appearances/flat.styl +44 -0
  222. package/source/css/_appearances/glass.styl +138 -0
  223. package/source/css/_appearances/minimal.styl +325 -0
  224. package/source/css/_common/base.styl +5 -9
  225. package/source/css/_common/blockquote.styl +0 -1
  226. package/source/css/_common/button.styl +1 -1
  227. package/source/css/_common/device.styl +24 -42
  228. package/source/css/_common/dropdown.styl +20 -14
  229. package/source/css/_common/highlight.styl +5 -12
  230. package/source/css/_common/icon.styl +38 -0
  231. package/source/css/_common/input.styl +33 -0
  232. package/source/css/_common/loading.styl +2 -2
  233. package/source/css/_common/svg.styl +0 -8
  234. package/source/css/_components/collection.styl +21 -64
  235. package/source/css/_components/layout.styl +524 -84
  236. package/source/css/_components/list.styl +36 -22
  237. package/source/css/_components/main.styl +16 -19
  238. package/source/css/_components/md.styl +8 -13
  239. package/source/css/_components/pages/article-indent.styl +1 -1
  240. package/source/css/_components/pages/article-story.styl +7 -6
  241. package/source/css/_components/pages/article-tech.styl +5 -5
  242. package/source/css/_components/pages/collection-preview.styl +1 -5
  243. package/source/css/_components/pages/settings.styl +184 -0
  244. package/source/css/_components/partial/article-banner.styl +2 -2
  245. package/source/css/_components/partial/article-footer.styl +0 -32
  246. package/source/css/_components/partial/article-share.styl +48 -0
  247. package/source/css/_components/partial/article-tags.styl +1 -1
  248. package/source/css/_components/partial/cover.styl +13 -13
  249. package/source/css/_components/partial/listing-nav.styl +68 -0
  250. package/source/css/_components/partial/paginator.styl +1 -1
  251. package/source/css/_components/pin-slider.styl +3 -3
  252. package/source/css/_components/sidebar/brand.styl +135 -0
  253. package/source/css/_components/sidebar/footer.styl +14 -31
  254. package/source/css/_components/sidebar/nav-area.styl +4 -0
  255. package/source/css/_components/sidebar/search.styl +176 -26
  256. package/source/css/_components/sidebar/sidebar.styl +76 -110
  257. package/source/css/_components/tag-plugins/banner.styl +16 -28
  258. package/source/css/_components/tag-plugins/checkbox.styl +7 -22
  259. package/source/css/_components/tag-plugins/copy.styl +3 -5
  260. package/source/css/_components/tag-plugins/gallery.styl +2 -2
  261. package/source/css/_components/tag-plugins/grid.styl +3 -0
  262. package/source/css/_components/tag-plugins/image.styl +2 -1
  263. package/source/css/_components/tag-plugins/link.styl +0 -1
  264. package/source/css/_components/tag-plugins/mark.styl +19 -4
  265. package/source/css/_components/tag-plugins/mdrender.styl +2 -2
  266. package/source/css/_components/tag-plugins/navbar.styl +23 -17
  267. package/source/css/_components/tag-plugins/note.styl +2 -2
  268. package/source/css/_components/tag-plugins/okr.styl +1 -2
  269. package/source/css/_components/tag-plugins/quot.styl +5 -0
  270. package/source/css/_components/tag-plugins/rating.styl +3 -2
  271. package/source/css/_components/tag-plugins/timeline.styl +1 -1
  272. package/source/css/_components/tag-plugins/tip.styl +1 -1
  273. package/source/css/_components/tag-plugins/vote.styl +3 -2
  274. package/source/css/_components/widgets/ghrepo.styl +2 -1
  275. package/source/css/_components/widgets/ghuser.styl +4 -6
  276. package/source/css/_components/widgets/settings.styl +49 -0
  277. package/source/css/_components/widgets/timeline.styl +2 -2
  278. package/source/css/_components/widgets/toc.styl +12 -33
  279. package/source/css/_components/widgets/widgets.styl +14 -19
  280. package/source/css/_components/wiki-card.styl +2 -2
  281. package/source/css/_custom.styl +26 -32
  282. package/source/css/_defines/func.styl +47 -37
  283. package/source/css/_defines/theme_base.styl +8 -10
  284. package/source/css/_plugins/card-hover.styl +1 -1
  285. package/source/css/_plugins/copycode.styl +16 -19
  286. package/source/css/_plugins/index.styl +3 -8
  287. package/source/css/_plugins/lazyload.styl +1 -1
  288. package/source/css/main.styl +12 -0
  289. package/source/js/main.js +302 -59
  290. package/source/js/plugins/adaptive-text.js +33 -16
  291. package/source/js/plugins/card-hover.js +2 -24
  292. package/source/js/plugins/copycode.js +10 -16
  293. package/source/js/plugins/voice.js +51 -48
  294. package/source/js/profile.js +316 -0
  295. package/source/js/runtime/asset-loader.js +61 -0
  296. package/source/js/runtime/extension-registry.js +149 -0
  297. package/source/js/runtime/extensions/card-hover.js +5 -0
  298. package/source/js/runtime/extensions/color-scheme-switch.js +101 -0
  299. package/source/js/runtime/extensions/comments.js +200 -0
  300. package/source/js/runtime/extensions/deferred-icons.js +53 -0
  301. package/source/js/{plugins → runtime/extensions}/dropdown.js +69 -30
  302. package/source/js/runtime/extensions/feature.js +200 -0
  303. package/source/js/runtime/extensions/hero-effect.js +179 -0
  304. package/source/js/runtime/extensions/reveal.js +80 -0
  305. package/source/js/runtime/extensions/search.js +23 -0
  306. package/source/js/{services.js → runtime/extensions/services.js} +67 -54
  307. package/source/js/runtime/extensions/settings.js +235 -0
  308. package/source/js/runtime/hero-effects/ferrofluid.js +385 -0
  309. package/source/js/{plugins → runtime/hero-effects}/galaxy.js +53 -177
  310. package/source/js/runtime/hero-effects/light-rays.js +293 -0
  311. package/source/js/runtime/index.js +75 -0
  312. package/source/js/runtime/legacy-request-adapter.js +47 -0
  313. package/source/js/runtime/request-cache.js +219 -0
  314. package/source/js/search/algolia-search.js +76 -51
  315. package/source/js/search/highlight.js +1 -1
  316. package/source/js/search/local-search.js +96 -57
  317. package/source/js/search/shortcut.js +31 -20
  318. package/source/js/services/friends_and_posts.js +6 -1
  319. package/source/js/services/rating.js +14 -6
  320. package/source/js/services/siteinfo.js +3 -7
  321. package/source/js/services/timeline.js +1 -1
  322. package/source/js/services/vote.js +7 -5
  323. package/source/js/services/weibo.js +1 -1
  324. package/source/js/utils.js +19 -444
  325. package/.claude/skills/stellar-theme-dev/SKILL.md +0 -51
  326. package/_data/chat_users.yml +0 -0
  327. package/layout/_partial/comments/artalk/script.ejs +0 -76
  328. package/layout/_partial/comments/beaudar/script.ejs +0 -33
  329. package/layout/_partial/comments/giscus/script.ejs +0 -31
  330. package/layout/_partial/comments/script.ejs +0 -3
  331. package/layout/_partial/comments/twikoo/script.ejs +0 -25
  332. package/layout/_partial/comments/utterances/script.ejs +0 -33
  333. package/layout/_partial/comments/waline/script.ejs +0 -43
  334. package/layout/_partial/main/article/article_footer.ejs +0 -164
  335. package/layout/_partial/main/article/article_tags.ejs +0 -16
  336. package/layout/_partial/main/article/read_next.ejs +0 -63
  337. package/layout/_partial/main/article/related_posts.ejs +0 -16
  338. package/layout/_partial/main/navbar/nav_tabs_wiki.ejs +0 -52
  339. package/layout/_partial/scripts/bootstrap.ejs +0 -37
  340. package/layout/_partial/scripts/lazyload.ejs +0 -89
  341. package/layout/_partial/sidebar/grad-def.ejs +0 -26
  342. package/layout/_partial/sidebar/index_leftbar.ejs +0 -191
  343. package/layout/_partial/sidebar/index_rightbar.ejs +0 -94
  344. package/layout/_partial/sidebar/logo.ejs +0 -99
  345. package/layout/_plugins/adaptive_text.ejs +0 -11
  346. package/layout/_plugins/card_hover.ejs +0 -32
  347. package/layout/_plugins/copycode.ejs +0 -17
  348. package/layout/_plugins/fancybox.ejs +0 -53
  349. package/layout/_plugins/heti.ejs +0 -21
  350. package/layout/_plugins/index.ejs +0 -50
  351. package/layout/_plugins/mathjax.ejs +0 -49
  352. package/layout/_plugins/mermaid.ejs +0 -33
  353. package/layout/_plugins/preload.ejs +0 -9
  354. package/layout/_plugins/scrollreveal.ejs +0 -102
  355. package/layout/_plugins/search/algolia_search.ejs +0 -12
  356. package/layout/_plugins/search/local_search.ejs +0 -9
  357. package/layout/_plugins/swiper.ejs +0 -27
  358. package/layout/_plugins/tianli_gpt.ejs +0 -14
  359. package/scripts/commands/new-note.js +0 -49
  360. package/scripts/events/lib/merge_posts.js +0 -48
  361. package/scripts/events/lib/topic_tree.js +0 -48
  362. package/scripts/helpers/related_posts.js +0 -51
  363. package/scripts/helpers/subtitle.js +0 -8
  364. package/scripts/lib/notebooks.js +0 -181
  365. package/scripts/lib/subtitle.js +0 -28
  366. package/scripts/tags/lib/about.js +0 -48
  367. package/source/css/_components/page-transition.styl +0 -22
  368. package/source/css/_components/partial/navbar.styl +0 -51
  369. package/source/css/_components/sidebar/logo.styl +0 -111
  370. package/source/css/_components/tag-plugins/about.styl +0 -56
  371. package/source/css/_components/widgets/tree.styl +0 -0
  372. package/source/css/_plugins/scrollreveal.styl +0 -6
  373. package/source/css/_plugins/tianli_gpt.styl +0 -213
  374. package/source/css/plugins/mermaid.styl +0 -137
  375. package/source/js/icons.js +0 -60
  376. package/source/js/services/fcircle.js +0 -35
  377. package/source/js/theme.js +0 -61
@@ -3,47 +3,6 @@
3
3
  if (window.__stellarUtilsLoaded) return;
4
4
  window.__stellarUtilsLoaded = true;
5
5
 
6
- function RunItem() {
7
- this.list = []; // 存放回调函数
8
- this.start = () => {
9
- for (var i = 0; i < this.list.length; i++) {
10
- this.list[i].run();
11
- }
12
- };
13
- this.push = (fn, name, setRequestAnimationFrame = true) => {
14
- let myfn = fn
15
- if (setRequestAnimationFrame) {
16
- myfn = () => {
17
- utils.requestAnimationFrame(fn)
18
- }
19
- }
20
- var f = new Item(myfn, name);
21
- this.list.push(f);
22
- };
23
- this.remove = (name) => {
24
- // 倒序遍历避免 splice 后的索引问题
25
- for (let index = this.list.length - 1; index >= 0; index--) {
26
- const e = this.list[index];
27
- if (e.name === name) {
28
- this.list.splice(index, 1);
29
- }
30
- }
31
- }
32
- // 构造一个可以run的对象
33
- function Item(fn, name) {
34
- // 函数名称
35
- this.name = name || fn.name;
36
- // run方法
37
- this.run = () => {
38
- try {
39
- fn()
40
- } catch (error) {
41
- console.log(error);
42
- }
43
- };
44
- }
45
- }
46
-
47
6
  const utils = {
48
7
  // 已加载样式缓存
49
8
  _loadedStyles: new Set(),
@@ -320,329 +279,6 @@
320
279
  }
321
280
  }
322
281
  },
323
- /********************** data cache ********************************/
324
- // 动态数据本地缓存:TTL 未过期直接命中;过期后先显示缓存再后台刷新(stale-while-revalidate)
325
- _cacheEnabled: true,
326
- _cacheMaxEntryBytes: 200 * 1024,
327
- // 同 URL 并发请求去重:页面内多个组件请求同一接口时共享一次 fetch
328
- _pendingRequests: {},
329
- _fetchShared: (url, options) => {
330
- const key = (options && options.method || 'GET') + ' ' + url;
331
- if (utils._pendingRequests[key]) {
332
- return utils._pendingRequests[key].then(resp => resp.clone());
333
- }
334
- const promise = fetch(url, options).then(resp => {
335
- if (!resp.ok) throw new Error('响应失败');
336
- return resp;
337
- }).finally(() => {
338
- delete utils._pendingRequests[key];
339
- });
340
- utils._pendingRequests[key] = promise;
341
- // 每个调用方各自 clone,避免 Response body 被消费后其他调用方取不到数据
342
- return promise.then(resp => resp.clone());
343
- },
344
- // 延迟执行:缓存写入等非关键操作让出主线程
345
- _defer: (fn) => {
346
- if (window.requestIdleCallback) {
347
- window.requestIdleCallback(fn, { timeout: 3000 });
348
- } else {
349
- setTimeout(fn, 0);
350
- }
351
- },
352
- cache: {
353
- prefix: 'Stellar.data_cache.v1.',
354
- enabled: () => !!def.data_cache?.enable && utils._cacheEnabled,
355
- serviceId: (el, options) => {
356
- if (options && options.service) return options.service;
357
- if (el) {
358
- const match = String(el.className || '').match(/\bds-([\w-]+)\b/);
359
- if (match) return match[1];
360
- }
361
- return null;
362
- },
363
- ttl: (el, options) => {
364
- const conf = def.data_cache || {};
365
- const id = utils.cache.serviceId(el, options);
366
- const value = id && conf.ttl && conf.ttl[id] != null ? conf.ttl[id] : conf.default_ttl;
367
- return typeof value === 'number' && value > 0 ? value : 0;
368
- },
369
- shouldCache: (url, options) => {
370
- if (!utils.cache.enabled()) return false;
371
- if (options && (options.cache === false || options.cache === 'no-store')) return false;
372
- if (options && options.method && options.method !== 'GET') return false;
373
- // 带时间戳缓存破坏参数的请求不缓存(如 mdrender 的 ?t=)
374
- if (/[?&]t=\d{10,}/.test(url)) return false;
375
- return true;
376
- },
377
- get: (url) => {
378
- try {
379
- const raw = localStorage.getItem(utils.cache.prefix + url);
380
- if (!raw) return null;
381
- const entry = JSON.parse(raw);
382
- if (!entry || typeof entry.text !== 'string' || typeof entry.ts !== 'number') return null;
383
- return entry;
384
- } catch (e) {
385
- console.warn('[cache] 读取失败:', url, e);
386
- return null;
387
- }
388
- },
389
- set: (url, text, contentType, ttl) => {
390
- if (!(ttl > 0)) return;
391
- if (text.length > utils._cacheMaxEntryBytes) return;
392
- const entry = JSON.stringify({
393
- text: text,
394
- contentType: contentType || 'application/json',
395
- ts: Date.now(),
396
- ttl: ttl
397
- });
398
- const trySet = () => {
399
- try {
400
- localStorage.setItem(utils.cache.prefix + url, entry);
401
- utils.cache.trim();
402
- return true;
403
- } catch (e) {
404
- return false;
405
- }
406
- };
407
- if (!trySet()) {
408
- // 配额不足时淘汰最旧条目后重试一次,仍失败则本会话禁用缓存
409
- utils.cache.evictOldest(url);
410
- if (!trySet()) {
411
- console.warn('[cache] 写入失败,本会话禁用缓存:', url);
412
- utils._cacheEnabled = false;
413
- }
414
- }
415
- },
416
- trim: () => {
417
- try {
418
- const max = (def.data_cache && def.data_cache.max_entries) || 200;
419
- const keys = [];
420
- for (let i = 0; i < localStorage.length; i++) {
421
- const key = localStorage.key(i);
422
- if (key && key.indexOf(utils.cache.prefix) === 0) keys.push(key);
423
- }
424
- if (keys.length <= max) return;
425
- const sorted = keys.map((key) => {
426
- let ts = 0;
427
- try {
428
- const entry = JSON.parse(localStorage.getItem(key) || 'null');
429
- if (entry && typeof entry.ts === 'number') ts = entry.ts;
430
- } catch (e) {}
431
- return { key, ts };
432
- }).sort((a, b) => a.ts - b.ts);
433
- for (let i = 0; i < sorted.length - max; i++) {
434
- localStorage.removeItem(sorted[i].key);
435
- }
436
- } catch (e) {
437
- console.warn('[cache] 清理失败:', e);
438
- }
439
- },
440
- evictOldest: (exceptUrl) => {
441
- try {
442
- let oldestKey = null;
443
- let oldestTs = Infinity;
444
- const exceptKey = utils.cache.prefix + exceptUrl;
445
- for (let i = 0; i < localStorage.length; i++) {
446
- const key = localStorage.key(i);
447
- if (!key || key.indexOf(utils.cache.prefix) !== 0 || key === exceptKey) continue;
448
- let ts = 0;
449
- try {
450
- const entry = JSON.parse(localStorage.getItem(key) || 'null');
451
- if (entry && typeof entry.ts === 'number') ts = entry.ts;
452
- } catch (e) {}
453
- if (ts < oldestTs) {
454
- oldestTs = ts;
455
- oldestKey = key;
456
- }
457
- }
458
- if (oldestKey) localStorage.removeItem(oldestKey);
459
- } catch (e) {}
460
- },
461
- isFresh: (entry) => {
462
- if (!entry || typeof entry.ts !== 'number' || typeof entry.ttl !== 'number') return false;
463
- if (!(entry.ttl > 0)) return false;
464
- return Date.now() - entry.ts < entry.ttl * 1000;
465
- },
466
- // 用缓存文本重建 Response,兼容回调中的 resp.json() / resp.text()
467
- toResponse: (entry) => new Response(entry.text, {
468
- status: 200,
469
- statusText: 'OK',
470
- headers: { 'Content-Type': entry.contentType }
471
- })
472
- },
473
- request: (el, url, callback, onFailure, options) => {
474
- // 检查元素实例是否已加载 (而不是检查属性)
475
- if (el && utils._loadedElements.has(el)) {
476
- return;
477
- }
478
- const maxRetry = 3;
479
- let retryCount = 0;
480
- const ttl = utils.cache.ttl(el, options);
481
- const cacheable = utils.cache.shouldCache(url, options) && ttl > 0;
482
- const cached = cacheable ? utils.cache.get(url) : null;
483
- // 缓存渲染前的初始结构,后台刷新渲染前恢复,避免重复渲染
484
- let initialHTML = null;
485
- // 缓存渲染完成后(或超时兜底)再启动后台刷新,避免异步渲染未结束就清空重绘
486
- let cacheRenderDone = null;
487
-
488
- if (cached) {
489
- if (el) {
490
- // 已有缓存时不显示加载动画
491
- utils.onLoadSuccess?.(el);
492
- initialHTML = el.innerHTML;
493
- }
494
- try {
495
- cacheRenderDone = Promise.resolve(callback(utils.cache.toResponse(cached))).catch(e => {
496
- console.warn('[request] 缓存渲染失败:', url, e);
497
- });
498
- } catch (e) {
499
- console.warn('[request] 缓存渲染失败:', url, e);
500
- }
501
- // 缓存未过期:直接完成,不发请求
502
- if (utils.cache.isFresh(cached)) {
503
- if (el) utils._loadedElements.add(el);
504
- return Promise.resolve(cached.text);
505
- }
506
- } else {
507
- utils.onLoading?.(el);
508
- }
509
-
510
- return new Promise((resolve, reject) => {
511
- const load = () => {
512
- let timedOut = false;
513
- const timeout = setTimeout(() => {
514
- timedOut = true;
515
- console.warn('[request] 超时:', url);
516
-
517
- if (++retryCount >= maxRetry) {
518
- if (cached) {
519
- // 已有缓存渲染,保留缓存内容,不显示失败
520
- resolve(cached.text);
521
- } else {
522
- utils.onLoadFailure?.(el);
523
- onFailure?.();
524
- reject('请求超时');
525
- }
526
- } else {
527
- setTimeout(load, 1000);
528
- }
529
- }, 5000);
530
-
531
- utils._fetchShared(url).then(resp => {
532
- if (timedOut) return;
533
- clearTimeout(timeout);
534
- return resp;
535
- }).then(data => {
536
- if (timedOut) return;
537
- // 标记元素实例为已加载
538
- if (el) utils._loadedElements.add(el);
539
- // 写入缓存:回调会立即消费 data 的 body,必须先同步 clone 再延迟读取
540
- if (cacheable && data.ok) {
541
- const cacheClone = data.clone();
542
- const contentType = data.headers.get('Content-Type') || 'application/json';
543
- utils._defer(() => {
544
- cacheClone.text().then(text => {
545
- utils.cache.set(url, text, contentType, ttl);
546
- }).catch(() => {});
547
- });
548
- }
549
- // 后台刷新渲染前恢复初始结构,避免缓存渲染的内容重复
550
- if (el && initialHTML !== null) {
551
- el.innerHTML = initialHTML;
552
- }
553
- utils.onLoadSuccess?.(el);
554
- callback(data);
555
- resolve(data);
556
- }).catch(err => {
557
- clearTimeout(timeout);
558
- console.warn('[request] 错误:', err);
559
-
560
- if (++retryCount >= maxRetry) {
561
- if (cached) {
562
- resolve(cached.text);
563
- } else {
564
- utils.onLoadFailure?.(el);
565
- onFailure?.();
566
- reject(err);
567
- }
568
- } else {
569
- setTimeout(load, 1000);
570
- }
571
- });
572
- };
573
-
574
- if (cacheRenderDone) {
575
- Promise.race([
576
- cacheRenderDone,
577
- new Promise(resolve => setTimeout(resolve, 5000))
578
- ]).then(load);
579
- } else {
580
- load();
581
- }
582
- });
583
- },
584
- requestWithoutLoading: (url, options = {}, maxRetry = 2, timeout = 5000) => {
585
- const ttl = utils.cache.ttl(null, options);
586
- const cacheable = utils.cache.shouldCache(url, options) && ttl > 0;
587
- const cached = cacheable ? utils.cache.get(url) : null;
588
-
589
- if (cached && utils.cache.isFresh(cached)) {
590
- return Promise.resolve(utils.cache.toResponse(cached));
591
- }
592
-
593
- return new Promise((resolve, reject) => {
594
- let retryCount = 0;
595
- // 与 request 保持一致:最终失败时回退 stale 缓存,避免闪失败态
596
- const fallback = () => {
597
- if (cached) {
598
- resolve(utils.cache.toResponse(cached));
599
- } else {
600
- reject('timeout');
601
- }
602
- };
603
-
604
- const tryRequest = () => {
605
- let timedOut = false;
606
- const timer = setTimeout(() => {
607
- timedOut = true;
608
- if (++retryCount > maxRetry) fallback();
609
- else tryRequest();
610
- }, timeout);
611
-
612
- utils._fetchShared(url, options)
613
- .then(resp => {
614
- clearTimeout(timer);
615
- if (timedOut) return;
616
- if (cacheable) {
617
- // 调用方会消费 resp 的 body,必须先同步 clone 再延迟读取
618
- const cacheClone = resp.clone();
619
- const contentType = resp.headers.get('Content-Type') || 'application/json';
620
- utils._defer(() => {
621
- cacheClone.text().then(text => {
622
- utils.cache.set(url, text, contentType, ttl);
623
- }).catch(() => {});
624
- });
625
- }
626
- resolve(resp);
627
- })
628
- .catch(err => {
629
- clearTimeout(timer);
630
- if (timedOut) return;
631
- if (++retryCount > maxRetry) {
632
- if (cached) {
633
- resolve(utils.cache.toResponse(cached));
634
- } else {
635
- reject(err);
636
- }
637
- } else {
638
- setTimeout(tryRequest, 500);
639
- }
640
- });
641
- };
642
-
643
- tryRequest();
644
- });
645
- },
646
282
  /********************** requestAnimationFrame ********************************/
647
283
  // 1、requestAnimationFrame 会把每一帧中的所有 DOM 操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
648
284
  // 2、在隐藏或不可见的元素中,requestAnimationFrame 将不会进行重绘或回流,这当然就意味着更少的的 cpu,gpu 和内存使用量。
@@ -652,90 +288,29 @@
652
288
  }
653
289
  window.requestAnimationFrame(fn)
654
290
  },
655
- dark: {},
656
-
657
- // 插件初始化管理器 - 统一处理 DOMContentLoaded 事件
658
- _pluginInitializers: [],
659
- _pluginCleanups: new Map(), // 存储每个插件的清理函数
660
-
661
- initPlugin: (initFn, name, options = {}) => {
662
- if (!initFn || typeof initFn !== 'function') return;
663
-
664
- // 避免重复注册
665
- const pluginName = name || initFn.name;
666
- if (utils._pluginInitializers.some(p => p.name === pluginName)) return;
667
-
668
- // 包装初始化函数,添加防重复执行的保护
669
- const wrappedInit = () => {
670
- try {
671
- // 在执行前先清理旧的资源
672
- if (utils._pluginCleanups.has(pluginName)) {
673
- const cleanup = utils._pluginCleanups.get(pluginName);
674
- if (typeof cleanup === 'function') {
675
- cleanup();
676
- }
677
- }
678
-
679
- // 执行初始化,可能返回清理函数
680
- const cleanup = initFn();
681
-
682
- // 如果初始化函数返回了清理函数,保存它
683
- if (typeof cleanup === 'function') {
684
- utils._pluginCleanups.set(pluginName, cleanup);
685
- }
686
- } catch (error) {
687
- console.error(`[Plugin ${pluginName}] 初始化失败:`, error);
688
- }
689
- };
690
-
691
- utils._pluginInitializers.push({
692
- fn: wrappedInit,
693
- name: pluginName,
694
- options: options
695
- });
696
-
697
- // 如果 DOM 已经加载完成,立即执行
698
- if (document.readyState === 'complete' || document.readyState === 'interactive') {
699
- wrappedInit();
700
- } else {
701
- // 否则等待 DOMContentLoaded
702
- window.addEventListener('DOMContentLoaded', wrappedInit, { once: true });
703
- }
704
- },
705
-
706
- // 清理所有插件资源
707
- cleanupPlugins: () => {
708
- utils._pluginCleanups.forEach((cleanup, name) => {
709
- try {
710
- cleanup();
711
- } catch (error) {
712
- console.error(`[Plugin ${name}] 清理失败:`, error);
713
- }
714
- });
715
- utils._pluginCleanups.clear();
716
- },
717
-
718
- // 清理所有资源(用于页面卸载或重置)
719
- cleanupAll: () => {
720
- utils.cleanupPlugins();
721
- },
722
291
  };
723
292
 
724
- // utils.dark.mode 当前模式 dark or light
725
- // utils.dark.toggle() 暗黑模式触发器
726
- // utils.dark.push(callBack[,"callBackName"]) 传入触发器回调函数
727
- utils.dark.method = {
728
- toggle: new RunItem(),
729
- };
730
- utils.dark = Object.assign(utils.dark, {
731
- push: utils.dark.method.toggle.push,
293
+ // 自定义注入脚本可能在 type=module runtime 执行前调用 request;以 Promise 接缝排队,
294
+ // runtime 安装真实 adapter 后统一放行,不在经典脚本中复制任何网络或缓存算法。
295
+ var requestBridge = {};
296
+ requestBridge.ready = new Promise(function (resolve) {
297
+ requestBridge.resolve = resolve;
732
298
  });
299
+ utils.request = function () {
300
+ var args = arguments;
301
+ return requestBridge.ready.then(function (adapter) {
302
+ return adapter.request.apply(null, args);
303
+ });
304
+ };
305
+ utils.requestWithoutLoading = function () {
306
+ var args = arguments;
307
+ return requestBridge.ready.then(function (adapter) {
308
+ return adapter.requestWithoutLoading.apply(null, args);
309
+ });
310
+ };
733
311
 
734
- // 暴露到 window:页尾插件片段经裸标识符 utils 即可使用
312
+ // 暴露到 window:迁移期经典核心脚本与 ESM runtime 的兼容接缝。
313
+ window.__stellarRequestBridge = requestBridge;
735
314
  window.utils = utils;
736
315
 
737
- // 补跑解析期注册的插件队列
738
- if (window.stellar && typeof window.stellar._flushPlugins === 'function') {
739
- window.stellar._flushPlugins();
740
- }
741
316
  })();
@@ -1,51 +0,0 @@
1
- ---
2
- name: stellar-theme-dev
3
- description: 主题仓库(hexo-theme-stellar)开发全流程:方案 → 开发 → 验证 → 提交 → 发版。当任务涉及本仓库主题文件、构建验证、知识库更新或主题发版时使用。
4
- ---
5
-
6
- # Stellar Theme Dev
7
-
8
- 主题仓库(hexo-theme-stellar)开发全流程。开始前先读仓库根 `AGENTS.md`(唯一权威);本文件只给出执行顺序与完成条件。涉及主题代码、配置或行为问题时,先查 `docs/knowledge/` 对应领域,再读源码确认。
9
-
10
- ## 流程
11
-
12
- ### 1. 方案
13
-
14
- - 先读 `AGENTS.md`「架构总览」(§6)与 `docs/knowledge/00-总览与安装配置/overview.md` 建立整体认知、定位改动范围。
15
- - 在 `docs/designs/{YYYY-MM-DD}-{功能简称}/` 下建方案文档(模板 `docs/designs/_template/`,含 `spec.md` / `plan.md` / `checklist.md`)。
16
- - 方案需写明:要解决的问题、技术方案与实现思路、影响范围、需同步的知识库页面与文档。
17
- - 知识库文档遵循“设计语义、行为契约、修改依据”分层;新增具体数值时说明语义和作用范围,普通 CSS 实现值以源码为准,不在多个页面重复维护。
18
- - 完成条件:方案文档已就位;改动范围与受影响维度已确认。
19
-
20
- ### 2. 开发
21
-
22
- - 新增功能覆盖全部相关维度:`layout/` + `scripts/` + `source/css/` + `source/js/`(如需)+ `languages/`(如需)+ `docs/`。
23
- - 新增或重构标签插件先读 `docs/guides/tag-plugins-style-guide.md`;代码遵循 `AGENTS.md` 编码规范。
24
- - 完成条件:改动文件清单覆盖全部相关维度;涉及行为或配置变更时已同步 `docs/knowledge/` 并在 `VERIFICATION.md` 登记。
25
-
26
- ### 3. 验证
27
-
28
- 命令按需执行:
29
-
30
- - `scripts/` 有改动 → 必须在主工程(xaoxuu.com)执行 `npm run g` 全量验证(已含 `hexo clean && hexo generate && npx gulp minify`);`npm run s` 是按需渲染,不能替代。
31
- - 新增/修改纯函数 → 补充单测并跑 `npm run check`(lint + 单测 + 依赖声明检查 + 知识库硬事实核查)。
32
- - 知识库有改动 → `python3 docs/knowledge/tools/verify.py` 硬事实核查。
33
- - UI 方面(样式、模板、前端交互等)改动量不大时无需自检流程,除非用户明确要求。
34
- - 检查所有受影响页面类型(首页、文章页、Wiki 页等),验证结果记录在方案目录 `checklist.md`。
35
- - 完成条件:应执行的命令全部通过;新增 `require` 均已声明或为 Node 内置模块(test/ 禁止幽灵依赖);首页、文章页、Wiki 页等受影响页面类型均检查通过。
36
-
37
- ### 4. 提交
38
-
39
- - 任务完成后**不自动提交**:改动保留在工作区供用户审查。
40
- - 仅在用户明确要求提交时执行;提交前须通过第 3 步中应执行的验证。
41
- - 使用 Conventional Commits,一次提交对应一个需求点;如果几个需求任务逻辑相似,可以合并为一次提交;类型与格式见 `AGENTS.md`「Git 规范」(§7)。
42
- - 合并代码时,把合并提交 / PR 标题改为 Conventional Commits 格式(见 `AGENTS.md`「Git 规范」§7),不保留默认的 `Merge branch ...` / `Merge pull request ...` 标题。
43
- - 改动只提交在本仓库(stellar);仅当用户明确要求时 push。
44
- - 完成条件:改动已通过应执行的验证并保留在工作区;如用户要求提交,提交符合规范;如用户要求 push,已推送且远端为最新。
45
-
46
- ### 5. 发版
47
-
48
- - 由用户触发时执行:分析自上一 tag 起的 commit 确定版本号 → 在 `CHANGELOG.md` 写入对应非空章节(H2 版本号 + H3 分类)→ 向用户确认版本号与变更摘要 → `npm run release:dry -- <version>` 预演 → 正式发版。
49
- - 发版前核对:`npm run check` 内含提交登记完整性检查,自上一 tag 起涉及主题代码/配置/行为变化的非合并提交须在 `docs/knowledge/VERIFICATION.md`「提交登记(发版前核对)」表登记短 SHA(纯文档 / CI 改动无需登记);缺失先补登记再发版。
50
- - 详见 `docs/guides/release-process.md` 与 `AGENTS.md`「发版规范」(§8)。
51
- - 完成条件:版本号与变更摘要已获用户确认;dry-run 通过后完成正式发版。
File without changes
@@ -1,76 +0,0 @@
1
- <script type="module">
2
- (function() {
3
-
4
- function initArtalk() {
5
- const el = document.getElementById('artalk_container');
6
- if (!el) return;
7
-
8
- // artalk 邮件通知链接携带 ?atk_comment=<id> / #atk-comment-<id> 定位目标,
9
- // 命中时跳过视口懒加载立即初始化,让 Artalk 自身的 list-goto 逻辑完成定位。
10
- const hasAtkTarget = /[?&]atk_comment=\d+/.test(window.location.search) || /#atk-comment-\d+/.test(window.location.hash);
11
-
12
- function load_artalk() {
13
- utils.css('<%- url_for('/css/comments/artalk.css') %>?v=<%- stellar_info('version') %>');
14
- utils.css('<%- theme.comments.artalk.css %>');
15
- utils.js('<%- theme.comments.artalk.js %>', {defer: true}).then(function () {
16
- // 监听 Artalk 事件
17
- // FIXME: Artalk开启了懒加载会导致评论输入预览框里的图也变成data-src,导致看不到图
18
- // Artalk.use((ctx) => {
19
- // ctx.on('list-loaded', () => window.lazyLoadInstance?.update())
20
- // })
21
- // 邮件通知链接以 ?atk_comment=<id> 定位,Artalk 在 list-loaded 时才重新读取 URL,
22
- // 固定延时清理会与之竞态(#598)。先把评论 id 改写到 hash(Artalk 读取优先级高于 query),
23
- // 同时立即移除 atk_comment 查询参数,避免其 hash 监听干扰目录定位;
24
- // atk_notify_key 保留到 list-loaded 完成定位与已读回执后再清理。
25
- const atkComment = window.location.search.match(/[?&]atk_comment=(\d+)/);
26
- if (atkComment && !/#atk-comment-\d+/.test(window.location.hash)) {
27
- const params = new URLSearchParams(window.location.search);
28
- const notifyKey = params.get('atk_notify_key');
29
- const query = notifyKey ? '?atk_notify_key=' + encodeURIComponent(notifyKey) : '';
30
- window.history.replaceState(null, '', window.location.pathname + query + '#atk-comment-' + atkComment[1]);
31
- }
32
- const path = el.getAttribute('comment_id') ?? decodeURI(window.location.pathname);
33
- const artalk = Artalk.init({
34
- el: '#artalk_container',
35
- pageKey: path,
36
- pageTitle: '<%= page.title %>',
37
- server: '<%= theme.comments.artalk.server %>',
38
- site: '<%= theme.comments.artalk.site %>',
39
- darkMode: '<%= theme.comments.artalk.darkMode %>',
40
- <% if (theme.comments.artalk.imageUploader?.api) { %>
41
- imgUploader: function(file) {
42
- let headers = new Headers();
43
- headers.set('Accept', 'application/json');
44
- <% if (theme.comments.artalk.imageUploader?.token) { %>
45
- headers.set('Authorization', '<%- theme.comments.artalk.imageUploader?.token %>')
46
- <% } %>
47
- let formData = new FormData();
48
- formData.append('file', file);
49
- return fetch('<%- theme.comments.artalk.imageUploader?.api %>',{
50
- method: 'POST',
51
- body: formData,
52
- headers: headers
53
- }).then((resp) => resp.json())
54
- .then((resp) => resp.<%- theme.comments.artalk.imageUploader?.resp %>)
55
- },
56
- <% } %>
57
- });
58
- // list-loaded 时 Artalk 已读取 atk_comment / atk_notify_key 并触发定位与已读回执,
59
- // 此时再清理残留的 ?atk_* 参数,避免固定延时与异步加载竞态(#598)。
60
- if (hasAtkTarget && window.location.search.indexOf('atk_') !== -1) {
61
- artalk.on('list-loaded', function () {
62
- window.setTimeout(function () {
63
- window.history.replaceState(null, '', window.location.pathname + window.location.hash);
64
- }, 0);
65
- });
66
- }
67
- });
68
- }
69
-
70
- util.viewportLazyload(el, load_artalk, !hasAtkTarget);
71
- }
72
-
73
- // Initialize on page load
74
- initArtalk();
75
- })();
76
- </script>
@@ -1,33 +0,0 @@
1
- <script type="module">
2
- (function() {
3
-
4
- function initBeaudar() {
5
- const el = document.querySelector('#comments #beaudar');
6
- if (!el) return;
7
-
8
- function load_beaudar() {
9
- utils.css('<%- url_for('/css/comments/beaudar.css') %>?v=<%- stellar_info('version') %>');
10
- try {
11
- el.innerHTML = '';
12
- } catch (error) {
13
- console.error(error);
14
- }
15
- const script = document.createElement('script');
16
- script.src = 'https://beaudar.lipk.org/client.js';
17
- script.async = true;
18
- for (const key of Object.keys(el.attributes)) {
19
- const attr = el.attributes[key];
20
- if (['class', 'id'].includes(attr.name) === false) {
21
- script.setAttribute(attr.name, attr.value);
22
- }
23
- }
24
- el.appendChild(script);
25
- }
26
-
27
- util.viewportLazyload(el, load_beaudar);
28
- }
29
-
30
- // Initialize on page load
31
- initBeaudar();
32
- })();
33
- </script>
@@ -1,31 +0,0 @@
1
- <script type="module">
2
- (function() {
3
-
4
- function initGiscus() {
5
- const el = document.querySelector('#comments #giscus');
6
- if (!el) return;
7
-
8
- function load_giscus() {
9
- try {
10
- el.innerHTML = '';
11
- } catch (error) {
12
- console.error(error);
13
- }
14
- const script = document.createElement('script');
15
- script.async = true;
16
- for (const key of Object.keys(el.attributes)) {
17
- const attr = el.attributes[key];
18
- if (['class', 'id'].includes(attr.name) === false) {
19
- script.setAttribute(attr.name, attr.value);
20
- }
21
- }
22
- el.appendChild(script);
23
- }
24
-
25
- util.viewportLazyload(el, load_giscus);
26
- }
27
-
28
- // Initialize on page load
29
- initGiscus();
30
- })();
31
- </script>
@@ -1,3 +0,0 @@
1
- <% if (page.cmt && page.cmt.service && page.cmt.service.length > 0) { %>
2
- <%- partial(page.cmt.service + '/script') %>
3
- <% } %>