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.
- package/CHANGELOG.md +63 -5
- package/CONTRIBUTING.md +29 -120
- package/README.md +66 -73
- package/README_EN.md +66 -73
- package/_config.yml +890 -743
- package/_data/icons.yml +43 -171
- package/_data/widgets.yml +1 -1
- package/assets/icon-v2-x512.webp +0 -0
- package/languages/en.yml +59 -2
- package/languages/zh-CN.yml +59 -2
- package/languages/zh-TW.yml +59 -2
- package/layout/404.ejs +7 -4
- package/layout/_partial/comments/artalk/layout.ejs +3 -2
- package/layout/_partial/comments/beaudar/layout.ejs +2 -2
- package/layout/_partial/comments/giscus/layout.ejs +2 -5
- package/layout/_partial/comments/layout.ejs +11 -40
- package/layout/_partial/comments/twikoo/layout.ejs +3 -2
- package/layout/_partial/comments/utterances/layout.ejs +2 -2
- package/layout/_partial/comments/waline/layout.ejs +3 -2
- package/layout/_partial/components/collection-item.ejs +30 -13
- package/layout/_partial/components/collection.ejs +2 -2
- package/layout/_partial/cover/index.ejs +5 -2
- package/layout/_partial/cover/wiki_cover.ejs +39 -28
- package/layout/_partial/dropdown.ejs +26 -14
- package/layout/_partial/head.ejs +96 -69
- package/layout/_partial/main/article/contributors.ejs +12 -9
- package/layout/_partial/main/article/post_footer.ejs +47 -0
- package/layout/_partial/main/article/post_read_next.ejs +22 -0
- package/layout/_partial/main/article/post_related.ejs +14 -0
- package/layout/_partial/main/article/post_tags.ejs +12 -0
- package/layout/_partial/main/article/share.ejs +55 -0
- package/layout/_partial/main/footer.ejs +11 -10
- package/layout/_partial/main/{navbar/nav_tabs_blog.ejs → listing_nav/blog.ejs} +21 -18
- package/layout/_partial/main/listing_nav/wiki.ejs +56 -0
- package/layout/_partial/main/navbar/article_banner.ejs +39 -35
- package/layout/_partial/main/navbar/breadcrumb/blog.ejs +15 -28
- package/layout/_partial/main/navbar/breadcrumb/note.ejs +12 -5
- package/layout/_partial/main/navbar/breadcrumb/wiki.ejs +15 -11
- package/layout/_partial/main/navbar/dateinfo.ejs +28 -12
- package/layout/_partial/main/navbar/ghinfo.ejs +5 -3
- package/layout/_partial/main/notebook/note_card.ejs +12 -17
- package/layout/_partial/main/notebook/note_tags.ejs +3 -4
- package/layout/_partial/main/notebook/notebook_card.ejs +11 -4
- package/layout/_partial/main/pin_slider.ejs +48 -43
- package/layout/_partial/main/post_list/archive_item.ejs +8 -4
- package/layout/_partial/main/post_list/latest_post_card.ejs +10 -4
- package/layout/_partial/main/post_list/post_card.ejs +39 -90
- package/layout/_partial/main/post_list/topic_card.ejs +7 -5
- package/layout/_partial/main/post_list/wiki_card.ejs +16 -13
- package/layout/_partial/menubtn.ejs +3 -3
- package/layout/_partial/primitives/item.ejs +8 -0
- package/layout/_partial/primitives/navigation.ejs +17 -0
- package/layout/_partial/primitives/region.ejs +16 -0
- package/layout/_partial/primitives/section.ejs +8 -0
- package/layout/_partial/primitives/shell.ejs +35 -0
- package/layout/_partial/regions/widgets.ejs +84 -0
- package/layout/_partial/scripts/defines.ejs +46 -76
- package/layout/_partial/scripts/runtime.ejs +55 -0
- package/layout/_partial/scripts.ejs +18 -42
- package/layout/_partial/search/dialog.ejs +33 -0
- package/layout/_partial/search/shortcut.ejs +1 -0
- package/layout/_partial/sidebar/brand.ejs +127 -0
- package/layout/_partial/sidebar/menu.ejs +59 -14
- package/layout/_partial/sidebar/search.ejs +58 -41
- package/layout/_partial/widgets/actions.ejs +25 -0
- package/layout/_partial/widgets/author.ejs +9 -5
- package/layout/_partial/widgets/components/linklist.ejs +1 -2
- package/layout/_partial/widgets/ghissues.ejs +7 -10
- package/layout/_partial/widgets/ghrepo.ejs +23 -16
- package/layout/_partial/widgets/ghuser.ejs +3 -3
- package/layout/_partial/widgets/recent.ejs +25 -21
- package/layout/_partial/widgets/related.ejs +25 -34
- package/layout/_partial/widgets/settings.ejs +17 -0
- package/layout/_partial/widgets/tagtree.ejs +18 -10
- package/layout/_partial/widgets/toc.ejs +17 -9
- package/layout/_partial/widgets/tree.ejs +12 -13
- package/layout/archive.ejs +20 -13
- package/layout/categories.ejs +4 -3
- package/layout/collection-preview.ejs +8 -9
- package/layout/index.ejs +32 -43
- package/layout/index_topic.ejs +6 -13
- package/layout/index_wiki.ejs +17 -34
- package/layout/layout.ejs +195 -65
- package/layout/notebooks.ejs +3 -3
- package/layout/notes.ejs +4 -4
- package/layout/page.ejs +95 -50
- package/layout/settings.ejs +109 -0
- package/layout/tags.ejs +4 -3
- package/{THIRD-PARTY-NOTICES.md → legal/THIRD-PARTY-NOTICES.md} +8 -4
- package/package.json +28 -6
- package/scripts/commands/stellar.js +55 -0
- package/scripts/events/index.js +15 -9
- package/scripts/events/lib/authors.js +9 -7
- package/scripts/events/lib/config-hot-reload.js +65 -0
- package/scripts/events/lib/config-schema.js +20 -0
- package/scripts/events/lib/config.js +22 -63
- package/scripts/events/lib/content-config.js +5 -0
- package/scripts/events/lib/doc_tree.js +99 -9
- package/scripts/events/lib/links.js +6 -3
- package/scripts/events/lib/notebooks.js +200 -8
- package/scripts/events/lib/utils.js +4 -4
- package/scripts/events/lib/version-check.js +57 -3
- package/scripts/filters/index.js +2 -27
- package/scripts/filters/lib/img_lazyload.js +4 -126
- package/scripts/filters/lib/img_onerror.js +14 -17
- package/scripts/filters/lib/page-view-model.js +152 -0
- package/scripts/generators/404.js +13 -8
- package/scripts/generators/author.js +16 -11
- package/scripts/generators/notebooks.js +68 -39
- package/scripts/generators/search.js +62 -67
- package/scripts/generators/settings.js +43 -0
- package/scripts/generators/stellar-icons.js +13 -5
- package/scripts/generators/topic.js +24 -13
- package/scripts/generators/wiki.js +49 -21
- package/scripts/helpers/ai_label.js +6 -12
- package/scripts/helpers/brand.js +17 -0
- package/scripts/helpers/browser_runtime_manifest.js +12 -0
- package/scripts/helpers/caption.js +8 -0
- package/scripts/helpers/category_color.js +13 -13
- package/scripts/helpers/collection.js +18 -0
- package/scripts/helpers/comments_model.js +14 -0
- package/scripts/helpers/extension_assets.js +8 -0
- package/scripts/helpers/json_ld.js +16 -7
- package/scripts/helpers/mdrender.js +3 -9
- package/scripts/helpers/menu.js +9 -0
- package/scripts/helpers/post_view_model.js +23 -0
- package/scripts/helpers/regions.js +37 -0
- package/scripts/helpers/scrollreveal.js +7 -7
- package/scripts/helpers/search_domain.js +34 -0
- package/scripts/helpers/service_provider.js +9 -0
- package/scripts/helpers/settings.js +16 -0
- package/scripts/helpers/share_action.js +8 -0
- package/scripts/helpers/stellar_config.js +12 -0
- package/scripts/helpers/stellar_data.js +8 -0
- package/scripts/helpers/stellar_info.js +21 -16
- package/scripts/helpers/stellar_inject.js +9 -0
- package/scripts/helpers/ui_classes.js +12 -0
- package/scripts/lib/ai_label.js +14 -11
- package/scripts/lib/brand.js +41 -0
- package/scripts/lib/browser-runtime.js +115 -0
- package/scripts/lib/caption.js +21 -0
- package/scripts/lib/collection-pipeline/adapters/notebook.js +62 -0
- package/scripts/lib/collection-pipeline/adapters/post.js +20 -0
- package/scripts/lib/collection-pipeline/adapters/topic.js +82 -0
- package/scripts/lib/collection-pipeline/adapters/wiki.js +20 -0
- package/scripts/lib/collection-pipeline/index.js +169 -0
- package/scripts/lib/collection-pipeline/registry.js +27 -0
- package/scripts/lib/collection-pipeline/shared.js +164 -0
- package/scripts/lib/comments.js +60 -0
- package/scripts/lib/config-inject.js +20 -0
- package/scripts/lib/config-schema.js +1095 -0
- package/scripts/lib/content-config.js +157 -0
- package/scripts/lib/content-defaults.js +56 -0
- package/scripts/lib/content-membership.js +233 -0
- package/scripts/lib/contribution-contract.js +165 -0
- package/scripts/lib/contribution-registry.js +429 -0
- package/scripts/lib/doc_tree.js +46 -44
- package/scripts/lib/doctor.js +296 -0
- package/scripts/lib/front-matter.js +29 -0
- package/scripts/lib/hero-effect-registry.js +262 -0
- package/scripts/lib/html-images.js +128 -0
- package/scripts/lib/internal-constants.js +152 -0
- package/scripts/lib/layout-config.js +62 -0
- package/scripts/lib/mdrender_html.js +36 -23
- package/scripts/lib/menu.js +36 -0
- package/scripts/lib/model-schema.js +90 -0
- package/scripts/lib/models/index.js +1542 -0
- package/scripts/lib/new-note.js +172 -0
- package/scripts/lib/page-view-model-registry.js +103 -0
- package/scripts/lib/regions.js +132 -0
- package/scripts/lib/runtime-data.js +23 -0
- package/scripts/lib/safe-path.js +44 -0
- package/scripts/lib/search-domain.js +59 -0
- package/scripts/lib/seo.js +10 -10
- package/scripts/lib/service-provider.js +12 -0
- package/scripts/lib/settings.js +16 -0
- package/scripts/lib/share-services.js +96 -0
- package/scripts/lib/source-config.js +27 -0
- package/scripts/lib/theme-metadata.js +22 -0
- package/scripts/lib/ui-capabilities.js +32 -0
- package/scripts/lib/widget-registry.js +150 -0
- package/scripts/lib/wiki_readme.js +15 -11
- package/scripts/schema/config-rules.js +290 -0
- package/scripts/schema/config-schema.js +163 -0
- package/scripts/schema/content-config-rules.js +264 -0
- package/scripts/schema/content-config-schema.js +321 -0
- package/scripts/schema/model-schema.js +971 -0
- package/scripts/schema/schema-utils.js +48 -0
- package/scripts/tags/index.js +2 -3
- package/scripts/tags/lib/albums.js +6 -6
- package/scripts/tags/lib/banner.js +10 -4
- package/scripts/tags/lib/box.js +1 -1
- package/scripts/tags/lib/button.js +1 -1
- package/scripts/tags/lib/chat.js +9 -31
- package/scripts/tags/lib/checkbox.js +6 -1
- package/scripts/tags/lib/copy.js +4 -1
- package/scripts/tags/lib/dropdown.js +6 -4
- package/scripts/tags/lib/emoji.js +5 -10
- package/scripts/tags/lib/friends.js +4 -4
- package/scripts/tags/lib/gallery.js +7 -7
- package/scripts/tags/lib/ghcard.js +5 -3
- package/scripts/tags/lib/gist.js +16 -0
- package/scripts/tags/lib/grid.js +4 -2
- package/scripts/tags/lib/hashtag.js +1 -1
- package/scripts/tags/lib/icon.js +1 -1
- package/scripts/tags/lib/image.js +1 -1
- package/scripts/tags/lib/link.js +6 -3
- package/scripts/tags/lib/mark.js +8 -3
- package/scripts/tags/lib/md.js +1 -1
- package/scripts/tags/lib/note.js +1 -1
- package/scripts/tags/lib/okr.js +18 -1
- package/scripts/tags/lib/posters.js +6 -6
- package/scripts/tags/lib/quot.js +15 -5
- package/scripts/tags/lib/rating.js +7 -4
- package/scripts/tags/lib/sites.js +8 -6
- package/scripts/tags/lib/tip.js +6 -6
- package/scripts/tags/lib/toc.js +2 -2
- package/scripts/tags/lib/vote.js +8 -5
- package/source/css/_appearances/_mixins.styl +258 -0
- package/source/css/_appearances/card.styl +30 -0
- package/source/css/_appearances/flat.styl +44 -0
- package/source/css/_appearances/glass.styl +138 -0
- package/source/css/_appearances/minimal.styl +325 -0
- package/source/css/_common/base.styl +5 -9
- package/source/css/_common/blockquote.styl +0 -1
- package/source/css/_common/button.styl +1 -1
- package/source/css/_common/device.styl +24 -42
- package/source/css/_common/dropdown.styl +20 -14
- package/source/css/_common/highlight.styl +5 -12
- package/source/css/_common/icon.styl +38 -0
- package/source/css/_common/input.styl +33 -0
- package/source/css/_common/loading.styl +2 -2
- package/source/css/_common/svg.styl +0 -8
- package/source/css/_components/collection.styl +21 -64
- package/source/css/_components/layout.styl +524 -84
- package/source/css/_components/list.styl +36 -22
- package/source/css/_components/main.styl +16 -19
- package/source/css/_components/md.styl +8 -13
- package/source/css/_components/pages/article-indent.styl +1 -1
- package/source/css/_components/pages/article-story.styl +7 -6
- package/source/css/_components/pages/article-tech.styl +5 -5
- package/source/css/_components/pages/collection-preview.styl +1 -5
- package/source/css/_components/pages/settings.styl +184 -0
- package/source/css/_components/partial/article-banner.styl +2 -2
- package/source/css/_components/partial/article-footer.styl +0 -32
- package/source/css/_components/partial/article-share.styl +48 -0
- package/source/css/_components/partial/article-tags.styl +1 -1
- package/source/css/_components/partial/cover.styl +13 -13
- package/source/css/_components/partial/listing-nav.styl +68 -0
- package/source/css/_components/partial/paginator.styl +1 -1
- package/source/css/_components/pin-slider.styl +3 -3
- package/source/css/_components/sidebar/brand.styl +135 -0
- package/source/css/_components/sidebar/footer.styl +14 -31
- package/source/css/_components/sidebar/nav-area.styl +4 -0
- package/source/css/_components/sidebar/search.styl +176 -26
- package/source/css/_components/sidebar/sidebar.styl +76 -110
- package/source/css/_components/tag-plugins/banner.styl +16 -28
- package/source/css/_components/tag-plugins/checkbox.styl +7 -22
- package/source/css/_components/tag-plugins/copy.styl +3 -5
- package/source/css/_components/tag-plugins/gallery.styl +2 -2
- package/source/css/_components/tag-plugins/grid.styl +3 -0
- package/source/css/_components/tag-plugins/image.styl +2 -1
- package/source/css/_components/tag-plugins/link.styl +0 -1
- package/source/css/_components/tag-plugins/mark.styl +19 -4
- package/source/css/_components/tag-plugins/mdrender.styl +2 -2
- package/source/css/_components/tag-plugins/navbar.styl +23 -17
- package/source/css/_components/tag-plugins/note.styl +2 -2
- package/source/css/_components/tag-plugins/okr.styl +1 -2
- package/source/css/_components/tag-plugins/quot.styl +5 -0
- package/source/css/_components/tag-plugins/rating.styl +3 -2
- package/source/css/_components/tag-plugins/timeline.styl +1 -1
- package/source/css/_components/tag-plugins/tip.styl +1 -1
- package/source/css/_components/tag-plugins/vote.styl +3 -2
- package/source/css/_components/widgets/ghrepo.styl +2 -1
- package/source/css/_components/widgets/ghuser.styl +4 -6
- package/source/css/_components/widgets/settings.styl +49 -0
- package/source/css/_components/widgets/timeline.styl +2 -2
- package/source/css/_components/widgets/toc.styl +12 -33
- package/source/css/_components/widgets/widgets.styl +14 -19
- package/source/css/_components/wiki-card.styl +2 -2
- package/source/css/_custom.styl +26 -32
- package/source/css/_defines/func.styl +47 -37
- package/source/css/_defines/theme_base.styl +8 -10
- package/source/css/_plugins/card-hover.styl +1 -1
- package/source/css/_plugins/copycode.styl +16 -19
- package/source/css/_plugins/index.styl +3 -8
- package/source/css/_plugins/lazyload.styl +1 -1
- package/source/css/main.styl +12 -0
- package/source/js/main.js +302 -59
- package/source/js/plugins/adaptive-text.js +33 -16
- package/source/js/plugins/card-hover.js +2 -24
- package/source/js/plugins/copycode.js +10 -16
- package/source/js/plugins/voice.js +51 -48
- package/source/js/profile.js +316 -0
- package/source/js/runtime/asset-loader.js +61 -0
- package/source/js/runtime/extension-registry.js +149 -0
- package/source/js/runtime/extensions/card-hover.js +5 -0
- package/source/js/runtime/extensions/color-scheme-switch.js +101 -0
- package/source/js/runtime/extensions/comments.js +200 -0
- package/source/js/runtime/extensions/deferred-icons.js +53 -0
- package/source/js/{plugins → runtime/extensions}/dropdown.js +69 -30
- package/source/js/runtime/extensions/feature.js +200 -0
- package/source/js/runtime/extensions/hero-effect.js +179 -0
- package/source/js/runtime/extensions/reveal.js +80 -0
- package/source/js/runtime/extensions/search.js +23 -0
- package/source/js/{services.js → runtime/extensions/services.js} +67 -54
- package/source/js/runtime/extensions/settings.js +235 -0
- package/source/js/runtime/hero-effects/ferrofluid.js +385 -0
- package/source/js/{plugins → runtime/hero-effects}/galaxy.js +53 -177
- package/source/js/runtime/hero-effects/light-rays.js +293 -0
- package/source/js/runtime/index.js +75 -0
- package/source/js/runtime/legacy-request-adapter.js +47 -0
- package/source/js/runtime/request-cache.js +219 -0
- package/source/js/search/algolia-search.js +76 -51
- package/source/js/search/highlight.js +1 -1
- package/source/js/search/local-search.js +96 -57
- package/source/js/search/shortcut.js +31 -20
- package/source/js/services/friends_and_posts.js +6 -1
- package/source/js/services/rating.js +14 -6
- package/source/js/services/siteinfo.js +3 -7
- package/source/js/services/timeline.js +1 -1
- package/source/js/services/vote.js +7 -5
- package/source/js/services/weibo.js +1 -1
- package/source/js/utils.js +19 -444
- package/.claude/skills/stellar-theme-dev/SKILL.md +0 -51
- package/_data/chat_users.yml +0 -0
- package/layout/_partial/comments/artalk/script.ejs +0 -76
- package/layout/_partial/comments/beaudar/script.ejs +0 -33
- package/layout/_partial/comments/giscus/script.ejs +0 -31
- package/layout/_partial/comments/script.ejs +0 -3
- package/layout/_partial/comments/twikoo/script.ejs +0 -25
- package/layout/_partial/comments/utterances/script.ejs +0 -33
- package/layout/_partial/comments/waline/script.ejs +0 -43
- package/layout/_partial/main/article/article_footer.ejs +0 -164
- package/layout/_partial/main/article/article_tags.ejs +0 -16
- package/layout/_partial/main/article/read_next.ejs +0 -63
- package/layout/_partial/main/article/related_posts.ejs +0 -16
- package/layout/_partial/main/navbar/nav_tabs_wiki.ejs +0 -52
- package/layout/_partial/scripts/bootstrap.ejs +0 -37
- package/layout/_partial/scripts/lazyload.ejs +0 -89
- package/layout/_partial/sidebar/grad-def.ejs +0 -26
- package/layout/_partial/sidebar/index_leftbar.ejs +0 -191
- package/layout/_partial/sidebar/index_rightbar.ejs +0 -94
- package/layout/_partial/sidebar/logo.ejs +0 -99
- package/layout/_plugins/adaptive_text.ejs +0 -11
- package/layout/_plugins/card_hover.ejs +0 -32
- package/layout/_plugins/copycode.ejs +0 -17
- package/layout/_plugins/fancybox.ejs +0 -53
- package/layout/_plugins/heti.ejs +0 -21
- package/layout/_plugins/index.ejs +0 -50
- package/layout/_plugins/mathjax.ejs +0 -49
- package/layout/_plugins/mermaid.ejs +0 -33
- package/layout/_plugins/preload.ejs +0 -9
- package/layout/_plugins/scrollreveal.ejs +0 -102
- package/layout/_plugins/search/algolia_search.ejs +0 -12
- package/layout/_plugins/search/local_search.ejs +0 -9
- package/layout/_plugins/swiper.ejs +0 -27
- package/layout/_plugins/tianli_gpt.ejs +0 -14
- package/scripts/commands/new-note.js +0 -49
- package/scripts/events/lib/merge_posts.js +0 -48
- package/scripts/events/lib/topic_tree.js +0 -48
- package/scripts/helpers/related_posts.js +0 -51
- package/scripts/helpers/subtitle.js +0 -8
- package/scripts/lib/notebooks.js +0 -181
- package/scripts/lib/subtitle.js +0 -28
- package/scripts/tags/lib/about.js +0 -48
- package/source/css/_components/page-transition.styl +0 -22
- package/source/css/_components/partial/navbar.styl +0 -51
- package/source/css/_components/sidebar/logo.styl +0 -111
- package/source/css/_components/tag-plugins/about.styl +0 -56
- package/source/css/_components/widgets/tree.styl +0 -0
- package/source/css/_plugins/scrollreveal.styl +0 -6
- package/source/css/_plugins/tianli_gpt.styl +0 -213
- package/source/css/plugins/mermaid.styl +0 -137
- package/source/js/icons.js +0 -60
- package/source/js/services/fcircle.js +0 -35
- package/source/js/theme.js +0 -61
package/source/js/main.js
CHANGED
|
@@ -45,6 +45,26 @@ const util = {
|
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
|
|
48
|
+
share: async (button) => {
|
|
49
|
+
if (!button) return;
|
|
50
|
+
const data = {
|
|
51
|
+
title: button.dataset.shareTitle || '',
|
|
52
|
+
text: button.dataset.shareText || button.dataset.shareTitle || '',
|
|
53
|
+
url: button.dataset.shareUrl || ''
|
|
54
|
+
};
|
|
55
|
+
try {
|
|
56
|
+
const supported = typeof navigator.share === 'function'
|
|
57
|
+
&& (typeof navigator.canShare !== 'function' || navigator.canShare(data));
|
|
58
|
+
if (supported) {
|
|
59
|
+
await navigator.share(data);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (error?.name === 'AbortError') return;
|
|
64
|
+
}
|
|
65
|
+
util.copy(button.dataset.copyTarget, button.dataset.copyMessage);
|
|
66
|
+
},
|
|
67
|
+
|
|
48
68
|
toggle: (id) => {
|
|
49
69
|
const el = document.getElementById(id);
|
|
50
70
|
if (el) {
|
|
@@ -95,30 +115,260 @@ const hud = {
|
|
|
95
115
|
|
|
96
116
|
// defines
|
|
97
117
|
|
|
98
|
-
const
|
|
118
|
+
const siteShell = document.querySelector('.site-shell');
|
|
119
|
+
const leftbarStateKey = 'stellar:v2:leftbar-state';
|
|
120
|
+
const leftbarDrawerQuery = '(max-width: 768px)';
|
|
121
|
+
const leftbarHiddenQuery = '(max-width: 768px)';
|
|
122
|
+
const rightbarDrawerQuery = '(max-width: 1180px)';
|
|
123
|
+
let shellDrawerTrigger = null;
|
|
124
|
+
let searchDialogTrigger = null;
|
|
125
|
+
let searchDialogRestoreFocus = true;
|
|
126
|
+
let shellInputModality = 'pointer';
|
|
99
127
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
function regionElement(region) {
|
|
129
|
+
return document.getElementById(region + '-region');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function regionUsesDrawer(region) {
|
|
133
|
+
if (typeof window.matchMedia !== 'function') return false;
|
|
134
|
+
return window.matchMedia(region === 'leftbar' ? leftbarDrawerQuery : rightbarDrawerQuery).matches;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function regionHiddenWhenClosed(region) {
|
|
138
|
+
if (typeof window.matchMedia !== 'function') return false;
|
|
139
|
+
if (region === 'leftbar') return window.matchMedia(leftbarHiddenQuery).matches;
|
|
140
|
+
return regionUsesDrawer(region);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function setRegionInteractive(region, interactive) {
|
|
144
|
+
const element = regionElement(region);
|
|
145
|
+
if (!element) return;
|
|
146
|
+
const hidden = regionHiddenWhenClosed(region);
|
|
147
|
+
element.inert = hidden && !interactive;
|
|
148
|
+
if (hidden && !interactive) {
|
|
149
|
+
element.setAttribute('aria-hidden', 'true');
|
|
150
|
+
} else {
|
|
151
|
+
element.removeAttribute('aria-hidden');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function syncLeftbarControls() {
|
|
156
|
+
const drawer = regionUsesDrawer('leftbar');
|
|
157
|
+
const expanded = drawer
|
|
158
|
+
? siteShell?.dataset.drawer === 'leftbar'
|
|
159
|
+
: document.documentElement.dataset.leftbarState !== 'collapsed';
|
|
160
|
+
document.querySelectorAll('[data-shell-action="toggle-leftbar"]').forEach(function (button) {
|
|
161
|
+
button.setAttribute('aria-expanded', String(expanded));
|
|
162
|
+
button.setAttribute('aria-label', drawer
|
|
163
|
+
? (expanded ? 'Close leftbar' : 'Open leftbar')
|
|
164
|
+
: (expanded ? 'Collapse leftbar' : 'Expand leftbar'));
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function syncDrawerControls() {
|
|
169
|
+
const openRegion = siteShell?.dataset.drawer || '';
|
|
170
|
+
['leftbar', 'rightbar'].forEach(function (region) {
|
|
171
|
+
const open = openRegion === region && regionUsesDrawer(region);
|
|
172
|
+
document.querySelectorAll('[data-shell-action="toggle-' + region + '-drawer"]').forEach(function (button) {
|
|
173
|
+
button.setAttribute('aria-expanded', String(open));
|
|
174
|
+
button.setAttribute('aria-label', (open ? 'Close ' : 'Open ') + region);
|
|
175
|
+
});
|
|
176
|
+
setRegionInteractive(region, open || !regionUsesDrawer(region));
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function focusRegion(region) {
|
|
181
|
+
const element = regionElement(region);
|
|
182
|
+
element?.querySelector('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')?.focus();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function dismissDrawer(options) {
|
|
186
|
+
if (!siteShell) return;
|
|
187
|
+
const restoreFocus = options?.restoreFocus !== false;
|
|
188
|
+
const wasOpen = !!siteShell.dataset.drawer;
|
|
189
|
+
delete siteShell.dataset.drawer;
|
|
190
|
+
syncDrawerControls();
|
|
191
|
+
syncLeftbarControls();
|
|
192
|
+
if (wasOpen && restoreFocus && shellDrawerTrigger?.focus) shellDrawerTrigger.focus();
|
|
193
|
+
if (wasOpen) shellDrawerTrigger = null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function toggleDrawer(region, trigger) {
|
|
197
|
+
if (!siteShell || !regionUsesDrawer(region) || !regionElement(region)) return;
|
|
198
|
+
const open = siteShell.dataset.drawer === region;
|
|
199
|
+
if (open) {
|
|
200
|
+
dismissDrawer();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
shellDrawerTrigger = trigger || document.activeElement;
|
|
204
|
+
siteShell.dataset.drawer = region;
|
|
205
|
+
syncDrawerControls();
|
|
206
|
+
syncLeftbarControls();
|
|
207
|
+
focusRegion(region);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function toggleLeftbarState() {
|
|
211
|
+
const root = document.documentElement;
|
|
212
|
+
const state = root.dataset.leftbarState === 'collapsed' ? 'expanded' : 'collapsed';
|
|
213
|
+
root.dataset.leftbarState = state;
|
|
214
|
+
try { localStorage.setItem(leftbarStateKey, state); } catch (error) {}
|
|
215
|
+
syncLeftbarControls();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function toggleLeftbar(trigger) {
|
|
219
|
+
if (regionUsesDrawer('leftbar')) {
|
|
220
|
+
toggleDrawer('leftbar', trigger);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
toggleLeftbarState();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function searchDialogElement() {
|
|
227
|
+
return document.getElementById('site-search-dialog');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function searchScopeOption(dialog, value) {
|
|
231
|
+
return dialog?.querySelector('[data-search-scope-option="' + value + '"]');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function applySearchScope(dialog, value, refresh = true) {
|
|
235
|
+
const input = dialog?.querySelector('.search-input');
|
|
236
|
+
const group = dialog?.querySelector('.search-dialog__scope');
|
|
237
|
+
if (!input || !group) return;
|
|
238
|
+
const selected = ['all', 'blog', 'current'].includes(value) ? value : 'all';
|
|
239
|
+
const option = searchScopeOption(dialog, selected);
|
|
240
|
+
const radio = option?.querySelector('input[type="radio"]');
|
|
241
|
+
if (!option || option.hidden || !radio) return;
|
|
242
|
+
|
|
243
|
+
if (selected === 'current') {
|
|
244
|
+
input.dataset.domain = group.dataset.currentDomain || '';
|
|
245
|
+
} else if (selected === 'blog') {
|
|
246
|
+
input.dataset.domain = 'blog';
|
|
247
|
+
} else {
|
|
248
|
+
input.dataset.domain = '';
|
|
249
|
+
}
|
|
250
|
+
radio.checked = true;
|
|
251
|
+
if (refresh && input.value.trim().length > 0) {
|
|
252
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function configureSearchScope(dialog, trigger) {
|
|
257
|
+
const group = dialog?.querySelector('.search-dialog__scope');
|
|
258
|
+
if (!group) return false;
|
|
259
|
+
const blogOption = searchScopeOption(dialog, 'blog');
|
|
260
|
+
const currentOption = searchScopeOption(dialog, 'current');
|
|
261
|
+
const currentLabel = currentOption?.querySelector('[data-search-scope-current-label]');
|
|
262
|
+
const currentDomain = trigger?.dataset?.searchDomain || '';
|
|
263
|
+
const hasBlog = trigger?.dataset?.searchDomainBlog === 'true';
|
|
264
|
+
const hasCurrent = currentDomain.length > 0 && currentDomain !== 'blog';
|
|
265
|
+
|
|
266
|
+
blogOption.hidden = !hasBlog;
|
|
267
|
+
currentOption.hidden = !hasCurrent;
|
|
268
|
+
if (currentLabel) currentLabel.textContent = trigger?.dataset?.searchDomainLabel || '';
|
|
269
|
+
group.dataset.currentDomain = currentDomain;
|
|
270
|
+
group.hidden = 1 + Number(hasBlog) + Number(hasCurrent) < 2;
|
|
271
|
+
|
|
272
|
+
const selected = hasCurrent ? 'current' : (hasBlog ? 'blog' : 'all');
|
|
273
|
+
applySearchScope(dialog, selected, false);
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function closeSearch() {
|
|
278
|
+
const dialog = searchDialogElement();
|
|
279
|
+
if (!dialog?.open) return;
|
|
280
|
+
dialog.close();
|
|
281
|
+
document.documentElement.removeAttribute('data-search-open');
|
|
282
|
+
if (searchDialogRestoreFocus && searchDialogTrigger?.focus) searchDialogTrigger.focus();
|
|
283
|
+
else if (searchDialogTrigger?.blur) searchDialogTrigger.blur();
|
|
284
|
+
searchDialogTrigger = null;
|
|
285
|
+
searchDialogRestoreFocus = true;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function openSearch(trigger, restoreFocus = true) {
|
|
289
|
+
const dialog = searchDialogElement();
|
|
290
|
+
const input = dialog?.querySelector('.search-input');
|
|
291
|
+
const wrapper = dialog?.querySelector('.search-wrapper');
|
|
292
|
+
const result = dialog?.querySelector('.search-result');
|
|
293
|
+
if (!dialog || !input) return;
|
|
294
|
+
searchDialogTrigger = trigger || document.activeElement;
|
|
295
|
+
searchDialogRestoreFocus = restoreFocus;
|
|
296
|
+
input.value = '';
|
|
297
|
+
if (!configureSearchScope(dialog, trigger)) {
|
|
298
|
+
input.dataset.algoliaFilterPath = trigger?.dataset?.algoliaFilterPath || '';
|
|
299
|
+
}
|
|
300
|
+
if (wrapper) {
|
|
301
|
+
wrapper.setAttribute('searching', 'false');
|
|
302
|
+
wrapper.classList.remove('noresult');
|
|
121
303
|
}
|
|
304
|
+
result?.replaceChildren();
|
|
305
|
+
if (!dialog.open) dialog.showModal();
|
|
306
|
+
document.documentElement.setAttribute('data-search-open', '');
|
|
307
|
+
input.focus();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function toggleToc(trigger) {
|
|
311
|
+
const widget = document.querySelector('#data-toc');
|
|
312
|
+
if (!widget) return;
|
|
313
|
+
const collapsed = widget.classList.toggle('collapse');
|
|
314
|
+
trigger?.classList.toggle('is-active', collapsed);
|
|
315
|
+
trigger?.setAttribute('aria-pressed', String(collapsed));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const shellActions = {
|
|
319
|
+
'toggle-leftbar-drawer': function (trigger) { toggleDrawer('leftbar', trigger); },
|
|
320
|
+
'toggle-rightbar-drawer': function (trigger) { toggleDrawer('rightbar', trigger); },
|
|
321
|
+
'dismiss-drawer': function () { dismissDrawer(); },
|
|
322
|
+
'toggle-leftbar': function (trigger) { toggleLeftbar(trigger); },
|
|
323
|
+
'open-search': function (trigger) { openSearch(trigger, shellInputModality !== 'pointer'); },
|
|
324
|
+
'close-search': function () { closeSearch(); },
|
|
325
|
+
'toggle-toc': function (trigger) { toggleToc(trigger); }
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
syncLeftbarControls();
|
|
329
|
+
syncDrawerControls();
|
|
330
|
+
document.addEventListener('pointerdown', function () {
|
|
331
|
+
shellInputModality = 'pointer';
|
|
332
|
+
});
|
|
333
|
+
document.addEventListener('click', function (event) {
|
|
334
|
+
const trigger = event.target?.closest?.('[data-shell-action]');
|
|
335
|
+
const action = trigger?.dataset?.shellAction;
|
|
336
|
+
if (!action || typeof shellActions[action] !== 'function') return;
|
|
337
|
+
event.preventDefault();
|
|
338
|
+
shellActions[action](trigger);
|
|
339
|
+
});
|
|
340
|
+
document.addEventListener('keydown', function (event) {
|
|
341
|
+
shellInputModality = 'keyboard';
|
|
342
|
+
if (event.key === 'Escape') {
|
|
343
|
+
if (searchDialogElement()?.open) closeSearch();
|
|
344
|
+
else dismissDrawer();
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
const searchDialog = searchDialogElement();
|
|
348
|
+
searchDialog?.addEventListener('cancel', function (event) {
|
|
349
|
+
event.preventDefault();
|
|
350
|
+
closeSearch();
|
|
351
|
+
});
|
|
352
|
+
searchDialog?.addEventListener('click', function (event) {
|
|
353
|
+
if (event.target === searchDialog) closeSearch();
|
|
354
|
+
});
|
|
355
|
+
searchDialog?.addEventListener('change', function (event) {
|
|
356
|
+
if (event.target?.name !== 'site-search-scope') return;
|
|
357
|
+
applySearchScope(searchDialog, event.target.value);
|
|
358
|
+
});
|
|
359
|
+
if (typeof window.matchMedia === 'function') {
|
|
360
|
+
[leftbarDrawerQuery, leftbarHiddenQuery, rightbarDrawerQuery].filter(function (query, index, queries) {
|
|
361
|
+
return queries.indexOf(query) === index;
|
|
362
|
+
}).map(function (query) {
|
|
363
|
+
return window.matchMedia(query);
|
|
364
|
+
}).forEach(function (media) {
|
|
365
|
+
const handleChange = function () {
|
|
366
|
+
dismissDrawer({ restoreFocus: false });
|
|
367
|
+
syncDrawerControls();
|
|
368
|
+
};
|
|
369
|
+
if (typeof media.addEventListener === 'function') media.addEventListener('change', handleChange);
|
|
370
|
+
else if (typeof media.addListener === 'function') media.addListener(handleChange);
|
|
371
|
+
});
|
|
122
372
|
}
|
|
123
373
|
|
|
124
374
|
// 通用平滑滚动(自定义动画,TOC / 回到顶部 / 参与讨论共用)
|
|
@@ -188,7 +438,7 @@ function rebuildToc(scope) {
|
|
|
188
438
|
const li = document.createElement('li');
|
|
189
439
|
li.className = 'toc-item toc-level-' + level;
|
|
190
440
|
const a = document.createElement('a');
|
|
191
|
-
a.className = 'toc-link';
|
|
441
|
+
a.className = 'toc-link ' + ctx.ui.classes.interactive;
|
|
192
442
|
a.href = '#' + encodeURIComponent(id);
|
|
193
443
|
const span = document.createElement('span');
|
|
194
444
|
span.className = 'toc-text';
|
|
@@ -339,7 +589,7 @@ const init = {
|
|
|
339
589
|
}, 50);
|
|
340
590
|
});
|
|
341
591
|
},
|
|
342
|
-
|
|
592
|
+
tocLinks: () => {
|
|
343
593
|
utils.dom("#data-toc a.toc-link").click(function (e) {
|
|
344
594
|
const href = this.getAttribute("href");
|
|
345
595
|
const id = href && href.indexOf("#") === 0 ? decodeURIComponent(href.slice(1)) : null;
|
|
@@ -353,11 +603,11 @@ const init = {
|
|
|
353
603
|
window.history.pushState(null, "", href);
|
|
354
604
|
}
|
|
355
605
|
}
|
|
356
|
-
|
|
606
|
+
dismissDrawer();
|
|
357
607
|
});
|
|
358
608
|
},
|
|
359
609
|
wikiStart: () => {
|
|
360
|
-
utils.dom('#
|
|
610
|
+
utils.dom('#site-cover .cover-content.wiki .start-wrap a.button.start').click(function (e) {
|
|
361
611
|
const href = this.getAttribute("href");
|
|
362
612
|
const id = href && href.indexOf("#") === 0 ? decodeURIComponent(href.slice(1)) : null;
|
|
363
613
|
const target = id && document.getElementById(id);
|
|
@@ -413,17 +663,9 @@ const init = {
|
|
|
413
663
|
}
|
|
414
664
|
});
|
|
415
665
|
|
|
416
|
-
const galaxyCanvases = document.querySelectorAll('.wiki-cover-background.galaxy canvas');
|
|
417
|
-
const reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
418
|
-
if (reduceMotion || galaxyCanvases.length === 0) return;
|
|
419
|
-
utils.js('/js/plugins/galaxy.js').then(function () {
|
|
420
|
-
if (stellar.galaxy && typeof stellar.galaxy.mountAll === 'function') {
|
|
421
|
-
stellar.galaxy.mountAll(galaxyCanvases);
|
|
422
|
-
}
|
|
423
|
-
}).catch(function () {});
|
|
424
666
|
},
|
|
425
667
|
leftbarScroll: () => {
|
|
426
|
-
const container = document.querySelector('.
|
|
668
|
+
const container = document.querySelector('.site-region--leftbar .site-region__body');
|
|
427
669
|
if (container == null) {
|
|
428
670
|
return;
|
|
429
671
|
}
|
|
@@ -438,8 +680,8 @@ const init = {
|
|
|
438
680
|
if (notebookEl != null) {
|
|
439
681
|
return 'notebook:' + encode(notebookEl.getAttribute('data-notebook'));
|
|
440
682
|
}
|
|
441
|
-
const body = document.
|
|
442
|
-
return 'layout:' + encode((body && body.
|
|
683
|
+
const body = document.body;
|
|
684
|
+
return 'layout:' + encode((body && body.dataset.pageLayout) || 'default');
|
|
443
685
|
}
|
|
444
686
|
window.addEventListener('pagehide', function () {
|
|
445
687
|
try {
|
|
@@ -475,16 +717,16 @@ const init = {
|
|
|
475
717
|
}
|
|
476
718
|
} catch (e) {}
|
|
477
719
|
},
|
|
478
|
-
|
|
479
|
-
//
|
|
480
|
-
//
|
|
481
|
-
// 吸顶判定直接测
|
|
720
|
+
listingNavPin: () => {
|
|
721
|
+
// Listing Nav 在吸顶边界切换 .is-pinned 类,视觉由 CSS 控制。
|
|
722
|
+
// 页面有 Topbar 时,pinned Listing Nav 进入 Topbar 内并复用其表面;无 Topbar 时保持独立容器外观。
|
|
723
|
+
// 吸顶判定直接测 Listing Nav 的实际视口位置,而非用 scrollY 推算:
|
|
482
724
|
// 移动端浏览器顶栏伸缩会改变 scrollY(展开顶栏时 scrollY 减小),
|
|
483
|
-
// 即使
|
|
484
|
-
// 无轮播区页面(如 wiki)的
|
|
725
|
+
// 即使 Listing Nav 仍吸顶也可能跌破阈值,导致玻璃效果误消失。
|
|
726
|
+
// 无轮播区页面(如 wiki)的 Listing Nav 在页面顶部即已吸顶,需额外要求页面实际滚动达到阈值,
|
|
485
727
|
// 否则默认保持卡片样式;回到顶部(滚动小于阈值)恢复卡片。
|
|
486
|
-
const
|
|
487
|
-
if (
|
|
728
|
+
const listingNavs = document.querySelectorAll('.listing-nav');
|
|
729
|
+
if (listingNavs.length === 0) {
|
|
488
730
|
return;
|
|
489
731
|
}
|
|
490
732
|
// 视口顶部允许的偏差(px),吸收亚像素/取整误差
|
|
@@ -495,22 +737,22 @@ const init = {
|
|
|
495
737
|
function update() {
|
|
496
738
|
const scrolled = window.scrollY >= SCROLL_THRESHOLD;
|
|
497
739
|
states.forEach((state) => {
|
|
498
|
-
const top = state.
|
|
499
|
-
state.
|
|
740
|
+
const top = state.listingNav.getBoundingClientRect().top;
|
|
741
|
+
state.surface.classList.toggle('is-pinned', scrolled && top <= state.stickyTop + TOLERANCE);
|
|
500
742
|
});
|
|
501
743
|
}
|
|
502
744
|
function measure() {
|
|
503
745
|
states = [];
|
|
504
|
-
|
|
505
|
-
const
|
|
506
|
-
if (
|
|
746
|
+
listingNavs.forEach((listingNav) => {
|
|
747
|
+
const surface = listingNav.querySelector('.listing-nav__surface');
|
|
748
|
+
if (surface == null) {
|
|
507
749
|
return;
|
|
508
750
|
}
|
|
509
751
|
// getComputedStyle().top 自动兼容桌面 var(--gap-page) 与移动端 8pt
|
|
510
|
-
const stickyTop = parseFloat(getComputedStyle(
|
|
752
|
+
const stickyTop = parseFloat(getComputedStyle(listingNav).top) || 16;
|
|
511
753
|
states.push({
|
|
512
|
-
|
|
513
|
-
|
|
754
|
+
listingNav: listingNav,
|
|
755
|
+
surface: surface,
|
|
514
756
|
stickyTop: stickyTop
|
|
515
757
|
});
|
|
516
758
|
});
|
|
@@ -579,9 +821,9 @@ const init = {
|
|
|
579
821
|
// 真实主站域名优先从 encoded(base64)反解,避免被「批量替换域名」的克隆站把提示指向自己
|
|
580
822
|
const getOriginalHost = () => {
|
|
581
823
|
try {
|
|
582
|
-
return atob(canonical.encoded || '') || canonical.
|
|
824
|
+
return atob(canonical.encoded || '') || canonical.host || '';
|
|
583
825
|
} catch (e) {
|
|
584
|
-
return canonical.
|
|
826
|
+
return canonical.host || '';
|
|
585
827
|
}
|
|
586
828
|
};
|
|
587
829
|
function originStatusCheck() {
|
|
@@ -646,7 +888,7 @@ const init = {
|
|
|
646
888
|
if (isCurrentHostValid) {
|
|
647
889
|
return;
|
|
648
890
|
}
|
|
649
|
-
if (canonical.
|
|
891
|
+
if (canonical.allowedHosts?.includes(currentHost)) {
|
|
650
892
|
showTip(true);
|
|
651
893
|
return;
|
|
652
894
|
}
|
|
@@ -660,7 +902,7 @@ const init = {
|
|
|
660
902
|
if (isCanonicalHostValid && isCurrentHostValid) {
|
|
661
903
|
return;
|
|
662
904
|
}
|
|
663
|
-
showTip(canonical.
|
|
905
|
+
showTip(canonical.allowedHosts?.includes(currentHost));
|
|
664
906
|
}
|
|
665
907
|
|
|
666
908
|
}
|
|
@@ -668,17 +910,18 @@ const init = {
|
|
|
668
910
|
|
|
669
911
|
// Stellar namespace
|
|
670
912
|
window.stellar = window.stellar || {};
|
|
913
|
+
stellar.toast = hud.toast;
|
|
671
914
|
|
|
672
915
|
/**
|
|
673
916
|
* Initialize page components
|
|
674
917
|
*/
|
|
675
918
|
stellar.initPage = function () {
|
|
676
919
|
init.toc();
|
|
677
|
-
init.
|
|
920
|
+
init.tocLinks();
|
|
678
921
|
init.wikiStart();
|
|
679
922
|
init.wikiCover();
|
|
680
923
|
init.leftbarScroll();
|
|
681
|
-
init.
|
|
924
|
+
init.listingNavPin();
|
|
682
925
|
init.relativeDate(document.querySelectorAll('#post-meta time'));
|
|
683
926
|
init.registerTabsTag();
|
|
684
927
|
};
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// contrast 黑白对比(两种变量同色)
|
|
8
8
|
// split 大字(标题/headline)用 contrast,小字(caption/subtitle/面包屑等)用 theme
|
|
9
9
|
// 用户显式覆盖优先:元素已有内联 --text-banner 或内联 color 时跳过。
|
|
10
|
-
// 由
|
|
10
|
+
// 由 runtime feature adapter 在页面存在目标元素时按需加载并挂载。
|
|
11
11
|
|
|
12
12
|
function parseCssUrl(value) {
|
|
13
13
|
if (!value) {
|
|
@@ -114,15 +114,16 @@ function setWikiOverlayColor(el, rgb) {
|
|
|
114
114
|
// Wiki 卡片主题色确定后(包括提取失败时的 CSS 回退)通知索引页。
|
|
115
115
|
// 覆盖层会同时等待原图 load,避免先用默认主题色绘制、再切换为平均色。
|
|
116
116
|
function notifyWikiOverlayReady(el) {
|
|
117
|
-
|
|
117
|
+
var ownerDocument = el && el.ownerDocument;
|
|
118
|
+
if (!el || !el.dispatchEvent || !ownerDocument || !ownerDocument.createEvent) {
|
|
118
119
|
return;
|
|
119
120
|
}
|
|
120
|
-
var event =
|
|
121
|
+
var event = ownerDocument.createEvent('Event');
|
|
121
122
|
event.initEvent('wiki-overlay-ready', true, false);
|
|
122
123
|
el.dispatchEvent(event);
|
|
123
124
|
}
|
|
124
125
|
|
|
125
|
-
function applyToElement(el) {
|
|
126
|
+
function applyToElement(el, isActive) {
|
|
126
127
|
// 用户显式覆盖优先:首次处理时元素已有内联 --text-banner 或内联 color 则跳过
|
|
127
128
|
// (插件自身写入的变量不视为用户覆盖,主题切换重算时需重新应用)
|
|
128
129
|
var isFirst = !appliedElements.has(el);
|
|
@@ -151,6 +152,7 @@ function applyToElement(el) {
|
|
|
151
152
|
} else {
|
|
152
153
|
var backdrop = resolveBackdrop(el);
|
|
153
154
|
stellar.color.getAverageColor(bg.url, { background: backdrop }).then(function (rgb) {
|
|
155
|
+
if (!isActive()) return;
|
|
154
156
|
if (rgb) {
|
|
155
157
|
apply(rgb);
|
|
156
158
|
} else if (styleName === 'split' && el.parentElement && (' ' + el.parentElement.className + ' ').indexOf(' wiki-card-cover ') !== -1) {
|
|
@@ -161,30 +163,45 @@ function applyToElement(el) {
|
|
|
161
163
|
}
|
|
162
164
|
}
|
|
163
165
|
|
|
164
|
-
var adaptiveTextElements = [];
|
|
165
166
|
var appliedElements = new WeakSet();
|
|
166
167
|
|
|
167
|
-
function applyAdaptiveText(elements) {
|
|
168
|
+
function applyAdaptiveText(elements, isActive) {
|
|
168
169
|
if (!window.stellar || !window.stellar.color || !elements || elements.length === 0) {
|
|
169
170
|
return;
|
|
170
171
|
}
|
|
171
|
-
|
|
172
|
+
var active = typeof isActive === 'function' ? isActive : function () { return true; };
|
|
172
173
|
for (var i = 0; i < elements.length; i++) {
|
|
173
|
-
applyToElement(elements[i]);
|
|
174
|
+
applyToElement(elements[i], active);
|
|
174
175
|
}
|
|
175
176
|
}
|
|
176
177
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
178
|
+
function mountAdaptiveText(elements) {
|
|
179
|
+
var active = true;
|
|
180
|
+
var mountedElements = Array.prototype.slice.call(elements || []);
|
|
181
|
+
var ownerDocument = mountedElements[0] && mountedElements[0].ownerDocument;
|
|
182
|
+
var observer = null;
|
|
183
|
+
var isActive = function () { return active; };
|
|
184
|
+
applyAdaptiveText(mountedElements, isActive);
|
|
185
|
+
// 主题明暗切换时重算:透明背景图的合成背景随 data-theme 变化,颜色需重新计算
|
|
186
|
+
if (window.MutationObserver && ownerDocument && ownerDocument.documentElement) {
|
|
187
|
+
observer = new MutationObserver(function () {
|
|
188
|
+
applyAdaptiveText(mountedElements, isActive);
|
|
189
|
+
if (typeof window.refreshPinNavColor === 'function') {
|
|
190
|
+
window.refreshPinNavColor();
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
observer.observe(ownerDocument.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
|
|
194
|
+
}
|
|
195
|
+
return function () {
|
|
196
|
+
active = false;
|
|
197
|
+
mountedElements = [];
|
|
198
|
+
observer?.disconnect();
|
|
199
|
+
observer = null;
|
|
200
|
+
};
|
|
185
201
|
}
|
|
186
202
|
|
|
187
203
|
// 供轮播箭头等场景复用:解析元素背后实际渲染背景色
|
|
188
204
|
window.resolveAdaptiveBackdrop = resolveBackdrop;
|
|
189
205
|
|
|
190
206
|
window.applyAdaptiveText = applyAdaptiveText;
|
|
207
|
+
window.stellarAdaptiveText = { mount: mountAdaptiveText };
|
|
@@ -8,31 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
window.stellar = window.stellar || {};
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
const DEFAULT_MAX_TILT = 3;
|
|
13
|
-
const MAX_TILT_LIMIT = 8;
|
|
11
|
+
const MAX_TILT = 3;
|
|
14
12
|
const mounted = new Map();
|
|
15
13
|
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
16
14
|
const finePointer = window.matchMedia('(hover: hover) and (pointer: fine)');
|
|
17
15
|
let lifecycleBound = false;
|
|
18
16
|
|
|
19
|
-
function normalizeConfig() {
|
|
20
|
-
const raw = typeof ctx !== 'undefined' && ctx.card_hover ? ctx.card_hover : {};
|
|
21
|
-
let maxTilt = Number(raw.maxTilt);
|
|
22
|
-
if (raw.maxTilt === null || raw.maxTilt === '' || !Number.isFinite(maxTilt)) {
|
|
23
|
-
maxTilt = DEFAULT_MAX_TILT;
|
|
24
|
-
}
|
|
25
|
-
maxTilt = Math.max(0, Math.min(MAX_TILT_LIMIT, maxTilt));
|
|
26
|
-
|
|
27
|
-
let spotlightColor = typeof raw.spotlightColor === 'string' && raw.spotlightColor.trim()
|
|
28
|
-
? raw.spotlightColor.trim()
|
|
29
|
-
: DEFAULT_SPOTLIGHT_COLOR;
|
|
30
|
-
if (window.CSS && typeof window.CSS.supports === 'function' && !window.CSS.supports('color', spotlightColor)) {
|
|
31
|
-
spotlightColor = DEFAULT_SPOTLIGHT_COLOR;
|
|
32
|
-
}
|
|
33
|
-
return { maxTilt: maxTilt, spotlightColor: spotlightColor };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
17
|
function canAnimate() {
|
|
37
18
|
return !reduceMotion.matches && finePointer.matches;
|
|
38
19
|
}
|
|
@@ -117,8 +98,6 @@
|
|
|
117
98
|
const hasTilt = element.classList.contains('card-hover--tilt');
|
|
118
99
|
if (!hasSpotlight && !hasTilt) return;
|
|
119
100
|
|
|
120
|
-
const config = normalizeConfig();
|
|
121
|
-
document.documentElement.style.setProperty('--card-hover-spotlight-color', config.spotlightColor);
|
|
122
101
|
let spotlight = null;
|
|
123
102
|
if (hasSpotlight) {
|
|
124
103
|
spotlight = document.createElement('span');
|
|
@@ -131,7 +110,7 @@
|
|
|
131
110
|
element: element,
|
|
132
111
|
spotlight: spotlight,
|
|
133
112
|
hasTilt: hasTilt,
|
|
134
|
-
maxTilt:
|
|
113
|
+
maxTilt: MAX_TILT,
|
|
135
114
|
frame: null,
|
|
136
115
|
pointer: null,
|
|
137
116
|
onPointerEnter: null,
|
|
@@ -243,7 +222,6 @@
|
|
|
243
222
|
document.removeEventListener('stellar:mdrender', handleRenderedMarkdown);
|
|
244
223
|
document.removeEventListener('visibilitychange', handleVisibility);
|
|
245
224
|
window.removeEventListener('pagehide', resetAll);
|
|
246
|
-
document.documentElement.style.removeProperty('--card-hover-spotlight-color');
|
|
247
225
|
}
|
|
248
226
|
|
|
249
227
|
stellar.cardHover = {
|
|
@@ -2,9 +2,13 @@ function createCopyButtons(codeElements) {
|
|
|
2
2
|
codeElements.forEach((codeElement) => {
|
|
3
3
|
if (codeElement.querySelector('.copy-btn')) return;
|
|
4
4
|
// 创建复制按钮
|
|
5
|
-
const codeCopyBtn = document.createElement('
|
|
5
|
+
const codeCopyBtn = document.createElement('button');
|
|
6
|
+
const copyIcon = ctx.icons['copy:copy'] || '';
|
|
6
7
|
codeCopyBtn.className = 'copy-btn';
|
|
7
|
-
codeCopyBtn.
|
|
8
|
+
codeCopyBtn.type = 'button';
|
|
9
|
+
codeCopyBtn.innerHTML = copyIcon;
|
|
10
|
+
codeCopyBtn.setAttribute('aria-label', ctx.copycode.label);
|
|
11
|
+
codeCopyBtn.setAttribute('title', ctx.copycode.label);
|
|
8
12
|
codeElement.appendChild(codeCopyBtn);
|
|
9
13
|
|
|
10
14
|
// 添加点击事件监听
|
|
@@ -13,27 +17,17 @@ function createCopyButtons(codeElements) {
|
|
|
13
17
|
if (navigator.clipboard) {
|
|
14
18
|
try {
|
|
15
19
|
await navigator.clipboard.writeText(codeToCopy);
|
|
16
|
-
|
|
17
|
-
codeCopyBtn.classList.add('success');
|
|
18
|
-
hud.toast(ctx.copycode.toast, 2500);
|
|
20
|
+
hud.toast(ctx.copycode.copied, ctx.copycode.toast_ms);
|
|
19
21
|
} catch (error) {
|
|
20
|
-
|
|
21
|
-
codeCopyBtn.classList.add('warning');
|
|
22
|
+
hud.toast(ctx.copycode.denied, ctx.copycode.toast_ms);
|
|
22
23
|
}
|
|
23
24
|
} else {
|
|
24
|
-
|
|
25
|
-
codeCopyBtn.classList.add('warning');
|
|
25
|
+
hud.toast(ctx.copycode.unsupported, ctx.copycode.toast_ms);
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
// 3秒后恢复默认文本
|
|
29
|
-
setTimeout(() => {
|
|
30
|
-
codeCopyBtn.textContent = ctx.copycode.default_text;
|
|
31
|
-
codeCopyBtn.classList.remove('success', 'warning');
|
|
32
|
-
}, 3000);
|
|
33
27
|
});
|
|
34
28
|
});
|
|
35
29
|
}
|
|
36
30
|
|
|
37
31
|
if (typeof window.codeElements !== 'undefined') {
|
|
38
32
|
createCopyButtons(window.codeElements);
|
|
39
|
-
}
|
|
33
|
+
}
|