@inpageedit/core 0.16.1 → 0.17.0

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.
Files changed (46) hide show
  1. package/dist/InPageEdit.js +1 -1
  2. package/dist/{PluginImagesUsed-DnPDXczO.js → PluginImagesUsed-CD7t5kqv.js} +2 -2
  3. package/dist/{PluginImagesUsed-DnPDXczO.js.map → PluginImagesUsed-CD7t5kqv.js.map} +1 -1
  4. package/dist/{PluginPrefSync-CDTFyM8g.js → PluginPrefSync-DgKVDgiK.js} +2 -2
  5. package/dist/{PluginPrefSync-CDTFyM8g.js.map → PluginPrefSync-DgKVDgiK.js.map} +1 -1
  6. package/dist/{PluginStoreApp-Bng4DFBZ.js → PluginStoreApp-BwiAYQMA.js} +2 -2
  7. package/dist/{PluginStoreApp-Bng4DFBZ.js.map → PluginStoreApp-BwiAYQMA.js.map} +1 -1
  8. package/dist/{PluginTemplatesUsed-oM_VzfbH.js → PluginTemplatesUsed-CmYn48Wd.js} +2 -2
  9. package/dist/{PluginTemplatesUsed-oM_VzfbH.js.map → PluginTemplatesUsed-CmYn48Wd.js.map} +1 -1
  10. package/dist/core.js +2 -2
  11. package/dist/{index-BcTomMXW.js → index-5DLUhCA3.js} +3 -3
  12. package/dist/{index-BcTomMXW.js.map → index-5DLUhCA3.js.map} +1 -1
  13. package/dist/{index-CkSHCMRN.js → index-B5UcAL5E.js} +2 -2
  14. package/dist/{index-CkSHCMRN.js.map → index-B5UcAL5E.js.map} +1 -1
  15. package/dist/{index-Bn6y0Eln.js → index-BMd6Bo6r.js} +101 -113
  16. package/dist/{index-Bn6y0Eln.js.map → index-BMd6Bo6r.js.map} +1 -1
  17. package/dist/{index-BBUv7Lv6.js → index-BTLjDVvD.js} +2 -2
  18. package/dist/{index-BBUv7Lv6.js.map → index-BTLjDVvD.js.map} +1 -1
  19. package/dist/{index-D7rUF8vA.js → index-BfW7ObKf.js} +534 -468
  20. package/dist/index-BfW7ObKf.js.map +1 -0
  21. package/dist/{index-mf_pX14E.js → index-BvHXETfl.js} +2 -2
  22. package/dist/{index-mf_pX14E.js.map → index-BvHXETfl.js.map} +1 -1
  23. package/dist/{index-BllIuJSJ.js → index-C2_G8gLW.js} +3 -3
  24. package/dist/{index-BllIuJSJ.js.map → index-C2_G8gLW.js.map} +1 -1
  25. package/dist/{index-42B3CrSO.js → index-C4ncbyR6.js} +2 -2
  26. package/dist/{index-42B3CrSO.js.map → index-C4ncbyR6.js.map} +1 -1
  27. package/dist/{index-1sZXko-X.js → index-CZ56EKIK.js} +2 -2
  28. package/dist/{index-1sZXko-X.js.map → index-CZ56EKIK.js.map} +1 -1
  29. package/dist/{index-DlCbsA25.js → index-Cjyf3z1w.js} +3 -3
  30. package/dist/{index-DlCbsA25.js.map → index-Cjyf3z1w.js.map} +1 -1
  31. package/dist/{index-TG_MTC9y.js → index-Dfp9Vp36.js} +2 -2
  32. package/dist/{index-TG_MTC9y.js.map → index-Dfp9Vp36.js.map} +1 -1
  33. package/dist/{index-CN7r2e0P.js → index-s7aFr-gn.js} +2 -2
  34. package/dist/{index-CN7r2e0P.js.map → index-s7aFr-gn.js.map} +1 -1
  35. package/dist/{index-CMmEZcB1.js → index-siZBRSp0.js} +2 -2
  36. package/dist/{index-CMmEZcB1.js.map → index-siZBRSp0.js.map} +1 -1
  37. package/dist/index.d.ts +74 -38
  38. package/dist/index.js +2 -2
  39. package/dist/plugins/index.js +12 -12
  40. package/dist/services/index.js +14 -12
  41. package/dist/style.css +1 -1
  42. package/lib/index.umd.js +15 -15
  43. package/lib/index.umd.js.map +1 -1
  44. package/lib/style.css +1 -1
  45. package/package.json +1 -1
  46. package/dist/index-D7rUF8vA.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { j as l } from "./Promise.withResolvers-C4chhLB1.js";
