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
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
function queryAll(root, selector) {
|
|
2
|
+
return Array.from(root.querySelectorAll(selector));
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
async function mountLazyLoading(root, context, config) {
|
|
6
|
+
if (root.nodeType !== 9) {
|
|
7
|
+
throw new TypeError('[stellar runtime] lazy-loading compatibility adapter requires a document root');
|
|
8
|
+
}
|
|
9
|
+
const ownerDocument = root.ownerDocument || root;
|
|
10
|
+
let instance = null;
|
|
11
|
+
const wrapLazyloadImages = container => {
|
|
12
|
+
const target = typeof container === 'string' ? root.querySelector(container) : container;
|
|
13
|
+
if (!target) return;
|
|
14
|
+
queryAll(target, 'img').forEach(image => {
|
|
15
|
+
if (image.classList.contains('lazy')) return;
|
|
16
|
+
const src = image.getAttribute('src');
|
|
17
|
+
if (!src) return;
|
|
18
|
+
const wrapper = ownerDocument.createElement('div');
|
|
19
|
+
wrapper.className = 'lazy-box';
|
|
20
|
+
const lazyImage = image.cloneNode();
|
|
21
|
+
lazyImage.removeAttribute('src');
|
|
22
|
+
lazyImage.setAttribute('data-src', src);
|
|
23
|
+
lazyImage.classList.add('lazy');
|
|
24
|
+
const icon = ownerDocument.createElement('div');
|
|
25
|
+
icon.className = 'lazy-icon';
|
|
26
|
+
wrapper.append(lazyImage, icon);
|
|
27
|
+
image.replaceWith(wrapper);
|
|
28
|
+
});
|
|
29
|
+
instance?.update?.();
|
|
30
|
+
};
|
|
31
|
+
window.wrapLazyloadImages = wrapLazyloadImages;
|
|
32
|
+
const onInitialized = event => {
|
|
33
|
+
instance = event.detail.instance;
|
|
34
|
+
window.lazyLoadInstance = instance;
|
|
35
|
+
};
|
|
36
|
+
const lazyLoadOptions = {
|
|
37
|
+
elements_selector: '.lazy',
|
|
38
|
+
callback_loaded(element) {
|
|
39
|
+
element.classList.add('loaded');
|
|
40
|
+
const wrapper = element.closest('.lazy-box') || element.parentElement;
|
|
41
|
+
wrapper?.querySelector('.lazy-icon')?.remove();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
window.lazyLoadOptions = lazyLoadOptions;
|
|
45
|
+
window.addEventListener('LazyLoad::Initialized', onInitialized);
|
|
46
|
+
const observer = new MutationObserver(mutations => {
|
|
47
|
+
const found = mutations.some(mutation => Array.from(mutation.addedNodes).some(node =>
|
|
48
|
+
node.nodeType === 1 && (node.matches?.('.lazy') || node.querySelector?.('.lazy'))
|
|
49
|
+
));
|
|
50
|
+
if (found) instance?.update?.();
|
|
51
|
+
});
|
|
52
|
+
observer.observe(root.documentElement || root, { childList: true, subtree: true });
|
|
53
|
+
const cleanup = () => {
|
|
54
|
+
observer.disconnect();
|
|
55
|
+
window.removeEventListener('LazyLoad::Initialized', onInitialized);
|
|
56
|
+
if (window.wrapLazyloadImages === wrapLazyloadImages) delete window.wrapLazyloadImages;
|
|
57
|
+
if (window.lazyLoadOptions === lazyLoadOptions) delete window.lazyLoadOptions;
|
|
58
|
+
instance?.destroy?.();
|
|
59
|
+
if (window.lazyLoadInstance === instance) delete window.lazyLoadInstance;
|
|
60
|
+
instance = null;
|
|
61
|
+
};
|
|
62
|
+
try {
|
|
63
|
+
await context.assets.script(config.asset);
|
|
64
|
+
instance?.update?.();
|
|
65
|
+
return cleanup;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
cleanup();
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function mountLightbox(root, context, config) {
|
|
73
|
+
let selector = '[data-fancybox]:not(.error), .with-fancybox .atk-content img:not([atk-emoticon]):not([class*="emo"]), .with-fancybox .tk-content img:not([atk-emoticon]):not([class*="emo"]), .with-fancybox .wl-content img:not([atk-emoticon]):not([class*="emo"])';
|
|
74
|
+
if (config.selector) selector += `, ${config.selector}`;
|
|
75
|
+
await Promise.all([
|
|
76
|
+
context.assets.style(config.assets.localCss),
|
|
77
|
+
context.assets.style(config.assets.css),
|
|
78
|
+
context.assets.script(config.assets.js)
|
|
79
|
+
]);
|
|
80
|
+
const options = {
|
|
81
|
+
hideScrollbar: false,
|
|
82
|
+
Thumbs: { autoStart: false },
|
|
83
|
+
caption: (_instance, slide) => slide.triggerEl.alt || slide.triggerEl.dataset.caption || null
|
|
84
|
+
};
|
|
85
|
+
const isDocumentRoot = root.nodeType === 9;
|
|
86
|
+
if (isDocumentRoot) {
|
|
87
|
+
window.Fancybox.bind(selector, options);
|
|
88
|
+
} else {
|
|
89
|
+
window.Fancybox.bind(root, selector, options);
|
|
90
|
+
}
|
|
91
|
+
return () => {
|
|
92
|
+
if (isDocumentRoot) window.Fancybox?.unbind?.(selector);
|
|
93
|
+
else window.Fancybox?.unbind?.(root, selector);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function mountMathJax(root, context, config) {
|
|
98
|
+
window.MathJax = {
|
|
99
|
+
tex: {
|
|
100
|
+
inlineMath: [['$', '$'], ['\\(', '\\)']],
|
|
101
|
+
processEscapes: true,
|
|
102
|
+
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
|
|
103
|
+
},
|
|
104
|
+
startup: {
|
|
105
|
+
ready() {
|
|
106
|
+
window.MathJax.startup.defaultReady();
|
|
107
|
+
window.MathJax.typesetPromise().then(() => {
|
|
108
|
+
queryAll(root, 'mjx-container').forEach(element => element.parentNode?.classList.add('has-jax'));
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
await context.assets.script(config.asset);
|
|
114
|
+
return () => {};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function mountDiagrams(root, context, config) {
|
|
118
|
+
await context.assets.script(config.assets.js);
|
|
119
|
+
const theme = config.colorScheme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
120
|
+
? 'dark'
|
|
121
|
+
: config.theme;
|
|
122
|
+
window.mermaid.initialize({
|
|
123
|
+
startOnLoad: false,
|
|
124
|
+
theme,
|
|
125
|
+
logLevel: 3,
|
|
126
|
+
flowchart: { useMaxWidth: false, htmlLabels: true, curve: 'linear' },
|
|
127
|
+
gantt: { axisFormat: '%Y/%m/%d' },
|
|
128
|
+
sequence: { actorMargin: 50 }
|
|
129
|
+
});
|
|
130
|
+
await window.mermaid.run({ nodes: queryAll(root, '.mermaid') });
|
|
131
|
+
return () => {};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function mountCodeCopy(root, context, config) {
|
|
135
|
+
const messages = config.messages || {};
|
|
136
|
+
const policy = context.manifest.policy.features;
|
|
137
|
+
context.legacy.ctx.copycode = {
|
|
138
|
+
label: messages.label || '',
|
|
139
|
+
copied: messages.copied || '',
|
|
140
|
+
denied: messages.denied || '',
|
|
141
|
+
unsupported: messages.unsupported || '',
|
|
142
|
+
toast_ms: policy.codeCopyToastMs
|
|
143
|
+
};
|
|
144
|
+
await context.assets.script(config.assets.js);
|
|
145
|
+
const elements = queryAll(root, '.code');
|
|
146
|
+
window.createCopyButtons?.(elements);
|
|
147
|
+
return () => elements.forEach(element => element.querySelector('.copy-btn')?.remove());
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function mountAdaptiveText(root, context, config) {
|
|
151
|
+
await context.assets.script(config.assets.colorJs);
|
|
152
|
+
await context.assets.script(config.assets.js);
|
|
153
|
+
return window.stellarAdaptiveText?.mount?.(queryAll(root, '[data-text-adaptive]')) || (() => {});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function mountHeti(root, context, config) {
|
|
157
|
+
await context.assets.style(config.assets.css);
|
|
158
|
+
await context.assets.script(config.assets.js);
|
|
159
|
+
const heti = new window.Heti('.heti');
|
|
160
|
+
queryAll(root, heti.rootSelector).forEach(element => heti.spacingElement(element));
|
|
161
|
+
return () => {};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function mountSwiper(root, context, config) {
|
|
165
|
+
await Promise.all([
|
|
166
|
+
context.assets.style(config.assets.localCss),
|
|
167
|
+
context.assets.style(config.assets.css),
|
|
168
|
+
context.assets.script(config.assets.js)
|
|
169
|
+
]);
|
|
170
|
+
const element = root.querySelector('#swiper-api');
|
|
171
|
+
const instance = new window.Swiper(element, {
|
|
172
|
+
slidesPerView: 'auto',
|
|
173
|
+
spaceBetween: 8,
|
|
174
|
+
centeredSlides: true,
|
|
175
|
+
effect: element?.getAttribute('effect') || '',
|
|
176
|
+
rewind: true,
|
|
177
|
+
pagination: { el: '.swiper-pagination', clickable: true },
|
|
178
|
+
navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' }
|
|
179
|
+
});
|
|
180
|
+
return () => instance.destroy?.(true, true);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export async function mount(root, context) {
|
|
184
|
+
const config = context.extension.config;
|
|
185
|
+
switch (config.feature) {
|
|
186
|
+
case 'lazy-loading': return mountLazyLoading(root, context, config);
|
|
187
|
+
case 'link-prefetch':
|
|
188
|
+
window.FPConfig = { delay: 0, ignoreKeywords: [], maxRPS: 5, hoverDelay: 25 };
|
|
189
|
+
await context.assets.script(config.asset);
|
|
190
|
+
return () => {};
|
|
191
|
+
case 'lightbox': return mountLightbox(root, context, config);
|
|
192
|
+
case 'mathjax': return mountMathJax(root, context, config);
|
|
193
|
+
case 'diagrams': return mountDiagrams(root, context, config);
|
|
194
|
+
case 'code-copy': return mountCodeCopy(root, context, config);
|
|
195
|
+
case 'adaptive-text': return mountAdaptiveText(root, context, config);
|
|
196
|
+
case 'heti': return mountHeti(root, context, config);
|
|
197
|
+
case 'swiper': return mountSwiper(root, context, config);
|
|
198
|
+
default: throw new TypeError(`unknown built-in feature ${config.feature}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
const EFFECT_SELECTOR = 'canvas[data-hero-effect]';
|
|
2
|
+
const MODULE_QUERY = new URL(import.meta.url).search;
|
|
3
|
+
|
|
4
|
+
function objectValue(value) {
|
|
5
|
+
return value != null && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function readObject(canvas, attribute) {
|
|
9
|
+
const raw = canvas.getAttribute(attribute);
|
|
10
|
+
if (!raw) return {};
|
|
11
|
+
try {
|
|
12
|
+
return objectValue(JSON.parse(raw));
|
|
13
|
+
} catch (error) {
|
|
14
|
+
void error;
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function runtimePolicy(canvas) {
|
|
20
|
+
const runtime = readObject(canvas, 'data-effect-runtime');
|
|
21
|
+
return Object.freeze({
|
|
22
|
+
pauseWhenHidden: runtime.pauseWhenHidden !== false,
|
|
23
|
+
respectReducedMotion: runtime.respectReducedMotion !== false
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function effectCanvases(root) {
|
|
28
|
+
const canvases = [];
|
|
29
|
+
if (root?.matches?.(EFFECT_SELECTOR)) canvases.push(root);
|
|
30
|
+
root?.querySelectorAll?.(EFFECT_SELECTOR).forEach(canvas => canvases.push(canvas));
|
|
31
|
+
return canvases;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function versionedModule(context, module) {
|
|
35
|
+
const resolved = context.assets.resolve(module);
|
|
36
|
+
if (!resolved) throw new TypeError('[stellar hero effect] renderer module is required');
|
|
37
|
+
if (!MODULE_QUERY) return resolved;
|
|
38
|
+
return `${resolved}${resolved.includes('?') ? '&' : '?'}${MODULE_QUERY.slice(1)}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function reducedMotion(windowRef) {
|
|
42
|
+
return windowRef.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function createLifecycle(canvas, renderer, runtime) {
|
|
46
|
+
const background = canvas.parentElement;
|
|
47
|
+
const interactionTarget = canvas.closest('.wiki-hero') || background;
|
|
48
|
+
const documentRef = canvas.ownerDocument;
|
|
49
|
+
const windowRef = documentRef?.defaultView || window;
|
|
50
|
+
if (!background || !interactionTarget || !documentRef) return null;
|
|
51
|
+
|
|
52
|
+
const pointer = { x: 0.5, y: 0.5, active: false };
|
|
53
|
+
let animationFrame = null;
|
|
54
|
+
let inViewport = true;
|
|
55
|
+
let destroyed = false;
|
|
56
|
+
|
|
57
|
+
function shouldRender() {
|
|
58
|
+
return !destroyed && (!runtime.pauseWhenHidden || (inViewport && !documentRef.hidden));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function frame(time) {
|
|
62
|
+
animationFrame = null;
|
|
63
|
+
if (!shouldRender()) return;
|
|
64
|
+
renderer.render(time, pointer);
|
|
65
|
+
animationFrame = windowRef.requestAnimationFrame(frame);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function start() {
|
|
69
|
+
if (shouldRender() && animationFrame === null) {
|
|
70
|
+
animationFrame = windowRef.requestAnimationFrame(frame);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function stop() {
|
|
75
|
+
if (animationFrame === null) return;
|
|
76
|
+
windowRef.cancelAnimationFrame(animationFrame);
|
|
77
|
+
animationFrame = null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function resize() {
|
|
81
|
+
renderer.resize(background.getBoundingClientRect(), windowRef.devicePixelRatio || 1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function onMouseMove(event) {
|
|
85
|
+
const rect = background.getBoundingClientRect();
|
|
86
|
+
if (rect.width <= 0 || rect.height <= 0) return;
|
|
87
|
+
pointer.x = Math.max(0, Math.min(1, (event.clientX - rect.left) / rect.width));
|
|
88
|
+
pointer.y = Math.max(0, Math.min(1, (event.clientY - rect.top) / rect.height));
|
|
89
|
+
pointer.active = true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function onMouseLeave() {
|
|
93
|
+
pointer.active = false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function onVisibilityChange() {
|
|
97
|
+
if (documentRef.hidden) stop();
|
|
98
|
+
else start();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (renderer.pointer === true) {
|
|
102
|
+
interactionTarget.addEventListener('mousemove', onMouseMove);
|
|
103
|
+
interactionTarget.addEventListener('mouseleave', onMouseLeave);
|
|
104
|
+
}
|
|
105
|
+
if (runtime.pauseWhenHidden) documentRef.addEventListener('visibilitychange', onVisibilityChange);
|
|
106
|
+
|
|
107
|
+
let resizeObserver = null;
|
|
108
|
+
if (windowRef.ResizeObserver) {
|
|
109
|
+
resizeObserver = new windowRef.ResizeObserver(resize);
|
|
110
|
+
resizeObserver.observe(background);
|
|
111
|
+
} else {
|
|
112
|
+
windowRef.addEventListener('resize', resize);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let viewportObserver = null;
|
|
116
|
+
if (runtime.pauseWhenHidden && windowRef.IntersectionObserver) {
|
|
117
|
+
viewportObserver = new windowRef.IntersectionObserver(entries => {
|
|
118
|
+
inViewport = entries[0]?.isIntersecting === true;
|
|
119
|
+
if (inViewport) start();
|
|
120
|
+
else stop();
|
|
121
|
+
}, { threshold: 0.01 });
|
|
122
|
+
viewportObserver.observe(background);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
resize();
|
|
126
|
+
start();
|
|
127
|
+
|
|
128
|
+
return function cleanup() {
|
|
129
|
+
if (destroyed) return;
|
|
130
|
+
destroyed = true;
|
|
131
|
+
stop();
|
|
132
|
+
if (renderer.pointer === true) {
|
|
133
|
+
interactionTarget.removeEventListener('mousemove', onMouseMove);
|
|
134
|
+
interactionTarget.removeEventListener('mouseleave', onMouseLeave);
|
|
135
|
+
}
|
|
136
|
+
if (runtime.pauseWhenHidden) documentRef.removeEventListener('visibilitychange', onVisibilityChange);
|
|
137
|
+
windowRef.removeEventListener('resize', resize);
|
|
138
|
+
resizeObserver?.disconnect();
|
|
139
|
+
viewportObserver?.disconnect();
|
|
140
|
+
renderer.destroy();
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function mountCanvas(canvas, context) {
|
|
145
|
+
const type = canvas.getAttribute('data-hero-effect') || '';
|
|
146
|
+
const definition = objectValue(context.extension.config.effects)[type];
|
|
147
|
+
if (!definition || typeof definition.module !== 'string') {
|
|
148
|
+
throw new TypeError(`[stellar hero effect] unregistered effect ${type || '<missing>'}`);
|
|
149
|
+
}
|
|
150
|
+
const runtime = runtimePolicy(canvas);
|
|
151
|
+
const windowRef = canvas.ownerDocument?.defaultView || window;
|
|
152
|
+
if (runtime.respectReducedMotion && reducedMotion(windowRef)) return null;
|
|
153
|
+
const module = await import(versionedModule(context, definition.module));
|
|
154
|
+
if (typeof module.createRenderer !== 'function') {
|
|
155
|
+
throw new TypeError(`[stellar hero effect] ${type} must export createRenderer(canvas, options, defaults)`);
|
|
156
|
+
}
|
|
157
|
+
const renderer = module.createRenderer(canvas, readObject(canvas, 'data-effect-options'), objectValue(definition.defaults));
|
|
158
|
+
if (!renderer) return null;
|
|
159
|
+
if (typeof renderer.resize !== 'function' || typeof renderer.render !== 'function' || typeof renderer.destroy !== 'function') {
|
|
160
|
+
renderer.destroy?.();
|
|
161
|
+
throw new TypeError(`[stellar hero effect] ${type} returned an invalid renderer`);
|
|
162
|
+
}
|
|
163
|
+
return createLifecycle(canvas, renderer, runtime);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export async function mount(root, context) {
|
|
167
|
+
const cleanups = [];
|
|
168
|
+
await Promise.all(effectCanvases(root).map(async canvas => {
|
|
169
|
+
try {
|
|
170
|
+
const cleanup = await mountCanvas(canvas, context);
|
|
171
|
+
if (typeof cleanup === 'function') cleanups.push(cleanup);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
context.reportError(error);
|
|
174
|
+
}
|
|
175
|
+
}));
|
|
176
|
+
return () => {
|
|
177
|
+
for (let index = cleanups.length - 1; index >= 0; index--) cleanups[index]();
|
|
178
|
+
};
|
|
179
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
function queryAll(root, selector) {
|
|
2
|
+
return Array.from(root.querySelectorAll(selector));
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const DISTANCE = '8px';
|
|
6
|
+
const DURATION_MS = 1000;
|
|
7
|
+
const INTERVAL_MS = 100;
|
|
8
|
+
const SCALE = 1;
|
|
9
|
+
|
|
10
|
+
function rootWindow(root) {
|
|
11
|
+
if (root?.defaultView) return root.defaultView;
|
|
12
|
+
if (root?.ownerDocument?.defaultView) return root.ownerDocument.defaultView;
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function prefersReducedMotion(windowRef) {
|
|
17
|
+
if (typeof windowRef?.matchMedia !== 'function') return false;
|
|
18
|
+
try {
|
|
19
|
+
return windowRef.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
void error;
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function mount(root) {
|
|
27
|
+
const elements = queryAll(root, '.slide-up');
|
|
28
|
+
const windowRef = rootWindow(root);
|
|
29
|
+
if (
|
|
30
|
+
elements.length === 0 ||
|
|
31
|
+
typeof windowRef?.IntersectionObserver !== 'function' ||
|
|
32
|
+
prefersReducedMotion(windowRef)
|
|
33
|
+
) return () => {};
|
|
34
|
+
|
|
35
|
+
const animations = new Set();
|
|
36
|
+
const pendingInitialObservation = new WeakSet(elements);
|
|
37
|
+
let observer = null;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
observer = new windowRef.IntersectionObserver(entries => {
|
|
41
|
+
let sequenceIndex = 0;
|
|
42
|
+
entries.forEach(entry => {
|
|
43
|
+
if (pendingInitialObservation.has(entry.target)) {
|
|
44
|
+
pendingInitialObservation.delete(entry.target);
|
|
45
|
+
if (entry.isIntersecting) observer.unobserve(entry.target);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!entry.isIntersecting) return;
|
|
49
|
+
observer.unobserve(entry.target);
|
|
50
|
+
if (typeof entry.target.animate !== 'function') return;
|
|
51
|
+
try {
|
|
52
|
+
const animation = entry.target.animate([
|
|
53
|
+
{ opacity: 0, transform: `translateY(${DISTANCE}) scale(${SCALE})` },
|
|
54
|
+
{ opacity: 1, transform: 'translateY(0) scale(1)' }
|
|
55
|
+
], {
|
|
56
|
+
delay: sequenceIndex * INTERVAL_MS,
|
|
57
|
+
duration: DURATION_MS,
|
|
58
|
+
easing: 'ease-out',
|
|
59
|
+
fill: 'backwards'
|
|
60
|
+
});
|
|
61
|
+
animations.add(animation);
|
|
62
|
+
sequenceIndex += 1;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
void error;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
elements.forEach(element => observer.observe(element));
|
|
69
|
+
} catch (error) {
|
|
70
|
+
void error;
|
|
71
|
+
observer?.disconnect();
|
|
72
|
+
return () => {};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return () => {
|
|
76
|
+
observer.disconnect();
|
|
77
|
+
animations.forEach(animation => animation.cancel());
|
|
78
|
+
animations.clear();
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export async function mount(root, context) {
|
|
2
|
+
const config = context.extension.config;
|
|
3
|
+
const assets = context.assets;
|
|
4
|
+
if (config.provider === 'algolia') {
|
|
5
|
+
window.searchConfig = Object.assign({}, config.options, {
|
|
6
|
+
js: config.assets.client,
|
|
7
|
+
hitsPerPage: 100
|
|
8
|
+
});
|
|
9
|
+
await assets.script(config.assets.client);
|
|
10
|
+
await assets.script(config.assets.provider);
|
|
11
|
+
} else if (config.provider === 'local') {
|
|
12
|
+
await assets.script(config.assets.provider);
|
|
13
|
+
}
|
|
14
|
+
await assets.script(config.assets.shortcut);
|
|
15
|
+
const providerCleanup = config.provider === 'algolia'
|
|
16
|
+
? window.stellarAlgoliaSearch?.mount?.(root)
|
|
17
|
+
: window.stellarLocalSearch?.mount?.(root);
|
|
18
|
+
const shortcutCleanup = window.stellarSearchShortcut?.mount?.(root);
|
|
19
|
+
return () => {
|
|
20
|
+
shortcutCleanup?.();
|
|
21
|
+
providerCleanup?.();
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -1,77 +1,74 @@
|
|
|
1
|
-
|
|
1
|
+
export async function mount(root, context) {
|
|
2
|
+
if (root.nodeType !== 9) {
|
|
3
|
+
throw new TypeError('[stellar runtime] legacy data-service adapter requires a document root');
|
|
4
|
+
}
|
|
5
|
+
const assets = context.assets;
|
|
6
|
+
const config = context.extension.config;
|
|
7
|
+
const services = Object.assign({}, config.services, {
|
|
8
|
+
siteinfo: Object.assign({}, config.services.siteinfo, { api: config.siteInfoEndpoint })
|
|
9
|
+
});
|
|
10
|
+
const deps = { marked: config.marked };
|
|
11
|
+
const loads = [];
|
|
12
|
+
const voiceCleanups = [];
|
|
2
13
|
// 用于存储需要清理的资源
|
|
3
|
-
let
|
|
14
|
+
let intervals = [];
|
|
15
|
+
let timeouts = [];
|
|
4
16
|
|
|
5
|
-
for (let id of Object.keys(
|
|
6
|
-
const js =
|
|
17
|
+
for (let id of Object.keys(services)) {
|
|
18
|
+
const js = services[id].js;
|
|
7
19
|
if (id == 'siteinfo') {
|
|
8
|
-
const cardlinks =
|
|
9
|
-
const siteCards =
|
|
20
|
+
const cardlinks = root.querySelectorAll('a.link-card[cardlink]');
|
|
21
|
+
const siteCards = root.querySelectorAll('.ds-sites, .site-card .card-link[data-siteinfo-api]');
|
|
10
22
|
if (cardlinks?.length > 0 || siteCards?.length > 0) {
|
|
11
|
-
|
|
23
|
+
loads.push(assets.script(js).then(function () {
|
|
12
24
|
if (cardlinks?.length > 0) {
|
|
13
25
|
setCardLink(cardlinks);
|
|
14
26
|
}
|
|
15
|
-
});
|
|
27
|
+
}));
|
|
16
28
|
}
|
|
17
29
|
} else if (id == 'ghinfo') {
|
|
18
|
-
const els =
|
|
30
|
+
const els = root.querySelectorAll('.ds-ghinfo');
|
|
19
31
|
if (els.length > 0) {
|
|
20
|
-
|
|
32
|
+
loads.push(assets.script(js));
|
|
21
33
|
}
|
|
22
34
|
} else if (id == 'voice') {
|
|
23
|
-
const voiceAudios =
|
|
35
|
+
const voiceAudios = root.querySelectorAll('.voice>audio');
|
|
24
36
|
if (voiceAudios?.length > 0) {
|
|
25
|
-
|
|
26
|
-
createVoiceDom(voiceAudios);
|
|
27
|
-
|
|
37
|
+
loads.push(assets.script(js).then(function () {
|
|
38
|
+
const voiceCleanup = createVoiceDom(voiceAudios);
|
|
39
|
+
if (typeof voiceCleanup === 'function') voiceCleanups.push(voiceCleanup);
|
|
40
|
+
}));
|
|
28
41
|
}
|
|
29
42
|
} else if (id == 'video') {
|
|
30
|
-
const videos =
|
|
43
|
+
const videos = root.querySelectorAll('.video>video');
|
|
31
44
|
if (videos?.length > 0) {
|
|
32
|
-
|
|
45
|
+
loads.push(assets.script(js).then(function () {
|
|
33
46
|
videoEvents(videos);
|
|
34
|
-
});
|
|
47
|
+
}));
|
|
35
48
|
}
|
|
36
49
|
} else if (id == 'download-file') {
|
|
37
|
-
const files =
|
|
50
|
+
const files = root.querySelectorAll('.chat-file');
|
|
38
51
|
if (files?.length > 0) {
|
|
39
|
-
|
|
52
|
+
loads.push(assets.script(js).then(function () {
|
|
40
53
|
downloadFileEvent(files);
|
|
41
|
-
});
|
|
54
|
+
}));
|
|
42
55
|
}
|
|
43
56
|
} else {
|
|
44
|
-
const els =
|
|
57
|
+
const els = root.getElementsByClassName(`ds-${id}`);
|
|
45
58
|
if (els?.length > 0) {
|
|
46
59
|
if (id == 'timeline' || id == 'memos' || id == 'marked' || id == 'mdrender') {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
60
|
+
loads.push(assets.script(deps.marked).then(function () {
|
|
61
|
+
return assets.script(js);
|
|
62
|
+
}));
|
|
50
63
|
} else {
|
|
51
|
-
|
|
64
|
+
loads.push(assets.script(js));
|
|
52
65
|
}
|
|
53
66
|
}
|
|
54
67
|
}
|
|
55
68
|
}
|
|
56
69
|
|
|
57
|
-
// search
|
|
58
|
-
if (ctx.search && typeof searchFunc === 'function') {
|
|
59
|
-
const searchCfg = ctx.search.local_search;
|
|
60
|
-
const lazyLoad = searchCfg ? searchCfg.lazy_load !== false : true;
|
|
61
|
-
// 懒加载模式下由 local-search.js 的聚焦事件负责初始化,此处跳过
|
|
62
|
-
if (!lazyLoad) {
|
|
63
|
-
const inputArea = document.querySelector("input#search-input");
|
|
64
|
-
if (inputArea && !inputArea._searchInitialized) {
|
|
65
|
-
const path = ctx.search.path.startsWith('/') ? ctx.root + ctx.search.path.substring(1) : ctx.root + ctx.search.path;
|
|
66
|
-
const filter = inputArea.getAttribute('data-filter') || '';
|
|
67
|
-
searchFunc(path, filter, 'search-wrapper', 'search-input', 'search-result');
|
|
68
|
-
// searchFunc 内部管理 _searchInitialized(pending → true),此处不再覆盖
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
70
|
// chat iphone time
|
|
74
|
-
let phoneTimes =
|
|
71
|
+
let phoneTimes = root.querySelectorAll('.chat .status-bar .time');
|
|
75
72
|
let firstAdjustInterval = null;
|
|
76
73
|
let mainInterval = null;
|
|
77
74
|
|
|
@@ -80,7 +77,7 @@ const initServices = () => {
|
|
|
80
77
|
const date = new Date();
|
|
81
78
|
const sec = date.getSeconds();
|
|
82
79
|
firstAdjustInterval = setInterval(firstAdjustTime, 1000 * (60 - sec));
|
|
83
|
-
|
|
80
|
+
intervals.push(firstAdjustInterval);
|
|
84
81
|
|
|
85
82
|
function firstAdjustTime() {
|
|
86
83
|
NowTime();
|
|
@@ -89,7 +86,7 @@ const initServices = () => {
|
|
|
89
86
|
firstAdjustInterval = null;
|
|
90
87
|
}
|
|
91
88
|
mainInterval = setInterval(NowTime, 1000 * 60);
|
|
92
|
-
|
|
89
|
+
intervals.push(mainInterval);
|
|
93
90
|
}
|
|
94
91
|
|
|
95
92
|
function NowTime() {
|
|
@@ -115,19 +112,22 @@ const initServices = () => {
|
|
|
115
112
|
const chat_quote_obverser = new IntersectionObserver((entries, observer) => {
|
|
116
113
|
entries.filter((entry) => { return entry.isIntersecting }).sort((a, b) => a.intersectionRect.y !== b.intersectionRect.y ? a.intersectionRect.y - b.intersectionRect.y : a.intersectionRect.x - b.intersectionRect.x).forEach((entry, index) => {
|
|
117
114
|
observer.unobserve(entry.target);
|
|
118
|
-
setTimeout(() => {
|
|
115
|
+
const blinkStart = setTimeout(() => {
|
|
119
116
|
entry.target.classList.add('quote-blink');
|
|
120
|
-
setTimeout(() => {
|
|
117
|
+
const blinkEnd = setTimeout(() => {
|
|
121
118
|
entry.target.classList.remove('quote-blink');
|
|
122
119
|
}, 1000);
|
|
120
|
+
timeouts.push(blinkEnd);
|
|
123
121
|
}, Math.max(100, 16) * (index + 1));
|
|
122
|
+
timeouts.push(blinkStart);
|
|
124
123
|
});
|
|
125
124
|
});
|
|
126
125
|
|
|
127
|
-
var chatQuotes =
|
|
126
|
+
var chatQuotes = root.querySelectorAll(".chat .talk .quote");
|
|
128
127
|
chatQuotes.forEach((quote) => {
|
|
129
128
|
const handler = function () {
|
|
130
|
-
var
|
|
129
|
+
var candidate = root.getElementById("quote-" + quote.getAttribute("quotedCellTag"));
|
|
130
|
+
var chatCellDom = candidate && root.documentElement.contains(candidate) ? candidate : null;
|
|
131
131
|
if (chatCellDom) {
|
|
132
132
|
var chatDiv = chatCellDom.parentElement;
|
|
133
133
|
var mid = chatDiv.clientHeight / 2;
|
|
@@ -151,12 +151,16 @@ const initServices = () => {
|
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
// 返回清理函数,用于清理定时器和观察器
|
|
154
|
-
|
|
154
|
+
const cleanup = () => {
|
|
155
155
|
// 清理所有定时器(包括可能未完成的 firstAdjustInterval)
|
|
156
|
-
|
|
156
|
+
intervals.forEach(timer => {
|
|
157
157
|
if (timer) clearInterval(timer);
|
|
158
158
|
});
|
|
159
|
-
|
|
159
|
+
intervals = [];
|
|
160
|
+
timeouts.forEach(timer => {
|
|
161
|
+
if (timer) clearTimeout(timer);
|
|
162
|
+
});
|
|
163
|
+
timeouts = [];
|
|
160
164
|
if (firstAdjustInterval) {
|
|
161
165
|
clearInterval(firstAdjustInterval);
|
|
162
166
|
firstAdjustInterval = null;
|
|
@@ -176,7 +180,16 @@ const initServices = () => {
|
|
|
176
180
|
quote.removeEventListener('click', handler);
|
|
177
181
|
});
|
|
178
182
|
quoteClickHandlers.clear();
|
|
183
|
+
for (let index = voiceCleanups.length - 1; index >= 0; index -= 1) {
|
|
184
|
+
voiceCleanups[index]();
|
|
185
|
+
}
|
|
186
|
+
voiceCleanups.length = 0;
|
|
179
187
|
};
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
188
|
+
try {
|
|
189
|
+
await Promise.all(loads);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
cleanup();
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
return cleanup;
|
|
195
|
+
}
|