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
@@ -0,0 +1,55 @@
1
+ <%
2
+ function actionLabel(action) {
3
+ return action.label ? `${__('meta.share')}: ${action.label}` : __('meta.share')
4
+ }
5
+
6
+ function actionClasses(action) {
7
+ return ui_classes(`social share-item ${action.service}`, 'interactive', 'is-icon-only')
8
+ }
9
+
10
+ function renderAction(service) {
11
+ var action = share_action(service, share)
12
+ if (!action) return ''
13
+ var label = actionLabel(action)
14
+ var classes = actionClasses(action)
15
+ var iconHtml = `<span class="share-item__icon ui-icon">${icon(`share:${action.service}`, '', true)}</span>`
16
+ if (action.kind === 'external') {
17
+ return `<a class="${classes}" href="${escape_html(action.href)}" target="_blank" rel="external nofollow noopener noreferrer" aria-label="${escape_html(label)}" title="${escape_html(label)}">${iconHtml}</a>`
18
+ }
19
+ if (action.kind === 'link') {
20
+ return `<a class="${classes}" href="${escape_html(action.href)}" aria-label="${escape_html(label)}" title="${escape_html(label)}">${iconHtml}</a>`
21
+ }
22
+ if (action.kind === 'toggle') {
23
+ return `<a class="${classes}" onclick="util.toggle(&quot;${escape_html(action.target)}&quot;)" aria-label="${escape_html(label)}" title="${escape_html(label)}">${iconHtml}</a>`
24
+ }
25
+ if (action.kind === 'copy') {
26
+ return `<a class="${classes}" data-copy-message="${escape_html(__('message.copied'))}" onclick="util.copy(&quot;${escape_html(action.target)}&quot;, this.dataset.copyMessage)" aria-label="${escape_html(label)}" title="${escape_html(label)}">${iconHtml}</a>`
27
+ }
28
+ if (action.kind === 'native') {
29
+ return `<button type="button" class="${classes}" data-share-title="${escape_html(action.data.title)}" data-share-text="${escape_html(action.data.text)}" data-share-url="${escape_html(action.data.url)}" data-copy-target="${escape_html(action.target)}" data-copy-message="${escape_html(__('message.copied'))}" onclick="util.share(this)" aria-label="${escape_html(label)}" title="${escape_html(label)}">${iconHtml}</button>`
30
+ }
31
+ return ''
32
+ }
33
+
34
+ function urlenc(value) {
35
+ return encodeURIComponent(value == null ? '' : String(value))
36
+ }
37
+
38
+ function layoutDiv() {
39
+ if (!share || !Array.isArray(share.services) || share.services.length === 0) return ''
40
+ var buttons = share.services.map(renderAction).join('')
41
+ if (buttons.length === 0) return ''
42
+ var qrcode = share.services.includes('wechat')
43
+ ? `<div class="qrcode" id="qrcode-wechat" style="opacity:0;height:0"><img src="https://api.qrserver.com/v1/create-qr-code/?size=256x256&amp;data=${urlenc(share.permalink)}"/></div>`
44
+ : ''
45
+ return `
46
+ <div class="article-share${scrollreveal(' ')}" id="share">
47
+ <div class="body">
48
+ <div class="link"><input class="copy-area" readonly="true" id="copy-link" value="${escape_html(share.permalink)}" /></div>
49
+ <div class="social-wrap dis-select">${buttons}</div>
50
+ ${qrcode}
51
+ </div>
52
+ </div>`
53
+ }
54
+ %>
55
+ <%- layoutDiv() %>
@@ -1,32 +1,33 @@
1
1
  <%
