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
@@ -1,10 +1,17 @@
1
1
  <%# 笔记本信息卡片 %>
2
+ <% var listing = render.listing %>
2
3
  <article class="md-text">
3
- <div class="preview"><img src="<%= notebook.icon || theme.default.project %>" alt="icon"/></div>
4
+ <div class="preview">
5
+ <% if (listing.icon) { %>
6
+ <img src="<%= listing.icon %>" alt="icon"/>
7
+ <% } else { %>
8
+ <%- icon('default:documents') %>
9
+ <% } %>
10
+ </div>
4
11
  <div class="excerpt">
5
- <h2 class="post-title"><%= notebook.title || notebook.name %></h2>
6
- <% if (notebook.description) { %>
7
- <p><%= notebook.description %></p>
12
+ <h2 class="post-title"><%= listing.headline || listing.name %></h2>
13
+ <% if (listing.description) { %>
14
+ <p><%= listing.description %></p>
8
15
  <% } %>
9
16
  </div>
10
17
  </article>
@@ -1,34 +1,31 @@
1
1
  <%
2
- // 置顶内容轮播:所有带 navbar top 的列表页上方共用。
2
+ // 置顶内容轮播:所有带 Listing Nav 的列表页上方共用,关闭导航时仍独立渲染。
3
3
  // type: post / wiki / topic
4
4
  var pinType = type || 'post'
5
5
  var pinItems = []
6
6
 
7
7
  function pinValue(item) {
8
- return item.pin != null ? item.pin : item.sticky
8
+ if (['post', 'topic'].includes(item?.collection?.profile)) return item.render.listing.priority
9
+ if (pinType == 'wiki' && item?.id && item?.href) return item.priority
10
+ return item.listing?.priority
9
11
  }
10
12
 
11
- // 只要设置了 pin(含 0、负数)即视为置顶,未设置 / false 不置顶
12
13
  function isPinned(item) {
13
- var v = pinValue(item)
14
- return v !== false && v != null
14
+ return pinValue(item) > 0
15
15
  }
16
16
 
17
- // 排序仅比较数值大小,true 视作 1
18
17
  function pinWeight(item) {
19
- var v = pinValue(item)
20
- if (v === true) {
21
- return 1
22
- }
23
- var n = Number(v)
18
+ var n = Number(pinValue(item))
24
19
  return isNaN(n) ? 0 : n
25
20
  }
26
21
 
27
22
  if (pinType == 'wiki') {
28
- var shelf = theme.wiki?.shelf || []
29
- for (var wi = 0; wi < shelf.length; wi++) {
30
- var wproj = theme.wiki.tree[shelf[wi]]
31
- if (wproj != null && isPinned(wproj)) {
23
+ if (!Array.isArray(wikiItems)) {
24
+ throw new Error('Stellar v2: Wiki 置顶列表缺少显式 render.listing')
25
+ }
26
+ for (var wi = 0; wi < wikiItems.length; wi++) {
27
+ var wproj = wikiItems[wi]
28
+ if (wproj.listed && isPinned(wproj)) {
32
29
  pinItems.push(wproj)
33
30
  }
34
31
  }
@@ -36,11 +33,13 @@ if (pinType == 'wiki') {
36
33
  var allPosts = site.posts.toArray() || []
37
34
  for (var pi = 0; pi < allPosts.length; pi++) {
38
35
  var post = allPosts[pi]
39
- if (post.indexing === false) {
40
- continue
36
+ var viewModel = post_view_model(post)
37
+ if (!['post', 'topic'].includes(viewModel?.collection?.profile) || !viewModel.render?.listing) {
38
+ throw new Error(`Stellar v2: Post ${post?.source || post?.path || '<unknown>'} 缺少置顶列表 ViewModel`)
41
39
  }
42
- if (isPinned(post)) {
43
- pinItems.push(post)
40
+ if (!viewModel.render.listing.listed) continue
41
+ if (isPinned(viewModel)) {
42
+ pinItems.push(viewModel)
44
43
  }
45
44
  }
46
45
  }
@@ -50,20 +49,22 @@ pinItems.sort(function(a, b) {
50
49
  })
51
50
 
52
51
  // 文章幻灯片:固定「标题 + 一行小字」结构。
53
- // 标题:post.title;小字由 subtitle() helper 统一取值(subtitle > description > excerpt 前 50 字)。
52
+ // 标题:post.title;小字由 caption() helper 统一取值。
54
53
  // 样式与 hero 卡片 cover-info 一致;无封面时为纯白卡片(文字按普通文章颜色)。
55
- function postSlide(post) {
56
- var noCover = !(post.cover != null && post.cover.length > 0)
54
+ function postSlide(viewModel) {
55
+ var post = viewModel.render.listing
56
+ var cover = post.cover
57
+ var noCover = !(cover != null && cover.length > 0)
57
58
  var headline = post.title
58
- var sub = subtitle(post)
59
+ var sub = post.caption
59
60
  var el = ''
60
- el += '<a class="pin-slide post-slide' + (noCover ? ' no-cover' : '') + '" href="' + escape_html(pretty_url(post.link || post.path)) + '"'
61
+ el += '<a class="pin-slide post-slide' + (noCover ? ' no-cover' : '') + '" href="' + escape_html(pretty_url(post.href)) + '"'
61
62
  if (!noCover) {
62
- el += ' style="--pin-cover-url:url(\'' + escape_html(post.cover.replace(/'/g, '%27')) + '\')"'
63
+ el += ' style="--pin-cover-url:url(\'' + escape_html(cover.replace(/'/g, '%27')) + '\')"'
63
64
  }
64
65
  el += '>'
65
66
  if (!noCover) {
66
- el += '<img class="pin-slide-bg" src="' + escape_html(post.cover) + '" alt=""/>'
67
+ el += '<img class="pin-slide-bg" src="' + escape_html(cover) + '" alt=""/>'
67
68
  }
68
69
  // 有封面时文字颜色自适应(大字 contrast、小字 theme);无封面保持普通文章文字颜色
69
70
  el += '<div class="pin-slide-text"' + (noCover ? '' : ' data-text-adaptive="split"') + '>'
@@ -85,13 +86,19 @@ function projectChips(tags) {
85
86
  }
86
87
 
87
88
  function wikiSlide(proj) {
88
- var img = proj.cover || proj.icon || theme.default.project
89
- var title = proj.title || proj.name || proj.id
89
+ var img = proj.cover
90
+ var title = proj.headline || proj.name || proj.id
90
91
  var excerpt = proj.description || ''
91
92
  var el = ''
92
- el += '<a class="pin-slide" href="' + escape_html(pretty_url(proj.homepage?.path || '/')) + '" style="--pin-cover-url:url(\'' + escape_html(img.replace(/'/g, '%27')) + '\')">'
93
- el += '<img class="pin-slide-bg" src="' + escape_html(img) + '" alt=""/>'
94
- el += '<div class="pin-slide-info" data-text-adaptive="split">'
93
+ el += '<a class="pin-slide' + (img ? '' : ' no-cover') + '" href="' + escape_html(pretty_url(proj.href || '/')) + '"'
94
+ if (img) {
95
+ el += ' style="--pin-cover-url:url(\'' + escape_html(img.replace(/'/g, '%27')) + '\')"'
96
+ }
97
+ el += '>'
98
+ if (img) {
99
+ el += '<img class="pin-slide-bg" src="' + escape_html(img) + '" alt=""/>'
100
+ }
101
+ el += '<div class="pin-slide-info"' + (img ? ' data-text-adaptive="split"' : '') + '>'
95
102
  el += '<div class="pin-slide-caps">' + projectChips(proj.tags) + '</div>'
96
103
  el += '<div class="pin-slide-title">' + escape_html(title) + '</div>'
97
104
  if (excerpt.length > 0) {
@@ -119,7 +126,7 @@ if (pinItems.length > 0) {
119
126
  var groupKey = pinType == 'wiki' ? 'wiki' : 'post'
120
127
  var sliderInterval = 5000 // 自动轮播间隔固定 5000ms
121
128
  var el = ''
122
- el += '<div class="pin-slider card-hover card-hover--spotlight card-hover--tilt" id="pin-slider" data-interval="' + sliderInterval + '" data-key="' + pinType + '" data-group="' + groupKey + '">'
129
+ el += '<div class="' + ui_classes('pin-slider', 'hoverCard') + '" id="pin-slider" data-interval="' + sliderInterval + '" data-key="' + pinType + '" data-group="' + groupKey + '">'
123
130
  el += '<div class="pin-slider-track">'
124
131
  el += slidesHtml
125
132
  el += '</div>'
@@ -132,19 +139,17 @@ if (pinItems.length > 0) {
132
139
  %>
133
140
  <%- el %>
134
141
  <script>
135
- function initWhenReady() {
136
- if (typeof stellar === 'object' && typeof stellar.initPlugin === 'function') {
137
- stellar.initPlugin(initPinSlider, 'pin-slider');
138
- } else {
139
- // pin_slider 内联脚本渲染在 scripts/bootstrap 之前,等待 DOMContentLoaded 后注册
140
- document.addEventListener('DOMContentLoaded', function () {
141
- if (typeof stellar === 'object' && typeof stellar.initPlugin === 'function') {
142
- stellar.initPlugin(initPinSlider, 'pin-slider');
143
- }
144
- });
142
+ function mountPinSliderWhenReady() {
143
+ var cleanup = initPinSlider();
144
+ if (typeof cleanup === 'function') {
145
+ window.addEventListener('pagehide', cleanup, { once: true });
145
146
  }
146
147
  }
147
- initWhenReady();
148
+ if (document.readyState === 'loading') {
149
+ document.addEventListener('DOMContentLoaded', mountPinSliderWhenReady, { once: true });
150
+ } else {
151
+ mountPinSliderWhenReady();
152
+ }
148
153
  function initPinSlider() {
149
154
  var slider = document.getElementById('pin-slider');
150
155
  if (!slider) return;
@@ -1,8 +1,12 @@
1
1
  <%
2
- var item = post || {};
3
- var href = pretty_url(item.link || item.path || '/');
4
- var itemDate = item.date ? date(item.date, 'MM-DD') : '';
5
- var itemTitle = item.title || (item.date ? date(item.date, config.date_format) : '');
2
+ var postViewModel = typeof post === 'undefined' && typeof viewModel !== 'undefined' ? viewModel : null
3
+ if (postViewModel && (!['post', 'topic'].includes(postViewModel.collection?.profile) || !postViewModel.render?.listing)) {
4
+ throw new Error('Stellar v2: 归档条目缺少合法 PageViewModel.render.listing')
5
+ }
6
+ var item = postViewModel ? postViewModel.render.listing : (typeof post !== 'undefined' ? post : {})
7
+ var href = pretty_url(postViewModel ? (item.href || '/') : (item.link || item.path || '/'))
8
+ var itemDate = item.date ? date(item.date, 'MM-DD') : ''
9
+ var itemTitle = item.title || (item.date ? date(item.date, config.date_format) : '')
6
10
  %>
7
11
  <div class="archive-list">
8
12
  <a class="post fs14" href="<%- escape_html(href) %>">
@@ -4,12 +4,18 @@
4
4
  // 专栏列表页与未来首页等场景复用;无 post 时仅渲染 label。
5
5
  function layoutDiv() {
6
6
  var el = '';
7
- var bg = background || theme.default.topic;
7
+ var bg = background || '';
8
8
  // 注意:不能用 `var href` 承接,var 提升会遮蔽 partial 传入的 href 参数
9
9
  var link = pretty_url(href || '/');
10
- el += '<a class="cover card-hover card-hover--spotlight card-hover--tilt" position="bottom" style="--cover-url:url(\'' + escape_html(bg.replace(/'/g, '%27')) + '\')" href="' + link + '">';
11
- el += '<img src="' + escape_html(bg) + '" alt=""/>';
12
- el += '<div class="cover-info" position="bottom" data-text-adaptive="split">';
10
+ el += '<a class="' + ui_classes('cover', 'hoverCard', bg ? '' : 'no-cover') + '" position="bottom"';
11
+ if (bg) {
12
+ el += ' style="--cover-url:url(\'' + escape_html(bg.replace(/'/g, '%27')) + '\')"';
13
+ }
14
+ el += ' href="' + link + '">';
15
+ if (bg) {
16
+ el += '<img src="' + escape_html(bg) + '" alt=""/>';
17
+ }
18
+ el += '<div class="cover-info" position="bottom"' + (bg ? ' data-text-adaptive="split"' : '') + '>';
13
19
  if (typeof label !== 'undefined' && label) {
14
20
  el += '<div class="text topic">' + escape_html(label) + '</div>';
15
21
  }
@@ -1,103 +1,52 @@
1
1
  <%
2
- var obj = {
3
- image: post.cover
4
- };
5
- function div_default() {
6
- var el = '';
7
- el += '<article class="md-text">';
2
+ if (!viewModel || !['post', 'topic'].includes(viewModel.collection?.profile) || !viewModel.render?.listing) {
3
+ throw new Error('Stellar v2: Post 卡片缺少合法 PageViewModel.render.listing')
4
+ }
5
+ var listing = viewModel.render.listing
8
6
 
9
- // 封面:仅当显式 cover 为完整 URL 时渲染(Unsplash 自动封面接口已失效,不再生成)
10
- if (obj.image && obj.image.includes('/')) {
11
- el += '<div class="post-cover">';
12
- el += '<img src="' + escape_html(obj.image) + '"/>';
13
- el += '</div>';
7
+ function divDefault() {
8
+ var el = '<article class="md-text">'
9
+ if (listing.cover && listing.cover.includes('/')) {
10
+ el += `<div class="post-cover"><img src="${escape_html(listing.cover)}"/></div>`
14
11
  }
15
-
16
- // 标题
17
- el += '<h2 class="post-title">';
18
- el += post.title ? escape_html(post.title) : date(post.date, config.date_format);
19
- el += '</h2>';
20
-
21
- // 摘要
22
- el += '<div class="excerpt';
23
- if (theme.plugins.heti?.enable) {
24
- el += ' heti';
12
+ var title = listing.title || (listing.date ? date(listing.date, config.date_format) : '')
13
+ el += `<h2 class="post-title">${escape_html(title)}</h2>`
14
+ el += `<div class="excerpt${viewModel.render.article.heti ? ' heti' : ''}"><p>${escape_html(listing.excerpt)}</p></div>`
15
+ el += '<div class="meta cap"><span class="cap" id="post-meta">'
16
+ el += icon('default:calendar')
17
+ if (listing.date) {
18
+ el += `<time datetime="${date_xml(listing.date)}">${date(listing.date, config.date_format)}</time>`
25
19
  }
26
- el += '">';
27
- el += '<p>';
28
- if (post.excerpt) {
29
- el += escape_html(strip_html(post.excerpt));
30
- } else if (post.description) {
31
- el += escape_html(post.description);
32
- } else if (post.content && theme.article.auto_excerpt > 0) {
33
- el += escape_html(truncate(strip_html(post.content), {length: theme.article.auto_excerpt}));
20
+ el += '</span>'
21
+ if (listing.categories.length > 0) {
22
+ var categoryStyle = listing.categoryStyle ? ` style="${escape_html(listing.categoryStyle)}"` : ''
23
+ el += `<span class="cap breadcrumb"${categoryStyle}>${icon('default:category')}<span>${escape_html(listing.categories.join(' / '))}</span></span>`
34
24
  }
35
- el += '</p>';
36
- el += '</div>';
37
-
38
- // meta
39
- el += '<div class="meta cap">';
40
- el += '<span class="cap" id="post-meta">';
41
- el += icon('default:calendar')
42
- // time
43
- el += `<time datetime="${date_xml(post.date)}">${date(post.date, config.date_format)}</time>`
44
- el += '</span>';
45
- // cat
46
- if (post.categories && post.categories.length > 0) {
47
- if (post.layout === 'post' && post.categories && post.categories.length > 0) {
48
- var cats = [];
49
- if (post.categories) {
50
- post.categories.forEach((cat, i) => {
51
- cats.push(cat.name);
52
- });
53
- }
54
- if (cats.length > 0) {
55
- let str = cats.join(' / ');
56
- let lastCat = cats.pop();
57
- el += '<span class="cap breadcrumb"' + category_color(lastCat) + '>';
58
- el += icon('default:category')
59
- el += `<span>${escape_html(str)}</span>`
60
- el += '</span>';
61
- }
62
- }
25
+ if (listing.tags.length > 0) {
26
+ el += '<span class="card-tags">'
27
+ listing.tags.forEach(function(tag) {
28
+ el += `<span class="cap tag-chip">${icon('default:hashtag')}${escape_html(tag)}</span>`
29
+ })
30
+ el += '</span>'
63
31
  }
64
- // 置顶文章由轮播(默认)或首页列表靠前展示(flat 平铺)承担,卡片内不显示 pin 图标。
65
- // 文章标签(最多 5 个,#580)
66
- if (theme.article.card_tags && post.tags && post.tags.length > 0) {
67
- el += '<span class="card-tags">';
68
- post.tags.forEach((tag, i) => {
69
- if (i >= 5) {
70
- return;
71
- }
72
- el += `<span class="cap tag-chip">${icon('default:hashtag')}${escape_html(tag.name)}</span>`;
73
- });
74
- el += '</span>';
32
+ if (listing.priority > 0) {
33
+ el += `<span class="pin">${icon('default:pin')}</span>`
75
34
  }
76
- el += '</div>';
77
- el += '</article>';
78
- return el;
35
+ return el + '</div></article>'
79
36
  }
80
- function div_photo() {
81
- var el = '';
82
- // 小字取值统一由 subtitle() helper 提供:subtitle > description > excerpt 前 50 字
83
- var caption = subtitle(post);
84
- // hero 卡片文字区固定 bottom:标题 + 一行小字,不再有 top 布局
85
- el += '<div class="cover" position="bottom" style="--cover-url:url(\'' + escape_html(obj.image.replace(/'/g, '%27')) + '\')">';
86
- el += '<img src="' + escape_html(obj.image) + '"/>';
87
- el += '<div class="cover-info" position="bottom" data-text-adaptive="split">';
88
- el += '<div class="text headline">' + escape_html(post.title ? post.title : date(post.date, config.date_format)) + '</div>';
89
- if (caption.length > 0) {
90
- el += '<div class="text caption">' + escape_html(caption) + '</div>';
91
- }
92
- el += '</div>';
93
- el += '</div>';
94
- return el;
37
+
38
+ function divPhoto() {
39
+ var title = listing.title || (listing.date ? date(listing.date, config.date_format) : '')
40
+ var el = `<div class="cover" position="bottom" style="--cover-url:url('${escape_html(listing.cover.replace(/'/g, '%27'))}')">`
41
+ el += `<img src="${escape_html(listing.cover)}"/>`
42
+ el += '<div class="cover-info" position="bottom" data-text-adaptive="split">'
43
+ el += `<div class="text headline">${escape_html(title)}</div>`
44
+ if (listing.caption) el += `<div class="text caption">${escape_html(listing.caption)}</div>`
45
+ return el + '</div></div>'
95
46
  }
47
+
96
48
  function div() {
97
- if (theme.article.card_style == 'hero' && obj.image && obj.image.length > 0) {
98
- return div_photo();
99
- }
100
- return div_default();
49
+ return listing.cardStyle === 'hero' && listing.cover ? divPhoto() : divDefault()
101
50
  }
102
51
  %>
103
52
  <%- div() %>
@@ -1,9 +1,11 @@
1
1
  <%
2
2
  function layoutDiv() {
3
3
  var el = '';
4
- var bg = topic.cover || topic.icon || theme.default.topic;
5
- var label = topic.title || topic.name;
6
- var latest = topic.homepage;
4
+ if (!viewModel?.render?.listing) throw new Error('Stellar v2: Topic 卡片缺少显式 render.listing')
5
+ var topic = viewModel.render.listing
6
+ var bg = topic.cover;
7
+ var label = topic.headline || topic.name;
8
+ var latest = topic.latest;
7
9
  el += '<article class="md-text">';
8
10
  // 专栏标题(story 文章 h2 样式,置于卡片外)
9
11
  el += '<h2 class="topic-title">' + escape_html(label) + '</h2>';
@@ -18,8 +20,8 @@ function layoutDiv() {
18
20
  post: latest
19
21
  });
20
22
  // 其他文章(排除最新,默认展示 3 条,剩余文章可展开)
21
- if (topic.pages && topic.pages.length > 1) {
22
- var otherPosts = topic.pages.slice(1);
23
+ if (topic.items && topic.items.length > 0) {
24
+ var otherPosts = topic.items;
23
25
  var visiblePosts = otherPosts.slice(0, 3);
24
26
  var hiddenPosts = otherPosts.slice(3);
25
27
  el += '<div class="topic-posts">';
@@ -1,10 +1,13 @@
1
1
  <%
2
2
  function layoutDiv() {
3
3
  var el = '';
4
- var cover = proj.cover;
5
- var projectIcon = proj.icon;
6
- var caption = subtitle(proj);
7
- var headline = proj.headline || proj.title || proj.name || '';
4
+ if (!listing || typeof listing !== 'object') {
5
+ throw new Error('Stellar v2: Wiki 卡片缺少显式 render.listing')
6
+ }
7
+ var cover = listing.cover;
8
+ var projectIcon = listing.icon;
9
+ var caption = listing.caption;
10
+ var headline = listing.headline || listing.name;
8
11
  el += '<article class="wiki-card-content">';
9
12
  el += '<div class="wiki-card-cover' + (cover ? '' : ' no-cover') + '" position="bottom"';
10
13
  if (cover) {
@@ -19,22 +22,22 @@ function layoutDiv() {
19
22
  }
20
23
  el += '>';
21
24
  el += '<div class="wiki-card-summary">';
22
- if (proj.tags && proj.tags.length > 0) {
25
+ if (listing.tags && listing.tags.length > 0) {
23
26
  el += '<div class="wiki-tags wiki-meta">';
24
- for (var i = 0; i < proj.tags.length; i++) {
25
- var tag = proj.tags[i];
27
+ for (var i = 0; i < listing.tags.length; i++) {
28
+ var tag = listing.tags[i];
26
29
  el += '<span>' + escape_html(tag) + '</span>';
27
30
  }
28
31
  el += '</div>';
29
32
  }
30
33
  el += '<h2 class="headline">' + escape_html(headline) + '</h2>';
31
- if (proj.available || proj.repo) {
34
+ if (listing.audience || listing.repository) {
32
35
  el += '<div class="wiki-meta">';
33
- if (proj.available) {
34
- el += '<span class="wiki-available">' + icon('default:platforms') + '<span class="label">' + escape_html(__('meta.available')) + '</span><span class="value">' + escape_html(proj.available) + '</span></span>';
36
+ if (listing.audience) {
37
+ el += '<span class="wiki-available">' + icon('default:platforms') + '<span class="label">' + escape_html(__('meta.available')) + '</span><span class="value">' + escape_html(listing.audience) + '</span></span>';
35
38
  }
36
- if (proj.repo) {
37
- el += '<span class="wiki-stars data-service ds-ghinfo" data-api="https://' + theme.api_host.ghapi + '/repos/' + escape_html(proj.repo) + '">';
39
+ if (listing.repository) {
40
+ el += '<span class="wiki-stars data-service ds-ghinfo" data-api="' + escape_html(listing.repositoryApi) + '">';
38
41
  el += icon('default:fire') + '<span type="text" id="stargazers_count"></span>';
39
42
  el += '</span>';
40
43
  }
@@ -49,7 +52,7 @@ function layoutDiv() {
49
52
  el += icon('default:documents');
50
53
  }
51
54
  el += '</div>';
52
- el += '<div class="project-text"><div class="project-name">' + escape_html(proj.name || proj.title || '') + '</div>';
55
+ el += '<div class="project-text"><div class="project-name">' + escape_html(listing.name || '') + '</div>';
53
56
  if (caption.length > 0) {
54
57
  el += '<div class="project-subtitle">' + escape_html(caption) + '</div>';
55
58
  }
@@ -1,8 +1,8 @@
1
- <div class='float-panel'>
2
- <button type='button' style='display:none' class='laptop-only rightbar-toggle mobile' onclick='sidebar.rightbar()'>
1
+ <div class="site-dock" role="group" aria-label="Layout panels">
2
+ <button type="button" class="<%- ui_classes('site-dock__button site-dock__button--rightbar', 'interactive') %>" aria-label="Open rightbar" aria-controls="rightbar-region" aria-expanded="false" data-shell-action="toggle-rightbar-drawer">
3
3
  <%- icon('default:rightbar', '', true) %>
4
4
  </button>
5
- <button type='button' style='display:none' class='mobile-only leftbar-toggle mobile' onclick='sidebar.leftbar()'>
5
+ <button type="button" class="<%- ui_classes('site-dock__button site-dock__button--leftbar', 'interactive') %>" aria-label="Open leftbar" aria-controls="leftbar-region" aria-expanded="false" data-shell-action="toggle-leftbar-drawer">
6
6
  <%- icon('default:leftbar', '', true) %>
7
7
  </button>
8
8
  </div>
@@ -0,0 +1,8 @@
1
+ <%
2
+ var allowedKinds = ['cover', 'brand', 'search', 'navigation', 'widget', 'content', 'footer', 'menu-button', 'scripts']
3
+ if (!allowedKinds.includes(kind)) {
4
+ throw new Error('Stellar Layout Item: 未知 kind ' + kind)
5
+ }
6
+ var itemBody = typeof body === 'string' ? body : ''
7
+ %>
8
+ <%- itemBody %>
@@ -0,0 +1,17 @@
1
+ <%
2
+ var allowedPlacements = ['main', 'leftbar', 'topbar', 'rightbar']
3
+ if (!allowedPlacements.includes(placement)) {
4
+ throw new Error('Stellar Layout Navigation: 未知 placement ' + placement)
5
+ }
6
+ var navigationItems = Array.isArray(entries) ? entries : []
7
+ var navigationBody = partial('_partial/components/collection', {options: {
8
+ layout: 'list',
9
+ variant: 'nav',
10
+ items: navigationItems
11
+ }})
12
+ var html = ''
13
+ if ((navigationBody || '').trim().length > 0) {
14
+ html = `<nav class="menu dis-select${placement === 'main' ? ' mobile-hidden' : ''}">${navigationBody}</nav>`
15
+ }
16
+ %>
17
+ <%- html %>
@@ -0,0 +1,16 @@
1
+ <%
2
+ var allowedSlots = ['topbar', 'leftbar', 'rightbar']
3
+ if (!allowedSlots.includes(slot)) {
4
+ throw new Error('Stellar Layout Region: 未知 slot ' + slot)
5
+ }
6
+ var regionBody = typeof body === 'string' ? body : ''
7
+ var html = ''
8
+ if (slot === 'topbar') {
9
+ html = `<header id="topbar-region" class="site-region site-region--topbar ui-surface" data-region="topbar"><div class="site-region__viewport">${regionBody}</div></header>`
10
+ } else if (slot === 'leftbar') {
11
+ html = `<aside id="leftbar-region" class="site-region site-region--leftbar" data-region="leftbar" aria-label="Leftbar"><div class="site-region__surface ui-surface"><div class="site-region__decoration" aria-hidden="true"></div><div class="site-region__viewport">${regionBody}</div></div></aside>`
12
+ } else if (slot === 'rightbar') {
13
+ html = `<aside id="rightbar-region" class="site-region site-region--rightbar" data-region="rightbar" aria-label="Rightbar"><div class="site-region__surface ui-drawer-surface"><div class="site-region__viewport">${regionBody}</div></div></aside>`
14
+ }
15
+ %>
16
+ <%- html %>
@@ -0,0 +1,8 @@
1
+ <%
2
+ var allowedSlots = ['cover', 'topbar', 'leftbar', 'rightbar', 'navigation', 'content', 'footer', 'scripts']
3
+ if (!allowedSlots.includes(slot)) {
4
+ throw new Error('Stellar Layout Section: 未知 slot ' + slot)
5
+ }
6
+ var sectionItems = Array.isArray(items) ? items : []
7
+ %>
8
+ <%- sectionItems.join('') %>
@@ -0,0 +1,35 @@
1
+ <%
2
+ var shellDocument = documentModel || {}
3
+ var shellPage = pageModel || {}
4
+ var shellRegions = regions || {}
5
+ var language = escape_html(shellDocument.language || 'zh-CN')
6
+ var htmlAttributes = shellDocument.preferredTheme === 'auto' ? '' : ` data-theme="${escape_html(shellDocument.preferredTheme)}"`
7
+ var presentRegions = ['topbar', 'leftbar', 'rightbar'].filter(function(region) {
8
+ return typeof shellRegions[region] === 'string' && shellRegions[region].trim().length > 0
9
+ })
10
+ var pageAttributes = ` data-page-type="${escape_html(shellPage.pageType || 'content')}"`
11
+ pageAttributes += ` data-page-layout="${escape_html(shellPage.layout || '')}"`
12
+ if (shellPage.articleStyle) pageAttributes += ` data-article-style="${escape_html(shellPage.articleStyle)}"`
13
+ if (shellPage.indent) pageAttributes += ' data-text-indent'
14
+ var html = '<!DOCTYPE html>'
15
+ html += `<html lang="${language}"${htmlAttributes}>`
16
+ html += head
17
+ html += `<body${pageAttributes}>`
18
+ html += bodyBegin || ''
19
+ html += siteBackground || ''
20
+ html += cover || ''
21
+ html += `<div class="site-shell" id="start" data-regions="${presentRegions.join(' ')}">`
22
+ html += shellRegions.topbar || ''
23
+ html += '<div class="site-workspace">'
24
+ html += shellRegions.leftbar || ''
25
+ html += `<main class="site-main" id="main">${main || ''}</main>`
26
+ html += shellRegions.rightbar || ''
27
+ html += '</div>'
28
+ html += '<button type="button" class="site-scrim" data-shell-action="dismiss-drawer" aria-label="Close navigation" tabindex="-1"></button>'
29
+ html += controls || ''
30
+ html += typeof overlays === 'string' ? overlays : ''
31
+ html += '</div>'
32
+ html += `<div class="site-scripts">${scripts || ''}</div>`
33
+ html += '</body></html>'
34
+ %>
35
+ <%- html %>