@inpageedit/core 0.12.0 → 0.12.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/IconQuickEdit-CMCQncyj.js.map +1 -1
- package/dist/InputBox-nQKtiWtZ.js +30 -0
- package/dist/InputBox-nQKtiWtZ.js.map +1 -0
- package/dist/PluginPrefSync-Ziogy_o-.js +339 -0
- package/dist/PluginPrefSync-Ziogy_o-.js.map +1 -0
- package/dist/PluginStoreApp-Bnvyl-Oc.js +452 -0
- package/dist/PluginStoreApp-Bnvyl-Oc.js.map +1 -0
- package/dist/Preferences-DS4-CFWe.js.map +1 -1
- package/dist/components/index.js +6 -7
- package/dist/components/index.js.map +1 -1
- package/dist/{index-CYc6LH26.js → index-B3FUDhxl.js} +2 -2
- package/dist/{index-CYc6LH26.js.map → index-B3FUDhxl.js.map} +1 -1
- package/dist/{index-DEav9Ptt.js → index-B3YJdjxo.js} +128 -132
- package/dist/index-B3YJdjxo.js.map +1 -0
- package/dist/{index-Bv7Dw5eO.js → index-BRjEc8b8.js} +2 -2
- package/dist/{index-Bv7Dw5eO.js.map → index-BRjEc8b8.js.map} +1 -1
- package/dist/{index-CZXxH2-9.js → index-Bd70aDMT.js} +6 -7
- package/dist/{index-CZXxH2-9.js.map → index-Bd70aDMT.js.map} +1 -1
- package/dist/{index-B5DtUqkK.js → index-BvuaLEFc.js} +3 -4
- package/dist/{index-B5DtUqkK.js.map → index-BvuaLEFc.js.map} +1 -1
- package/dist/index-CG38LlAh.js.map +1 -1
- package/dist/index-CM_6yF2v.js.map +1 -1
- package/dist/{index-D4uwfUZL.js → index-Ccr3YhkP.js} +2 -2
- package/dist/{index-D4uwfUZL.js.map → index-Ccr3YhkP.js.map} +1 -1
- package/dist/{index-CPoUaSMw.js → index-D5zX93bn.js} +39 -40
- package/dist/index-D5zX93bn.js.map +1 -0
- package/dist/index-DD5CVCfD.js.map +1 -1
- package/dist/{index-BXaiDKnr.js → index-DgQNTfPR.js} +15 -14
- package/dist/index-DgQNTfPR.js.map +1 -0
- package/dist/{index-CJFePavo.js → index-Dnmv-xDn.js} +2 -2
- package/dist/{index-CJFePavo.js.map → index-Dnmv-xDn.js.map} +1 -1
- package/dist/{index-hSl8LzNb.js → index-eARjMi7f.js} +5 -6
- package/dist/index-eARjMi7f.js.map +1 -0
- package/dist/{index-Ckozkp6W.js → index-zHTGCjfF.js} +2 -2
- package/dist/{index-Ckozkp6W.js.map → index-zHTGCjfF.js.map} +1 -1
- package/dist/index.js +1 -1
- package/dist/makeCallable-LDU0xZMJ.js.map +1 -1
- package/dist/models/WikiPage/index.d.ts +5 -1
- package/dist/noop-ClDc6zv4.js.map +1 -1
- package/dist/plugins/plugin-store/index.d.ts +9 -12
- package/dist/style.css +1 -1
- package/dist/{vueHooks-D0uVqbO-.js → vueHooks-l04s8cIl.js} +1112 -1080
- package/dist/{vueHooks-D0uVqbO-.js.map → vueHooks-l04s8cIl.js.map} +1 -1
- package/lib/index.umd.js +15 -11
- package/lib/index.umd.js.map +1 -1
- package/lib/style.css +1 -1
- package/package.json +1 -1
- package/dist/CheckBox-Bc79KBEB.js +0 -13
- package/dist/CheckBox-Bc79KBEB.js.map +0 -1
- package/dist/InputBox-DZAdyZ4B.js +0 -22
- package/dist/InputBox-DZAdyZ4B.js.map +0 -1
- package/dist/PluginPrefSync-BPQkNtX8.js +0 -292
- package/dist/PluginPrefSync-BPQkNtX8.js.map +0 -1
- package/dist/PluginStoreApp-Cxspe6t8.js +0 -158
- package/dist/PluginStoreApp-Cxspe6t8.js.map +0 -1
- package/dist/index-BXaiDKnr.js.map +0 -1
- package/dist/index-CB7TltEb.js +0 -297
- package/dist/index-CB7TltEb.js.map +0 -1
- package/dist/index-CPoUaSMw.js.map +0 -1
- package/dist/index-DEav9Ptt.js.map +0 -1
- package/dist/index-hSl8LzNb.js.map +0 -1
- package/dist/plugins/quick-delete/index.d.ts +0 -55
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-CYc6LH26.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-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,8 +1,8 @@
|
|
|
1
|
-
import { j as
|
|
2
|
-
import { S as i, B as
|
|
3
|
-
import { c as
|
|
4
|
-
const
|
|
5
|
-
var
|
|
1
|
+
import { j as R } from "./index-CM_6yF2v.js";
|
|
2
|
+
import { S as i, B as T, E as C, I as j } from "./index-DgQNTfPR.js";
|
|
3
|
+
import { c as L, d as O } from "./vueHooks-l04s8cIl.js";
|
|
4
|
+
const F = 1;
|
|
5
|
+
var m;
|
|
6
6
|
((n) => {
|
|
7
7
|
n.PackageLoader = new i(
|
|
8
8
|
i.object({
|
|
@@ -33,7 +33,7 @@ var w;
|
|
|
33
33
|
})
|
|
34
34
|
), n.Registry = new i(
|
|
35
35
|
i.object({
|
|
36
|
-
manifest_version: i.number().min(
|
|
36
|
+
manifest_version: i.number().min(F).required(),
|
|
37
37
|
name: i.string().required(),
|
|
38
38
|
base_url: i.string().required(),
|
|
39
39
|
homepage: i.string(),
|
|
@@ -42,19 +42,19 @@ var w;
|
|
|
42
42
|
packages: i.array(n.Package).required()
|
|
43
43
|
})
|
|
44
44
|
);
|
|
45
|
-
})(
|
|
46
|
-
var
|
|
45
|
+
})(m || (m = {}));
|
|
46
|
+
var G = Object.create, x = Object.defineProperty, B = Object.getOwnPropertyDescriptor, S = (n, e) => (e = Symbol[n]) ? e : Symbol.for("Symbol." + n), b = (n) => {
|
|
47
47
|
throw TypeError(n);
|
|
48
|
-
},
|
|
49
|
-
for (var s = 0, a = n[e >> 1],
|
|
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, s) => ({ kind: D[n], name: e, metadata: r, addInitializer: (a) => t._ ? b("Already initialized") : s.push($(a || null)) }), Y = (n, e) => M(e, S("metadata"), n[3]), z = (n, e, t, r) => {
|
|
49
|
+
for (var s = 0, a = n[e >> 1], l = a && a.length; s < l; s++) a[s].call(t);
|
|
50
50
|
return r;
|
|
51
|
-
},
|
|
52
|
-
var
|
|
53
|
-
|
|
54
|
-
for (var
|
|
55
|
-
|
|
56
|
-
return
|
|
57
|
-
},
|
|
51
|
+
}, Q = (n, e, t, r, s, a) => {
|
|
52
|
+
var l, f, h, g = e & 7, p = !1, c = 0, y = n[c] || (n[c] = []), d = g && (s = s.prototype, g < 5 && (g > 3 || !p) && B(s, t));
|
|
53
|
+
q(s, t);
|
|
54
|
+
for (var o = r.length - 1; o >= 0; o--)
|
|
55
|
+
h = U(g, t, f = {}, n[3], y), l = (0, r[o])(s, h), f._ = 1, $(l) && (s = l);
|
|
56
|
+
return Y(n, s), d && x(s, t, d), p ? g ^ 4 ? a : d : s;
|
|
57
|
+
}, k, I, A;
|
|
58
58
|
const P = (n) => {
|
|
59
59
|
if (!n) return null;
|
|
60
60
|
try {
|
|
@@ -62,12 +62,12 @@ const P = (n) => {
|
|
|
62
62
|
} catch {
|
|
63
63
|
return null;
|
|
64
64
|
}
|
|
65
|
-
},
|
|
65
|
+
}, E = (n, e, t) => {
|
|
66
66
|
if (/^https?:\/\//i.test(n)) return n;
|
|
67
|
-
const r = (
|
|
67
|
+
const r = (l) => l.endsWith("/") ? l : l + "/";
|
|
68
68
|
if (/^https?:\/\//i.test(e)) {
|
|
69
|
-
const
|
|
70
|
-
return new URL(n,
|
|
69
|
+
const l = r(e);
|
|
70
|
+
return new URL(n, l).href;
|
|
71
71
|
}
|
|
72
72
|
const s = (() => {
|
|
73
73
|
try {
|
|
@@ -78,20 +78,27 @@ const P = (n) => {
|
|
|
78
78
|
})(), a = new URL(r(e), s).href;
|
|
79
79
|
return new URL(n, a).href;
|
|
80
80
|
};
|
|
81
|
-
|
|
82
|
-
let
|
|
81
|
+
k = [j(["storage", "preferences", "resourceLoader"])];
|
|
82
|
+
let w = class v extends (A = T) {
|
|
83
83
|
constructor(e) {
|
|
84
|
-
super(e, {}, "plugin-store"), this.ctx = e, this.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
1
|
|
84
|
+
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
|
+
v.REGISTRY_INFO_STORAGE_NAME,
|
|
86
|
+
v.REGISTRY_INFO_CACHE_TTL,
|
|
87
|
+
1,
|
|
88
|
+
"indexedDB"
|
|
88
89
|
);
|
|
89
90
|
}
|
|
90
91
|
static {
|
|
91
|
-
this.PluginStoreSchemas =
|
|
92
|
+
this.PluginStoreSchemas = m;
|
|
92
93
|
}
|
|
93
94
|
static {
|
|
94
|
-
this.
|
|
95
|
+
this.REGISTRY_INFO_CACHE_TTL = 1e3 * 60 * 60 * 24;
|
|
96
|
+
}
|
|
97
|
+
static {
|
|
98
|
+
this.REGISTRY_INFO_STORAGE_NAME = "plugin-store-registry";
|
|
99
|
+
}
|
|
100
|
+
static {
|
|
101
|
+
this.REGISTRY_ETAG_STORAGE_NAME = "psreg-etag";
|
|
95
102
|
}
|
|
96
103
|
async start() {
|
|
97
104
|
this._installUserPlugins(), this._injectPreferenceUI();
|
|
@@ -103,8 +110,8 @@ let R = class E extends ($ = L) {
|
|
|
103
110
|
this.install(t.registry, t.id, t.source);
|
|
104
111
|
}
|
|
105
112
|
async _createManagementApp() {
|
|
106
|
-
const e = await this.ctx.withInject(["store"]), t =
|
|
107
|
-
return
|
|
113
|
+
const e = await this.ctx.withInject(["store"]), t = O(() => import("./PluginStoreApp-Bnvyl-Oc.js"));
|
|
114
|
+
return L(e, t);
|
|
108
115
|
}
|
|
109
116
|
async _injectPreferenceUI() {
|
|
110
117
|
const e = this.ctx;
|
|
@@ -113,25 +120,20 @@ let R = class E extends ($ = L) {
|
|
|
113
120
|
label: "Plugin Store",
|
|
114
121
|
description: "Plugin Store",
|
|
115
122
|
index: 90,
|
|
123
|
+
autoGenerateForm: !1,
|
|
116
124
|
customRenderer: async ({ onUnmount: t }) => {
|
|
117
|
-
const r = /* @__PURE__ */
|
|
125
|
+
const r = /* @__PURE__ */ R("div", { id: "ipe-plugin-store-preferences-vue" }), s = await this._createManagementApp();
|
|
118
126
|
return s.mount(r), t(() => {
|
|
119
127
|
s.unmount(), this.ctx.logger.debug("Plugin Store preferences app unmounted");
|
|
120
|
-
}), /* @__PURE__ */
|
|
121
|
-
r,
|
|
122
|
-
/* @__PURE__ */ y("div", { className: "theme-ipe-prose", children: [
|
|
123
|
-
/* @__PURE__ */ y("hr", {}),
|
|
124
|
-
/* @__PURE__ */ y("div", { style: { textAlign: "center", marginBottom: "1em", fontSize: "0.8em" }, children: "🚫 DO NOT edit fields below manually 🚫" })
|
|
125
|
-
] })
|
|
126
|
-
] });
|
|
128
|
+
}), /* @__PURE__ */ R("section", { children: r });
|
|
127
129
|
}
|
|
128
130
|
}), e.preferences.registerCustomConfig(
|
|
129
131
|
"plugin-store",
|
|
130
132
|
i.object({
|
|
131
133
|
"pluginStore.registries": i.array(i.string()).default([
|
|
132
|
-
|
|
133
|
-
]).description("Registry URLs"),
|
|
134
|
-
"pluginStore.cdnForNpm": i.string().description("CDN to install packages from npm").default('https://cdn.jsdelivr.net/npm/{{ package }}{{ version ? "@" + version : "" }}'),
|
|
134
|
+
C.PLUGIN_REGISTRY_URL
|
|
135
|
+
]).description("Registry URLs").hidden(),
|
|
136
|
+
"pluginStore.cdnForNpm": i.string().description("CDN to install packages from npm").default('https://cdn.jsdelivr.net/npm/{{ package }}{{ version ? "@" + version : "" }}').hidden(),
|
|
135
137
|
"pluginStore.plugins": i.array(
|
|
136
138
|
i.object({
|
|
137
139
|
source: i.union(["online_manifest", "npm"]).default("online_manifest"),
|
|
@@ -147,7 +149,7 @@ let R = class E extends ($ = L) {
|
|
|
147
149
|
const e = this.ctx.modal.show({
|
|
148
150
|
title: "Plugin Store",
|
|
149
151
|
sizeClass: "small"
|
|
150
|
-
}), t = /* @__PURE__ */
|
|
152
|
+
}), t = /* @__PURE__ */ R("section", { id: "ipe-plugin-store-vue" });
|
|
151
153
|
e.setContent(t);
|
|
152
154
|
const r = await this._createManagementApp();
|
|
153
155
|
return r.mount(t), e.on(e.Event.Close, () => {
|
|
@@ -155,17 +157,20 @@ let R = class E extends ($ = L) {
|
|
|
155
157
|
}), e;
|
|
156
158
|
}
|
|
157
159
|
async install(e, t, r = "online_manifest") {
|
|
158
|
-
const s = await this.getRegistryInfo(e
|
|
160
|
+
const s = await this.getRegistryInfo(e, r);
|
|
161
|
+
if (!s)
|
|
162
|
+
return this.ctx.logger.warn(`Registry ${e} not found`), null;
|
|
163
|
+
const a = `${e}#${t}`;
|
|
159
164
|
if (this._installedPlugins.has(a))
|
|
160
165
|
return await this._installedPlugins.get(a) ?? null;
|
|
161
|
-
const
|
|
162
|
-
return this._installedPlugins.set(a,
|
|
166
|
+
const l = this._installOneByRegistryInfo(e, s, t);
|
|
167
|
+
return this._installedPlugins.set(a, l), await l;
|
|
163
168
|
}
|
|
164
169
|
async uninstall(e, t) {
|
|
165
|
-
const r = this._installedPlugins.get(`${e}
|
|
170
|
+
const r = this._installedPlugins.get(`${e}#${t}`);
|
|
166
171
|
if (r === void 0)
|
|
167
172
|
return !0;
|
|
168
|
-
this._installedPlugins.delete(`${e}
|
|
173
|
+
this._installedPlugins.delete(`${e}#${t}`);
|
|
169
174
|
const s = await r;
|
|
170
175
|
return s ? s.dispose?.() ?? !0 : !0;
|
|
171
176
|
}
|
|
@@ -185,35 +190,35 @@ let R = class E extends ($ = L) {
|
|
|
185
190
|
}
|
|
186
191
|
// 3) 增加 registryUrl 参数
|
|
187
192
|
async _installOneByRegistryInfo(e, t, r) {
|
|
188
|
-
const s = t.base_url, a = t.packages.find((
|
|
193
|
+
const s = t.base_url, a = t.packages.find((o) => o.id === r);
|
|
189
194
|
if (!a)
|
|
190
195
|
return this.ctx.logger.warn(`Package ${r} not found in registry ${e}`), null;
|
|
191
|
-
const
|
|
196
|
+
const l = a.loader, { kind: f, entry: h = "index.js", styles: g = [], main_export: p = null } = l;
|
|
192
197
|
let c = null;
|
|
193
|
-
if (
|
|
194
|
-
if (!
|
|
195
|
-
return this.ctx.logger.warn(`Entry url missing for ${r}`,
|
|
198
|
+
if (f !== "styles") {
|
|
199
|
+
if (!h)
|
|
200
|
+
return this.ctx.logger.warn(`Entry url missing for ${r}`, l), null;
|
|
196
201
|
try {
|
|
197
|
-
c =
|
|
198
|
-
} catch (
|
|
202
|
+
c = E(h, s, e);
|
|
203
|
+
} catch (o) {
|
|
199
204
|
return this.ctx.logger.warn(
|
|
200
|
-
`Failed to resolve entry "${
|
|
201
|
-
|
|
205
|
+
`Failed to resolve entry "${h}" with base "${s}" and registry "${e}"`,
|
|
206
|
+
o
|
|
202
207
|
), null;
|
|
203
208
|
}
|
|
204
209
|
}
|
|
205
|
-
const
|
|
210
|
+
const y = {
|
|
206
211
|
"data-plugin-registry": e,
|
|
207
212
|
"data-plugin-id": r
|
|
208
213
|
};
|
|
209
214
|
let d = null;
|
|
210
|
-
switch (
|
|
215
|
+
switch (f) {
|
|
211
216
|
case "autoload": {
|
|
212
217
|
d = this.ctx.plugin({
|
|
213
218
|
inject: ["resourceLoader"],
|
|
214
219
|
name: `plugin-store-${e}-${r}`,
|
|
215
|
-
apply: (
|
|
216
|
-
c &&
|
|
220
|
+
apply: (o) => {
|
|
221
|
+
c && o.resourceLoader.loadScript(c, { ...y });
|
|
217
222
|
}
|
|
218
223
|
});
|
|
219
224
|
break;
|
|
@@ -221,36 +226,36 @@ let R = class E extends ($ = L) {
|
|
|
221
226
|
case "module": {
|
|
222
227
|
if (!c)
|
|
223
228
|
return this.ctx.logger.warn(`Entry url missing for module kind, package ${r}`), null;
|
|
224
|
-
const
|
|
229
|
+
const o = await import(
|
|
225
230
|
/* @vite-ignore */
|
|
226
231
|
c
|
|
227
232
|
).then(
|
|
228
233
|
(u) => (p ? u[p] : u.default) ?? u
|
|
229
234
|
);
|
|
230
|
-
if (!
|
|
235
|
+
if (!o)
|
|
231
236
|
return this.ctx.logger.warn(`Main export ${p} not found in module ${c}`), null;
|
|
232
|
-
d = this.ctx.plugin(
|
|
237
|
+
d = this.ctx.plugin(o);
|
|
233
238
|
break;
|
|
234
239
|
}
|
|
235
240
|
case "umd": {
|
|
236
|
-
let
|
|
237
|
-
if (!
|
|
241
|
+
let o = P(p);
|
|
242
|
+
if (!o) {
|
|
238
243
|
if (!c)
|
|
239
244
|
return this.ctx.logger.warn(`Entry url missing for umd kind, package ${r}`), null;
|
|
240
|
-
await this.ctx.resourceLoader.loadScript(c, { ...
|
|
245
|
+
await this.ctx.resourceLoader.loadScript(c, { ...y }), o = P(p);
|
|
241
246
|
}
|
|
242
|
-
if (!
|
|
247
|
+
if (!o)
|
|
243
248
|
return this.ctx.logger.warn(
|
|
244
249
|
`Main export ${p} not found on globalThis after loading ${c}`
|
|
245
250
|
), null;
|
|
246
|
-
d = this.ctx.plugin(
|
|
251
|
+
d = this.ctx.plugin(o);
|
|
247
252
|
break;
|
|
248
253
|
}
|
|
249
254
|
}
|
|
250
255
|
if (g && g.length > 0) {
|
|
251
|
-
let
|
|
256
|
+
let o = [];
|
|
252
257
|
try {
|
|
253
|
-
|
|
258
|
+
o = g.map((u) => E(u, s, e)).filter(Boolean);
|
|
254
259
|
} catch (u) {
|
|
255
260
|
this.ctx.logger.warn(`Failed to resolve styles for ${r}`, g, u);
|
|
256
261
|
}
|
|
@@ -259,9 +264,9 @@ let R = class E extends ($ = L) {
|
|
|
259
264
|
inject: ["resourceLoader"],
|
|
260
265
|
name: `plugin-store-${e}-${r}-styles`,
|
|
261
266
|
apply: (u) => {
|
|
262
|
-
|
|
267
|
+
o.forEach((_) => u.resourceLoader.loadStyle(_, { ...y })), u.on("dispose", () => {
|
|
263
268
|
try {
|
|
264
|
-
|
|
269
|
+
o.forEach((_) => u.resourceLoader.removeStyle(_));
|
|
265
270
|
} catch {
|
|
266
271
|
}
|
|
267
272
|
});
|
|
@@ -271,95 +276,86 @@ let R = class E extends ($ = L) {
|
|
|
271
276
|
return d;
|
|
272
277
|
}
|
|
273
278
|
validateRegistry(e) {
|
|
274
|
-
return
|
|
275
|
-
}
|
|
276
|
-
async getRegistryInfo(e) {
|
|
277
|
-
const t = await this.getRegistryCache(e);
|
|
278
|
-
if (t) return t;
|
|
279
|
-
const r = await this._fetchOnlineRegistryInfo(e);
|
|
280
|
-
return await this.setRegistryCache(e, r), r;
|
|
281
|
-
}
|
|
282
|
-
async _fetchOnlineRegistryInfo(e) {
|
|
283
|
-
const r = await (await fetch(e)).json(), s = this.validateRegistry(r);
|
|
284
|
-
return this.ctx.storage.simpleKV.set(`plugin-store-last-fetch/${e}`, Date.now()), s;
|
|
279
|
+
return m.Registry(e);
|
|
285
280
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
return this._registryUpdateCheckCaches.get(e);
|
|
294
|
-
const t = (async () => {
|
|
295
|
-
try {
|
|
296
|
-
const s = await fetch(e, { method: "HEAD" });
|
|
297
|
-
if (!s.ok)
|
|
298
|
-
throw new Error(s.statusText, { cause: s });
|
|
299
|
-
if (s.status === 304)
|
|
300
|
-
return this.ctx.logger.debug("Registry not modified:", e), !1;
|
|
301
|
-
const a = s.headers.get("Last-Modified");
|
|
302
|
-
if (a) {
|
|
303
|
-
const o = Date.parse(a);
|
|
304
|
-
if (!isNaN(o))
|
|
305
|
-
return !1;
|
|
306
|
-
const h = await this.ctx.storage.simpleKV.get(
|
|
307
|
-
`plugin-store-last-fetch/${e}`
|
|
308
|
-
);
|
|
309
|
-
return !h || o > h ? (await this.ctx.storage.simpleKV.set(`plugin-store-last-fetch/${e}`, o), !0) : !1;
|
|
281
|
+
async getRegistryInfo(e, t = "online_manifest", r = !1) {
|
|
282
|
+
try {
|
|
283
|
+
let a;
|
|
284
|
+
switch (t) {
|
|
285
|
+
case "online_manifest": {
|
|
286
|
+
a = await this._fetchOnlineRegistryInfo(e, r), this.logger.debug("Fetched registry info from online manifest", a), this.setRegistryCache(e, a);
|
|
287
|
+
break;
|
|
310
288
|
}
|
|
311
|
-
|
|
312
|
-
|
|
289
|
+
default:
|
|
290
|
+
throw new Error(`Unsupported registry source: ${t}`);
|
|
313
291
|
}
|
|
314
|
-
return
|
|
292
|
+
return a;
|
|
293
|
+
} catch (a) {
|
|
294
|
+
this.ctx.logger.warn("Failed to fetch registry info", a);
|
|
295
|
+
}
|
|
296
|
+
const s = await this.getRegistryCache(e);
|
|
297
|
+
if (!s)
|
|
298
|
+
throw new Error(`Failed to fetch registry info: ${e}`);
|
|
299
|
+
return s;
|
|
300
|
+
}
|
|
301
|
+
async _fetchOnlineRegistryInfo(e, t = !1) {
|
|
302
|
+
if (!t && this._onlineRegistryQueries.has(e))
|
|
303
|
+
return await this._onlineRegistryQueries.get(e);
|
|
304
|
+
const s = (async () => {
|
|
305
|
+
const a = {
|
|
306
|
+
method: "GET"
|
|
307
|
+
};
|
|
308
|
+
t && (a.cache = "no-store");
|
|
309
|
+
const f = await (await fetch(e, a)).json();
|
|
310
|
+
return this.validateRegistry(f);
|
|
315
311
|
})();
|
|
316
|
-
return this.
|
|
312
|
+
return this._onlineRegistryQueries.set(e, s), await s;
|
|
317
313
|
}
|
|
318
314
|
async getRegistryCache(e) {
|
|
319
|
-
const t = await this.
|
|
315
|
+
const t = await this.regInfoDB.get(e);
|
|
320
316
|
if (t)
|
|
321
317
|
try {
|
|
322
|
-
return
|
|
318
|
+
return this.validateRegistry(t);
|
|
323
319
|
} catch (r) {
|
|
324
|
-
this.ctx.logger.warn("Invalid cached registry", r, t), this.
|
|
320
|
+
this.ctx.logger.warn("Invalid cached registry", r, t), this.regInfoDB.delete(e);
|
|
325
321
|
}
|
|
326
322
|
return null;
|
|
327
323
|
}
|
|
328
324
|
async setRegistryCache(e, t) {
|
|
329
|
-
return this.
|
|
325
|
+
return this.regInfoDB.set(e, t);
|
|
330
326
|
}
|
|
331
327
|
async deleteRegistryCache(e) {
|
|
332
|
-
await
|
|
333
|
-
this.registryInfoDB.delete(e),
|
|
334
|
-
this.ctx.storage.simpleKV.delete(`plugin-store-last-fetch/${e}`)
|
|
335
|
-
]);
|
|
328
|
+
await this.regInfoDB.delete(e);
|
|
336
329
|
}
|
|
337
330
|
async clearAllRegistryCaches() {
|
|
338
|
-
await
|
|
331
|
+
await this.regInfoDB.clear(), this.ctx.logger.debug("All registry caches cleared");
|
|
339
332
|
}
|
|
340
333
|
/**
|
|
341
334
|
* 刷新指定 registry 的缓存(重新从网络获取)
|
|
342
335
|
*/
|
|
343
336
|
async refreshRegistryCache(e) {
|
|
344
|
-
await this.
|
|
345
|
-
|
|
346
|
-
|
|
337
|
+
const t = await this.getRegistryInfo(e, "online_manifest", !0);
|
|
338
|
+
if (!t)
|
|
339
|
+
throw new Error(`Failed to refresh registry cache: ${e}`);
|
|
340
|
+
return this.ctx.logger.debug("Registry cache refreshed:", e), t;
|
|
347
341
|
}
|
|
348
342
|
/**
|
|
349
343
|
* 刷新所有已配置的 registry 缓存
|
|
350
344
|
*/
|
|
351
345
|
async refreshAllRegistryCaches() {
|
|
352
|
-
const e = await this.ctx.preferences.get("pluginStore.registries") || [],
|
|
346
|
+
const e = await this.ctx.preferences.get("pluginStore.registries") || [], t = await Promise.allSettled(
|
|
353
347
|
e.map((s) => this.refreshRegistryCache(s))
|
|
354
|
-
)
|
|
355
|
-
|
|
348
|
+
), r = {};
|
|
349
|
+
for (const [s, a] of t.entries())
|
|
350
|
+
a.status === "fulfilled" ? r[e[s]] = a.value : r[e[s]] = null;
|
|
351
|
+
return r;
|
|
356
352
|
}
|
|
357
353
|
};
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
let J =
|
|
354
|
+
I = N(A);
|
|
355
|
+
w = Q(I, 0, "PluginPluginStore", k, w);
|
|
356
|
+
z(I, 1, w);
|
|
357
|
+
let J = w;
|
|
362
358
|
export {
|
|
363
359
|
J as PluginPluginStore
|
|
364
360
|
};
|
|
365
|
-
//# sourceMappingURL=index-
|
|
361
|
+
//# sourceMappingURL=index-B3YJdjxo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-B3YJdjxo.js","sources":["../src/plugins/plugin-store/schema.ts","../src/plugins/plugin-store/index.tsx"],"sourcesContent":["import Schema from 'schemastery'\n\nexport const PLUGIN_STORE_REGISTRY_MANIFEST_VERSION = 1\n\nexport interface PluginStoreRegistry {\n manifest_version: number\n name: string\n base_url: string\n homepage?: string\n maintainers?: PluginStoreRegistryMaintainer[]\n repository?: PluginStoreRegistryRepository\n packages: PluginStorePackage[]\n}\n\nexport interface PluginStoreRegistryMaintainer {\n name: string\n email?: string\n}\n\nexport interface PluginStoreRegistryRepository {\n type: 'git'\n url: string\n}\n\nexport interface PluginStorePackage {\n id: string\n name: string\n version: string\n description?: string\n author?: string\n license?: string\n loader: PluginStorePackageLoader\n}\n\nexport interface PluginStorePackageLoader {\n kind: 'autoload' | 'module' | 'umd' | 'styles'\n entry?: string\n styles?: string[]\n main_export?: string\n}\n\nexport namespace PluginStoreSchemas {\n export const PackageLoader = new Schema<PluginStorePackageLoader>(\n Schema.object({\n kind: Schema.union(['autoload', 'module', 'umd', 'styles']).required().default('autoload'),\n entry: Schema.string(),\n styles: Schema.array(Schema.string()),\n main_export: Schema.string(),\n })\n )\n\n export const Package = new Schema<PluginStorePackage>(\n Schema.object({\n id: Schema.string().required(),\n name: Schema.string().required(),\n version: Schema.string().required(),\n description: Schema.string(),\n author: Schema.string(),\n license: Schema.string(),\n loader: PackageLoader.required(),\n })\n )\n\n export const RegistryMaintainer = new Schema<PluginStoreRegistryMaintainer>(\n Schema.object({\n name: Schema.string().required(),\n email: Schema.string(),\n })\n )\n\n export const RegistryRepository = new Schema<PluginStoreRegistryRepository>(\n Schema.object({\n type: Schema.union(['git']).required().default('git'),\n url: Schema.string().required(),\n })\n )\n\n export const Registry = new Schema<PluginStoreRegistry>(\n Schema.object({\n manifest_version: Schema.number().min(PLUGIN_STORE_REGISTRY_MANIFEST_VERSION).required(),\n name: Schema.string().required(),\n base_url: Schema.string().required(),\n homepage: Schema.string(),\n maintainers: Schema.array(RegistryMaintainer),\n repository: RegistryRepository,\n packages: Schema.array(Package).required(),\n })\n )\n}\n","import { InPageEdit, Schema } from '@/InPageEdit'\nimport { ForkScope, Inject } from '@cordisjs/core'\nimport { defineAsyncComponent, type App as VueApp } from 'vue'\nimport { PluginStoreRegistry, PluginStoreSchemas } from './schema'\nimport { AbstractIPEStorageManager } from '@/services/storage/index.js'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n store: PluginPluginStore\n }\n interface PreferencesMap {\n 'pluginStore.registries': string[]\n 'pluginStore.plugins': { source?: 'online_manifest' | 'npm'; registry: string; id: string }[]\n 'pluginStore.cdnForNpm': string\n }\n}\n\nexport type PluginStoreRegistrySource = 'online_manifest' | 'npm'\n\nconst tryGetGlobalPlugin = (main_export: string) => {\n if (!main_export) return null\n try {\n return main_export\n .split('.')\n .reduce<any>((acc, key) => (acc == null ? acc : acc[key]), globalThis as any)\n } catch {\n return null\n }\n}\n\n/**\n * 解析资源URL\n * @param resourcePath - entry或style路径,可能是相对路径或完整URL\n * @param baseUrl - registry中的base_url,可能是完整URL或相对路径\n * @param registryUrl - registry的URL(必须是绝对URL,作为相对baseUrl时的基准)\n * @returns 解析后的完整URL\n */\nconst resolveResourceUrl = (resourcePath: string, baseUrl: string, registryUrl: string): string => {\n // 完整URL:直接返回\n if (/^https?:\\/\\//i.test(resourcePath)) return resourcePath\n\n // 兜底:规范化一个“带尾斜杠”的 helper\n const ensureSlash = (s: string) => (s.endsWith('/') ? s : s + '/')\n\n // 如果 baseUrl 是完整URL:直接用它当基准(并确保目录语义)\n if (/^https?:\\/\\//i.test(baseUrl)) {\n const normalizedBase = ensureSlash(baseUrl)\n return new URL(resourcePath, normalizedBase).href\n }\n\n // baseUrl 是相对路径(如 './' 或 '/plugins')\n // 先把 baseUrl 相对于 registryUrl 解析成绝对URL\n // 注意:当 baseUrl 是 '/plugins' 这种根相对路径时,new URL 会以 registryUrl 的 origin 作为根。\n const registryAbs = (() => {\n try {\n return new URL(registryUrl).href\n } catch {\n // 极端情况(开发环境传了相对 registry),用页面 origin 兜底\n return new URL(registryUrl, location.origin).href\n }\n })()\n\n const resolvedBaseUrl = new URL(ensureSlash(baseUrl), registryAbs).href\n return new URL(resourcePath, resolvedBaseUrl).href\n}\n\n@Inject(['storage', 'preferences', 'resourceLoader'])\nexport class PluginPluginStore extends BasePlugin {\n // re-export for external usage\n static readonly PluginStoreSchemas = PluginStoreSchemas\n static REGISTRY_INFO_CACHE_TTL = 1000 * 60 * 60 * 24 // 1 day\n static REGISTRY_INFO_STORAGE_NAME = 'plugin-store-registry'\n static REGISTRY_ETAG_STORAGE_NAME = 'psreg-etag'\n private regInfoDB: AbstractIPEStorageManager<PluginStoreRegistry>\n\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'plugin-store')\n ctx.set('store', this)\n this.regInfoDB = ctx.storage.createDatabase<PluginStoreRegistry>(\n PluginPluginStore.REGISTRY_INFO_STORAGE_NAME,\n PluginPluginStore.REGISTRY_INFO_CACHE_TTL,\n 1,\n 'indexedDB'\n )\n }\n\n protected async start() {\n this._installUserPlugins()\n this._injectPreferenceUI()\n }\n\n private async _installUserPlugins() {\n const prefs = await this.ctx.preferences.get('pluginStore.plugins', [])\n if (!prefs?.length) {\n return\n }\n for (const pref of prefs) {\n this.install(pref.registry, pref.id, pref.source)\n }\n }\n\n private async _createManagementApp() {\n const ctx = await this.ctx.withInject(['store'])\n const PluginStoreApp = defineAsyncComponent(() => import('./components/PluginStoreApp.vue'))\n const app = createVueAppWithIPE(ctx, PluginStoreApp)\n return app\n }\n\n private async _injectPreferenceUI() {\n const ctx = this.ctx\n\n ctx.preferences.defineCategory({\n name: 'plugin-store',\n label: 'Plugin Store',\n description: 'Plugin Store',\n index: 90,\n autoGenerateForm: false,\n customRenderer: async ({ onUnmount }) => {\n const container = <div id=\"ipe-plugin-store-preferences-vue\"></div>\n const app = await this._createManagementApp()\n app.mount(container)\n\n onUnmount(() => {\n app.unmount()\n this.ctx.logger.debug('Plugin Store preferences app unmounted')\n })\n\n return (\n <section>\n {container}\n {/* <div className=\"theme-ipe-prose\">\n <hr />\n <div style={{ textAlign: 'center', marginBottom: '1em', fontSize: '0.8em' }}>\n 🚫 DO NOT edit fields below manually 🚫\n </div>\n </div> */}\n </section>\n )\n },\n })\n\n ctx.preferences.registerCustomConfig(\n 'plugin-store',\n Schema.object({\n 'pluginStore.registries': Schema.array(Schema.string())\n .default([\n import.meta.env.PROD\n ? Endpoints.PLUGIN_REGISTRY_URL\n : 'http://127.0.0.1:1005/src/__test__/plugin-registry/index.json',\n ])\n .description('Registry URLs')\n .hidden(),\n 'pluginStore.cdnForNpm': Schema.string()\n .description('CDN to install packages from npm')\n .default('https://cdn.jsdelivr.net/npm/{{ package }}{{ version ? \"@\" + version : \"\" }}')\n .hidden(),\n 'pluginStore.plugins': Schema.array(\n Schema.object({\n source: Schema.union(['online_manifest', 'npm']).default('online_manifest'),\n registry: Schema.string().required(),\n id: Schema.string().required(),\n })\n )\n .description('Installed plugins')\n .default([])\n .hidden(),\n }),\n 'plugin-store'\n )\n }\n\n async showModal() {\n const modal = this.ctx.modal.show({\n title: 'Plugin Store',\n sizeClass: 'small',\n })\n const container = <section id=\"ipe-plugin-store-vue\"></section>\n modal.setContent(container)\n const app = await this._createManagementApp()\n app.mount(container)\n modal.on(modal.Event.Close, () => {\n app.unmount()\n })\n return modal\n }\n\n private _installedPlugins = new Map<string, Promise<ForkScope<InPageEdit> | null>>()\n async install(\n registry: string,\n id: string,\n source: PluginStoreRegistrySource = 'online_manifest'\n ): Promise<ForkScope<InPageEdit> | null> {\n const registryInfo = await this.getRegistryInfo(registry, source)\n if (!registryInfo) {\n this.ctx.logger.warn(`Registry ${registry} not found`)\n return null\n }\n const key = `${registry}#${id}`\n if (this._installedPlugins.has(key)) {\n return (await this._installedPlugins.get(key)) ?? null\n }\n // 2) 把 registry 原始 URL 传进去,供 URL 解析使用\n const scope = this._installOneByRegistryInfo(registry, registryInfo, id)\n this._installedPlugins.set(key, scope)\n return await scope\n }\n async uninstall(registry: string, id: string): Promise<boolean> {\n const promise = this._installedPlugins.get(`${registry}#${id}`)\n if (promise === void 0) {\n return true // not installed or already uninstalled\n }\n this._installedPlugins.delete(`${registry}#${id}`)\n const scope = await promise\n if (scope) {\n return scope.dispose?.() ?? true // disposed successfully\n }\n return true // not a plugin, just removed from the list\n }\n\n async addToPreferences(registry: string, id: string) {\n let prefs =\n (await this.ctx.preferences.get<{ registry: string; id: string }[]>('pluginStore.plugins')) ||\n []\n const existed = prefs.some((p) => p.registry === registry && p.id === id)\n if (existed) {\n return true\n }\n prefs.push({ registry, id })\n await this.ctx.preferences.set('pluginStore.plugins', prefs)\n return true\n }\n async removeFromPreferences(registry: string, id: string) {\n let prefs =\n (await this.ctx.preferences.get<{ registry: string; id: string }[]>('pluginStore.plugins')) ||\n []\n prefs = prefs.filter((p) => p.registry !== registry || p.id !== id)\n await this.ctx.preferences.set('pluginStore.plugins', prefs)\n return true\n }\n\n async installAndSetPreference(registry: string, id: string) {\n await this.addToPreferences(registry, id)\n return this.install(registry, id)\n }\n async uninstallAndRemovePreference(registry: string, id: string) {\n await this.removeFromPreferences(registry, id)\n return this.uninstall(registry, id)\n }\n\n // 3) 增加 registryUrl 参数\n private async _installOneByRegistryInfo(\n registryUrl: string,\n registryInfo: PluginStoreRegistry,\n id: string\n ): Promise<ForkScope<InPageEdit> | null> {\n const baseUrl = registryInfo.base_url\n const pkg = registryInfo.packages.find((p) => p.id === id)\n if (!pkg) {\n this.ctx.logger.warn(`Package ${id} not found in registry ${registryUrl}`)\n return null\n }\n\n const loader = pkg.loader\n const { kind, entry = 'index.js', styles = [], main_export = null } = loader\n\n // 4) 统一用 resolveResourceUrl 解析入口\n let entryUrl: string | null = null\n if (kind !== 'styles') {\n if (!entry) {\n this.ctx.logger.warn(`Entry url missing for ${id}`, loader)\n return null\n }\n try {\n entryUrl = resolveResourceUrl(entry, baseUrl, registryUrl)\n } catch (e) {\n this.ctx.logger.warn(\n `Failed to resolve entry \"${entry}\" with base \"${baseUrl}\" and registry \"${registryUrl}\"`,\n e\n )\n return null\n }\n }\n\n const datasets = {\n 'data-plugin-registry': registryUrl,\n 'data-plugin-id': id,\n }\n\n let fork: ForkScope<InPageEdit> | null = null\n\n switch (kind) {\n case 'autoload': {\n fork = this.ctx.plugin({\n inject: ['resourceLoader'],\n name: `plugin-store-${registryUrl}-${id}`,\n apply: (ctx) => {\n if (!entryUrl) return\n ctx.resourceLoader.loadScript(entryUrl, { ...datasets })\n },\n })\n break\n }\n case 'module': {\n if (!entryUrl) {\n this.ctx.logger.warn(`Entry url missing for module kind, package ${id}`)\n return null\n }\n const apply = await import(/* @vite-ignore */ entryUrl).then(\n (m) => (main_export ? m[main_export] : m.default) ?? m\n )\n if (!apply) {\n this.ctx.logger.warn(`Main export ${main_export} not found in module ${entryUrl}`)\n return null\n }\n fork = this.ctx.plugin(apply)\n break\n }\n case 'umd': {\n let apply = tryGetGlobalPlugin(main_export!)\n if (!apply) {\n if (!entryUrl) {\n this.ctx.logger.warn(`Entry url missing for umd kind, package ${id}`)\n return null\n }\n await this.ctx.resourceLoader.loadScript(entryUrl, { ...datasets })\n apply = tryGetGlobalPlugin(main_export!)\n }\n if (!apply) {\n this.ctx.logger.warn(\n `Main export ${main_export} not found on globalThis after loading ${entryUrl}`\n )\n return null\n }\n fork = this.ctx.plugin(apply)\n break\n }\n case 'styles': {\n // 没有脚本,仅样式。下面统一样式注入逻辑会覆盖\n break\n }\n }\n\n // 5) 统一解析并注入样式(兼容绝对URL与相对 + base_url 的组合)\n if (styles && styles.length > 0) {\n let urls: string[] = []\n try {\n urls = styles.map((u) => resolveResourceUrl(u, baseUrl, registryUrl)).filter(Boolean)\n } catch (e) {\n this.ctx.logger.warn(`Failed to resolve styles for ${id}`, styles, e)\n }\n\n // 确保存在父 fork\n fork ||= this.ctx.plugin({ name: `plugin-store-${registryUrl}-${id}`, apply() {} })\n\n // 在子插件里加载样式,并在卸载时清理\n fork.ctx.plugin({\n inject: ['resourceLoader'],\n name: `plugin-store-${registryUrl}-${id}-styles`,\n apply: (ctx) => {\n urls.forEach((u) => ctx.resourceLoader.loadStyle(u, { ...datasets }))\n ctx.on('dispose', () => {\n try {\n urls.forEach((u) => ctx.resourceLoader.removeStyle(u))\n } catch (e) {\n console.info('styles cleanup failed', e)\n }\n })\n },\n })\n }\n\n return fork\n }\n\n validateRegistry(data: any): PluginStoreRegistry {\n return PluginStoreSchemas.Registry(data)\n }\n\n async getRegistryInfo(\n registry: string,\n source: PluginStoreRegistrySource = 'online_manifest',\n noCache = false\n ): Promise<PluginStoreRegistry> {\n try {\n let info: PluginStoreRegistry\n switch (source) {\n case 'online_manifest': {\n info = await this._fetchOnlineRegistryInfo(registry, noCache)\n this.logger.debug('Fetched registry info from online manifest', info)\n this.setRegistryCache(registry, info)\n break\n }\n default: {\n throw new Error(`Unsupported registry source: ${source}`)\n }\n }\n\n return info\n } catch (e) {\n this.ctx.logger.warn('Failed to fetch registry info', e)\n }\n\n const info = await this.getRegistryCache(registry)\n if (!info) {\n throw new Error(`Failed to fetch registry info: ${registry}`)\n }\n return info\n }\n\n private _onlineRegistryQueries = new Map<string, Promise<PluginStoreRegistry>>()\n private async _fetchOnlineRegistryInfo(\n registry: string,\n noCache = false\n ): Promise<PluginStoreRegistry> {\n if (!noCache && this._onlineRegistryQueries.has(registry)) {\n return await this._onlineRegistryQueries.get(registry)!\n }\n const task = async () => {\n const payload: RequestInit = {\n method: 'GET',\n }\n if (noCache) {\n payload.cache = 'no-store'\n }\n const response = await fetch(registry, payload)\n const data = await response.json()\n const validated = this.validateRegistry(data)\n return validated\n }\n const promise = task()\n this._onlineRegistryQueries.set(registry, promise)\n return await promise\n }\n\n private async getRegistryCache(registry: string) {\n const data = await this.regInfoDB.get(registry)\n if (data) {\n try {\n const validated = this.validateRegistry(data)\n return validated\n } catch (e) {\n this.ctx.logger.warn('Invalid cached registry', e, data)\n this.regInfoDB.delete(registry)\n }\n }\n return null\n }\n private async setRegistryCache(registry: string, data: PluginStoreRegistry) {\n return this.regInfoDB.set(registry, data)\n }\n private async deleteRegistryCache(registry: string) {\n await this.regInfoDB.delete(registry)\n }\n async clearAllRegistryCaches() {\n await this.regInfoDB.clear()\n this.ctx.logger.debug('All registry caches cleared')\n }\n\n /**\n * 刷新指定 registry 的缓存(重新从网络获取)\n */\n async refreshRegistryCache(registry: string): Promise<PluginStoreRegistry> {\n const data = await this.getRegistryInfo(registry, 'online_manifest', true)\n if (!data) {\n throw new Error(`Failed to refresh registry cache: ${registry}`)\n }\n this.ctx.logger.debug('Registry cache refreshed:', registry)\n return data\n }\n\n /**\n * 刷新所有已配置的 registry 缓存\n */\n async refreshAllRegistryCaches(): Promise<Record<string, PluginStoreRegistry | null>> {\n const registryUrls = (await this.ctx.preferences.get('pluginStore.registries')) || []\n const responses = await Promise.allSettled(\n registryUrls.map((url) => this.refreshRegistryCache(url))\n )\n const results: Record<string, PluginStoreRegistry | null> = {}\n for (const [index, response] of responses.entries()) {\n if (response.status === 'fulfilled') {\n results[registryUrls[index]] = response.value\n } else {\n results[registryUrls[index]] = null\n }\n }\n return results\n }\n}\n"],"names":["PLUGIN_STORE_REGISTRY_MANIFEST_VERSION","PluginStoreSchemas","Schema","_PluginPluginStore_decorators","_init","_a","tryGetGlobalPlugin","main_export","acc","key","resolveResourceUrl","resourcePath","baseUrl","registryUrl","ensureSlash","s","normalizedBase","registryAbs","resolvedBaseUrl","Inject","_PluginPluginStore","BasePlugin","ctx","prefs","pref","PluginStoreApp","defineAsyncComponent","createVueAppWithIPE","onUnmount","container","jsx","app","Endpoints","modal","registry","id","source","registryInfo","scope","promise","p","pkg","loader","kind","entry","styles","entryUrl","e","datasets","fork","apply","m","urls","u","data","noCache","info","payload","registryUrls","responses","url","results","index","response","__decoratorStart","__decorateElement","__runInitializers","PluginPluginStore"],"mappings":";;;AAEO,MAAMA,IAAyC;AAuC/C,IAAUC;AAAA,CAAV,CAAUA,MAAV;AACQA,EAAAA,EAAA,gBAAgB,IAAIC;AAAA,IAC/BA,EAAO,OAAO;AAAA,MACZ,MAAMA,EAAO,MAAM,CAAC,YAAY,UAAU,OAAO,QAAQ,CAAC,EAAE,WAAW,QAAQ,UAAU;AAAA,MACzF,OAAOA,EAAO,OAAA;AAAA,MACd,QAAQA,EAAO,MAAMA,EAAO,QAAQ;AAAA,MACpC,aAAaA,EAAO,OAAA;AAAA,IAAO,CAC5B;AAAA,EAAA,GAGUD,EAAA,UAAU,IAAIC;AAAA,IACzBA,EAAO,OAAO;AAAA,MACZ,IAAIA,EAAO,OAAA,EAAS,SAAA;AAAA,MACpB,MAAMA,EAAO,OAAA,EAAS,SAAA;AAAA,MACtB,SAASA,EAAO,OAAA,EAAS,SAAA;AAAA,MACzB,aAAaA,EAAO,OAAA;AAAA,MACpB,QAAQA,EAAO,OAAA;AAAA,MACf,SAASA,EAAO,OAAA;AAAA,MAChB,QAAQD,EAAA,cAAc,SAAA;AAAA,IAAS,CAChC;AAAA,EAAA,GAGUA,EAAA,qBAAqB,IAAIC;AAAA,IACpCA,EAAO,OAAO;AAAA,MACZ,MAAMA,EAAO,OAAA,EAAS,SAAA;AAAA,MACtB,OAAOA,EAAO,OAAA;AAAA,IAAO,CACtB;AAAA,EAAA,GAGUD,EAAA,qBAAqB,IAAIC;AAAA,IACpCA,EAAO,OAAO;AAAA,MACZ,MAAMA,EAAO,MAAM,CAAC,KAAK,CAAC,EAAE,SAAA,EAAW,QAAQ,KAAK;AAAA,MACpD,KAAKA,EAAO,OAAA,EAAS,SAAA;AAAA,IAAS,CAC/B;AAAA,EAAA,GAGUD,EAAA,WAAW,IAAIC;AAAA,IAC1BA,EAAO,OAAO;AAAA,MACZ,kBAAkBA,EAAO,OAAA,EAAS,IAAIF,CAAsC,EAAE,SAAA;AAAA,MAC9E,MAAME,EAAO,OAAA,EAAS,SAAA;AAAA,MACtB,UAAUA,EAAO,OAAA,EAAS,SAAA;AAAA,MAC1B,UAAUA,EAAO,OAAA;AAAA,MACjB,aAAaA,EAAO,MAAMD,EAAA,kBAAkB;AAAA,MAC5C,YAAYA,EAAA;AAAA,MACZ,UAAUC,EAAO,MAAMD,EAAA,OAAO,EAAE,SAAA;AAAA,IAAS,CAC1C;AAAA,EAAA;AACH,GA9CeA,MAAAA,IAAA,CAAA,EAAA;;;;;;;;;;;;GCzCjBE,GAAAC,GAAAC;AAmBA,MAAMC,IAAqB,CAACC,MAAwB;AAClD,MAAI,CAACA,EAAa,QAAO;AACzB,MAAI;AACF,WAAOA,EACJ,MAAM,GAAG,EACT,OAAY,CAACC,GAAKC,MAASD,KAAO,OAAOA,IAAMA,EAAIC,CAAG,GAAI,UAAiB;AAAA,EAChF,QAAQ;AACN,WAAO;AAAA,EACT;AACF,GASMC,IAAqB,CAACC,GAAsBC,GAAiBC,MAAgC;AAEjG,MAAI,gBAAgB,KAAKF,CAAY,EAAG,QAAOA;AAG/C,QAAMG,IAAc,CAACC,MAAeA,EAAE,SAAS,GAAG,IAAIA,IAAIA,IAAI;AAG9D,MAAI,gBAAgB,KAAKH,CAAO,GAAG;AACjC,UAAMI,IAAiBF,EAAYF,CAAO;AAC1C,WAAO,IAAI,IAAID,GAAcK,CAAc,EAAE;AAAA,EAC/C;AAKA,QAAMC,KAAe,MAAM;AACzB,QAAI;AACF,aAAO,IAAI,IAAIJ,CAAW,EAAE;AAAA,IAC9B,QAAQ;AAEN,aAAO,IAAI,IAAIA,GAAa,SAAS,MAAM,EAAE;AAAA,IAC/C;AAAA,EACF,GAAA,GAEMK,IAAkB,IAAI,IAAIJ,EAAYF,CAAO,GAAGK,CAAW,EAAE;AACnE,SAAO,IAAI,IAAIN,GAAcO,CAAe,EAAE;AAChD;AAEAf,IAAA,CAACgB,EAAO,CAAC,WAAW,eAAe,gBAAgB,CAAC,CAAA;AAC7C,IAAMC,IAAN,MAAMA,WAA0Bf,IAAAgB,GAAW;AAAA,EAQhD,YAAmBC,GAAiB;AAClC,UAAMA,GAAK,CAAA,GAAI,cAAc,GADZ,KAAA,MAAAA,GAFnB,KAAQ,YAAR,QAiHA,KAAQ,wCAAwB,IAAA,GA+NhC,KAAQ,6CAA6B,IAAA,GA5UnCA,EAAI,IAAI,SAAS,IAAI,GACrB,KAAK,YAAYA,EAAI,QAAQ;AAAA,MAC3BF,EAAkB;AAAA,MAClBA,EAAkB;AAAA,MAClB;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAfA,OAAA;AAAA,SAAgB,qBAAqBnB;AAAA,EAAA;AAAA,EACrC,OAAA;AAAA,SAAO,0BAA0B,MAAO,KAAK,KAAK;AAAA,EAAA;AAAA,EAClD,OAAA;AAAA,SAAO,6BAA6B;AAAA,EAAA;AAAA,EACpC,OAAA;AAAA,SAAO,6BAA6B;AAAA,EAAA;AAAA,EAcpC,MAAgB,QAAQ;AACtB,SAAK,oBAAA,GACL,KAAK,oBAAA;AAAA,EACP;AAAA,EAEA,MAAc,sBAAsB;AAClC,UAAMsB,IAAQ,MAAM,KAAK,IAAI,YAAY,IAAI,uBAAuB,EAAE;AACtE,QAAKA,GAAO;AAGZ,iBAAWC,KAAQD;AACjB,aAAK,QAAQC,EAAK,UAAUA,EAAK,IAAIA,EAAK,MAAM;AAAA,EAEpD;AAAA,EAEA,MAAc,uBAAuB;AACnC,UAAMF,IAAM,MAAM,KAAK,IAAI,WAAW,CAAC,OAAO,CAAC,GACzCG,IAAiBC,EAAqB,MAAM,OAAO,8BAAiC,CAAC;AAE3F,WADYC,EAAoBL,GAAKG,CAAc;AAAA,EAErD;AAAA,EAEA,MAAc,sBAAsB;AAClC,UAAMH,IAAM,KAAK;AAEjB,IAAAA,EAAI,YAAY,eAAe;AAAA,MAC7B,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,MACb,OAAO;AAAA,MACP,kBAAkB;AAAA,MAClB,gBAAgB,OAAO,EAAE,WAAAM,QAAgB;AACvC,cAAMC,IAAY,gBAAAC,EAAC,OAAA,EAAI,IAAG,oCAAmC,GACvDC,IAAM,MAAM,KAAK,qBAAA;AACvB,eAAAA,EAAI,MAAMF,CAAS,GAEnBD,EAAU,MAAM;AACd,UAAAG,EAAI,QAAA,GACJ,KAAK,IAAI,OAAO,MAAM,wCAAwC;AAAA,QAChE,CAAC,GAGC,gBAAAD,EAAC,aACE,UAAAD,GAOH;AAAA,MAEJ;AAAA,IAAA,CACD,GAEDP,EAAI,YAAY;AAAA,MACd;AAAA,MACApB,EAAO,OAAO;AAAA,QACZ,0BAA0BA,EAAO,MAAMA,EAAO,OAAA,CAAQ,EACnD,QAAQ;AAAA,UAEH8B,EAAU;AAAA,QACV,CACL,EACA,YAAY,eAAe,EAC3B,OAAA;AAAA,QACH,yBAAyB9B,EAAO,OAAA,EAC7B,YAAY,kCAAkC,EAC9C,QAAQ,8EAA8E,EACtF,OAAA;AAAA,QACH,uBAAuBA,EAAO;AAAA,UAC5BA,EAAO,OAAO;AAAA,YACZ,QAAQA,EAAO,MAAM,CAAC,mBAAmB,KAAK,CAAC,EAAE,QAAQ,iBAAiB;AAAA,YAC1E,UAAUA,EAAO,OAAA,EAAS,SAAA;AAAA,YAC1B,IAAIA,EAAO,OAAA,EAAS,SAAA;AAAA,UAAS,CAC9B;AAAA,QAAA,EAEA,YAAY,mBAAmB,EAC/B,QAAQ,CAAA,CAAE,EACV,OAAA;AAAA,MAAO,CACX;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,YAAY;AAChB,UAAM+B,IAAQ,KAAK,IAAI,MAAM,KAAK;AAAA,MAChC,OAAO;AAAA,MACP,WAAW;AAAA,IAAA,CACZ,GACKJ,IAAY,gBAAAC,EAAC,WAAA,EAAQ,IAAG,wBAAuB;AACrD,IAAAG,EAAM,WAAWJ,CAAS;AAC1B,UAAME,IAAM,MAAM,KAAK,qBAAA;AACvB,WAAAA,EAAI,MAAMF,CAAS,GACnBI,EAAM,GAAGA,EAAM,MAAM,OAAO,MAAM;AAChC,MAAAF,EAAI,QAAA;AAAA,IACN,CAAC,GACME;AAAA,EACT;AAAA,EAGA,MAAM,QACJC,GACAC,GACAC,IAAoC,mBACG;AACvC,UAAMC,IAAe,MAAM,KAAK,gBAAgBH,GAAUE,CAAM;AAChE,QAAI,CAACC;AACH,kBAAK,IAAI,OAAO,KAAK,YAAYH,CAAQ,YAAY,GAC9C;AAET,UAAMzB,IAAM,GAAGyB,CAAQ,IAAIC,CAAE;AAC7B,QAAI,KAAK,kBAAkB,IAAI1B,CAAG;AAChC,aAAQ,MAAM,KAAK,kBAAkB,IAAIA,CAAG,KAAM;AAGpD,UAAM6B,IAAQ,KAAK,0BAA0BJ,GAAUG,GAAcF,CAAE;AACvE,gBAAK,kBAAkB,IAAI1B,GAAK6B,CAAK,GAC9B,MAAMA;AAAA,EACf;AAAA,EACA,MAAM,UAAUJ,GAAkBC,GAA8B;AAC9D,UAAMI,IAAU,KAAK,kBAAkB,IAAI,GAAGL,CAAQ,IAAIC,CAAE,EAAE;AAC9D,QAAII,MAAY;AACd,aAAO;AAET,SAAK,kBAAkB,OAAO,GAAGL,CAAQ,IAAIC,CAAE,EAAE;AACjD,UAAMG,IAAQ,MAAMC;AACpB,WAAID,IACKA,EAAM,eAAe,KAEvB;AAAA,EACT;AAAA,EAEA,MAAM,iBAAiBJ,GAAkBC,GAAY;AACnD,QAAIZ,IACD,MAAM,KAAK,IAAI,YAAY,IAAwC,qBAAqB,KACzF,CAAA;AAEF,WADgBA,EAAM,KAAK,CAACiB,MAAMA,EAAE,aAAaN,KAAYM,EAAE,OAAOL,CAAE,MAIxEZ,EAAM,KAAK,EAAE,UAAAW,GAAU,IAAAC,EAAA,CAAI,GAC3B,MAAM,KAAK,IAAI,YAAY,IAAI,uBAAuBZ,CAAK,IACpD;AAAA,EACT;AAAA,EACA,MAAM,sBAAsBW,GAAkBC,GAAY;AACxD,QAAIZ,IACD,MAAM,KAAK,IAAI,YAAY,IAAwC,qBAAqB,KACzF,CAAA;AACF,WAAAA,IAAQA,EAAM,OAAO,CAACiB,MAAMA,EAAE,aAAaN,KAAYM,EAAE,OAAOL,CAAE,GAClE,MAAM,KAAK,IAAI,YAAY,IAAI,uBAAuBZ,CAAK,GACpD;AAAA,EACT;AAAA,EAEA,MAAM,wBAAwBW,GAAkBC,GAAY;AAC1D,iBAAM,KAAK,iBAAiBD,GAAUC,CAAE,GACjC,KAAK,QAAQD,GAAUC,CAAE;AAAA,EAClC;AAAA,EACA,MAAM,6BAA6BD,GAAkBC,GAAY;AAC/D,iBAAM,KAAK,sBAAsBD,GAAUC,CAAE,GACtC,KAAK,UAAUD,GAAUC,CAAE;AAAA,EACpC;AAAA;AAAA,EAGA,MAAc,0BACZtB,GACAwB,GACAF,GACuC;AACvC,UAAMvB,IAAUyB,EAAa,UACvBI,IAAMJ,EAAa,SAAS,KAAK,CAACG,MAAMA,EAAE,OAAOL,CAAE;AACzD,QAAI,CAACM;AACH,kBAAK,IAAI,OAAO,KAAK,WAAWN,CAAE,0BAA0BtB,CAAW,EAAE,GAClE;AAGT,UAAM6B,IAASD,EAAI,QACb,EAAE,MAAAE,GAAM,OAAAC,IAAQ,YAAY,QAAAC,IAAS,IAAI,aAAAtC,IAAc,KAAA,IAASmC;AAGtE,QAAII,IAA0B;AAC9B,QAAIH,MAAS,UAAU;AACrB,UAAI,CAACC;AACH,oBAAK,IAAI,OAAO,KAAK,yBAAyBT,CAAE,IAAIO,CAAM,GACnD;AAET,UAAI;AACF,QAAAI,IAAWpC,EAAmBkC,GAAOhC,GAASC,CAAW;AAAA,MAC3D,SAASkC,GAAG;AACV,oBAAK,IAAI,OAAO;AAAA,UACd,4BAA4BH,CAAK,gBAAgBhC,CAAO,mBAAmBC,CAAW;AAAA,UACtFkC;AAAA,QAAA,GAEK;AAAA,MACT;AAAA,IACF;AAEA,UAAMC,IAAW;AAAA,MACf,wBAAwBnC;AAAA,MACxB,kBAAkBsB;AAAA,IAAA;AAGpB,QAAIc,IAAqC;AAEzC,YAAQN,GAAA;AAAA,MACN,KAAK,YAAY;AACf,QAAAM,IAAO,KAAK,IAAI,OAAO;AAAA,UACrB,QAAQ,CAAC,gBAAgB;AAAA,UACzB,MAAM,gBAAgBpC,CAAW,IAAIsB,CAAE;AAAA,UACvC,OAAO,CAACb,MAAQ;AACd,YAAKwB,KACLxB,EAAI,eAAe,WAAWwB,GAAU,EAAE,GAAGE,GAAU;AAAA,UACzD;AAAA,QAAA,CACD;AACD;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,YAAI,CAACF;AACH,sBAAK,IAAI,OAAO,KAAK,8CAA8CX,CAAE,EAAE,GAChE;AAET,cAAMe,IAAQ,MAAM;AAAA;AAAA,UAA0BJ;AAAA,UAAU;AAAA,UACtD,CAACK,OAAO5C,IAAc4C,EAAE5C,CAAW,IAAI4C,EAAE,YAAYA;AAAA,QAAA;AAEvD,YAAI,CAACD;AACH,sBAAK,IAAI,OAAO,KAAK,eAAe3C,CAAW,wBAAwBuC,CAAQ,EAAE,GAC1E;AAET,QAAAG,IAAO,KAAK,IAAI,OAAOC,CAAK;AAC5B;AAAA,MACF;AAAA,MACA,KAAK,OAAO;AACV,YAAIA,IAAQ5C,EAAmBC,CAAY;AAC3C,YAAI,CAAC2C,GAAO;AACV,cAAI,CAACJ;AACH,wBAAK,IAAI,OAAO,KAAK,2CAA2CX,CAAE,EAAE,GAC7D;AAET,gBAAM,KAAK,IAAI,eAAe,WAAWW,GAAU,EAAE,GAAGE,GAAU,GAClEE,IAAQ5C,EAAmBC,CAAY;AAAA,QACzC;AACA,YAAI,CAAC2C;AACH,sBAAK,IAAI,OAAO;AAAA,YACd,eAAe3C,CAAW,0CAA0CuC,CAAQ;AAAA,UAAA,GAEvE;AAET,QAAAG,IAAO,KAAK,IAAI,OAAOC,CAAK;AAC5B;AAAA,MACF;AAAA,IAIA;AAIF,QAAIL,KAAUA,EAAO,SAAS,GAAG;AAC/B,UAAIO,IAAiB,CAAA;AACrB,UAAI;AACF,QAAAA,IAAOP,EAAO,IAAI,CAAC,MAAMnC,EAAmB,GAAGE,GAASC,CAAW,CAAC,EAAE,OAAO,OAAO;AAAA,MACtF,SAASkC,GAAG;AACV,aAAK,IAAI,OAAO,KAAK,gCAAgCZ,CAAE,IAAIU,GAAQE,CAAC;AAAA,MACtE;AAGA,MAAAE,MAAS,KAAK,IAAI,OAAO,EAAE,MAAM,gBAAgBpC,CAAW,IAAIsB,CAAE,IAAI,QAAQ;AAAA,MAAC,GAAG,GAGlFc,EAAK,IAAI,OAAO;AAAA,QACd,QAAQ,CAAC,gBAAgB;AAAA,QACzB,MAAM,gBAAgBpC,CAAW,IAAIsB,CAAE;AAAA,QACvC,OAAO,CAACb,MAAQ;AACd,UAAA8B,EAAK,QAAQ,CAACC,MAAM/B,EAAI,eAAe,UAAU+B,GAAG,EAAE,GAAGL,EAAA,CAAU,CAAC,GACpE1B,EAAI,GAAG,WAAW,MAAM;AACtB,gBAAI;AACF,cAAA8B,EAAK,QAAQ,CAACC,MAAM/B,EAAI,eAAe,YAAY+B,CAAC,CAAC;AAAA,YACvD,QAAY;AAAA,YAEZ;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MAAA,CACD;AAAA,IACH;AAEA,WAAOJ;AAAA,EACT;AAAA,EAEA,iBAAiBK,GAAgC;AAC/C,WAAOrD,EAAmB,SAASqD,CAAI;AAAA,EACzC;AAAA,EAEA,MAAM,gBACJpB,GACAE,IAAoC,mBACpCmB,IAAU,IACoB;AAC9B,QAAI;AACF,UAAIC;AACJ,cAAQpB,GAAA;AAAA,QACN,KAAK,mBAAmB;AACtBoB,UAAAA,IAAO,MAAM,KAAK,yBAAyBtB,GAAUqB,CAAO,GAC5D,KAAK,OAAO,MAAM,8CAA8CC,CAAI,GACpE,KAAK,iBAAiBtB,GAAUsB,CAAI;AACpC;AAAA,QACF;AAAA,QACA;AACE,gBAAM,IAAI,MAAM,gCAAgCpB,CAAM,EAAE;AAAA,MAC1D;AAGF,aAAOoB;AAAAA,IACT,SAAST,GAAG;AACV,WAAK,IAAI,OAAO,KAAK,iCAAiCA,CAAC;AAAA,IACzD;AAEA,UAAMS,IAAO,MAAM,KAAK,iBAAiBtB,CAAQ;AACjD,QAAI,CAACsB;AACH,YAAM,IAAI,MAAM,kCAAkCtB,CAAQ,EAAE;AAE9D,WAAOsB;AAAA,EACT;AAAA,EAGA,MAAc,yBACZtB,GACAqB,IAAU,IACoB;AAC9B,QAAI,CAACA,KAAW,KAAK,uBAAuB,IAAIrB,CAAQ;AACtD,aAAO,MAAM,KAAK,uBAAuB,IAAIA,CAAQ;AAcvD,UAAMK,KAZO,YAAY;AACvB,YAAMkB,IAAuB;AAAA,QAC3B,QAAQ;AAAA,MAAA;AAEV,MAAIF,MACFE,EAAQ,QAAQ;AAGlB,YAAMH,IAAO,OADI,MAAM,MAAMpB,GAAUuB,CAAO,GAClB,KAAA;AAE5B,aADkB,KAAK,iBAAiBH,CAAI;AAAA,IAE9C,GACgB;AAChB,gBAAK,uBAAuB,IAAIpB,GAAUK,CAAO,GAC1C,MAAMA;AAAA,EACf;AAAA,EAEA,MAAc,iBAAiBL,GAAkB;AAC/C,UAAMoB,IAAO,MAAM,KAAK,UAAU,IAAIpB,CAAQ;AAC9C,QAAIoB;AACF,UAAI;AAEF,eADkB,KAAK,iBAAiBA,CAAI;AAAA,MAE9C,SAASP,GAAG;AACV,aAAK,IAAI,OAAO,KAAK,2BAA2BA,GAAGO,CAAI,GACvD,KAAK,UAAU,OAAOpB,CAAQ;AAAA,MAChC;AAEF,WAAO;AAAA,EACT;AAAA,EACA,MAAc,iBAAiBA,GAAkBoB,GAA2B;AAC1E,WAAO,KAAK,UAAU,IAAIpB,GAAUoB,CAAI;AAAA,EAC1C;AAAA,EACA,MAAc,oBAAoBpB,GAAkB;AAClD,UAAM,KAAK,UAAU,OAAOA,CAAQ;AAAA,EACtC;AAAA,EACA,MAAM,yBAAyB;AAC7B,UAAM,KAAK,UAAU,MAAA,GACrB,KAAK,IAAI,OAAO,MAAM,6BAA6B;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,qBAAqBA,GAAgD;AACzE,UAAMoB,IAAO,MAAM,KAAK,gBAAgBpB,GAAU,mBAAmB,EAAI;AACzE,QAAI,CAACoB;AACH,YAAM,IAAI,MAAM,qCAAqCpB,CAAQ,EAAE;AAEjE,gBAAK,IAAI,OAAO,MAAM,6BAA6BA,CAAQ,GACpDoB;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,2BAAgF;AACpF,UAAMI,IAAgB,MAAM,KAAK,IAAI,YAAY,IAAI,wBAAwB,KAAM,CAAA,GAC7EC,IAAY,MAAM,QAAQ;AAAA,MAC9BD,EAAa,IAAI,CAACE,MAAQ,KAAK,qBAAqBA,CAAG,CAAC;AAAA,IAAA,GAEpDC,IAAsD,CAAA;AAC5D,eAAW,CAACC,GAAOC,CAAQ,KAAKJ,EAAU;AACxC,MAAII,EAAS,WAAW,cACtBF,EAAQH,EAAaI,CAAK,CAAC,IAAIC,EAAS,QAExCF,EAAQH,EAAaI,CAAK,CAAC,IAAI;AAGnC,WAAOD;AAAA,EACT;AACF;AAraOzD,IAAA4D,EAAA3D,CAAA;AAAMe,IAAN6C,6BADP9D,GACaiB,CAAA;AAAN8C,EAAA9D,GAAA,GAAMgB,CAAA;AAAN,IAAM+C,IAAN/C;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { j as c } from "./index-CM_6yF2v.js";
|
|
2
|
-
import { b as D, I as C, S as f } from "./index-
|
|
2
|
+
import { b as D, I as C, S as f } from "./index-DgQNTfPR.js";
|
|
3
3
|
import { R as E } from "./Preferences-DS4-CFWe.js";
|
|
4
4
|
var I = Object.create, v = Object.defineProperty, T = Object.getOwnPropertyDescriptor, y = (e, t) => (t = Symbol[e]) ? t : Symbol.for("Symbol." + e), _ = (e) => {
|
|
5
5
|
throw TypeError(e);
|
|
@@ -143,4 +143,4 @@ A(m, 1, x);
|
|
|
143
143
|
export {
|
|
144
144
|
x as PluginToolbox
|
|
145
145
|
};
|
|
146
|
-
//# sourceMappingURL=index-
|
|
146
|
+
//# sourceMappingURL=index-BRjEc8b8.js.map
|