2
- const content = theme.footer.content?.replace('{author.name}', (config.author || 'Anonymity'))?.replace('{theme.name}', stellar_info('name'))?.replace('{theme.version}', stellar_info('version'))?.replace('{theme.tree}', stellar_info('tree'))
2
+ var siteFooter = stellar_config('footer')
3
+ var content = siteFooter.content?.replace('{author.name}', (config.author || 'Anonymity'))?.replace('{theme.name}', stellar_info('name'))?.replace('{theme.version}', stellar_info('version'))?.replace('{theme.tree}', stellar_info('tree'))
3
4
  function layoutDiv() {
4
5
  var el = ''
5
6
  el += `<footer class="page-footer${scrollreveal(' ')} footnote">`
6
7
  el += '<hr>'
7
8
  // sitemap
8
- const sitemap = theme.footer.sitemap
9
- if (sitemap?.length > 0) {
10
- var count = sitemap.length
9
+ var sections = siteFooter.sections
10
+ if (sections.length > 0) {
11
+ var count = sections.length
11
12
  if ([6].includes(count)) {
12
13
  count = 3
13
14
  } else if ([7,8].includes(count)) {
14
15
  count = 4
15
16
  } else {
16
- count = Math.min(sitemap.length, 5)
17
+ count = Math.min(sections.length, 5)
17
18
  }
18
19
  el += `<div class="sitemap" style="column-count:${count};">`
19
- for (let group of sitemap) {
20
- let title = group.title
21
- let items = group.items
20
+ for (var group of sections) {
21
+ var title = escape_html(group.title)
22
+ var items = group.items
22
23
  if (items == undefined || items.length == 0) {
23
24
  continue
24
25
  }
25
26
  el += '<div class="sitemap-group">'
26
27
  el += '<span class="fs15">' + title + '</span>'
27
28
  items.forEach((item, i) => {
28
- el += '<a href="' + url_for(md_link(item)) + '">'
29
- el += __(md_text(item))
29
+ el += '<a href="' + escape_html(url_for(item.url)) + '">'
30
+ el += escape_html(__(item.title))
30
31
  el += '</a>'
31
32
  });
32
33
  el += '</div>'
@@ -2,12 +2,18 @@
2
2
  function layoutDiv() {
3
3
  var el = '';
4
4
  // 置顶文章样式为平铺时不渲染轮播,置顶文章改由首页文章列表靠前展示
5
- if (theme.article?.pin_style !== 'flat') {
5
+ if (stellar_config('article.listing.pinnedLayout') !== 'flat') {
6
6
  el += partial('_partial/main/pin_slider', {type: 'post'});
7
7
  }
8
- el += '<div class="navbar top">';
9
- el += '<div class="navbar-blur">';
10
- el += '<div class="navbar-container">';
8
+
9
+ const listingNav = stellar_config('profiles.blogIndex.listingNav');
10
+ if (!listingNav.enabled) {
11
+ return el;
12
+ }
13
+
14
+ el += '<div class="listing-nav">';
15
+ el += '<div class="listing-nav__surface">';
16
+ el += '<div class="listing-nav__viewport">';
11
17
  el += '<nav class="post">';
12
18
  if (is_home()) {
13
19
  el += '<a class="active" href="' + pretty_url(config.index_generator.path) + '">' + __("btn.recent_publish") + '</a>';
@@ -34,15 +40,15 @@ function layoutDiv() {
34
40
  el += '<a href="' + pretty_url(config.tag_dir) + '">' + __("btn.tags") + '</a>';
35
41
  }
36
42
  }
37
-
38
- if (theme.topic?.publish_list?.length > 0) {
43
+
44
+ if (stellar_data('topic')?.publish_list?.length > 0) {
39
45
  if (page.layout == 'index_topic') {
40
- el += '<a class="active" href="' + pretty_url(theme.site_tree.index_topic.base_dir) + '">' + __("btn.topic") + '</a>';
46
+ el += '<a class="active" href="' + pretty_url(stellar_config('profiles.topic.path')) + '">' + __("btn.topic") + '</a>';
41
47
  } else {
42
- el += '<a href="' + pretty_url(theme.site_tree.index_topic.base_dir) + '">' + __("btn.topic") + '</a>';
48
+ el += '<a href="' + pretty_url(stellar_config('profiles.topic.path')) + '">' + __("btn.topic") + '</a>';
43
49
  }
44
50
  }
45
-
51
+
46
52
  if (site.posts && site.posts.length > 0) {
47
53
  if (is_archive()) {
48
54
  el += '<a class="active" href="' + pretty_url(config.archive_dir) + '">' + __("btn.archives") + '</a>';
@@ -50,16 +56,13 @@ function layoutDiv() {
50
56
  el += '<a href="' + pretty_url(config.archive_dir) + '">' + __("btn.archives") + '</a>';
51
57
  }
52
58
  }
53
-
54
- const { nav_tabs } = theme.site_tree.index_blog
55
- if (nav_tabs) {
56
- for (let key of Object.keys(nav_tabs)) {
57
- // 当 page 的末尾为 index.html 或者处于该 page 的某个子页面时也应该匹配
58
- // if (full_url_for(page.path) == full_url_for(nav_tabs[key])) {
59
- if (full_url_for(page.path).startsWith(full_url_for(nav_tabs[key]))){
60
- el += '<a class="active" href="' + url_for(nav_tabs[key]) + '">' + key + '</a>';
59
+
60
+ if (Array.isArray(listingNav.tabs)) {
61
+ for (const item of listingNav.tabs) {
62
+ if (full_url_for(page.path).startsWith(full_url_for(item.url))){
63
+ el += '<a class="active" href="' + escape_html(url_for(item.url)) + '">' + escape_html(item.title) + '</a>';
61
64
  } else {
62
- el += '<a href="' + url_for(nav_tabs[key]) + '">' + key + '</a>';
65
+ el += '<a href="' + escape_html(url_for(item.url)) + '">' + escape_html(item.title) + '</a>';
63
66
  }
64
67
  }
65
68
  }
@@ -0,0 +1,56 @@
1
+ <%
2
+ function layoutDiv() {
3
+ if (!wikiIndex || !Array.isArray(wikiIndex.items) || !Array.isArray(wikiIndex.allItems) || !Array.isArray(wikiIndex.tags)) {
4
+ throw new Error('Stellar v2: Wiki Listing Nav 缺少显式索引投影')
5
+ }
6
+ var el = '';
7
+ el += partial('_partial/main/pin_slider', {type: 'wiki', wikiItems: wikiIndex.allItems});
8
+
9
+ const listingNav = stellar_config('profiles.wikiIndex.listingNav');
10
+ if (!listingNav.enabled) {
11
+ return el;
12
+ }
13
+
14
+ el += '<div class="listing-nav">';
15
+ el += '<div class="listing-nav__surface">';
16
+ el += '<div class="listing-nav__viewport">';
17
+ el += '<nav class="wiki">';
18
+ // 所有项目
19
+ el += '<a';
20
+ if (wikiIndex.filter === false) {
21
+ el += ' class="active"';
22
+ }
23
+ el += ' href="' + pretty_url(wikiIndex.path) + '">' + __("btn.all_wiki") + '</a>';
24
+ el += '</a>';
25
+ // 项目分类
26
+ for (var tag of wikiIndex.tags) {
27
+ var projects = tag.itemIds.filter(id => wikiIndex.allItems.some(item => item.id === id))
28
+ if (projects.length > 0) {
29
+ el += '<a';
30
+ if (tag.name && tag.name.length > 0 && wikiIndex.tagName === tag.name) {
31
+ el += ' class="active"';
32
+ }
33
+ el += ' href="' + escape_html(pretty_url(tag.path)) + '">' + escape_html(tag.name) + '</a>';
34
+ el += '</a>';
35
+ }
36
+ }
37
+
38
+ if (Array.isArray(listingNav.tabs)) {
39
+ for (const item of listingNav.tabs) {
40
+ if (full_url_for(page.path).startsWith(full_url_for(item.url))){
41
+ el += '<a class="active" href="' + escape_html(url_for(item.url)) + '">' + escape_html(item.title) + '</a>';
42
+ } else {
43
+ el += '<a href="' + escape_html(url_for(item.url)) + '">' + escape_html(item.title) + '</a>';
44
+ }
45
+ }
46
+ }
47
+
48
+ el += '</nav>';
49
+ el += '</div>';
50
+ el += '</div>';
51
+ el += '</div>';
52
+ return el;
53
+ }
54
+ %>
55
+
56
+ <%- layoutDiv() %>
@@ -1,27 +1,28 @@
1
1
  <%
2
2
 
3
- var banner = {}
3
+ var renderViewModel = typeof viewModel !== 'undefined' && ['post', 'wiki', 'topic', 'notebook'].includes(viewModel?.collection?.profile)
4
+ ? viewModel
5
+ : null
6
+ var postViewModel = ['post', 'topic'].includes(renderViewModel?.collection?.profile) ? renderViewModel : null
7
+ var wikiViewModel = renderViewModel?.collection?.profile === 'wiki' ? renderViewModel : null
8
+ var notebookViewModel = renderViewModel?.collection?.profile === 'notebook' ? renderViewModel : null
9
+ var pageConfig = content_config(page)
10
+ var banner = Object.assign({}, wikiViewModel
11
+ ? wikiViewModel.render.article.banner
12
+ : notebookViewModel
13
+ ? notebookViewModel.render.article.banner
14
+ : postViewModel?.collection?.profile === 'topic'
15
+ ? postViewModel.render.article.banner
16
+ : postViewModel ? postViewModel.item.presentation.banner : pageConfig.banner || {})
4
17
 
5
- if (page.banner) {
6
- banner.url = page.banner
7
- } else if (theme.topic.tree[page.topic]?.banner != null) {
8
- banner.url = theme.topic.tree[page.topic]?.banner
9
- } else if (theme.wiki.tree[page.wiki]?.banner != null) {
10
- banner.url = theme.wiki.tree[page.wiki]?.banner
11
- }
12
- banner = Object.assign(banner, page.banner_info)
13
18
  // 标题
14
- if (banner.title == null) {
15
- banner.title = page.h1 != null ? page.h1 : page.title
16
- }
17
- // 副标题
18
- if (banner.subtitle == null) {
19
- banner.subtitle = page.subtitle
19
+ if (banner.headline == null) {
20
+ banner.headline = renderViewModel ? renderViewModel.item.title : page.title
20
21
  }
21
22
 
22
23
  // 上块:第一行(左侧面包屑 + 右侧阅读时长 / AI 标签)+ 第二行(日期信息,靠左)
23
24
  function layoutTop() {
24
- if (page.breadcrumb === false) {
25
+ if ((renderViewModel ? renderViewModel.item.navigation.breadcrumb : pageConfig.breadcrumb) === false) {
25
26
  return ''
26
27
  }
27
28
  var el = ''
@@ -33,12 +34,12 @@ function layoutTop() {
33
34
  el += `<div class="left" id="breadcrumb">`
34
35
  // 首页
35
36
  el += `<a class="cap breadcrumb" href="${pretty_url(config.root)}">${__("btn.home")}</a>`
36
- if (theme.wiki.tree[page.wiki]) {
37
- el += partial('breadcrumb/wiki')
38
- } else if (page.notebook) {
39
- el += partial('breadcrumb/note')
37
+ if (wikiViewModel) {
38
+ el += partial('breadcrumb/wiki', {viewModel: wikiViewModel})
39
+ } else if (notebookViewModel) {
40
+ el += partial('breadcrumb/note', {viewModel: notebookViewModel})
40
41
  } else if (page.layout == 'post') {
41
- el += partial('breadcrumb/blog')
42
+ el += partial('breadcrumb/blog', {viewModel: postViewModel})
42
43
  } else {
43
44
  el += partial('breadcrumb/page')
44
45
  }
@@ -46,7 +47,7 @@ function layoutTop() {
46
47
  // 2.2 右:字数和预计阅读时长 + AI 成分标签(仅在有内容时渲染)
47
48
  var rightHtml = ''
48
49
  // 字数和预计阅读时长,置于第一行右侧(#302)
49
- if (page.layout == 'post' && theme.article.reading_time) {
50
+ if ((renderViewModel ? renderViewModel.item.layout : page.layout) == 'post' && stellar_config('article.showReadingTime')) {
50
51
  var _wc = word_count(page)
51
52
  if (_wc > 0) {
52
53
  rightHtml += `<span class="cap reading">${__("meta.word_count", _wc)} · ${__("meta.reading_time", reading_time(page))}</span>`
@@ -54,8 +55,8 @@ function layoutTop() {
54
55
  }
55
56
  // AI 成分标签:置于第一行最右(阅读时长右侧);
56
57
  // banner 含图片时不用配置色,继承默认文字色(--text-banner)
57
- const bannerHasImage = banner.url && banner.url.length > 0
58
- rightHtml += ai_label(page.ai_label, 'cap', bannerHasImage)
58
+ const bannerHasImage = banner.image && banner.image.length > 0
59
+ rightHtml += ai_label(renderViewModel ? renderViewModel.item.presentation.article?.aiLabel : pageConfig.article?.aiLabel, 'cap', bannerHasImage)
59
60
  if (rightHtml.length > 0) {
60
61
  el += `<div class="right">${rightHtml}</div>`
61
62
  }
@@ -63,7 +64,7 @@ function layoutTop() {
63
64
  el += `</div>`
64
65
  // 3.第二行:日期信息,靠左
65
66
  el += `<div class="meta-row">`
66
- el += partial('dateinfo')
67
+ el += partial('dateinfo', {viewModel: renderViewModel})
67
68
  el += `</div>`
68
69
  // end 1.上块
69
70
  el += `</div>`
@@ -71,24 +72,24 @@ function layoutTop() {
71
72
  }
72
73
 
73
74
  function layoutTitle() {
74
- if (banner.title?.length > 0) {
75
- return `<h1 class="text title"><span>${banner.title}</span></h1>`
75
+ if (banner.headline?.length > 0) {
76
+ return `<h1 class="text title"><span>${banner.headline}</span></h1>`
76
77
  } else {
77
78
  return ''
78
79
  }
79
80
  }
80
81
 
81
82
  function layoutSubtitle() {
82
- if (banner.subtitle?.length > 0) {
83
- return `<div class="text subtitle">${banner.subtitle}</div>`
83
+ if (banner.tagline?.length > 0) {
84
+ return `<div class="text subtitle">${banner.tagline}</div>`
84
85
  } else {
85
86
  return ''
86
87
  }
87
88
  }
88
89
 
89
90
  function layoutIcon() {
90
- if (banner.avatar?.length > 0 || banner.icon?.length > 0) {
91
- return `<img class="lazy avatar" data-src="${banner.avatar || banner.icon}">`
91
+ if (banner.avatar?.length > 0) {
92
+ return `<img class="lazy avatar" data-src="${banner.avatar}">`
92
93
  } else {
93
94
  return ''
94
95
  }
@@ -118,6 +119,9 @@ function layoutBottom() {
118
119
  }
119
120
 
120
121
  function layoutDiv() {
122
+ if (banner.enabled === false) {
123
+ return ``
124
+ }
121
125
  const bottom = layoutBottom()
122
126
  const top = layoutTop()
123
127
  if (top.length == 0 && bottom.length == 0) {
@@ -127,15 +131,15 @@ function layoutDiv() {
127
131
  var adaptiveAttr = ``
128
132
  var maskHtml = ``
129
133
  var el = ``
130
- if (banner.url?.length > 0) {
131
- bannerStyle += ` style="--bg-url:url('${banner.url.replace(/'/g, '%27')}')"`
134
+ if (banner.image?.length > 0) {
135
+ bannerStyle += ` style="--bg-url:url('${banner.image.replace(/'/g, '%27')}')"`
132
136
  // 背景图上方文字颜色自适应
133
137
  adaptiveAttr = ` data-text-adaptive="split"`
134
138
  }
135
139
  el += `<div class="article-banner-wrap${scrollreveal(' ')}">`
136
140
  el += `<div class="article banner top"${bannerStyle}>`
137
- if (banner.url?.length > 0) {
138
- el += `<img class="lazy bg" data-src="${banner.url}">`
141
+ if (banner.image?.length > 0) {
142
+ el += `<img class="lazy bg" data-src="${banner.image}">`
139
143
  maskHtml = `<div class="banner-mask banner-mask-top" aria-hidden="true"></div><div class="banner-mask banner-mask-bottom" aria-hidden="true"></div>`
140
144
  }
141
145
  el += `
@@ -1,34 +1,21 @@
1
1
  <%
2
2
  function layoutDiv() {
3
- const topicObject = theme.topic.tree[page.topic]
4
- var el = ''
5
- if (topicObject) { // 专栏文章
6
- // 专栏列表页
7
- const topicIndexPageURL = pretty_url(theme.site_tree.index_topic.base_dir)
8
- el += `<span class="sep"></span>`
9
- el += `<a class="cap breadcrumb" id="menu" href="${topicIndexPageURL}">${__("btn.topic")}</a>`
10
- // 专栏项目名
11
- const topicHomePageURL = pretty_url(topicObject.homepage?.path);
12
- if (topicHomePageURL != topicIndexPageURL) {
13
- el += `<span class="sep"></span>`
14
- el += `<a class="cap breadcrumb" id="proj" href="${topicHomePageURL}">${topicObject.name || topicObject.title}</a>`
15
- }
16
- } else { // 普通文章
17
- // 文章列表页
18
- el += `<span class="sep"></span>`
19
- el += `<a class="cap breadcrumb" href="${pretty_url(config.index_generator.path)}">${__("btn.blog")}</a>`
20
- // 分类列表页
21
- if (page.categories?.length > 0) {
22
- el += `<span class="sep"></span>`
23
- el += list_categories(page.categories, {
24
- class: "cap breadcrumb",
25
- show_count: false,
26
- separator: ' <span class="sep"></span> ',
27
- style: "none"
28
- })
29
- }
3
+ var postViewModel = typeof viewModel !== 'undefined' && ['post', 'topic'].includes(viewModel?.collection?.profile)
4
+ ? viewModel
5
+ : null
6
+ if (!postViewModel) {
7
+ throw new Error('Stellar v2: Blog 面包屑必须接收 Post/Topic ViewModel')
30
8
  }
31
- return el
9
+ var postHtml = ''
10
+ postHtml += `<span class="sep"></span>`
11
+ var isTopic = postViewModel.collection.profile === 'topic'
12
+ postHtml += `<a class="cap breadcrumb"${isTopic ? ' id="menu"' : ''} href="${pretty_url(postViewModel.render.layout.blogPath)}">${__(isTopic ? "btn.topic" : "btn.blog")}</a>`
13
+ for (var breadcrumb of postViewModel.render.layout.breadcrumbs) {
14
+ if (isTopic && pretty_url(breadcrumb.path) == pretty_url(postViewModel.render.layout.blogPath)) continue
15
+ postHtml += `<span class="sep"></span>`
16
+ postHtml += `<a class="cap ${isTopic ? 'breadcrumb' : 'breadcrumb-link'}"${isTopic ? ' id="proj"' : ''} href="${pretty_url(breadcrumb.path)}">${escape_html(breadcrumb.name)}</a>`
17
+ }
18
+ return postHtml
32
19
  }
33
20
  %>
34
21
  <%- layoutDiv() %>
@@ -1,8 +1,15 @@
1
1
  <%# 笔记页面的面包屑 %>
2
- <span class="sep"></span>
3
- <a class="cap breadcrumb" href="<%= pretty_url(theme.site_tree.notebooks.base_dir) %>"><%= __('btn.notebook') %></a>
4
- <% const notebook = theme.notebooks.tree[page.notebook] %>
5
- <% if (notebook) { %>
2
+ <%
3
+ var notebookViewModel = typeof viewModel !== 'undefined' && viewModel?.collection?.profile === 'notebook'
4
+ ? viewModel
5
+ : null
6
+ var render = notebookViewModel.render.layout
7
+ %>
8
+ <% if (render.notebookIndexPath) { %>
6
9
  <span class="sep"></span>
7
- <a class="cap breadcrumb" href="<%= pretty_url(notebook.base_dir) %>"><%= notebook.name || notebook.title %></a>
10
+ <a class="cap breadcrumb" href="<%= pretty_url(render.notebookIndexPath) %>"><%= __('btn.notebook') %></a>
11
+ <% } %>
12
+ <% for (var breadcrumb of render.breadcrumbs) { %>
13
+ <span class="sep"></span>
14
+ <a class="cap breadcrumb" href="<%= pretty_url(breadcrumb.path) %>"><%= escape_html(breadcrumb.name) %></a>
8
15
  <% } %>
@@ -1,20 +1,24 @@
1
1
  <%
2
2
  function layoutDiv() {
3
- const wikiObject = theme.wiki.tree[page.wiki]
3
+ var wikiViewModel = typeof viewModel !== 'undefined' && viewModel?.collection?.profile === 'wiki'
4
+ ? viewModel
5
+ : null
6
+ if (!wikiViewModel) {
7
+ throw new Error('Stellar v2: Wiki 面包屑必须接收 Wiki ViewModel')
8
+ }
9
+ var render = wikiViewModel.render.layout
4
10
  var el = ''
5
- // 文档列表页
6
- el += `<span class="sep"></span>`
7
- const wikiIndexPageURL = pretty_url(theme.site_tree.index_wiki.base_dir)
8
- el += `<a class="cap breadcrumb" id="menu" href="${wikiIndexPageURL}">${__("btn.wiki")}</a>`
9
- if (wikiObject) {
10
- // 文档项目名
11
- const wikiHomePageURL = pretty_url(wikiObject.homepage?.path);
12
- if (wikiHomePageURL != wikiIndexPageURL) {
11
+ if (render.wikiIndexPath) {
12
+ el += `<span class="sep"></span>`
13
+ el += `<a class="cap breadcrumb" id="menu" href="${pretty_url(render.wikiIndexPath)}">${__("btn.wiki")}</a>`
14
+ }
15
+ for (var breadcrumb of render.breadcrumbs) {
16
+ if (pretty_url(breadcrumb.path) != pretty_url(render.wikiIndexPath)) {
13
17
  el += `<span class="sep"></span>`
14
- el += `<a class="cap breadcrumb" id="proj" href="${wikiHomePageURL}">${wikiObject.name || wikiObject.title}</a>`
18
+ el += `<a class="cap breadcrumb" id="proj" href="${pretty_url(breadcrumb.path)}">${escape_html(breadcrumb.name)}</a>`
15
19
  }
16
20
  }
17
21
  return el
18
22
  }
19
23
  %>
20
- <%- layoutDiv() %>
24
+ <%- layoutDiv() %>
@@ -1,25 +1,39 @@
1
1
  <%
2
2
  function layoutDiv() {
3
+ var wikiViewModel = typeof viewModel !== 'undefined' && viewModel?.collection?.profile === 'wiki'
4
+ ? viewModel
5
+ : null
6
+ var postViewModel = typeof viewModel !== 'undefined' && ['post', 'topic'].includes(viewModel?.collection?.profile)
7
+ ? viewModel
8
+ : null
9
+ var notebookViewModel = typeof viewModel !== 'undefined' && viewModel?.collection?.profile === 'notebook'
10
+ ? viewModel
11
+ : null
3
12
  // 作者
4
13
  var el = ''
5
14
  el += `<div class="flex-row" id="post-meta">`
6
- if (page.wiki) {
7
- el += `<span class="text created">${__("meta.updated") + __("symbol.colon")}`
8
- el += `<time datetime="${date_xml(page.updated)}">${date(page.updated, config.date_format)}</time>`
9
- el += `</span>`
10
- } else if (page.notebook) {
11
- // 更新日期
15
+ if (wikiViewModel) {
16
+ var updated = wikiViewModel.render.article.updated
17
+ if (updated) {
18
+ el += `<span class="text created">${__("meta.updated") + __("symbol.colon")}`
19
+ el += `<time datetime="${date_xml(updated)}">${date(updated, config.date_format)}</time>`
20
+ el += `</span>`
21
+ }
22
+ } else if (notebookViewModel) {
23
+ var notebookArticle = notebookViewModel.render.article
12
24
  el += `<span class="text created">${__("meta.updated") + __("symbol.colon")}`
13
- el += `<time datetime="${date_xml(page.updated)}">${date(page.updated, config.date_format)}</time>`
25
+ el += `<time datetime="${date_xml(notebookArticle.updated)}">${date(notebookArticle.updated, config.date_format)}</time>`
14
26
  el += `</span>`
15
- // 发布日期
16
27
  el += `<span class="sep updated"></span>`
17
28
  el += `<span class="text updated">`
18
29
  el += `${__("meta.created") + __("symbol.colon")}`
19
- el += `<time datetime="${date_xml(page.date)}">${date(page.date, config.date_format)}</time>`
30
+ el += `<time datetime="${date_xml(notebookArticle.created)}">${date(notebookArticle.created, config.date_format)}</time>`
20
31
  el += `</span>`
21
32
  } else {
22
- const author = theme.authors ? (theme.authors[page.author] || theme.default_author) : null
33
+ var authorId = postViewModel
34
+ ? postViewModel.render.listing.authorId
35
+ : content_config(page).article?.author
36
+ var author = stellar_data('authors') ? (stellar_data('authors')[authorId] || stellar_data('defaultAuthor')) : null
23
37
  if (author) {
24
38
  el += `<a class="author" href="${pretty_url(author.path)}">${author.name}</a>`
25
39
  el += `<span class="sep"></span>`
@@ -29,13 +43,15 @@ function layoutDiv() {
29
43
  if (!author) {
30
44
  el += `${__("meta.created") + __("symbol.colon")}`
31
45
  }
32
- el += `<time datetime="${date_xml(page.date)}">${date(page.date, config.date_format)}</time>`
46
+ var created = postViewModel ? postViewModel.item.date : page.date
47
+ var updated = postViewModel ? postViewModel.item.updated : page.updated
48
+ el += `<time datetime="${date_xml(created)}">${date(created, config.date_format)}</time>`
33
49
  el += `</span>`
34
50
  // 更新日期
35
51
  el += `<span class="sep updated"></span>`
36
52
  el += `<span class="text updated">`
37
53
  el += `${__("meta.updated") + __("symbol.colon")}`
38
- el += `<time datetime="${date_xml(page.updated)}">${date(page.updated, config.date_format)}</time>`
54
+ el += `<time datetime="${date_xml(updated)}">${date(updated, config.date_format)}</time>`
39
55
  el += `</span>`
40
56
  }
41
57
  el += `</div>`
@@ -1,11 +1,13 @@
1
1
  <%
2
2
  function layoutDiv() {
3
- const repo = page.repo || theme.wiki.tree[page.wiki]?.repo
3
+ var pageConfig = content_config(page);
4
+ var wikiViewModel = typeof viewModel !== 'undefined' && viewModel?.collection?.profile === 'wiki' ? viewModel : null
5
+ var repo = wikiViewModel?.render?.listing?.repository || pageConfig.source?.repository
4
6
  if (repo == null) {
5
7
  return ''
6
8
  }
7
9
  return `
8
- <div class="right ghrepo data-service data-service ds-ghinfo" data-api="https://${theme.api_host.ghapi}/repos/${repo}">
10
+ <div class="right ghrepo data-service data-service ds-ghinfo" data-api="${stellar_config('services.github.apiUrl')}/repos/${repo}">
9
11
  <a class="repo-link bold" href="https://github.com/${repo}">
10
12
  ${icon('github:repo')}
11
13
  <span type="text">${repo}</span>
@@ -22,4 +24,4 @@ function layoutDiv() {
22
24
  `
23
25
  }
24
26
  %>
25
- <%- layoutDiv() %>
27
+ <%- layoutDiv() %>
@@ -1,36 +1,31 @@
1
1
  <%# 笔记卡片 %>
2
+ <% var listing = render.listing %>
2
3
  <article class="md-text">
3
- <% if (note.cover) { %>
4
+ <% if (listing.cover) { %>
4
5
  <div class="post-cover">
5
- <img src="<%= note.cover %>" alt="cover" />
6
+ <img src="<%= listing.cover %>" alt="cover" />
6
7
  </div>
7
8
  <% } %>
8
- <h2 class="post-title"><%= note.title %></h2>
9
- <div class="excerpt<% if (theme.plugins.heti?.enable) { %> heti<% } %>">
9
+ <h2 class="post-title"><%= listing.title %></h2>
10
+ <div class="excerpt<% if (stellar_config('features.heti.enabled')) { %> heti<% } %>">
10
11
  <p>
11
- <% if (note.excerpt) { %>
12
- <%= strip_html(note.excerpt) %>
13
- <% } else if (note.description) { %>
14
- <%= note.description %>
15
- <% } else if (note.content && theme.notebook.auto_excerpt > 0) { %>
16
- <%= truncate(strip_html(note.content), { length: theme.notebook.auto_excerpt }) %>
17
- <% } %>
12
+ <%= listing.excerpt %>
18
13
  </p>
19
14
  </div>
20
15
  <div class="meta cap">
21
- <% if (note.pin) { %>
22
- <span class="pin"><%- icon('default:pin') %></span>
23
- <% } %>
24
16
  <span class="cap" id="post-meta">
25
17
  <%- icon('default:calendar') %>
26
- <time datetime="<%= date_xml(note.updated || note.date) %>"><%= date(note.updated || note.date, config.date_format) %></time>
18
+ <time datetime="<%= date_xml(listing.updated || listing.date) %>"><%= date(listing.updated || listing.date, config.date_format) %></time>
27
19
  </span>
28
- <% if (note.tags) { %>
29
- <% note.tags.forEach((tag, i) => { %>
20
+ <% if (listing.tags) { %>
21
+ <% listing.tags.forEach((tag, i) => { %>
30
22
  <span class="cap breadcrumb" %>>
31
23
  <span class="tag"><%= tag %></span>
32
24
  </span>
33
25
  <% }) %>
34
26
  <% } %>
27
+ <% if (listing.priority > 0) { %>
28
+ <span class="pin"><%- icon('default:pin') %></span>
29
+ <% } %>
35
30
  </div>
36
31
  </article>
@@ -1,8 +1,7 @@
1
- <%# 笔记的所属标签(容器与胶囊样式复用 article/article_tags.ejs 的 article-tags) %>
2
- <% if (page.tags) { %>
1
+ <%# 笔记的所属标签(容器与胶囊样式复用 post_tags.ejs 的 article-tags) %>
2
+ <% if (typeof tags !== 'undefined' && tags.length > 0) { %>
3
3
  <div class="article-tags<%= scrollreveal(' ') %>">
4
- <% for (const t of page.tags) { %>
5
- <% const tag = notebook.tagTree.get(t.toLowerCase()) %>
4
+ <% for (var tag of tags) { %>
6
5
  <a class="tag" href="<%= pretty_url(tag.path) %>"><%- icon('default:hashtag') %><%- escape_html(tag.name) %></a>
7
6
  <% } %>
8
7
  </div>