@waline/client 3.0.0-alpha.5 → 3.0.0-alpha.7

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.
@@ -0,0 +1,48 @@
1
+ declare const version: string;
2
+
3
+ type WalineAbort = (reason?: any) => void;
4
+
5
+ interface WalinePageviewCountOptions {
6
+ /**
7
+ * Waline 服务端地址
8
+ *
9
+ * Waline server url
10
+ */
11
+ serverURL: string;
12
+ /**
13
+ * 浏览量 CSS 选择器
14
+ *
15
+ * Pageview CSS selector
16
+ *
17
+ * @default '.waline-pageview-count'
18
+ */
19
+ selector?: string;
20
+ /**
21
+ * 需要更新和获取的路径
22
+ *
23
+ * Path to be fetched and updated
24
+ *
25
+ * @default window.location.pathname
26
+ */
27
+ path?: string;
28
+ /**
29
+ * 是否在查询时更新 path 的浏览量
30
+ *
31
+ * Whether update pageviews when fetching path result
32
+ *
33
+ * @default true
34
+ */
35
+ update?: boolean;
36
+ /**
37
+ * 错误提示消息所使用的语言
38
+ *
39
+ * Language of error message
40
+ *
41
+ * @default navigator.language
42
+ */
43
+ lang?: string;
44
+ }
45
+
46
+ declare const pageviewCount: ({ serverURL, path, selector, update, lang, }: WalinePageviewCountOptions) => WalineAbort;
47
+
48
+ export { type WalineAbort, type WalinePageviewCountOptions, pageviewCount, version };
@@ -0,0 +1,2 @@
1
+ const u="3.0.0-alpha.7",v={"Content-Type":"application/json"},g=e=>`${e.replace(/\/?$/,"/")}api/`,$=(e,t="")=>{if(typeof e=="object"&&e.errno)throw new TypeError(`${t} failed with ${e.errno}: ${e.errmsg}`);return e},f=({serverURL:e,lang:t,paths:r,type:a,signal:n})=>fetch(`${g(e)}article?path=${encodeURIComponent(r.join(","))}&type=${encodeURIComponent(a.join(","))}&lang=${t}`,{signal:n}).then(o=>o.json()),R=({serverURL:e,lang:t,path:r,type:a,action:n})=>fetch(`${g(e)}article?lang=${t}`,{method:"POST",headers:v,body:JSON.stringify({path:r,type:a,action:n})}).then(o=>o.json()).then(o=>$(o,"Update counter").data),U=({serverURL:e,lang:t,paths:r,signal:a})=>f({serverURL:e,lang:t,paths:r,type:["time"],signal:a}).then(n=>Array.isArray(n)?n:[n]),w=e=>R({...e,type:"time",action:"inc"}),L=(e="")=>e.replace(/\/$/u,""),A=e=>/^(https?:)?\/\//.test(e),y=e=>{const t=L(e);return A(t)?t:`https://${t}`},b=e=>{e.name!=="AbortError"&&console.error(e.message)},d=e=>e.dataset.path||null,m=(e,t)=>{t.forEach((r,a)=>{r.innerText=e[a].toString()})},j=({serverURL:e,path:t=window.location.pathname,selector:r=".waline-pageview-count",update:a=!0,lang:n=navigator.language})=>{const o=new AbortController,i=Array.from(document.querySelectorAll(r)),c=l=>{const s=d(l);return s!==null&&t!==s},h=l=>U({serverURL:y(e),paths:l.map(s=>d(s)||t),lang:n,signal:o.signal}).then(s=>m(s,l)).catch(b);if(a){const l=i.filter(p=>!c(p)),s=i.filter(c);w({serverURL:y(e),path:t,lang:n}).then(([p])=>m(new Array(l.length).fill(p),l)),s.length&&h(s)}else h(i);return o.abort.bind(o)};export{j as pageviewCount,u as version};
2
+ //# sourceMappingURL=pageview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageview.js","sources":["../src/version.ts","../../api/dist/api.js","../src/utils/path.ts","../src/utils/config.ts","../src/utils/error.ts","../src/utils/query.ts","../src/pageview.ts"],"sourcesContent":["declare const VERSION: string;\n\nexport const version = VERSION;\n","const m={\"Content-Type\":\"application/json\"},s=t=>`${t.replace(/\\/?$/,\"/\")}api/`,h=(t,n=\"\")=>{if(typeof t==\"object\"&&t.errno)throw new TypeError(`${n} failed with ${t.errno}: ${t.errmsg}`);return t},p=({serverURL:t,lang:n,paths:o,type:a,signal:e})=>fetch(`${s(t)}article?path=${encodeURIComponent(o.join(\",\"))}&type=${encodeURIComponent(a.join(\",\"))}&lang=${n}`,{signal:e}).then(r=>r.json()),d=({serverURL:t,lang:n,path:o,type:a,action:e})=>fetch(`${s(t)}article?lang=${n}`,{method:\"POST\",headers:m,body:JSON.stringify({path:o,type:a,action:e})}).then(r=>r.json()).then(r=>h(r,\"Update counter\").data),$=({serverURL:t,lang:n,path:o,page:a,pageSize:e,sortBy:r,signal:c,token:i})=>{const l={};return i&&(l.Authorization=`Bearer ${i}`),fetch(`${s(t)}comment?path=${encodeURIComponent(o)}&pageSize=${e}&page=${a}&lang=${n}&sortBy=${r}`,{signal:c,headers:l}).then(g=>g.json()).then(g=>h(g,\"Get comment data\").data)},u=({serverURL:t,lang:n,token:o,comment:a})=>{const e={\"Content-Type\":\"application/json\"};return o&&(e.Authorization=`Bearer ${o}`),fetch(`${s(t)}comment?lang=${n}`,{method:\"POST\",headers:e,body:JSON.stringify(a)}).then(r=>r.json())},y=({serverURL:t,lang:n,token:o,objectId:a})=>fetch(`${s(t)}comment/${a}?lang=${n}`,{method:\"DELETE\",headers:{Authorization:`Bearer ${o}`}}).then(e=>e.json()).then(e=>h(e,\"Delete comment\")),U=({serverURL:t,lang:n,token:o,objectId:a,comment:e})=>fetch(`${s(t)}comment/${a}?lang=${n}`,{method:\"PUT\",headers:{...m,Authorization:`Bearer ${o}`},body:JSON.stringify(e)}).then(r=>r.json()).then(r=>h(r,\"Update comment\")),f=({serverURL:t,lang:n,paths:o,signal:a})=>fetch(`${s(t)}comment?type=count&url=${encodeURIComponent(o.join(\",\"))}&lang=${n}`,{signal:a}).then(e=>e.json()).then(e=>h(e,\"Get comment count\").data),R=({lang:t,serverURL:n})=>{const o=(window.innerWidth-450)/2,a=(window.innerHeight-450)/2,e=window.open(`${n.replace(/\\/$/,\"\")}/ui/login?lng=${encodeURIComponent(t)}`,\"_blank\",`width=450,height=450,left=${o},top=${a},scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no`);return e?.postMessage({type:\"TOKEN\",data:null},\"*\"),new Promise(r=>{const c=({data:i})=>{!i||typeof i!=\"object\"||i.type!==\"userInfo\"||i.data.token&&(e?.close(),window.removeEventListener(\"message\",c),r(i.data))};window.addEventListener(\"message\",c)})},j=({serverURL:t,lang:n,paths:o,signal:a})=>p({serverURL:t,lang:n,paths:o,type:[\"time\"],signal:a}).then(e=>Array.isArray(e)?e:[e]),v=t=>d({...t,type:\"time\",action:\"inc\"}),w=({serverURL:t,lang:n,count:o,signal:a,token:e})=>{const r={};return e&&(r.Authorization=`Bearer ${e}`),fetch(`${s(t)}comment?type=recent&count=${o}&lang=${n}`,{signal:a,headers:r}).then(c=>c.json())},C=({serverURL:t,signal:n,pageSize:o,lang:a})=>fetch(`${s(t)}user?pageSize=${o}&lang=${a}`,{signal:n}).then(e=>e.json()).then(e=>h(e,\"user list\")).then(e=>e.data);export{u as addComment,y as deleteComment,f as fetchCommentCount,p as getArticleCounter,$ as getComment,j as getPageview,w as getRecentComment,C as getUserList,R as login,d as updateArticleCounter,U as updateComment,v as updatePageview};\n//# sourceMappingURL=api.js.map\n","export const decodePath = (path: string): string => {\n try {\n path = decodeURI(path);\n } catch (err) {\n // ignore error\n }\n\n return path;\n};\n\nexport const removeEndingSplash = (content = ''): string =>\n content.replace(/\\/$/u, '');\n\nexport const isLinkHttp = (link: string): boolean =>\n /^(https?:)?\\/\\//.test(link);\n","import { decodePath, isLinkHttp, removeEndingSplash } from './path.js';\nimport {\n DEFAULT_EMOJI,\n DEFAULT_LANG,\n DEFAULT_LOCALES,\n DEFAULT_REACTION,\n defaultUploadImage,\n defaultHighlighter,\n defaultTeXRenderer,\n getDefaultSearchOptions,\n getMeta,\n} from '../config/index.js';\nimport {\n type WalineEmojiInfo,\n type WalineEmojiMaps,\n type WalineLocale,\n type WalineProps,\n} from '../typings/index.js';\n\nexport interface WalineEmojiConfig {\n tabs: Pick<WalineEmojiInfo, 'name' | 'icon' | 'items'>[];\n map: WalineEmojiMaps;\n}\n\nexport interface WalineConfig\n extends Required<\n Omit<\n WalineProps,\n | 'emoji'\n | 'imageUploader'\n | 'highlighter'\n | 'texRenderer'\n | 'wordLimit'\n | 'reaction'\n | 'search'\n >\n > {\n locale: WalineLocale;\n wordLimit: [number, number] | false;\n reaction: string[];\n emoji: Exclude<WalineProps['emoji'], boolean | undefined>;\n highlighter: Exclude<WalineProps['highlighter'], true | undefined>;\n imageUploader: Exclude<WalineProps['imageUploader'], true | undefined>;\n texRenderer: Exclude<WalineProps['texRenderer'], true | undefined>;\n search: Exclude<WalineProps['search'], true | undefined>;\n}\n\nexport const getServerURL = (serverURL: string): string => {\n const result = removeEndingSplash(serverURL);\n\n return isLinkHttp(result) ? result : `https://${result}`;\n};\n\nconst getWordLimit = (\n wordLimit: WalineProps['wordLimit'],\n): [number, number] | false =>\n Array.isArray(wordLimit) ? wordLimit : wordLimit ? [0, wordLimit] : false;\n\nconst fallback = <T = unknown>(\n value: T | boolean | undefined,\n fallback: T,\n): T | false =>\n typeof value === 'function' ? value : value === false ? false : fallback;\n\nexport const getConfig = ({\n serverURL,\n\n path = location.pathname,\n lang = typeof navigator === 'undefined' ? 'en-US' : navigator.language,\n locale,\n emoji = DEFAULT_EMOJI,\n meta = ['nick', 'mail', 'link'],\n requiredMeta = [],\n dark = false,\n pageSize = 10,\n wordLimit,\n imageUploader,\n highlighter,\n texRenderer,\n copyright = true,\n login = 'enable',\n search,\n reaction,\n recaptchaV3Key = '',\n turnstileKey = '',\n commentSorting = 'latest',\n ...more\n}: WalineProps): WalineConfig => ({\n serverURL: getServerURL(serverURL),\n path: decodePath(path),\n locale: {\n ...(DEFAULT_LOCALES[lang] || DEFAULT_LOCALES[DEFAULT_LANG]),\n ...(typeof locale === 'object' ? locale : {}),\n } as WalineLocale,\n wordLimit: getWordLimit(wordLimit),\n meta: getMeta(meta),\n requiredMeta: getMeta(requiredMeta),\n imageUploader: fallback(imageUploader, defaultUploadImage),\n highlighter: fallback(highlighter, defaultHighlighter),\n texRenderer: fallback(texRenderer, defaultTeXRenderer),\n lang: Object.keys(DEFAULT_LOCALES).includes(lang) ? lang : 'en-US',\n dark,\n emoji: typeof emoji === 'boolean' ? (emoji ? DEFAULT_EMOJI : []) : emoji,\n pageSize,\n login,\n copyright,\n search:\n search === false\n ? false\n : typeof search === 'object'\n ? search\n : getDefaultSearchOptions(lang),\n recaptchaV3Key,\n turnstileKey,\n reaction: Array.isArray(reaction)\n ? reaction\n : reaction === true\n ? DEFAULT_REACTION\n : [],\n commentSorting,\n ...more,\n});\n","export const errorHandler = (err: Error): void => {\n if (err.name !== 'AbortError') console.error(err.message);\n};\n","export const getQuery = (element: HTMLElement): string | null =>\n element.dataset.path || null;\n","import { getPageview, updatePageview } from '@waline/api';\n\nimport { type WalineAbort } from './typings/index.js';\nimport { errorHandler, getQuery, getServerURL } from './utils/index.js';\n\nexport interface WalinePageviewCountOptions {\n /**\n * Waline 服务端地址\n *\n * Waline server url\n */\n serverURL: string;\n\n /**\n * 浏览量 CSS 选择器\n *\n * Pageview CSS selector\n *\n * @default '.waline-pageview-count'\n */\n selector?: string;\n\n /**\n * 需要更新和获取的路径\n *\n * Path to be fetched and updated\n *\n * @default window.location.pathname\n */\n path?: string;\n\n /**\n * 是否在查询时更新 path 的浏览量\n *\n * Whether update pageviews when fetching path result\n *\n * @default true\n */\n update?: boolean;\n\n /**\n * 错误提示消息所使用的语言\n *\n * Language of error message\n *\n * @default navigator.language\n */\n lang?: string;\n}\n\nexport { type WalineAbort } from './typings/index.js';\n\nconst renderVisitorCount = (\n counts: number[],\n countElements: HTMLElement[],\n): void => {\n countElements.forEach((element, index) => {\n element.innerText = counts[index].toString();\n });\n};\n\nexport const pageviewCount = ({\n serverURL,\n path = window.location.pathname,\n selector = '.waline-pageview-count',\n update = true,\n lang = navigator.language,\n}: WalinePageviewCountOptions): WalineAbort => {\n const controller = new AbortController();\n\n const elements = Array.from(\n // pageview selectors\n document.querySelectorAll<HTMLElement>(selector),\n );\n\n const filter = (element: HTMLElement): boolean => {\n const query = getQuery(element);\n\n return query !== null && path !== query;\n };\n\n const fetch = (elements: HTMLElement[]): Promise<void> =>\n getPageview({\n serverURL: getServerURL(serverURL),\n paths: elements.map((element) => getQuery(element) || path),\n lang,\n signal: controller.signal,\n })\n .then((counts) => renderVisitorCount(counts, elements))\n .catch(errorHandler);\n\n // we should update pageviews\n if (update) {\n const normalElements = elements.filter((element) => !filter(element));\n const elementsNeedstoBeFetched = elements.filter(filter);\n\n void updatePageview({\n serverURL: getServerURL(serverURL),\n path,\n lang,\n }).then(([count]) =>\n renderVisitorCount(\n new Array<number>(normalElements.length).fill(count),\n normalElements,\n ),\n );\n\n // if we should fetch count of other pages\n if (elementsNeedstoBeFetched.length) {\n void fetch(elementsNeedstoBeFetched);\n }\n }\n // we should not update pageviews\n else {\n void fetch(elements);\n }\n\n return controller.abort.bind(controller);\n};\n"],"names":["version","m","s","t","h","n","p","o","a","e","r","d","j","v","removeEndingSplash","content","isLinkHttp","link","getServerURL","serverURL","result","errorHandler","err","getQuery","element","renderVisitorCount","counts","countElements","index","pageviewCount","path","selector","update","lang","controller","elements","filter","query","fetch","getPageview","normalElements","elementsNeedstoBeFetched","updatePageview","count"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ (function(l,p){typeof exports=="object"&&typeof module<"u"?p(exports):typeof define=="function"&&define.amd?define(["exports"],p):(l=typeof globalThis<"u"?globalThis:l||self,p(l.Waline={}))})(this,function(l){"use strict";const p="3.0.0-alpha.7",v={"Content-Type":"application/json"},g=e=>`${e.replace(/\/?$/,"/")}api/`,$=(e,t="")=>{if(typeof e=="object"&&e.errno)throw new TypeError(`${t} failed with ${e.errno}: ${e.errmsg}`);return e},w=({serverURL:e,lang:t,paths:r,type:o,signal:n})=>fetch(`${g(e)}article?path=${encodeURIComponent(r.join(","))}&type=${encodeURIComponent(o.join(","))}&lang=${t}`,{signal:n}).then(a=>a.json()),R=({serverURL:e,lang:t,path:r,type:o,action:n})=>fetch(`${g(e)}article?lang=${t}`,{method:"POST",headers:v,body:JSON.stringify({path:r,type:o,action:n})}).then(a=>a.json()).then(a=>$(a,"Update counter").data),U=({serverURL:e,lang:t,paths:r,signal:o})=>w({serverURL:e,lang:t,paths:r,type:["time"],signal:o}).then(n=>Array.isArray(n)?n:[n]),L=e=>R({...e,type:"time",action:"inc"}),b=(e="")=>e.replace(/\/$/u,""),j=e=>/^(https?:)?\/\//.test(e),d=e=>{const t=b(e);return j(t)?t:`https://${t}`},A=e=>{e.name!=="AbortError"&&console.error(e.message)},f=e=>e.dataset.path||null,u=(e,t)=>{t.forEach((r,o)=>{r.innerText=e[o].toString()})},C=({serverURL:e,path:t=window.location.pathname,selector:r=".waline-pageview-count",update:o=!0,lang:n=navigator.language})=>{const a=new AbortController,c=Array.from(document.querySelectorAll(r)),y=s=>{const i=f(s);return i!==null&&t!==i},m=s=>U({serverURL:d(e),paths:s.map(i=>f(i)||t),lang:n,signal:a.signal}).then(i=>u(i,s)).catch(A);if(o){const s=c.filter(h=>!y(h)),i=c.filter(y);L({serverURL:d(e),path:t,lang:n}).then(([h])=>u(new Array(s.length).fill(h),s)),i.length&&m(i)}else m(c);return a.abort.bind(a)};l.pageviewCount=C,l.version=p});
2
+ //# sourceMappingURL=pageview.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageview.umd.js","sources":["../src/version.ts","../../api/dist/api.js","../src/utils/path.ts","../src/utils/config.ts","../src/utils/error.ts","../src/utils/query.ts","../src/pageview.ts"],"sourcesContent":["declare const VERSION: string;\n\nexport const version = VERSION;\n","const m={\"Content-Type\":\"application/json\"},s=t=>`${t.replace(/\\/?$/,\"/\")}api/`,h=(t,n=\"\")=>{if(typeof t==\"object\"&&t.errno)throw new TypeError(`${n} failed with ${t.errno}: ${t.errmsg}`);return t},p=({serverURL:t,lang:n,paths:o,type:a,signal:e})=>fetch(`${s(t)}article?path=${encodeURIComponent(o.join(\",\"))}&type=${encodeURIComponent(a.join(\",\"))}&lang=${n}`,{signal:e}).then(r=>r.json()),d=({serverURL:t,lang:n,path:o,type:a,action:e})=>fetch(`${s(t)}article?lang=${n}`,{method:\"POST\",headers:m,body:JSON.stringify({path:o,type:a,action:e})}).then(r=>r.json()).then(r=>h(r,\"Update counter\").data),$=({serverURL:t,lang:n,path:o,page:a,pageSize:e,sortBy:r,signal:c,token:i})=>{const l={};return i&&(l.Authorization=`Bearer ${i}`),fetch(`${s(t)}comment?path=${encodeURIComponent(o)}&pageSize=${e}&page=${a}&lang=${n}&sortBy=${r}`,{signal:c,headers:l}).then(g=>g.json()).then(g=>h(g,\"Get comment data\").data)},u=({serverURL:t,lang:n,token:o,comment:a})=>{const e={\"Content-Type\":\"application/json\"};return o&&(e.Authorization=`Bearer ${o}`),fetch(`${s(t)}comment?lang=${n}`,{method:\"POST\",headers:e,body:JSON.stringify(a)}).then(r=>r.json())},y=({serverURL:t,lang:n,token:o,objectId:a})=>fetch(`${s(t)}comment/${a}?lang=${n}`,{method:\"DELETE\",headers:{Authorization:`Bearer ${o}`}}).then(e=>e.json()).then(e=>h(e,\"Delete comment\")),U=({serverURL:t,lang:n,token:o,objectId:a,comment:e})=>fetch(`${s(t)}comment/${a}?lang=${n}`,{method:\"PUT\",headers:{...m,Authorization:`Bearer ${o}`},body:JSON.stringify(e)}).then(r=>r.json()).then(r=>h(r,\"Update comment\")),f=({serverURL:t,lang:n,paths:o,signal:a})=>fetch(`${s(t)}comment?type=count&url=${encodeURIComponent(o.join(\",\"))}&lang=${n}`,{signal:a}).then(e=>e.json()).then(e=>h(e,\"Get comment count\").data),R=({lang:t,serverURL:n})=>{const o=(window.innerWidth-450)/2,a=(window.innerHeight-450)/2,e=window.open(`${n.replace(/\\/$/,\"\")}/ui/login?lng=${encodeURIComponent(t)}`,\"_blank\",`width=450,height=450,left=${o},top=${a},scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no`);return e?.postMessage({type:\"TOKEN\",data:null},\"*\"),new Promise(r=>{const c=({data:i})=>{!i||typeof i!=\"object\"||i.type!==\"userInfo\"||i.data.token&&(e?.close(),window.removeEventListener(\"message\",c),r(i.data))};window.addEventListener(\"message\",c)})},j=({serverURL:t,lang:n,paths:o,signal:a})=>p({serverURL:t,lang:n,paths:o,type:[\"time\"],signal:a}).then(e=>Array.isArray(e)?e:[e]),v=t=>d({...t,type:\"time\",action:\"inc\"}),w=({serverURL:t,lang:n,count:o,signal:a,token:e})=>{const r={};return e&&(r.Authorization=`Bearer ${e}`),fetch(`${s(t)}comment?type=recent&count=${o}&lang=${n}`,{signal:a,headers:r}).then(c=>c.json())},C=({serverURL:t,signal:n,pageSize:o,lang:a})=>fetch(`${s(t)}user?pageSize=${o}&lang=${a}`,{signal:n}).then(e=>e.json()).then(e=>h(e,\"user list\")).then(e=>e.data);export{u as addComment,y as deleteComment,f as fetchCommentCount,p as getArticleCounter,$ as getComment,j as getPageview,w as getRecentComment,C as getUserList,R as login,d as updateArticleCounter,U as updateComment,v as updatePageview};\n//# sourceMappingURL=api.js.map\n","export const decodePath = (path: string): string => {\n try {\n path = decodeURI(path);\n } catch (err) {\n // ignore error\n }\n\n return path;\n};\n\nexport const removeEndingSplash = (content = ''): string =>\n content.replace(/\\/$/u, '');\n\nexport const isLinkHttp = (link: string): boolean =>\n /^(https?:)?\\/\\//.test(link);\n","import { decodePath, isLinkHttp, removeEndingSplash } from './path.js';\nimport {\n DEFAULT_EMOJI,\n DEFAULT_LANG,\n DEFAULT_LOCALES,\n DEFAULT_REACTION,\n defaultUploadImage,\n defaultHighlighter,\n defaultTeXRenderer,\n getDefaultSearchOptions,\n getMeta,\n} from '../config/index.js';\nimport {\n type WalineEmojiInfo,\n type WalineEmojiMaps,\n type WalineLocale,\n type WalineProps,\n} from '../typings/index.js';\n\nexport interface WalineEmojiConfig {\n tabs: Pick<WalineEmojiInfo, 'name' | 'icon' | 'items'>[];\n map: WalineEmojiMaps;\n}\n\nexport interface WalineConfig\n extends Required<\n Omit<\n WalineProps,\n | 'emoji'\n | 'imageUploader'\n | 'highlighter'\n | 'texRenderer'\n | 'wordLimit'\n | 'reaction'\n | 'search'\n >\n > {\n locale: WalineLocale;\n wordLimit: [number, number] | false;\n reaction: string[];\n emoji: Exclude<WalineProps['emoji'], boolean | undefined>;\n highlighter: Exclude<WalineProps['highlighter'], true | undefined>;\n imageUploader: Exclude<WalineProps['imageUploader'], true | undefined>;\n texRenderer: Exclude<WalineProps['texRenderer'], true | undefined>;\n search: Exclude<WalineProps['search'], true | undefined>;\n}\n\nexport const getServerURL = (serverURL: string): string => {\n const result = removeEndingSplash(serverURL);\n\n return isLinkHttp(result) ? result : `https://${result}`;\n};\n\nconst getWordLimit = (\n wordLimit: WalineProps['wordLimit'],\n): [number, number] | false =>\n Array.isArray(wordLimit) ? wordLimit : wordLimit ? [0, wordLimit] : false;\n\nconst fallback = <T = unknown>(\n value: T | boolean | undefined,\n fallback: T,\n): T | false =>\n typeof value === 'function' ? value : value === false ? false : fallback;\n\nexport const getConfig = ({\n serverURL,\n\n path = location.pathname,\n lang = typeof navigator === 'undefined' ? 'en-US' : navigator.language,\n locale,\n emoji = DEFAULT_EMOJI,\n meta = ['nick', 'mail', 'link'],\n requiredMeta = [],\n dark = false,\n pageSize = 10,\n wordLimit,\n imageUploader,\n highlighter,\n texRenderer,\n copyright = true,\n login = 'enable',\n search,\n reaction,\n recaptchaV3Key = '',\n turnstileKey = '',\n commentSorting = 'latest',\n ...more\n}: WalineProps): WalineConfig => ({\n serverURL: getServerURL(serverURL),\n path: decodePath(path),\n locale: {\n ...(DEFAULT_LOCALES[lang] || DEFAULT_LOCALES[DEFAULT_LANG]),\n ...(typeof locale === 'object' ? locale : {}),\n } as WalineLocale,\n wordLimit: getWordLimit(wordLimit),\n meta: getMeta(meta),\n requiredMeta: getMeta(requiredMeta),\n imageUploader: fallback(imageUploader, defaultUploadImage),\n highlighter: fallback(highlighter, defaultHighlighter),\n texRenderer: fallback(texRenderer, defaultTeXRenderer),\n lang: Object.keys(DEFAULT_LOCALES).includes(lang) ? lang : 'en-US',\n dark,\n emoji: typeof emoji === 'boolean' ? (emoji ? DEFAULT_EMOJI : []) : emoji,\n pageSize,\n login,\n copyright,\n search:\n search === false\n ? false\n : typeof search === 'object'\n ? search\n : getDefaultSearchOptions(lang),\n recaptchaV3Key,\n turnstileKey,\n reaction: Array.isArray(reaction)\n ? reaction\n : reaction === true\n ? DEFAULT_REACTION\n : [],\n commentSorting,\n ...more,\n});\n","export const errorHandler = (err: Error): void => {\n if (err.name !== 'AbortError') console.error(err.message);\n};\n","export const getQuery = (element: HTMLElement): string | null =>\n element.dataset.path || null;\n","import { getPageview, updatePageview } from '@waline/api';\n\nimport { type WalineAbort } from './typings/index.js';\nimport { errorHandler, getQuery, getServerURL } from './utils/index.js';\n\nexport interface WalinePageviewCountOptions {\n /**\n * Waline 服务端地址\n *\n * Waline server url\n */\n serverURL: string;\n\n /**\n * 浏览量 CSS 选择器\n *\n * Pageview CSS selector\n *\n * @default '.waline-pageview-count'\n */\n selector?: string;\n\n /**\n * 需要更新和获取的路径\n *\n * Path to be fetched and updated\n *\n * @default window.location.pathname\n */\n path?: string;\n\n /**\n * 是否在查询时更新 path 的浏览量\n *\n * Whether update pageviews when fetching path result\n *\n * @default true\n */\n update?: boolean;\n\n /**\n * 错误提示消息所使用的语言\n *\n * Language of error message\n *\n * @default navigator.language\n */\n lang?: string;\n}\n\nexport { type WalineAbort } from './typings/index.js';\n\nconst renderVisitorCount = (\n counts: number[],\n countElements: HTMLElement[],\n): void => {\n countElements.forEach((element, index) => {\n element.innerText = counts[index].toString();\n });\n};\n\nexport const pageviewCount = ({\n serverURL,\n path = window.location.pathname,\n selector = '.waline-pageview-count',\n update = true,\n lang = navigator.language,\n}: WalinePageviewCountOptions): WalineAbort => {\n const controller = new AbortController();\n\n const elements = Array.from(\n // pageview selectors\n document.querySelectorAll<HTMLElement>(selector),\n );\n\n const filter = (element: HTMLElement): boolean => {\n const query = getQuery(element);\n\n return query !== null && path !== query;\n };\n\n const fetch = (elements: HTMLElement[]): Promise<void> =>\n getPageview({\n serverURL: getServerURL(serverURL),\n paths: elements.map((element) => getQuery(element) || path),\n lang,\n signal: controller.signal,\n })\n .then((counts) => renderVisitorCount(counts, elements))\n .catch(errorHandler);\n\n // we should update pageviews\n if (update) {\n const normalElements = elements.filter((element) => !filter(element));\n const elementsNeedstoBeFetched = elements.filter(filter);\n\n void updatePageview({\n serverURL: getServerURL(serverURL),\n path,\n lang,\n }).then(([count]) =>\n renderVisitorCount(\n new Array<number>(normalElements.length).fill(count),\n normalElements,\n ),\n );\n\n // if we should fetch count of other pages\n if (elementsNeedstoBeFetched.length) {\n void fetch(elementsNeedstoBeFetched);\n }\n }\n // we should not update pageviews\n else {\n void fetch(elements);\n }\n\n return controller.abort.bind(controller);\n};\n"],"names":["version","m","s","t","h","n","p","o","a","e","r","d","j","v","removeEndingSplash","content","isLinkHttp","link","getServerURL","serverURL","result","errorHandler","err","getQuery","element","renderVisitorCount","counts","countElements","index","pageviewCount","path","selector","update","lang","controller","elements","filter","query","fetch","getPageview","normalElements","elementsNeedstoBeFetched","updatePageview","count"],"mappings":"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"}