@inpageedit/core 0.14.1 → 0.14.3
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/README.md +5 -4
- package/dist/{BasePlugin-YOi2_vUo.js → BasePlugin-DD7l-5Xw.js} +2 -2
- package/dist/{BasePlugin-YOi2_vUo.js.map → BasePlugin-DD7l-5Xw.js.map} +1 -1
- package/dist/{PluginPrefSync-jTNlRQE-.js → PluginPrefSync-CbFuuC19.js} +3 -3
- package/dist/{PluginPrefSync-jTNlRQE-.js.map → PluginPrefSync-CbFuuC19.js.map} +1 -1
- package/dist/{PluginStoreApp-CGNxKXAN.js → PluginStoreApp-qiSVtnBy.js} +2 -2
- package/dist/{PluginStoreApp-CGNxKXAN.js.map → PluginStoreApp-qiSVtnBy.js.map} +1 -1
- package/dist/Preferences-C10tZMl1.js +2701 -0
- package/dist/Preferences-C10tZMl1.js.map +1 -0
- package/dist/{index-3NZkG2a3.js → index-BXNyXvre.js} +3 -3
- package/dist/{index-3NZkG2a3.js.map → index-BXNyXvre.js.map} +1 -1
- package/dist/{index-Bb0FiU2c.js → index-BanevHQ2.js} +21 -17
- package/dist/index-BanevHQ2.js.map +1 -0
- package/dist/index-BjDTD66_.js +491 -0
- package/dist/index-BjDTD66_.js.map +1 -0
- package/dist/{index-D97lUU3h.js → index-BpQ6VGMz.js} +55 -55
- package/dist/index-BpQ6VGMz.js.map +1 -0
- package/dist/{index-D-fW3ESK.js → index-CnR6CqkM.js} +2 -2
- package/dist/{index-D-fW3ESK.js.map → index-CnR6CqkM.js.map} +1 -1
- package/dist/{index-DELHsLHS.js → index-DKCZDN-Q.js} +4 -4
- package/dist/{index-DELHsLHS.js.map → index-DKCZDN-Q.js.map} +1 -1
- package/dist/{index-BBNseJXG.js → index-DVOc6fB6.js} +3 -3
- package/dist/{index-BBNseJXG.js.map → index-DVOc6fB6.js.map} +1 -1
- package/dist/{index-D6zFqL2u.js → index-De25v1_Q.js} +3 -3
- package/dist/{index-D6zFqL2u.js.map → index-De25v1_Q.js.map} +1 -1
- package/dist/{index-BrYKe18j.js → index-DensW9qt.js} +3 -3
- package/dist/{index-BrYKe18j.js.map → index-DensW9qt.js.map} +1 -1
- package/dist/{index-DTHY5rAO.js → index-DrIf5j8O.js} +156 -127
- package/dist/index-DrIf5j8O.js.map +1 -0
- package/dist/index-MgXERLzL.js +3090 -0
- package/dist/index-MgXERLzL.js.map +1 -0
- package/dist/{index-DmLoihN1.js → index-WfXtYVMt.js} +134 -131
- package/dist/index-WfXtYVMt.js.map +1 -0
- package/dist/index.d.ts +38 -6
- package/dist/index.js +5 -5
- package/dist/models/index.js +7 -503
- package/dist/models/index.js.map +1 -1
- package/dist/plugins/index.js +10 -10
- package/dist/services/index.js +1 -1
- package/lib/index.umd.js +11 -11
- package/lib/index.umd.js.map +1 -1
- package/package.json +5 -5
- package/dist/Preferences-BF2fcXrn.js +0 -1539
- package/dist/Preferences-BF2fcXrn.js.map +0 -1
- package/dist/index-Bb0FiU2c.js.map +0 -1
- package/dist/index-BgkZW91u.js +0 -4245
- package/dist/index-BgkZW91u.js.map +0 -1
- package/dist/index-D97lUU3h.js.map +0 -1
- package/dist/index-DTHY5rAO.js.map +0 -1
- package/dist/index-DmLoihN1.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-BXNyXvre.js","sources":["../src/plugins/quick-preview/index.tsx"],"sourcesContent":["import { Inject, InPageEdit, Schema } from '@/InPageEdit'\nimport { type QuickEditEventPayload } from '@/plugins/quick-edit'\nimport { IWikiPage } from '@/models/WikiPage'\nimport { MwApiParams } from 'wiki-saikou'\nimport { PageParseData } from '@/models/WikiPage/types/PageParseData'\nimport { IPEModal, IPEModalOptions } from '@inpageedit/modal'\n\ninterface QuickPreviewEventPayload {\n ctx: InPageEdit\n modal: IPEModal\n wikiPage: IWikiPage\n text: string\n parseData: PageParseData\n}\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n quickPreview: PluginQuickPreview & {\n // for backward compatibility\n (\n ...args: Parameters<PluginQuickPreview['previewWikitext']>\n ): ReturnType<PluginQuickPreview['previewWikitext']>\n }\n }\n interface Events {\n 'quick-preview/show-modal'(payload: Omit<QuickPreviewEventPayload, 'parseData'>): void\n 'quick-preview/loaded'(payload: QuickPreviewEventPayload): void\n }\n interface PreferencesMap {\n 'quickPreview.keyshortcut.quickEdit': string\n 'quickPreview.keyshortcut.quickDelete': string\n }\n}\n\n@Inject(['api', 'wikiPage', 'modal', 'preferences', '$'])\n@RegisterPreferences(\n Schema.object({\n 'quickPreview.keyshortcut': Schema.string()\n .default('ctrl-p')\n .description('Key shortcut to open quick preview in quick edit modal'),\n })\n .extra('category', 'editor')\n .description('Quick preview options')\n)\nexport class PluginQuickPreview extends BasePlugin {\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'quickPreview')\n this.ctx.set('quickPreview', makeCallable(this, 'previewWikitext'))\n }\n\n protected start(): Promise<void> | void {\n this.ctx.on('quick-edit/wiki-page', this.injectQuickEdit.bind(this))\n }\n\n protected stop(): Promise<void> | void {}\n\n previewWikitext(\n text: string,\n params?: MwApiParams,\n wikiPage?: IWikiPage,\n modal?: IPEModal,\n modalOptions?: Partial<IPEModalOptions>\n ) {\n const $ = this.ctx.$\n\n wikiPage ||= this.ctx.wikiPage.newBlankPage({\n title: 'API',\n })\n\n if (!modal || modal.isDestroyed) {\n modal = this.ctx.modal\n .createObject({\n className: 'in-page-edit ipe-quickPreview',\n sizeClass: 'large',\n center: false,\n ...modalOptions,\n })\n .init()\n }\n\n modal.show()\n modal.setTitle($`Preview - Loading...`)\n modal.setContent(<ProgressBar />)\n modal.bringToFront()\n this.ctx.emit('quick-preview/show-modal', {\n ctx: this.ctx,\n text,\n modal,\n wikiPage,\n })\n\n wikiPage\n .preview(text, params)\n .then((ret) => {\n const {\n data: { parse },\n } = ret\n modal.setTitle($(parse.title)`Preview - {{ $1 }}`)\n let outputRef: HTMLElement | null = null\n modal.setContent(\n (\n <section>\n <div\n ref={(el) => (outputRef = el)}\n className=\"mw-parser-output\"\n innerHTML={parse.text}\n ></div>\n </section>\n ) as HTMLElement\n )\n if (window.mw?.hook && typeof jQuery === 'function') {\n window.mw.hook('wikipage.content').fire(jQuery(outputRef!))\n }\n this.ctx.emit('quick-preview/loaded', {\n ctx: this.ctx,\n modal,\n wikiPage,\n text,\n parseData: parse,\n })\n })\n .catch((error) => {\n modal.setTitle($`Preview - Failed`)\n modal.setContent(\n <>\n <p>{$`Failed to preview`}</p>\n <p>{error instanceof Error ? error.message : String(error)}</p>\n </>\n )\n })\n\n return modal\n }\n\n private async injectQuickEdit({ options, modal, wikiPage }: QuickEditEventPayload) {\n const $ = this.ctx.$\n let latestPreviewModal: IPEModal | undefined = undefined\n modal.addButton(\n {\n label: $`Preview`,\n side: 'left',\n className: 'btn btn-secondary',\n keyPress:\n (await this.ctx.preferences.get('quickPreview.keyshortcut.quickEdit')) || undefined,\n method: () => {\n let wikitext =\n (modal.get$content().querySelector<HTMLTextAreaElement>('textarea[name=\"text\"]')\n ?.value as string) || ''\n if (options.section === 'new') {\n const title = modal\n .get$content()\n .querySelector<HTMLInputElement>('input[name=\"summary\"]')?.value\n if (title) {\n wikitext = `==${title}==\\n${wikitext}`\n }\n }\n\n latestPreviewModal = this.previewWikitext(\n wikitext,\n undefined,\n wikiPage,\n latestPreviewModal,\n {\n backdrop: false,\n draggable: true,\n }\n )\n },\n },\n 1\n )\n modal.on(modal.Event.Close, () => {\n latestPreviewModal?.destroy()\n latestPreviewModal = undefined\n })\n }\n}\n"],"names":["_PluginQuickPreview_decorators","_init","_a","Inject","RegisterPreferences","Schema","PluginQuickPreview","BasePlugin","ctx","makeCallable","text","params","wikiPage","modal","modalOptions","$","jsx","ProgressBar","ret","parse","outputRef","el","error","jsxs","Fragment","options","latestPreviewModal","wikitext","title","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { j as n } from "./index-CM_6yF2v.js";
|
|
2
|
-
import { S as g, E as b, p as A, d as x, I as P } from "./Preferences-
|
|
3
|
-
import { B as U } from "./BasePlugin-
|
|
2
|
+
import { S as g, E as b, p as A, d as x, I as P } from "./Preferences-C10tZMl1.js";
|
|
3
|
+
import { B as U } from "./BasePlugin-DD7l-5Xw.js";
|
|
4
4
|
var B = Object.create, f = Object.defineProperty, q = Object.getOwnPropertyDescriptor, v = (i, e) => (e = Symbol[i]) ? e : Symbol.for("Symbol." + i), w = (i) => {
|
|
5
5
|
throw TypeError(i);
|
|
6
|
-
}, L = (i, e, t) => e in i ? f(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t, N = (i, e) => f(i, "name", { value: e, configurable: !0 }),
|
|
6
|
+
}, L = (i, e, t) => e in i ? f(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t, N = (i, e) => f(i, "name", { value: e, configurable: !0 }), $ = (i) => [, , , B(i?.[v("metadata")] ?? null)], T = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], k = (i) => i !== void 0 && typeof i != "function" ? w("Function expected") : i, D = (i, e, t, a, s) => ({ kind: T[i], name: e, metadata: a, addInitializer: (r) => t._ ? w("Already initialized") : s.push(k(r || null)) }), O = (i, e) => L(e, v("metadata"), i[3]), j = (i, e, t, a) => {
|
|
7
7
|
for (var s = 0, r = i[e >> 1], o = r && r.length; s < o; s++) r[s].call(t);
|
|
8
8
|
return a;
|
|
9
|
-
},
|
|
10
|
-
var o,
|
|
9
|
+
}, C = (i, e, t, a, s, r) => {
|
|
10
|
+
var o, c, h, d = e & 7, l = !1, y = 0, I = i[y] || (i[y] = []), u = d && (s = s.prototype, d < 5 && (d > 3 || !l) && q(s, t));
|
|
11
11
|
N(s, t);
|
|
12
12
|
for (var p = a.length - 1; p >= 0; p--)
|
|
13
|
-
h =
|
|
14
|
-
return
|
|
13
|
+
h = D(d, t, c = {}, i[3], I), o = (0, a[p])(s, h), c._ = 1, k(o) && (s = o);
|
|
14
|
+
return O(i, s), u && f(s, t, u), l ? d ^ 4 ? r : u : s;
|
|
15
15
|
}, E, _, S;
|
|
16
16
|
E = [P(["wiki", "preferences", "$"])];
|
|
17
17
|
class m extends (S = U) {
|
|
@@ -150,10 +150,14 @@ class m extends (S = U) {
|
|
|
150
150
|
this.addEvent("quick-edit", void 0, t.wikiPage.title);
|
|
151
151
|
}), e.on("quick-edit/submit", (t) => {
|
|
152
152
|
this.addEvent("quick-edit", "submit", t.wikiPage.title);
|
|
153
|
-
}), e.on("quick-move/submit", (
|
|
153
|
+
}), e.on("quick-move/submit", () => {
|
|
154
154
|
this.addEvent("quick-move", "submit");
|
|
155
|
-
}), e.on("toolbox/button-clicked", (t) => {
|
|
155
|
+
}), e.on("toolbox/button-clicked", ({ payload: t }) => {
|
|
156
156
|
this.addEvent("toolbox", `button-clicked#${t.id || "unknown"}`);
|
|
157
|
+
}), e.on("plugin-store/plugin-installed", ({ registry: t, id: a, by: s }) => {
|
|
158
|
+
s === "new-added" && this.addEvent("plugin-store", "plugin-installed", `${t.name}#${a}`);
|
|
159
|
+
}), e.on("plugin-store/plugin-uninstalled", ({ registry: t, id: a }) => {
|
|
160
|
+
this.addEvent("plugin-store", "plugin-uninstalled", `${t.name}#${a}`);
|
|
157
161
|
});
|
|
158
162
|
}
|
|
159
163
|
addEvent(e, t, a) {
|
|
@@ -182,18 +186,18 @@ class m extends (S = U) {
|
|
|
182
186
|
return this.logger.debug("Beacon sent successfully", a), !0;
|
|
183
187
|
{
|
|
184
188
|
this.logger.debug("Beacon failed, sending via XMLHttpRequest");
|
|
185
|
-
const { promise:
|
|
189
|
+
const { promise: c, resolve: h, reject: d } = x();
|
|
186
190
|
try {
|
|
187
191
|
const l = new XMLHttpRequest();
|
|
188
192
|
l.open("POST", r, !0), l.setRequestHeader("Content-Type", "application/json"), l.send(s), l.onload = () => {
|
|
189
193
|
this.logger.debug("Beacon sent successfully via XMLHttpRequest", a), h(l.status >= 200 && l.status < 300);
|
|
190
194
|
}, l.onerror = () => {
|
|
191
|
-
|
|
195
|
+
d(new Error("Failed to send beacon"));
|
|
192
196
|
};
|
|
193
197
|
} catch (l) {
|
|
194
|
-
|
|
198
|
+
d(l);
|
|
195
199
|
}
|
|
196
|
-
return
|
|
200
|
+
return c;
|
|
197
201
|
}
|
|
198
202
|
}
|
|
199
203
|
/**
|
|
@@ -203,10 +207,10 @@ class m extends (S = U) {
|
|
|
203
207
|
this._timer !== null && (clearInterval(this._timer), this._timer = null), this._usages.length > 0 && this.sendBeacon();
|
|
204
208
|
}
|
|
205
209
|
}
|
|
206
|
-
_ =
|
|
207
|
-
m =
|
|
208
|
-
|
|
210
|
+
_ = $(S);
|
|
211
|
+
m = C(_, 0, "PluginAnalytics", E, m);
|
|
212
|
+
j(_, 1, m);
|
|
209
213
|
export {
|
|
210
214
|
m as PluginAnalytics
|
|
211
215
|
};
|
|
212
|
-
//# sourceMappingURL=index-
|
|
216
|
+
//# sourceMappingURL=index-BanevHQ2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BanevHQ2.js","sources":["../src/plugins/analytics/index.tsx"],"sourcesContent":["import { Endpoints } from '@/constants/endpoints.js'\nimport { Inject, InPageEdit, Schema } from '@/InPageEdit'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n analytics: PluginAnalytics\n }\n}\n\nexport interface IPEBeaconPayload {\n siteApi: string\n siteName?: string\n userId: number\n userName: string\n version?: string\n usages: IPEBeaconUsage[]\n}\n\nexport interface IPEBeaconUsage {\n ts: number\n feature: string\n subtype?: string\n page?: string\n}\n\n@Inject(['wiki', 'preferences', '$'])\nexport class PluginAnalytics extends BasePlugin {\n private _usages: IPEBeaconUsage[] = []\n private _timer: ReturnType<typeof setInterval> | null = null\n private readonly MAX_QUEUE_SIZE = 50\n private readonly INTERVAL_MS = 60 * 1000 // 1分钟\n\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'analytics')\n this._setupTimer()\n this._registerUnloadHandler()\n this._showConfirmNotify()\n this._initPluginListeners()\n ctx.set('analytics', this)\n }\n\n protected start(): Promise<void> | void {\n const ctx = this.ctx\n const $ = ctx.$\n ctx.preferences.registerCustomConfig(\n 'analytics',\n Schema.object({\n 'analytics._intro': Schema.const(\n <section>\n <h3>{$`InPageEdit Analytics`}</h3>\n <p>\n {$`InPageEdit Analytics is the companion analytics platform for the InPageEdit NEXT project. By collecting and displaying usage data from around the world, it helps developers and the community better understand how the tool is used, optimize feature design, and enhance user experience.`}\n </p>\n <h4>{$`What data will be collected?`}</h4>\n <ol style={{ listStyle: 'number', paddingLeft: '1em' }}>\n <li>\n <strong>{$`Usage data`}</strong>:{' '}\n {$`When and which features you use, what pages you edit, etc.`}\n </li>\n <li>\n <strong>{$`User information`}</strong>: {$`Your user name and user ID.`}\n </li>\n <li>\n <strong>{$`Site information`}</strong>: {$`This wiki's url and site name.`}\n </li>\n </ol>\n <p>\n <strong>{$`NO sensitive data will be collected.`}</strong>\n </p>\n <div style={{ display: 'grid', gap: '0.5rem' }}>\n <a href={this.analyticsDashUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n <button className=\"btn\" style={{ width: '100%' }}>\n {$`Analytics Platform`}\n </button>\n </a>\n <a\n href={`${this.analyticsDashUrl}/_redirect/user?${new URLSearchParams({\n siteApi: this.ctx.wiki.getSciprtUrl('api'),\n mwUserId: this.ctx.wiki.userInfo.id.toString(),\n }).toString()}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <button className=\"btn\" style={{ width: '100%' }}>\n {$`View My Data`}\n </button>\n </a>\n </div>\n </section>\n ).role('raw-html'),\n 'analytics.enabled': Schema.boolean()\n .description($`prefs.analytics.enabled`)\n .default(false),\n }).description($`prefs.analytics.$`),\n 'general'\n )\n }\n\n private get analyticsDashUrl() {\n return import.meta.env.PROD ? Endpoints.ANALYTICS_DASH_URL : 'http://localhost:20105'\n }\n private get analyticsApiBase() {\n return import.meta.env.PROD ? Endpoints.ANALYTICS_API_BASE : 'http://localhost:20105/api/v6'\n }\n\n private _setupTimer() {\n this._timer = setInterval(() => {\n if (this._usages.length > 0) {\n this.sendBeacon()\n }\n }, this.INTERVAL_MS)\n }\n\n private _registerUnloadHandler() {\n const handleUnload = () => {\n if (this._usages.length > 0) {\n this.sendBeacon()\n }\n }\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n handleUnload()\n }\n })\n\n window.addEventListener('pagehide', handleUnload)\n window.addEventListener('beforeunload', handleUnload)\n }\n\n private async _showConfirmNotify() {\n const $ = this.ctx.$\n this.ctx.inject(['modal', 'storage'], async (ctx) => {\n const key = 'analytics/confirm-shown'\n const shown = await ctx.storage.simpleKV.get(key)\n const enabled = await ctx.preferences.get('analytics.enabled')\n if (shown || enabled) {\n return\n }\n ctx.modal.notify(\n 'confirm',\n {\n title: $`Enable Analytics`,\n content: (\n <div>\n <p>{$`Help us improve InPageEdit by sharing your usage data with us.`}</p>\n <p>{$`What data will be collected?`}</p>\n <ul style={{ listStyle: 'auto', paddingLeft: '1.5em' }}>\n <li>\n {$`Usage data`}: {$`When and which features you use, what pages you edit, etc.`}\n </li>\n <li>\n {$`User information`}: {$`Your user name and user ID.`}\n </li>\n <li>\n {$`Site information`}: {$`This wiki's url and site name.`}\n </li>\n </ul>\n <p>\n <strong>{$`NO sensitive data will be collected.`}</strong>\n </p>\n </div>\n ),\n okBtn: {\n label: $`Enable`,\n },\n cancelBtn: {\n label: $`Disable`,\n },\n closeAfter: 0,\n onClose: () => {\n this.ctx.storage.simpleKV.set(key, 1)\n },\n },\n (result) => {\n ctx.preferences.set('analytics.enabled', result)\n if (result) {\n this.addEvent('analytics', 'enabled')\n }\n }\n )\n })\n }\n\n private _initPluginListeners() {\n const ctx = this.ctx\n ctx.on('in-article-links/anchor-clicked', (payload) => {\n this.addEvent('in-article-links', paramCase(payload.action))\n })\n ctx.on('quick-diff/loaded', (payload) => {\n this.addEvent('quick-diff', 'loaded', payload.compare.fromtitle)\n })\n ctx.on('quick-redirect/submit', (payload) => {\n this.addEvent('quick-redirect', 'submit', payload.payload.to || undefined)\n })\n ctx.on('quick-preview/loaded', (payload) => {\n this.addEvent('quick-preview', 'loaded', payload.wikiPage.title)\n })\n ctx.on('quick-edit/wiki-page', (payload) => {\n this.addEvent('quick-edit', undefined, payload.wikiPage.title)\n })\n ctx.on('quick-edit/submit', (payload) => {\n this.addEvent('quick-edit', 'submit', payload.wikiPage.title)\n })\n ctx.on('quick-move/submit', () => {\n this.addEvent('quick-move', 'submit')\n })\n ctx.on('toolbox/button-clicked', ({ payload }) => {\n this.addEvent('toolbox', `button-clicked#${payload.id || 'unknown'}`)\n })\n ctx.on('plugin-store/plugin-installed', ({ registry, id, by }) => {\n if (by === 'new-added') {\n this.addEvent('plugin-store', 'plugin-installed', `${registry.name}#${id}`)\n }\n })\n ctx.on('plugin-store/plugin-uninstalled', ({ registry, id }) => {\n this.addEvent('plugin-store', 'plugin-uninstalled', `${registry.name}#${id}`)\n })\n }\n\n public addEvent(feature: string, subtype?: string, page?: string) {\n const usage: IPEBeaconUsage = {\n ts: Date.now(),\n feature,\n subtype,\n page,\n }\n this._usages.push(usage)\n\n // 如果usages数组超过50个,立即发送\n if (this._usages.length >= this.MAX_QUEUE_SIZE) {\n this.sendBeacon()\n }\n\n return this\n }\n\n private async sendBeacon() {\n if (this._usages.length === 0) {\n return true\n }\n\n const enabled = await this.ctx.preferences.get<boolean>('analytics.enabled', false)\n if (!enabled) {\n this.logger.debug('Analytics disabled, skipping')\n return true\n }\n\n const usages = this._usages.splice(0, this._usages.length)\n const payload: IPEBeaconPayload = {\n siteApi: this.ctx.wiki.getSciprtUrl('api'),\n siteName: this.ctx.wiki.siteInfo.general.sitename,\n userId: this.ctx.wiki.userInfo.id,\n userName: this.ctx.wiki.userInfo.name,\n version: this.ctx.version.split('-')[0],\n usages,\n }\n const body = JSON.stringify(payload)\n\n const endpoint = `${this.analyticsApiBase}/submit`\n\n const beaconOK = navigator?.sendBeacon?.(endpoint, body)\n if (beaconOK) {\n this.logger.debug('Beacon sent successfully', payload)\n return true\n } else {\n this.logger.debug('Beacon failed, sending via XMLHttpRequest')\n const { promise, resolve, reject } = promiseWithResolvers<boolean>()\n try {\n const xhr = new XMLHttpRequest()\n xhr.open('POST', endpoint, true)\n xhr.setRequestHeader('Content-Type', 'application/json')\n xhr.send(body)\n xhr.onload = () => {\n this.logger.debug('Beacon sent successfully via XMLHttpRequest', payload)\n resolve(xhr.status >= 200 && xhr.status < 300)\n }\n xhr.onerror = () => {\n reject(new Error('Failed to send beacon'))\n }\n } catch (error) {\n reject(error)\n }\n return promise\n }\n }\n\n /**\n * 清理资源\n */\n protected stop() {\n if (this._timer !== null) {\n clearInterval(this._timer)\n this._timer = null\n }\n // 在销毁前发送剩余的数据\n if (this._usages.length > 0) {\n this.sendBeacon()\n }\n }\n}\n"],"names":["_PluginAnalytics_decorators","_init","_a","Inject","PluginAnalytics","BasePlugin","ctx","$","Schema","jsx","jsxs","Endpoints","handleUnload","key","shown","enabled","result","payload","paramCase","registry","id","by","feature","subtype","page","usage","usages","body","endpoint","promise","resolve","reject","promiseWithResolvers","xhr","error","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
class I {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.values = {};
|
|
4
|
+
}
|
|
5
|
+
get length() {
|
|
6
|
+
return Object.keys(this.values).length;
|
|
7
|
+
}
|
|
8
|
+
clear() {
|
|
9
|
+
this.values = {};
|
|
10
|
+
}
|
|
11
|
+
getItem(s) {
|
|
12
|
+
return this.values[s] ?? null;
|
|
13
|
+
}
|
|
14
|
+
setItem(s, o) {
|
|
15
|
+
this.values[s] = typeof o == "string" ? o : String(o);
|
|
16
|
+
}
|
|
17
|
+
removeItem(s) {
|
|
18
|
+
delete this.values[s];
|
|
19
|
+
}
|
|
20
|
+
key(s) {
|
|
21
|
+
return Object.keys(this.values)[s] ?? null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const x = () => new Proxy(new I(), {
|
|
25
|
+
set(i, s, o) {
|
|
26
|
+
return typeof s == "string" && i.setItem(s, o), !0;
|
|
27
|
+
},
|
|
28
|
+
get(i, s) {
|
|
29
|
+
return typeof s == "string" && !(s in i) ? i.getItem(s) : Reflect.get(i, s);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
function v(i) {
|
|
33
|
+
class s {
|
|
34
|
+
constructor(a, t = !0) {
|
|
35
|
+
this._loaded = t, this.api = i, a.revisions?.forEach((r) => {
|
|
36
|
+
typeof r?.slots?.main == "object" && Object.assign(r, r.slots.main);
|
|
37
|
+
}), this.pageInfo = {
|
|
38
|
+
...s.DEFAULT_PAGE_INFO,
|
|
39
|
+
...a
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
static {
|
|
43
|
+
this.api = i;
|
|
44
|
+
}
|
|
45
|
+
static {
|
|
46
|
+
this.DEFAULT_QUERY_PARAMS = {
|
|
47
|
+
action: "query",
|
|
48
|
+
prop: "info|templates|transcludedin|images|pageimages|revisions",
|
|
49
|
+
inprop: "protection|url|varianttitles",
|
|
50
|
+
intestactions: "edit|move|delete",
|
|
51
|
+
tllimit: "max",
|
|
52
|
+
tilimit: "max",
|
|
53
|
+
imlimit: "max",
|
|
54
|
+
piprop: "thumbnail|name|original",
|
|
55
|
+
pithumbsize: "200",
|
|
56
|
+
pilimit: "max",
|
|
57
|
+
rvprop: "ids|timestamp|flags|comment|user|content",
|
|
58
|
+
rvslots: "main"
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
static {
|
|
62
|
+
this.DEFAULT_PAGE_INFO = {
|
|
63
|
+
pageid: 0,
|
|
64
|
+
ns: 0,
|
|
65
|
+
title: "",
|
|
66
|
+
contentmodel: "wikitext",
|
|
67
|
+
pagelanguage: "",
|
|
68
|
+
pagelanguagehtmlcode: "",
|
|
69
|
+
pagelanguagedir: "ltr",
|
|
70
|
+
touched: (/* @__PURE__ */ new Date()).toISOString(),
|
|
71
|
+
lastrevid: 0,
|
|
72
|
+
length: 0,
|
|
73
|
+
protection: [],
|
|
74
|
+
restrictiontypes: [],
|
|
75
|
+
fullurl: "",
|
|
76
|
+
canonicalurl: "",
|
|
77
|
+
editurl: "",
|
|
78
|
+
varianttitles: {},
|
|
79
|
+
actions: {
|
|
80
|
+
edit: !0,
|
|
81
|
+
move: !1,
|
|
82
|
+
delete: !1
|
|
83
|
+
},
|
|
84
|
+
revisions: [],
|
|
85
|
+
templates: [],
|
|
86
|
+
images: []
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Utils
|
|
90
|
+
static async newFromApi(a) {
|
|
91
|
+
const { data: t } = await this.api.get({
|
|
92
|
+
...s.DEFAULT_QUERY_PARAMS,
|
|
93
|
+
...a
|
|
94
|
+
}), r = t?.query?.pages?.[0];
|
|
95
|
+
if (!r || !r.title)
|
|
96
|
+
throw new Error("Invalid page info", { cause: t });
|
|
97
|
+
return new s(r, !0);
|
|
98
|
+
}
|
|
99
|
+
static newBlankPage(a = {}) {
|
|
100
|
+
return new s(a, !1);
|
|
101
|
+
}
|
|
102
|
+
static async newFromAnyKind(a) {
|
|
103
|
+
const { title: t, pageId: r, revisionId: e } = a || {};
|
|
104
|
+
return e ? this.newFromApi({ revids: parseInt(e.toString(), 10) }) : r ? this.newFromApi({ pageids: parseInt(r.toString(), 10) }) : t ? this.newFromApi({ titles: t.toString() }) : null;
|
|
105
|
+
}
|
|
106
|
+
static async newBatchFromApi(a) {
|
|
107
|
+
const { titles: t, pageids: r, revids: e, ...n } = a || {}, { data: l } = await this.api.post({
|
|
108
|
+
...s.DEFAULT_QUERY_PARAMS,
|
|
109
|
+
titles: t?.join("|") ?? void 0,
|
|
110
|
+
pageids: r?.join("|") ?? void 0,
|
|
111
|
+
revids: e?.join("|") ?? void 0,
|
|
112
|
+
...n
|
|
113
|
+
});
|
|
114
|
+
return l?.query?.pages?.map((c) => new s(c, !0)) || [];
|
|
115
|
+
}
|
|
116
|
+
// Page actions
|
|
117
|
+
async parse(a) {
|
|
118
|
+
return this.api.post({
|
|
119
|
+
action: "parse",
|
|
120
|
+
page: this.pageInfo.title,
|
|
121
|
+
prop: "text|langlinks|categories|links|templates|images|externallinks|sections|revid|displaytitle|iwlinks|properties|parsewarnings",
|
|
122
|
+
...a
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async preview(a, t) {
|
|
126
|
+
return this.parse({
|
|
127
|
+
action: "parse",
|
|
128
|
+
page: void 0,
|
|
129
|
+
title: this.title,
|
|
130
|
+
text: a,
|
|
131
|
+
pst: 1,
|
|
132
|
+
preview: 1,
|
|
133
|
+
disableeditsection: 1,
|
|
134
|
+
disablelimitreport: 1,
|
|
135
|
+
...t
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async edit(a, t) {
|
|
139
|
+
return this.api.postWithEditToken({
|
|
140
|
+
action: "edit",
|
|
141
|
+
title: this.title,
|
|
142
|
+
starttimestamp: this.pageInfo.touched,
|
|
143
|
+
basetimestamp: this.revisions[0]?.timestamp,
|
|
144
|
+
...a,
|
|
145
|
+
...t
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
async createOnly(a, t) {
|
|
149
|
+
return this.edit(a, { createonly: 1, recreate: a.recreate, ...t });
|
|
150
|
+
}
|
|
151
|
+
async delete(a, t) {
|
|
152
|
+
return this.api.postWithEditToken({
|
|
153
|
+
action: "delete",
|
|
154
|
+
title: this.pageInfo.title || void 0,
|
|
155
|
+
pageid: this.pageInfo.pageid || void 0,
|
|
156
|
+
reason: a,
|
|
157
|
+
deletetalk: t?.deletetalk,
|
|
158
|
+
...t
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async moveTo(a, t, r) {
|
|
162
|
+
return this.api.postWithEditToken({
|
|
163
|
+
action: "move",
|
|
164
|
+
from: this.pageInfo.title,
|
|
165
|
+
to: a,
|
|
166
|
+
reason: t,
|
|
167
|
+
movetalk: 1,
|
|
168
|
+
movesubpages: 1,
|
|
169
|
+
...r
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
// === utilities ===
|
|
173
|
+
userCan(a) {
|
|
174
|
+
return !!this.pageInfo?.actions?.[a];
|
|
175
|
+
}
|
|
176
|
+
userCanEdit() {
|
|
177
|
+
return this.userCan("edit");
|
|
178
|
+
}
|
|
179
|
+
async reloadSelfInfo() {
|
|
180
|
+
const a = await s.newFromApi({
|
|
181
|
+
pageids: this.pageInfo.pageid,
|
|
182
|
+
titles: this.pageInfo.title
|
|
183
|
+
}), t = (this.pageInfo.revisions || []).concat(a.revisions || []).sort((r, e) => r.revid - e.revid).reduce(
|
|
184
|
+
(r, e) => (r.find((n) => n.revid === e.revid) || r.push(e), r),
|
|
185
|
+
[]
|
|
186
|
+
);
|
|
187
|
+
return this.pageInfo = a.pageInfo, this.pageInfo.revisions = t, this._loaded = !0, this;
|
|
188
|
+
}
|
|
189
|
+
// === sugar getters ===
|
|
190
|
+
get pageid() {
|
|
191
|
+
return this.pageInfo.pageid;
|
|
192
|
+
}
|
|
193
|
+
get title() {
|
|
194
|
+
return this.pageInfo.title;
|
|
195
|
+
}
|
|
196
|
+
get ns() {
|
|
197
|
+
return this.pageInfo.ns;
|
|
198
|
+
}
|
|
199
|
+
get contentmodel() {
|
|
200
|
+
return this.pageInfo.contentmodel;
|
|
201
|
+
}
|
|
202
|
+
get fullurl() {
|
|
203
|
+
return this.pageInfo.fullurl;
|
|
204
|
+
}
|
|
205
|
+
get canonicalurl() {
|
|
206
|
+
return this.pageInfo.canonicalurl;
|
|
207
|
+
}
|
|
208
|
+
get editurl() {
|
|
209
|
+
return this.pageInfo.editurl;
|
|
210
|
+
}
|
|
211
|
+
get revisions() {
|
|
212
|
+
return this.pageInfo.revisions || [];
|
|
213
|
+
}
|
|
214
|
+
get lastrevid() {
|
|
215
|
+
return this.pageInfo.lastrevid;
|
|
216
|
+
}
|
|
217
|
+
get templates() {
|
|
218
|
+
return this.pageInfo.templates || [];
|
|
219
|
+
}
|
|
220
|
+
get images() {
|
|
221
|
+
return this.pageInfo.images || [];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return s;
|
|
225
|
+
}
|
|
226
|
+
const m = /* @__PURE__ */ new WeakMap(), g = {
|
|
227
|
+
toDBKey: (i) => i.replace(/ /g, "_"),
|
|
228
|
+
toNormalText: (i) => i.replace(/_/g, " "),
|
|
229
|
+
ensureCase: (i, s) => s === "first-letter" ? i.charAt(0).toUpperCase() + i.slice(1) : i
|
|
230
|
+
}, h = {
|
|
231
|
+
/**
|
|
232
|
+
* 标准化特殊页面名称:转换为全小写
|
|
233
|
+
*/
|
|
234
|
+
normalizeSpecialPageName: (i) => i.toLowerCase(),
|
|
235
|
+
/**
|
|
236
|
+
* 构建特殊页面别名索引
|
|
237
|
+
*/
|
|
238
|
+
buildSpecialPageIndex: (i) => {
|
|
239
|
+
const s = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map();
|
|
240
|
+
for (const t of i.specialpagealiases) {
|
|
241
|
+
const r = t.realname;
|
|
242
|
+
s.set(r, r);
|
|
243
|
+
const e = h.normalizeSpecialPageName(r);
|
|
244
|
+
a.set(e, r);
|
|
245
|
+
for (const n of t.aliases) {
|
|
246
|
+
o.set(n, r);
|
|
247
|
+
const l = h.normalizeSpecialPageName(n);
|
|
248
|
+
a.set(l, r);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return { byRealName: s, byAlias: o, byNormalized: a };
|
|
252
|
+
},
|
|
253
|
+
/**
|
|
254
|
+
* 查找特殊页面的真实名称
|
|
255
|
+
*/
|
|
256
|
+
findSpecialPageRealName: (i, s) => {
|
|
257
|
+
const o = i.split("/")[0];
|
|
258
|
+
let a = s.byRealName.get(o) ?? s.byAlias.get(o);
|
|
259
|
+
if (a !== void 0)
|
|
260
|
+
return a;
|
|
261
|
+
const t = h.normalizeSpecialPageName(o);
|
|
262
|
+
return s.byNormalized.get(t) ?? null;
|
|
263
|
+
}
|
|
264
|
+
}, p = {
|
|
265
|
+
/**
|
|
266
|
+
* 标准化命名空间文本:转换为全小写+下划线格式
|
|
267
|
+
*/
|
|
268
|
+
normalizeNamespaceText: (i) => i.replace(/[_\s]+/g, "_").toLowerCase().replace(/^_+|_+$/g, ""),
|
|
269
|
+
buildIndex: (i) => {
|
|
270
|
+
const s = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map();
|
|
271
|
+
for (const [r, e] of Object.entries(i.namespaces)) {
|
|
272
|
+
const n = parseInt(r);
|
|
273
|
+
s.set(e.name, n), o.set(e.canonical ?? "", n);
|
|
274
|
+
const l = p.normalizeNamespaceText(e.name), c = p.normalizeNamespaceText(e.canonical ?? "");
|
|
275
|
+
t.set(l, n), t.set(c, n);
|
|
276
|
+
}
|
|
277
|
+
for (const r of i.namespacealiases) {
|
|
278
|
+
a.set(r.alias, r.id);
|
|
279
|
+
const e = p.normalizeNamespaceText(r.alias);
|
|
280
|
+
t.set(e, r.id);
|
|
281
|
+
}
|
|
282
|
+
return { byName: s, byCanonical: o, byAlias: a, byNormalized: t };
|
|
283
|
+
},
|
|
284
|
+
findNamespaceId: (i, s) => {
|
|
285
|
+
let o = s.byName.get(i) ?? s.byCanonical.get(i) ?? s.byAlias.get(i);
|
|
286
|
+
if (o !== void 0)
|
|
287
|
+
return o;
|
|
288
|
+
const a = p.normalizeNamespaceText(i);
|
|
289
|
+
return s.byNormalized.get(a) ?? null;
|
|
290
|
+
},
|
|
291
|
+
isTalkPage: (i) => i % 2 === 1 && i > 0,
|
|
292
|
+
getDefaultNamespaceInfo: (i) => ({
|
|
293
|
+
id: i,
|
|
294
|
+
name: "",
|
|
295
|
+
canonical: "",
|
|
296
|
+
case: "first-letter",
|
|
297
|
+
content: !1,
|
|
298
|
+
nonincludable: !1,
|
|
299
|
+
subpages: !1
|
|
300
|
+
})
|
|
301
|
+
};
|
|
302
|
+
function N(i) {
|
|
303
|
+
const s = m.get(i);
|
|
304
|
+
if (s)
|
|
305
|
+
return s;
|
|
306
|
+
const o = p.buildIndex(i), a = h.buildSpecialPageIndex(i);
|
|
307
|
+
class t {
|
|
308
|
+
constructor(e, n) {
|
|
309
|
+
if (this.newTitle = t.create.bind(t), this.toText = this.getPrefixedText.bind(this), this.toString = this.getPrefixedDBKey.bind(this), this.#t = e || "", this.#e = n ?? 0, n === void 0)
|
|
310
|
+
this.fixNSByTitle();
|
|
311
|
+
else {
|
|
312
|
+
const l = this.parseTitlePrefix(this.#t);
|
|
313
|
+
l && l.namespaceId === this.#e && (this.#t = l.mainTitle);
|
|
314
|
+
}
|
|
315
|
+
if (this.getMainText() === "")
|
|
316
|
+
throw new Error("Invalid title");
|
|
317
|
+
}
|
|
318
|
+
static {
|
|
319
|
+
this._meta = i;
|
|
320
|
+
}
|
|
321
|
+
static {
|
|
322
|
+
this._namespaceIndex = o;
|
|
323
|
+
}
|
|
324
|
+
static {
|
|
325
|
+
this._specialPageIndex = a;
|
|
326
|
+
}
|
|
327
|
+
/** 缓存的 main title,不包含命名空间前缀,大小写和空格状态不确定 */
|
|
328
|
+
#t;
|
|
329
|
+
/** 缓存的 namespace ID */
|
|
330
|
+
#e;
|
|
331
|
+
static create(e, n) {
|
|
332
|
+
return new t(e, n);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* 解析标题前缀,返回匹配到的命名空间 ID 与剥离后的主标题
|
|
336
|
+
*/
|
|
337
|
+
parseTitlePrefix(e) {
|
|
338
|
+
const n = e.indexOf(":");
|
|
339
|
+
if (n <= 0)
|
|
340
|
+
return null;
|
|
341
|
+
const l = e.substring(0, n), c = e.substring(n + 1), u = p.findNamespaceId(
|
|
342
|
+
l,
|
|
343
|
+
t._namespaceIndex
|
|
344
|
+
);
|
|
345
|
+
return u === null ? null : { namespaceId: u, mainTitle: c };
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* 如果标题包含可识别命名空间,则采用该命名空间并剥离前缀
|
|
349
|
+
*/
|
|
350
|
+
adoptNamespaceFromTitle() {
|
|
351
|
+
const e = this.parseTitlePrefix(this.#t);
|
|
352
|
+
e && (this.#t = e.mainTitle, this.#e = e.namespaceId);
|
|
353
|
+
}
|
|
354
|
+
fixNSByTitle() {
|
|
355
|
+
const e = this.#t.indexOf(":");
|
|
356
|
+
if (e !== -1) {
|
|
357
|
+
if (e === 0) {
|
|
358
|
+
this.#t = this.#t.substring(1);
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
this.adoptNamespaceFromTitle();
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
getNamespaceInfo() {
|
|
365
|
+
return t._meta.namespaces[this.#e] ?? p.getDefaultNamespaceInfo(this.#e);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* 若为特殊页面,返回解析后的真实主名(含子页面);否则返回 null
|
|
369
|
+
*/
|
|
370
|
+
resolveSpecialFullTitle() {
|
|
371
|
+
if (this.#e !== -1) return null;
|
|
372
|
+
const e = h.findSpecialPageRealName(
|
|
373
|
+
this.#t,
|
|
374
|
+
t._specialPageIndex
|
|
375
|
+
);
|
|
376
|
+
if (!e) return null;
|
|
377
|
+
const n = this.#t.includes("/") ? this.#t.substring(this.#t.indexOf("/")) : "";
|
|
378
|
+
return e + n;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* 将主标题格式化为输出内容(文本或 DBKey),并做大小写规范化
|
|
382
|
+
*/
|
|
383
|
+
formatMainForOutput(e) {
|
|
384
|
+
const n = this.getNamespaceInfo(), c = this.resolveSpecialFullTitle() ?? this.#t, u = e === "db" ? g.toDBKey(c) : g.toNormalText(c);
|
|
385
|
+
return g.ensureCase(u, n.case);
|
|
386
|
+
}
|
|
387
|
+
getMainDBKey() {
|
|
388
|
+
return this.formatMainForOutput("db");
|
|
389
|
+
}
|
|
390
|
+
getMainText() {
|
|
391
|
+
return this.formatMainForOutput("text");
|
|
392
|
+
}
|
|
393
|
+
getMainRootText() {
|
|
394
|
+
return this.getMainText().split("/")[0];
|
|
395
|
+
}
|
|
396
|
+
getPrefixedDBKey() {
|
|
397
|
+
return this.#e === 0 ? this.getMainDBKey() : `${this.getNamespaceDBKey()}:${this.getMainDBKey()}`;
|
|
398
|
+
}
|
|
399
|
+
getPrefixedText() {
|
|
400
|
+
return this.#e === 0 ? this.getMainText() : `${this.getNamespaceText()}:${this.getMainText()}`;
|
|
401
|
+
}
|
|
402
|
+
getNamespaceId() {
|
|
403
|
+
return this.#e;
|
|
404
|
+
}
|
|
405
|
+
getNamespaceText() {
|
|
406
|
+
return this.getNamespaceInfo().name ?? "";
|
|
407
|
+
}
|
|
408
|
+
getNamespaceDBKey() {
|
|
409
|
+
const e = this.getNamespaceInfo();
|
|
410
|
+
return g.ensureCase(g.toDBKey(this.getNamespaceText()), e.case);
|
|
411
|
+
}
|
|
412
|
+
getSubjectPage() {
|
|
413
|
+
if (p.isTalkPage(this.#e)) {
|
|
414
|
+
const e = this.#e - 1;
|
|
415
|
+
return new t(this.#t, e);
|
|
416
|
+
}
|
|
417
|
+
return this;
|
|
418
|
+
}
|
|
419
|
+
getTalkPage() {
|
|
420
|
+
if (p.isTalkPage(this.#e))
|
|
421
|
+
return this;
|
|
422
|
+
if (this.#e < 0)
|
|
423
|
+
return null;
|
|
424
|
+
const e = this.#e + 1;
|
|
425
|
+
return t._meta.namespaces[e.toString()] ? new t(this.#t, e) : null;
|
|
426
|
+
}
|
|
427
|
+
getURL(e) {
|
|
428
|
+
const n = this.getPrefixedDBKey();
|
|
429
|
+
return this.buildArticleURL(n, e);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* 构建文章 URL 并附加查询参数
|
|
433
|
+
*/
|
|
434
|
+
buildArticleURL(e, n) {
|
|
435
|
+
const c = t._meta.general.articlepath.replace("$1", e), u = new URL(c, location.origin);
|
|
436
|
+
return n && (n instanceof URLSearchParams ? n : new URLSearchParams(n)).forEach((d, f) => {
|
|
437
|
+
u.searchParams.set(f, d);
|
|
438
|
+
}), u;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* 设置标题,重置当前实例的 dbkey 和 ns
|
|
442
|
+
* 行为:
|
|
443
|
+
* - 如果标题包含可识别的命名空间前缀,则以该前缀为准更新 ns,并移除前缀
|
|
444
|
+
* - 如果标题前缀与当前 ns 相同,则仅移除冗余前缀并保留当前 ns
|
|
445
|
+
* - 否则(无前缀),重置为主命名空间
|
|
446
|
+
*/
|
|
447
|
+
setTitle(e) {
|
|
448
|
+
this.#t = e;
|
|
449
|
+
const n = this.#e;
|
|
450
|
+
this.#e = 0;
|
|
451
|
+
const l = this.parseTitlePrefix(this.#t);
|
|
452
|
+
return l ? (n !== 0 && l.namespaceId === n ? (this.#t = l.mainTitle, this.#e = n) : (this.#t = l.mainTitle, this.#e = l.namespaceId), this) : this;
|
|
453
|
+
}
|
|
454
|
+
setMainText(e) {
|
|
455
|
+
return this.#t = e, this;
|
|
456
|
+
}
|
|
457
|
+
setNamespaceText(e) {
|
|
458
|
+
const n = p.findNamespaceId(e, t._namespaceIndex);
|
|
459
|
+
return n !== null && (this.#e = n), this;
|
|
460
|
+
}
|
|
461
|
+
setNamespaceId(e) {
|
|
462
|
+
return this.#e = e, this;
|
|
463
|
+
}
|
|
464
|
+
equals(e) {
|
|
465
|
+
return typeof e == "string" && (e = new t(e)), this.getPrefixedDBKey() === e.getPrefixedDBKey();
|
|
466
|
+
}
|
|
467
|
+
isSpecial(e) {
|
|
468
|
+
if (this.#e !== -1)
|
|
469
|
+
return !1;
|
|
470
|
+
const n = new t(e, -1);
|
|
471
|
+
return this.getMainRootText() === n.getMainRootText();
|
|
472
|
+
}
|
|
473
|
+
toJSON() {
|
|
474
|
+
return {
|
|
475
|
+
ns: this.#e,
|
|
476
|
+
text: this.getMainText(),
|
|
477
|
+
title: this.getPrefixedText(),
|
|
478
|
+
url: this.getURL().toString(),
|
|
479
|
+
isSpecial: this.#e < 0
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return m.set(i, t), t;
|
|
484
|
+
}
|
|
485
|
+
export {
|
|
486
|
+
I as M,
|
|
487
|
+
N as a,
|
|
488
|
+
v as c,
|
|
489
|
+
x as u
|
|
490
|
+
};
|
|
491
|
+
//# sourceMappingURL=index-BjDTD66_.js.map
|