@inpageedit/core 0.17.1 → 0.17.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/InPageEdit.js +1 -1
- package/dist/{PluginImagesUsed-D5O8t694.js → PluginImagesUsed-DWpe6M-r.js} +2 -2
- package/dist/{PluginImagesUsed-D5O8t694.js.map → PluginImagesUsed-DWpe6M-r.js.map} +1 -1
- package/dist/{PluginPrefSync-C8tb5SJJ.js → PluginPrefSync-CmVHL2wx.js} +2 -2
- package/dist/{PluginPrefSync-C8tb5SJJ.js.map → PluginPrefSync-CmVHL2wx.js.map} +1 -1
- package/dist/{PluginStoreApp-CeKtXL3p.js → PluginStoreApp-CmLstT3F.js} +2 -2
- package/dist/{PluginStoreApp-CeKtXL3p.js.map → PluginStoreApp-CmLstT3F.js.map} +1 -1
- package/dist/{PluginTemplatesUsed-DYv_lbHw.js → PluginTemplatesUsed-BjRYFXHz.js} +2 -2
- package/dist/{PluginTemplatesUsed-DYv_lbHw.js.map → PluginTemplatesUsed-BjRYFXHz.js.map} +1 -1
- package/dist/Promise.withResolvers-C4chhLB1.js.map +1 -1
- package/dist/core.js +2 -2
- package/dist/{index-h57rl1RH.js → index-BVMm7Dix.js} +2 -2
- package/dist/{index-h57rl1RH.js.map → index-BVMm7Dix.js.map} +1 -1
- package/dist/{index--IhZKYnh.js → index-BYgh1HkH.js} +2 -2
- package/dist/{index--IhZKYnh.js.map → index-BYgh1HkH.js.map} +1 -1
- package/dist/{index-DSh05RaI.js → index-BbvMbIgz.js} +3 -3
- package/dist/{index-DSh05RaI.js.map → index-BbvMbIgz.js.map} +1 -1
- package/dist/{index-Bf6ewNGZ.js → index-BlVSMvH-.js} +2 -2
- package/dist/{index-Bf6ewNGZ.js.map → index-BlVSMvH-.js.map} +1 -1
- package/dist/{index-qbW7-LUD.js → index-CUDVeUEv.js} +2 -2
- package/dist/{index-qbW7-LUD.js.map → index-CUDVeUEv.js.map} +1 -1
- package/dist/{index-CxjH0_fO.js → index-Ce-zc5RR.js} +2 -2
- package/dist/{index-CxjH0_fO.js.map → index-Ce-zc5RR.js.map} +1 -1
- package/dist/{index-Dp_n8QEV.js → index-CkSdNy0U.js} +2 -2
- package/dist/{index-Dp_n8QEV.js.map → index-CkSdNy0U.js.map} +1 -1
- package/dist/{index-QtXlz9l0.js → index-D-8cyCdX.js} +148 -125
- package/dist/index-D-8cyCdX.js.map +1 -0
- package/dist/{index-CaTtMzfu.js → index-DTU2DZU6.js} +14 -14
- package/dist/{index-CaTtMzfu.js.map → index-DTU2DZU6.js.map} +1 -1
- package/dist/{index-BuSA1t5R.js → index-Dfdy54gH.js} +2 -2
- package/dist/{index-BuSA1t5R.js.map → index-Dfdy54gH.js.map} +1 -1
- package/dist/{index-Mi3qr9J0.js → index-DvFkW8lL.js} +2 -2
- package/dist/{index-Mi3qr9J0.js.map → index-DvFkW8lL.js.map} +1 -1
- package/dist/{index-_Sydb5MZ.js → index-JvsrhizC.js} +3 -3
- package/dist/{index-_Sydb5MZ.js.map → index-JvsrhizC.js.map} +1 -1
- package/dist/{index-fa8d4Dv_.js → index-LvMaeDQn.js} +2 -2
- package/dist/{index-fa8d4Dv_.js.map → index-LvMaeDQn.js.map} +1 -1
- package/dist/index.d.ts +5858 -27237
- package/dist/index.js +2 -2
- package/dist/plugins/index.js +12 -12
- package/dist/services/index.js +1 -1
- package/lib/index.umd.js +11 -11
- package/lib/index.umd.js.map +1 -1
- package/package.json +2 -1
- package/dist/index-QtXlz9l0.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-Bf6ewNGZ.js","sources":["../src/plugins/quick-upload/index.tsx"],"sourcesContent":["import { Inject, InPageEdit, Schema } from '@/InPageEdit'\n\nimport './style.scss'\n\nimport BasePlugin from '@/plugins/BasePlugin'\nimport { RegisterPreferences } from '@/decorators/Preferences'\nimport { IconUpload } from '@/components/Icon'\nimport { CheckBox } from '@/components'\nimport type { UploadFileResult } from '@/services/WikiFileService'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n quickUpload: PluginQuickUpload\n }\n interface Preferences {\n 'quickUpload.summary': string\n }\n}\n\ntype UploadItem = {\n id: string\n file: File\n filename: string\n text: string\n status: 'queued' | 'uploading' | 'success' | 'warning' | 'error' | 'paused'\n message?: string\n retryable?: boolean\n fileUrl?: string\n result?: UploadFileResult\n}\n\nconst PreviewPlaceholderNA = ({ $ }: { $: (strings: TemplateStringsArray) => string }) => (\n <div className=\"ipe-quickUpload__preview-placeholder is-na\">\n <span>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"icon icon-tabler icons-tabler-filled icon-tabler-file-unknown\"\n >\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\n <path d=\"M12 2l.117 .007a1 1 0 0 1 .876 .876l.007 .117v4l.005 .15a2 2 0 0 0 1.838 1.844l.157 .006h4l.117 .007a1 1 0 0 1 .876 .876l.007 .117v9a3 3 0 0 1 -2.824 2.995l-.176 .005h-10a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-14a3 3 0 0 1 2.824 -2.995l.176 -.005zm0 15a1 1 0 0 0 -.993 .883l-.007 .127a1 1 0 0 0 1.993 .117l.007 -.127a1 1 0 0 0 -1 -1m1.136 -5.727a2.5 2.5 0 0 0 -3.037 .604a1 1 0 0 0 1.434 1.389l.088 -.09a.5 .5 0 1 1 .379 .824a1 1 0 0 0 -.002 2a2.5 2.5 0 0 0 1.137 -4.727\" />\n <path d=\"M19 7h-4l-.001 -4.001z\" />\n </svg>\n <p>{$`No preview available`}</p>\n </span>\n </div>\n)\n\n@RegisterPreferences(\n Schema.object({\n 'quickUpload.summary': Schema.string()\n .description('Default summary of the quick upload')\n .default('[IPE-NEXT] Quick upload'),\n })\n)\n@Inject(['modal', '$', 'wikiTitle', 'wikiFile', 'quickPreview', 'preferences'])\nexport class PluginQuickUpload extends BasePlugin {\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'quick-upload')\n }\n\n protected async start() {\n this.injectToolbox()\n this.ctx.set('quickUpload', this)\n }\n\n protected async stop() {}\n\n private injectToolbox() {\n const { $ } = this.ctx\n this.ctx.inject(['toolbox'], (ctx) => {\n ctx.toolbox.addButton({\n id: 'quick-upload',\n group: 'group2',\n index: 2,\n icon: <IconUpload />,\n tooltip: () => $`Quick Upload`,\n onClick: (e) => {\n e.preventDefault()\n this.showModal()\n },\n })\n ctx.on('dispose', () => {\n ctx.toolbox.removeButton('quick-upload')\n })\n })\n }\n\n private formatFileSize(size: number = 0) {\n size = Number(size)\n if (!Number.isFinite(size) || size < 0) return '0 B'\n\n const units = ['B', 'KB', 'MB', 'GB', 'TB']\n let index = 0\n while (size >= 1024 && index < units.length - 1) {\n size /= 1024\n index++\n }\n\n // 使用 Intl 来格式化数字(自动处理千分位、小数等)\n const formatter = new Intl.NumberFormat(undefined, { maximumFractionDigits: 2 })\n return `${formatter.format(size)} ${units[index]}`\n }\n\n private isFileAccepted(file: File, accept: string): boolean {\n if (!accept) return true\n const rules = accept\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n if (!rules.length) return true\n const fileType = file.type || ''\n const fileName = file.name || ''\n return rules.some((rule) => {\n // extension: .png .pdf\n if (rule.startsWith('.')) {\n return fileName.toLowerCase().endsWith(rule.toLowerCase())\n }\n // image/*, video/* ...\n if (rule.endsWith('/*')) {\n const prefix = rule.slice(0, -1) // keep the trailing slash\n return fileType.startsWith(prefix)\n }\n // exact mime\n return fileType === rule\n })\n }\n\n private getDefaultPreviewPlaceholder() {\n const { $ } = this.ctx\n return (\n <div className=\"ipe-quickUpload__preview-placeholder\">\n <span>\n <IconUpload />\n <p>{$`You can drag & drop files to this modal`}</p>\n </span>\n </div>\n )\n }\n\n private safeId() {\n return `mu_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n }\n\n async showModal() {\n const { $ } = this.ctx\n\n let isUploading = false\n let pauseRequested = false\n\n const showMessage = (type: 'success' | 'warning' | 'error', title: string, content: any) => {\n this.ctx.modal.notify(type, {\n title,\n content,\n closeAfter: type === 'success' ? 3000 : 8000,\n })\n }\n\n const modal = this.ctx.modal.show({\n className: 'ipe-quickUpload compact-buttons',\n sizeClass: 'mediumToLarge',\n center: false,\n title: $`Quick Upload`,\n content: $`Quick Upload`,\n outSideClose: false,\n beforeClose: () => {\n if (isUploading) {\n showMessage('warning', $`Upload in progress`, $`Please pause or wait for it to finish.`)\n return false\n }\n return true\n },\n })\n\n const defaultSummary = (await this.ctx.preferences.get('quickUpload.summary')) || ''\n const accept = 'image/*,video/*,audio/*,application/pdf'\n const confirmThreshold = 20\n\n let items: UploadItem[] = []\n let selectedId: string | null = null\n\n const ui = {\n fileInput: null as HTMLInputElement | null,\n listEl: null as HTMLElement | null,\n previewWrapper: null as HTMLElement | null,\n progressEl: null as HTMLElement | null,\n progressTextEl: null as HTMLElement | null,\n summaryInput: null as HTMLTextAreaElement | null,\n ignoreWarnings: null as HTMLInputElement | null,\n selectedCountEl: null as HTMLElement | null,\n readyCountEl: null as HTMLElement | null,\n }\n\n const updateItem = (id: string, patch: Partial<UploadItem>) => {\n items = items.map((x) => (x.id === id ? { ...x, ...patch } : x))\n }\n\n const removeItem = (id: string) => {\n items = items.filter((x) => x.id !== id)\n if (selectedId === id) {\n selectedId = items[0]?.id ?? null\n }\n }\n\n const updateMany = (ids: Set<string>, fn: (it: UploadItem) => UploadItem) => {\n items = items.map((x) => (ids.has(x.id) ? fn(x) : x))\n }\n\n const summarizeApiErrors = (e: any) => {\n const out: string[] = []\n const s = (v: any) => (v == null ? '' : String(v))\n if (e instanceof Error) {\n out.push(e.message)\n let cur: any = e\n while (cur?.cause) {\n cur = cur.cause\n if (cur instanceof Error) out.push(cur.message)\n else break\n }\n } else if (e?.data?.error?.info) {\n out.push(s(e.data.error.info))\n } else if (e?.error?.info) {\n out.push(s(e.error.info))\n } else if (e?.message) {\n out.push(s(e.message))\n }\n return out.filter(Boolean)\n }\n\n const formatUploadError = (e: any): { message: string; retryable: boolean } => {\n let reasons = summarizeApiErrors(e)\n if (reasons.length === 0) reasons = ['Upload failed with unknown error.']\n\n const combined = reasons.join('\\n')\n const lower = combined.toLowerCase()\n\n if (\n lower.includes('file is larger') ||\n lower.includes('files larger than') ||\n lower.includes('maximum upload size')\n ) {\n return { message: `File too large\\n${combined}`, retryable: false }\n }\n\n if (lower.includes('network') || lower.includes('timeout') || lower.includes('timed out')) {\n return { message: `Network issue\\n${combined}`, retryable: true }\n }\n\n return { message: combined, retryable: true }\n }\n\n const shouldRetryItem = (it: UploadItem) => {\n if (it.status === 'warning') return true\n if (it.status === 'error') return it.retryable !== false\n return false\n }\n\n type UploadMode = 'all' | 'resume' | 'retry'\n\n const getUploadCandidates = (mode: UploadMode, list: UploadItem[]) => {\n if (mode === 'retry') return list.filter((it) => shouldRetryItem(it))\n if (mode === 'resume') {\n return list.filter(\n (it) => (it.status === 'queued' || it.status === 'paused') && it.retryable !== false\n )\n }\n return list.filter((it) => it.status === 'queued' || it.status === 'paused')\n }\n\n const prepareRetryState = (candidates: UploadItem[]) => {\n const idset = new Set(candidates.map((c) => c.id))\n updateMany(idset, (x) =>\n x.retryable === false ? x : { ...x, status: 'queued', message: undefined }\n )\n }\n\n const getSelected = () => {\n return items.find((x) => x.id === selectedId) || null\n }\n\n const setSelected = (id: string | null) => {\n selectedId = id\n renderList()\n void renderPreview()\n }\n\n const countByStatus = () => {\n const out = { ok: 0, warn: 0, err: 0, paused: 0 }\n for (const it of items) {\n if (it.status === 'success') out.ok++\n else if (it.status === 'warning') out.warn++\n else if (it.status === 'error') out.err++\n else if (it.status === 'paused') out.paused++\n }\n return out\n }\n\n const setProgress = (done: number, total: number) => {\n const pct = total > 0 ? Math.floor((done / total) * 100) : 0\n if (ui.progressTextEl) ui.progressTextEl.textContent = `${done}/${total} (${pct}%)`\n if (ui.progressEl) ui.progressEl.style.width = `${Math.max(0, Math.min(100, pct))}%`\n }\n\n const sanitizeFilename = (name: string) => {\n return (name || '').replace(/\\s+/g, ' ').trim()\n }\n\n const resetAll = () => {\n items = []\n selectedId = null\n setProgress(0, 0)\n if (ui.summaryInput) ui.summaryInput.value = String(defaultSummary || '')\n if (ui.ignoreWarnings) ui.ignoreWarnings.checked = false\n renderList()\n void renderPreview()\n }\n\n const addFiles = (files: File[]) => {\n const accepted = files.filter((f) => this.isFileAccepted(f, String(accept || '')))\n if (!accepted.length) return\n\n const newItems: UploadItem[] = accepted.map((file) => ({\n id: this.safeId(),\n file,\n filename: file.name,\n text: '',\n status: 'queued',\n retryable: true,\n }))\n\n items = [...items, ...newItems]\n if (!selectedId && items.length) {\n selectedId = items[0].id\n }\n renderList()\n void renderPreview()\n }\n\n const buildUploadBody = (item: UploadItem) => {\n const body: Record<string, any> = {}\n\n body.filename = sanitizeFilename(item.filename || item.file.name)\n body.file = item.file\n\n const summary = (ui.summaryInput?.value || '').trim() || ''\n body.comment = summary\n\n body.text = item.text || ''\n\n if (ui.ignoreWarnings?.checked) {\n body.ignorewarnings = '1'\n }\n\n return body\n }\n\n const getStatusLabel = (status: UploadItem['status']) => {\n switch (status) {\n case 'queued':\n return 'Queued'\n case 'uploading':\n return 'Uploading'\n case 'success':\n return 'Uploaded'\n case 'warning':\n return 'Warning'\n case 'error':\n return 'Failed'\n case 'paused':\n return 'Paused'\n default:\n return status\n }\n }\n\n const renderList = () => {\n if (!ui.listEl) return\n ui.listEl.innerHTML = ''\n\n if (!isUploading) {\n setProgress(0, items.length)\n }\n\n if (!items.length) {\n ui.listEl.appendChild(\n <div style={{ opacity: 0.75, padding: '8px 0' }}>\n <p>No files selected.</p>\n </div>\n )\n updateFooter()\n return\n } else {\n const list = (\n <ul\n style={{\n listStyle: 'none',\n padding: 0,\n margin: 0,\n display: 'grid',\n gap: '6px',\n }}\n />\n ) as HTMLUListElement\n\n items.forEach((item) => {\n const isActive = item.id === selectedId\n const row = (\n <li\n style={{\n border: '1px solid var(--ipe-border-color, rgba(0,0,0,.12))',\n borderRadius: '8px',\n padding: '8px',\n cursor: 'pointer',\n background: isActive ? 'rgba(59,130,246,.08)' : 'transparent',\n minWidth: 0,\n }}\n onClick={() => setSelected(item.id)}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>\n <div style={{ flex: 1, minWidth: 0, overflow: 'hidden' }}>\n <div\n style={{\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n wordBreak: 'break-word',\n fontSize: '13px',\n }}\n >\n <strong style={{ fontWeight: 600 }}>{item.filename}</strong>\n </div>\n <div style={{ fontSize: '12px', opacity: 0.75 }}>\n {getStatusLabel(item.status)}\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>\n <button\n type=\"button\"\n className=\"ipe-btn is-text\"\n title={'Remove'}\n onClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n removeItem(item.id)\n renderList()\n void renderPreview()\n }}\n >\n ×\n </button>\n </div>\n </div>\n\n {item.message ? (\n <div\n style={{\n fontSize: '12px',\n opacity: 0.8,\n marginTop: '4px',\n whiteSpace: 'pre-wrap',\n }}\n >\n {item.message}\n </div>\n ) : null}\n </li>\n ) as HTMLLIElement\n\n list.appendChild(row)\n })\n\n ui.listEl.appendChild(list)\n }\n\n updateFooter()\n }\n\n const renderPreview = async () => {\n if (!ui.previewWrapper) return\n ui.previewWrapper.innerHTML = ''\n\n const item = getSelected()\n if (!item) {\n ui.previewWrapper.appendChild(this.getDefaultPreviewPlaceholder())\n return\n }\n\n const file = item.file\n\n const header = (\n <section style={{ display: 'grid', gap: '6px' }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'baseline',\n justifyContent: 'space-between',\n gap: '12px',\n }}\n >\n <strong style={{ wordBreak: 'break-word' }}>{file.name}</strong>\n <span style={{ fontSize: '12px', opacity: 0.8 }}>{this.formatFileSize(file.size)}</span>\n </div>\n <div style={{ display: 'flex', gap: '10px', alignItems: 'center', flexWrap: 'wrap' }}>\n <span style={{ fontSize: '12px', opacity: 0.8 }}>{file.type || $`Unknown type`}</span>\n {item.fileUrl ? (\n <a\n href={item.fileUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ fontSize: '12px' }}\n >\n {$`Open file page`}\n </a>\n ) : null}\n </div>\n </section>\n ) as HTMLElement\n\n const previewEl = (await this.ctx.quickPreview.getPreviewElement(file)) || (\n <PreviewPlaceholderNA $={$} />\n )\n\n const previewBox = (\n <div className=\"ipe-quickUpload__preview-content\" style={{ marginTop: '10px' }}>\n {previewEl}\n </div>\n ) as HTMLElement\n\n const isLocked = item.status === 'success'\n const filenameEditor = (\n <div\n className=\"ipe-input-box\"\n style={{\n marginTop: '8px',\n opacity: isLocked ? 0.55 : 1,\n filter: isLocked ? 'grayscale(1)' : undefined,\n pointerEvents: isLocked ? 'none' : undefined,\n }}\n >\n <label htmlFor=\"mu_filename\">{$`Target filename`}</label>\n <input\n id=\"mu_filename\"\n name=\"mu_filename\"\n type=\"text\"\n value={item.filename}\n disabled={isUploading || isLocked}\n onInput={(e: Event) => {\n const v = (e.target as HTMLInputElement).value\n updateItem(item.id, { filename: v })\n renderList()\n }}\n />\n </div>\n ) as HTMLElement\n\n const descEditor = (\n <div\n className=\"ipe-input-box\"\n style={{\n marginTop: '8px',\n opacity: isLocked ? 0.55 : 1,\n filter: isLocked ? 'grayscale(1)' : undefined,\n pointerEvents: isLocked ? 'none' : undefined,\n }}\n >\n <label htmlFor=\"mu_text\">File description</label>\n <textarea\n id=\"mu_text\"\n placeholder={'This file is for...\\n[[Category:XXX]]'}\n disabled={isUploading || isLocked}\n value={item.text || ''}\n onInput={(e: Event) => {\n const v = (e.target as HTMLTextAreaElement).value\n updateItem(item.id, { text: v })\n renderList()\n }}\n ></textarea>\n </div>\n ) as HTMLElement\n\n ui.previewWrapper.appendChild(header)\n ui.previewWrapper.appendChild(previewBox)\n ui.previewWrapper.appendChild(filenameEditor)\n ui.previewWrapper.appendChild(descEditor)\n }\n\n const uploadOne = async (item: UploadItem) => {\n updateItem(item.id, { status: 'uploading', message: undefined })\n renderList()\n await renderPreview()\n\n const body = buildUploadBody(item)\n\n this.ctx.emit('analytics/event', {\n feature: 'quick-upload',\n page: body.filename?.toString() || undefined,\n })\n\n try {\n const result = await this.ctx.wikiFile.upload(body)\n\n if (result.data?.upload?.result === 'Success') {\n const fileUrl = this.ctx.wikiFile.getFileUrl(`File:${result.data.upload.filename}`)\n updateItem(item.id, {\n status: 'success',\n fileUrl,\n result: result.data.upload as any,\n retryable: true,\n })\n renderList()\n await renderPreview()\n return\n }\n\n throw result\n } catch (e) {\n let reasons: string[] = []\n\n if ((e as any)?.data?.upload) {\n const uploadResult = (e as any).data.upload as UploadFileResult\n\n if (uploadResult.result === 'Success') {\n const fname = (uploadResult as any).filename || body.filename\n const fileUrl = this.ctx.wikiFile.getFileUrl(`File:${fname}`)\n updateItem(item.id, {\n status: 'success',\n fileUrl,\n result: uploadResult,\n retryable: true,\n })\n renderList()\n await renderPreview()\n return\n }\n\n if (\n Array.isArray(uploadResult.warnings?.duplicate) &&\n uploadResult.warnings.duplicate.length > 0\n ) {\n reasons.push(`Duplicate of: ${uploadResult.warnings.duplicate.join(', ')}`)\n updateItem(item.id, {\n status: 'warning',\n message: reasons.join('\\n'),\n result: uploadResult,\n retryable: true,\n })\n renderList()\n await renderPreview()\n return\n }\n\n if (uploadResult.warnings?.exists) {\n reasons.push('A file with the same name already exists.')\n updateItem(item.id, {\n status: 'warning',\n message: reasons.join('\\n'),\n result: uploadResult,\n retryable: true,\n })\n renderList()\n await renderPreview()\n return\n }\n\n const { message, retryable } = formatUploadError(e)\n updateItem(item.id, { status: 'error', message, retryable })\n renderList()\n await renderPreview()\n return\n }\n\n const { message, retryable } = formatUploadError(e)\n updateItem(item.id, { status: 'error', message, retryable })\n renderList()\n await renderPreview()\n }\n }\n\n const uploadAll = async (mode: UploadMode = 'all') => {\n if (isUploading) return\n\n let candidates = getUploadCandidates(mode, items)\n\n if (mode === 'retry') {\n if (candidates.length === 0) {\n showMessage(\n 'warning',\n 'Nothing to retry',\n <div>There are no retryable failed/warning items.</div>\n )\n return\n }\n } else if (mode === 'resume') {\n if (candidates.length === 0) {\n showMessage(\n 'warning',\n 'Nothing to resume',\n <div>There are no queued paused items to continue.</div>\n )\n return\n }\n } else {\n if (items.length === 0) {\n showMessage(\n 'warning',\n $`No files selected`,\n <div>{$`Please select one or more files.`}</div>\n )\n return\n }\n if (items.length > confirmThreshold) {\n this.ctx.modal.confirm(\n {\n title: $`Confirm bulk upload`,\n content: (\n <div>\n {$`You are about to upload`} <strong>{items.length}</strong>{' '}\n {$`files at once. Are you sure?`}\n </div>\n ),\n center: true,\n okBtn: { label: $`Upload`, className: 'is-primary is-ghost' },\n cancelBtn: { label: $`Cancel`, className: 'is-danger is-ghost' },\n },\n (confirmed) => {\n if (confirmed) {\n void uploadAll('all')\n }\n return true\n }\n )\n return\n }\n }\n\n if (mode === 'retry') {\n prepareRetryState(candidates)\n renderList()\n await renderPreview()\n candidates = getUploadCandidates('retry', items)\n }\n\n isUploading = true\n pauseRequested = false\n updateFooter()\n\n try {\n const total = candidates.length\n let done = 0\n setProgress(0, total)\n\n for (const item of candidates) {\n if (pauseRequested) {\n const remainingIds = new Set(candidates.slice(done).map((x) => x.id))\n updateMany(remainingIds, (x) =>\n x.status === 'queued' || x.status === 'uploading'\n ? { ...x, status: 'paused', message: 'Paused by user', retryable: true }\n : x\n )\n renderList()\n await renderPreview()\n break\n }\n\n const current = items.find((x) => x.id === item.id)\n if (!current) {\n done++\n setProgress(done, total)\n continue\n }\n\n await uploadOne(current)\n done++\n setProgress(done, total)\n }\n\n const { ok, warn, err, paused } = countByStatus()\n if (paused > 0) {\n showMessage(\n 'warning',\n 'Upload paused',\n <div>\n <div>\n Uploaded: <strong>{ok}</strong>\n </div>\n <div>\n Warnings: <strong>{warn}</strong>\n </div>\n <div>\n Errors: <strong>{err}</strong>\n </div>\n <div>\n Paused: <strong>{paused}</strong>\n </div>\n </div>\n )\n } else if (err === 0 && warn === 0) {\n showMessage(\n 'success',\n 'Upload completed',\n <div>\n <strong>All files uploaded successfully.</strong>\n <div>\n Uploaded: <strong>{ok}</strong>\n </div>\n </div>\n )\n } else {\n showMessage(\n 'warning',\n 'Upload completed with issues',\n <div>\n <div>\n Uploaded: <strong>{ok}</strong>\n </div>\n {warn ? (\n <div>\n Warnings: <strong>{warn}</strong>\n </div>\n ) : null}\n {err ? (\n <div>\n Errors: <strong>{err}</strong>\n </div>\n ) : null}\n </div>\n )\n }\n } finally {\n isUploading = false\n updateFooter()\n }\n }\n\n const handleDrop = (e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n const container = e.currentTarget as HTMLElement\n container?.classList.remove('is-dragover')\n\n const files = Array.from(e.dataTransfer?.files || [])\n if (!files.length) return\n addFiles(files)\n }\n\n const handleDragOver = (e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n const container = e.currentTarget as HTMLElement\n if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy'\n container?.classList.add('is-dragover')\n }\n\n const handleDragLeave = (e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n const container = e.currentTarget as HTMLElement\n container?.classList.remove('is-dragover')\n }\n\n const progressBar = (\n <div style={{ marginBottom: '10px' }}>\n <div\n style={{\n height: '8px',\n borderRadius: '999px',\n background: 'rgba(0,0,0,.08)',\n overflow: 'hidden',\n }}\n >\n <div\n ref={(el: any) => {\n ui.progressEl = el\n }}\n style={{\n height: '100%',\n width: '0%',\n background: 'var(--ipe-primary, #3b82f6)',\n transition: 'width .2s ease',\n }}\n />\n </div>\n <div\n style={{\n marginTop: '6px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '10px',\n }}\n >\n <div\n ref={(el: any) => {\n ui.progressTextEl = el\n }}\n style={{ fontSize: '12px', opacity: 0.8 }}\n >\n 0/0 (0%)\n </div>\n </div>\n </div>\n ) as HTMLElement\n\n const leftPanel = (\n <section style={{ display: 'grid', gap: '10px', minWidth: 0 }}>\n <div className=\"ipe-input-box\">\n <label htmlFor=\"mu_files\">\n Files{' '}\n {items.length > 0 ? (\n <span style={{ opacity: 0.85 }}>({items.length} selected)</span>\n ) : null}\n </label>\n <input\n id=\"mu_files\"\n type=\"file\"\n multiple\n accept={String(accept || '')}\n disabled={isUploading}\n ref={(el: any) => {\n ui.fileInput = el\n }}\n onChange={(e: Event) => {\n const files = Array.from((e.target as HTMLInputElement).files || [])\n addFiles(files)\n ;(e.target as HTMLInputElement).value = ''\n }}\n />\n </div>\n\n <div\n ref={(el: any) => {\n ui.listEl = el\n }}\n />\n </section>\n ) as HTMLElement\n\n const rightPanel = (\n <section style={{ display: 'grid', gap: '10px' }}>\n <div\n className=\"ipe-quickUpload__preview\"\n ref={(el: any) => {\n ui.previewWrapper = el\n }}\n onClick={(e) => {\n const target = e.target\n if (\n target &&\n (target as HTMLElement).closest('img, .ipe-quickUpload__preview-placeholder')\n ) {\n e.preventDefault()\n ui.fileInput?.click()\n }\n }}\n style={{\n border: '1px solid var(--ipe-border-color, rgba(0,0,0,.12))',\n borderRadius: '8px',\n padding: '10px',\n minWidth: 0,\n }}\n />\n </section>\n ) as HTMLElement\n\n const containerEl = (\n <section\n className=\"ipe-quickUpload__container\"\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n style={{ display: 'grid', gap: '12px' }}\n >\n {progressBar}\n <div className=\"ipe-quickUpload__layout\">\n {leftPanel}\n {rightPanel}\n </div>\n\n <div\n style={{\n borderTop: '1px solid var(--ipe-border-color, rgba(0,0,0,.12))',\n paddingTop: '10px',\n display: 'grid',\n gap: '10px',\n }}\n >\n <div className=\"ipe-input-box\">\n <label htmlFor=\"mu_summary\">Summary (applies to all files)</label>\n <textarea\n id=\"mu_summary\"\n disabled={isUploading}\n ref={(el: any) => {\n ui.summaryInput = el\n }}\n onInput={() => {}}\n />\n </div>\n\n <CheckBox\n name=\"ignorewarnings\"\n label={$`Ignore warnings and upload anyway`}\n inputProps={{\n disabled: isUploading,\n ref: (el: any) => {\n ui.ignoreWarnings = el\n },\n }}\n />\n </div>\n </section>\n ) as HTMLElement\n\n modal.setContent(containerEl)\n\n if (ui.summaryInput) ui.summaryInput.value = String(defaultSummary || '')\n\n const updateFooter = () => {\n const { warn, err, paused } = countByStatus()\n const hasFailed = err > 0 || warn > 0\n const hasPaused = paused > 0\n\n let label = $`Upload`\n let action = () => void uploadAll('all')\n let className = 'is-primary is-text'\n\n if (isUploading) {\n label = pauseRequested ? 'Pausing...' : 'Pause after current'\n action = () => {\n pauseRequested = true\n updateFooter()\n }\n } else if (hasPaused) {\n label = 'Resume'\n action = () => void uploadAll('resume')\n } else if (hasFailed) {\n label = 'Retry failed/warnings'\n action = () => void uploadAll('retry')\n }\n\n modal.setButtons([\n {\n label: $`Cancel`,\n className: 'is-danger is-text',\n method: () => modal.close(),\n },\n {\n label: 'Reset',\n className: 'is-text',\n method: () => {\n if (isUploading) return\n resetAll()\n },\n },\n {\n label,\n className,\n method: action,\n },\n ])\n }\n\n renderList()\n await renderPreview()\n\n return modal\n }\n}\n"],"names":["_PluginQuickUpload_decorators","_init","_a","PreviewPlaceholderNA","$","jsxs","jsx","RegisterPreferences","Schema","Inject","PluginQuickUpload","BasePlugin","ctx","IconUpload","e","size","units","index","file","accept","rules","s","fileType","fileName","rule","prefix","isUploading","pauseRequested","showMessage","type","title","content","modal","defaultSummary","confirmThreshold","items","selectedId","ui","updateItem","id","patch","x","removeItem","updateMany","ids","fn","summarizeApiErrors","out","v","cur","formatUploadError","reasons","combined","lower","shouldRetryItem","it","getUploadCandidates","mode","list","prepareRetryState","candidates","idset","c","getSelected","setSelected","renderList","renderPreview","countByStatus","setProgress","done","total","pct","sanitizeFilename","name","resetAll","addFiles","files","accepted","f","newItems","buildUploadBody","item","body","summary","getStatusLabel","status","isActive","row","updateFooter","header","previewEl","previewBox","isLocked","filenameEditor","descEditor","uploadOne","result","fileUrl","uploadResult","fname","message","retryable","uploadAll","confirmed","remainingIds","current","ok","warn","err","paused","handleDrop","handleDragOver","container","handleDragLeave","progressBar","el","leftPanel","containerEl","target","CheckBox","hasFailed","hasPaused","label","action","className","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-BlVSMvH-.js","sources":["../src/plugins/quick-upload/index.tsx"],"sourcesContent":["import { Inject, InPageEdit, Schema } from '@/InPageEdit'\n\nimport './style.scss'\n\nimport BasePlugin from '@/plugins/BasePlugin'\nimport { RegisterPreferences } from '@/decorators/Preferences'\nimport { IconUpload } from '@/components/Icon'\nimport { CheckBox } from '@/components'\nimport type { UploadFileResult } from '@/services/WikiFileService'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n quickUpload: PluginQuickUpload\n }\n interface Preferences {\n 'quickUpload.summary': string\n }\n}\n\ntype UploadItem = {\n id: string\n file: File\n filename: string\n text: string\n status: 'queued' | 'uploading' | 'success' | 'warning' | 'error' | 'paused'\n message?: string\n retryable?: boolean\n fileUrl?: string\n result?: UploadFileResult\n}\n\nconst PreviewPlaceholderNA = ({ $ }: { $: (strings: TemplateStringsArray) => string }) => (\n <div className=\"ipe-quickUpload__preview-placeholder is-na\">\n <span>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n class=\"icon icon-tabler icons-tabler-filled icon-tabler-file-unknown\"\n >\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\n <path d=\"M12 2l.117 .007a1 1 0 0 1 .876 .876l.007 .117v4l.005 .15a2 2 0 0 0 1.838 1.844l.157 .006h4l.117 .007a1 1 0 0 1 .876 .876l.007 .117v9a3 3 0 0 1 -2.824 2.995l-.176 .005h-10a3 3 0 0 1 -2.995 -2.824l-.005 -.176v-14a3 3 0 0 1 2.824 -2.995l.176 -.005zm0 15a1 1 0 0 0 -.993 .883l-.007 .127a1 1 0 0 0 1.993 .117l.007 -.127a1 1 0 0 0 -1 -1m1.136 -5.727a2.5 2.5 0 0 0 -3.037 .604a1 1 0 0 0 1.434 1.389l.088 -.09a.5 .5 0 1 1 .379 .824a1 1 0 0 0 -.002 2a2.5 2.5 0 0 0 1.137 -4.727\" />\n <path d=\"M19 7h-4l-.001 -4.001z\" />\n </svg>\n <p>{$`No preview available`}</p>\n </span>\n </div>\n)\n\n@RegisterPreferences(\n Schema.object({\n 'quickUpload.summary': Schema.string()\n .description('Default summary of the quick upload')\n .default('[IPE-NEXT] Quick upload'),\n })\n)\n@Inject(['modal', '$', 'wikiTitle', 'wikiFile', 'quickPreview', 'preferences'])\nexport class PluginQuickUpload extends BasePlugin {\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'quick-upload')\n }\n\n protected async start() {\n this.injectToolbox()\n this.ctx.set('quickUpload', this)\n }\n\n protected async stop() {}\n\n private injectToolbox() {\n const { $ } = this.ctx\n this.ctx.inject(['toolbox'], (ctx) => {\n ctx.toolbox.addButton({\n id: 'quick-upload',\n group: 'group2',\n index: 2,\n icon: <IconUpload />,\n tooltip: () => $`Quick Upload`,\n onClick: (e) => {\n e.preventDefault()\n this.showModal()\n },\n })\n ctx.on('dispose', () => {\n ctx.toolbox.removeButton('quick-upload')\n })\n })\n }\n\n private formatFileSize(size: number = 0) {\n size = Number(size)\n if (!Number.isFinite(size) || size < 0) return '0 B'\n\n const units = ['B', 'KB', 'MB', 'GB', 'TB']\n let index = 0\n while (size >= 1024 && index < units.length - 1) {\n size /= 1024\n index++\n }\n\n // 使用 Intl 来格式化数字(自动处理千分位、小数等)\n const formatter = new Intl.NumberFormat(undefined, { maximumFractionDigits: 2 })\n return `${formatter.format(size)} ${units[index]}`\n }\n\n private isFileAccepted(file: File, accept: string): boolean {\n if (!accept) return true\n const rules = accept\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n if (!rules.length) return true\n const fileType = file.type || ''\n const fileName = file.name || ''\n return rules.some((rule) => {\n // extension: .png .pdf\n if (rule.startsWith('.')) {\n return fileName.toLowerCase().endsWith(rule.toLowerCase())\n }\n // image/*, video/* ...\n if (rule.endsWith('/*')) {\n const prefix = rule.slice(0, -1) // keep the trailing slash\n return fileType.startsWith(prefix)\n }\n // exact mime\n return fileType === rule\n })\n }\n\n private getDefaultPreviewPlaceholder() {\n const { $ } = this.ctx\n return (\n <div className=\"ipe-quickUpload__preview-placeholder\">\n <span>\n <IconUpload />\n <p>{$`You can drag & drop files to this modal`}</p>\n </span>\n </div>\n )\n }\n\n private safeId() {\n return `mu_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`\n }\n\n async showModal() {\n const { $ } = this.ctx\n\n let isUploading = false\n let pauseRequested = false\n\n const showMessage = (type: 'success' | 'warning' | 'error', title: string, content: any) => {\n this.ctx.modal.notify(type, {\n title,\n content,\n closeAfter: type === 'success' ? 3000 : 8000,\n })\n }\n\n const modal = this.ctx.modal.show({\n className: 'ipe-quickUpload compact-buttons',\n sizeClass: 'mediumToLarge',\n center: false,\n title: $`Quick Upload`,\n content: $`Quick Upload`,\n outSideClose: false,\n beforeClose: () => {\n if (isUploading) {\n showMessage('warning', $`Upload in progress`, $`Please pause or wait for it to finish.`)\n return false\n }\n return true\n },\n })\n\n const defaultSummary = (await this.ctx.preferences.get('quickUpload.summary')) || ''\n const accept = 'image/*,video/*,audio/*,application/pdf'\n const confirmThreshold = 20\n\n let items: UploadItem[] = []\n let selectedId: string | null = null\n\n const ui = {\n fileInput: null as HTMLInputElement | null,\n listEl: null as HTMLElement | null,\n previewWrapper: null as HTMLElement | null,\n progressEl: null as HTMLElement | null,\n progressTextEl: null as HTMLElement | null,\n summaryInput: null as HTMLTextAreaElement | null,\n ignoreWarnings: null as HTMLInputElement | null,\n selectedCountEl: null as HTMLElement | null,\n readyCountEl: null as HTMLElement | null,\n }\n\n const updateItem = (id: string, patch: Partial<UploadItem>) => {\n items = items.map((x) => (x.id === id ? { ...x, ...patch } : x))\n }\n\n const removeItem = (id: string) => {\n items = items.filter((x) => x.id !== id)\n if (selectedId === id) {\n selectedId = items[0]?.id ?? null\n }\n }\n\n const updateMany = (ids: Set<string>, fn: (it: UploadItem) => UploadItem) => {\n items = items.map((x) => (ids.has(x.id) ? fn(x) : x))\n }\n\n const summarizeApiErrors = (e: any) => {\n const out: string[] = []\n const s = (v: any) => (v == null ? '' : String(v))\n if (e instanceof Error) {\n out.push(e.message)\n let cur: any = e\n while (cur?.cause) {\n cur = cur.cause\n if (cur instanceof Error) out.push(cur.message)\n else break\n }\n } else if (e?.data?.error?.info) {\n out.push(s(e.data.error.info))\n } else if (e?.error?.info) {\n out.push(s(e.error.info))\n } else if (e?.message) {\n out.push(s(e.message))\n }\n return out.filter(Boolean)\n }\n\n const formatUploadError = (e: any): { message: string; retryable: boolean } => {\n let reasons = summarizeApiErrors(e)\n if (reasons.length === 0) reasons = ['Upload failed with unknown error.']\n\n const combined = reasons.join('\\n')\n const lower = combined.toLowerCase()\n\n if (\n lower.includes('file is larger') ||\n lower.includes('files larger than') ||\n lower.includes('maximum upload size')\n ) {\n return { message: `File too large\\n${combined}`, retryable: false }\n }\n\n if (lower.includes('network') || lower.includes('timeout') || lower.includes('timed out')) {\n return { message: `Network issue\\n${combined}`, retryable: true }\n }\n\n return { message: combined, retryable: true }\n }\n\n const shouldRetryItem = (it: UploadItem) => {\n if (it.status === 'warning') return true\n if (it.status === 'error') return it.retryable !== false\n return false\n }\n\n type UploadMode = 'all' | 'resume' | 'retry'\n\n const getUploadCandidates = (mode: UploadMode, list: UploadItem[]) => {\n if (mode === 'retry') return list.filter((it) => shouldRetryItem(it))\n if (mode === 'resume') {\n return list.filter(\n (it) => (it.status === 'queued' || it.status === 'paused') && it.retryable !== false\n )\n }\n return list.filter((it) => it.status === 'queued' || it.status === 'paused')\n }\n\n const prepareRetryState = (candidates: UploadItem[]) => {\n const idset = new Set(candidates.map((c) => c.id))\n updateMany(idset, (x) =>\n x.retryable === false ? x : { ...x, status: 'queued', message: undefined }\n )\n }\n\n const getSelected = () => {\n return items.find((x) => x.id === selectedId) || null\n }\n\n const setSelected = (id: string | null) => {\n selectedId = id\n renderList()\n void renderPreview()\n }\n\n const countByStatus = () => {\n const out = { ok: 0, warn: 0, err: 0, paused: 0 }\n for (const it of items) {\n if (it.status === 'success') out.ok++\n else if (it.status === 'warning') out.warn++\n else if (it.status === 'error') out.err++\n else if (it.status === 'paused') out.paused++\n }\n return out\n }\n\n const setProgress = (done: number, total: number) => {\n const pct = total > 0 ? Math.floor((done / total) * 100) : 0\n if (ui.progressTextEl) ui.progressTextEl.textContent = `${done}/${total} (${pct}%)`\n if (ui.progressEl) ui.progressEl.style.width = `${Math.max(0, Math.min(100, pct))}%`\n }\n\n const sanitizeFilename = (name: string) => {\n return (name || '').replace(/\\s+/g, ' ').trim()\n }\n\n const resetAll = () => {\n items = []\n selectedId = null\n setProgress(0, 0)\n if (ui.summaryInput) ui.summaryInput.value = String(defaultSummary || '')\n if (ui.ignoreWarnings) ui.ignoreWarnings.checked = false\n renderList()\n void renderPreview()\n }\n\n const addFiles = (files: File[]) => {\n const accepted = files.filter((f) => this.isFileAccepted(f, String(accept || '')))\n if (!accepted.length) return\n\n const newItems: UploadItem[] = accepted.map((file) => ({\n id: this.safeId(),\n file,\n filename: file.name,\n text: '',\n status: 'queued',\n retryable: true,\n }))\n\n items = [...items, ...newItems]\n if (!selectedId && items.length) {\n selectedId = items[0].id\n }\n renderList()\n void renderPreview()\n }\n\n const buildUploadBody = (item: UploadItem) => {\n const body: Record<string, any> = {}\n\n body.filename = sanitizeFilename(item.filename || item.file.name)\n body.file = item.file\n\n const summary = (ui.summaryInput?.value || '').trim() || ''\n body.comment = summary\n\n body.text = item.text || ''\n\n if (ui.ignoreWarnings?.checked) {\n body.ignorewarnings = '1'\n }\n\n return body\n }\n\n const getStatusLabel = (status: UploadItem['status']) => {\n switch (status) {\n case 'queued':\n return 'Queued'\n case 'uploading':\n return 'Uploading'\n case 'success':\n return 'Uploaded'\n case 'warning':\n return 'Warning'\n case 'error':\n return 'Failed'\n case 'paused':\n return 'Paused'\n default:\n return status\n }\n }\n\n const renderList = () => {\n if (!ui.listEl) return\n ui.listEl.innerHTML = ''\n\n if (!isUploading) {\n setProgress(0, items.length)\n }\n\n if (!items.length) {\n ui.listEl.appendChild(\n <div style={{ opacity: 0.75, padding: '8px 0' }}>\n <p>No files selected.</p>\n </div>\n )\n updateFooter()\n return\n } else {\n const list = (\n <ul\n style={{\n listStyle: 'none',\n padding: 0,\n margin: 0,\n display: 'grid',\n gap: '6px',\n }}\n />\n ) as HTMLUListElement\n\n items.forEach((item) => {\n const isActive = item.id === selectedId\n const row = (\n <li\n style={{\n border: '1px solid var(--ipe-border-color, rgba(0,0,0,.12))',\n borderRadius: '8px',\n padding: '8px',\n cursor: 'pointer',\n background: isActive ? 'rgba(59,130,246,.08)' : 'transparent',\n minWidth: 0,\n }}\n onClick={() => setSelected(item.id)}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>\n <div style={{ flex: 1, minWidth: 0, overflow: 'hidden' }}>\n <div\n style={{\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n wordBreak: 'break-word',\n fontSize: '13px',\n }}\n >\n <strong style={{ fontWeight: 600 }}>{item.filename}</strong>\n </div>\n <div style={{ fontSize: '12px', opacity: 0.75 }}>\n {getStatusLabel(item.status)}\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>\n <button\n type=\"button\"\n className=\"ipe-btn is-text\"\n title={'Remove'}\n onClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n removeItem(item.id)\n renderList()\n void renderPreview()\n }}\n >\n ×\n </button>\n </div>\n </div>\n\n {item.message ? (\n <div\n style={{\n fontSize: '12px',\n opacity: 0.8,\n marginTop: '4px',\n whiteSpace: 'pre-wrap',\n }}\n >\n {item.message}\n </div>\n ) : null}\n </li>\n ) as HTMLLIElement\n\n list.appendChild(row)\n })\n\n ui.listEl.appendChild(list)\n }\n\n updateFooter()\n }\n\n const renderPreview = async () => {\n if (!ui.previewWrapper) return\n ui.previewWrapper.innerHTML = ''\n\n const item = getSelected()\n if (!item) {\n ui.previewWrapper.appendChild(this.getDefaultPreviewPlaceholder())\n return\n }\n\n const file = item.file\n\n const header = (\n <section style={{ display: 'grid', gap: '6px' }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'baseline',\n justifyContent: 'space-between',\n gap: '12px',\n }}\n >\n <strong style={{ wordBreak: 'break-word' }}>{file.name}</strong>\n <span style={{ fontSize: '12px', opacity: 0.8 }}>{this.formatFileSize(file.size)}</span>\n </div>\n <div style={{ display: 'flex', gap: '10px', alignItems: 'center', flexWrap: 'wrap' }}>\n <span style={{ fontSize: '12px', opacity: 0.8 }}>{file.type || $`Unknown type`}</span>\n {item.fileUrl ? (\n <a\n href={item.fileUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ fontSize: '12px' }}\n >\n {$`Open file page`}\n </a>\n ) : null}\n </div>\n </section>\n ) as HTMLElement\n\n const previewEl = (await this.ctx.quickPreview.getPreviewElement(file)) || (\n <PreviewPlaceholderNA $={$} />\n )\n\n const previewBox = (\n <div className=\"ipe-quickUpload__preview-content\" style={{ marginTop: '10px' }}>\n {previewEl}\n </div>\n ) as HTMLElement\n\n const isLocked = item.status === 'success'\n const filenameEditor = (\n <div\n className=\"ipe-input-box\"\n style={{\n marginTop: '8px',\n opacity: isLocked ? 0.55 : 1,\n filter: isLocked ? 'grayscale(1)' : undefined,\n pointerEvents: isLocked ? 'none' : undefined,\n }}\n >\n <label htmlFor=\"mu_filename\">{$`Target filename`}</label>\n <input\n id=\"mu_filename\"\n name=\"mu_filename\"\n type=\"text\"\n value={item.filename}\n disabled={isUploading || isLocked}\n onInput={(e: Event) => {\n const v = (e.target as HTMLInputElement).value\n updateItem(item.id, { filename: v })\n renderList()\n }}\n />\n </div>\n ) as HTMLElement\n\n const descEditor = (\n <div\n className=\"ipe-input-box\"\n style={{\n marginTop: '8px',\n opacity: isLocked ? 0.55 : 1,\n filter: isLocked ? 'grayscale(1)' : undefined,\n pointerEvents: isLocked ? 'none' : undefined,\n }}\n >\n <label htmlFor=\"mu_text\">File description</label>\n <textarea\n id=\"mu_text\"\n placeholder={'This file is for...\\n[[Category:XXX]]'}\n disabled={isUploading || isLocked}\n value={item.text || ''}\n onInput={(e: Event) => {\n const v = (e.target as HTMLTextAreaElement).value\n updateItem(item.id, { text: v })\n renderList()\n }}\n ></textarea>\n </div>\n ) as HTMLElement\n\n ui.previewWrapper.appendChild(header)\n ui.previewWrapper.appendChild(previewBox)\n ui.previewWrapper.appendChild(filenameEditor)\n ui.previewWrapper.appendChild(descEditor)\n }\n\n const uploadOne = async (item: UploadItem) => {\n updateItem(item.id, { status: 'uploading', message: undefined })\n renderList()\n await renderPreview()\n\n const body = buildUploadBody(item)\n\n this.ctx.emit('analytics/event', {\n feature: 'quick-upload',\n page: body.filename?.toString() || undefined,\n })\n\n try {\n const result = await this.ctx.wikiFile.upload(body)\n\n if (result.data?.upload?.result === 'Success') {\n const fileUrl = this.ctx.wikiFile.getFileUrl(`File:${result.data.upload.filename}`)\n updateItem(item.id, {\n status: 'success',\n fileUrl,\n result: result.data.upload as any,\n retryable: true,\n })\n renderList()\n await renderPreview()\n return\n }\n\n throw result\n } catch (e) {\n let reasons: string[] = []\n\n if ((e as any)?.data?.upload) {\n const uploadResult = (e as any).data.upload as UploadFileResult\n\n if (uploadResult.result === 'Success') {\n const fname = (uploadResult as any).filename || body.filename\n const fileUrl = this.ctx.wikiFile.getFileUrl(`File:${fname}`)\n updateItem(item.id, {\n status: 'success',\n fileUrl,\n result: uploadResult,\n retryable: true,\n })\n renderList()\n await renderPreview()\n return\n }\n\n if (\n Array.isArray(uploadResult.warnings?.duplicate) &&\n uploadResult.warnings.duplicate.length > 0\n ) {\n reasons.push(`Duplicate of: ${uploadResult.warnings.duplicate.join(', ')}`)\n updateItem(item.id, {\n status: 'warning',\n message: reasons.join('\\n'),\n result: uploadResult,\n retryable: true,\n })\n renderList()\n await renderPreview()\n return\n }\n\n if (uploadResult.warnings?.exists) {\n reasons.push('A file with the same name already exists.')\n updateItem(item.id, {\n status: 'warning',\n message: reasons.join('\\n'),\n result: uploadResult,\n retryable: true,\n })\n renderList()\n await renderPreview()\n return\n }\n\n const { message, retryable } = formatUploadError(e)\n updateItem(item.id, { status: 'error', message, retryable })\n renderList()\n await renderPreview()\n return\n }\n\n const { message, retryable } = formatUploadError(e)\n updateItem(item.id, { status: 'error', message, retryable })\n renderList()\n await renderPreview()\n }\n }\n\n const uploadAll = async (mode: UploadMode = 'all') => {\n if (isUploading) return\n\n let candidates = getUploadCandidates(mode, items)\n\n if (mode === 'retry') {\n if (candidates.length === 0) {\n showMessage(\n 'warning',\n 'Nothing to retry',\n <div>There are no retryable failed/warning items.</div>\n )\n return\n }\n } else if (mode === 'resume') {\n if (candidates.length === 0) {\n showMessage(\n 'warning',\n 'Nothing to resume',\n <div>There are no queued paused items to continue.</div>\n )\n return\n }\n } else {\n if (items.length === 0) {\n showMessage(\n 'warning',\n $`No files selected`,\n <div>{$`Please select one or more files.`}</div>\n )\n return\n }\n if (items.length > confirmThreshold) {\n this.ctx.modal.confirm(\n {\n title: $`Confirm bulk upload`,\n content: (\n <div>\n {$`You are about to upload`} <strong>{items.length}</strong>{' '}\n {$`files at once. Are you sure?`}\n </div>\n ),\n center: true,\n okBtn: { label: $`Upload`, className: 'is-primary is-ghost' },\n cancelBtn: { label: $`Cancel`, className: 'is-danger is-ghost' },\n },\n (confirmed) => {\n if (confirmed) {\n void uploadAll('all')\n }\n return true\n }\n )\n return\n }\n }\n\n if (mode === 'retry') {\n prepareRetryState(candidates)\n renderList()\n await renderPreview()\n candidates = getUploadCandidates('retry', items)\n }\n\n isUploading = true\n pauseRequested = false\n updateFooter()\n\n try {\n const total = candidates.length\n let done = 0\n setProgress(0, total)\n\n for (const item of candidates) {\n if (pauseRequested) {\n const remainingIds = new Set(candidates.slice(done).map((x) => x.id))\n updateMany(remainingIds, (x) =>\n x.status === 'queued' || x.status === 'uploading'\n ? { ...x, status: 'paused', message: 'Paused by user', retryable: true }\n : x\n )\n renderList()\n await renderPreview()\n break\n }\n\n const current = items.find((x) => x.id === item.id)\n if (!current) {\n done++\n setProgress(done, total)\n continue\n }\n\n await uploadOne(current)\n done++\n setProgress(done, total)\n }\n\n const { ok, warn, err, paused } = countByStatus()\n if (paused > 0) {\n showMessage(\n 'warning',\n 'Upload paused',\n <div>\n <div>\n Uploaded: <strong>{ok}</strong>\n </div>\n <div>\n Warnings: <strong>{warn}</strong>\n </div>\n <div>\n Errors: <strong>{err}</strong>\n </div>\n <div>\n Paused: <strong>{paused}</strong>\n </div>\n </div>\n )\n } else if (err === 0 && warn === 0) {\n showMessage(\n 'success',\n 'Upload completed',\n <div>\n <strong>All files uploaded successfully.</strong>\n <div>\n Uploaded: <strong>{ok}</strong>\n </div>\n </div>\n )\n } else {\n showMessage(\n 'warning',\n 'Upload completed with issues',\n <div>\n <div>\n Uploaded: <strong>{ok}</strong>\n </div>\n {warn ? (\n <div>\n Warnings: <strong>{warn}</strong>\n </div>\n ) : null}\n {err ? (\n <div>\n Errors: <strong>{err}</strong>\n </div>\n ) : null}\n </div>\n )\n }\n } finally {\n isUploading = false\n updateFooter()\n }\n }\n\n const handleDrop = (e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n const container = e.currentTarget as HTMLElement\n container?.classList.remove('is-dragover')\n\n const files = Array.from(e.dataTransfer?.files || [])\n if (!files.length) return\n addFiles(files)\n }\n\n const handleDragOver = (e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n const container = e.currentTarget as HTMLElement\n if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy'\n container?.classList.add('is-dragover')\n }\n\n const handleDragLeave = (e: DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n const container = e.currentTarget as HTMLElement\n container?.classList.remove('is-dragover')\n }\n\n const progressBar = (\n <div style={{ marginBottom: '10px' }}>\n <div\n style={{\n height: '8px',\n borderRadius: '999px',\n background: 'rgba(0,0,0,.08)',\n overflow: 'hidden',\n }}\n >\n <div\n ref={(el: any) => {\n ui.progressEl = el\n }}\n style={{\n height: '100%',\n width: '0%',\n background: 'var(--ipe-primary, #3b82f6)',\n transition: 'width .2s ease',\n }}\n />\n </div>\n <div\n style={{\n marginTop: '6px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '10px',\n }}\n >\n <div\n ref={(el: any) => {\n ui.progressTextEl = el\n }}\n style={{ fontSize: '12px', opacity: 0.8 }}\n >\n 0/0 (0%)\n </div>\n </div>\n </div>\n ) as HTMLElement\n\n const leftPanel = (\n <section style={{ display: 'grid', gap: '10px', minWidth: 0 }}>\n <div className=\"ipe-input-box\">\n <label htmlFor=\"mu_files\">\n Files{' '}\n {items.length > 0 ? (\n <span style={{ opacity: 0.85 }}>({items.length} selected)</span>\n ) : null}\n </label>\n <input\n id=\"mu_files\"\n type=\"file\"\n multiple\n accept={String(accept || '')}\n disabled={isUploading}\n ref={(el: any) => {\n ui.fileInput = el\n }}\n onChange={(e: Event) => {\n const files = Array.from((e.target as HTMLInputElement).files || [])\n addFiles(files)\n ;(e.target as HTMLInputElement).value = ''\n }}\n />\n </div>\n\n <div\n ref={(el: any) => {\n ui.listEl = el\n }}\n />\n </section>\n ) as HTMLElement\n\n const rightPanel = (\n <section style={{ display: 'grid', gap: '10px' }}>\n <div\n className=\"ipe-quickUpload__preview\"\n ref={(el: any) => {\n ui.previewWrapper = el\n }}\n onClick={(e) => {\n const target = e.target\n if (\n target &&\n (target as HTMLElement).closest('img, .ipe-quickUpload__preview-placeholder')\n ) {\n e.preventDefault()\n ui.fileInput?.click()\n }\n }}\n style={{\n border: '1px solid var(--ipe-border-color, rgba(0,0,0,.12))',\n borderRadius: '8px',\n padding: '10px',\n minWidth: 0,\n }}\n />\n </section>\n ) as HTMLElement\n\n const containerEl = (\n <section\n className=\"ipe-quickUpload__container\"\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n style={{ display: 'grid', gap: '12px' }}\n >\n {progressBar}\n <div className=\"ipe-quickUpload__layout\">\n {leftPanel}\n {rightPanel}\n </div>\n\n <div\n style={{\n borderTop: '1px solid var(--ipe-border-color, rgba(0,0,0,.12))',\n paddingTop: '10px',\n display: 'grid',\n gap: '10px',\n }}\n >\n <div className=\"ipe-input-box\">\n <label htmlFor=\"mu_summary\">Summary (applies to all files)</label>\n <textarea\n id=\"mu_summary\"\n disabled={isUploading}\n ref={(el: any) => {\n ui.summaryInput = el\n }}\n onInput={() => {}}\n />\n </div>\n\n <CheckBox\n name=\"ignorewarnings\"\n label={$`Ignore warnings and upload anyway`}\n inputProps={{\n disabled: isUploading,\n ref: (el: any) => {\n ui.ignoreWarnings = el\n },\n }}\n />\n </div>\n </section>\n ) as HTMLElement\n\n modal.setContent(containerEl)\n\n if (ui.summaryInput) ui.summaryInput.value = String(defaultSummary || '')\n\n const updateFooter = () => {\n const { warn, err, paused } = countByStatus()\n const hasFailed = err > 0 || warn > 0\n const hasPaused = paused > 0\n\n let label = $`Upload`\n let action = () => void uploadAll('all')\n let className = 'is-primary is-text'\n\n if (isUploading) {\n label = pauseRequested ? 'Pausing...' : 'Pause after current'\n action = () => {\n pauseRequested = true\n updateFooter()\n }\n } else if (hasPaused) {\n label = 'Resume'\n action = () => void uploadAll('resume')\n } else if (hasFailed) {\n label = 'Retry failed/warnings'\n action = () => void uploadAll('retry')\n }\n\n modal.setButtons([\n {\n label: $`Cancel`,\n className: 'is-danger is-text',\n method: () => modal.close(),\n },\n {\n label: 'Reset',\n className: 'is-text',\n method: () => {\n if (isUploading) return\n resetAll()\n },\n },\n {\n label,\n className,\n method: action,\n },\n ])\n }\n\n renderList()\n await renderPreview()\n\n return modal\n }\n}\n"],"names":["_PluginQuickUpload_decorators","_init","_a","PreviewPlaceholderNA","$","jsxs","jsx","RegisterPreferences","Schema","Inject","PluginQuickUpload","BasePlugin","ctx","IconUpload","e","size","units","index","file","accept","rules","s","fileType","fileName","rule","prefix","isUploading","pauseRequested","showMessage","type","title","content","modal","defaultSummary","confirmThreshold","items","selectedId","ui","updateItem","id","patch","x","removeItem","updateMany","ids","fn","summarizeApiErrors","out","v","cur","formatUploadError","reasons","combined","lower","shouldRetryItem","it","getUploadCandidates","mode","list","prepareRetryState","candidates","idset","c","getSelected","setSelected","renderList","renderPreview","countByStatus","setProgress","done","total","pct","sanitizeFilename","name","resetAll","addFiles","files","accepted","f","newItems","buildUploadBody","item","body","summary","getStatusLabel","status","isActive","row","updateFooter","header","previewEl","previewBox","isLocked","filenameEditor","descEditor","uploadOne","result","fileUrl","uploadResult","fname","message","retryable","uploadAll","confirmed","remainingIds","current","ok","warn","err","paused","handleDrop","handleDragOver","container","handleDragLeave","progressBar","el","leftPanel","containerEl","target","CheckBox","hasFailed","hasPaused","label","action","className","__decoratorStart","__decorateElement","__runInitializers"],"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-
|
|
2
|
+
import { a as C, R as q, S as f } from "./index-DTU2DZU6.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-
|
|
168
|
+
//# sourceMappingURL=index-CUDVeUEv.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-qbW7-LUD.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 .role('keyshortcut')\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":";;;;;;;;;;;;;;;GAAAA,GAAAC,GAAAC;AAoCAF,IAAA,CAACG,EAAO,CAAC,OAAO,YAAY,SAAS,eAAe,GAAG,CAAC,GACvDC;AAAA,EACCC,EAAO,OAAO;AAAA,IACZ,4BAA4BA,EAAO,OAAA,EAChC,QAAQ,QAAQ,EAChB,KAAK,aAAa,EAClB,YAAY,wDAAwD;AAAA,EAAA,CACxE,EACE,MAAM,YAAY,QAAQ,EAC1B,YAAY,uBAAuB;AACxC,CAAA;AACO,MAAMC,WAA2BJ,IAAAK,GAAW;AAAA,EACjD,YAAmBC,GAAiB;AAClC,UAAMA,GAAK,CAAA,GAAI,cAAc,GADZ,KAAA,MAAAA,GAoInB,KAAQ,wCAAwB,IAAA,GA6DhC,KAAQ,kCAAkB,QAAA,GA/LxB,KAAK,IAAI,IAAI,gBAAgBC,EAAa,MAAM,iBAAiB,CAAC;AAAA,EACpE;AAAA,EAEU,QAA8B;AACtC,SAAK,IAAI,GAAG,wBAAwB,KAAK,gBAAgB,KAAK,IAAI,CAAC;AAAA,EACrE;AAAA,EAEU,OAA6B;AAAA,EAAC;AAAA,EAExC,gBACEC,GACAC,GACAC,GACAC,GACAC,GACA;AACA,UAAM,EAAE,GAAAC,MAAM,KAAK;AAEnB,WAAAH,MAAa,KAAK,IAAI,SAAS,aAAa;AAAA,MAC1C,OAAO;AAAA,IAAA,CACR,IAEG,CAACC,KAASA,EAAM,iBAClBA,IAAQ,KAAK,IAAI,MACd,aAAa;AAAA,MACZ,WAAW;AAAA,MACX,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,GAAGC;AAAA,IAAA,CACJ,EACA,KAAA,IAGLD,EAAM,KAAA,GACNA,EAAM,SAASE,uBAAuB,GACtCF,EAAM,WAAW,gBAAAG,EAACC,GAAA,CAAA,CAAY,CAAE,GAChCJ,EAAM,aAAA,GACN,KAAK,IAAI,KAAK,4BAA4B;AAAA,MACxC,KAAK,KAAK;AAAA,MACV,MAAAH;AAAA,MACA,OAAAG;AAAA,MACA,UAAAD;AAAA,IAAA,CACD,GAEDA,EACG,QAAQF,GAAMC,CAAM,EACpB,KAAK,CAACO,MAAQ;AACb,YAAM;AAAA,QACJ,MAAM,EAAE,OAAAC,EAAA;AAAA,MAAM,IACZD;AACJ,MAAAL,EAAM,SAASE,EAAEI,EAAM,KAAK,qBAAqB;AACjD,UAAIC,IAAgC;AACpC,MAAAP,EAAM;AAAA,0BAED,WAAA,EACC,UAAA,gBAAAG;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK,CAACK,MAAQD,IAAYC;AAAA,YAC1B,WAAU;AAAA,YACV,WAAWF,EAAM;AAAA,UAAA;AAAA,QAAA,EAClB,CACH;AAAA,MAAA,GAGA,OAAO,IAAI,QAAQ,OAAO,UAAW,cACvC,OAAO,GAAG,KAAK,kBAAkB,EAAE,KAAK,OAAOC,CAAU,CAAC,GAE5D,KAAK,IAAI,KAAK,wBAAwB;AAAA,QACpC,KAAK,KAAK;AAAA,QACV,OAAAP;AAAA,QACA,UAAAD;AAAA,QACA,MAAAF;AAAA,QACA,WAAWS;AAAA,MAAA,CACZ;AAAA,IACH,CAAC,EACA,MAAM,CAACG,MAAU;AAChB,MAAAT,EAAM,SAASE,mBAAmB,GAClCF,EAAM;AAAA,QACJU,gBAAAA,EAAAC,GAAA,EACE,UAAA;AAAA,UAAA,gBAAAR,EAAC,OAAG,UAAAD,qBAAA,CAAqB;AAAA,UACzB,gBAAAC,EAAC,OAAG,UAAAM,aAAiB,QAAQA,EAAM,UAAU,OAAOA,CAAK,EAAA,CAAE;AAAA,QAAA,EAAA,CAC7D;AAAA,MAAA;AAAA,IAEJ,CAAC,GAEIT;AAAA,EACT;AAAA,EAEA,MAAc,gBAAgB,EAAE,SAAAY,GAAS,OAAAZ,GAAO,UAAAD,KAAmC;AACjF,UAAM,EAAE,GAAAG,MAAM,KAAK;AACnB,QAAIW;AACJ,IAAAb,EAAM;AAAA,MACJ;AAAA,QACE,OAAOE;AAAA,QACP,MAAM;AAAA,QACN,WAAW;AAAA,QACX,UACG,MAAM,KAAK,IAAI,YAAY,IAAI,oCAAoC,KAAM;AAAA,QAC5E,QAAQ,MAAM;AACZ,cAAIY,IACDd,EAAM,YAAA,EAAc,cAAmC,uBAAuB,GAC3E,SAAoB;AAC1B,cAAIY,EAAQ,YAAY,OAAO;AAC7B,kBAAMG,IAAQf,EACX,YAAA,EACA,cAAgC,uBAAuB,GAAG;AAC7D,YAAIe,MACFD,IAAW,KAAKC,CAAK;AAAA,EAAOD,CAAQ;AAAA,UAExC;AAEA,UAAAD,IAAqB,KAAK;AAAA,YACxBC;AAAA,YACA;AAAA,YACAf;AAAA,YACAc;AAAA,YACA;AAAA,cACE,UAAU;AAAA,cACV,WAAW;AAAA,YAAA;AAAA,UACb;AAAA,QAEJ;AAAA,MAAA;AAAA,MAEF;AAAA,IAAA,GAEFb,EAAM,GAAGA,EAAM,MAAM,OAAO,MAAM;AAChC,MAAAa,GAAoB,QAAA,GACpBA,IAAqB;AAAA,IACvB,CAAC;AAAA,EACH;AAAA,EAGQ,iBAAiBG,GAAa;AACpC,UAAMC,IAAS,KAAK,kBAAkB,IAAID,CAAG;AAC7C,QAAIC,EAAQ,QAAOA;AACnB,UAAMC,IAAU,MAAMF,GAAK,EAAE,QAAQ,OAAA,CAAQ,EAC1C,KAAK,CAACG,MAAQA,EAAI,QAAQ,IAAI,cAAc,KAAK,EAAE,EACnD,MAAM,OACL,KAAK,kBAAkB,OAAOH,CAAG,GAC1B,GACR;AACH,gBAAK,kBAAkB,IAAIA,GAAKE,CAAO,GAChCA;AAAA,EACT;AAAA,EACA,MAAM,eAAeE,GAA0B;AAC7C,QAAI,CAACA,EAAW,QAAO;AACvB,QAAIC,GACAC;AACJ,QAAIF,aAAqB;AACvB,MAAAC,IAAcD,EAAU,MACxBE,IAAMF,EAAU,KAAK,MAAM,GAAG,EAAE,IAAA,GAAO,iBAAiB;AAAA,SACnD;AACL,YAAMJ,IAAM,IAAI,IAAII,GAAW,SAAS,MAAM;AAC9C,MAAIJ,EAAI,aAAa,WAAWA,EAAI,aAAa,WAAWA,EAAI,SAAS,WAAW,MAAM,IACxFK,IAAc,MAAM,KAAK,iBAAiBL,EAAI,IAAI,IAElDK,IAAc,IAEhBC,IAAMN,EAAI,SAAS,MAAM,GAAG,EAAE,IAAA,GAAO,iBAAiB;AAAA,IACxD;AACA,WACEK,EAAY,WAAW,QAAQ;AAAA,IACU,CAACA,EAAY,SAAS,KAAK,IAE7D,UAELA,EAAY,WAAW,QAAQ,IAAU,UACzCA,EAAY,WAAW,QAAQ,IAAU,UACzCA,EAAY,WAAW,WAAW,IAAU,SAC5CC,MAAQ,OAAa,aACrBD,EAAY,WAAW,OAAO,IAAU,SAExC,CAAC,OAAO,QAAQ,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE,SAASC,CAAG,IAAU,UAClF,CAAC,OAAO,QAAQ,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,EAAE,SAASA,CAAG,IAAU,UAChF,CAAC,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO,KAAK,EAAE,SAASA,CAAG,IAAU,UACzE,CAAC,QAAQ,KAAK,EAAE,SAASA,CAAG,IAAU,SACtC,CAAC,QAAQ,OAAO,QAAQ,QAAQ,IAAI,EAAE,SAASA,CAAG,IAAU,SAC5D,CAAC,KAAK,EAAE,SAASA,CAAG,IAAU,QAC3B;AAAA,EACT;AAAA,EACA,MAAM,YAAYF,GAA0BG,GAAc;AACxD,UAAMC,IAAiB,MAAM,KAAK,kBAAkBJ,GAAWG,CAAG;AAClE,WAAKC,IACS,KAAK,IAAI,MAAM,OAAO;AAAA,MAClC,WAAW;AAAA,MACX,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,OAAOD,MAAQH,aAAqB,OAAOA,EAAU,OAAOA;AAAA,MAC5D,SAAS,gBAAAjB,EAAC,WAAA,EAAQ,WAAU,6BAA6B,UAAAqB,EAAA,CAAe;AAAA,IAAA,CACzE,IAPoB;AAAA,EASvB;AAAA,EAEQ,aAAaC,GAAY;AAC/B,QAAI,CAAC,KAAK,YAAY,IAAIA,CAAI,GAAG;AAC/B,YAAMC,IAAS,IAAI,gBAAgBD,CAAI;AACvC,WAAK,YAAY,IAAIA,GAAMC,CAAM;AAAA,IACnC;AACA,WAAO,KAAK,YAAY,IAAID,CAAI;AAAA,EAClC;AAAA,EACA,MAAM,kBAAkBL,GAA0BG,GAAc;AAC9D,UAAMI,IAAc,MAAM,KAAK,eAAeP,CAAS,GACjDJ,IAAMI,aAAqB,OAAO,KAAK,aAAaA,CAAS,IAAIA;AACvE,YAAQO,GAAA;AAAA,MACN,KAAK;AACH,eACE,gBAAAxB,EAAC,OAAA,EAAI,KAAKa,GAAK,KAAKO,MAAQH,aAAqB,OAAOA,EAAU,OAAOA,GAAA,CAAY;AAAA,MAEzF,KAAK;AACH,iCAAQ,SAAA,EAAM,KAAKJ,GAAK,UAAU,IAAM,cAAYO,GAAK;AAAA,MAC3D,KAAK;AACH,iCAAQ,SAAA,EAAM,KAAKP,GAAK,UAAU,IAAM,cAAYO,GAAK;AAAA,MAC3D,KAAK;AACH,iCAAQ,SAAA,EAAM,MAAK,mBAAkB,KAAKP,GAAK,cAAYO,GAAK;AAAA,IAAA;AAEpE,WAAO;AAAA,EACT;AAAA,EAEA,gBAAgBR,GAAe;AAC7B,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACnC;AACF;AA/NO3B,IAAAwC,EAAAvC,CAAA;AAAMI,IAANoC,8BAXP1C,GAWaM,CAAA;AAANqC,EAAA1C,GAAA,GAAMK,CAAA;"}
|
|
1
|
+
{"version":3,"file":"index-CUDVeUEv.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 .role('keyshortcut')\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,4 +1,4 @@
|
|
|
1
|
-
import { a as D, R as C, S as k } from "./index-
|
|
1
|
+
import { a as D, R as C, S as k } from "./index-DTU2DZU6.js";
|
|
2
2
|
import { BasePlugin as R } from "./core.js";
|
|
3
3
|
var P = Object.create, _ = Object.defineProperty, M = Object.getOwnPropertyDescriptor, x = (t, e) => (e = Symbol[t]) ? e : /* @__PURE__ */ Symbol.for("Symbol." + t), b = (t) => {
|
|
4
4
|
throw TypeError(t);
|
|
@@ -167,4 +167,4 @@ W(g, 1, v);
|
|
|
167
167
|
export {
|
|
168
168
|
v as PluginInArticleLinks
|
|
169
169
|
};
|
|
170
|
-
//# sourceMappingURL=index-
|
|
170
|
+
//# sourceMappingURL=index-Ce-zc5RR.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-CxjH0_fO.js","sources":["../src/plugins/in-article-links/index.tsx"],"sourcesContent":["import { Inject, InPageEdit, Schema } from '@/InPageEdit'\nimport { CompareApiRequestOptions } from '../quick-diff/index.js'\nimport { QuickEditOptions } from '../quick-edit/index.js'\nimport { WikiLinkMetadata } from '@/services/WikiTitleService.js'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n inArticleLinks: PluginInArticleLinks\n }\n interface Events {\n 'in-article-links/anchor-parsed'(payload: {\n ctx: InPageEdit\n anchor: HTMLAnchorElement\n info: InArticleWikiAnchorMetadata\n }): void\n 'in-article-links/anchor-clicked'(payload: {\n ctx: InPageEdit\n anchor: HTMLAnchorElement\n info: InArticleWikiAnchorMetadata\n event: MouseEvent\n action: 'quickEdit' | 'quickDiff'\n }): void\n }\n interface PreferencesMap {\n 'inArticleLinks.quickEdit.enable': boolean\n 'inArticleLinks.quickDiff.enable': boolean\n 'inArticleLinks.quickEdit.redlinks': boolean\n }\n}\n\nexport interface InArticleWikiAnchorMetadata extends WikiLinkMetadata {\n $el: HTMLAnchorElement\n kind: 'normal' | 'mw:File'\n external: boolean\n redlink: boolean\n}\n\n@Inject(['wiki', 'wikiTitle', 'preferences', '$'])\n@RegisterPreferences(\n Schema.object({\n 'inArticleLinks.enable': Schema.boolean()\n .description('Whether to enable in-article links')\n .default(true),\n 'inArticleLinks.quickDiff.enable': Schema.boolean()\n .description('Whether to enable in-article links for quick diff')\n .default(true),\n 'inArticleLinks.quickEdit.enable': Schema.boolean()\n .description('Whether to enable in-article links for quick edit')\n .default(true),\n 'inArticleLinks.quickEdit.redlinks': Schema.boolean()\n .description('Whether to show quick edit button for redlinks')\n .default(true),\n })\n .description('In-article links preferences')\n .extra('category', 'in-article-links')\n)\nexport class PluginInArticleLinks extends BasePlugin<{\n linkClassName: string\n}> {\n constructor(ctx: InPageEdit) {\n super(\n ctx,\n {\n linkClassName: 'ipe__in-article-link',\n },\n 'InArticleLinks'\n )\n this.ctx.set('inArticleLinks', this)\n const { $ } = this.ctx\n\n this.ctx.preferences.defineCategory({\n name: 'in-article-links',\n label: $`prefs.inArticleLinks.label`,\n description: $`prefs.inArticleLinks.$`,\n index: 9,\n })\n }\n\n protected async start() {\n // TODO: 这些都不应该硬编码,暂时先这样\n if (await this.ctx.preferences.get('inArticleLinks.quickEdit.enable')) {\n this.handleQuickEdit()\n }\n if (await this.ctx.preferences.get('inArticleLinks.quickDiff.enable')) {\n this.handleQuickDiff()\n }\n }\n\n protected async stop() {\n Array.from(\n document.getElementsByClassName(this.config.linkClassName) as HTMLCollectionOf<HTMLElement>\n ).forEach((el) => {\n el.remove()\n })\n document.querySelectorAll<HTMLElement>('[data-ipe-edit-mounted]').forEach((el) => {\n el.dataset.ipeEditMounted = undefined\n })\n }\n\n private _cachedAnchorInfo = new WeakMap<HTMLAnchorElement, InArticleWikiAnchorMetadata>()\n parseAnchor(anchor: HTMLAnchorElement): InArticleWikiAnchorMetadata | null {\n // 不是链接元素\n if (!(anchor instanceof HTMLAnchorElement)) {\n return null\n }\n\n const cached = this._cachedAnchorInfo.get(anchor)\n if (cached) {\n return cached\n }\n\n const attrHref = anchor.getAttribute('href') || ''\n if (!this.ctx.wikiTitle.validateHrefAttr(attrHref)) {\n return null\n }\n const href = anchor.href || ''\n const linkInfo = this.ctx.wikiTitle.parseWikiLink(href)\n if (!linkInfo) {\n return null\n }\n\n const info: InArticleWikiAnchorMetadata = {\n $el: anchor,\n kind: anchor.closest('[typeof^=\"mw:File\"]') ? 'mw:File' : 'normal',\n external: anchor.classList.contains('external') || !!attrHref.startsWith('http'),\n redlink: anchor.classList.contains('new') || linkInfo.params.has('redlink'),\n ...linkInfo,\n }\n this._cachedAnchorInfo.set(anchor, info)\n this.ctx.emit('in-article-links/anchor-parsed', {\n ctx: this.ctx,\n anchor,\n info,\n })\n return info\n }\n\n scanAnchors(\n parent: HTMLElement,\n filter?: (info: InArticleWikiAnchorMetadata) => boolean\n ): InArticleWikiAnchorMetadata[] {\n const anchors = parent.querySelectorAll<HTMLAnchorElement>('a[href]')\n return Array.from(anchors)\n .map((anchor) => this.parseAnchor(anchor))\n .filter(\n (anchor) => anchor !== null && (!filter || filter(anchor))\n ) as InArticleWikiAnchorMetadata[]\n }\n\n private onContentReady(callback: ($content: JQuery<HTMLElement>) => void) {\n const register = () => {\n if (!window.mw) return\n window.mw.hook('wikipage.content').add(callback)\n const $content = (window as any).$?.('#mw-content-text')\n if ($content?.length) callback($content)\n }\n\n if (window.mw && typeof window.mw.hook === 'function') {\n register()\n } else {\n window.RLQ = window.RLQ || ([] as any)\n window.RLQ.push(['mediawiki.base', register])\n }\n }\n\n async handleQuickEdit() {\n let enable = false\n const showButtonOnRedlinks = await this.ctx.preferences.get('inArticleLinks.quickEdit.redlinks')\n\n this.ctx.inject(['quickEdit'], (ctx) => {\n enable = true\n ctx.on('dispose', () => {\n enable = false\n })\n\n this.onContentReady(($content) => {\n if (!enable || !$content?.length) {\n return\n }\n const anchors = this.scanAnchors($content.get(0)!, ({ action, title, redlink }) => {\n const enabled = showButtonOnRedlinks || !redlink\n if (!enabled) {\n return false\n }\n const isActionEdit = ['edit', 'create'].includes(action)\n if (isActionEdit) {\n return true\n }\n const isSpecialEdit = title?.isSpecial('edit') || title?.isSpecial('newsection')\n if (isSpecialEdit) {\n return title!.getMainText().split('/').length >= 2\n }\n return false\n })\n anchors.forEach((info) => {\n const { $el, title, pageId, params } = info\n if ($el.dataset.ipeEditMounted) {\n return\n }\n $el.dataset.ipeEditMounted = '1'\n\n const notCompatible = params.has('preload') || params.has('redo')\n if (notCompatible) {\n return this.ctx.logger.debug($el, `Not compatible with quick edit`)\n }\n\n const titleText = title?.getPrefixedDBKey() || ''\n const sectionRaw = params.get('section')?.replace(/^T-/, '') || undefined\n const revisionRaw = params.get('oldid')\n const createOnly = params.has('redlink')\n\n let section: 'new' | number | undefined = undefined\n if (sectionRaw === 'new' || title?.isSpecial('newsection')) {\n section = 'new'\n } else if (sectionRaw && /^\\d+$/.test(sectionRaw)) {\n section = parseInt(sectionRaw, 10)\n }\n\n const revision = revisionRaw ? parseInt(revisionRaw, 10) : undefined\n\n const payload: Partial<QuickEditOptions> = {\n title: titleText,\n pageId: pageId || undefined,\n section,\n revision,\n createOnly,\n }\n\n const link = ctx.quickEdit.createQuickEditButton(payload, { label: '' })\n link.classList.add(this.config.linkClassName)\n link.addEventListener('click', (e) => {\n this.ctx.emit('in-article-links/anchor-clicked', {\n ctx: this.ctx,\n anchor: $el,\n info,\n event: e,\n action: 'quickEdit',\n })\n })\n\n $el.insertAdjacentElement('afterend', link)\n })\n })\n })\n }\n\n handleQuickDiff() {\n let enable = false\n const isRelative = (str: string): str is 'prev' | 'next' | 'cur' =>\n ['prev', 'next', 'cur'].includes(str)\n\n this.ctx.inject(['quickDiff'], (ctx) => {\n enable = true\n ctx.on('dispose', () => {\n enable = false\n })\n\n this.onContentReady(($content) => {\n if (!enable || !$content?.length) {\n return\n }\n const anchors = this.scanAnchors($content.get(0)!, ({ params, title }) => {\n return !!(params.has('diff') || title?.isSpecial('diff'))\n })\n anchors.forEach((info) => {\n const { $el, title, params } = info\n if ($el.dataset.ipeDiffMounted) {\n return\n }\n $el.dataset.ipeDiffMounted = '1'\n\n let diff: string | null\n let oldid: string | null\n if (title?.getNamespaceId() === -1) {\n // prettier-ignore\n ;[/** special page name */, oldid, diff] = title.getMainDBKey().split('/')\n if (!diff) {\n diff = 'prev'\n }\n } else {\n diff = params.get('diff')\n oldid = params.get('oldid')\n }\n if (!diff || !oldid) {\n return\n }\n\n const compare: Partial<CompareApiRequestOptions> = {}\n if (isRelative(diff)) {\n compare.fromrev = parseInt(oldid)\n compare.torelative = diff\n } else {\n compare.fromrev = parseInt(oldid)\n compare.torev = parseInt(diff)\n }\n\n const link = this.ctx.quickDiff.createQuickDiffButton(compare, { label: '' })\n link.classList.add(this.config.linkClassName)\n link.addEventListener('click', (e) => {\n this.ctx.emit('in-article-links/anchor-clicked', {\n ctx: this.ctx,\n anchor: $el,\n info,\n event: e,\n action: 'quickDiff',\n })\n })\n\n $el.insertAdjacentElement('afterend', link)\n })\n })\n })\n }\n}\n"],"names":["_PluginInArticleLinks_decorators","_init","_a","Inject","RegisterPreferences","Schema","PluginInArticleLinks","BasePlugin","ctx","$","el","anchor","cached","attrHref","href","linkInfo","info","parent","filter","anchors","callback","register","$content","enable","showButtonOnRedlinks","action","title","redlink","$el","pageId","params","titleText","sectionRaw","revisionRaw","createOnly","section","revision","payload","link","e","isRelative","str","diff","oldid","compare","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-Ce-zc5RR.js","sources":["../src/plugins/in-article-links/index.tsx"],"sourcesContent":["import { Inject, InPageEdit, Schema } from '@/InPageEdit'\nimport { CompareApiRequestOptions } from '../quick-diff/index.js'\nimport { QuickEditOptions } from '../quick-edit/index.js'\nimport { WikiLinkMetadata } from '@/services/WikiTitleService.js'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n inArticleLinks: PluginInArticleLinks\n }\n interface Events {\n 'in-article-links/anchor-parsed'(payload: {\n ctx: InPageEdit\n anchor: HTMLAnchorElement\n info: InArticleWikiAnchorMetadata\n }): void\n 'in-article-links/anchor-clicked'(payload: {\n ctx: InPageEdit\n anchor: HTMLAnchorElement\n info: InArticleWikiAnchorMetadata\n event: MouseEvent\n action: 'quickEdit' | 'quickDiff'\n }): void\n }\n interface PreferencesMap {\n 'inArticleLinks.quickEdit.enable': boolean\n 'inArticleLinks.quickDiff.enable': boolean\n 'inArticleLinks.quickEdit.redlinks': boolean\n }\n}\n\nexport interface InArticleWikiAnchorMetadata extends WikiLinkMetadata {\n $el: HTMLAnchorElement\n kind: 'normal' | 'mw:File'\n external: boolean\n redlink: boolean\n}\n\n@Inject(['wiki', 'wikiTitle', 'preferences', '$'])\n@RegisterPreferences(\n Schema.object({\n 'inArticleLinks.enable': Schema.boolean()\n .description('Whether to enable in-article links')\n .default(true),\n 'inArticleLinks.quickDiff.enable': Schema.boolean()\n .description('Whether to enable in-article links for quick diff')\n .default(true),\n 'inArticleLinks.quickEdit.enable': Schema.boolean()\n .description('Whether to enable in-article links for quick edit')\n .default(true),\n 'inArticleLinks.quickEdit.redlinks': Schema.boolean()\n .description('Whether to show quick edit button for redlinks')\n .default(true),\n })\n .description('In-article links preferences')\n .extra('category', 'in-article-links')\n)\nexport class PluginInArticleLinks extends BasePlugin<{\n linkClassName: string\n}> {\n constructor(ctx: InPageEdit) {\n super(\n ctx,\n {\n linkClassName: 'ipe__in-article-link',\n },\n 'InArticleLinks'\n )\n this.ctx.set('inArticleLinks', this)\n const { $ } = this.ctx\n\n this.ctx.preferences.defineCategory({\n name: 'in-article-links',\n label: $`prefs.inArticleLinks.label`,\n description: $`prefs.inArticleLinks.$`,\n index: 9,\n })\n }\n\n protected async start() {\n // TODO: 这些都不应该硬编码,暂时先这样\n if (await this.ctx.preferences.get('inArticleLinks.quickEdit.enable')) {\n this.handleQuickEdit()\n }\n if (await this.ctx.preferences.get('inArticleLinks.quickDiff.enable')) {\n this.handleQuickDiff()\n }\n }\n\n protected async stop() {\n Array.from(\n document.getElementsByClassName(this.config.linkClassName) as HTMLCollectionOf<HTMLElement>\n ).forEach((el) => {\n el.remove()\n })\n document.querySelectorAll<HTMLElement>('[data-ipe-edit-mounted]').forEach((el) => {\n el.dataset.ipeEditMounted = undefined\n })\n }\n\n private _cachedAnchorInfo = new WeakMap<HTMLAnchorElement, InArticleWikiAnchorMetadata>()\n parseAnchor(anchor: HTMLAnchorElement): InArticleWikiAnchorMetadata | null {\n // 不是链接元素\n if (!(anchor instanceof HTMLAnchorElement)) {\n return null\n }\n\n const cached = this._cachedAnchorInfo.get(anchor)\n if (cached) {\n return cached\n }\n\n const attrHref = anchor.getAttribute('href') || ''\n if (!this.ctx.wikiTitle.validateHrefAttr(attrHref)) {\n return null\n }\n const href = anchor.href || ''\n const linkInfo = this.ctx.wikiTitle.parseWikiLink(href)\n if (!linkInfo) {\n return null\n }\n\n const info: InArticleWikiAnchorMetadata = {\n $el: anchor,\n kind: anchor.closest('[typeof^=\"mw:File\"]') ? 'mw:File' : 'normal',\n external: anchor.classList.contains('external') || !!attrHref.startsWith('http'),\n redlink: anchor.classList.contains('new') || linkInfo.params.has('redlink'),\n ...linkInfo,\n }\n this._cachedAnchorInfo.set(anchor, info)\n this.ctx.emit('in-article-links/anchor-parsed', {\n ctx: this.ctx,\n anchor,\n info,\n })\n return info\n }\n\n scanAnchors(\n parent: HTMLElement,\n filter?: (info: InArticleWikiAnchorMetadata) => boolean\n ): InArticleWikiAnchorMetadata[] {\n const anchors = parent.querySelectorAll<HTMLAnchorElement>('a[href]')\n return Array.from(anchors)\n .map((anchor) => this.parseAnchor(anchor))\n .filter(\n (anchor) => anchor !== null && (!filter || filter(anchor))\n ) as InArticleWikiAnchorMetadata[]\n }\n\n private onContentReady(callback: ($content: JQuery<HTMLElement>) => void) {\n const register = () => {\n if (!window.mw) return\n window.mw.hook('wikipage.content').add(callback)\n const $content = (window as any).$?.('#mw-content-text')\n if ($content?.length) callback($content)\n }\n\n if (window.mw && typeof window.mw.hook === 'function') {\n register()\n } else {\n window.RLQ = window.RLQ || ([] as any)\n window.RLQ.push(['mediawiki.base', register])\n }\n }\n\n async handleQuickEdit() {\n let enable = false\n const showButtonOnRedlinks = await this.ctx.preferences.get('inArticleLinks.quickEdit.redlinks')\n\n this.ctx.inject(['quickEdit'], (ctx) => {\n enable = true\n ctx.on('dispose', () => {\n enable = false\n })\n\n this.onContentReady(($content) => {\n if (!enable || !$content?.length) {\n return\n }\n const anchors = this.scanAnchors($content.get(0)!, ({ action, title, redlink }) => {\n const enabled = showButtonOnRedlinks || !redlink\n if (!enabled) {\n return false\n }\n const isActionEdit = ['edit', 'create'].includes(action)\n if (isActionEdit) {\n return true\n }\n const isSpecialEdit = title?.isSpecial('edit') || title?.isSpecial('newsection')\n if (isSpecialEdit) {\n return title!.getMainText().split('/').length >= 2\n }\n return false\n })\n anchors.forEach((info) => {\n const { $el, title, pageId, params } = info\n if ($el.dataset.ipeEditMounted) {\n return\n }\n $el.dataset.ipeEditMounted = '1'\n\n const notCompatible = params.has('preload') || params.has('redo')\n if (notCompatible) {\n return this.ctx.logger.debug($el, `Not compatible with quick edit`)\n }\n\n const titleText = title?.getPrefixedDBKey() || ''\n const sectionRaw = params.get('section')?.replace(/^T-/, '') || undefined\n const revisionRaw = params.get('oldid')\n const createOnly = params.has('redlink')\n\n let section: 'new' | number | undefined = undefined\n if (sectionRaw === 'new' || title?.isSpecial('newsection')) {\n section = 'new'\n } else if (sectionRaw && /^\\d+$/.test(sectionRaw)) {\n section = parseInt(sectionRaw, 10)\n }\n\n const revision = revisionRaw ? parseInt(revisionRaw, 10) : undefined\n\n const payload: Partial<QuickEditOptions> = {\n title: titleText,\n pageId: pageId || undefined,\n section,\n revision,\n createOnly,\n }\n\n const link = ctx.quickEdit.createQuickEditButton(payload, { label: '' })\n link.classList.add(this.config.linkClassName)\n link.addEventListener('click', (e) => {\n this.ctx.emit('in-article-links/anchor-clicked', {\n ctx: this.ctx,\n anchor: $el,\n info,\n event: e,\n action: 'quickEdit',\n })\n })\n\n $el.insertAdjacentElement('afterend', link)\n })\n })\n })\n }\n\n handleQuickDiff() {\n let enable = false\n const isRelative = (str: string): str is 'prev' | 'next' | 'cur' =>\n ['prev', 'next', 'cur'].includes(str)\n\n this.ctx.inject(['quickDiff'], (ctx) => {\n enable = true\n ctx.on('dispose', () => {\n enable = false\n })\n\n this.onContentReady(($content) => {\n if (!enable || !$content?.length) {\n return\n }\n const anchors = this.scanAnchors($content.get(0)!, ({ params, title }) => {\n return !!(params.has('diff') || title?.isSpecial('diff'))\n })\n anchors.forEach((info) => {\n const { $el, title, params } = info\n if ($el.dataset.ipeDiffMounted) {\n return\n }\n $el.dataset.ipeDiffMounted = '1'\n\n let diff: string | null\n let oldid: string | null\n if (title?.getNamespaceId() === -1) {\n // prettier-ignore\n ;[/** special page name */, oldid, diff] = title.getMainDBKey().split('/')\n if (!diff) {\n diff = 'prev'\n }\n } else {\n diff = params.get('diff')\n oldid = params.get('oldid')\n }\n if (!diff || !oldid) {\n return\n }\n\n const compare: Partial<CompareApiRequestOptions> = {}\n if (isRelative(diff)) {\n compare.fromrev = parseInt(oldid)\n compare.torelative = diff\n } else {\n compare.fromrev = parseInt(oldid)\n compare.torev = parseInt(diff)\n }\n\n const link = this.ctx.quickDiff.createQuickDiffButton(compare, { label: '' })\n link.classList.add(this.config.linkClassName)\n link.addEventListener('click', (e) => {\n this.ctx.emit('in-article-links/anchor-clicked', {\n ctx: this.ctx,\n anchor: $el,\n info,\n event: e,\n action: 'quickDiff',\n })\n })\n\n $el.insertAdjacentElement('afterend', link)\n })\n })\n })\n }\n}\n"],"names":["_PluginInArticleLinks_decorators","_init","_a","Inject","RegisterPreferences","Schema","PluginInArticleLinks","BasePlugin","ctx","$","el","anchor","cached","attrHref","href","linkInfo","info","parent","filter","anchors","callback","register","$content","enable","showButtonOnRedlinks","action","title","redlink","$el","pageId","params","titleText","sectionRaw","revisionRaw","createOnly","section","revision","payload","link","e","isRelative","str","diff","oldid","compare","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { j as n, p as I } from "./Promise.withResolvers-C4chhLB1.js";
|
|
2
|
-
import { S as p, E as v, p as x, a as P } from "./index-
|
|
2
|
+
import { S as p, E as v, p as x, a as P } from "./index-DTU2DZU6.js";
|
|
3
3
|
import { BasePlugin as U } from "./core.js";
|
|
4
4
|
var q = Object.create, f = Object.defineProperty, B = Object.getOwnPropertyDescriptor, b = (i, t) => (t = Symbol[i]) ? t : /* @__PURE__ */ Symbol.for("Symbol." + i), w = (i) => {
|
|
5
5
|
throw TypeError(i);
|
|
@@ -216,4 +216,4 @@ j(_, 1, m);
|
|
|
216
216
|
export {
|
|
217
217
|
m as PluginAnalytics
|
|
218
218
|
};
|
|
219
|
-
//# sourceMappingURL=index-
|
|
219
|
+
//# sourceMappingURL=index-CkSdNy0U.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-Dp_n8QEV.js","sources":["../src/plugins/analytics/index.tsx"],"sourcesContent":["import { Endpoints } from '@/constants/endpoints.js'\nimport { Inject, InPageEdit, Schema } from '@/InPageEdit'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n analytics: PluginAnalytics\n }\n interface Events {\n 'analytics/event'(payload: { feature: string; subtype?: string; page?: string }): void\n }\n}\n\nexport interface IPEBeaconPayload {\n siteApi: string\n siteName?: string\n userId: number\n userName: string\n version?: string\n usages: IPEBeaconUsage[]\n}\n\nexport interface IPEBeaconUsage {\n ts: number\n feature: string\n subtype?: string\n page?: string\n}\n\n@Inject(['wiki', 'preferences', '$'])\nexport class PluginAnalytics extends BasePlugin {\n private _usages: IPEBeaconUsage[] = []\n private _timer: ReturnType<typeof setInterval> | null = null\n private readonly MAX_QUEUE_SIZE = 50\n private readonly INTERVAL_MS = 60 * 1000 // 1分钟\n\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'analytics')\n this._setupTimer()\n this._registerUnloadHandler()\n this._showConfirmNotify()\n this._initPluginListeners()\n ctx.set('analytics', this)\n }\n\n protected start(): Promise<void> | void {\n const ctx = this.ctx\n const $ = ctx.$\n ctx.preferences.registerCustomConfig(\n 'analytics',\n Schema.object({\n 'analytics._intro': Schema.const(\n <section>\n <h3>{$`InPageEdit Analytics`}</h3>\n <p>\n {$`InPageEdit Analytics is the companion analytics platform for the InPageEdit NEXT project. By collecting and displaying usage data from around the world, it helps developers and the community better understand how the tool is used, optimize feature design, and enhance user experience.`}\n </p>\n <h4>{$`What data will be collected?`}</h4>\n <ol style={{ listStyle: 'number', paddingLeft: '1em' }}>\n <li>\n <strong>{$`Usage data`}</strong>:{' '}\n {$`When and which features you use, what pages you edit, etc.`}\n </li>\n <li>\n <strong>{$`User information`}</strong>: {$`Your user name and user ID.`}\n </li>\n <li>\n <strong>{$`Site information`}</strong>: {$`This wiki's url and site name.`}\n </li>\n </ol>\n <p>\n <strong>{$`NO sensitive data will be collected.`}</strong>\n </p>\n <div style={{ display: 'grid', gap: '0.5rem' }}>\n <a href={this.analyticsDashUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n <button className=\"btn\" style={{ width: '100%' }}>\n {$`Analytics Platform`}\n </button>\n </a>\n <a\n href={`${this.analyticsDashUrl}/_redirect/user?${new URLSearchParams({\n siteApi: this.ctx.wiki.getSciprtUrl('api'),\n mwUserId: this.ctx.wiki.userInfo.id.toString(),\n }).toString()}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <button className=\"btn\" style={{ width: '100%' }}>\n {$`View My Data`}\n </button>\n </a>\n </div>\n </section>\n ).role('raw-html'),\n 'analytics.enabled': Schema.boolean()\n .description($`prefs.analytics.enabled`)\n .default(false),\n }).description($`prefs.analytics.$`),\n 'general'\n )\n }\n\n private get analyticsDashUrl() {\n return import.meta.env.PROD ? Endpoints.ANALYTICS_DASH_URL : 'http://localhost:20105'\n }\n private get analyticsApiBase() {\n return import.meta.env.PROD ? Endpoints.ANALYTICS_API_BASE : 'http://localhost:20105/api/v6'\n }\n\n private _setupTimer() {\n this._timer = setInterval(() => {\n if (this._usages.length > 0) {\n this.sendBeacon()\n }\n }, this.INTERVAL_MS)\n }\n\n private _registerUnloadHandler() {\n const handleUnload = () => {\n if (this._usages.length > 0) {\n this.sendBeacon()\n }\n }\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n handleUnload()\n }\n })\n\n window.addEventListener('pagehide', handleUnload)\n window.addEventListener('beforeunload', handleUnload)\n }\n\n private async _showConfirmNotify() {\n const { $ } = this.ctx\n this.ctx.inject(['modal', 'storage'], async (ctx) => {\n const key = 'analytics/confirm-shown'\n const shown = await ctx.storage.simpleKV.get(key)\n const enabled = await ctx.preferences.get('analytics.enabled')\n if (shown || enabled) {\n return\n }\n ctx.modal.notify(\n 'confirm',\n {\n title: $`Enable Analytics`,\n content: (\n <div>\n <p>{$`Help us improve InPageEdit by sharing your usage data with us.`}</p>\n <p>{$`What data will be collected?`}</p>\n <ul style={{ listStyle: 'auto', paddingLeft: '1.5em' }}>\n <li>\n {$`Usage data`}: {$`When and which features you use, what pages you edit, etc.`}\n </li>\n <li>\n {$`User information`}: {$`Your user name and user ID.`}\n </li>\n <li>\n {$`Site information`}: {$`This wiki's url and site name.`}\n </li>\n </ul>\n <p>\n <strong>{$`NO sensitive data will be collected.`}</strong>\n </p>\n </div>\n ),\n okBtn: {\n label: $`Enable`,\n },\n cancelBtn: {\n label: $`Disable`,\n },\n closeAfter: 0,\n onClose: () => {\n this.ctx.storage.simpleKV.set(key, 1)\n },\n },\n (result) => {\n ctx.preferences.set('analytics.enabled', result)\n if (result) {\n this.addEvent('analytics', 'enabled')\n }\n }\n )\n })\n }\n\n private _initPluginListeners() {\n const ctx = this.ctx\n ctx.on('analytics/event', (payload) => {\n if (!payload) return\n this.addEvent(payload.feature, payload.subtype, payload.page)\n })\n ctx.on('in-article-links/anchor-clicked', (payload) => {\n this.addEvent('in-article-links', paramCase(payload.action))\n })\n ctx.on('quick-diff/loaded', (payload) => {\n this.addEvent('quick-diff', 'loaded', payload.compare.fromtitle)\n })\n ctx.on('quick-redirect/submit', (payload) => {\n this.addEvent('quick-redirect', 'submit', payload.payload.to || undefined)\n })\n ctx.on('quick-preview/loaded', (payload) => {\n this.addEvent('quick-preview', 'loaded', payload.wikiPage.title)\n })\n ctx.on('quick-edit/wiki-page', (payload) => {\n this.addEvent('quick-edit', undefined, payload.wikiPage.title)\n })\n ctx.on('quick-edit/submit', (payload) => {\n this.addEvent('quick-edit', 'submit', payload.wikiPage.title)\n })\n ctx.on('quick-move/submit', () => {\n this.addEvent('quick-move', 'submit')\n })\n ctx.on('toolbox/button-clicked', ({ payload }) => {\n this.addEvent('toolbox', `button-clicked#${payload.id || 'unknown'}`)\n })\n ctx.on('plugin-store/plugin-installed', ({ registry, id, by }) => {\n if (by === 'new-added') {\n this.addEvent('plugin-store', 'plugin-installed', `${id}@${registry.name}`)\n }\n })\n ctx.on('plugin-store/plugin-uninstalled', ({ registry, id }) => {\n this.addEvent('plugin-store', 'plugin-uninstalled', `${id}@${registry.name}`)\n })\n }\n\n public addEvent(feature: string, subtype?: string, page?: string) {\n if (!feature) return\n const usage: IPEBeaconUsage = {\n ts: Date.now(),\n feature,\n subtype,\n page,\n }\n this._usages.push(usage)\n\n // 如果usages数组超过50个,立即发送\n if (this._usages.length >= this.MAX_QUEUE_SIZE) {\n this.sendBeacon()\n }\n\n return this\n }\n\n private async sendBeacon() {\n if (this._usages.length === 0) {\n return true\n }\n\n const enabled = await this.ctx.preferences.get<boolean>('analytics.enabled', false)\n if (!enabled) {\n this.logger.debug('Analytics disabled, skipping')\n return true\n }\n\n const usages = this._usages.splice(0, this._usages.length)\n const payload: IPEBeaconPayload = {\n siteApi: this.ctx.wiki.getSciprtUrl('api'),\n siteName: this.ctx.wiki.siteInfo.general.sitename,\n userId: this.ctx.wiki.userInfo.id,\n userName: this.ctx.wiki.userInfo.name,\n version: this.ctx.version.split('-')[0],\n usages,\n }\n const body = JSON.stringify(payload)\n\n const endpoint = `${this.analyticsApiBase}/submit`\n\n const beaconOK = navigator?.sendBeacon?.(endpoint, body)\n if (beaconOK) {\n this.logger.debug('Beacon sent successfully', payload)\n return true\n } else {\n this.logger.debug('Beacon failed, sending via XMLHttpRequest')\n const { promise, resolve, reject } = promiseWithResolvers<boolean>()\n try {\n const xhr = new XMLHttpRequest()\n xhr.open('POST', endpoint, true)\n xhr.setRequestHeader('Content-Type', 'application/json')\n xhr.send(body)\n xhr.onload = () => {\n this.logger.debug('Beacon sent successfully via XMLHttpRequest', payload)\n resolve(xhr.status >= 200 && xhr.status < 300)\n }\n xhr.onerror = () => {\n reject(new Error('Failed to send beacon'))\n }\n } catch (error) {\n reject(error)\n }\n return promise\n }\n }\n\n /**\n * 清理资源\n */\n protected stop() {\n if (this._timer !== null) {\n clearInterval(this._timer)\n this._timer = null\n }\n // 在销毁前发送剩余的数据\n if (this._usages.length > 0) {\n this.sendBeacon()\n }\n }\n}\n"],"names":["_PluginAnalytics_decorators","_init","_a","Inject","PluginAnalytics","BasePlugin","ctx","$","Schema","jsx","jsxs","Endpoints","handleUnload","key","shown","enabled","result","payload","paramCase","registry","id","by","feature","subtype","page","usage","usages","body","endpoint","promise","resolve","reject","promiseWithResolvers","xhr","error","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-CkSdNy0U.js","sources":["../src/plugins/analytics/index.tsx"],"sourcesContent":["import { Endpoints } from '@/constants/endpoints.js'\nimport { Inject, InPageEdit, Schema } from '@/InPageEdit'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n analytics: PluginAnalytics\n }\n interface Events {\n 'analytics/event'(payload: { feature: string; subtype?: string; page?: string }): void\n }\n}\n\nexport interface IPEBeaconPayload {\n siteApi: string\n siteName?: string\n userId: number\n userName: string\n version?: string\n usages: IPEBeaconUsage[]\n}\n\nexport interface IPEBeaconUsage {\n ts: number\n feature: string\n subtype?: string\n page?: string\n}\n\n@Inject(['wiki', 'preferences', '$'])\nexport class PluginAnalytics extends BasePlugin {\n private _usages: IPEBeaconUsage[] = []\n private _timer: ReturnType<typeof setInterval> | null = null\n private readonly MAX_QUEUE_SIZE = 50\n private readonly INTERVAL_MS = 60 * 1000 // 1分钟\n\n constructor(public ctx: InPageEdit) {\n super(ctx, {}, 'analytics')\n this._setupTimer()\n this._registerUnloadHandler()\n this._showConfirmNotify()\n this._initPluginListeners()\n ctx.set('analytics', this)\n }\n\n protected start(): Promise<void> | void {\n const ctx = this.ctx\n const $ = ctx.$\n ctx.preferences.registerCustomConfig(\n 'analytics',\n Schema.object({\n 'analytics._intro': Schema.const(\n <section>\n <h3>{$`InPageEdit Analytics`}</h3>\n <p>\n {$`InPageEdit Analytics is the companion analytics platform for the InPageEdit NEXT project. By collecting and displaying usage data from around the world, it helps developers and the community better understand how the tool is used, optimize feature design, and enhance user experience.`}\n </p>\n <h4>{$`What data will be collected?`}</h4>\n <ol style={{ listStyle: 'number', paddingLeft: '1em' }}>\n <li>\n <strong>{$`Usage data`}</strong>:{' '}\n {$`When and which features you use, what pages you edit, etc.`}\n </li>\n <li>\n <strong>{$`User information`}</strong>: {$`Your user name and user ID.`}\n </li>\n <li>\n <strong>{$`Site information`}</strong>: {$`This wiki's url and site name.`}\n </li>\n </ol>\n <p>\n <strong>{$`NO sensitive data will be collected.`}</strong>\n </p>\n <div style={{ display: 'grid', gap: '0.5rem' }}>\n <a href={this.analyticsDashUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n <button className=\"btn\" style={{ width: '100%' }}>\n {$`Analytics Platform`}\n </button>\n </a>\n <a\n href={`${this.analyticsDashUrl}/_redirect/user?${new URLSearchParams({\n siteApi: this.ctx.wiki.getSciprtUrl('api'),\n mwUserId: this.ctx.wiki.userInfo.id.toString(),\n }).toString()}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <button className=\"btn\" style={{ width: '100%' }}>\n {$`View My Data`}\n </button>\n </a>\n </div>\n </section>\n ).role('raw-html'),\n 'analytics.enabled': Schema.boolean()\n .description($`prefs.analytics.enabled`)\n .default(false),\n }).description($`prefs.analytics.$`),\n 'general'\n )\n }\n\n private get analyticsDashUrl() {\n return import.meta.env.PROD ? Endpoints.ANALYTICS_DASH_URL : 'http://localhost:20105'\n }\n private get analyticsApiBase() {\n return import.meta.env.PROD ? Endpoints.ANALYTICS_API_BASE : 'http://localhost:20105/api/v6'\n }\n\n private _setupTimer() {\n this._timer = setInterval(() => {\n if (this._usages.length > 0) {\n this.sendBeacon()\n }\n }, this.INTERVAL_MS)\n }\n\n private _registerUnloadHandler() {\n const handleUnload = () => {\n if (this._usages.length > 0) {\n this.sendBeacon()\n }\n }\n\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') {\n handleUnload()\n }\n })\n\n window.addEventListener('pagehide', handleUnload)\n window.addEventListener('beforeunload', handleUnload)\n }\n\n private async _showConfirmNotify() {\n const { $ } = this.ctx\n this.ctx.inject(['modal', 'storage'], async (ctx) => {\n const key = 'analytics/confirm-shown'\n const shown = await ctx.storage.simpleKV.get(key)\n const enabled = await ctx.preferences.get('analytics.enabled')\n if (shown || enabled) {\n return\n }\n ctx.modal.notify(\n 'confirm',\n {\n title: $`Enable Analytics`,\n content: (\n <div>\n <p>{$`Help us improve InPageEdit by sharing your usage data with us.`}</p>\n <p>{$`What data will be collected?`}</p>\n <ul style={{ listStyle: 'auto', paddingLeft: '1.5em' }}>\n <li>\n {$`Usage data`}: {$`When and which features you use, what pages you edit, etc.`}\n </li>\n <li>\n {$`User information`}: {$`Your user name and user ID.`}\n </li>\n <li>\n {$`Site information`}: {$`This wiki's url and site name.`}\n </li>\n </ul>\n <p>\n <strong>{$`NO sensitive data will be collected.`}</strong>\n </p>\n </div>\n ),\n okBtn: {\n label: $`Enable`,\n },\n cancelBtn: {\n label: $`Disable`,\n },\n closeAfter: 0,\n onClose: () => {\n this.ctx.storage.simpleKV.set(key, 1)\n },\n },\n (result) => {\n ctx.preferences.set('analytics.enabled', result)\n if (result) {\n this.addEvent('analytics', 'enabled')\n }\n }\n )\n })\n }\n\n private _initPluginListeners() {\n const ctx = this.ctx\n ctx.on('analytics/event', (payload) => {\n if (!payload) return\n this.addEvent(payload.feature, payload.subtype, payload.page)\n })\n ctx.on('in-article-links/anchor-clicked', (payload) => {\n this.addEvent('in-article-links', paramCase(payload.action))\n })\n ctx.on('quick-diff/loaded', (payload) => {\n this.addEvent('quick-diff', 'loaded', payload.compare.fromtitle)\n })\n ctx.on('quick-redirect/submit', (payload) => {\n this.addEvent('quick-redirect', 'submit', payload.payload.to || undefined)\n })\n ctx.on('quick-preview/loaded', (payload) => {\n this.addEvent('quick-preview', 'loaded', payload.wikiPage.title)\n })\n ctx.on('quick-edit/wiki-page', (payload) => {\n this.addEvent('quick-edit', undefined, payload.wikiPage.title)\n })\n ctx.on('quick-edit/submit', (payload) => {\n this.addEvent('quick-edit', 'submit', payload.wikiPage.title)\n })\n ctx.on('quick-move/submit', () => {\n this.addEvent('quick-move', 'submit')\n })\n ctx.on('toolbox/button-clicked', ({ payload }) => {\n this.addEvent('toolbox', `button-clicked#${payload.id || 'unknown'}`)\n })\n ctx.on('plugin-store/plugin-installed', ({ registry, id, by }) => {\n if (by === 'new-added') {\n this.addEvent('plugin-store', 'plugin-installed', `${id}@${registry.name}`)\n }\n })\n ctx.on('plugin-store/plugin-uninstalled', ({ registry, id }) => {\n this.addEvent('plugin-store', 'plugin-uninstalled', `${id}@${registry.name}`)\n })\n }\n\n public addEvent(feature: string, subtype?: string, page?: string) {\n if (!feature) return\n const usage: IPEBeaconUsage = {\n ts: Date.now(),\n feature,\n subtype,\n page,\n }\n this._usages.push(usage)\n\n // 如果usages数组超过50个,立即发送\n if (this._usages.length >= this.MAX_QUEUE_SIZE) {\n this.sendBeacon()\n }\n\n return this\n }\n\n private async sendBeacon() {\n if (this._usages.length === 0) {\n return true\n }\n\n const enabled = await this.ctx.preferences.get<boolean>('analytics.enabled', false)\n if (!enabled) {\n this.logger.debug('Analytics disabled, skipping')\n return true\n }\n\n const usages = this._usages.splice(0, this._usages.length)\n const payload: IPEBeaconPayload = {\n siteApi: this.ctx.wiki.getSciprtUrl('api'),\n siteName: this.ctx.wiki.siteInfo.general.sitename,\n userId: this.ctx.wiki.userInfo.id,\n userName: this.ctx.wiki.userInfo.name,\n version: this.ctx.version.split('-')[0],\n usages,\n }\n const body = JSON.stringify(payload)\n\n const endpoint = `${this.analyticsApiBase}/submit`\n\n const beaconOK = navigator?.sendBeacon?.(endpoint, body)\n if (beaconOK) {\n this.logger.debug('Beacon sent successfully', payload)\n return true\n } else {\n this.logger.debug('Beacon failed, sending via XMLHttpRequest')\n const { promise, resolve, reject } = promiseWithResolvers<boolean>()\n try {\n const xhr = new XMLHttpRequest()\n xhr.open('POST', endpoint, true)\n xhr.setRequestHeader('Content-Type', 'application/json')\n xhr.send(body)\n xhr.onload = () => {\n this.logger.debug('Beacon sent successfully via XMLHttpRequest', payload)\n resolve(xhr.status >= 200 && xhr.status < 300)\n }\n xhr.onerror = () => {\n reject(new Error('Failed to send beacon'))\n }\n } catch (error) {\n reject(error)\n }\n return promise\n }\n }\n\n /**\n * 清理资源\n */\n protected stop() {\n if (this._timer !== null) {\n clearInterval(this._timer)\n this._timer = null\n }\n // 在销毁前发送剩余的数据\n if (this._usages.length > 0) {\n this.sendBeacon()\n }\n }\n}\n"],"names":["_PluginAnalytics_decorators","_init","_a","Inject","PluginAnalytics","BasePlugin","ctx","$","Schema","jsx","jsxs","Endpoints","handleUnload","key","shown","enabled","result","payload","paramCase","registry","id","by","feature","subtype","page","usage","usages","body","endpoint","promise","resolve","reject","promiseWithResolvers","xhr","error","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
|