@waline/client
Version:
client for waline comment system
114 lines (97 loc) • 3.03 kB
text/typescript
import { createApp, h, reactive, watchEffect } from 'vue';
import Waline from './components/WalineComment.vue';
import { commentCount } from './comment';
import { pageviewCount } from './pageview';
import { getRoot } from './utils';
import type { WalineInitOptions } from './typings';
export interface WalineInstance {
/**
* Waline 被挂载到的元素
*
* @description 当通过 `el: null` 初始化,值为 `null`
*
* Element where Waline is mounted
*
* @description when initialized with `el: null`, it will be `null`
*/
el: HTMLElement | null;
/**
* 更新 Waline 实例
*
* @description 只要不设置`path` 选项,更新时它就会被重置为 `windows.location.pathname`
*
* Update Waline instance
*
* @description when not setting `path` option, it will be reset to `window.location.pathname`
*/
update: (newOptions?: Partial<Omit<WalineInitOptions, 'el'>>) => void;
/**
* 取消挂载并摧毁 Waline 实例
*
* Unmount and destroy Waline instance
*/
destroy: () => void;
}
export const init = ({
el = '#waline',
path = window.location.pathname,
comment = false,
pageview = false,
...initProps
}: WalineInitOptions): WalineInstance | null => {
// check el element
const root = el ? getRoot(el) : null;
// check root
if (el && !root) throw new Error(`Option 'el' do not match any domElement!`);
// check serverURL
if (!initProps.serverURL) throw new Error("Option 'serverURL' is missing!");
const props = reactive({ ...initProps });
const state = reactive({ comment, pageview, path });
const updateCommentCount = (): void => {
if (state.comment)
commentCount({
serverURL: props.serverURL,
path: state.path,
selector: typeof state.comment === 'string' ? state.comment : undefined,
});
};
const updatePageviewCount = (): void => {
if (state.pageview)
pageviewCount({
serverURL: props.serverURL,
path: state.path,
selector:
typeof state.pageview === 'string' ? state.pageview : undefined,
});
};
const app = root
? createApp(() => h(Waline, { path: state.path, ...props }))
: null;
if (app) app.mount(root!);
const stopComment = watchEffect(updateCommentCount);
const stopPageview = watchEffect(updatePageviewCount);
return {
el: root,
update: ({
comment,
pageview,
path = window.location.pathname,
...newProps
}: Partial<Omit<WalineInitOptions, 'el'>> = {}): void => {
Object.entries(newProps).forEach(([key, value]) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line
props[key] = value;
});
state.path = path;
if (comment !== undefined) state.comment = comment;
if (pageview !== undefined) state.pageview = pageview;
},
destroy: (): void => {
app?.unmount();
stopComment();
stopPageview();
},
};
};