@inpageedit/core 0.12.1 → 0.13.0-alpha.1
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/LICENSE +20 -20
- package/dist/BasePlugin-Bf2UuIHF.js +64 -0
- package/dist/BasePlugin-Bf2UuIHF.js.map +1 -0
- package/dist/IconQuickEdit-CMCQncyj.js.map +1 -1
- package/dist/InputBox-nQKtiWtZ.js.map +1 -1
- package/dist/{PluginPrefSync-Ziogy_o-.js → PluginPrefSync-Dn1Xsiqz.js} +6 -4
- package/dist/PluginPrefSync-Dn1Xsiqz.js.map +1 -0
- package/dist/{PluginStoreApp-Bnvyl-Oc.js → PluginStoreApp-CpOLArL7.js} +2 -2
- package/dist/{PluginStoreApp-Bnvyl-Oc.js.map → PluginStoreApp-CpOLArL7.js.map} +1 -1
- package/dist/Preferences-DS4-CFWe.js.map +1 -1
- package/dist/WatchlistAction-BbNAyryN.js +5 -0
- package/dist/WatchlistAction-BbNAyryN.js.map +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/endpoints-DgyuoRZd.js +1507 -0
- package/dist/endpoints-DgyuoRZd.js.map +1 -0
- package/dist/{index-BvuaLEFc.js → index-2RfILgXm.js} +11 -10
- package/dist/{index-BvuaLEFc.js.map → index-2RfILgXm.js.map} +1 -1
- package/dist/{index-eARjMi7f.js → index-B7c6jL9x.js} +25 -23
- package/dist/index-B7c6jL9x.js.map +1 -0
- package/dist/{index-zHTGCjfF.js → index-BJ7_Q1mB.js} +8 -7
- package/dist/{index-zHTGCjfF.js.map → index-BJ7_Q1mB.js.map} +1 -1
- package/dist/{index-Dnmv-xDn.js → index-BNh95-x2.js} +37 -49
- package/dist/index-BNh95-x2.js.map +1 -0
- package/dist/{index-B3FUDhxl.js → index-BQ-cHWkJ.js} +15 -16
- package/dist/{index-B3FUDhxl.js.map → index-BQ-cHWkJ.js.map} +1 -1
- package/dist/{index-B3YJdjxo.js → index-BwdWyHLe.js} +77 -76
- package/dist/{index-B3YJdjxo.js.map → index-BwdWyHLe.js.map} +1 -1
- package/dist/{index-Ccr3YhkP.js → index-CCRMmnwk.js} +10 -9
- package/dist/index-CCRMmnwk.js.map +1 -0
- package/dist/index-CG38LlAh.js.map +1 -1
- package/dist/index-CM_6yF2v.js.map +1 -1
- package/dist/index-C_BIsubQ.js +3744 -0
- package/dist/index-C_BIsubQ.js.map +1 -0
- package/dist/{index-Bd70aDMT.js → index-CnIpUF9x.js} +7 -6
- package/dist/{index-Bd70aDMT.js.map → index-CnIpUF9x.js.map} +1 -1
- package/dist/{index-D5zX93bn.js → index-CyG7_IYz.js} +47 -45
- package/dist/index-CyG7_IYz.js.map +1 -0
- package/dist/index-DD5CVCfD.js.map +1 -1
- package/dist/{index-BRjEc8b8.js → index-eSlbrNqF.js} +6 -6
- package/dist/{index-BRjEc8b8.js.map → index-eSlbrNqF.js.map} +1 -1
- package/dist/index.d.ts +1742 -31
- package/dist/index.js +73 -9
- package/dist/index.js.map +1 -1
- package/dist/makeCallable-LDU0xZMJ.js.map +1 -1
- package/dist/models/index.js +486 -0
- package/dist/models/index.js.map +1 -0
- package/dist/noop-ClDc6zv4.js.map +1 -1
- package/dist/plugins/index.js +23 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/services/index.js +16 -0
- package/dist/services/index.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/vueHooks-l04s8cIl.js.map +1 -1
- package/lib/index.umd.js +10 -10
- package/lib/index.umd.js.map +1 -1
- package/package.json +23 -30
- package/dist/InPageEdit.d.ts +0 -42
- package/dist/PluginPrefSync-Ziogy_o-.js.map +0 -1
- package/dist/__test__/utils/constants.d.ts +0 -3
- package/dist/components/ActionButton.d.ts +0 -6
- package/dist/components/CheckBox.d.ts +0 -10
- package/dist/components/Icon/IconEdit.d.ts +0 -2
- package/dist/components/Icon/IconQuickEdit.d.ts +0 -2
- package/dist/components/InputBox.d.ts +0 -11
- package/dist/components/MBox/index.d.ts +0 -14
- package/dist/components/MwUserLinks.d.ts +0 -6
- package/dist/components/ProgressBar/index.d.ts +0 -7
- package/dist/components/RadioBox.d.ts +0 -10
- package/dist/components/TabView/index.d.ts +0 -19
- package/dist/components/TwinSwapInput/index.d.ts +0 -19
- package/dist/components/index.d.ts +0 -8
- package/dist/components/utils.d.ts +0 -4
- package/dist/constants/endpoints.d.ts +0 -8
- package/dist/decorators/Preferences.d.ts +0 -35
- package/dist/index-Ccr3YhkP.js.map +0 -1
- package/dist/index-D5zX93bn.js.map +0 -1
- package/dist/index-DgQNTfPR.js +0 -5829
- package/dist/index-DgQNTfPR.js.map +0 -1
- package/dist/index-Dnmv-xDn.js.map +0 -1
- package/dist/index-eARjMi7f.js.map +0 -1
- package/dist/models/MemoryStorage.d.ts +0 -10
- package/dist/models/WikiPage/index.d.ts +0 -76
- package/dist/models/WikiPage/types/PageInfo.d.ts +0 -58
- package/dist/models/WikiPage/types/PageParseData.d.ts +0 -17
- package/dist/models/WikiPage/types/WatchlistAction.d.ts +0 -6
- package/dist/models/WikiTitle/index.d.ts +0 -89
- package/dist/models/WikiTitle/index.spec.d.ts +0 -1
- package/dist/plugins/BasePlugin.d.ts +0 -25
- package/dist/plugins/_debug/index.d.ts +0 -8
- package/dist/plugins/analytics/index.d.ts +0 -41
- package/dist/plugins/in-article-links/index.d.ts +0 -44
- package/dist/plugins/plugin-store/index.d.ts +0 -56
- package/dist/plugins/plugin-store/schema.d.ts +0 -41
- package/dist/plugins/preferences-ui/PluginPrefSync.d.ts +0 -28
- package/dist/plugins/preferences-ui/index.d.ts +0 -48
- package/dist/plugins/quick-diff/components/DiffTable.d.ts +0 -23
- package/dist/plugins/quick-diff/index.d.ts +0 -85
- package/dist/plugins/quick-edit/index.d.ts +0 -79
- package/dist/plugins/quick-move/index.d.ts +0 -47
- package/dist/plugins/quick-preview/index.d.ts +0 -37
- package/dist/plugins/quick-redirect/index.d.ts +0 -48
- package/dist/plugins/toolbox/index.d.ts +0 -65
- package/dist/polyfills/Promise.withResolvers.d.ts +0 -5
- package/dist/polyfills/index.d.ts +0 -0
- package/dist/services/ApiService.d.ts +0 -14
- package/dist/services/CurrentPageService.d.ts +0 -28
- package/dist/services/ModalService.d.ts +0 -27
- package/dist/services/PreferencesService.d.ts +0 -94
- package/dist/services/ResourceLoaderService.d.ts +0 -17
- package/dist/services/WikiMetadataService.d.ts +0 -108
- package/dist/services/WikiPageService.d.ts +0 -20
- package/dist/services/WikiTitleService.d.ts +0 -70
- package/dist/services/storage/index.d.ts +0 -40
- package/dist/services/storage/managers/IDBStorageManager.d.ts +0 -28
- package/dist/services/storage/managers/LocalStorageManager.d.ts +0 -27
- package/dist/types/WikiMetadata.d.ts +0 -131
- package/dist/utils/computeable.d.ts +0 -2
- package/dist/utils/defineAsyncPlugin.d.ts +0 -2
- package/dist/utils/interpolate.d.ts +0 -20
- package/dist/utils/interpolate.spec.d.ts +0 -1
- package/dist/utils/makeCallable.d.ts +0 -3
- package/dist/utils/noop.d.ts +0 -1
- package/dist/utils/sleep.d.ts +0 -1
- package/dist/utils/string.d.ts +0 -7
- package/dist/utils/url.d.ts +0 -24
- package/dist/utils/vueHooks.d.ts +0 -6
- package/dist/utils/vueReactivity.d.ts +0 -2
|
@@ -1,57 +1,58 @@
|
|
|
1
|
-
import { j as l, F as q, P as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { j as l, F as q, P as S } from "./index-CM_6yF2v.js";
|
|
2
|
+
import { R as j } from "./Preferences-DS4-CFWe.js";
|
|
3
|
+
import { B as E } from "./BasePlugin-Bf2UuIHF.js";
|
|
4
4
|
import { m as C } from "./makeCallable-LDU0xZMJ.js";
|
|
5
|
-
|
|
5
|
+
import { I as F, S as f } from "./endpoints-DgyuoRZd.js";
|
|
6
|
+
var I = Object.create, w = Object.defineProperty, O = Object.getOwnPropertyDescriptor, P = (t, i) => (i = Symbol[t]) ? i : Symbol.for("Symbol." + t), x = (t) => {
|
|
6
7
|
throw TypeError(t);
|
|
7
|
-
},
|
|
8
|
-
for (var e = 0,
|
|
8
|
+
}, Q = (t, i, r) => i in t ? w(t, i, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[i] = r, T = (t, i) => w(t, "name", { value: i, configurable: !0 }), z = (t) => [, , , I(t?.[P("metadata")] ?? null)], B = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], g = (t) => t !== void 0 && typeof t != "function" ? x("Function expected") : t, D = (t, i, r, c, e) => ({ kind: B[t], name: i, metadata: c, addInitializer: (a) => r._ ? x("Already initialized") : e.push(g(a || null)) }), N = (t, i) => Q(i, P("metadata"), t[3]), M = (t, i, r, c) => {
|
|
9
|
+
for (var e = 0, a = t[i >> 1], s = a && a.length; e < s; e++) a[e].call(r);
|
|
9
10
|
return c;
|
|
10
|
-
}, R = (t, i, r, c, e,
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
for (var
|
|
14
|
-
u =
|
|
15
|
-
return N(t, e),
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"quickPreview.keyshortcut":
|
|
11
|
+
}, R = (t, i, r, c, e, a) => {
|
|
12
|
+
var s, o, u, n = i & 7, h = !1, k = 0, y = t[k] || (t[k] = []), p = n && (e = e.prototype, n < 5 && (n > 3 || !h) && O(e, r));
|
|
13
|
+
T(e, r);
|
|
14
|
+
for (var v = c.length - 1; v >= 0; v--)
|
|
15
|
+
u = D(n, r, o = {}, t[3], y), s = (0, c[v])(e, u), o._ = 1, g(s) && (e = s);
|
|
16
|
+
return N(t, e), p && w(e, r, p), h ? n ^ 4 ? a : p : e;
|
|
17
|
+
}, m, _, b;
|
|
18
|
+
m = [F(["api", "wikiPage", "modal", "preferences"]), j(
|
|
19
|
+
f.object({
|
|
20
|
+
"quickPreview.keyshortcut": f.string().default("ctrl-p").description("Key shortcut to open quick preview in quick edit modal")
|
|
20
21
|
}).extra("category", "editor").description("Quick preview options")
|
|
21
22
|
)];
|
|
22
|
-
class
|
|
23
|
+
class d extends (b = E) {
|
|
23
24
|
constructor(i) {
|
|
24
25
|
super(i, {}, "quickPreview"), this.ctx = i, this.ctx.set("quickPreview", C(this, "previewWikitext"));
|
|
25
26
|
}
|
|
26
27
|
start() {
|
|
27
|
-
this.ctx.on("quick-edit/wiki-page", this.injectQuickEdit.bind(this))
|
|
28
|
+
this.ctx.on("quick-edit/wiki-page", this.injectQuickEdit.bind(this));
|
|
28
29
|
}
|
|
29
30
|
stop() {
|
|
30
31
|
}
|
|
31
|
-
previewWikitext(i, r, c, e,
|
|
32
|
+
previewWikitext(i, r, c, e, a) {
|
|
32
33
|
return c ||= this.ctx.wikiPage.newBlankPage({
|
|
33
34
|
title: "API"
|
|
34
35
|
}), (!e || e.isDestroyed) && (e = this.ctx.modal.createObject({
|
|
35
36
|
className: "in-page-edit ipe-quickPreview",
|
|
36
37
|
sizeClass: "large",
|
|
37
38
|
center: !1,
|
|
38
|
-
...
|
|
39
|
-
}).init()), e.show(), e.setTitle("Preview - Loading..."), e.setContent(/* @__PURE__ */ l(
|
|
39
|
+
...a
|
|
40
|
+
}).init()), e.show(), e.setTitle("Preview - Loading..."), e.setContent(/* @__PURE__ */ l(S, {})), e.bringToFront(), this.ctx.emit("quick-preview/show-modal", {
|
|
40
41
|
ctx: this.ctx,
|
|
41
42
|
text: i,
|
|
42
43
|
modal: e,
|
|
43
44
|
wikiPage: c
|
|
44
|
-
}), c.preview(i, r).then((
|
|
45
|
+
}), c.preview(i, r).then((s) => {
|
|
45
46
|
const {
|
|
46
47
|
data: { parse: o }
|
|
47
|
-
} =
|
|
48
|
+
} = s;
|
|
48
49
|
e.setTitle(`Preview - ${o.title}`);
|
|
49
50
|
let u = null;
|
|
50
51
|
e.setContent(
|
|
51
52
|
/* @__PURE__ */ l("section", { children: /* @__PURE__ */ l(
|
|
52
53
|
"div",
|
|
53
54
|
{
|
|
54
|
-
ref: (
|
|
55
|
+
ref: (n) => u = n,
|
|
55
56
|
className: "mw-parser-output",
|
|
56
57
|
innerHTML: o.text
|
|
57
58
|
}
|
|
@@ -63,11 +64,11 @@ class v extends (m = S) {
|
|
|
63
64
|
text: i,
|
|
64
65
|
parseData: o
|
|
65
66
|
});
|
|
66
|
-
}).catch((
|
|
67
|
+
}).catch((s) => {
|
|
67
68
|
e.setTitle("Preview - Failed"), e.setContent(
|
|
68
69
|
/* @__PURE__ */ l(q, { children: [
|
|
69
70
|
/* @__PURE__ */ l("p", { children: "Failed to preview" }),
|
|
70
|
-
/* @__PURE__ */ l("p", { children:
|
|
71
|
+
/* @__PURE__ */ l("p", { children: s instanceof Error ? s.message : String(s) })
|
|
71
72
|
] })
|
|
72
73
|
);
|
|
73
74
|
}), e;
|
|
@@ -81,14 +82,14 @@ class v extends (m = S) {
|
|
|
81
82
|
className: "btn btn-secondary",
|
|
82
83
|
keyPress: await this.ctx.preferences.get("quickPreview.keyshortcut.quickEdit") || void 0,
|
|
83
84
|
method: () => {
|
|
84
|
-
let
|
|
85
|
+
let a = r.get$content().querySelector('textarea[name="text"]')?.value || "";
|
|
85
86
|
if (i.section === "new") {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
${
|
|
87
|
+
const s = r.get$content().querySelector('input[name="summary"]')?.value;
|
|
88
|
+
s && (a = `==${s}==
|
|
89
|
+
${a}`);
|
|
89
90
|
}
|
|
90
91
|
e = this.previewWikitext(
|
|
91
|
-
|
|
92
|
+
a,
|
|
92
93
|
void 0,
|
|
93
94
|
c,
|
|
94
95
|
e,
|
|
@@ -104,24 +105,11 @@ ${s}`);
|
|
|
104
105
|
e?.destroy(), e = void 0;
|
|
105
106
|
});
|
|
106
107
|
}
|
|
107
|
-
injectQuickDelete({ ctx: i, modal: r, wikiPage: c }) {
|
|
108
|
-
r.addButton(
|
|
109
|
-
{
|
|
110
|
-
label: "Preview",
|
|
111
|
-
side: "left",
|
|
112
|
-
className: "btn btn-secondary",
|
|
113
|
-
method: () => {
|
|
114
|
-
this.logger.warn("To be implemented: preview wikitext for quick delete");
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
2
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
108
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
M(
|
|
109
|
+
_ = z(b);
|
|
110
|
+
d = R(_, 0, "PluginQuickPreview", m, d);
|
|
111
|
+
M(_, 1, d);
|
|
124
112
|
export {
|
|
125
|
-
|
|
113
|
+
d as PluginQuickPreview
|
|
126
114
|
};
|
|
127
|
-
//# sourceMappingURL=index-
|
|
115
|
+
//# sourceMappingURL=index-BNh95-x2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BNh95-x2.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 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(`Preview - ${parse.title}`)\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 window.mw?.hook('wikipage.content').fire($(outputRef!))\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 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":";;;;;;;;;;;;;;;;GAAAA,GAAAC,GAAAC;AAkCAF,IAAA,CAACG,EAAO,CAAC,OAAO,YAAY,SAAS,aAAa,CAAC,GAClDC;AAAA,EACCC,EAAO,OAAO;AAAA,IACZ,4BAA4BA,EAAO,OAAA,EAChC,QAAQ,QAAQ,EAChB,YAAY,wDAAwD;AAAA,EAAA,CACxE,EACE,MAAM,YAAY,QAAQ,EAC1B,YAAY,uBAAuB;AACxC,CAAA;AACO,MAAMC,WAA2BJ,IAAAK,GAAW;AAAA,EACjD,YAAmBC,GAAiB;AAClC,UAAMA,GAAK,CAAA,GAAI,cAAc,GADZ,KAAA,MAAAA,GAEjB,KAAK,IAAI,IAAI,gBAAgBC,EAAa,MAAM,iBAAiB,CAAC;AAAA,EACpE;AAAA,EAEU,QAA8B;AACtC,SAAK,IAAI,GAAG,wBAAwB,KAAK,gBAAgB,KAAK,IAAI,CAAC;AAAA,EACrE;AAAA,EAEU,OAA6B;AAAA,EAAC;AAAA,EAExC,gBACEC,GACAC,GACAC,GACAC,GACAC,GACA;AACA,WAAAF,MAAa,KAAK,IAAI,SAAS,aAAa;AAAA,MAC1C,OAAO;AAAA,IAAA,CACR,IAEG,CAACC,KAASA,EAAM,iBAClBA,IAAQ,KAAK,IAAI,MACd,aAAa;AAAA,MACZ,WAAW;AAAA,MACX,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,GAAGC;AAAA,IAAA,CACJ,EACA,KAAA,IAGLD,EAAM,KAAA,GACNA,EAAM,SAAS,sBAAsB,GACrCA,EAAM,WAAW,gBAAAE,EAACC,GAAA,CAAA,CAAY,CAAE,GAChCH,EAAM,aAAA,GACN,KAAK,IAAI,KAAK,4BAA4B;AAAA,MACxC,KAAK,KAAK;AAAA,MACV,MAAAH;AAAA,MACA,OAAAG;AAAA,MACA,UAAAD;AAAA,IAAA,CACD,GAEDA,EACG,QAAQF,GAAMC,CAAM,EACpB,KAAK,CAACM,MAAQ;AACb,YAAM;AAAA,QACJ,MAAM,EAAE,OAAAC,EAAA;AAAA,MAAM,IACZD;AACJ,MAAAJ,EAAM,SAAS,aAAaK,EAAM,KAAK,EAAE;AACzC,UAAIC,IAAgC;AACpC,MAAAN,EAAM;AAAA,0BAED,WAAA,EACC,UAAA,gBAAAE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK,CAACK,MAAQD,IAAYC;AAAA,YAC1B,WAAU;AAAA,YACV,WAAWF,EAAM;AAAA,UAAA;AAAA,QAAA,EAClB,CACH;AAAA,MAAA,GAGJ,OAAO,IAAI,KAAK,kBAAkB,EAAE,KAAK,EAAEC,CAAU,CAAC,GACtD,KAAK,IAAI,KAAK,wBAAwB;AAAA,QACpC,KAAK,KAAK;AAAA,QACV,OAAAN;AAAA,QACA,UAAAD;AAAA,QACA,MAAAF;AAAA,QACA,WAAWQ;AAAA,MAAA,CACZ;AAAA,IACH,CAAC,EACA,MAAM,CAACG,MAAU;AAChB,MAAAR,EAAM,SAAS,kBAAkB,GACjCA,EAAM;AAAA,QACJS,gBAAAA,EAAAC,GAAA,EACE,UAAA;AAAA,UAAA,gBAAAR,EAAC,OAAE,UAAA,oBAAA,CAAiB;AAAA,UACpB,gBAAAA,EAAC,OAAG,UAAAM,aAAiB,QAAQA,EAAM,UAAU,OAAOA,CAAK,EAAA,CAAE;AAAA,QAAA,EAAA,CAC7D;AAAA,MAAA;AAAA,IAEJ,CAAC,GAEIR;AAAA,EACT;AAAA,EAEA,MAAc,gBAAgB,EAAE,SAAAW,GAAS,OAAAX,GAAO,UAAAD,KAAmC;AACjF,QAAIa;AACJ,IAAAZ,EAAM;AAAA,MACJ;AAAA,QACE,OAAO;AAAA,QACP,MAAM;AAAA,QACN,WAAW;AAAA,QACX,UACG,MAAM,KAAK,IAAI,YAAY,IAAI,oCAAoC,KAAM;AAAA,QAC5E,QAAQ,MAAM;AACZ,cAAIa,IACDb,EAAM,YAAA,EAAc,cAAmC,uBAAuB,GAC3E,SAAoB;AAC1B,cAAIW,EAAQ,YAAY,OAAO;AAC7B,kBAAMG,IAAQd,EACX,YAAA,EACA,cAAgC,uBAAuB,GAAG;AAC7D,YAAIc,MACFD,IAAW,KAAKC,CAAK;AAAA,EAAOD,CAAQ;AAAA,UAExC;AAEA,UAAAD,IAAqB,KAAK;AAAA,YACxBC;AAAA,YACA;AAAA,YACAd;AAAA,YACAa;AAAA,YACA;AAAA,cACE,UAAU;AAAA,cACV,WAAW;AAAA,YAAA;AAAA,UACb;AAAA,QAEJ;AAAA,MAAA;AAAA,MAEF;AAAA,IAAA,GAEFZ,EAAM,GAAGA,EAAM,MAAM,OAAO,MAAM;AAChC,MAAAY,GAAoB,QAAA,GACpBA,IAAqB;AAAA,IACvB,CAAC;AAAA,EACH;AACF;AA/HOxB,IAAA2B,EAAA1B,CAAA;AAAMI,IAANuB,8BAVP7B,GAUaM,CAAA;AAANwB,EAAA7B,GAAA,GAAMK,CAAA;"}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { j as n } from "./index-CM_6yF2v.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { S as p, E as b, p as I, I as x } from "./endpoints-DgyuoRZd.js";
|
|
3
|
+
import { B as P, p as U } from "./BasePlugin-Bf2UuIHF.js";
|
|
4
|
+
var B = Object.create, f = Object.defineProperty, q = Object.getOwnPropertyDescriptor, v = (i, e) => (e = Symbol[i]) ? e : Symbol.for("Symbol." + i), w = (i) => {
|
|
4
5
|
throw TypeError(i);
|
|
5
|
-
}, L = (i, e, t) => e in 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 }), T = (i) => [, , , B(i?.[v("metadata")] ?? null)], D = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], k = (i) => i !== void 0 && typeof i != "function" ? w("Function expected") : i, O = (i, e, t, a, s) => ({ kind: D[i], name: e, metadata: a, addInitializer: (r) => t._ ? w("Already initialized") : s.push(k(r || null)) }), j = (i, e) => L(e, v("metadata"), i[3]), C = (i, e, t, a) => {
|
|
6
7
|
for (var s = 0, r = i[e >> 1], c = r && r.length; s < c; s++) r[s].call(t);
|
|
7
8
|
return a;
|
|
8
9
|
}, M = (i, e, t, a, s, r) => {
|
|
9
|
-
var c, d, h, o = e & 7, l = !1, y = 0, A = i[y] || (i[y] = []), u = o && (s = s.prototype, o < 5 && (o > 3 || !l) &&
|
|
10
|
+
var c, d, h, o = e & 7, l = !1, y = 0, A = i[y] || (i[y] = []), u = o && (s = s.prototype, o < 5 && (o > 3 || !l) && q(s, t));
|
|
10
11
|
N(s, t);
|
|
11
12
|
for (var g = a.length - 1; g >= 0; g--)
|
|
12
13
|
h = O(o, t, d = {}, i[3], A), c = (0, a[g])(s, h), d._ = 1, k(c) && (s = c);
|
|
13
|
-
return j(i, s), u &&
|
|
14
|
-
}, E,
|
|
15
|
-
E = [
|
|
16
|
-
class m extends (S =
|
|
14
|
+
return j(i, s), u && f(s, t, u), l ? o ^ 4 ? r : u : s;
|
|
15
|
+
}, E, _, S;
|
|
16
|
+
E = [x(["wiki", "preferences"])];
|
|
17
|
+
class m extends (S = P) {
|
|
17
18
|
// 1分钟
|
|
18
19
|
constructor(e) {
|
|
19
20
|
super(e, {}, "analytics"), this.ctx = e, this._usages = [], this._timer = null, this.MAX_QUEUE_SIZE = 50, this.INTERVAL_MS = 60 * 1e3, this._setupTimer(), this._registerUnloadHandler(), this._showConfirmNotify(), this._initPluginListeners(), e.set("analytics", this);
|
|
@@ -120,9 +121,7 @@ class m extends (S = I) {
|
|
|
120
121
|
_initPluginListeners() {
|
|
121
122
|
const e = this.ctx;
|
|
122
123
|
e.on("in-article-links/anchor-clicked", (t) => {
|
|
123
|
-
this.addEvent("in-article-links",
|
|
124
|
-
}), e.on("quick-delete/submit", (t) => {
|
|
125
|
-
this.addEvent("quick-delete", "submit", t.wikiPage.title);
|
|
124
|
+
this.addEvent("in-article-links", U(t.action));
|
|
126
125
|
}), e.on("quick-diff/loaded", (t) => {
|
|
127
126
|
this.addEvent("quick-diff", "loaded", t.compare.fromtitle);
|
|
128
127
|
}), e.on("quick-redirect/submit", (t) => {
|
|
@@ -165,7 +164,7 @@ class m extends (S = I) {
|
|
|
165
164
|
return this.logger.debug("Beacon sent successfully", a), !0;
|
|
166
165
|
{
|
|
167
166
|
this.logger.debug("Beacon failed, sending via XMLHttpRequest");
|
|
168
|
-
const { promise: d, resolve: h, reject: o } =
|
|
167
|
+
const { promise: d, resolve: h, reject: o } = I();
|
|
169
168
|
try {
|
|
170
169
|
const l = new XMLHttpRequest();
|
|
171
170
|
l.open("POST", r, !0), l.setRequestHeader("Content-Type", "application/json"), l.send(s), l.onload = () => {
|
|
@@ -186,10 +185,10 @@ class m extends (S = I) {
|
|
|
186
185
|
this._timer !== null && (clearInterval(this._timer), this._timer = null), this._usages.length > 0 && this.sendBeacon();
|
|
187
186
|
}
|
|
188
187
|
}
|
|
189
|
-
|
|
190
|
-
m = M(
|
|
191
|
-
C(
|
|
188
|
+
_ = T(S);
|
|
189
|
+
m = M(_, 0, "PluginAnalytics", E, m);
|
|
190
|
+
C(_, 1, m);
|
|
192
191
|
export {
|
|
193
192
|
m as PluginAnalytics
|
|
194
193
|
};
|
|
195
|
-
//# sourceMappingURL=index-
|
|
194
|
+
//# sourceMappingURL=index-BQ-cHWkJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-B3FUDhxl.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 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\n project. By collecting and displaying usage data from around the world, it helps\n developers and the community better understand how the tool is used, optimize feature\n 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>: When and which features you use, what pages you edit,\n 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('Share my usage data with the community.')\n .default(false),\n }).description('Analytics settings'),\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 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>Usage data: What features you use, what pages you edit, etc.</li>\n <li>User information: Your username, user ID.</li>\n <li>Site information: The wiki you are editing.</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-delete/submit', (payload) => {\n this.addEvent('quick-delete', 'submit', payload.wikiPage.title)\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', (payload) => {\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 }\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","feature","subtype","page","usage","usages","body","endpoint","promise","resolve","reject","promiseWithResolvers","xhr","error","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-BQ-cHWkJ.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 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\n project. By collecting and displaying usage data from around the world, it helps\n developers and the community better understand how the tool is used, optimize feature\n 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>: When and which features you use, what pages you edit,\n 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('Share my usage data with the community.')\n .default(false),\n }).description('Analytics settings'),\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 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>Usage data: What features you use, what pages you edit, etc.</li>\n <li>User information: Your username, user ID.</li>\n <li>Site information: The wiki you are editing.</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', (payload) => {\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 }\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","feature","subtype","page","usage","usages","body","endpoint","promise","resolve","reject","promiseWithResolvers","xhr","error","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
|
|
@@ -1,59 +1,60 @@
|
|
|
1
1
|
import { j as R } from "./index-CM_6yF2v.js";
|
|
2
|
-
import { S as
|
|
2
|
+
import { S as s, E as T, I as C } from "./endpoints-DgyuoRZd.js";
|
|
3
|
+
import { B as j } from "./BasePlugin-Bf2UuIHF.js";
|
|
3
4
|
import { c as L, d as O } from "./vueHooks-l04s8cIl.js";
|
|
4
5
|
const F = 1;
|
|
5
6
|
var m;
|
|
6
7
|
((n) => {
|
|
7
|
-
n.PackageLoader = new
|
|
8
|
-
|
|
9
|
-
kind:
|
|
10
|
-
entry:
|
|
11
|
-
styles:
|
|
12
|
-
main_export:
|
|
8
|
+
n.PackageLoader = new s(
|
|
9
|
+
s.object({
|
|
10
|
+
kind: s.union(["autoload", "module", "umd", "styles"]).required().default("autoload"),
|
|
11
|
+
entry: s.string(),
|
|
12
|
+
styles: s.array(s.string()),
|
|
13
|
+
main_export: s.string()
|
|
13
14
|
})
|
|
14
|
-
), n.Package = new
|
|
15
|
-
|
|
16
|
-
id:
|
|
17
|
-
name:
|
|
18
|
-
version:
|
|
19
|
-
description:
|
|
20
|
-
author:
|
|
21
|
-
license:
|
|
15
|
+
), n.Package = new s(
|
|
16
|
+
s.object({
|
|
17
|
+
id: s.string().required(),
|
|
18
|
+
name: s.string().required(),
|
|
19
|
+
version: s.string().required(),
|
|
20
|
+
description: s.string(),
|
|
21
|
+
author: s.string(),
|
|
22
|
+
license: s.string(),
|
|
22
23
|
loader: n.PackageLoader.required()
|
|
23
24
|
})
|
|
24
|
-
), n.RegistryMaintainer = new
|
|
25
|
-
|
|
26
|
-
name:
|
|
27
|
-
email:
|
|
25
|
+
), n.RegistryMaintainer = new s(
|
|
26
|
+
s.object({
|
|
27
|
+
name: s.string().required(),
|
|
28
|
+
email: s.string()
|
|
28
29
|
})
|
|
29
|
-
), n.RegistryRepository = new
|
|
30
|
-
|
|
31
|
-
type:
|
|
32
|
-
url:
|
|
30
|
+
), n.RegistryRepository = new s(
|
|
31
|
+
s.object({
|
|
32
|
+
type: s.union(["git"]).required().default("git"),
|
|
33
|
+
url: s.string().required()
|
|
33
34
|
})
|
|
34
|
-
), n.Registry = new
|
|
35
|
-
|
|
36
|
-
manifest_version:
|
|
37
|
-
name:
|
|
38
|
-
base_url:
|
|
39
|
-
homepage:
|
|
40
|
-
maintainers:
|
|
35
|
+
), n.Registry = new s(
|
|
36
|
+
s.object({
|
|
37
|
+
manifest_version: s.number().min(F).required(),
|
|
38
|
+
name: s.string().required(),
|
|
39
|
+
base_url: s.string().required(),
|
|
40
|
+
homepage: s.string(),
|
|
41
|
+
maintainers: s.array(n.RegistryMaintainer),
|
|
41
42
|
repository: n.RegistryRepository,
|
|
42
|
-
packages:
|
|
43
|
+
packages: s.array(n.Package).required()
|
|
43
44
|
})
|
|
44
45
|
);
|
|
45
46
|
})(m || (m = {}));
|
|
46
47
|
var G = Object.create, x = Object.defineProperty, B = Object.getOwnPropertyDescriptor, S = (n, e) => (e = Symbol[n]) ? e : Symbol.for("Symbol." + n), b = (n) => {
|
|
47
48
|
throw TypeError(n);
|
|
48
|
-
}, M = (n, e, t) => e in n ? x(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t, q = (n, e) => x(n, "name", { value: e, configurable: !0 }), N = (n) => [, , , G(n?.[S("metadata")] ?? null)], D = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], $ = (n) => n !== void 0 && typeof n != "function" ? b("Function expected") : n, U = (n, e, t, r,
|
|
49
|
-
for (var
|
|
49
|
+
}, M = (n, e, t) => e in n ? x(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t, q = (n, e) => x(n, "name", { value: e, configurable: !0 }), N = (n) => [, , , G(n?.[S("metadata")] ?? null)], D = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], $ = (n) => n !== void 0 && typeof n != "function" ? b("Function expected") : n, U = (n, e, t, r, i) => ({ kind: D[n], name: e, metadata: r, addInitializer: (a) => t._ ? b("Already initialized") : i.push($(a || null)) }), Y = (n, e) => M(e, S("metadata"), n[3]), z = (n, e, t, r) => {
|
|
50
|
+
for (var i = 0, a = n[e >> 1], l = a && a.length; i < l; i++) a[i].call(t);
|
|
50
51
|
return r;
|
|
51
|
-
}, Q = (n, e, t, r,
|
|
52
|
-
var l, f, h, g = e & 7, p = !1, c = 0, y = n[c] || (n[c] = []), d = g && (
|
|
53
|
-
q(
|
|
52
|
+
}, Q = (n, e, t, r, i, a) => {
|
|
53
|
+
var l, f, h, g = e & 7, p = !1, c = 0, y = n[c] || (n[c] = []), d = g && (i = i.prototype, g < 5 && (g > 3 || !p) && B(i, t));
|
|
54
|
+
q(i, t);
|
|
54
55
|
for (var o = r.length - 1; o >= 0; o--)
|
|
55
|
-
h = U(g, t, f = {}, n[3], y), l = (0, r[o])(
|
|
56
|
-
return Y(n,
|
|
56
|
+
h = U(g, t, f = {}, n[3], y), l = (0, r[o])(i, h), f._ = 1, $(l) && (i = l);
|
|
57
|
+
return Y(n, i), d && x(i, t, d), p ? g ^ 4 ? a : d : i;
|
|
57
58
|
}, k, I, A;
|
|
58
59
|
const P = (n) => {
|
|
59
60
|
if (!n) return null;
|
|
@@ -69,17 +70,17 @@ const P = (n) => {
|
|
|
69
70
|
const l = r(e);
|
|
70
71
|
return new URL(n, l).href;
|
|
71
72
|
}
|
|
72
|
-
const
|
|
73
|
+
const i = (() => {
|
|
73
74
|
try {
|
|
74
75
|
return new URL(t).href;
|
|
75
76
|
} catch {
|
|
76
77
|
return new URL(t, location.origin).href;
|
|
77
78
|
}
|
|
78
|
-
})(), a = new URL(r(e),
|
|
79
|
+
})(), a = new URL(r(e), i).href;
|
|
79
80
|
return new URL(n, a).href;
|
|
80
81
|
};
|
|
81
|
-
k = [
|
|
82
|
-
let w = class v extends (A =
|
|
82
|
+
k = [C(["storage", "preferences", "resourceLoader"])];
|
|
83
|
+
let w = class v extends (A = j) {
|
|
83
84
|
constructor(e) {
|
|
84
85
|
super(e, {}, "plugin-store"), this.ctx = e, this.regInfoDB = void 0, this._installedPlugins = /* @__PURE__ */ new Map(), this._onlineRegistryQueries = /* @__PURE__ */ new Map(), e.set("store", this), this.regInfoDB = e.storage.createDatabase(
|
|
85
86
|
v.REGISTRY_INFO_STORAGE_NAME,
|
|
@@ -110,7 +111,7 @@ let w = class v extends (A = T) {
|
|
|
110
111
|
this.install(t.registry, t.id, t.source);
|
|
111
112
|
}
|
|
112
113
|
async _createManagementApp() {
|
|
113
|
-
const e = await this.ctx.withInject(["store"]), t = O(() => import("./PluginStoreApp-
|
|
114
|
+
const e = await this.ctx.withInject(["store"]), t = O(() => import("./PluginStoreApp-CpOLArL7.js"));
|
|
114
115
|
return L(e, t);
|
|
115
116
|
}
|
|
116
117
|
async _injectPreferenceUI() {
|
|
@@ -122,23 +123,23 @@ let w = class v extends (A = T) {
|
|
|
122
123
|
index: 90,
|
|
123
124
|
autoGenerateForm: !1,
|
|
124
125
|
customRenderer: async ({ onUnmount: t }) => {
|
|
125
|
-
const r = /* @__PURE__ */ R("div", { id: "ipe-plugin-store-preferences-vue" }),
|
|
126
|
-
return
|
|
127
|
-
|
|
126
|
+
const r = /* @__PURE__ */ R("div", { id: "ipe-plugin-store-preferences-vue" }), i = await this._createManagementApp();
|
|
127
|
+
return i.mount(r), t(() => {
|
|
128
|
+
i.unmount(), this.ctx.logger.debug("Plugin Store preferences app unmounted");
|
|
128
129
|
}), /* @__PURE__ */ R("section", { children: r });
|
|
129
130
|
}
|
|
130
131
|
}), e.preferences.registerCustomConfig(
|
|
131
132
|
"plugin-store",
|
|
132
|
-
|
|
133
|
-
"pluginStore.registries":
|
|
134
|
-
|
|
133
|
+
s.object({
|
|
134
|
+
"pluginStore.registries": s.array(s.string()).default([
|
|
135
|
+
T.PLUGIN_REGISTRY_URL
|
|
135
136
|
]).description("Registry URLs").hidden(),
|
|
136
|
-
"pluginStore.cdnForNpm":
|
|
137
|
-
"pluginStore.plugins":
|
|
138
|
-
|
|
139
|
-
source:
|
|
140
|
-
registry:
|
|
141
|
-
id:
|
|
137
|
+
"pluginStore.cdnForNpm": s.string().description("CDN to install packages from npm").default('https://cdn.jsdelivr.net/npm/{{ package }}{{ version ? "@" + version : "" }}').hidden(),
|
|
138
|
+
"pluginStore.plugins": s.array(
|
|
139
|
+
s.object({
|
|
140
|
+
source: s.union(["online_manifest", "npm"]).default("online_manifest"),
|
|
141
|
+
registry: s.string().required(),
|
|
142
|
+
id: s.string().required()
|
|
142
143
|
})
|
|
143
144
|
).description("Installed plugins").default([]).hidden()
|
|
144
145
|
}),
|
|
@@ -157,13 +158,13 @@ let w = class v extends (A = T) {
|
|
|
157
158
|
}), e;
|
|
158
159
|
}
|
|
159
160
|
async install(e, t, r = "online_manifest") {
|
|
160
|
-
const
|
|
161
|
-
if (!
|
|
161
|
+
const i = await this.getRegistryInfo(e, r);
|
|
162
|
+
if (!i)
|
|
162
163
|
return this.ctx.logger.warn(`Registry ${e} not found`), null;
|
|
163
164
|
const a = `${e}#${t}`;
|
|
164
165
|
if (this._installedPlugins.has(a))
|
|
165
166
|
return await this._installedPlugins.get(a) ?? null;
|
|
166
|
-
const l = this._installOneByRegistryInfo(e,
|
|
167
|
+
const l = this._installOneByRegistryInfo(e, i, t);
|
|
167
168
|
return this._installedPlugins.set(a, l), await l;
|
|
168
169
|
}
|
|
169
170
|
async uninstall(e, t) {
|
|
@@ -171,8 +172,8 @@ let w = class v extends (A = T) {
|
|
|
171
172
|
if (r === void 0)
|
|
172
173
|
return !0;
|
|
173
174
|
this._installedPlugins.delete(`${e}#${t}`);
|
|
174
|
-
const
|
|
175
|
-
return
|
|
175
|
+
const i = await r;
|
|
176
|
+
return i ? i.dispose?.() ?? !0 : !0;
|
|
176
177
|
}
|
|
177
178
|
async addToPreferences(e, t) {
|
|
178
179
|
let r = await this.ctx.preferences.get("pluginStore.plugins") || [];
|
|
@@ -180,7 +181,7 @@ let w = class v extends (A = T) {
|
|
|
180
181
|
}
|
|
181
182
|
async removeFromPreferences(e, t) {
|
|
182
183
|
let r = await this.ctx.preferences.get("pluginStore.plugins") || [];
|
|
183
|
-
return r = r.filter((
|
|
184
|
+
return r = r.filter((i) => i.registry !== e || i.id !== t), await this.ctx.preferences.set("pluginStore.plugins", r), !0;
|
|
184
185
|
}
|
|
185
186
|
async installAndSetPreference(e, t) {
|
|
186
187
|
return await this.addToPreferences(e, t), this.install(e, t);
|
|
@@ -190,7 +191,7 @@ let w = class v extends (A = T) {
|
|
|
190
191
|
}
|
|
191
192
|
// 3) 增加 registryUrl 参数
|
|
192
193
|
async _installOneByRegistryInfo(e, t, r) {
|
|
193
|
-
const
|
|
194
|
+
const i = t.base_url, a = t.packages.find((o) => o.id === r);
|
|
194
195
|
if (!a)
|
|
195
196
|
return this.ctx.logger.warn(`Package ${r} not found in registry ${e}`), null;
|
|
196
197
|
const l = a.loader, { kind: f, entry: h = "index.js", styles: g = [], main_export: p = null } = l;
|
|
@@ -199,10 +200,10 @@ let w = class v extends (A = T) {
|
|
|
199
200
|
if (!h)
|
|
200
201
|
return this.ctx.logger.warn(`Entry url missing for ${r}`, l), null;
|
|
201
202
|
try {
|
|
202
|
-
c = E(h,
|
|
203
|
+
c = E(h, i, e);
|
|
203
204
|
} catch (o) {
|
|
204
205
|
return this.ctx.logger.warn(
|
|
205
|
-
`Failed to resolve entry "${h}" with base "${
|
|
206
|
+
`Failed to resolve entry "${h}" with base "${i}" and registry "${e}"`,
|
|
206
207
|
o
|
|
207
208
|
), null;
|
|
208
209
|
}
|
|
@@ -255,7 +256,7 @@ let w = class v extends (A = T) {
|
|
|
255
256
|
if (g && g.length > 0) {
|
|
256
257
|
let o = [];
|
|
257
258
|
try {
|
|
258
|
-
o = g.map((u) => E(u,
|
|
259
|
+
o = g.map((u) => E(u, i, e)).filter(Boolean);
|
|
259
260
|
} catch (u) {
|
|
260
261
|
this.ctx.logger.warn(`Failed to resolve styles for ${r}`, g, u);
|
|
261
262
|
}
|
|
@@ -293,15 +294,15 @@ let w = class v extends (A = T) {
|
|
|
293
294
|
} catch (a) {
|
|
294
295
|
this.ctx.logger.warn("Failed to fetch registry info", a);
|
|
295
296
|
}
|
|
296
|
-
const
|
|
297
|
-
if (!
|
|
297
|
+
const i = await this.getRegistryCache(e);
|
|
298
|
+
if (!i)
|
|
298
299
|
throw new Error(`Failed to fetch registry info: ${e}`);
|
|
299
|
-
return
|
|
300
|
+
return i;
|
|
300
301
|
}
|
|
301
302
|
async _fetchOnlineRegistryInfo(e, t = !1) {
|
|
302
303
|
if (!t && this._onlineRegistryQueries.has(e))
|
|
303
304
|
return await this._onlineRegistryQueries.get(e);
|
|
304
|
-
const
|
|
305
|
+
const i = (async () => {
|
|
305
306
|
const a = {
|
|
306
307
|
method: "GET"
|
|
307
308
|
};
|
|
@@ -309,7 +310,7 @@ let w = class v extends (A = T) {
|
|
|
309
310
|
const f = await (await fetch(e, a)).json();
|
|
310
311
|
return this.validateRegistry(f);
|
|
311
312
|
})();
|
|
312
|
-
return this._onlineRegistryQueries.set(e,
|
|
313
|
+
return this._onlineRegistryQueries.set(e, i), await i;
|
|
313
314
|
}
|
|
314
315
|
async getRegistryCache(e) {
|
|
315
316
|
const t = await this.regInfoDB.get(e);
|
|
@@ -344,18 +345,18 @@ let w = class v extends (A = T) {
|
|
|
344
345
|
*/
|
|
345
346
|
async refreshAllRegistryCaches() {
|
|
346
347
|
const e = await this.ctx.preferences.get("pluginStore.registries") || [], t = await Promise.allSettled(
|
|
347
|
-
e.map((
|
|
348
|
+
e.map((i) => this.refreshRegistryCache(i))
|
|
348
349
|
), r = {};
|
|
349
|
-
for (const [
|
|
350
|
-
a.status === "fulfilled" ? r[e[
|
|
350
|
+
for (const [i, a] of t.entries())
|
|
351
|
+
a.status === "fulfilled" ? r[e[i]] = a.value : r[e[i]] = null;
|
|
351
352
|
return r;
|
|
352
353
|
}
|
|
353
354
|
};
|
|
354
355
|
I = N(A);
|
|
355
356
|
w = Q(I, 0, "PluginPluginStore", k, w);
|
|
356
357
|
z(I, 1, w);
|
|
357
|
-
let
|
|
358
|
+
let K = w;
|
|
358
359
|
export {
|
|
359
|
-
|
|
360
|
+
K as PluginPluginStore
|
|
360
361
|
};
|
|
361
|
-
//# sourceMappingURL=index-
|
|
362
|
+
//# sourceMappingURL=index-BwdWyHLe.js.map
|