kt-blog-web/src/factories/blogDomFactory.ts

192 lines
6.3 KiB
TypeScript

import { shallowRef, type ComponentPublicInstance, type Ref } from 'vue';
export const BLOG_DOM_IDS = {
banner: 'banner',
bannerContainer: 'banner_container',
blogSettingsPopup: 'blog_settings_popup',
commentEmotionButton: 'comment_emotion_btn',
commentPostUseMarkdown: 'comment_post_use_markdown',
comments: 'comments',
content: 'content',
floatBackToTop: 'fabtn_back_to_top',
floatReadingProgress: 'fabtn_reading_progress',
floatSettingsToggle: 'fabtn_toggle_blog_settings_popup',
floatToggleSides: 'fabtn_toggle_sides',
footer: 'footer',
headerNavbar: 'navbar-main',
leftbar: 'leftbar',
leftbarCatalog: 'leftbar_catalog',
leftbarCatalogTab: 'leftbar_tab_catalog',
leftbarCatalogTabButton: 'leftbar_tab_catalog_btn',
leftbarOverviewAuthorImage: 'leftbar_overview_author_image',
leftbarOverviewAuthorName: 'leftbar_overview_author_name',
leftbarOverviewTab: 'leftbar_tab_overview',
leftbarOverviewTabButton: 'leftbar_tab_overview_btn',
leftbarPart1: 'leftbar_part1',
leftbarPart1Menu: 'leftbar_part1_menu',
leftbarPart2: 'leftbar_part2',
leftbarPart2Inner: 'leftbar_part2_inner',
leftbarSearchContainer: 'leftbar_search_container',
leftbarSearchInput: 'leftbar_search_input',
live2dCanvas: 'live2d',
live2dChatText: 'live2dChatText',
live2dSend: 'live2dSend',
live2dSendClose: 'live2dSendClose',
live2dTextureButton: 'live2d-texture-button',
main: 'main',
openSidebar: 'open_sidebar',
postArticleTitle: 'post_article_title',
postComment: 'post_comment',
postCommentCaptcha: 'post_comment_captcha',
postCommentContent: 'post_comment_content',
postCommentEmail: 'post_comment_email',
postCommentName: 'post_comment_name',
postCommentSend: 'post_comment_send',
postContent: 'post_content',
primary: 'primary',
rightbar: 'rightbar',
shareContainer: 'share_container',
shareCopyLink: 'share_copy_link',
sharePanel: 'share',
shareShow: 'share_show',
sidebarMask: 'sidebar_mask',
settingsFontSansSerif: 'blog_setting_font_sans_serif',
settingsFontSerif: 'blog_setting_font_serif',
settingsShadowBig: 'blog_setting_shadow_big',
settingsShadowSmall: 'blog_setting_shadow_small',
themeStyle: 'kt-blog-theme-style',
} as const;
export const BLOG_META_NAMES = {
themeColor: 'theme-color',
themeColorRgb: 'theme-color-rgb',
} as const;
export type BlogDomIdKey = keyof typeof BLOG_DOM_IDS;
/**
* @param key Semantic key for a stable Argon-compatible DOM id.
* @returns Concrete DOM id string used by markup, source tests, and Argon compatibility hooks.
*/
export function blogDomId(key: BlogDomIdKey) {
return BLOG_DOM_IDS[key];
}
/**
* @param key Semantic key for a stable Argon-compatible DOM id.
* @returns CSS id selector for document queries that cannot yet be replaced by a Vue ref.
*/
export function blogDomSelector(key: BlogDomIdKey) {
return blogDomSelectorFromId(blogDomId(key));
}
/**
* @param id Existing DOM id from WordPress, upstream plugins, or generated Argon content.
* @returns CSS id selector for legacy ids that are externally defined but still queried by app code.
*/
export function blogDomSelectorFromId(id: string) {
return `#${id}`;
}
/**
* @param key Semantic key for a stable Argon-compatible DOM id.
* @returns Hash href pointing at the matching local DOM id.
*/
export function blogDomAnchor(key: BlogDomIdKey) {
return blogDomAnchorFromId(blogDomId(key));
}
/**
* @param id Existing DOM id from WordPress or generated Argon catalog content.
* @returns Hash href without resolving it through the browser URL.
*/
export function blogDomAnchorFromId(id: string) {
return `#${id}`;
}
/**
* @param articleId Local article id mirrored as Argon's `post-{id}` card anchor.
* @returns Stable article card DOM id.
*/
export function blogPostCardId(articleId: number | string) {
return `post-${articleId}`;
}
/**
* @param index One-based paragraph index in fallback article content.
* @returns Stable fallback paragraph DOM id.
*/
export function blogPostParagraphId(index: number) {
return `post_paragraph_${index}`;
}
/**
* @param index One-based heading index produced for WordPress content without preserved heading ids.
* @returns Stable heading id matching Argon's captured `header-id-N` convention.
*/
export function blogGeneratedHeadingId(index: number) {
return `header-id-${index}`;
}
/**
* @param filterMode Blog filter preference value rendered in the settings panel.
* @returns Stable settings filter button id.
*/
export function blogSettingsFilterId(filterMode: string) {
return `blog_setting_filter_${filterMode}`;
}
/**
* @param postType WordPress search result type rendered in the filter checkbox row.
* @returns Stable search filter checkbox id.
*/
export function blogSearchFilterId(postType: string) {
return `search_filter_${postType}`;
}
/**
* @param name Meta tag name controlled by the Blog theme runtime.
* @returns CSS selector for the matching meta tag.
*/
export function blogMetaSelector(name: string) {
return `meta[name="${name}"]`;
}
/**
* @param id Concrete DOM id, often from generated WordPress heading anchors.
* @returns Matching HTMLElement when it exists in the current document.
*/
export function getBlogElementById<T extends HTMLElement = HTMLElement>(id: string) {
return document.getElementById(id) as T | null;
}
/**
* @returns Shallow Vue ref for DOM nodes whose identity, not deep fields, drives layout side effects.
*/
export function createBlogElementRef<T extends HTMLElement = HTMLElement>() {
return shallowRef<T | null>(null);
}
/**
* @returns Shallow Vue ref for focusable component instances such as antdv-next inputs.
*/
export function createBlogFocusableRef<T = unknown>() {
return shallowRef<T | null>(null);
}
/**
* @param target Vue ref callback payload from native elements or component instances.
* @returns Native HTMLElement only when the callback payload is a real DOM element.
*/
export function toBlogHTMLElement(target: Element | ComponentPublicInstance | null) {
return target instanceof HTMLElement ? target : null;
}
/**
* @param targetRef Layout-owned HTMLElement ref that cross-component effects read from.
* @param target Vue ref callback payload emitted by TSX render functions.
*/
export function assignBlogElementRef(targetRef: Ref<HTMLElement | null>, target: Element | ComponentPublicInstance | null) {
targetRef.value = toBlogHTMLElement(target);
}