89 行
2.5 KiB
TypeScript
89 行
2.5 KiB
TypeScript
import commentWidgetThemeStyle from "../styles/devcm-comment-widget.css?raw";
|
|
|
|
const injectShadowStyle = (root: ShadowRoot | null | undefined, id: string, css: string) => {
|
|
if (!root || root.querySelector(`#${id}`)) {
|
|
return;
|
|
}
|
|
|
|
const style = document.createElement("style");
|
|
style.id = id;
|
|
style.textContent = css;
|
|
root.appendChild(style);
|
|
};
|
|
|
|
const themeCommentRoot = (root: ParentNode | null | undefined) => {
|
|
if (!root) {
|
|
return;
|
|
}
|
|
|
|
root.querySelectorAll<HTMLElement>("*").forEach((element) => {
|
|
if (element.shadowRoot) {
|
|
injectShadowStyle(element.shadowRoot, "devcm-comment-widget-theme", commentWidgetThemeStyle);
|
|
themeCommentRoot(element.shadowRoot);
|
|
}
|
|
});
|
|
};
|
|
|
|
const commentScopeSelector = ".devcm-comments, .devcm-moment-comments";
|
|
|
|
const getCommentScopes = (root: ParentNode) => {
|
|
const scopes = Array.from(root.querySelectorAll<HTMLElement>(commentScopeSelector));
|
|
if (root instanceof HTMLElement && root.matches(commentScopeSelector)) {
|
|
scopes.unshift(root);
|
|
}
|
|
return scopes;
|
|
};
|
|
|
|
const themeCommentWidget = (root: ParentNode) => {
|
|
const commentScopes = getCommentScopes(root);
|
|
if (!commentScopes.length) {
|
|
return;
|
|
}
|
|
|
|
commentScopes.forEach((comments) => {
|
|
themeCommentRoot(comments);
|
|
|
|
comments.querySelectorAll<HTMLElement>("comment-widget").forEach((widget) => {
|
|
injectShadowStyle(widget.shadowRoot, "devcm-comment-widget-theme", commentWidgetThemeStyle);
|
|
|
|
const form = widget.shadowRoot?.querySelector<HTMLElement>("comment-form");
|
|
injectShadowStyle(form?.shadowRoot, "devcm-comment-form-theme", commentWidgetThemeStyle);
|
|
|
|
const baseForm = form?.shadowRoot?.querySelector<HTMLElement>("base-form");
|
|
injectShadowStyle(baseForm?.shadowRoot, "devcm-comment-base-form-theme", commentWidgetThemeStyle);
|
|
});
|
|
});
|
|
};
|
|
|
|
type ThemeCommentState = {
|
|
$el: HTMLElement;
|
|
observer: MutationObserver | null;
|
|
timers: number[];
|
|
init: () => void;
|
|
destroy: () => void;
|
|
refresh: () => void;
|
|
};
|
|
|
|
export const themeComment = (): ThemeCommentState => ({
|
|
$el: null as unknown as HTMLElement,
|
|
observer: null,
|
|
timers: [],
|
|
init() {
|
|
this.refresh();
|
|
this.timers = [120, 500, 1200, 2400].map((delay) => window.setTimeout(() => this.refresh(), delay));
|
|
|
|
this.observer = new MutationObserver(() => this.refresh());
|
|
this.observer.observe(this.$el, {
|
|
childList: true,
|
|
subtree: true,
|
|
});
|
|
},
|
|
destroy() {
|
|
this.observer?.disconnect();
|
|
this.timers.forEach((timer) => window.clearTimeout(timer));
|
|
},
|
|
refresh() {
|
|
themeCommentWidget(this.$el);
|
|
},
|
|
});
|