2
- import { d as M, g as f, R as L, a as I, S as v } from "./index-D7rUF8vA.js";
2
+ import { d as M, g as f, R as L, a as I, S as v } from "./index-BfW7ObKf.js";
3
3
  var N = Object.create, x = Object.defineProperty, q = Object.getOwnPropertyDescriptor, _ = (i, t) => (t = Symbol[i]) ? t : /* @__PURE__ */ Symbol.for("Symbol." + i), w = (i) => {
4
4
  throw TypeError(i);
5
5
  }, A = (i, t, e) => t in i ? x(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e, T = (i, t) => x(i, "name", { value: t, configurable: !0 }), C = (i) => [, , , N(i?.[_("metadata")] ?? null)], E = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], P = (i) => i !== void 0 && typeof i != "function" ? w("Function expected") : i, k = (i, t, e, n, o) => ({ kind: E[i], name: t, metadata: n, addInitializer: (r) => e._ ? w("Already initialized") : o.push(P(r || null)) }), D = (i, t) => A(t, _("metadata"), i[3]), z = (i, t, e, n) => {
@@ -192,4 +192,4 @@ z(m, 1, b);
192
192
  export {
193
193
  b as PluginToolbox
194
194
  };
195
- //# sourceMappingURL=index-TG_MTC9y.js.map
195
+ //# sourceMappingURL=index-Dfp9Vp36.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-TG_MTC9y.js","sources":["../src/plugins/toolbox/index.tsx"],"sourcesContent":["import { Inject, InPageEdit, Schema, Service } from '@/InPageEdit'\nimport { JSX, ReactElement } from 'jsx-dom'\nimport './styles.scss'\nimport { ComputeAbleSync } from '@/utils/computeable.js'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n toolbox: PluginToolbox\n }\n interface Events {\n 'toolbox/button-added'(payload: { ctx: InPageEdit; payload: ToolboxButton }): void\n 'toolbox/button-removed'(payload: { ctx: InPageEdit; payload: ToolboxButton }): void\n 'toolbox/button-clicked'(payload: {\n ctx: InPageEdit\n event: MouseEvent\n payload: ToolboxButton\n }): void\n 'toolbox/toggle'(payload: { ctx: InPageEdit; opened: boolean }): void\n }\n interface PreferencesMap {\n toolboxAlwaysShow: boolean\n }\n}\n\ninterface ToolboxButton {\n id: string\n group?: 'auto' | 'group1' | 'group2'\n icon: ComputeAbleSync<string | HTMLElement | SVGElement | ReactElement>\n tooltip?: ComputeAbleSync<string | HTMLElement>\n itemProps?: JSX.IntrinsicElements['li']\n buttonProps?: JSX.IntrinsicElements['button']\n onClick?: (event: MouseEvent) => void\n index?: number // 任意数值均可:负数靠前、正数靠后、Infinity 末尾、未传时按插入顺序\n}\n\n@RegisterPreferences(\n Schema.object({\n toolboxAlwaysShow: Schema.boolean()\n .description('Make the toolbox opened by default')\n .default(false),\n }).description('Toolbox preferences')\n)\n@Inject(['preferences'])\nexport class PluginToolbox extends Service {\n container!: HTMLElement\n\n // ==== 内部状态 ====\n private buttons: ToolboxButton[] = []\n\n // 插入顺序序列号:用于当 index 未给时保持“自然顺序”\n private seqCounter = 0\n private seqMap = new Map<string, number>() // id -> seq\n\n constructor(public ctx: InPageEdit) {\n super(ctx, 'toolbox', false)\n }\n\n protected async start(): Promise<void> {\n this.container = this.createToolbox()\n this.ctx.preferences.get('toolboxAlwaysShow').then((val) => {\n if (val) {\n this.container.classList.add('is-persistent')\n }\n })\n this.setupHoverLogic()\n document.body.appendChild(this.container)\n\n // 国际化变化时重新渲染\n this.ctx.on('i18n/changed', () => {\n console.info('i18n/changed', this.buttons)\n this.renderAll()\n })\n }\n\n protected stop(): void | Promise<void> {\n this.container?.remove()\n }\n\n private get isPersistent() {\n return this.container.classList.contains('is-persistent')\n }\n\n private setupHoverLogic() {\n let hoverTimeout: number | null = null\n\n // 鼠标进入时暂时展开\n this.container.addEventListener('mouseenter', () => {\n if (hoverTimeout) {\n clearTimeout(hoverTimeout)\n hoverTimeout = null\n }\n\n // 如果不在持久化状态,则添加hover展开效果\n if (!this.isPersistent) {\n this.container.classList.add('is-hovered')\n }\n })\n\n // 鼠标离开时收起(如果不是持久化状态)\n this.container.addEventListener('mouseleave', () => {\n if (!this.isPersistent) {\n hoverTimeout = window.setTimeout(() => {\n this.container.classList.remove('is-hovered')\n }, 150) // 延迟150ms收起,避免快速移动鼠标时闪烁\n }\n })\n }\n\n /**\n * 计算按钮动画延迟\n * @param index 按钮索引(从0开始)\n * @param totalCount 总按钮数量\n * @returns 延迟时间(秒)\n */\n private calculateButtonDelay(index: number, totalCount: number): number {\n if (totalCount <= 1) return 0\n\n // 总动画时长150ms = 0.15s\n const totalDuration = 0.15\n // 使用平方根函数创建非线性延迟,差值逐渐缩小\n const normalizedIndex = index / (totalCount - 1)\n const delay = totalDuration * Math.sqrt(normalizedIndex)\n\n return Math.round(delay * 1000) / 1000 // 保留3位小数\n }\n\n /**\n * 更新按钮组的动画延迟\n */\n private updateButtonDelays() {\n const btnGroups = this.container.querySelectorAll('.btn-group')\n\n btnGroups.forEach((group) => {\n const buttons = group.querySelectorAll('.btn-tip-group')\n const totalCount = buttons.length\n\n buttons.forEach((button, index) => {\n const delay = this.calculateButtonDelay(index, totalCount)\n ;(button as HTMLElement).style.setProperty('--transition-delay', `${delay}s`)\n ;(button as HTMLElement).style.setProperty('--max-transition-delay', '0.15s')\n })\n })\n }\n\n private createToolbox() {\n const toggler = (\n <button\n className=\"ipe-toolbox-btn\"\n id=\"toolbox-toggler\"\n onClick={() => {\n this.toggle()\n }}\n >\n {/* Font Awesome 5 Solid: Plus */}\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"448\" height=\"512\" viewBox=\"0 0 448 512\">\n <rect width=\"448\" height=\"512\" fill=\"none\" />\n <path\n fill=\"currentColor\"\n d=\"M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32\"\n />\n </svg>\n </button>\n )\n const element = (\n <div id=\"ipe-edit-toolbox\">\n <ul className=\"btn-group group1\" style={{ display: 'flex', flexDirection: 'column' }}></ul>\n <ul className=\"btn-group group2\" style={{ display: 'flex', flexDirection: 'row' }}></ul>\n {toggler}\n </div>\n )\n\n return element as HTMLElement\n }\n\n private normalizeButtonId(id: string) {\n if (!id) {\n id = Math.random().toString(36).substring(2, 8)\n }\n // 修复:正确替换空白/点/井号(保留语义,修正正则)\n return `ipe-toolbox__${id.trim()}`.replace(/[\\s.#]+/g, '-')\n }\n\n // ====== 排序与分组 ======\n private chooseAutoGroup(): 'group1' | 'group2' {\n const g1 = this.buttons.filter((b) => b.group === 'group1').length\n const g2 = this.buttons.filter((b) => b.group === 'group2').length\n return g1 <= g2 ? 'group1' : 'group2'\n }\n\n // 归一化排序键:\n // 1) 若 index 是有限数值 => 直接使用(允许负数/小数/很大数);\n // 2) 若为 Infinity / -Infinity => 自然比较;\n // 3) 若 NaN / 未提供 => 返回 null,后续用插入顺序(seq)比较。\n private orderKey(btn: ToolboxButton): number | null {\n const idx = (btn as any).index\n if (typeof idx === 'number') {\n if (Number.isNaN(idx)) return null\n return idx // 包含 Infinity 与 -Infinity\n }\n return null\n }\n\n private compareButtons = (a: ToolboxButton, b: ToolboxButton) => {\n const ak = this.orderKey(a) // number | null\n const bk = this.orderKey(b)\n\n const va = ak ?? 0\n const vb = bk ?? 0\n\n if (va < vb) return -1\n if (va > vb) return 1\n\n // 有效值相等时的细化:\n const sa = this.seqMap.get(a.id) ?? 0\n const sb = this.seqMap.get(b.id) ?? 0\n\n if (ak === null && bk === null) {\n if (sa !== sb) return sa - sb\n return 0 // 不以 id 再兜底,保持稳定排序\n }\n\n if (ak === null && bk !== null) return -1 // 无 index(按0) 优先于 数值 index=0\n if (ak !== null && bk === null) return 1\n\n // 双方都有 index 且值相等,退化到 seq;仍然相等时返回 0\n if (sa !== sb) return sa - sb\n return 0\n }\n\n // ====== 对外 API:新增/替换/删除 ======\n addButton(payload: ToolboxButton) {\n // 统一化 id(保留原意:若缺失则补)\n payload.id = (payload.id || '').trim()\n if (!payload.id) {\n this.ctx.logger('toolbox').warn('Button id is empty, generating a random one.')\n payload.id = Math.random().toString(36).slice(2, 10)\n }\n\n const existingIndex = this.buttons.findIndex((button) => button.id === payload.id)\n\n // 分组:新增时 auto,替换时默认保留原组,除非明确指定\n const nextGroup: 'group1' | 'group2' = (() => {\n if (existingIndex !== -1) {\n const old = this.buttons[existingIndex]\n return !payload.group || payload.group === 'auto' ? (old.group as any) : payload.group\n }\n return !payload.group || payload.group === 'auto' ? this.chooseAutoGroup() : payload.group\n })()\n\n // 序列号:用于 index 未提供时,保持插入顺序\n if (!this.seqMap.has(payload.id)) {\n this.seqMap.set(payload.id, this.seqCounter++)\n }\n\n if (existingIndex !== -1) {\n // 替换:保留旧的 seq,不动;index 未传则沿用旧值\n const old = this.buttons[existingIndex]\n const incomingIndex =\n typeof payload.index === 'number' && !Number.isNaN(payload.index)\n ? payload.index\n : old.index\n const merged: ToolboxButton = { ...old, ...payload, group: nextGroup, index: incomingIndex }\n\n this.buttons.splice(existingIndex, 1, merged)\n } else {\n // 新增:按给定 index 或留空;只设置组\n const incomingIndex =\n typeof payload.index === 'number' && !Number.isNaN(payload.index)\n ? payload.index\n : undefined\n const fresh: ToolboxButton = { ...payload, group: nextGroup, index: incomingIndex }\n this.buttons.push(fresh)\n }\n\n this.ctx.emit('toolbox/button-added', { ctx: this.ctx, payload })\n this.renderAll()\n }\n\n removeButton(id: string) {\n const index = this.buttons.findIndex((button) => button.id === id)\n if (index !== -1) {\n const payload = this.buttons[index]\n this.buttons.splice(index, 1)\n // 可选择是否保留 seq,使得将来同 id 重加时仍按旧顺序;这里删除时保留更合理\n this.ctx.emit('toolbox/button-removed', { ctx: this.ctx, payload })\n this.renderAll()\n }\n }\n\n // ====== 渲染 ======\n private renderButton(payload: ToolboxButton) {\n let { id, icon, index, tooltip, itemProps, buttonProps, onClick } = payload\n const normalizedId = this.normalizeButtonId(id)\n\n // 结构尽量保持,避免在 <li> 上绑定 click 造成双触发\n const element = (\n <li class=\"btn-tip-group\" id={normalizedId} data-id={id} data-index={index} {...itemProps}>\n <div class=\"btn-tip\">{computeFallbackSync(tooltip)}</div>\n <button\n id={`${normalizedId}-btn`}\n data-id={payload.id}\n class=\"ipe-toolbox-btn\"\n onClick={(e: any) => {\n onClick?.(e as MouseEvent)\n this.ctx.emit('toolbox/button-clicked', {\n ctx: this.ctx,\n event: e as MouseEvent,\n payload,\n })\n }}\n {...buttonProps}\n >\n {computeFallbackSync(icon)}\n </button>\n </li>\n )\n\n return element as HTMLElement\n }\n\n private renderAll() {\n const group1 = this.buttons\n .filter((b) => b.group === 'group1')\n .slice()\n .sort(this.compareButtons)\n const group2 = this.buttons\n .filter((b) => b.group === 'group2')\n .slice()\n .sort(this.compareButtons)\n\n const group1El = this.container.querySelector('.btn-group.group1') as HTMLElement\n const group2El = this.container.querySelector('.btn-group.group2') as HTMLElement\n\n group1El.innerHTML = ''\n group2El.innerHTML = ''\n\n group1.forEach((button) => {\n group1El.appendChild(this.renderButton(button))\n })\n group2.forEach((button) => {\n group2El.appendChild(this.renderButton(button))\n })\n\n // 统一更新动画延迟\n this.updateButtonDelays()\n }\n\n getContainer() {\n return this.container\n }\n\n get isOpened() {\n return (\n this.container.classList.contains('is-persistent') ||\n this.container.classList.contains('is-hovered')\n )\n }\n\n toggle(force?: boolean) {\n const isPersistent = this.isPersistent\n const newPersistent = typeof force === 'boolean' ? force : !isPersistent\n this.container.classList.toggle('is-persistent', newPersistent)\n this.container.classList.remove('is-hovered')\n this.ctx.preferences.set('toolboxAlwaysShow', newPersistent)\n this.ctx.emit('toolbox/toggle', { ctx: this.ctx, opened: this.isOpened })\n }\n}\n"],"names":["_PluginToolbox_decorators","_init","_a","RegisterPreferences","Schema","Inject","PluginToolbox","Service","ctx","a","b","ak","bk","va","vb","sa","sb","val","hoverTimeout","index","totalCount","totalDuration","normalizedIndex","delay","group","buttons","button","jsxs","jsx","id","g1","g2","btn","idx","payload","existingIndex","nextGroup","old","incomingIndex","merged","fresh","icon","tooltip","itemProps","buttonProps","onClick","normalizedId","computeFallbackSync","e","group1","group2","group1El","group2El","force","isPersistent","newPersistent","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
1
+ {"version":3,"file":"index-Dfp9Vp36.js","sources":["../src/plugins/toolbox/index.tsx"],"sourcesContent":["import { Inject, InPageEdit, Schema, Service } from '@/InPageEdit'\nimport { JSX, ReactElement } from 'jsx-dom'\nimport './styles.scss'\nimport { ComputeAbleSync } from '@/utils/computeable.js'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n toolbox: PluginToolbox\n }\n interface Events {\n 'toolbox/button-added'(payload: { ctx: InPageEdit; payload: ToolboxButton }): void\n 'toolbox/button-removed'(payload: { ctx: InPageEdit; payload: ToolboxButton }): void\n 'toolbox/button-clicked'(payload: {\n ctx: InPageEdit\n event: MouseEvent\n payload: ToolboxButton\n }): void\n 'toolbox/toggle'(payload: { ctx: InPageEdit; opened: boolean }): void\n }\n interface PreferencesMap {\n toolboxAlwaysShow: boolean\n }\n}\n\ninterface ToolboxButton {\n id: string\n group?: 'auto' | 'group1' | 'group2'\n icon: ComputeAbleSync<string | HTMLElement | SVGElement | ReactElement>\n tooltip?: ComputeAbleSync<string | HTMLElement>\n itemProps?: JSX.IntrinsicElements['li']\n buttonProps?: JSX.IntrinsicElements['button']\n onClick?: (event: MouseEvent) => void\n index?: number // 任意数值均可:负数靠前、正数靠后、Infinity 末尾、未传时按插入顺序\n}\n\n@RegisterPreferences(\n Schema.object({\n toolboxAlwaysShow: Schema.boolean()\n .description('Make the toolbox opened by default')\n .default(false),\n }).description('Toolbox preferences')\n)\n@Inject(['preferences'])\nexport class PluginToolbox extends Service {\n container!: HTMLElement\n\n // ==== 内部状态 ====\n private buttons: ToolboxButton[] = []\n\n // 插入顺序序列号:用于当 index 未给时保持“自然顺序”\n private seqCounter = 0\n private seqMap = new Map<string, number>() // id -> seq\n\n constructor(public ctx: InPageEdit) {\n super(ctx, 'toolbox', false)\n }\n\n protected async start(): Promise<void> {\n this.container = this.createToolbox()\n this.ctx.preferences.get('toolboxAlwaysShow').then((val) => {\n if (val) {\n this.container.classList.add('is-persistent')\n }\n })\n this.setupHoverLogic()\n document.body.appendChild(this.container)\n\n // 国际化变化时重新渲染\n this.ctx.on('i18n/changed', () => {\n console.info('i18n/changed', this.buttons)\n this.renderAll()\n })\n }\n\n protected stop(): void | Promise<void> {\n this.container?.remove()\n }\n\n private get isPersistent() {\n return this.container.classList.contains('is-persistent')\n }\n\n private setupHoverLogic() {\n let hoverTimeout: number | null = null\n\n // 鼠标进入时暂时展开\n this.container.addEventListener('mouseenter', () => {\n if (hoverTimeout) {\n clearTimeout(hoverTimeout)\n hoverTimeout = null\n }\n\n // 如果不在持久化状态,则添加hover展开效果\n if (!this.isPersistent) {\n this.container.classList.add('is-hovered')\n }\n })\n\n // 鼠标离开时收起(如果不是持久化状态)\n this.container.addEventListener('mouseleave', () => {\n if (!this.isPersistent) {\n hoverTimeout = window.setTimeout(() => {\n this.container.classList.remove('is-hovered')\n }, 150) // 延迟150ms收起,避免快速移动鼠标时闪烁\n }\n })\n }\n\n /**\n * 计算按钮动画延迟\n * @param index 按钮索引(从0开始)\n * @param totalCount 总按钮数量\n * @returns 延迟时间(秒)\n */\n private calculateButtonDelay(index: number, totalCount: number): number {\n if (totalCount <= 1) return 0\n\n // 总动画时长150ms = 0.15s\n const totalDuration = 0.15\n // 使用平方根函数创建非线性延迟,差值逐渐缩小\n const normalizedIndex = index / (totalCount - 1)\n const delay = totalDuration * Math.sqrt(normalizedIndex)\n\n return Math.round(delay * 1000) / 1000 // 保留3位小数\n }\n\n /**\n * 更新按钮组的动画延迟\n */\n private updateButtonDelays() {\n const btnGroups = this.container.querySelectorAll('.btn-group')\n\n btnGroups.forEach((group) => {\n const buttons = group.querySelectorAll('.btn-tip-group')\n const totalCount = buttons.length\n\n buttons.forEach((button, index) => {\n const delay = this.calculateButtonDelay(index, totalCount)\n ;(button as HTMLElement).style.setProperty('--transition-delay', `${delay}s`)\n ;(button as HTMLElement).style.setProperty('--max-transition-delay', '0.15s')\n })\n })\n }\n\n private createToolbox() {\n const toggler = (\n <button\n className=\"ipe-toolbox-btn\"\n id=\"toolbox-toggler\"\n onClick={() => {\n this.toggle()\n }}\n >\n {/* Font Awesome 5 Solid: Plus */}\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"448\" height=\"512\" viewBox=\"0 0 448 512\">\n <rect width=\"448\" height=\"512\" fill=\"none\" />\n <path\n fill=\"currentColor\"\n d=\"M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32\"\n />\n </svg>\n </button>\n )\n const element = (\n <div id=\"ipe-edit-toolbox\">\n <ul className=\"btn-group group1\" style={{ display: 'flex', flexDirection: 'column' }}></ul>\n <ul className=\"btn-group group2\" style={{ display: 'flex', flexDirection: 'row' }}></ul>\n {toggler}\n </div>\n )\n\n return element as HTMLElement\n }\n\n private normalizeButtonId(id: string) {\n if (!id) {\n id = Math.random().toString(36).substring(2, 8)\n }\n // 修复:正确替换空白/点/井号(保留语义,修正正则)\n return `ipe-toolbox__${id.trim()}`.replace(/[\\s.#]+/g, '-')\n }\n\n // ====== 排序与分组 ======\n private chooseAutoGroup(): 'group1' | 'group2' {\n const g1 = this.buttons.filter((b) => b.group === 'group1').length\n const g2 = this.buttons.filter((b) => b.group === 'group2').length\n return g1 <= g2 ? 'group1' : 'group2'\n }\n\n // 归一化排序键:\n // 1) 若 index 是有限数值 => 直接使用(允许负数/小数/很大数);\n // 2) 若为 Infinity / -Infinity => 自然比较;\n // 3) 若 NaN / 未提供 => 返回 null,后续用插入顺序(seq)比较。\n private orderKey(btn: ToolboxButton): number | null {\n const idx = (btn as any).index\n if (typeof idx === 'number') {\n if (Number.isNaN(idx)) return null\n return idx // 包含 Infinity 与 -Infinity\n }\n return null\n }\n\n private compareButtons = (a: ToolboxButton, b: ToolboxButton) => {\n const ak = this.orderKey(a) // number | null\n const bk = this.orderKey(b)\n\n const va = ak ?? 0\n const vb = bk ?? 0\n\n if (va < vb) return -1\n if (va > vb) return 1\n\n // 有效值相等时的细化:\n const sa = this.seqMap.get(a.id) ?? 0\n const sb = this.seqMap.get(b.id) ?? 0\n\n if (ak === null && bk === null) {\n if (sa !== sb) return sa - sb\n return 0 // 不以 id 再兜底,保持稳定排序\n }\n\n if (ak === null && bk !== null) return -1 // 无 index(按0) 优先于 数值 index=0\n if (ak !== null && bk === null) return 1\n\n // 双方都有 index 且值相等,退化到 seq;仍然相等时返回 0\n if (sa !== sb) return sa - sb\n return 0\n }\n\n // ====== 对外 API:新增/替换/删除 ======\n addButton(payload: ToolboxButton) {\n // 统一化 id(保留原意:若缺失则补)\n payload.id = (payload.id || '').trim()\n if (!payload.id) {\n this.ctx.logger('toolbox').warn('Button id is empty, generating a random one.')\n payload.id = Math.random().toString(36).slice(2, 10)\n }\n\n const existingIndex = this.buttons.findIndex((button) => button.id === payload.id)\n\n // 分组:新增时 auto,替换时默认保留原组,除非明确指定\n const nextGroup: 'group1' | 'group2' = (() => {\n if (existingIndex !== -1) {\n const old = this.buttons[existingIndex]\n return !payload.group || payload.group === 'auto' ? (old.group as any) : payload.group\n }\n return !payload.group || payload.group === 'auto' ? this.chooseAutoGroup() : payload.group\n })()\n\n // 序列号:用于 index 未提供时,保持插入顺序\n if (!this.seqMap.has(payload.id)) {\n this.seqMap.set(payload.id, this.seqCounter++)\n }\n\n if (existingIndex !== -1) {\n // 替换:保留旧的 seq,不动;index 未传则沿用旧值\n const old = this.buttons[existingIndex]\n const incomingIndex =\n typeof payload.index === 'number' && !Number.isNaN(payload.index)\n ? payload.index\n : old.index\n const merged: ToolboxButton = { ...old, ...payload, group: nextGroup, index: incomingIndex }\n\n this.buttons.splice(existingIndex, 1, merged)\n } else {\n // 新增:按给定 index 或留空;只设置组\n const incomingIndex =\n typeof payload.index === 'number' && !Number.isNaN(payload.index)\n ? payload.index\n : undefined\n const fresh: ToolboxButton = { ...payload, group: nextGroup, index: incomingIndex }\n this.buttons.push(fresh)\n }\n\n this.ctx.emit('toolbox/button-added', { ctx: this.ctx, payload })\n this.renderAll()\n }\n\n removeButton(id: string) {\n const index = this.buttons.findIndex((button) => button.id === id)\n if (index !== -1) {\n const payload = this.buttons[index]\n this.buttons.splice(index, 1)\n // 可选择是否保留 seq,使得将来同 id 重加时仍按旧顺序;这里删除时保留更合理\n this.ctx.emit('toolbox/button-removed', { ctx: this.ctx, payload })\n this.renderAll()\n }\n }\n\n // ====== 渲染 ======\n private renderButton(payload: ToolboxButton) {\n let { id, icon, index, tooltip, itemProps, buttonProps, onClick } = payload\n const normalizedId = this.normalizeButtonId(id)\n\n // 结构尽量保持,避免在 <li> 上绑定 click 造成双触发\n const element = (\n <li class=\"btn-tip-group\" id={normalizedId} data-id={id} data-index={index} {...itemProps}>\n <div class=\"btn-tip\">{computeFallbackSync(tooltip)}</div>\n <button\n id={`${normalizedId}-btn`}\n data-id={payload.id}\n class=\"ipe-toolbox-btn\"\n onClick={(e: any) => {\n onClick?.(e as MouseEvent)\n this.ctx.emit('toolbox/button-clicked', {\n ctx: this.ctx,\n event: e as MouseEvent,\n payload,\n })\n }}\n {...buttonProps}\n >\n {computeFallbackSync(icon)}\n </button>\n </li>\n )\n\n return element as HTMLElement\n }\n\n private renderAll() {\n const group1 = this.buttons\n .filter((b) => b.group === 'group1')\n .slice()\n .sort(this.compareButtons)\n const group2 = this.buttons\n .filter((b) => b.group === 'group2')\n .slice()\n .sort(this.compareButtons)\n\n const group1El = this.container.querySelector('.btn-group.group1') as HTMLElement\n const group2El = this.container.querySelector('.btn-group.group2') as HTMLElement\n\n group1El.innerHTML = ''\n group2El.innerHTML = ''\n\n group1.forEach((button) => {\n group1El.appendChild(this.renderButton(button))\n })\n group2.forEach((button) => {\n group2El.appendChild(this.renderButton(button))\n })\n\n // 统一更新动画延迟\n this.updateButtonDelays()\n }\n\n getContainer() {\n return this.container\n }\n\n get isOpened() {\n return (\n this.container.classList.contains('is-persistent') ||\n this.container.classList.contains('is-hovered')\n )\n }\n\n toggle(force?: boolean) {\n const isPersistent = this.isPersistent\n const newPersistent = typeof force === 'boolean' ? force : !isPersistent\n this.container.classList.toggle('is-persistent', newPersistent)\n this.container.classList.remove('is-hovered')\n this.ctx.preferences.set('toolboxAlwaysShow', newPersistent)\n this.ctx.emit('toolbox/toggle', { ctx: this.ctx, opened: this.isOpened })\n }\n}\n"],"names":["_PluginToolbox_decorators","_init","_a","RegisterPreferences","Schema","Inject","PluginToolbox","Service","ctx","a","b","ak","bk","va","vb","sa","sb","val","hoverTimeout","index","totalCount","totalDuration","normalizedIndex","delay","group","buttons","button","jsxs","jsx","id","g1","g2","btn","idx","payload","existingIndex","nextGroup","old","incomingIndex","merged","fresh","icon","tooltip","itemProps","buttonProps","onClick","normalizedId","computeFallbackSync","e","group1","group2","group1El","group2El","force","isPersistent","newPersistent","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { j as i, F as y, P as Q } from "./Promise.withResolvers-C4chhLB1.js";
2
- import { a as R, R as $, S as d } from "./index-D7rUF8vA.js";
2
+ import { a as R, R as $, S as d } from "./index-BfW7ObKf.js";
3
3
  import { WatchlistAction as f } from "./models/index.js";
4
4
  import { m as U } from "./makeCallable-Cg4zUG4c.js";
5
5
  import { BasePlugin as W } from "./core.js";
@@ -426,4 +426,4 @@ let ge = S;
426
426
  export {
427
427
  ge as PluginQuickEdit
428
428
  };
429
- //# sourceMappingURL=index-CN7r2e0P.js.map
429
+ //# sourceMappingURL=index-s7aFr-gn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-CN7r2e0P.js","sources":["../src/utils/sleep.ts","../src/plugins/quick-edit/index.tsx"],"sourcesContent":["export const sleep = (ms: number = 0) =>\n new Promise((resolve) => setTimeout(resolve, ms))\n","import { Inject, InPageEdit, Schema } from '@/InPageEdit'\nimport { IWikiPage } from '@/models/WikiPage'\nimport { WatchlistAction } from '@/models/WikiPage/types/WatchlistAction'\nimport { IPEModal } from '@inpageedit/modal'\nimport { ReactNode } from 'jsx-dom'\nimport { makeCallable } from '@/utils/makeCallable.js'\nimport { MediaWikiApiError } from 'wiki-saikou'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n quickEdit: PluginQuickEdit & {\n (...args: Parameters<PluginQuickEdit['showModal']>): ReturnType<PluginQuickEdit['showModal']>\n }\n }\n interface Events {\n 'quick-edit/init-options'(payload: Omit<QuickEditEventPayload, 'modal' | 'wikiPage'>): void\n 'quick-edit/show-modal'(payload: Omit<QuickEditEventPayload, 'wikiPage'>): void\n 'quick-edit/wiki-page'(payload: QuickEditEventPayload): void\n 'quick-edit/edit-notice'(payload: QuickEditEventPayload & { editNotices: ReactNode[] }): void\n 'quick-edit/submit'(payload: QuickEditSubmitPayload & { ctx: InPageEdit }): void\n }\n interface PreferencesMap {\n 'quickEdit.editSummary': string\n 'quickEdit.editMinor': boolean\n 'quickEdit.outSideClose': boolean\n 'quickEdit.watchList': WatchlistAction\n 'quickEdit.keyshortcut.save': string\n 'quickEdit.editFont': string\n }\n}\n\nexport interface QuickEditOptions {\n title: string\n pageId: number\n revision: number\n /**\n * - `undefined` for full article edit\n * - `0` for the first section\n * - `\"new\"` for a new section\n */\n section: number | 'new' | undefined\n editMinor: boolean\n editSummary: string\n createOnly: boolean\n reloadAfterSave: boolean\n}\n\nexport interface QuickEditEventPayload {\n ctx: InPageEdit\n options: QuickEditOptions\n modal: IPEModal\n wikiPage: IWikiPage\n}\n\nexport interface QuickEditSubmitPayload {\n wikiPage: IWikiPage\n text?: string\n summary?: string\n section?: number | 'new' | undefined\n minor?: boolean\n createonly?: boolean\n recreate?: boolean\n watchlist?: WatchlistAction\n}\n\n@Inject(['api', 'wikiPage', 'wikiTitle', 'currentPage', 'wiki', 'modal', 'preferences', '$'])\n@RegisterPreferences(\n Schema.object({\n 'quickEdit.editSummary': Schema.string()\n .description('Default edit summary for quick edits')\n .default('[IPE-NEXT] Quick edit'),\n 'quickEdit.editMinor': Schema.boolean()\n .description('Default to checking \"minor edit\" option')\n .default(false),\n 'quickEdit.outSideClose': Schema.boolean()\n .description('Close editor modal by clicking outside')\n .default(true),\n 'quickEdit.watchList': Schema.union([\n Schema.const(WatchlistAction.preferences).description('Follow MW preferences'),\n Schema.const(WatchlistAction.nochange).description('Keep the current watchlist status'),\n Schema.const(WatchlistAction.watch).description('Add the page to watchlist'),\n Schema.const(WatchlistAction.unwatch).description('Remove the page from watchlist'),\n ])\n .description('Watchlist options')\n .default(WatchlistAction.preferences),\n 'quickEdit.keyshortcut.save': Schema.string()\n .default('ctrl-s')\n .description('save button key shortcut (blank to disable)'),\n 'quickEdit.editFont': Schema.union([\n Schema.const('preferences').description('Follow MW preferences'),\n Schema.const('monospace').description('Monospace'),\n Schema.const('sans-serif').description('Sans-serif'),\n Schema.const('serif').description('Serif'),\n Schema.string().description('Custom font (same as CSS `font-family` property)').default(''),\n ])\n .description(\"Font to use in quick edit's textarea\")\n .default('preferences'),\n })\n .description('Quick edit options')\n .extra('category', 'editor')\n)\nexport class PluginQuickEdit extends BasePlugin {\n private readonly DEFAULT_OPTIONS: QuickEditOptions = {\n title: '',\n pageId: 0,\n revision: 0,\n section: undefined,\n editMinor: false,\n editSummary: '',\n createOnly: false,\n reloadAfterSave: true,\n }\n\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'quick-edit')\n this.ctx.root.set('quickEdit', makeCallable(this, 'showModal'))\n }\n\n protected start(): Promise<void> | void {\n this.ctx.inject(['toolbox'], (ctx) => {\n this.injectToolbox(ctx)\n ctx.on('dispose', () => {\n this.removeToolbox(ctx)\n })\n })\n }\n\n async showModal(payload?: string | Partial<QuickEditOptions>) {\n const { $ } = this.ctx\n if (typeof payload === 'undefined') {\n payload = {}\n } else if (typeof payload === 'string') {\n payload = {\n title: payload,\n } as Partial<QuickEditOptions>\n }\n\n // @ts-expect-error legacy `page` option\n if (payload?.page) {\n // @ts-expect-error\n payload.title = payload.page\n // @ts-expect-error\n delete payload.page\n }\n\n if (!payload.title && !payload.pageId && !payload.revision) {\n this.logger.warn('None of the title, pageId or revision provided. Using defaults.')\n const searchParams = new URLSearchParams(window.location.search)\n const title = this.ctx.currentPage.wikiTitle\n payload = {\n ...payload,\n title: title?.getPrefixedDBKey(),\n revision: searchParams.has('oldid') ? Number(searchParams.get('oldid')) : undefined,\n pageId: searchParams.has('curid') ? Number(searchParams.get('curid')) : undefined,\n }\n }\n\n if (!payload.revision && !payload.pageId && payload.title) {\n const realTarget = this.ctx.wikiTitle.resolveSpecialPageTarget(payload.title)\n if (realTarget && realTarget.title.getNamespaceId() >= 0) {\n payload.title = realTarget.title.getPrefixedDBKey()\n payload.section ??= realTarget.section\n }\n }\n\n const outSideClose = (await this.ctx.preferences.get('quickEdit.outSideClose'))!\n const watchList = (await this.ctx.preferences.get('quickEdit.watchList'))!\n const editSummary =\n typeof payload.editSummary === 'string'\n ? payload.editSummary\n : (await this.ctx.preferences.get('quickEdit.editSummary'))!\n const editMinor =\n typeof payload.editMinor === 'boolean'\n ? payload.editMinor\n : (await this.ctx.preferences.get('quickEdit.editMinor'))!\n const fontOptions = await this.getEditFontOptions()\n\n const options: QuickEditOptions = {\n ...this.DEFAULT_OPTIONS,\n editSummary,\n editMinor,\n ...payload,\n }\n if (!options.editSummary) {\n options.editSummary = (await this.ctx.preferences.get('quickEdit.editSummary')) || ''\n }\n this.ctx.emit('quick-edit/init-options', { ctx: this.ctx, options })\n\n const modal = this.ctx.modal\n .createObject({\n className: 'ipe-quickEdit',\n sizeClass: 'large',\n // backdrop: false,\n // draggable: true,\n center: false,\n outSideClose,\n })\n .init()\n modal.setTitle(\n (\n <>\n Loading: <u>{options.title}</u>\n </>\n ) as HTMLElement\n )\n modal.setContent(\n (\n <section\n className=\"ipe-quickEdit-loading\"\n style={{\n height: '70vh',\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <ProgressBar />\n </section>\n ) as HTMLElement\n )\n modal.addButton({\n side: 'right',\n type: 'button',\n className: 'is-danger is-ghost',\n label: $`Cancel`,\n method() {\n modal.close()\n },\n })\n modal.show()\n this.ctx.emit('quick-edit/show-modal', { ctx: this.ctx, modal, options })\n\n let wikiPage: IWikiPage\n try {\n wikiPage = await this.getWikiPageFromPayload(options)\n if (wikiPage.pageInfo.special) {\n throw new Error($`Special page is not editable.`)\n }\n } catch (e) {\n modal.off(modal.Event.Close)\n modal.close()\n this.ctx.modal.notify('error', {\n content: e instanceof Error ? e.message : String(e),\n })\n return\n }\n\n const edittingContent = options.section === 'new' ? '' : wikiPage.revisions[0]?.content || ''\n const edittingRevId = wikiPage.revisions[0]?.revid\n const isEdittingOld = edittingRevId && edittingRevId !== wikiPage.lastrevid\n const isCreatingNewSection = options.section === 'new'\n const isCreatingNewPage = wikiPage.pageid === 0\n\n modal.setTitle(\n (\n <>\n {isCreatingNewSection\n ? $`New Section`\n : $`Quick ${isCreatingNewPage ? 'Create' : 'Edit'}`}\n : <u>{wikiPage.pageInfo.title}</u>\n {isEdittingOld ? ` (${$`Revision`} ${edittingRevId})` : ''}\n </>\n ) as HTMLElement\n )\n\n const editNotices = [] as ReactNode[]\n // Page not exists\n if (isCreatingNewPage) {\n editNotices.push(\n <MBox title={$`Attention`} type=\"important\">\n <p>{$`This page does not exist.`}</p>\n </MBox>\n )\n }\n // Edit based on old revision\n if (isEdittingOld) {\n editNotices.push(\n <MBox title={$`Attention`} type=\"warning\">\n <p\n innerHTML={$`You are editing a <em>historical version</em>; the content is not the latest!`}\n ></p>\n </MBox>\n )\n }\n this.ctx.emit('quick-edit/edit-notice', {\n ctx: this.ctx,\n options,\n modal,\n wikiPage,\n editNotices,\n })\n\n const editForm = (\n <form className=\"ipe-quickEdit__form\">\n <div className=\"ipe-quickEdit__notices\">{editNotices}</div>\n <div\n className=\"ipe-quickEdit__content\"\n style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}\n >\n {options.section === 'new' && (\n <>\n <InputBox\n label={$`Section title`}\n id=\"summary\"\n name=\"summary\"\n value={''}\n inputProps={{ placeholder: $`Topic for new section, this will be the h2 heading` }}\n />\n </>\n )}\n <textarea\n className={`ipe-quickEdit__textarea ${fontOptions.className}`}\n style={{ fontFamily: fontOptions.fontFamily }}\n name=\"text\"\n id=\"wpTextbox1\"\n >\n {edittingContent}\n </textarea>\n </div>\n <div\n class=\"ipe-quickEdit__options\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '1rem',\n marginTop: '1rem',\n }}\n >\n {!isCreatingNewSection && (\n <InputBox label={$`Summary`} id=\"summary\" name=\"summary\" value={options.editSummary} />\n )}\n <div className=\"ipe-input-box\">\n <label htmlFor=\"watchlist\" style={{ display: 'block' }}>\n {$`Watchlist`}\n </label>\n <div style={{ display: 'flex', gap: '1rem', whiteSpace: 'nowrap', overflowX: 'auto' }}>\n {[\n WatchlistAction.preferences,\n WatchlistAction.nochange,\n WatchlistAction.watch,\n WatchlistAction.unwatch,\n ].map((action) => (\n <RadioBox\n key={action}\n name=\"watchlist\"\n value={action}\n inputProps={{\n checked: watchList === action,\n onChange: (e) => {\n e.target &&\n (e.target as HTMLElement).closest('label')?.scrollIntoView({\n behavior: 'smooth',\n inline: 'center',\n })\n },\n }}\n >\n {$`watchlist.${action}`}\n </RadioBox>\n ))}\n </div>\n </div>\n <div style={{ display: 'flex', gap: '1rem' }}>\n <CheckBox name=\"minor\" id=\"minor\" checked={options.editMinor}>\n {$`Minor edit`}\n </CheckBox>\n <CheckBox name=\"reloadAfterSave\" id=\"reloadAfterSave\" checked={options.reloadAfterSave}>\n {$`Reload after save`}\n </CheckBox>\n </div>\n </div>\n {/* Debug Info */}\n {import.meta.env.DEV && (\n <div className=\"debug\" style={{ marginTop: '1rem' }}>\n <details>\n <pre>{JSON.stringify(wikiPage.pageInfo, null, 2)}</pre>\n </details>\n </div>\n )}\n </form>\n ) as HTMLFormElement\n modal.setContent(editForm)\n\n let dismissWarnings = false\n modal.addButton(\n {\n side: 'left',\n className: 'is-primary submit-btn',\n label: $`Submit`,\n keyPress: (await this.ctx.preferences.get('quickEdit.keyshortcut.save')) || undefined,\n method: async () => {\n const formData = new FormData(editForm)\n console.info(wikiPage, editForm, {\n text: formData.get('text') as string,\n summary: formData.get('summary') as string,\n minor: formData.get('minor') === 'on',\n })\n modal.setLoadingState(true)\n\n try {\n await this.handleSubmit({\n wikiPage,\n text: formData.get('text') as string,\n summary: formData.get('summary') as string,\n minor: formData.get('minor') === 'on',\n section: options.section,\n watchlist: watchList,\n // 如果无视风险,那么就不再尝试解决冲突,直接重建页面\n createonly: wikiPage.pageid === 0 && !dismissWarnings,\n recreate: wikiPage.pageid === 0 && dismissWarnings,\n })\n\n modal.setOptions({\n beforeClose: noop,\n })\n modal.close()\n\n this.ctx.modal.notify('success', {\n title: $`Submission Successful`,\n content: $`Your changes have been saved.`,\n })\n\n if (formData.get('reloadAfterSave')) {\n await sleep(500)\n location.reload()\n }\n } catch (error) {\n modal.setLoadingState(false)\n\n if (MediaWikiApiError.is(error)) {\n if (\n error.code === 'pagedeleted' ||\n error.code === 'editconflict' ||\n error.code === 'articleexists'\n ) {\n dismissWarnings = true\n this.ctx.modal.notify('warning', {\n title: $`Submission Error`,\n content: (\n <div>\n <p>\n <strong>{error.message}</strong>\n </p>\n <p>{$`You can try to submit again to dismiss the warnings.`}</p>\n </div>\n ),\n closeAfter: 15 * 1000,\n })\n return // can be dismissed by re-submission\n }\n }\n\n // Errors not handled above\n this.ctx.modal.notify('error', {\n title: $`Submission Error`,\n content: error instanceof Error ? error.message : String(error),\n })\n }\n },\n },\n 0\n )\n modal.setOptions({\n beforeClose: () => {\n const oldStr = wikiPage.revisions[0]?.content || ''\n const newStr = editForm.querySelector('textarea')?.value || ''\n if (newStr === oldStr) {\n return true\n } else {\n this.ctx.modal.confirm(\n {\n className: 'is-primary',\n title: $`Unsaved Changes`,\n content: $`All edit contents will be lost after closing the modal. Are you sure you want to close?`,\n center: true,\n okBtn: {\n label: $`Give Up`,\n className: 'is-danger is-ghost',\n },\n cancelBtn: {\n label: $`Continue Editing`,\n className: 'is-primary is-ghost',\n },\n },\n (confirmed) => {\n if (confirmed) {\n modal.setOptions({\n beforeClose: noop,\n })\n modal.close()\n }\n return true\n }\n )\n return false\n }\n },\n })\n this.ctx.emit('quick-edit/wiki-page', {\n ctx: this.ctx,\n options,\n modal,\n wikiPage,\n })\n\n const beforeUnload = (e: BeforeUnloadEvent) => {\n if (editForm.querySelector('textarea')?.value === edittingContent) {\n return true\n }\n e.preventDefault()\n return $`You have unsaved changes. Are you sure you want to leave?`\n }\n window.addEventListener('beforeunload', beforeUnload)\n modal.on(modal.Event.Close, () => {\n window.removeEventListener('beforeunload', beforeUnload)\n })\n }\n\n async handleSubmit(payload: QuickEditSubmitPayload) {\n const { wikiPage, ...rest } = payload\n\n this.ctx.emit('quick-edit/submit', {\n ctx: this.ctx,\n wikiPage,\n ...rest,\n })\n\n return wikiPage.edit({\n ...rest,\n })\n }\n\n static readonly BUILT_IN_FONT_OPTIONS = ['preferences', 'monospace', 'sans-serif', 'serif']\n async getEditFontOptions() {\n const prefEditFont = (await this.ctx.preferences.get('quickEdit.editFont'))!\n if (PluginQuickEdit.BUILT_IN_FONT_OPTIONS.includes(prefEditFont)) {\n const editfont =\n prefEditFont === 'preferences'\n ? this.ctx.wiki.userOptions?.editfont || 'monospace'\n : prefEditFont\n return {\n className: `mw-editfont-${editfont}`,\n fontFamily: '',\n }\n } else {\n return {\n className: 'mw-editfont-custom',\n fontFamily: prefEditFont,\n }\n }\n }\n\n async getWikiPageFromPayload(payload: Partial<QuickEditOptions>) {\n if (payload.revision) {\n return this.ctx.wikiPage.newFromRevision(payload.revision, payload.section)\n } else if (payload.pageId) {\n return this.ctx.wikiPage.newFromPageId(payload.pageId, payload.section)\n } else if (payload.title) {\n return this.ctx.wikiPage.newFromTitle(payload.title, false, payload.section)\n }\n throw new Error('Invalid payload')\n }\n\n private async injectToolbox(ctx: InPageEdit) {\n const { $ } = this.ctx\n const title = this.ctx.currentPage.wikiTitle\n const canEdit = title && title.getNamespaceId() >= 0\n ctx.toolbox.addButton({\n id: 'quick-edit',\n group: 'group1',\n index: 0,\n icon: (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"icon icon-tabler icons-tabler-outline icon-tabler-edit\"\n >\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\n <path d=\"M7 7h-1a2 2 0 0 0 -2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2 -2v-1\" />\n <path d=\"M20.385 6.585a2.1 2.1 0 0 0 -2.97 -2.97l-8.415 8.385v3h3l8.385 -8.415z\" />\n <path d=\"M16 5l3 3\" />\n </svg>\n ) as HTMLElement,\n buttonProps: {\n disabled: !canEdit,\n },\n tooltip: () => (canEdit ? $`Quick Edit` : $`Not editable`),\n onClick: () => {\n const revision = new URLSearchParams(window.location.search).get('oldid')\n this.showModal({\n title: title?.getPrefixedText(),\n revision: revision ? Number(revision) : undefined,\n })\n },\n })\n }\n\n protected removeToolbox(ctx: InPageEdit) {\n ctx.toolbox.removeButton('quick-edit')\n }\n\n createQuickEditButton(\n payload: Partial<QuickEditOptions>,\n options?: {\n icon?: ReactNode\n label?: ReactNode\n }\n ) {\n const { $ } = this.ctx\n const icon = options?.icon ?? <IconQuickEdit className=\"ipe-icon\" />\n const label = options?.label ?? $`Quick Edit`\n return (\n <a\n href={`#ipe://quick-edit/`}\n dataset={payload as any}\n className={`ipe-quick-edit ${payload.createOnly ? 'ipe-quick-edit--create-only' : ''}`}\n style={{\n userSelect: 'none',\n marginLeft: '0.2em',\n }}\n onClick={(e) => {\n e.preventDefault()\n this.showModal(payload)\n }}\n >\n {icon}\n {label}\n </a>\n ) as HTMLAnchorElement\n }\n}\n"],"names":["sleep","ms","resolve","_PluginQuickEdit_decorators","_init","_a","Inject","RegisterPreferences","Schema","WatchlistAction","_PluginQuickEdit","BasePlugin","ctx","makeCallable","payload","$","searchParams","title","realTarget","outSideClose","watchList","editSummary","editMinor","fontOptions","options","modal","jsxs","Fragment","jsx","ProgressBar","wikiPage","e","edittingContent","edittingRevId","isEdittingOld","isCreatingNewSection","isCreatingNewPage","editNotices","MBox","editForm","InputBox","action","RadioBox","CheckBox","dismissWarnings","formData","noop","error","MediaWikiApiError","oldStr","confirmed","beforeUnload","rest","prefEditFont","canEdit","revision","icon","IconQuickEdit","label","__decoratorStart","__decorateElement","__runInitializers","PluginQuickEdit"],"mappings":"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"}
1
+ {"version":3,"file":"index-s7aFr-gn.js","sources":["../src/utils/sleep.ts","../src/plugins/quick-edit/index.tsx"],"sourcesContent":["export const sleep = (ms: number = 0) =>\n new Promise((resolve) => setTimeout(resolve, ms))\n","import { Inject, InPageEdit, Schema } from '@/InPageEdit'\nimport { IWikiPage } from '@/models/WikiPage'\nimport { WatchlistAction } from '@/models/WikiPage/types/WatchlistAction'\nimport { IPEModal } from '@inpageedit/modal'\nimport { ReactNode } from 'jsx-dom'\nimport { makeCallable } from '@/utils/makeCallable.js'\nimport { MediaWikiApiError } from 'wiki-saikou'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n quickEdit: PluginQuickEdit & {\n (...args: Parameters<PluginQuickEdit['showModal']>): ReturnType<PluginQuickEdit['showModal']>\n }\n }\n interface Events {\n 'quick-edit/init-options'(payload: Omit<QuickEditEventPayload, 'modal' | 'wikiPage'>): void\n 'quick-edit/show-modal'(payload: Omit<QuickEditEventPayload, 'wikiPage'>): void\n 'quick-edit/wiki-page'(payload: QuickEditEventPayload): void\n 'quick-edit/edit-notice'(payload: QuickEditEventPayload & { editNotices: ReactNode[] }): void\n 'quick-edit/submit'(payload: QuickEditSubmitPayload & { ctx: InPageEdit }): void\n }\n interface PreferencesMap {\n 'quickEdit.editSummary': string\n 'quickEdit.editMinor': boolean\n 'quickEdit.outSideClose': boolean\n 'quickEdit.watchList': WatchlistAction\n 'quickEdit.keyshortcut.save': string\n 'quickEdit.editFont': string\n }\n}\n\nexport interface QuickEditOptions {\n title: string\n pageId: number\n revision: number\n /**\n * - `undefined` for full article edit\n * - `0` for the first section\n * - `\"new\"` for a new section\n */\n section: number | 'new' | undefined\n editMinor: boolean\n editSummary: string\n createOnly: boolean\n reloadAfterSave: boolean\n}\n\nexport interface QuickEditEventPayload {\n ctx: InPageEdit\n options: QuickEditOptions\n modal: IPEModal\n wikiPage: IWikiPage\n}\n\nexport interface QuickEditSubmitPayload {\n wikiPage: IWikiPage\n text?: string\n summary?: string\n section?: number | 'new' | undefined\n minor?: boolean\n createonly?: boolean\n recreate?: boolean\n watchlist?: WatchlistAction\n}\n\n@Inject(['api', 'wikiPage', 'wikiTitle', 'currentPage', 'wiki', 'modal', 'preferences', '$'])\n@RegisterPreferences(\n Schema.object({\n 'quickEdit.editSummary': Schema.string()\n .description('Default edit summary for quick edits')\n .default('[IPE-NEXT] Quick edit'),\n 'quickEdit.editMinor': Schema.boolean()\n .description('Default to checking \"minor edit\" option')\n .default(false),\n 'quickEdit.outSideClose': Schema.boolean()\n .description('Close editor modal by clicking outside')\n .default(true),\n 'quickEdit.watchList': Schema.union([\n Schema.const(WatchlistAction.preferences).description('Follow MW preferences'),\n Schema.const(WatchlistAction.nochange).description('Keep the current watchlist status'),\n Schema.const(WatchlistAction.watch).description('Add the page to watchlist'),\n Schema.const(WatchlistAction.unwatch).description('Remove the page from watchlist'),\n ])\n .description('Watchlist options')\n .default(WatchlistAction.preferences),\n 'quickEdit.keyshortcut.save': Schema.string()\n .default('ctrl-s')\n .description('save button key shortcut (blank to disable)'),\n 'quickEdit.editFont': Schema.union([\n Schema.const('preferences').description('Follow MW preferences'),\n Schema.const('monospace').description('Monospace'),\n Schema.const('sans-serif').description('Sans-serif'),\n Schema.const('serif').description('Serif'),\n Schema.string().description('Custom font (same as CSS `font-family` property)').default(''),\n ])\n .description(\"Font to use in quick edit's textarea\")\n .default('preferences'),\n })\n .description('Quick edit options')\n .extra('category', 'editor')\n)\nexport class PluginQuickEdit extends BasePlugin {\n private readonly DEFAULT_OPTIONS: QuickEditOptions = {\n title: '',\n pageId: 0,\n revision: 0,\n section: undefined,\n editMinor: false,\n editSummary: '',\n createOnly: false,\n reloadAfterSave: true,\n }\n\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'quick-edit')\n this.ctx.root.set('quickEdit', makeCallable(this, 'showModal'))\n }\n\n protected start(): Promise<void> | void {\n this.ctx.inject(['toolbox'], (ctx) => {\n this.injectToolbox(ctx)\n ctx.on('dispose', () => {\n this.removeToolbox(ctx)\n })\n })\n }\n\n async showModal(payload?: string | Partial<QuickEditOptions>) {\n const { $ } = this.ctx\n if (typeof payload === 'undefined') {\n payload = {}\n } else if (typeof payload === 'string') {\n payload = {\n title: payload,\n } as Partial<QuickEditOptions>\n }\n\n // @ts-expect-error legacy `page` option\n if (payload?.page) {\n // @ts-expect-error\n payload.title = payload.page\n // @ts-expect-error\n delete payload.page\n }\n\n if (!payload.title && !payload.pageId && !payload.revision) {\n this.logger.warn('None of the title, pageId or revision provided. Using defaults.')\n const searchParams = new URLSearchParams(window.location.search)\n const title = this.ctx.currentPage.wikiTitle\n payload = {\n ...payload,\n title: title?.getPrefixedDBKey(),\n revision: searchParams.has('oldid') ? Number(searchParams.get('oldid')) : undefined,\n pageId: searchParams.has('curid') ? Number(searchParams.get('curid')) : undefined,\n }\n }\n\n if (!payload.revision && !payload.pageId && payload.title) {\n const realTarget = this.ctx.wikiTitle.resolveSpecialPageTarget(payload.title)\n if (realTarget && realTarget.title.getNamespaceId() >= 0) {\n payload.title = realTarget.title.getPrefixedDBKey()\n payload.section ??= realTarget.section\n }\n }\n\n const outSideClose = (await this.ctx.preferences.get('quickEdit.outSideClose'))!\n const watchList = (await this.ctx.preferences.get('quickEdit.watchList'))!\n const editSummary =\n typeof payload.editSummary === 'string'\n ? payload.editSummary\n : (await this.ctx.preferences.get('quickEdit.editSummary'))!\n const editMinor =\n typeof payload.editMinor === 'boolean'\n ? payload.editMinor\n : (await this.ctx.preferences.get('quickEdit.editMinor'))!\n const fontOptions = await this.getEditFontOptions()\n\n const options: QuickEditOptions = {\n ...this.DEFAULT_OPTIONS,\n editSummary,\n editMinor,\n ...payload,\n }\n if (!options.editSummary) {\n options.editSummary = (await this.ctx.preferences.get('quickEdit.editSummary')) || ''\n }\n this.ctx.emit('quick-edit/init-options', { ctx: this.ctx, options })\n\n const modal = this.ctx.modal\n .createObject({\n className: 'ipe-quickEdit',\n sizeClass: 'large',\n // backdrop: false,\n // draggable: true,\n center: false,\n outSideClose,\n })\n .init()\n modal.setTitle(\n (\n <>\n Loading: <u>{options.title}</u>\n </>\n ) as HTMLElement\n )\n modal.setContent(\n (\n <section\n className=\"ipe-quickEdit-loading\"\n style={{\n height: '70vh',\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n <ProgressBar />\n </section>\n ) as HTMLElement\n )\n modal.addButton({\n side: 'right',\n type: 'button',\n className: 'is-danger is-ghost',\n label: $`Cancel`,\n method() {\n modal.close()\n },\n })\n modal.show()\n this.ctx.emit('quick-edit/show-modal', { ctx: this.ctx, modal, options })\n\n let wikiPage: IWikiPage\n try {\n wikiPage = await this.getWikiPageFromPayload(options)\n if (wikiPage.pageInfo.special) {\n throw new Error($`Special page is not editable.`)\n }\n } catch (e) {\n modal.off(modal.Event.Close)\n modal.close()\n this.ctx.modal.notify('error', {\n content: e instanceof Error ? e.message : String(e),\n })\n return\n }\n\n const edittingContent = options.section === 'new' ? '' : wikiPage.revisions[0]?.content || ''\n const edittingRevId = wikiPage.revisions[0]?.revid\n const isEdittingOld = edittingRevId && edittingRevId !== wikiPage.lastrevid\n const isCreatingNewSection = options.section === 'new'\n const isCreatingNewPage = wikiPage.pageid === 0\n\n modal.setTitle(\n (\n <>\n {isCreatingNewSection\n ? $`New Section`\n : $`Quick ${isCreatingNewPage ? 'Create' : 'Edit'}`}\n : <u>{wikiPage.pageInfo.title}</u>\n {isEdittingOld ? ` (${$`Revision`} ${edittingRevId})` : ''}\n </>\n ) as HTMLElement\n )\n\n const editNotices = [] as ReactNode[]\n // Page not exists\n if (isCreatingNewPage) {\n editNotices.push(\n <MBox title={$`Attention`} type=\"important\">\n <p>{$`This page does not exist.`}</p>\n </MBox>\n )\n }\n // Edit based on old revision\n if (isEdittingOld) {\n editNotices.push(\n <MBox title={$`Attention`} type=\"warning\">\n <p\n innerHTML={$`You are editing a <em>historical version</em>; the content is not the latest!`}\n ></p>\n </MBox>\n )\n }\n this.ctx.emit('quick-edit/edit-notice', {\n ctx: this.ctx,\n options,\n modal,\n wikiPage,\n editNotices,\n })\n\n const editForm = (\n <form className=\"ipe-quickEdit__form\">\n <div className=\"ipe-quickEdit__notices\">{editNotices}</div>\n <div\n className=\"ipe-quickEdit__content\"\n style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}\n >\n {options.section === 'new' && (\n <>\n <InputBox\n label={$`Section title`}\n id=\"summary\"\n name=\"summary\"\n value={''}\n inputProps={{ placeholder: $`Topic for new section, this will be the h2 heading` }}\n />\n </>\n )}\n <textarea\n className={`ipe-quickEdit__textarea ${fontOptions.className}`}\n style={{ fontFamily: fontOptions.fontFamily }}\n name=\"text\"\n id=\"wpTextbox1\"\n >\n {edittingContent}\n </textarea>\n </div>\n <div\n class=\"ipe-quickEdit__options\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '1rem',\n marginTop: '1rem',\n }}\n >\n {!isCreatingNewSection && (\n <InputBox label={$`Summary`} id=\"summary\" name=\"summary\" value={options.editSummary} />\n )}\n <div className=\"ipe-input-box\">\n <label htmlFor=\"watchlist\" style={{ display: 'block' }}>\n {$`Watchlist`}\n </label>\n <div style={{ display: 'flex', gap: '1rem', whiteSpace: 'nowrap', overflowX: 'auto' }}>\n {[\n WatchlistAction.preferences,\n WatchlistAction.nochange,\n WatchlistAction.watch,\n WatchlistAction.unwatch,\n ].map((action) => (\n <RadioBox\n key={action}\n name=\"watchlist\"\n value={action}\n inputProps={{\n checked: watchList === action,\n onChange: (e) => {\n e.target &&\n (e.target as HTMLElement).closest('label')?.scrollIntoView({\n behavior: 'smooth',\n inline: 'center',\n })\n },\n }}\n >\n {$`watchlist.${action}`}\n </RadioBox>\n ))}\n </div>\n </div>\n <div style={{ display: 'flex', gap: '1rem' }}>\n <CheckBox name=\"minor\" id=\"minor\" checked={options.editMinor}>\n {$`Minor edit`}\n </CheckBox>\n <CheckBox name=\"reloadAfterSave\" id=\"reloadAfterSave\" checked={options.reloadAfterSave}>\n {$`Reload after save`}\n </CheckBox>\n </div>\n </div>\n {/* Debug Info */}\n {import.meta.env.DEV && (\n <div className=\"debug\" style={{ marginTop: '1rem' }}>\n <details>\n <pre>{JSON.stringify(wikiPage.pageInfo, null, 2)}</pre>\n </details>\n </div>\n )}\n </form>\n ) as HTMLFormElement\n modal.setContent(editForm)\n\n let dismissWarnings = false\n modal.addButton(\n {\n side: 'left',\n className: 'is-primary submit-btn',\n label: $`Submit`,\n keyPress: (await this.ctx.preferences.get('quickEdit.keyshortcut.save')) || undefined,\n method: async () => {\n const formData = new FormData(editForm)\n console.info(wikiPage, editForm, {\n text: formData.get('text') as string,\n summary: formData.get('summary') as string,\n minor: formData.get('minor') === 'on',\n })\n modal.setLoadingState(true)\n\n try {\n await this.handleSubmit({\n wikiPage,\n text: formData.get('text') as string,\n summary: formData.get('summary') as string,\n minor: formData.get('minor') === 'on',\n section: options.section,\n watchlist: watchList,\n // 如果无视风险,那么就不再尝试解决冲突,直接重建页面\n createonly: wikiPage.pageid === 0 && !dismissWarnings,\n recreate: wikiPage.pageid === 0 && dismissWarnings,\n })\n\n modal.setOptions({\n beforeClose: noop,\n })\n modal.close()\n\n this.ctx.modal.notify('success', {\n title: $`Submission Successful`,\n content: $`Your changes have been saved.`,\n })\n\n if (formData.get('reloadAfterSave')) {\n await sleep(500)\n location.reload()\n }\n } catch (error) {\n modal.setLoadingState(false)\n\n if (MediaWikiApiError.is(error)) {\n if (\n error.code === 'pagedeleted' ||\n error.code === 'editconflict' ||\n error.code === 'articleexists'\n ) {\n dismissWarnings = true\n this.ctx.modal.notify('warning', {\n title: $`Submission Error`,\n content: (\n <div>\n <p>\n <strong>{error.message}</strong>\n </p>\n <p>{$`You can try to submit again to dismiss the warnings.`}</p>\n </div>\n ),\n closeAfter: 15 * 1000,\n })\n return // can be dismissed by re-submission\n }\n }\n\n // Errors not handled above\n this.ctx.modal.notify('error', {\n title: $`Submission Error`,\n content: error instanceof Error ? error.message : String(error),\n })\n }\n },\n },\n 0\n )\n modal.setOptions({\n beforeClose: () => {\n const oldStr = wikiPage.revisions[0]?.content || ''\n const newStr = editForm.querySelector('textarea')?.value || ''\n if (newStr === oldStr) {\n return true\n } else {\n this.ctx.modal.confirm(\n {\n className: 'is-primary',\n title: $`Unsaved Changes`,\n content: $`All edit contents will be lost after closing the modal. Are you sure you want to close?`,\n center: true,\n okBtn: {\n label: $`Give Up`,\n className: 'is-danger is-ghost',\n },\n cancelBtn: {\n label: $`Continue Editing`,\n className: 'is-primary is-ghost',\n },\n },\n (confirmed) => {\n if (confirmed) {\n modal.setOptions({\n beforeClose: noop,\n })\n modal.close()\n }\n return true\n }\n )\n return false\n }\n },\n })\n this.ctx.emit('quick-edit/wiki-page', {\n ctx: this.ctx,\n options,\n modal,\n wikiPage,\n })\n\n const beforeUnload = (e: BeforeUnloadEvent) => {\n if (editForm.querySelector('textarea')?.value === edittingContent) {\n return true\n }\n e.preventDefault()\n return $`You have unsaved changes. Are you sure you want to leave?`\n }\n window.addEventListener('beforeunload', beforeUnload)\n modal.on(modal.Event.Close, () => {\n window.removeEventListener('beforeunload', beforeUnload)\n })\n }\n\n async handleSubmit(payload: QuickEditSubmitPayload) {\n const { wikiPage, ...rest } = payload\n\n this.ctx.emit('quick-edit/submit', {\n ctx: this.ctx,\n wikiPage,\n ...rest,\n })\n\n return wikiPage.edit({\n ...rest,\n })\n }\n\n static readonly BUILT_IN_FONT_OPTIONS = ['preferences', 'monospace', 'sans-serif', 'serif']\n async getEditFontOptions() {\n const prefEditFont = (await this.ctx.preferences.get('quickEdit.editFont'))!\n if (PluginQuickEdit.BUILT_IN_FONT_OPTIONS.includes(prefEditFont)) {\n const editfont =\n prefEditFont === 'preferences'\n ? this.ctx.wiki.userOptions?.editfont || 'monospace'\n : prefEditFont\n return {\n className: `mw-editfont-${editfont}`,\n fontFamily: '',\n }\n } else {\n return {\n className: 'mw-editfont-custom',\n fontFamily: prefEditFont,\n }\n }\n }\n\n async getWikiPageFromPayload(payload: Partial<QuickEditOptions>) {\n if (payload.revision) {\n return this.ctx.wikiPage.newFromRevision(payload.revision, payload.section)\n } else if (payload.pageId) {\n return this.ctx.wikiPage.newFromPageId(payload.pageId, payload.section)\n } else if (payload.title) {\n return this.ctx.wikiPage.newFromTitle(payload.title, false, payload.section)\n }\n throw new Error('Invalid payload')\n }\n\n private async injectToolbox(ctx: InPageEdit) {\n const { $ } = this.ctx\n const title = this.ctx.currentPage.wikiTitle\n const canEdit = title && title.getNamespaceId() >= 0\n ctx.toolbox.addButton({\n id: 'quick-edit',\n group: 'group1',\n index: 0,\n icon: (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n class=\"icon icon-tabler icons-tabler-outline icon-tabler-edit\"\n >\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\n <path d=\"M7 7h-1a2 2 0 0 0 -2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2 -2v-1\" />\n <path d=\"M20.385 6.585a2.1 2.1 0 0 0 -2.97 -2.97l-8.415 8.385v3h3l8.385 -8.415z\" />\n <path d=\"M16 5l3 3\" />\n </svg>\n ) as HTMLElement,\n buttonProps: {\n disabled: !canEdit,\n },\n tooltip: () => (canEdit ? $`Quick Edit` : $`Not editable`),\n onClick: () => {\n const revision = new URLSearchParams(window.location.search).get('oldid')\n this.showModal({\n title: title?.getPrefixedText(),\n revision: revision ? Number(revision) : undefined,\n })\n },\n })\n }\n\n protected removeToolbox(ctx: InPageEdit) {\n ctx.toolbox.removeButton('quick-edit')\n }\n\n createQuickEditButton(\n payload: Partial<QuickEditOptions>,\n options?: {\n icon?: ReactNode\n label?: ReactNode\n }\n ) {\n const { $ } = this.ctx\n const icon = options?.icon ?? <IconQuickEdit className=\"ipe-icon\" />\n const label = options?.label ?? $`Quick Edit`\n return (\n <a\n href={`#ipe://quick-edit/`}\n dataset={payload as any}\n className={`ipe-quick-edit ${payload.createOnly ? 'ipe-quick-edit--create-only' : ''}`}\n style={{\n userSelect: 'none',\n marginLeft: '0.2em',\n }}\n onClick={(e) => {\n e.preventDefault()\n this.showModal(payload)\n }}\n >\n {icon}\n {label}\n </a>\n ) as HTMLAnchorElement\n }\n}\n"],"names":["sleep","ms","resolve","_PluginQuickEdit_decorators","_init","_a","Inject","RegisterPreferences","Schema","WatchlistAction","_PluginQuickEdit","BasePlugin","ctx","makeCallable","payload","$","searchParams","title","realTarget","outSideClose","watchList","editSummary","editMinor","fontOptions","options","modal","jsxs","Fragment","jsx","ProgressBar","wikiPage","e","edittingContent","edittingRevId","isEdittingOld","isCreatingNewSection","isCreatingNewPage","editNotices","MBox","editForm","InputBox","action","RadioBox","CheckBox","dismissWarnings","formData","noop","error","MediaWikiApiError","oldStr","confirmed","beforeUnload","rest","prefEditFont","canEdit","revision","icon","IconQuickEdit","label","__decoratorStart","__decorateElement","__runInitializers","PluginQuickEdit"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { j as o, F as j, P as T } from "./Promise.withResolvers-C4chhLB1.js";
2
- import { a as C, R as q, S as f } from "./index-D7rUF8vA.js";
2
+ import { a as C, R as q, S as f } from "./index-BfW7ObKf.js";
3
3
  import { BasePlugin as E } from "./core.js";
4
4
  import { m as F } from "./makeCallable-Cg4zUG4c.js";
5
5
  var S = Object.create, w = Object.defineProperty, W = Object.getOwnPropertyDescriptor, _ = (n, e) => (e = Symbol[n]) ? e : /* @__PURE__ */ Symbol.for("Symbol." + n), k = (n) => {
@@ -165,4 +165,4 @@ D(m, 1, v);
165
165
  export {
166
166
  v as PluginQuickPreview
167
167
  };
168
- //# sourceMappingURL=index-CMmEZcB1.js.map
168
+ //# sourceMappingURL=index-siZBRSp0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-CMmEZcB1.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\nimport './style.scss'\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-i')\n .description('Key shortcut to open quick preview in quick edit modal'),\n })\n .extra('category', 'editor')\n .description('Quick preview options')\n)\nexport class PluginQuickPreview extends BasePlugin {\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'quickPreview')\n this.ctx.set('quickPreview', makeCallable(this, 'previewWikitext'))\n }\n\n protected start(): Promise<void> | void {\n this.ctx.on('quick-edit/wiki-page', this.injectQuickEdit.bind(this))\n }\n\n protected stop(): Promise<void> | void {}\n\n previewWikitext(\n text: string,\n params?: MwApiParams,\n wikiPage?: IWikiPage,\n modal?: IPEModal,\n modalOptions?: Partial<IPEModalOptions>\n ) {\n const { $ } = this.ctx\n\n wikiPage ||= this.ctx.wikiPage.newBlankPage({\n title: 'API',\n })\n\n if (!modal || modal.isDestroyed) {\n modal = this.ctx.modal\n .createObject({\n className: 'in-page-edit ipe-quickPreview',\n sizeClass: 'large',\n center: false,\n ...modalOptions,\n })\n .init()\n }\n\n modal.show()\n modal.setTitle($`Preview - Loading...`)\n modal.setContent(<ProgressBar />)\n modal.bringToFront()\n this.ctx.emit('quick-preview/show-modal', {\n ctx: this.ctx,\n text,\n modal,\n wikiPage,\n })\n\n wikiPage\n .preview(text, params)\n .then((ret) => {\n const {\n data: { parse },\n } = ret\n modal.setTitle($(parse.title)`Preview - {{ $1 }}`)\n let outputRef: HTMLElement | null = null\n modal.setContent(\n (\n <section>\n <div\n ref={(el) => (outputRef = el)}\n className=\"mw-parser-output\"\n innerHTML={parse.text}\n ></div>\n </section>\n ) as HTMLElement\n )\n if (window.mw?.hook && typeof jQuery === 'function') {\n window.mw.hook('wikipage.content').fire(jQuery(outputRef!))\n }\n this.ctx.emit('quick-preview/loaded', {\n ctx: this.ctx,\n modal,\n wikiPage,\n text,\n parseData: parse,\n })\n })\n .catch((error) => {\n modal.setTitle($`Preview - Failed`)\n modal.setContent(\n <>\n <p>{$`Failed to preview`}</p>\n <p>{error instanceof Error ? error.message : String(error)}</p>\n </>\n )\n })\n\n return modal\n }\n\n private async injectQuickEdit({ options, modal, wikiPage }: QuickEditEventPayload) {\n const { $ } = this.ctx\n let latestPreviewModal: IPEModal | undefined = undefined\n modal.addButton(\n {\n label: $`Preview`,\n side: 'left',\n className: 'btn btn-secondary',\n keyPress:\n (await this.ctx.preferences.get('quickPreview.keyshortcut.quickEdit')) || undefined,\n method: () => {\n let wikitext =\n (modal.get$content().querySelector<HTMLTextAreaElement>('textarea[name=\"text\"]')\n ?.value as string) || ''\n if (options.section === 'new') {\n const title = modal\n .get$content()\n .querySelector<HTMLInputElement>('input[name=\"summary\"]')?.value\n if (title) {\n wikitext = `==${title}==\\n${wikitext}`\n }\n }\n\n latestPreviewModal = this.previewWikitext(\n wikitext,\n undefined,\n wikiPage,\n latestPreviewModal,\n {\n backdrop: false,\n draggable: true,\n }\n )\n },\n },\n 1\n )\n modal.on(modal.Event.Close, () => {\n latestPreviewModal?.destroy()\n latestPreviewModal = undefined\n })\n }\n\n private _contentTypeCache = new Map<string, Promise<string>>()\n private fetchContentType(url: string) {\n const cached = this._contentTypeCache.get(url)\n if (cached) return cached\n const promise = fetch(url, { method: 'HEAD' })\n .then((res) => res.headers.get('content-type') || '')\n .catch(() => {\n this._contentTypeCache.delete(url)\n return ''\n })\n this._contentTypeCache.set(url, promise)\n return promise\n }\n async getPreviewType(fileOrUrl: File | string) {\n if (!fileOrUrl) return 'unknown'\n let contentType: string\n let ext: string\n if (fileOrUrl instanceof File) {\n contentType = fileOrUrl.type\n ext = fileOrUrl.name.split('.').pop()?.toLowerCase() || ''\n } else {\n const url = new URL(fileOrUrl, location.origin)\n if (url.protocol === 'data:' || url.protocol === 'blob:' || url.protocol.startsWith('http')) {\n contentType = await this.fetchContentType(url.href)\n } else {\n contentType = ''\n }\n ext = url.pathname.split('.').pop()?.toLowerCase() || ''\n }\n if (\n contentType.startsWith('image/') &&\n /** Windows provide PDFs as image/pdf */ !contentType.includes('pdf')\n ) {\n return 'image'\n }\n if (contentType.startsWith('video/')) return 'video'\n if (contentType.startsWith('audio/')) return 'audio'\n if (contentType.startsWith('text/html')) return 'html'\n if (ext === 'md') return 'markdown'\n if (contentType.startsWith('text/')) return 'text'\n // detect by file extension\n if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'ico', 'webp'].includes(ext)) return 'image'\n if (['mp4', 'webm', 'ogg', 'flv', 'avi', 'mov', 'wmv', 'mkv'].includes(ext)) return 'video'\n if (['mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a', 'wma'].includes(ext)) return 'audio'\n if (['html', 'htm'].includes(ext)) return 'html'\n if (['json', 'yml', 'yaml', 'toml', 'py'].includes(ext)) return 'text'\n if (['pdf'].includes(ext)) return 'pdf'\n return 'unknown'\n }\n async previewFile(fileOrUrl: File | string, alt?: string) {\n const previewElement = await this.getPreviewElement(fileOrUrl, alt)\n if (!previewElement) return\n const modal = this.ctx.modal.dialog({\n className: 'in-page-edit ipe-quickPreview',\n sizeClass: 'mediumToLarge',\n center: true,\n title: alt ?? (fileOrUrl instanceof File ? fileOrUrl.name : fileOrUrl),\n content: <section className=\"ipe-quickPreview__content\">{previewElement}</section>,\n })\n return modal\n }\n private _objectUrls = new WeakMap<File, string>()\n private getObjectUrl(file: File) {\n if (!this._objectUrls.has(file)) {\n const objUrl = URL.createObjectURL(file)\n this._objectUrls.set(file, objUrl)\n }\n return this._objectUrls.get(file)!\n }\n async getPreviewElement(fileOrUrl: File | string, alt?: string) {\n const previewType = await this.getPreviewType(fileOrUrl)\n const url = fileOrUrl instanceof File ? this.getObjectUrl(fileOrUrl) : fileOrUrl\n switch (previewType) {\n case 'image':\n return (\n <img src={url} alt={alt ?? (fileOrUrl instanceof File ? fileOrUrl.name : fileOrUrl)} />\n )\n case 'video':\n return <video src={url} controls={true} aria-label={alt} />\n case 'audio':\n return <audio src={url} controls={true} aria-label={alt} />\n case 'pdf':\n return <embed type=\"application/pdf\" src={url} aria-label={alt} />\n }\n return null\n }\n\n previewWikiPage(title: string) {\n throw new Error('Not implemented')\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","url","cached","promise","res","fileOrUrl","contentType","ext","alt","previewElement","file","objUrl","previewType","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
1
+ {"version":3,"file":"index-siZBRSp0.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\nimport './style.scss'\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-i')\n .description('Key shortcut to open quick preview in quick edit modal'),\n })\n .extra('category', 'editor')\n .description('Quick preview options')\n)\nexport class PluginQuickPreview extends BasePlugin {\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'quickPreview')\n this.ctx.set('quickPreview', makeCallable(this, 'previewWikitext'))\n }\n\n protected start(): Promise<void> | void {\n this.ctx.on('quick-edit/wiki-page', this.injectQuickEdit.bind(this))\n }\n\n protected stop(): Promise<void> | void {}\n\n previewWikitext(\n text: string,\n params?: MwApiParams,\n wikiPage?: IWikiPage,\n modal?: IPEModal,\n modalOptions?: Partial<IPEModalOptions>\n ) {\n const { $ } = this.ctx\n\n wikiPage ||= this.ctx.wikiPage.newBlankPage({\n title: 'API',\n })\n\n if (!modal || modal.isDestroyed) {\n modal = this.ctx.modal\n .createObject({\n className: 'in-page-edit ipe-quickPreview',\n sizeClass: 'large',\n center: false,\n ...modalOptions,\n })\n .init()\n }\n\n modal.show()\n modal.setTitle($`Preview - Loading...`)\n modal.setContent(<ProgressBar />)\n modal.bringToFront()\n this.ctx.emit('quick-preview/show-modal', {\n ctx: this.ctx,\n text,\n modal,\n wikiPage,\n })\n\n wikiPage\n .preview(text, params)\n .then((ret) => {\n const {\n data: { parse },\n } = ret\n modal.setTitle($(parse.title)`Preview - {{ $1 }}`)\n let outputRef: HTMLElement | null = null\n modal.setContent(\n (\n <section>\n <div\n ref={(el) => (outputRef = el)}\n className=\"mw-parser-output\"\n innerHTML={parse.text}\n ></div>\n </section>\n ) as HTMLElement\n )\n if (window.mw?.hook && typeof jQuery === 'function') {\n window.mw.hook('wikipage.content').fire(jQuery(outputRef!))\n }\n this.ctx.emit('quick-preview/loaded', {\n ctx: this.ctx,\n modal,\n wikiPage,\n text,\n parseData: parse,\n })\n })\n .catch((error) => {\n modal.setTitle($`Preview - Failed`)\n modal.setContent(\n <>\n <p>{$`Failed to preview`}</p>\n <p>{error instanceof Error ? error.message : String(error)}</p>\n </>\n )\n })\n\n return modal\n }\n\n private async injectQuickEdit({ options, modal, wikiPage }: QuickEditEventPayload) {\n const { $ } = this.ctx\n let latestPreviewModal: IPEModal | undefined = undefined\n modal.addButton(\n {\n label: $`Preview`,\n side: 'left',\n className: 'btn btn-secondary',\n keyPress:\n (await this.ctx.preferences.get('quickPreview.keyshortcut.quickEdit')) || undefined,\n method: () => {\n let wikitext =\n (modal.get$content().querySelector<HTMLTextAreaElement>('textarea[name=\"text\"]')\n ?.value as string) || ''\n if (options.section === 'new') {\n const title = modal\n .get$content()\n .querySelector<HTMLInputElement>('input[name=\"summary\"]')?.value\n if (title) {\n wikitext = `==${title}==\\n${wikitext}`\n }\n }\n\n latestPreviewModal = this.previewWikitext(\n wikitext,\n undefined,\n wikiPage,\n latestPreviewModal,\n {\n backdrop: false,\n draggable: true,\n }\n )\n },\n },\n 1\n )\n modal.on(modal.Event.Close, () => {\n latestPreviewModal?.destroy()\n latestPreviewModal = undefined\n })\n }\n\n private _contentTypeCache = new Map<string, Promise<string>>()\n private fetchContentType(url: string) {\n const cached = this._contentTypeCache.get(url)\n if (cached) return cached\n const promise = fetch(url, { method: 'HEAD' })\n .then((res) => res.headers.get('content-type') || '')\n .catch(() => {\n this._contentTypeCache.delete(url)\n return ''\n })\n this._contentTypeCache.set(url, promise)\n return promise\n }\n async getPreviewType(fileOrUrl: File | string) {\n if (!fileOrUrl) return 'unknown'\n let contentType: string\n let ext: string\n if (fileOrUrl instanceof File) {\n contentType = fileOrUrl.type\n ext = fileOrUrl.name.split('.').pop()?.toLowerCase() || ''\n } else {\n const url = new URL(fileOrUrl, location.origin)\n if (url.protocol === 'data:' || url.protocol === 'blob:' || url.protocol.startsWith('http')) {\n contentType = await this.fetchContentType(url.href)\n } else {\n contentType = ''\n }\n ext = url.pathname.split('.').pop()?.toLowerCase() || ''\n }\n if (\n contentType.startsWith('image/') &&\n /** Windows provide PDFs as image/pdf */ !contentType.includes('pdf')\n ) {\n return 'image'\n }\n if (contentType.startsWith('video/')) return 'video'\n if (contentType.startsWith('audio/')) return 'audio'\n if (contentType.startsWith('text/html')) return 'html'\n if (ext === 'md') return 'markdown'\n if (contentType.startsWith('text/')) return 'text'\n // detect by file extension\n if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'ico', 'webp'].includes(ext)) return 'image'\n if (['mp4', 'webm', 'ogg', 'flv', 'avi', 'mov', 'wmv', 'mkv'].includes(ext)) return 'video'\n if (['mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a', 'wma'].includes(ext)) return 'audio'\n if (['html', 'htm'].includes(ext)) return 'html'\n if (['json', 'yml', 'yaml', 'toml', 'py'].includes(ext)) return 'text'\n if (['pdf'].includes(ext)) return 'pdf'\n return 'unknown'\n }\n async previewFile(fileOrUrl: File | string, alt?: string) {\n const previewElement = await this.getPreviewElement(fileOrUrl, alt)\n if (!previewElement) return\n const modal = this.ctx.modal.dialog({\n className: 'in-page-edit ipe-quickPreview',\n sizeClass: 'mediumToLarge',\n center: true,\n title: alt ?? (fileOrUrl instanceof File ? fileOrUrl.name : fileOrUrl),\n content: <section className=\"ipe-quickPreview__content\">{previewElement}</section>,\n })\n return modal\n }\n private _objectUrls = new WeakMap<File, string>()\n private getObjectUrl(file: File) {\n if (!this._objectUrls.has(file)) {\n const objUrl = URL.createObjectURL(file)\n this._objectUrls.set(file, objUrl)\n }\n return this._objectUrls.get(file)!\n }\n async getPreviewElement(fileOrUrl: File | string, alt?: string) {\n const previewType = await this.getPreviewType(fileOrUrl)\n const url = fileOrUrl instanceof File ? this.getObjectUrl(fileOrUrl) : fileOrUrl\n switch (previewType) {\n case 'image':\n return (\n <img src={url} alt={alt ?? (fileOrUrl instanceof File ? fileOrUrl.name : fileOrUrl)} />\n )\n case 'video':\n return <video src={url} controls={true} aria-label={alt} />\n case 'audio':\n return <audio src={url} controls={true} aria-label={alt} />\n case 'pdf':\n return <embed type=\"application/pdf\" src={url} aria-label={alt} />\n }\n return null\n }\n\n previewWikiPage(title: string) {\n throw new Error('Not implemented')\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","url","cached","promise","res","fileOrUrl","contentType","ext","alt","previewElement","file","objUrl","previewType","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1724,6 +1724,9 @@ declare module '.' {
1724
1724
  }
1725
1725
  interface Events {
1726
1726
  'current-page/popstate'(): void;
1727
+ 'current-page/resolve-title'(title: IWikiTitle | null): IWikiTitle | void;
1728
+ 'current-page/resolve-action'(action: string): string | void;
1729
+ 'current-page/resolve-main-page'(isMainPage: boolean): boolean | void;
1727
1730
  }
1728
1731
  }
1729
1732
  declare class CurrentPageService extends Service {
@@ -1744,7 +1747,7 @@ declare class CurrentPageService extends Service {
1744
1747
  * @returns IWikiTitle or null if cannot be determined
1745
1748
  */
1746
1749
  wikiTitle: IWikiTitle | null;
1747
- get wikiAction(): string;
1750
+ get wikiAction(): string | boolean | Promise<void>;
1748
1751
  }
1749
1752
  //#endregion
1750
1753
  //#region src/services/ResourceLoaderService.d.ts
@@ -13691,42 +13694,6 @@ declare class WikiMetadataService extends Service {
13691
13694
  getBlockInfo(): WikiUserBlockInfo | null;
13692
13695
  }
13693
13696
  //#endregion
13694
- //#region src/services/ThemeService.d.ts
13695
- type ThemePreference = 'light' | 'dark' | 'auto' | 'fandom';
13696
- type ThemeMode = 'light' | 'dark';
13697
- // ↓ '@/InPageEdit'
13698
- declare module '.' {
13699
- interface InPageEdit {
13700
- theme: ThemeService;
13701
- }
13702
- interface Events {
13703
- 'theme/changed'(payload: {
13704
- ctx: InPageEdit;
13705
- theme: ThemeMode;
13706
- }): void;
13707
- }
13708
- interface PreferencesMap {
13709
- theme: ThemePreference;
13710
- }
13711
- }
13712
- declare class ThemeService extends Service {
13713
- ctx: InPageEdit;
13714
- private _mediaQueryList;
13715
- private _observer;
13716
- private readonly _handleSystemThemeChange;
13717
- private readonly _handleBodyClassChange;
13718
- constructor(ctx: InPageEdit);
13719
- protected start(): Promise<void>;
13720
- protected stop(): void;
13721
- private _onSystemThemeChange;
13722
- private _onBodyClassChange;
13723
- applyTheme(): Promise<void>;
13724
- private updateFandomObserver;
13725
- private getTheme;
13726
- private applyThemeClass;
13727
- get currentTheme(): ThemeMode;
13728
- }
13729
- //#endregion
13730
13697
  //#region src/models/WikiPage/types/PageInfo.d.ts
13731
13698
  /**
13732
13699
  * @url https://www.mediawiki.org/wiki/Content_handlers
@@ -38341,6 +38308,75 @@ declare class PluginToolbox extends Service {
38341
38308
  toggle(force?: boolean): void;
38342
38309
  }
38343
38310
  //#endregion
38311
+ //#region src/services/theme/SiteThemeAdapter.d.ts
38312
+ type ThemeMode = 'light' | 'dark';
38313
+ interface SiteThemeAdapter {
38314
+ /** Display name, e.g. "Fandom", "Vector 2022" */
38315
+ name: string;
38316
+ /** Whether this adapter can handle the current page */
38317
+ match(): boolean;
38318
+ /** Get current site theme */
38319
+ getCurrentTheme(): ThemeMode;
38320
+ /** Start observing site theme changes, call onChange when theme changes */
38321
+ startObserving(onChange: () => void): void;
38322
+ /** Stop observing */
38323
+ stopObserving(): void;
38324
+ }
38325
+ interface ClassBasedAdapterConfig {
38326
+ name: string;
38327
+ /** CSS class names on html/body that indicate this skin is active */
38328
+ skinClasses: string[];
38329
+ /** CSS class names that indicate dark mode */
38330
+ darkClasses: string[];
38331
+ /** CSS class names that indicate "follow system preference" mode */
38332
+ systemClasses?: string[];
38333
+ /** Which element(s) to check for darkClasses/systemClasses. Default: 'both' */
38334
+ target?: 'body' | 'html' | 'both';
38335
+ }
38336
+ declare function createClassBasedAdapter(config: ClassBasedAdapterConfig): SiteThemeAdapter;
38337
+ /** Built-in site theme adapters, ordered by specificity. */
38338
+ declare const BUILTIN_SITE_ADAPTERS: ClassBasedAdapterConfig[];
38339
+ //#endregion
38340
+ //#region src/services/theme/ThemeService.d.ts
38341
+ type ThemePreference = 'light' | 'dark' | 'auto' | 'site';
38342
+ // ↓ '@/InPageEdit'
38343
+ declare module '.' {
38344
+ interface InPageEdit {
38345
+ theme: ThemeService;
38346
+ }
38347
+ interface Events {
38348
+ 'theme/changed'(payload: {
38349
+ ctx: InPageEdit;
38350
+ theme: ThemeMode;
38351
+ }): void;
38352
+ }
38353
+ interface PreferencesMap {
38354
+ theme: ThemePreference;
38355
+ }
38356
+ }
38357
+ declare class ThemeService extends Service {
38358
+ ctx: InPageEdit;
38359
+ private _mediaQueryList;
38360
+ private adapters;
38361
+ private activeAdapter;
38362
+ private readonly _handleSystemThemeChange;
38363
+ constructor(ctx: InPageEdit);
38364
+ protected start(): Promise<void>;
38365
+ protected stop(): void;
38366
+ /**
38367
+ * Register a site theme adapter. Returns a dispose function to unregister it.
38368
+ * Custom adapters take priority over previously registered (built-in) ones.
38369
+ */
38370
+ registerSiteThemeAdapter(adapter: SiteThemeAdapter): () => void;
38371
+ private resolveActiveAdapter;
38372
+ private _onSystemThemeChange;
38373
+ applyTheme(): Promise<void>;
38374
+ private updateSiteObserver;
38375
+ private getTheme;
38376
+ private applyThemeClass;
38377
+ get currentTheme(): ThemeMode;
38378
+ }
38379
+ //#endregion
38344
38380
  //#region src/index.d.ts
38345
38381
  declare global {
38346
38382
  const ipe: InPageEdit;
@@ -38376,4 +38412,4 @@ declare global {
38376
38412
  }
38377
38413
  }
38378
38414
  //#endregion
38379
- export { AbstractIPEStorageManager, ActionButton, ActionButtonProps, AnyContent, ApiService, ApiServiceOptions, AwaitAble$1 as AwaitAble, BasePlugin, CallableInstance, CheckBox, CheckBoxProps, type ClientLoginOptions, type ClientLoginResult, CompareApiRequestOptions, CompareApiResponse, ContentModelMap, CordisError, symbols as CordisSymbols, CurrentPageService, CustomIPEModal, EffectScope, Endpoints, Events, FetchLike, Fexios, FexiosConfigs, FexiosContext, FexiosError, FexiosErrorCodes, FexiosFinalContext, FexiosHeaderBuilder, FexiosHook, FexiosHookHandler, FexiosHookStore, FexiosInterceptor, FexiosInterceptors, FexiosLifecycleEventMap, FexiosLifecycleEvents, FexiosMethods, FexiosPlugin, FexiosQueryBuilder, FexiosRequestContext, FexiosRequestOptions, FexiosRequestShortcut, FexiosResponse, FexiosResponse as FexiosResponseContext, FexiosResponseError, FexiosRuntimeContext, type FexiosSaikou, MediaWikiForeignApi as ForeignApi, MediaWikiForeignApi, ForkScope, IFexiosResponse, IPEBeaconPayload, IPEBeaconUsage, IPEModal, IPEModalAnimation, IPEModalButtonOptions, IPEModalEvent, IPEModalHook, IPEModalNotifyPosition, IPEModalNotifyType, IPEModalOptions, IPEPlugin, IPERegistry, IWikiPage, IWikiTitle, IconEdit, IconQuickDiff, IconQuickEdit, IconUpload, InArticleWikiAnchorMetadata, InPageEdit, InPageEditCoreConfig, InPageEditPreferenceUICategory, InPageEditPreferenceUIRegistryItem, Inject, InputBox, InputBoxProps, LevelDefinition, Lifecycle, Logger, LoggerLevel, LoggerOptions, MBox, MBoxElement, MBoxProps, MainScope, MediaWikiApi, MediaWikiApi as MwApi, MediaWikiApiError, MemoryStorage, ModalService, MovePageOptions, WikiSaikouCore as MwApiBase, WikiSaikouCore, type MwApiParams, type MwApiResponse, type MwApiResponseError, MwParamNormalizer, type MwTokenName, PageInfo, PageParseData, PluginAnalytics, PluginInArticleLinks, PluginPluginStore, PluginPreferencesUI, PluginQuickDiff, PluginQuickEdit, PluginQuickMove, PluginQuickPreview, PluginQuickRedirect, PluginQuickUpload, PluginQuickUsage, PluginStoreRegistrySource, PluginToolbox, PreferencesMap, PreferencesService, ProgressBar, QuickEditEventPayload, QuickEditOptions, QuickEditSubmitPayload, QuickMoveOptions, QuickRedirectOptions, RadioBox, RadioBoxProps, RedirectPageOptions, RegisterPreferences, ResourceLoaderService, Schema, ScopeStatus, Service, SsiModalSizeClass, StorageService, StorageServiceConfig, TabContent, TabLabel, TabView, TabViewLabelOptions, ThemeService, TwinSwapElement, TwinSwapInput, TwinSwapInputInput, TwinSwapInputProps, TypedStorageEntry, UploadFileParams, UploadFileResult, WatchlistAction, WikiFileRepo, WikiFileService, WikiImageInfo, WikiLinkMetadata, WikiMagicWord, WikiMetadataService, WikiNameSpaceAlias, WikiNamespace, WikiPageConstructor, WikiPageService, type WikiSaikouConfig, WikiSaikouError, WikiSaikouErrorCode, type WikiSaikouInitConfig, WikiSiteGeneralInfo, WikiSiteInfo, WikiSpecialPageAlias, WikiTitleConstructor, WikiTitleService, WikiUserBlockInfo, WikiUserInfo, WikiUserOptions, clone, createFexios, createFexiosResponse, createFexiosSaikou, createLogger, createWikiPageModel, createWikiTitleModel, deepMerge, fexios, isFexiosError, isPlainObject, useMemoryStorage };
38415
+ export { AbstractIPEStorageManager, ActionButton, ActionButtonProps, AnyContent, ApiService, ApiServiceOptions, AwaitAble$1 as AwaitAble, BUILTIN_SITE_ADAPTERS, BasePlugin, CallableInstance, CheckBox, CheckBoxProps, ClassBasedAdapterConfig, type ClientLoginOptions, type ClientLoginResult, CompareApiRequestOptions, CompareApiResponse, ContentModelMap, CordisError, symbols as CordisSymbols, CurrentPageService, CustomIPEModal, EffectScope, Endpoints, Events, FetchLike, Fexios, FexiosConfigs, FexiosContext, FexiosError, FexiosErrorCodes, FexiosFinalContext, FexiosHeaderBuilder, FexiosHook, FexiosHookHandler, FexiosHookStore, FexiosInterceptor, FexiosInterceptors, FexiosLifecycleEventMap, FexiosLifecycleEvents, FexiosMethods, FexiosPlugin, FexiosQueryBuilder, FexiosRequestContext, FexiosRequestOptions, FexiosRequestShortcut, FexiosResponse, FexiosResponse as FexiosResponseContext, FexiosResponseError, FexiosRuntimeContext, type FexiosSaikou, MediaWikiForeignApi as ForeignApi, MediaWikiForeignApi, ForkScope, IFexiosResponse, IPEBeaconPayload, IPEBeaconUsage, IPEModal, IPEModalAnimation, IPEModalButtonOptions, IPEModalEvent, IPEModalHook, IPEModalNotifyPosition, IPEModalNotifyType, IPEModalOptions, IPEPlugin, IPERegistry, IWikiPage, IWikiTitle, IconEdit, IconQuickDiff, IconQuickEdit, IconUpload, InArticleWikiAnchorMetadata, InPageEdit, InPageEditCoreConfig, InPageEditPreferenceUICategory, InPageEditPreferenceUIRegistryItem, Inject, InputBox, InputBoxProps, LevelDefinition, Lifecycle, Logger, LoggerLevel, LoggerOptions, MBox, MBoxElement, MBoxProps, MainScope, MediaWikiApi, MediaWikiApi as MwApi, MediaWikiApiError, MemoryStorage, ModalService, MovePageOptions, WikiSaikouCore as MwApiBase, WikiSaikouCore, type MwApiParams, type MwApiResponse, type MwApiResponseError, MwParamNormalizer, type MwTokenName, PageInfo, PageParseData, PluginAnalytics, PluginInArticleLinks, PluginPluginStore, PluginPreferencesUI, PluginQuickDiff, PluginQuickEdit, PluginQuickMove, PluginQuickPreview, PluginQuickRedirect, PluginQuickUpload, PluginQuickUsage, PluginStoreRegistrySource, PluginToolbox, PreferencesMap, PreferencesService, ProgressBar, QuickEditEventPayload, QuickEditOptions, QuickEditSubmitPayload, QuickMoveOptions, QuickRedirectOptions, RadioBox, RadioBoxProps, RedirectPageOptions, RegisterPreferences, ResourceLoaderService, Schema, ScopeStatus, Service, SiteThemeAdapter, SsiModalSizeClass, StorageService, StorageServiceConfig, TabContent, TabLabel, TabView, TabViewLabelOptions, ThemeMode, ThemeService, TwinSwapElement, TwinSwapInput, TwinSwapInputInput, TwinSwapInputProps, TypedStorageEntry, UploadFileParams, UploadFileResult, WatchlistAction, WikiFileRepo, WikiFileService, WikiImageInfo, WikiLinkMetadata, WikiMagicWord, WikiMetadataService, WikiNameSpaceAlias, WikiNamespace, WikiPageConstructor, WikiPageService, type WikiSaikouConfig, WikiSaikouError, WikiSaikouErrorCode, type WikiSaikouInitConfig, WikiSiteGeneralInfo, WikiSiteInfo, WikiSpecialPageAlias, WikiTitleConstructor, WikiTitleService, WikiUserBlockInfo, WikiUserInfo, WikiUserOptions, clone, createClassBasedAdapter, createFexios, createFexiosResponse, createFexiosSaikou, createLogger, createWikiPageModel, createWikiTitleModel, deepMerge, fexios, isFexiosError, isPlainObject, useMemoryStorage };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { I as r, E as s } from "./index-D7rUF8vA.js";
2
- import { C as E, s as l, b as g, F as L, a as S, e as I, m as P, $ as m, M as y, R as U, S as M, c as h, d as R, f as O } from "./index-D7rUF8vA.js";
1
+ import { I as r, E as s } from "./index-BfW7ObKf.js";
2
+ import { C as E, s as l, b as g, F as L, a as S, e as I, m as P, $ as m, M as y, R as U, S as M, c as h, d as R, f as O } from "./index-BfW7ObKf.js";
3
3
  import { BasePlugin as b } from "./core.js";
4
4
  window.RLQ ||= [];
5
5
  window.__IPE_MODULES__ ||= [];
@@ -1,15 +1,15 @@
1
- import { PluginAnalytics as i } from "../index-mf_pX14E.js";
2
- import { PluginInArticleLinks as u } from "../index-1sZXko-X.js";
3
- import { PluginPluginStore as n } from "../index-BllIuJSJ.js";
4
- import { PluginPreferencesUI as f } from "../index-BcTomMXW.js";
5
- import { PluginQuickDiff as g } from "../index-42B3CrSO.js";
6
- import { PluginQuickEdit as x } from "../index-CN7r2e0P.js";
7
- import { PluginQuickMove as c } from "../index-CkSHCMRN.js";
8
- import { PluginQuickPreview as Q } from "../index-CMmEZcB1.js";
9
- import { PluginQuickRedirect as a } from "../index-BBUv7Lv6.js";
10
- import { PluginQuickUpload as U } from "../index-Bn6y0Eln.js";
11
- import { PluginQuickUsage as A } from "../index-DlCbsA25.js";
12
- import { PluginToolbox as b } from "../index-TG_MTC9y.js";
1
+ import { PluginAnalytics as i } from "../index-BvHXETfl.js";
2
+ import { PluginInArticleLinks as u } from "../index-CZ56EKIK.js";
3
+ import { PluginPluginStore as n } from "../index-C2_G8gLW.js";
4
+ import { PluginPreferencesUI as f } from "../index-5DLUhCA3.js";
5
+ import { PluginQuickDiff as g } from "../index-C4ncbyR6.js";
6
+ import { PluginQuickEdit as x } from "../index-s7aFr-gn.js";
7
+ import { PluginQuickMove as c } from "../index-B5UcAL5E.js";
8
+ import { PluginQuickPreview as Q } from "../index-siZBRSp0.js";
9
+ import { PluginQuickRedirect as a } from "../index-BTLjDVvD.js";
10
+ import { PluginQuickUpload as U } from "../index-BMd6Bo6r.js";
11
+ import { PluginQuickUsage as A } from "../index-Cjyf3z1w.js";
12
+ import { PluginToolbox as b } from "../index-Dfp9Vp36.js";
13
13
  export {
14
14
  i as PluginAnalytics,
15
15
  u as PluginInArticleLinks,