From 31614374a774fc527e812420bb6fdbedc3db4232 Mon Sep 17 00:00:00 2001 From: PingChuan <1259732256@qq.com> Date: Sat, 22 Nov 2025 19:02:53 +0800 Subject: [PATCH 01/13] =?UTF-8?q?temp=EF=BC=9A=E5=A4=87=E4=BB=BD=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/collabora/CollaboraViewer.tsx | 136 ++++++++++++++++--- app/components/collabora/Uno.ts | 81 ++++++++++- app/components/collabora/hooks.ts | 128 +++++++++++++++-- app/components/collabora/types.ts | 27 ++++ app/components/reviews/FilePreview.tsx | 106 +++++++++++---- 5 files changed, 419 insertions(+), 59 deletions(-) diff --git a/app/components/collabora/CollaboraViewer.tsx b/app/components/collabora/CollaboraViewer.tsx index a26e3e1..c181edc 100644 --- a/app/components/collabora/CollaboraViewer.tsx +++ b/app/components/collabora/CollaboraViewer.tsx @@ -10,30 +10,63 @@ * @encoding UTF-8 */ -import { useRef } from 'react'; -import type { CollaboraViewerProps } from './types'; +import { useRef, forwardRef, useImperativeHandle, useState, useEffect } from 'react'; +import type { CollaboraViewerProps, CollaboraViewerHandle } from './types'; import { useCollaboraConfig, useDocumentReady, useCollaboraUnoCommands } from './hooks'; +import { sendUnoCommand } from './Uno'; /** * Collabora 文档查看器组件 * @param props - 组件属性 + * @param ref - 父组件传入的 ref,用于暴露命令接口 */ -export function CollaboraViewer({ - fileId, - mode = 'view', - userId = 'guest', - userName = '访客', -}: CollaboraViewerProps) { - const iframeRef = useRef(null); +export const CollaboraViewer = forwardRef( + function CollaboraViewer( + { + fileId, + mode = 'view', + userId = 'guest', + userName = '访客', + }, + ref + ) { + const iframeRef = useRef(null); - // 1. 加载 Collabora 配置 - const { config, loading, error } = useCollaboraConfig(fileId, mode, userId, userName); + // 调试面板状态 + const [unoCmd, setUnoCmd] = useState('.uno:GoToStartOfDoc'); + const [unoArgs, setUnoArgs] = useState('{}'); + const [unoResult, setUnoResult] = useState(null); - // 2. 监听文档加载状态 - const { isDocumentLoaded } = useDocumentReady(iframeRef); + // 1. 加载 Collabora 配置 + const { config, loading, error } = useCollaboraConfig(fileId, mode, userId, userName); - // 3. UNO 命令封装 - const unoCommands = useCollaboraUnoCommands(iframeRef); + // 2. 监听文档加载状态 + const { isDocumentLoaded } = useDocumentReady(iframeRef); + + // 3. UNO 命令封装 + const unoCommands = useCollaboraUnoCommands(iframeRef); + + // 4. 暴露接口给父组件 + useImperativeHandle(ref, () => ({ + unoCommands, + isReady: isDocumentLoaded, + mode, + }), [unoCommands, isDocumentLoaded, mode]); + + // 5. 将 sendUnoCommand 挂载到 window 对象,供调试面板和控制台使用 + useEffect(() => { + if (iframeRef.current?.contentWindow) { + (window as any).sendUno = (cmd: string, args: any = {}) => { + if (iframeRef.current?.contentWindow) { + sendUnoCommand(iframeRef.current.contentWindow, cmd, args); + } + }; + } + + return () => { + delete (window as any).sendUno; + }; + }, [isDocumentLoaded]); // 加载中状态 if (loading) { @@ -60,8 +93,75 @@ export function CollaboraViewer({ ); } + // 发送 UNO 命令的处理函数 + const sendUno = () => { + if (!iframeRef.current?.contentWindow) { + setUnoResult('iframe 不可用'); + return; + } + + if (!(window as any).sendUno) { + setUnoResult('window.sendUno 未初始化'); + return; + } + + let args: any = {}; + const raw = (unoArgs || '').trim(); + if (raw !== '') { + try { + args = JSON.parse(raw); + } catch (err) { + try { + // fallback: replace single quotes with double quotes and parse + args = JSON.parse(raw.replace(/'(.*?)'/g, '"$1"')); + } catch (err2) { + console.error('解析 UNO Args 失败:', err2); + setUnoResult('Args 解析失败,请使用有效 JSON'); + return; + } + } + } + + try { + // 先让 iframe 获得焦点 + iframeRef.current.focus(); + console.log('[调试面板] 已聚焦 iframe'); + + (window as any).sendUno?.(unoCmd, args); + setUnoResult(`已发送: ${unoCmd}`); + } catch (e) { + console.error('发送 UNO 失败:', e); + setUnoResult('发送失败,请查看控制台'); + } + }; + return (
+ {/* UNO 命令测试面板 */} +
+ setUnoCmd(e.target.value)} + placeholder="UNO 命令" + aria-label="UNO 命令" + /> + setUnoArgs(e.target.value)} + placeholder="UNO Args (JSON)" + aria-label="UNO Args (JSON)" + /> + + {unoResult && {unoResult}} +
+ {/* 文档加载提示 */} {!isDocumentLoaded && (
@@ -85,10 +185,12 @@ export function CollaboraViewer({ allow="clipboard-read; clipboard-write" title={`Collabora Online - ${config.fileName}`} sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-modals" + tabIndex={0} />
); -} +}); -// 导出 UNO 命令 hook 供父组件使用(如果需要) +// 导出类型和 hook +export type { CollaboraViewerHandle }; export { useCollaboraUnoCommands }; diff --git a/app/components/collabora/Uno.ts b/app/components/collabora/Uno.ts index c20af04..f67a551 100644 --- a/app/components/collabora/Uno.ts +++ b/app/components/collabora/Uno.ts @@ -19,7 +19,6 @@ export function sendUnoCommand( ): void { const message = { MessageId: 'Send_UNO_Command', - SendTime: Date.now(), Values: { Command: command, Args: args, @@ -130,10 +129,25 @@ export function unoEscape(iframeWindow: Window): void { } /** - * 滚动到文档开头 + * 滚动到文档开头 (带焦点请求) * @param iframeWindow - iframe 的 contentWindow */ -export function unoScrollToTop(iframeWindow: Window): void { +export async function unoScrollToTop(iframeWindow: Window): Promise { + // 1. 先请求 iframe 获取焦点 + const focusMessage = { + MessageId: 'custompostMessage', + Values: { + Command: 'REQUEST_FOCUS', + Args: {}, + }, + }; + console.log('[custompostMessage] 请求焦点 (滚动到顶部)'); + iframeWindow.postMessage(JSON.stringify(focusMessage), '*'); + + // 2. 等待焦点激活 + await new Promise((resolve) => setTimeout(resolve, 100)); + + // 3. 发送滚动命令 sendUnoCommand(iframeWindow, '.uno:GoToStartOfDoc', {}); } @@ -166,3 +180,64 @@ export function unoGetState(iframeWindow: Window): void { console.log('[UNO] 发送 Get_State (.uno:ModifiedStatus) - 等待命令队列执行完成'); iframeWindow.postMessage(JSON.stringify(message), '*'); } + +/** + * 放大文档(固定步长) + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoZoomPlus(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:ZoomPlus', {}); +} + +/** + * 缩小文档(固定步长) + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoZoomMinus(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:ZoomMinus', {}); +} + +/** + * 设置文档缩放比例 + * @param iframeWindow - iframe 的 contentWindow + * @param percentage - 缩放百分比(例如:100 表示 100%) + */ +export function unoSetZoom(iframeWindow: Window, percentage: number): void { + sendUnoCommand(iframeWindow, '.uno:Zoom', { + Zoom: { + type: 'short', + value: percentage, + }, + }); +} + +/** + * 跳转到指定页面 + * @param iframeWindow - iframe 的 contentWindow + * @param pageNumber - 页码(从1开始) + */ +export function unoGotoPage(iframeWindow: Window, pageNumber: number): void { + sendUnoCommand(iframeWindow, '.uno:GotoPage', { + Page: { + type: 'long', + value: pageNumber, + }, + }); +} + +/** + * 跳转到第一页 + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoFirstPage(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:FirstPage', {}); +} + +/** + * 跳转到最后一页 + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoLastPage(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:LastPage', {}); +} + diff --git a/app/components/collabora/hooks.ts b/app/components/collabora/hooks.ts index 37e4815..d7ef109 100644 --- a/app/components/collabora/hooks.ts +++ b/app/components/collabora/hooks.ts @@ -21,6 +21,12 @@ import { unoEscape, unoScrollToTop, unoSave, + unoZoomPlus, + unoZoomMinus, + unoSetZoom, + unoGotoPage, + unoFirstPage, + unoLastPage, } from './Uno'; import { COLLABORA_URL } from '~/config/api-config'; @@ -131,9 +137,8 @@ export function useCollaboraUnoCommands(iframeRef: RefObject) console.warn('[UNO] iframe 不可用'); return; } - console.log(`[UNO] 搜索文本: "${text}"`); - unoSearchText(iframeRef.current.contentWindow, text); + await unoSearchText(iframeRef.current.contentWindow, text); await new Promise((resolve) => setTimeout(resolve, 100)); }, [iframeRef] @@ -175,9 +180,8 @@ export function useCollaboraUnoCommands(iframeRef: RefObject) console.warn('[UNO] iframe 不可用'); return; } - console.log(`[UNO] 替换文本: "${searchText}" -> "${replaceText}"`); - unoReplaceText(iframeRef.current.contentWindow, searchText, replaceText); + await unoReplaceText(iframeRef.current.contentWindow, searchText, replaceText); await new Promise((resolve) => setTimeout(resolve, 200)); }, [iframeRef] @@ -192,9 +196,8 @@ export function useCollaboraUnoCommands(iframeRef: RefObject) console.warn('[UNO] iframe 不可用'); return; } - console.log(`[UNO] 高亮文本: "${text}"`); - unoHighlightText(iframeRef.current.contentWindow, text, color); + await unoHighlightText(iframeRef.current.contentWindow, text, color); await new Promise((resolve) => setTimeout(resolve, 200)); }, [iframeRef] @@ -209,9 +212,8 @@ export function useCollaboraUnoCommands(iframeRef: RefObject) console.warn('[UNO] iframe 不可用'); return; } - console.log(`[UNO] 移除高亮: "${text}"`); - unoRemoveHighlight(iframeRef.current.contentWindow, text); + await unoRemoveHighlight(iframeRef.current.contentWindow, text); await new Promise((resolve) => setTimeout(resolve, 200)); }, [iframeRef] @@ -227,7 +229,7 @@ export function useCollaboraUnoCommands(iframeRef: RefObject) } console.log('[UNO] 取消选中'); - unoEscape(iframeRef.current.contentWindow); + await unoEscape(iframeRef.current.contentWindow); await new Promise((resolve) => setTimeout(resolve, 50)); }, [iframeRef]); @@ -241,7 +243,7 @@ export function useCollaboraUnoCommands(iframeRef: RefObject) } console.log('[UNO] 滚动到顶部'); - unoScrollToTop(iframeRef.current.contentWindow); + await unoScrollToTop(iframeRef.current.contentWindow); await new Promise((resolve) => setTimeout(resolve, 100)); }, [iframeRef]); @@ -255,10 +257,102 @@ export function useCollaboraUnoCommands(iframeRef: RefObject) } console.log('[UNO] 保存文档'); - unoSave(iframeRef.current.contentWindow); + await unoSave(iframeRef.current.contentWindow); await new Promise((resolve) => setTimeout(resolve, 1000)); }, [iframeRef]); + /** + * 放大文档 + */ + const zoomIn = useCallback(async () => { + if (!iframeRef.current?.contentWindow) { + console.warn('[UNO] iframe 不可用'); + return; + } + + console.log('[UNO] 放大文档'); + await unoZoomPlus(iframeRef.current.contentWindow); + await new Promise((resolve) => setTimeout(resolve, 100)); + }, [iframeRef]); + + /** + * 缩小文档 + */ + const zoomOut = useCallback(async () => { + if (!iframeRef.current?.contentWindow) { + console.warn('[UNO] iframe 不可用'); + return; + } + + console.log('[UNO] 缩小文档'); + await unoZoomMinus(iframeRef.current.contentWindow); + await new Promise((resolve) => setTimeout(resolve, 100)); + }, [iframeRef]); + + /** + * 设置缩放比例 + * @param percentage - 缩放百分比 (例如:100 表示 100%) + */ + const setZoom = useCallback( + async (percentage: number) => { + if (!iframeRef.current?.contentWindow) { + console.warn('[UNO] iframe 不可用'); + return; + } + + console.log(`[UNO] 设置缩放比例: ${percentage}%`); + await unoSetZoom(iframeRef.current.contentWindow, percentage); + await new Promise((resolve) => setTimeout(resolve, 100)); + }, + [iframeRef] + ); + + /** + * 跳转到指定页面 + * @param pageNumber - 页码(从1开始) + */ + const gotoPage = useCallback( + async (pageNumber: number) => { + if (!iframeRef.current?.contentWindow) { + console.warn('[UNO] iframe 不可用'); + return; + } + + console.log(`[UNO] 跳转到第 ${pageNumber} 页`); + await unoGotoPage(iframeRef.current.contentWindow, pageNumber); + await new Promise((resolve) => setTimeout(resolve, 100)); + }, + [iframeRef] + ); + + /** + * 跳转到第一页 + */ + const gotoFirstPage = useCallback(async () => { + if (!iframeRef.current?.contentWindow) { + console.warn('[UNO] iframe 不可用'); + return; + } + + console.log('[UNO] 跳转到第一页'); + await unoFirstPage(iframeRef.current.contentWindow); + await new Promise((resolve) => setTimeout(resolve, 100)); + }, [iframeRef]); + + /** + * 跳转到最后一页 + */ + const gotoLastPage = useCallback(async () => { + if (!iframeRef.current?.contentWindow) { + console.warn('[UNO] iframe 不可用'); + return; + } + + console.log('[UNO] 跳转到最后一页'); + await unoLastPage(iframeRef.current.contentWindow); + await new Promise((resolve) => setTimeout(resolve, 100)); + }, [iframeRef]); + return useMemo( () => ({ searchText, @@ -269,6 +363,12 @@ export function useCollaboraUnoCommands(iframeRef: RefObject) escapeSelection, scrollToTop, saveDocument, + zoomIn, + zoomOut, + setZoom, + gotoPage, + gotoFirstPage, + gotoLastPage, }), [ searchText, @@ -279,6 +379,12 @@ export function useCollaboraUnoCommands(iframeRef: RefObject) escapeSelection, scrollToTop, saveDocument, + zoomIn, + zoomOut, + setZoom, + gotoPage, + gotoFirstPage, + gotoLastPage, ] ); } diff --git a/app/components/collabora/types.ts b/app/components/collabora/types.ts index 94e4a36..72e920c 100644 --- a/app/components/collabora/types.ts +++ b/app/components/collabora/types.ts @@ -35,3 +35,30 @@ export interface CollaboraViewerProps { /** 用户名称 */ userName?: string; } + +/** + * CollaboraViewer 暴露给父组件的方法接口 + */ +export interface CollaboraViewerHandle { + /** UNO 命令方法集合 */ + unoCommands: { + searchText: (text: string) => Promise; + locateText: (text: string) => Promise; + replaceText: (searchText: string, replaceText: string) => Promise; + highlightText: (text: string, color?: number) => Promise; + removeHighlight: (text: string) => Promise; + escapeSelection: () => Promise; + scrollToTop: () => Promise; + saveDocument: () => Promise; + zoomIn: () => Promise; + zoomOut: () => Promise; + setZoom: (percentage: number) => Promise; + gotoPage: (pageNumber: number) => Promise; + gotoFirstPage: () => Promise; + gotoLastPage: () => Promise; + }; + /** 文档是否已加载完成 */ + isReady: boolean; + /** 当前模式 */ + mode: 'view' | 'edit'; +} diff --git a/app/components/reviews/FilePreview.tsx b/app/components/reviews/FilePreview.tsx index be6ca10..352c3ea 100644 --- a/app/components/reviews/FilePreview.tsx +++ b/app/components/reviews/FilePreview.tsx @@ -5,7 +5,7 @@ import { useState, useEffect, useRef, ChangeEvent } from 'react'; import { Document, Page, pdfjs } from 'react-pdf'; import { DOCUMENT_URL } from '~/api/axios-client'; -import { CollaboraViewer } from '~/components/collabora/CollaboraViewer'; +import { CollaboraViewer, type CollaboraViewerHandle } from '~/components/collabora/CollaboraViewer'; // 设置worker路径为public目录下的worker文件 // 使用已经下载的兼容版本 (pdfjs-dist v2.12.313) @@ -85,10 +85,17 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage const [zoomLevel, setZoomLevel] = useState(100); // const [highlightsVisible, setHighlightsVisible] = useState(true); const contentRef = useRef(null); + const collaboraViewerRef = useRef(null); const [numPages, setNumPages] = useState(null); const [loadError, setLoadError] = useState(null); const [pageInputValue, setPageInputValue] = useState(''); - + + // 获取文件类型 + const real_path = fileContent.path || fileContent.template_contract_path || ''; + const fileExtension = real_path.split('.').pop()?.toLowerCase(); + const isDocx = fileExtension === 'docx'; + const isPdf = fileExtension === 'pdf'; + // 拖拽状态管理 const [dragMode, setDragMode] = useState(false); // 是否处于拖拽模式 const [isDragging, setIsDragging] = useState(false); @@ -97,15 +104,35 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage // 放大文档 const handleZoomIn = () => { - if (zoomLevel < 200) { - setZoomLevel(prevZoom => prevZoom + 10); + if (isDocx) { + // DOCX 文件:调用 Collabora UNO 命令 + if (!collaboraViewerRef.current?.isReady) { + toastService.warning('文档尚未加载完成,请稍候...'); + return; + } + collaboraViewerRef.current?.unoCommands.zoomIn(); + } else if (isPdf) { + // PDF 文件:修改 zoomLevel 状态 + if (zoomLevel < 200) { + setZoomLevel(prevZoom => prevZoom + 10); + } } }; - + // 缩小文档 const handleZoomOut = () => { - if (zoomLevel > 50) { - setZoomLevel(prevZoom => prevZoom - 10); + if (isDocx) { + // DOCX 文件:调用 Collabora UNO 命令 + if (!collaboraViewerRef.current?.isReady) { + toastService.warning('文档尚未加载完成,请稍候...'); + return; + } + collaboraViewerRef.current?.unoCommands.zoomOut(); + } else if (isPdf) { + // PDF 文件:修改 zoomLevel 状态 + if (zoomLevel > 50) { + setZoomLevel(prevZoom => prevZoom - 10); + } } }; @@ -243,21 +270,37 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage // 处理页码跳转 const handlePageJump = () => { - if (!pageInputValue || !numPages) return; - + if (!pageInputValue) return; + const targetPageNum = parseInt(pageInputValue, 10); - - // 验证页码是否在有效范围内 - if (targetPageNum > 0 && targetPageNum <= numPages) { - // 找到目标页面元素并滚动到该位置 - const pageElement = document.getElementById(`page-${targetPageNum}`); - if (pageElement) { - pageElement.scrollIntoView({ behavior: 'smooth', block: 'start' }); + + if (isDocx) { + // DOCX 文件:调用 Collabora UNO 命令 + if (!collaboraViewerRef.current?.isReady) { + toastService.warning('文档尚未加载完成,请稍候...'); + return; + } + if (targetPageNum > 0) { + collaboraViewerRef.current?.unoCommands.gotoPage(targetPageNum); + } else { + toastService.warning('请输入有效页码'); + setPageInputValue(''); + } + } else if (isPdf) { + // PDF 文件:验证页码并滚动到目标页面 + if (!numPages) return; + + if (targetPageNum > 0 && targetPageNum <= numPages) { + // 找到目标页面元素并滚动到该位置 + const pageElement = document.getElementById(`page-${targetPageNum}`); + if (pageElement) { + pageElement.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + } else { + // 页码超出范围,显示错误信息或重置输入 + toastService.warning(`请输入有效页码 (1-${numPages})`); + setPageInputValue(''); } - } else { - // 页码超出范围,显示错误信息或重置输入 - toastService.warning(`请输入有效页码 (1-${numPages})`); - setPageInputValue(''); } }; @@ -285,8 +328,18 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage // 滚动到顶部 const handleScrollToTop = () => { - if (contentRef.current) { - contentRef.current.scrollTo({ top: 0, behavior: 'smooth' }); + if (isDocx) { + // DOCX 文件:调用 Collabora UNO 命令 + if (!collaboraViewerRef.current?.isReady) { + toastService.warning('文档尚未加载完成,请稍候...'); + return; + } + collaboraViewerRef.current?.unoCommands.scrollToTop(); + } else { + // PDF 文件:滚动容器到顶部 + if (contentRef.current) { + contentRef.current.scrollTo({ top: 0, behavior: 'smooth' }); + } } }; @@ -385,8 +438,6 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage // 渲染文档内容 const renderDocumentContent = () => { - const real_path = fileContent.path || fileContent.template_contract_path || ''; - // 如果路径无效,显示错误信息 if (!real_path) { if(!fileContent.template_contract_path){ @@ -404,9 +455,7 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage } // console.log('real_path',real_path); - // 获取文件扩展名 - const fileExtension = real_path.split('.').pop()?.toLowerCase(); - + // PDF内容渲染 const renderPdfContent = () => (
From 272c3e8dce5aa45d4ab8352d2e317d92cc7b460e Mon Sep 17 00:00:00 2001 From: PingChuan <1259732256@qq.com> Date: Tue, 25 Nov 2025 10:56:47 +0800 Subject: [PATCH 02/13] =?UTF-8?q?feat=EF=BC=9A=E5=AE=8C=E6=88=90Collabora?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E9=9B=86=E6=88=90=EF=BC=88=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E9=A1=B6=E9=83=A8=E3=80=81=E6=96=87=E6=A1=A3=E9=A1=B5=E6=95=B0?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/collabora/CollaboraViewer.tsx | 17 +- app/components/collabora/Uno.ts | 195 +------------------ app/components/collabora/hooks.ts | 2 +- app/components/collabora/lib/README.md | 111 +++++++++++ app/components/collabora/lib/document.ts | 15 ++ app/components/collabora/lib/highlight.ts | 64 ++++++ app/components/collabora/lib/index.ts | 34 ++++ app/components/collabora/lib/navigation.ts | 62 ++++++ app/components/collabora/lib/pageInfo.ts | 152 +++++++++++++++ app/components/collabora/lib/replace.ts | 29 +++ app/components/collabora/lib/search.ts | 27 +++ app/components/collabora/lib/zoom.ts | 37 ++++ app/components/collabora/types.ts | 2 + app/components/reviews/FilePreview.tsx | 44 +++++ 14 files changed, 583 insertions(+), 208 deletions(-) create mode 100644 app/components/collabora/lib/README.md create mode 100644 app/components/collabora/lib/document.ts create mode 100644 app/components/collabora/lib/highlight.ts create mode 100644 app/components/collabora/lib/index.ts create mode 100644 app/components/collabora/lib/navigation.ts create mode 100644 app/components/collabora/lib/pageInfo.ts create mode 100644 app/components/collabora/lib/replace.ts create mode 100644 app/components/collabora/lib/search.ts create mode 100644 app/components/collabora/lib/zoom.ts diff --git a/app/components/collabora/CollaboraViewer.tsx b/app/components/collabora/CollaboraViewer.tsx index c181edc..a899e7f 100644 --- a/app/components/collabora/CollaboraViewer.tsx +++ b/app/components/collabora/CollaboraViewer.tsx @@ -51,6 +51,7 @@ export const CollaboraViewer = forwardRef iframeRef.current?.contentWindow || null, }), [unoCommands, isDocumentLoaded, mode]); // 5. 将 sendUnoCommand 挂载到 window 对象,供调试面板和控制台使用 @@ -121,24 +122,12 @@ export const CollaboraViewer = forwardRef {/* UNO 命令测试面板 */} -
+ {/*
{unoResult && {unoResult}} -
+
*/} {/* 文档加载提示 */} {!isDocumentLoaded && ( diff --git a/app/components/collabora/Uno.ts b/app/components/collabora/Uno.ts index f67a551..545834f 100644 --- a/app/components/collabora/Uno.ts +++ b/app/components/collabora/Uno.ts @@ -1,7 +1,7 @@ /** - * Collabora Online UNO 命令工具函数 + * Collabora Online UNO 命令核心工具 * - * 职责: 封装 Collabora iframe 的 UNO 命令调用 + * 职责: 提供基础的 UNO 命令发送和状态监听功能 * * @encoding UTF-8 */ @@ -29,136 +29,6 @@ export function sendUnoCommand( iframeWindow.postMessage(JSON.stringify(message), '*'); } -/** - * 搜索文本 - * @param iframeWindow - iframe 的 contentWindow - * @param text - 要搜索的文本 - */ -export function unoSearchText(iframeWindow: Window, text: string): void { - sendUnoCommand(iframeWindow, '.uno:ExecuteSearch', { - 'SearchItem.SearchString': { type: 'string', value: text }, - 'SearchItem.Command': { type: 'long', value: 1 }, // 1 = Search Next (搜索下一个) - 'SearchItem.Backward': { type: 'boolean', value: false }, - 'SearchItem.Pattern': { type: 'boolean', value: false }, - 'SearchItem.Content': { type: 'boolean', value: false }, - 'SearchItem.AsianOptions': { type: 'boolean', value: false }, - 'SearchItem.AlgorithmType': { type: 'short', value: 0 }, // 普通搜索 - 'SearchItem.SearchFlags': { type: 'long', value: 0 }, - 'SearchItem.Start': { type: 'boolean', value: true }, // 从头开始搜索 - 'SearchItem.Quiet': { type: 'boolean', value: true }, // 静默模式 - }); -} - -/** - * 替换文本 - * @param iframeWindow - iframe 的 contentWindow - * @param searchText - 要搜索的文本 - * @param replaceText - 替换后的文本 - */ -export function unoReplaceText( - iframeWindow: Window, - searchText: string, - replaceText: string -): void { - sendUnoCommand(iframeWindow, '.uno:ExecuteSearch', { - 'SearchItem.SearchString': { type: 'string', value: searchText }, - 'SearchItem.ReplaceString': { type: 'string', value: replaceText }, - 'SearchItem.Command': { type: 'long', value: 3 }, // 3 = ReplaceAll - 'SearchItem.AlgorithmType': { type: 'short', value: 0 }, - 'SearchItem.SearchFlags': { type: 'long', value: 0 }, - 'SearchItem.Backward': { type: 'boolean', value: false }, - 'Quiet': { type: 'boolean', value: true }, - }); -} - -/** - * 高亮文本 - * @param iframeWindow - iframe 的 contentWindow - * @param text - 要高亮的文本 - * @param color - 高亮颜色,默认 16776960 = 黄色 - */ -export function unoHighlightText( - iframeWindow: Window, - text: string, - color: number = 16776960 -): void { - // 1. 查找所有 - sendUnoCommand(iframeWindow, '.uno:ExecuteSearch', { - 'SearchItem.SearchString': { type: 'string', value: text }, - 'SearchItem.Command': { type: 'long', value: 1 }, // 1 = FindAll - 'SearchItem.SearchFlags': { type: 'long', value: 0 }, - 'SearchItem.AlgorithmType': { type: 'short', value: 0 }, - 'SearchItem.Backward': { type: 'boolean', value: false }, - 'Quiet': { type: 'boolean', value: true }, - }); - - // 2. 设置背景色 - sendUnoCommand(iframeWindow, '.uno:BackColor', { - BackColor: { type: 'long', value: color }, - }); -} - -/** - * 移除高亮 - * @param iframeWindow - iframe 的 contentWindow - * @param text - 要移除高亮的文本 - */ -export function unoRemoveHighlight(iframeWindow: Window, text: string): void { - // 1. 查找所有 - sendUnoCommand(iframeWindow, '.uno:ExecuteSearch', { - 'SearchItem.SearchString': { type: 'string', value: text }, - 'SearchItem.Command': { type: 'long', value: 1 }, // 1 = FindAll - 'SearchItem.SearchFlags': { type: 'long', value: 0 }, - 'SearchItem.AlgorithmType': { type: 'short', value: 0 }, - 'SearchItem.Backward': { type: 'boolean', value: false }, - 'Quiet': { type: 'boolean', value: true }, - }); - - // 2. 移除背景色 -1 = 无色 - sendUnoCommand(iframeWindow, '.uno:BackColor', { - BackColor: { type: 'long', value: -1 }, - }); -} - -/** - * 取消 - Escape - * @param iframeWindow - iframe 的 contentWindow - */ -export function unoEscape(iframeWindow: Window): void { - sendUnoCommand(iframeWindow, '.uno:Escape', {}); -} - -/** - * 滚动到文档开头 (带焦点请求) - * @param iframeWindow - iframe 的 contentWindow - */ -export async function unoScrollToTop(iframeWindow: Window): Promise { - // 1. 先请求 iframe 获取焦点 - const focusMessage = { - MessageId: 'custompostMessage', - Values: { - Command: 'REQUEST_FOCUS', - Args: {}, - }, - }; - console.log('[custompostMessage] 请求焦点 (滚动到顶部)'); - iframeWindow.postMessage(JSON.stringify(focusMessage), '*'); - - // 2. 等待焦点激活 - await new Promise((resolve) => setTimeout(resolve, 100)); - - // 3. 发送滚动命令 - sendUnoCommand(iframeWindow, '.uno:GoToStartOfDoc', {}); -} - -/** - * 保存文档 - * @param iframeWindow - iframe 的 contentWindow - */ -export function unoSave(iframeWindow: Window): void { - sendUnoCommand(iframeWindow, '.uno:Save'); -} - /** * 获取文档状态 (用于检测命令队列完成) * @param iframeWindow - iframe 的 contentWindow @@ -180,64 +50,3 @@ export function unoGetState(iframeWindow: Window): void { console.log('[UNO] 发送 Get_State (.uno:ModifiedStatus) - 等待命令队列执行完成'); iframeWindow.postMessage(JSON.stringify(message), '*'); } - -/** - * 放大文档(固定步长) - * @param iframeWindow - iframe 的 contentWindow - */ -export function unoZoomPlus(iframeWindow: Window): void { - sendUnoCommand(iframeWindow, '.uno:ZoomPlus', {}); -} - -/** - * 缩小文档(固定步长) - * @param iframeWindow - iframe 的 contentWindow - */ -export function unoZoomMinus(iframeWindow: Window): void { - sendUnoCommand(iframeWindow, '.uno:ZoomMinus', {}); -} - -/** - * 设置文档缩放比例 - * @param iframeWindow - iframe 的 contentWindow - * @param percentage - 缩放百分比(例如:100 表示 100%) - */ -export function unoSetZoom(iframeWindow: Window, percentage: number): void { - sendUnoCommand(iframeWindow, '.uno:Zoom', { - Zoom: { - type: 'short', - value: percentage, - }, - }); -} - -/** - * 跳转到指定页面 - * @param iframeWindow - iframe 的 contentWindow - * @param pageNumber - 页码(从1开始) - */ -export function unoGotoPage(iframeWindow: Window, pageNumber: number): void { - sendUnoCommand(iframeWindow, '.uno:GotoPage', { - Page: { - type: 'long', - value: pageNumber, - }, - }); -} - -/** - * 跳转到第一页 - * @param iframeWindow - iframe 的 contentWindow - */ -export function unoFirstPage(iframeWindow: Window): void { - sendUnoCommand(iframeWindow, '.uno:FirstPage', {}); -} - -/** - * 跳转到最后一页 - * @param iframeWindow - iframe 的 contentWindow - */ -export function unoLastPage(iframeWindow: Window): void { - sendUnoCommand(iframeWindow, '.uno:LastPage', {}); -} - diff --git a/app/components/collabora/hooks.ts b/app/components/collabora/hooks.ts index d7ef109..79bc2a5 100644 --- a/app/components/collabora/hooks.ts +++ b/app/components/collabora/hooks.ts @@ -27,7 +27,7 @@ import { unoGotoPage, unoFirstPage, unoLastPage, -} from './Uno'; +} from './lib'; import { COLLABORA_URL } from '~/config/api-config'; // ==================== 1. 配置加载 ==================== diff --git a/app/components/collabora/lib/README.md b/app/components/collabora/lib/README.md new file mode 100644 index 0000000..3ee9816 --- /dev/null +++ b/app/components/collabora/lib/README.md @@ -0,0 +1,111 @@ +# Collabora 功能模块说明 + +本目录包含按功能拆分的 Collabora UNO 命令封装模块。 + +## 文件结构 + +``` +lib/ +├── README.md # 本说明文档 +├── index.ts # 统一导出所有功能模块 +├── search.ts # 搜索功能 +├── replace.ts # 替换功能 +├── highlight.ts # 高亮功能 +├── navigation.ts # 导航/跳转功能 +├── zoom.ts # 缩放功能 +└── document.ts # 文档操作 +``` + +## 功能模块 + +### 1. search.ts - 搜索功能 +- `unoSearchText(iframeWindow, text)` - 搜索文本 + +### 2. replace.ts - 替换功能 +- `unoReplaceText(iframeWindow, searchText, replaceText)` - 替换文本 + +### 3. highlight.ts - 高亮功能 +- `unoHighlightText(iframeWindow, text, color)` - 高亮文本 +- `unoRemoveHighlight(iframeWindow, text)` - 移除高亮 +- `unoEscape(iframeWindow)` - 取消(Escape) + +### 4. navigation.ts - 导航/跳转功能 +- `unoScrollToTop(iframeWindow)` - 滚动到文档开头(带焦点请求) +- `unoGotoPage(iframeWindow, pageNumber)` - 跳转到指定页面 +- `unoFirstPage(iframeWindow)` - 跳转到第一页 +- `unoLastPage(iframeWindow)` - 跳转到最后一页 + +### 5. zoom.ts - 缩放功能 +- `unoZoomPlus(iframeWindow)` - 放大文档 +- `unoZoomMinus(iframeWindow)` - 缩小文档 +- `unoSetZoom(iframeWindow, percentage)` - 设置缩放比例 + +### 6. document.ts - 文档操作 +- `unoSave(iframeWindow)` - 保存文档 + +### 7. pageInfo.ts - 页数信息获取 +- `listenPageNumberChanged(iframeWindow, callback)` - 监听文档页数变化事件 +- `requestPageInfo(iframeWindow)` - 请求页数信息(返回 Promise) +- `getPageInfoFromCollabora()` - 从 Collabora 内部直接获取页数(仅 iframe 内部可用) +- `PageInfo` 接口 - 页数信息类型定义 + +## 使用方式 + +### 方式 1: 从统一入口导入(推荐) + +```typescript +import { + unoSearchText, + unoReplaceText, + unoHighlightText, + unoScrollToTop, + unoSave, +} from '~/components/collabora/lib'; +``` + +### 方式 2: 从具体模块导入 + +```typescript +import { unoSearchText } from '~/components/collabora/lib/search'; +import { unoScrollToTop } from '~/components/collabora/lib/navigation'; +``` + +## 核心工具函数 + +核心的命令发送和状态监听函数位于 `../Uno.ts`: + +- `sendUnoCommand(iframeWindow, command, args)` - 发送 UNO 命令 +- `unoGetState(iframeWindow)` - 获取文档状态(用于检测命令队列完成) + +## 设计原则 + +1. **单一职责**: 每个文件只负责一个功能领域 +2. **清晰命名**: 文件名直接反映功能(search, replace, highlight 等) +3. **统一接口**: 所有函数第一个参数都是 `iframeWindow: Window` +4. **依赖注入**: 通过 import `sendUnoCommand` 而不是重复实现 +5. **便于维护**: 功能独立,修改某个模块不影响其他模块 + +## 扩展指南 + +如果需要添加新功能模块: + +1. 在 `lib/` 下创建新文件,如 `lib/print.ts` +2. 实现功能函数,import `sendUnoCommand` from `../Uno` +3. 在 `lib/index.ts` 中添加导出 +4. 在本 README 中补充说明 + +示例: + +```typescript +// lib/print.ts +import { sendUnoCommand } from '../Uno'; + +export function unoPrint(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:Print', {}); +} +``` + +```typescript +// lib/index.ts +export { unoPrint } from './print'; +``` diff --git a/app/components/collabora/lib/document.ts b/app/components/collabora/lib/document.ts new file mode 100644 index 0000000..540062f --- /dev/null +++ b/app/components/collabora/lib/document.ts @@ -0,0 +1,15 @@ +/** + * Collabora 文档操作功能模块 + * + * @encoding UTF-8 + */ + +import { sendUnoCommand } from '../Uno'; + +/** + * 保存文档 + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoSave(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:Save'); +} diff --git a/app/components/collabora/lib/highlight.ts b/app/components/collabora/lib/highlight.ts new file mode 100644 index 0000000..6ec1ca4 --- /dev/null +++ b/app/components/collabora/lib/highlight.ts @@ -0,0 +1,64 @@ +/** + * Collabora 高亮功能模块 + * + * @encoding UTF-8 + */ + +import { sendUnoCommand } from '../Uno'; + +/** + * 高亮文本 + * @param iframeWindow - iframe 的 contentWindow + * @param text - 要高亮的文本 + * @param color - 高亮颜色,默认 16776960 = 黄色 + */ +export function unoHighlightText( + iframeWindow: Window, + text: string, + color: number = 16776960 +): void { + // 1. 查找所有 + sendUnoCommand(iframeWindow, '.uno:ExecuteSearch', { + 'SearchItem.SearchString': { type: 'string', value: text }, + 'SearchItem.Command': { type: 'long', value: 1 }, // 1 = FindAll + 'SearchItem.SearchFlags': { type: 'long', value: 0 }, + 'SearchItem.AlgorithmType': { type: 'short', value: 0 }, + 'SearchItem.Backward': { type: 'boolean', value: false }, + 'Quiet': { type: 'boolean', value: true }, + }); + + // 2. 设置背景色 + sendUnoCommand(iframeWindow, '.uno:BackColor', { + BackColor: { type: 'long', value: color }, + }); +} + +/** + * 移除高亮 + * @param iframeWindow - iframe 的 contentWindow + * @param text - 要移除高亮的文本 + */ +export function unoRemoveHighlight(iframeWindow: Window, text: string): void { + // 1. 查找所有 + sendUnoCommand(iframeWindow, '.uno:ExecuteSearch', { + 'SearchItem.SearchString': { type: 'string', value: text }, + 'SearchItem.Command': { type: 'long', value: 1 }, // 1 = FindAll + 'SearchItem.SearchFlags': { type: 'long', value: 0 }, + 'SearchItem.AlgorithmType': { type: 'short', value: 0 }, + 'SearchItem.Backward': { type: 'boolean', value: false }, + 'Quiet': { type: 'boolean', value: true }, + }); + + // 2. 移除背景色 -1 = 无色 + sendUnoCommand(iframeWindow, '.uno:BackColor', { + BackColor: { type: 'long', value: -1 }, + }); +} + +/** + * 取消 - Escape + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoEscape(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:Escape', {}); +} diff --git a/app/components/collabora/lib/index.ts b/app/components/collabora/lib/index.ts new file mode 100644 index 0000000..32f1394 --- /dev/null +++ b/app/components/collabora/lib/index.ts @@ -0,0 +1,34 @@ +/** + * Collabora 功能模块统一导出 + * + * @encoding UTF-8 + */ + +// 搜索功能 +export { unoSearchText } from './search'; + +// 替换功能 +export { unoReplaceText } from './replace'; + +// 高亮功能 +export { unoHighlightText, unoRemoveHighlight, unoEscape } from './highlight'; + +// 导航/跳转功能 +export { + unoScrollToTop, + unoGotoPage, + unoFirstPage, + unoLastPage, +} from './navigation'; + +// 缩放功能 +export { unoZoomPlus, unoZoomMinus, unoSetZoom } from './zoom'; + +// 文档操作 +export { unoSave } from './document'; + +// 页数信息 +export { + requestPageInfo, + type PageInfo, +} from './pageInfo'; diff --git a/app/components/collabora/lib/navigation.ts b/app/components/collabora/lib/navigation.ts new file mode 100644 index 0000000..e592227 --- /dev/null +++ b/app/components/collabora/lib/navigation.ts @@ -0,0 +1,62 @@ +/** + * Collabora 导航/跳转功能模块 + * + * @encoding UTF-8 + */ + +import { sendUnoCommand } from '../Uno'; + +/** + * 滚动到文档开头 (带焦点请求) + * @param iframeWindow - iframe 的 contentWindow + */ +export async function unoScrollToTop(iframeWindow: Window): Promise { + // 1. 先请求 iframe 获取焦点 + const focusMessage = { + MessageId: 'custompostMessage', + Values: { + Command: 'REQUEST_FOCUS', + Args: {}, + }, + }; + console.log('[custompostMessage] 请求焦点 (滚动到顶部)'); + iframeWindow.postMessage(JSON.stringify(focusMessage), '*'); + + // 2. 等待焦点激活 + await new Promise((resolve) => setTimeout(resolve, 100)); + + // 3. 发送滚动命令,要发三次,有时候卡在表格里面就是需要多发几次 + sendUnoCommand(iframeWindow, '.uno:GoToStartOfDoc', {}); + sendUnoCommand(iframeWindow, '.uno:GoToStartOfDoc', {}); + sendUnoCommand(iframeWindow, '.uno:GoToStartOfDoc', {}); +} + +/** + * 跳转到指定页面 + * @param iframeWindow - iframe 的 contentWindow + * @param pageNumber - 页码(从1开始) + */ +export function unoGotoPage(iframeWindow: Window, pageNumber: number): void { + sendUnoCommand(iframeWindow, '.uno:GotoPage', { + Page: { + type: 'long', + value: pageNumber, + }, + }); +} + +/** + * 跳转到第一页 + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoFirstPage(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:FirstPage', {}); +} + +/** + * 跳转到最后一页 + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoLastPage(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:LastPage', {}); +} diff --git a/app/components/collabora/lib/pageInfo.ts b/app/components/collabora/lib/pageInfo.ts new file mode 100644 index 0000000..e6f3b3b --- /dev/null +++ b/app/components/collabora/lib/pageInfo.ts @@ -0,0 +1,152 @@ +/** + * Collabora 页数信息获取模块 + * + * @encoding UTF-8 + */ + +/** + * 页数信息接口 + */ +export interface PageInfo { + totalPages: number; + currentPage: number; + timestamp: number; +} + +/** + * Collabora PostMessage 数据类型 + */ +interface CollaboraMessageData { + MessageId?: string; + msgId?: string; + // bundle.js _postMessage 发送的格式 + Values?: { + Command?: string; + Status?: string; + totalPages?: number; + currentPage?: number; + timestamp?: number; + pages?: number; + currentPage?: number; + [key: string]: unknown; + }; + // 原始插件返回的格式 + args?: { + Command?: string; + Status?: string; + totalPages?: number; + currentPage?: number; + timestamp?: number; + [key: string]: unknown; + }; + [key: string]: unknown; +} + +/** + * Collabora 全局对象类型 + */ +interface CollaboraApp { + map?: { + _docLayer?: { + _pages?: number; + _currentPage?: number; + [key: string]: unknown; + }; + [key: string]: unknown; + }; + [key: string]: unknown; +} + +/** + * 扩展 Window 类型以包含 Collabora app + */ +interface CollaboraWindow extends Window { + app?: CollaboraApp; +} + +/** + * 解析 PostMessage 数据 + */ +function parseMessageData(data: unknown): CollaboraMessageData { + if (typeof data === 'string') { + return JSON.parse(data) as CollaboraMessageData; + } + return data as CollaboraMessageData; +} + + +/** + * 通过 PostMessage 请求页数信息 + * + * 使用自定义 custompostMessage 插件获取文档页数。 + * 注意: Collabora 的页码是从 0 开始的。 + * + * @param iframeWindow - iframe 的 contentWindow + * @returns Promise,解析为页数信息 + * + * @example + * ```typescript + * const info = await requestPageInfo(iframeWindow); + * console.log(`文档共 ${info.totalPages} 页,当前在第 ${info.currentPage + 1} 页`); + * ``` + */ +export async function requestPageInfo(iframeWindow: Window): Promise { + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + cleanup(); + reject(new Error('请求页数信息超时')); + }, 5000); + + const handleMessage = (event: MessageEvent) => { + try { + if (event.source !== iframeWindow) { + return; + } + + const data = parseMessageData(event.data); + + // bundle.js 的 _postMessage 会将消息转换为: + // { MessageId: 'custompostMessage_Resp', Values: { Command: 'GET_PAGE_INFO', ... } } + // 所以我们需要监听 MessageId 而不是 msgId + if ( + data.MessageId === 'custompostMessage_Resp' && + data.Values?.Command === 'GET_PAGE_INFO' && + data.Values?.Status === 'success' + ) { + clearTimeout(timeout); + cleanup(); + + const info: PageInfo = { + totalPages: data.Values.totalPages || 0, + currentPage: data.Values.currentPage || 0, + timestamp: data.Values.timestamp || Date.now(), + }; + + resolve(info); + } + } catch (error) { + clearTimeout(timeout); + cleanup(); + reject(error); + } + }; + + const cleanup = () => { + window.removeEventListener('message', handleMessage); + }; + + window.addEventListener('message', handleMessage); + + // 发送请求消息 + const message = { + MessageId: 'custompostMessage', + Values: { + Command: 'GET_PAGE_INFO', + Args: {}, + }, + }; + + iframeWindow.postMessage(JSON.stringify(message), '*'); + }); +} + diff --git a/app/components/collabora/lib/replace.ts b/app/components/collabora/lib/replace.ts new file mode 100644 index 0000000..e548c16 --- /dev/null +++ b/app/components/collabora/lib/replace.ts @@ -0,0 +1,29 @@ +/** + * Collabora 替换功能模块 + * + * @encoding UTF-8 + */ + +import { sendUnoCommand } from '../Uno'; + +/** + * 替换文本 + * @param iframeWindow - iframe 的 contentWindow + * @param searchText - 要搜索的文本 + * @param replaceText - 替换后的文本 + */ +export function unoReplaceText( + iframeWindow: Window, + searchText: string, + replaceText: string +): void { + sendUnoCommand(iframeWindow, '.uno:ExecuteSearch', { + 'SearchItem.SearchString': { type: 'string', value: searchText }, + 'SearchItem.ReplaceString': { type: 'string', value: replaceText }, + 'SearchItem.Command': { type: 'long', value: 3 }, // 3 = ReplaceAll + 'SearchItem.AlgorithmType': { type: 'short', value: 0 }, + 'SearchItem.SearchFlags': { type: 'long', value: 0 }, + 'SearchItem.Backward': { type: 'boolean', value: false }, + 'Quiet': { type: 'boolean', value: true }, + }); +} diff --git a/app/components/collabora/lib/search.ts b/app/components/collabora/lib/search.ts new file mode 100644 index 0000000..3448c38 --- /dev/null +++ b/app/components/collabora/lib/search.ts @@ -0,0 +1,27 @@ +/** + * Collabora 搜索功能模块 + * + * @encoding UTF-8 + */ + +import { sendUnoCommand } from '../Uno'; + +/** + * 搜索文本 + * @param iframeWindow - iframe 的 contentWindow + * @param text - 要搜索的文本 + */ +export function unoSearchText(iframeWindow: Window, text: string): void { + sendUnoCommand(iframeWindow, '.uno:ExecuteSearch', { + 'SearchItem.SearchString': { type: 'string', value: text }, + 'SearchItem.Command': { type: 'long', value: 1 }, // 1 = Search Next (搜索下一个) + 'SearchItem.Backward': { type: 'boolean', value: false }, + 'SearchItem.Pattern': { type: 'boolean', value: false }, + 'SearchItem.Content': { type: 'boolean', value: false }, + 'SearchItem.AsianOptions': { type: 'boolean', value: false }, + 'SearchItem.AlgorithmType': { type: 'short', value: 0 }, // 普通搜索 + 'SearchItem.SearchFlags': { type: 'long', value: 0 }, + 'SearchItem.Start': { type: 'boolean', value: true }, // 从头开始搜索 + 'SearchItem.Quiet': { type: 'boolean', value: true }, // 静默模式 + }); +} diff --git a/app/components/collabora/lib/zoom.ts b/app/components/collabora/lib/zoom.ts new file mode 100644 index 0000000..35c41bb --- /dev/null +++ b/app/components/collabora/lib/zoom.ts @@ -0,0 +1,37 @@ +/** + * Collabora 缩放功能模块 + * + * @encoding UTF-8 + */ + +import { sendUnoCommand } from '../Uno'; + +/** + * 放大文档(固定步长) + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoZoomPlus(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:ZoomPlus', {}); +} + +/** + * 缩小文档(固定步长) + * @param iframeWindow - iframe 的 contentWindow + */ +export function unoZoomMinus(iframeWindow: Window): void { + sendUnoCommand(iframeWindow, '.uno:ZoomMinus', {}); +} + +/** + * 设置文档缩放比例 + * @param iframeWindow - iframe 的 contentWindow + * @param percentage - 缩放百分比(例如:100 表示 100%) + */ +export function unoSetZoom(iframeWindow: Window, percentage: number): void { + sendUnoCommand(iframeWindow, '.uno:Zoom', { + Zoom: { + type: 'short', + value: percentage, + }, + }); +} diff --git a/app/components/collabora/types.ts b/app/components/collabora/types.ts index 72e920c..275c09e 100644 --- a/app/components/collabora/types.ts +++ b/app/components/collabora/types.ts @@ -61,4 +61,6 @@ export interface CollaboraViewerHandle { isReady: boolean; /** 当前模式 */ mode: 'view' | 'edit'; + /** 获取 iframe 的 contentWindow (用于发送 PostMessage) */ + getIframeWindow: () => Window | null; } diff --git a/app/components/reviews/FilePreview.tsx b/app/components/reviews/FilePreview.tsx index 352c3ea..a0ec862 100644 --- a/app/components/reviews/FilePreview.tsx +++ b/app/components/reviews/FilePreview.tsx @@ -6,6 +6,7 @@ import { useState, useEffect, useRef, ChangeEvent } from 'react'; import { Document, Page, pdfjs } from 'react-pdf'; import { DOCUMENT_URL } from '~/api/axios-client'; import { CollaboraViewer, type CollaboraViewerHandle } from '~/components/collabora/CollaboraViewer'; +import { requestPageInfo } from '~/components/collabora/lib/pageInfo'; // 设置worker路径为public目录下的worker文件 // 使用已经下载的兼容版本 (pdfjs-dist v2.12.313) @@ -96,6 +97,49 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage const isDocx = fileExtension === 'docx'; const isPdf = fileExtension === 'pdf'; + // DOCX 页数获取: 使用 requestPageInfo 方法 + useEffect(() => { + if (!isDocx) return; + + // console.log('[FilePreview] DOCX 文档加载,尝试获取页数'); + + let intervalCleared = false; + + // 等待 CollaboraViewer 准备就绪 + const checkInterval = setInterval(() => { + if (intervalCleared) return; + + if (!collaboraViewerRef.current?.isReady) { + console.log('[FilePreview] 等待 Collabora 就绪...'); + return; + } + + // console.log('[FilePreview] Collabora 已就绪,尝试获取页数'); + clearInterval(checkInterval); + intervalCleared = true; + + const iframeWindow = collaboraViewerRef.current.getIframeWindow?.(); + if (!iframeWindow) { + console.warn('[FilePreview] 无法获取 iframe window'); + return; + } + + // 使用 requestPageInfo 获取页数 + requestPageInfo(iframeWindow) + .then((info) => { + setNumPages(info.totalPages); + }) + .catch((error) => { + console.warn('[FilePreview] 获取 DOCX 页数失败:', error.message); + }); + }, 500); + + // 清理定时器 + return () => { + clearInterval(checkInterval); + }; + }, [isDocx]); + // 拖拽状态管理 const [dragMode, setDragMode] = useState(false); // 是否处于拖拽模式 const [isDragging, setIsDragging] = useState(false); From 0ed6f0aaf401bdfd10721feffc31057674a4c352 Mon Sep 17 00:00:00 2001 From: yorn <1057707203@qq.com> Date: Tue, 25 Nov 2025 11:02:40 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=E5=A4=87=E4=BB=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/evaluation_points/reviews.ts | 32 +-- app/routes/monaco-demo.tsx | 233 +++++++++++++----- app/routes/pdf-demo.tsx | 85 +------ ...终版)智慧法务平台建设采购项目合同(1).docx | Bin 0 -> 70822 bytes ...终版)智慧法务平台建设采购项目合同(2).docx | Bin 0 -> 70822 bytes 5 files changed, 194 insertions(+), 156 deletions(-) create mode 100644 public/testWork/(最终版)智慧法务平台建设采购项目合同(1).docx create mode 100644 public/testWork/(最终版)智慧法务平台建设采购项目合同(2).docx diff --git a/app/api/evaluation_points/reviews.ts b/app/api/evaluation_points/reviews.ts index bbe9e9d..c95f1a2 100644 --- a/app/api/evaluation_points/reviews.ts +++ b/app/api/evaluation_points/reviews.ts @@ -461,22 +461,22 @@ export async function getReviewPoints(fileId: string, request: Request) { evaluatedPointResultsLog: evaluatedPointResultsLog || {} // evaluatedPointResultsLog: { // rules:[ - // { - // "id": "0", - // "type": "consistency", - // "res": true, - // "config": { - // "logic": "all", - // "pairs": [ - // { - // "sourceField": {"证据先行登记保存批准书-负责人意见并签名-时间": {page: 1,value: ''}}, - // "targetField": {"证据先行登记保存批准书-负责人意见并签名-签名": {page: 2,value: '有无判断类型'}}, - // "compareMethod": "exact", - // "res": true - // } - // ] - // } - // }, + // { + // "id": "0", + // "type": "consistency", + // "res": true, + // "config": { + // "logic": "all", + // "pairs": [ + // { + // "sourceField": {"证据先行登记保存批准书-负责人意见并签名-时间": {page: 1,value: ''}}, + // "targetField": {"证据先行登记保存批准书-负责人意见并签名-签名": {page: 2,value: '有无判断类型'}}, + // "compareMethod": "exact", + // "res": true + // } + // ] + // } + // }, // { // "id": "1", // "type": "consistency", diff --git a/app/routes/monaco-demo.tsx b/app/routes/monaco-demo.tsx index 3dc6ea8..b3228cc 100644 --- a/app/routes/monaco-demo.tsx +++ b/app/routes/monaco-demo.tsx @@ -13,6 +13,7 @@ import { useState, useRef, useEffect } from "react"; import { DiffEditor } from "@monaco-editor/react"; import type { editor } from "monaco-editor"; import { pdfjs } from 'react-pdf'; +import mammoth from 'mammoth'; import { toastService } from '~/components/ui/Toast'; // 设置 PDF.js worker(与 pdf-demo.tsx 相同) @@ -25,14 +26,26 @@ export const meta: MetaFunction = () => { ]; }; +// 文档类型枚举 +type DocumentType = 'pdf' | 'docx' | 'unknown'; + // PDF 类型枚举 type PdfType = 'text' | 'scanned' | 'unknown'; -// PDF 信息接口 +// PDF 信息接口(内部使用) interface PdfInfo { type: PdfType; numPages: number; textLength: number; + confidence: number; +} + +// 文档信息接口 +interface DocumentInfo { + fileType: DocumentType; + pdfType?: PdfType; // 只有 PDF 才有 + numPages?: number; // PDF 页数 + textLength: number; confidence: number; // 文本提取置信度 (0-1) } @@ -120,15 +133,23 @@ export default function MonacoDemoPage() { const [diffCount, setDiffCount] = useState(0); const [currentDiff, setCurrentDiff] = useState(0); - // PDF相关状态 - const [pdf1Url, setPdf1Url] = useState(''); - const [pdf2Url, setPdf2Url] = useState(''); - const [pdf1Info, setPdf1Info] = useState(null); - const [pdf2Info, setPdf2Info] = useState(null); - const [isLoadingPdf1, setIsLoadingPdf1] = useState(false); - const [isLoadingPdf2, setIsLoadingPdf2] = useState(false); + // 文档相关状态 + const [doc1Url, setDoc1Url] = useState(''); + const [doc2Url, setDoc2Url] = useState(''); + const [doc1Info, setDoc1Info] = useState(null); + const [doc2Info, setDoc2Info] = useState(null); + const [isLoadingDoc1, setIsLoadingDoc1] = useState(false); + const [isLoadingDoc2, setIsLoadingDoc2] = useState(false); const [useExample, setUseExample] = useState(true); + // 检测文件类型(根据文件路径) + const detectFileType = (filePath: string): DocumentType => { + const lowerPath = filePath.toLowerCase(); + if (lowerPath.endsWith('.pdf')) return 'pdf'; + if (lowerPath.endsWith('.docx') || lowerPath.endsWith('.doc')) return 'docx'; + return 'unknown'; + }; + // PDF类型检测函数 const detectPdfType = async (pdfUrl: string): Promise => { const loadingTask = pdfjs.getDocument(pdfUrl); @@ -189,32 +210,81 @@ export default function MonacoDemoPage() { return fullText; }; - // 加载PDF并提取文本 - const loadPdfAndExtractText = async (pdfUrl: string, setPdfInfo: (info: PdfInfo | null) => void, setLoading: (loading: boolean) => void, setTextContent: (text: string) => void) => { + // Word文档文本提取函数 + const extractTextFromWord = async (docUrl: string): Promise => { + // 通过 fetch 获取文件 + const response = await fetch(docUrl); + if (!response.ok) { + throw new Error(`无法加载文档: ${response.statusText}`); + } + + // 获取 ArrayBuffer + const arrayBuffer = await response.arrayBuffer(); + + // 使用 mammoth 提取纯文本 + const result = await mammoth.extractRawText({ arrayBuffer }); + + return result.value; + }; + + // 加载文档并提取文本(支持 PDF 和 Word) + const loadDocumentAndExtractText = async ( + docUrl: string, + filePath: string, + setDocInfo: (info: DocumentInfo | null) => void, + setLoading: (loading: boolean) => void, + setTextContent: (text: string) => void + ) => { try { setLoading(true); - // 1. 检测PDF类型 - const pdfInfo = await detectPdfType(pdfUrl); - setPdfInfo(pdfInfo); + // 1. 检测文件类型 + const fileType = detectFileType(filePath); - // 2. 提取文本 - if (pdfInfo.type === 'text') { - const text = await extractTextFromPdf(pdfUrl); + if (fileType === 'pdf') { + // PDF 处理 + const pdfInfo = await detectPdfType(docUrl); + const text = await extractTextFromPdf(docUrl); + + const docInfo: DocumentInfo = { + fileType: 'pdf', + pdfType: pdfInfo.type, + numPages: pdfInfo.numPages, + textLength: pdfInfo.textLength, + confidence: pdfInfo.confidence + }; + + setDocInfo(docInfo); setTextContent(text); - toastService.success(`PDF加载成功!共 ${pdfInfo.numPages} 页,提取了 ${pdfInfo.textLength} 个字符`); - } else if (pdfInfo.type === 'scanned') { - toastService.warning('检测到扫描版PDF,文本提取质量可能较低'); - const text = await extractTextFromPdf(pdfUrl); + + if (pdfInfo.type === 'text') { + toastService.success(`PDF加载成功!共 ${pdfInfo.numPages} 页,提取了 ${pdfInfo.textLength} 个字符`); + } else if (pdfInfo.type === 'scanned') { + toastService.warning('检测到扫描版PDF,文本提取质量可能较低'); + } else { + toastService.error('无法识别PDF类型,可能是图片PDF'); + } + } else if (fileType === 'docx') { + // Word 处理 + const text = await extractTextFromWord(docUrl); + + const docInfo: DocumentInfo = { + fileType: 'docx', + textLength: text.length, + confidence: 1.0 // Word 文档文本提取置信度为 100% + }; + + setDocInfo(docInfo); setTextContent(text); + toastService.success(`Word文档加载成功!提取了 ${text.length} 个字符`); } else { - toastService.error('无法识别PDF类型,可能是图片PDF'); + toastService.error('不支持的文件类型'); setTextContent(''); } } catch (error) { - console.error('PDF加载失败:', error); - toastService.error('PDF加载失败,请检查文件路径'); - setPdfInfo(null); + console.error('文档加载失败:', error); + toastService.error(`文档加载失败: ${error instanceof Error ? error.message : '未知错误'}`); + setDocInfo(null); setTextContent(''); } finally { setLoading(false); @@ -281,8 +351,8 @@ export default function MonacoDemoPage() { setModifiedText(CONTRACT_B); setCurrentDiff(0); setUseExample(true); - setPdf1Info(null); - setPdf2Info(null); + setDoc1Info(null); + setDoc2Info(null); // 重新计算差异数量 setTimeout(() => { @@ -295,34 +365,50 @@ export default function MonacoDemoPage() { }, 100); }; - // 从URL参数加载PDF - const loadPdfsFromUrl = () => { + // 构建文件访问 URL + const buildFileUrl = (filePath: string): string => { + // 如果路径以 public/ 开头或者以已知的 public 子目录开头(如 testWork/) + // 则直接使用静态资源路径 + if (filePath.startsWith('public/')) { + // 去掉 public/ 前缀,直接访问静态资源 + return '/' + filePath.substring(7); + } else if (filePath.startsWith('testWork/') || filePath.startsWith('testPDF/')) { + // testWork 和 testPDF 目录在 public 下,直接作为静态资源访问 + return '/' + filePath; + } else { + // 其他路径通过 api/pdf-proxy 代理访问(从 MinIO 获取) + return `/api/pdf-proxy?path=${encodeURIComponent(filePath)}`; + } + }; + + // 从URL参数加载文档(支持 PDF 和 Word) + const loadDocumentsFromUrl = () => { if (typeof window === 'undefined') return; const searchParams = new URLSearchParams(window.location.search); - const pdf1Path = searchParams.get('pdf1'); - const pdf2Path = searchParams.get('pdf2'); + const doc1Path = searchParams.get('doc1') || searchParams.get('pdf1'); // 兼容旧参数名 + const doc2Path = searchParams.get('doc2') || searchParams.get('pdf2'); // 兼容旧参数名 - if (pdf1Path || pdf2Path) { + if (doc1Path || doc2Path) { setUseExample(false); - if (pdf1Path) { - const fullUrl = `/api/pdf-proxy?path=${encodeURIComponent(pdf1Path)}`; - setPdf1Url(fullUrl); - loadPdfAndExtractText(fullUrl, setPdf1Info, setIsLoadingPdf1, setOriginalText); + if (doc1Path) { + const fullUrl = buildFileUrl(doc1Path); + setDoc1Url(fullUrl); + loadDocumentAndExtractText(fullUrl, doc1Path, setDoc1Info, setIsLoadingDoc1, setOriginalText); } - if (pdf2Path) { - const fullUrl = `/api/pdf-proxy?path=${encodeURIComponent(pdf2Path)}`; - setPdf2Url(fullUrl); - loadPdfAndExtractText(fullUrl, setPdf2Info, setIsLoadingPdf2, setModifiedText); + if (doc2Path) { + const fullUrl = buildFileUrl(doc2Path); + setDoc2Url(fullUrl); + loadDocumentAndExtractText(fullUrl, doc2Path, setDoc2Info, setIsLoadingDoc2, setModifiedText); } } }; // 组件挂载时读取URL参数 useEffect(() => { - loadPdfsFromUrl(); + loadDocumentsFromUrl(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -452,8 +538,8 @@ export default function MonacoDemoPage() {
- {/* PDF加载信息 */} - {!useExample && (pdf1Info || pdf2Info || isLoadingPdf1 || isLoadingPdf2) && ( + {/* 文档加载信息 */} + {!useExample && (doc1Info || doc2Info || isLoadingDoc1 || isLoadingDoc2) && (
- +
- PDF文档信息: + 文档信息:
- {/* PDF 1 信息 */} + {/* 文档 1 信息 */}
📄 文档1(左侧/原始)
- {isLoadingPdf1 ? ( + {isLoadingDoc1 ? (
⏳ 加载中...
- ) : pdf1Info ? ( + ) : doc1Info ? (
类型: - {pdf1Info.type === 'text' ? '✅ 文本PDF' : pdf1Info.type === 'scanned' ? '⚠️ 扫描PDF' : '❌ 未知类型'} + {doc1Info.fileType === 'pdf' ? '📕 PDF文档' : doc1Info.fileType === 'docx' ? '📘 Word文档' : '❌ 未知类型'}
-
页数: {pdf1Info.numPages} 页
-
字符数: {pdf1Info.textLength} 个
-
置信度: {(pdf1Info.confidence * 100).toFixed(0)}%
+ {doc1Info.fileType === 'pdf' && doc1Info.numPages && ( +
页数: {doc1Info.numPages} 页
+ )} + {doc1Info.fileType === 'pdf' && doc1Info.pdfType && ( +
PDF类型: {doc1Info.pdfType === 'text' ? '✅ 文本' : doc1Info.pdfType === 'scanned' ? '⚠️ 扫描' : '❌ 未知'}
+ )} +
字符数: {doc1Info.textLength} 个
+
置信度: {(doc1Info.confidence * 100).toFixed(0)}%
) : (
未加载
)}
- {/* PDF 2 信息 */} + {/* 文档 2 信息 */}
📄 文档2(右侧/修改)
- {isLoadingPdf2 ? ( + {isLoadingDoc2 ? (
⏳ 加载中...
- ) : pdf2Info ? ( + ) : doc2Info ? (
类型: - {pdf2Info.type === 'text' ? '✅ 文本PDF' : pdf2Info.type === 'scanned' ? '⚠️ 扫描PDF' : '❌ 未知类型'} + {doc2Info.fileType === 'pdf' ? '📕 PDF文档' : doc2Info.fileType === 'docx' ? '📘 Word文档' : '❌ 未知类型'}
-
页数: {pdf2Info.numPages} 页
-
字符数: {pdf2Info.textLength} 个
-
置信度: {(pdf2Info.confidence * 100).toFixed(0)}%
+ {doc2Info.fileType === 'pdf' && doc2Info.numPages && ( +
页数: {doc2Info.numPages} 页
+ )} + {doc2Info.fileType === 'pdf' && doc2Info.pdfType && ( +
PDF类型: {doc2Info.pdfType === 'text' ? '✅ 文本' : doc2Info.pdfType === 'scanned' ? '⚠️ 扫描' : '❌ 未知'}
+ )} +
字符数: {doc2Info.textLength} 个
+
置信度: {(doc2Info.confidence * 100).toFixed(0)}%
) : (
未加载
@@ -537,7 +633,7 @@ export default function MonacoDemoPage() {
💡 使用提示:
- 您可以通过URL参数加载PDF文档进行对比: + 您可以通过URL参数加载文档进行对比(支持 PDF 和 Word): - /monaco-demo?pdf1=路径1&pdf2=路径2 + /monaco-demo?doc1=路径1&doc2=路径2
- 示例: /monaco-demo?pdf1=documents/contract_v1.pdf&pdf2=documents/contract_v2.pdf +
PDF示例: /monaco-demo?doc1=documents/contract_v1.pdf&doc2=documents/contract_v2.pdf
+
Word示例: /monaco-demo?doc1=testWork/(最终版)智慧法务平台建设采购项目合同(1).docx&doc2=testWork/(最终版)智慧法务平台建设采购项目合同(2).docx
@@ -591,8 +688,8 @@ export default function MonacoDemoPage() { }} /> - {/* PDF加载中的遮罩层 */} - {(isLoadingPdf1 || isLoadingPdf2) && ( + {/* 文档加载中的遮罩层 */} + {(isLoadingDoc1 || isLoadingDoc2) && (
- 正在加载PDF文档并提取文本... + 正在加载文档并提取文本...
- {isLoadingPdf1 &&
📄 加载文档1
} - {isLoadingPdf2 &&
📄 加载文档2
} + {isLoadingDoc1 &&
📄 加载文档1
} + {isLoadingDoc2 &&
📄 加载文档2
}
)} diff --git a/app/routes/pdf-demo.tsx b/app/routes/pdf-demo.tsx index 51a8bc8..22a9540 100644 --- a/app/routes/pdf-demo.tsx +++ b/app/routes/pdf-demo.tsx @@ -39,7 +39,7 @@ interface HighlightArea { // 基于坐标的字符数据 interface CharacterBox { - box: [number, number][]; // 4个点:左上、右上、右下、左下 + box: [number, number][]; char: string; page: number; } @@ -70,7 +70,7 @@ export default function PdfDemo() { // PDF文件URL(使用示例PDF) // const [pdfUrl] = useState('/testPDF/sample.pdf'); // 使用包含真实文本层的PDF // const [pdfUrl] = useState('/api/pdf-proxy?path=documents/mz/行政处罚决定书/2025/11月13日/第71号--未在当地烟草专卖批发企业进货_02时58分36秒/第71号--未在当地烟草专卖批发企业进货.pdf'); // 使用项目中的示例PDF - const [pdfUrl] = useState('/api/pdf-proxy?path=documents/mz/行政处罚决定书/2025/11月22日/第35号--无烟草专卖品准运证运输烟草专卖品_15时15分24秒/第35号--无烟草专卖品准运证运输烟草专卖品.pdf') + const [pdfUrl] = useState('/api/pdf-proxy?path=documents/mz/测试示范类型/2025/11月24日/第37号--涉嫌生产、销售伪劣产品罪_12时19分10秒/第37号--涉嫌生产、销售伪劣产品罪.pdf') // PDF状态 const [numPages, setNumPages] = useState(null); @@ -227,87 +227,28 @@ export default function PdfDemo() { // 获取Page容器(SVG实际渲染的坐标空间) const pageContainer = canvas?.closest('.react-pdf__Page') as HTMLElement; - if (canvas && pageContainer && pdfOriginalWidthPt) { - // Canvas 内部绘制尺寸(考虑了 devicePixelRatio) - const canvasInternalWidth = canvas.width; - const canvasInternalHeight = canvas.height; - + if (canvas && pdfOriginalWidthPt) { // Canvas 显示尺寸(浏览器中实际占用的像素) const canvasDisplayWidth = canvas.offsetWidth; const canvasDisplayHeight = canvas.offsetHeight; - // Page容器尺寸(SVG高亮渲染的实际坐标空间) - const pageContainerWidth = pageContainer.offsetWidth; - const pageContainerHeight = pageContainer.offsetHeight; + // 计算坐标缩放比例:Canvas显示尺寸 / PDF原始尺寸 + const autoScale = canvasDisplayWidth / pdfOriginalWidthPt; - // 尝试多种计算方式 - const scale1_canvasDisplay = canvasDisplayWidth / pdfOriginalWidthPt; - const scale2_canvasInternal = canvasInternalWidth / pdfOriginalWidthPt; - const scale3_pageContainer = pageContainerWidth / pdfOriginalWidthPt; - - // 尝试反向计算:如果OCR尺寸比渲染尺寸大(需要缩小) - const scale4_inverseCanvasInternal = canvasDisplayWidth / canvasInternalWidth; - const scale5_inversePage = canvasDisplayWidth / pageContainerWidth; - - // 计算如果要达到 0.83 的缩放比例,OCR原始尺寸应该是多少 - const expectedOcrWidth = canvasDisplayWidth / 0.83; - - console.log('📏 尺寸信息汇总:'); - console.log(' 1️⃣ PDF原始尺寸 (page.view):', pdfOriginalWidthPt, 'x', pdfOriginalHeightPt, 'pt'); - console.log(' 2️⃣ Page容器尺寸:', pageContainerWidth, 'x', pageContainerHeight, 'px'); - console.log(' 3️⃣ Canvas显示尺寸:', canvasDisplayWidth, 'x', canvasDisplayHeight, 'px'); - console.log(' 4️⃣ Canvas内部尺寸:', canvasInternalWidth, 'x', canvasInternalHeight, 'px'); - console.log(' 5️⃣ 用户缩放 (scale):', scale); - console.log(' 6️⃣ devicePixelRatio:', window.devicePixelRatio || 1); - console.log(''); - console.log('🎯 各种计算方式:'); - console.log(' 方案1️⃣: Canvas显示 / PDF原始 =', scale1_canvasDisplay.toFixed(3), 'x'); - console.log(' 方案2️⃣: Canvas内部 / PDF原始 =', scale2_canvasInternal.toFixed(3), 'x'); - console.log(' 方案3️⃣: Page容器 / PDF原始 =', scale3_pageContainer.toFixed(3), 'x'); - console.log(' 方案4️⃣: Canvas显示 / Canvas内部 =', scale4_inverseCanvasInternal.toFixed(3), 'x ⬅ 可能是这个!'); - console.log(' 方案5️⃣: Canvas显示 / Page容器 =', scale5_inversePage.toFixed(3), 'x'); - console.log(''); - console.log('🔍 目标值分析:'); - console.log(' - 手动校准的正确值: 0.83'); - console.log(' - 反推OCR图像尺寸:', expectedOcrWidth.toFixed(0), 'x', (canvasDisplayHeight / 0.83).toFixed(0), 'px'); - console.log(' - 比较: ', expectedOcrWidth.toFixed(0), 'vs Canvas内部', canvasInternalWidth); - - // 使用最接近0.83的方案 - let autoScale = scale1_canvasDisplay; - let scaleMethod = '方案1 (Canvas显示/PDF原始)'; - - // 检查哪个方案最接近0.83 - const diff1 = Math.abs(scale1_canvasDisplay - 0.83); - const diff2 = Math.abs(scale2_canvasInternal - 0.83); - const diff3 = Math.abs(scale3_pageContainer - 0.83); - const diff4 = Math.abs(scale4_inverseCanvasInternal - 0.83); - const diff5 = Math.abs(scale5_inversePage - 0.83); - - const minDiff = Math.min(diff1, diff2, diff3, diff4, diff5); - - if (minDiff === diff4) { - autoScale = scale4_inverseCanvasInternal; - scaleMethod = '方案4 (Canvas显示/Canvas内部)'; - } else if (minDiff === diff5) { - autoScale = scale5_inversePage; - scaleMethod = '方案5 (Canvas显示/Page容器)'; - } else if (minDiff === diff2) { - autoScale = scale2_canvasInternal; - scaleMethod = '方案2 (Canvas内部/PDF原始)'; - } else if (minDiff === diff3) { - autoScale = scale3_pageContainer; - scaleMethod = '方案3 (Page容器/PDF原始)'; - } - - console.log(''); - console.log('✅ 自动选择:', scaleMethod, '=', autoScale.toFixed(3), 'x (最接近0.83)'); + console.log('📏 PDF尺寸信息:'); + console.log(' - PDF原始尺寸 (page.view):', pdfOriginalWidthPt, 'x', pdfOriginalHeightPt, 'pt'); + console.log(' - Canvas显示尺寸 (offsetWidth):', canvasDisplayWidth, 'x', canvasDisplayHeight, 'px'); + console.log(' - 用户缩放 (scale):', scale); + console.log(' - devicePixelRatio:', window.devicePixelRatio || 1); + console.log('🎯 自动计算坐标缩放:', autoScale.toFixed(3), 'x'); + console.log(' 公式: Canvas显示宽度 / PDF原始宽度 =', canvasDisplayWidth, '/', pdfOriginalWidthPt); // 保存原始宽度和自动计算的缩放比例 setPdfOriginalWidth(pdfOriginalWidthPt); setCoordinateScale(autoScale); setIsScaleAutoCalculated(true); - toastService.success(`自动校准完成: ${autoScale.toFixed(3)}x (${scaleMethod})`); + toastService.success(`自动校准完成: ${autoScale.toFixed(3)}x`); } else { console.warn('⚠️ 无法获取Canvas元素、Page容器或原始尺寸'); console.log('调试信息:', { diff --git a/public/testWork/(最终版)智慧法务平台建设采购项目合同(1).docx b/public/testWork/(最终版)智慧法务平台建设采购项目合同(1).docx new file mode 100644 index 0000000000000000000000000000000000000000..2aa055cdfb78c6313330092f77808907f4ccf36d GIT binary patch literal 70822 zcmeEtW0NRB)8*Kgi0{05Sjskd~00t+R=(v!1ety@`_!ox6=S zK>-L5MIHdq@BRP(_dZsrmEbzEq^a;hou2+6K>hGi!isrw{qn=;j|X1}J-0#PAD zlm^_vQMCjN)fNv6$G@ofsmeBsBWV!^Nlzu{`XZIz0b*q>@vHegqn+@AKdDdpW=9Th zwLQc3?1N>%GG%=QX;Z zWy}2Uvx85LeELdm*<#2nL5HiuU!~M54&->LYPz&FFKGB;*Z0paHKoiyGMf;(gOklq zR+6tHP&aJ8+&soi1nuyv_ObeRMDZ6a?6O&##)HDKHZXg*pj(@m!i|5P2F(k(NRet_ zifY-$+PB^Li$V!OSjV%Wa03^KRM>j3fzo`1-8 zF^=|l-ps%c+32m}KTdzgz*~NDzIcnRz_We;-=!yhzWluRLsNYSV3}vKkVPpF4|YHF z2Dp!iiBzjm0M+XEd^O$M`589~YgWMK5h&XqzH?P(P)la(9#-cuvy5DO-rd)-KfgHt z`2hxy|36lMbQNFF@87WA{{=Yo?+T#jXkzU|Pxqhm|407+!*Ks^pI((HBL&R(i~PVJ z!l`bqO)8>=ZC&9r8RIWNp+6r1ned6_Ek8RHk#tMVVR%d)r{hdQE1BK6%haRH?rQxF z6aw{&J1{ksd+i?TTY-{-GjnISYW8~|nePvVUqi$awvt~6i4!P)sm??Oa19rDv?N2| zuO4JB3rWXE*9-{01aS{5XzUoiP5F5YDyqu~Y^PDnP7q#ETI@Cj9=lh$CS_x}1G>;% zL#K&`w(w2H7Ry2nM->C^-x>cRD?*5f0^_l1X50RIX)@Osi$}1;_t-flW+ZRoK8-Ai zz|UmEhs~&c$eMoQu=z(9(fU($%Jf(roD`?g3;chBOUIlyR#iR#z_T&Htp!s|*RdO;ME5ThMo0kR4pdHl=Xfc+E%v9u$cWz!4IY`hBp(hO3

=fIqu2rB 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%0Ay1T6k;mepl2bwp5n7^cBALR{Ji|WzZTkTs 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

=fIqu2rB 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%0Ay1T6k;mepl2bwp5n7^cBALR{Ji|WzZTkTs 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 Date: Tue, 25 Nov 2025 11:10:30 +0800 Subject: [PATCH 04/13] =?UTF-8?q?fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E4=BB=8Ere?= =?UTF-8?q?actdom=E5=AF=BC=E5=85=A5useNavigate=EF=BC=8C=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E4=BB=8Eremix=E5=8C=85=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/reviews/ReviewTabs.tsx | 2 +- pnpm-lock.yaml | 1091 +++++++------------------ 2 files changed, 318 insertions(+), 775 deletions(-) diff --git a/app/components/reviews/ReviewTabs.tsx b/app/components/reviews/ReviewTabs.tsx index 3d466da..3801345 100644 --- a/app/components/reviews/ReviewTabs.tsx +++ b/app/components/reviews/ReviewTabs.tsx @@ -3,7 +3,7 @@ * 提供三个选项卡:评查结果、AI智能分析、文件信息 */ import { ReactNode, useState, useRef } from 'react'; -import { useNavigate, useRevalidator } from 'react-router-dom'; +import { useNavigate, useRevalidator } from '@remix-run/react'; import { loadingBarService } from '~/components/ui/LoadingBar'; import { Modal } from '~/components/ui/Modal'; import { UploadArea, type UploadAreaRef } from '~/components/ui/UploadArea'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b98894..32b5a9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,21 +8,18 @@ importers: .: dependencies: + '@ant-design/icons': + specifier: ^5.6.1 + version: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@codemirror/lang-javascript': specifier: ^6.2.3 version: 6.2.4 '@codemirror/theme-one-dark': specifier: ^6.1.2 version: 6.1.3 - '@react-pdf-viewer/core': - specifier: ^3.12.0 - version: 3.12.0(pdfjs-dist@3.11.174)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/highlight': - specifier: ^3.12.0 - version: 3.12.0(pdfjs-dist@3.11.174)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/search': - specifier: ^3.12.0 - version: 3.12.0(pdfjs-dist@3.11.174)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@monaco-editor/react': + specifier: ^4.7.0 + version: 4.7.0(monaco-editor@0.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@remix-run/node': specifier: ^2.16.2 version: 2.16.8(typescript@5.8.3) @@ -32,6 +29,9 @@ importers: '@remix-run/serve': specifier: ^2.16.2 version: 2.16.8(typescript@5.8.3) + '@types/jsonwebtoken': + specifier: ^9.0.10 + version: 9.0.10 '@uiw/react-codemirror': specifier: ^4.23.10 version: 4.23.14(@babel/runtime@7.27.6)(@codemirror/autocomplete@6.18.6)(@codemirror/language@6.11.2)(@codemirror/lint@6.8.5)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/theme-one-dark@6.1.3)(@codemirror/view@6.38.0)(codemirror@6.0.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -68,6 +68,9 @@ importers: isbot: specifier: ^4.1.0 version: 4.4.0 + jsonwebtoken: + specifier: ^9.0.2 + version: 9.0.2 jszip: specifier: ^3.10.1 version: 3.10.1 @@ -77,12 +80,12 @@ importers: mammoth: specifier: ^1.9.0 version: 1.9.1 + monaco-editor: + specifier: ^0.55.1 + version: 0.55.1 pdf-lib: specifier: ^1.17.1 version: 1.17.1 - pdfjs-dist: - specifier: ^3.11.174 - version: 3.11.174 pg: specifier: ^8.14.1 version: 8.16.3 @@ -102,8 +105,8 @@ importers: specifier: ^10.1.0 version: 10.1.0(@types/react@18.3.23)(react@18.3.1) react-pdf: - specifier: ^5.7.2 - version: 5.7.2(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.9(esbuild@0.25.5)) + specifier: ^9.2.1 + version: 9.2.1(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rehype-katex: specifier: ^7.0.1 version: 7.0.1 @@ -137,7 +140,7 @@ importers: version: 18.3.7(@types/react@18.3.23) '@types/react-pdf': specifier: ^7.0.0 - version: 7.0.0(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.9(esbuild@0.25.5)) + version: 7.0.0(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@typescript-eslint/eslint-plugin': specifier: ^6.7.4 version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3) @@ -147,6 +150,9 @@ importers: autoprefixer: specifier: ^10.4.21 version: 10.4.21(postcss@8.5.6) + cross-env: + specifier: ^7.0.3 + version: 7.0.3 esbuild: specifier: ^0.25.1 version: 0.25.5 @@ -894,16 +900,22 @@ packages: '@lezer/lr@1.4.2': resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==} - '@mapbox/node-pre-gyp@1.0.11': - resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} - hasBin: true - '@marijn/find-cluster-break@1.0.2': resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} '@mdx-js/mdx@2.3.0': resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} + '@monaco-editor/loader@1.7.0': + resolution: {integrity: sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA==} + + '@monaco-editor/react@4.7.0': + resolution: {integrity: sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==} + peerDependencies: + monaco-editor: '>= 0.25.0 < 1' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@napi-rs/wasm-runtime@0.2.11': resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==} @@ -1018,25 +1030,6 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' - '@react-pdf-viewer/core@3.12.0': - resolution: {integrity: sha512-8MsdlQJ4jaw3GT+zpCHS33nwnvzpY0ED6DEahZg9WngG++A5RMhk8LSlxdHelwaFFHFiXBjmOaj2Kpxh50VQRg==} - peerDependencies: - pdfjs-dist: ^2.16.105 || ^3.0.279 - react: '>=16.8.0' - react-dom: '>=16.8.0' - - '@react-pdf-viewer/highlight@3.12.0': - resolution: {integrity: sha512-UxdnvnvTjikugOUEj/RIeJm3Lm93aVu+Xr0jMa7d+wrZlHh5b7wTd+FeI6gNk9wdJDrB70oHiCzn6MTbepkc5g==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - - '@react-pdf-viewer/search@3.12.0': - resolution: {integrity: sha512-jAkLpis49fsDDY/HrbUZIOIhzF5vynONQNA4INQKI38r/MjveblrkNv7qbr9j5lQ/WFic5+gD1e+Mtpf1/7DiA==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - '@remix-run/dev@2.16.8': resolution: {integrity: sha512-2EKByaD5CDwh7H56UFVCqc90kCZ9LukPlSwkcsR3gj7WlfL7sXtcIqIopcToAlKAeao3HDbhBlBT2CTOivxZCg==} engines: {node: '>=18.0.0'} @@ -1155,67 +1148,56 @@ packages: resolution: {integrity: sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.44.1': resolution: {integrity: sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.44.1': resolution: {integrity: sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.44.1': resolution: {integrity: sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loongarch64-gnu@4.44.1': resolution: {integrity: sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-powerpc64le-gnu@4.44.1': resolution: {integrity: sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.44.1': resolution: {integrity: sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.44.1': resolution: {integrity: sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.44.1': resolution: {integrity: sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.44.1': resolution: {integrity: sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.44.1': resolution: {integrity: sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.44.1': resolution: {integrity: sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==} @@ -1250,12 +1232,6 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - '@types/eslint-scope@3.7.7': - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - - '@types/eslint@9.6.1': - resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} - '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} @@ -1274,6 +1250,9 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/jsonwebtoken@9.0.10': + resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==} + '@types/katex@0.16.7': resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} @@ -1310,6 +1289,9 @@ packages: '@types/semver@7.7.0': resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -1438,49 +1420,41 @@ packages: resolution: {integrity: sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA==} cpu: [arm64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-arm64-musl@1.9.2': resolution: {integrity: sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA==} cpu: [arm64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-ppc64-gnu@1.9.2': resolution: {integrity: sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw==} cpu: [ppc64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-gnu@1.9.2': resolution: {integrity: sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ==} cpu: [riscv64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-riscv64-musl@1.9.2': resolution: {integrity: sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg==} cpu: [riscv64] os: [linux] - libc: [musl] '@unrs/resolver-binding-linux-s390x-gnu@1.9.2': resolution: {integrity: sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ==} cpu: [s390x] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-gnu@1.9.2': resolution: {integrity: sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w==} cpu: [x64] os: [linux] - libc: [glibc] '@unrs/resolver-binding-linux-x64-musl@1.9.2': resolution: {integrity: sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw==} cpu: [x64] os: [linux] - libc: [musl] '@unrs/resolver-binding-wasm32-wasi@1.9.2': resolution: {integrity: sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ==} @@ -1517,67 +1491,13 @@ packages: '@web3-storage/multipart-parser@1.0.0': resolution: {integrity: sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==} - '@webassemblyjs/ast@1.14.1': - resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} - - '@webassemblyjs/floating-point-hex-parser@1.13.2': - resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} - - '@webassemblyjs/helper-api-error@1.13.2': - resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} - - '@webassemblyjs/helper-buffer@1.14.1': - resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} - - '@webassemblyjs/helper-numbers@1.13.2': - resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} - - '@webassemblyjs/helper-wasm-bytecode@1.13.2': - resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} - - '@webassemblyjs/helper-wasm-section@1.14.1': - resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} - - '@webassemblyjs/ieee754@1.13.2': - resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} - - '@webassemblyjs/leb128@1.13.2': - resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} - - '@webassemblyjs/utf8@1.13.2': - resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} - - '@webassemblyjs/wasm-edit@1.14.1': - resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} - - '@webassemblyjs/wasm-gen@1.14.1': - resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} - - '@webassemblyjs/wasm-opt@1.14.1': - resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} - - '@webassemblyjs/wasm-parser@1.14.1': - resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} - - '@webassemblyjs/wast-printer@1.14.1': - resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} - '@xmldom/xmldom@0.8.10': resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} engines: {node: '>=10.0.0'} - '@xtuc/ieee754@1.2.0': - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - - '@xtuc/long@4.2.2': - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - '@zxing/text-encoding@0.9.0': resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==} - abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -1596,10 +1516,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} @@ -1615,30 +1531,9 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv-keywords@3.5.2: - resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} - peerDependencies: - ajv: ^6.9.1 - - ajv-keywords@5.1.0: - resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} - peerDependencies: - ajv: ^8.8.2 - ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - amp-message@0.1.2: resolution: {integrity: sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==} @@ -1682,14 +1577,6 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - - are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - deprecated: This package is no longer supported. - arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -1805,9 +1692,6 @@ packages: resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} engines: {node: '>=10.0.0'} - big.js@5.2.2: - resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -1848,6 +1732,9 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -1889,9 +1776,9 @@ packages: caniuse-lite@1.0.30001726: resolution: {integrity: sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==} - canvas@2.11.2: - resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} - engines: {node: '>=6'} + canvas@3.2.0: + resolution: {integrity: sha512-jk0GxrLtUEmW/TmFsk2WghvgHe8B0pxGilqCL21y8lHkPUGa6FTsnCNtHPOzT8O3y+N+m3espawV80bbBlgfTA==} + engines: {node: ^18.12.0 || >= 20.9.0} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1930,10 +1817,6 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - chrome-trace-event@1.0.4: - resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} - engines: {node: '>=6.0'} - classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} @@ -1957,6 +1840,10 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + codemirror@6.0.2: resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==} @@ -1967,10 +1854,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -2012,9 +1895,6 @@ packages: confbox@0.2.2: resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} - console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} @@ -2053,6 +1933,11 @@ packages: croner@4.1.97: resolution: {integrity: sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==} + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -2138,9 +2023,9 @@ packages: decode-named-character-reference@1.2.0: resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==} - decompress-response@4.2.1: - resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} - engines: {node: '>=8'} + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} dedent@1.6.0: resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} @@ -2150,6 +2035,10 @@ packages: babel-plugin-macros: optional: true + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -2179,9 +2068,6 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -2233,6 +2119,9 @@ packages: docx-preview@0.3.5: resolution: {integrity: sha512-nod1jG5PkvzDIiZAcgAY4gSFQzgmAAChcuZH4Hj9dj7oCzscY3Hn8NfbUv7X7Jk4xL1lfKO113JLDhWKOt6fYw==} + dompurify@3.2.7: + resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} + dotenv@16.6.1: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} @@ -2250,6 +2139,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -2262,10 +2154,6 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - emojis-list@3.0.0: - resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} - engines: {node: '>= 4'} - encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -2277,10 +2165,6 @@ packages: end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - enhanced-resolve@5.18.2: - resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==} - engines: {node: '>=10.13.0'} - enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} engines: {node: '>=8.6'} @@ -2433,10 +2317,6 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2468,10 +2348,6 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -2526,10 +2402,6 @@ packages: eventemitter2@6.4.9: resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==} - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -2538,6 +2410,10 @@ packages: resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} engines: {node: '>=6'} + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + express@4.21.2: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} @@ -2567,9 +2443,6 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-uri@3.0.6: - resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} - fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -2591,12 +2464,6 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} - file-loader@6.2.0: - resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -2685,11 +2552,6 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - deprecated: This package is no longer supported. - generic-names@4.0.0: resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} @@ -2735,6 +2597,9 @@ packages: git-sha1@0.1.2: resolution: {integrity: sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==} + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -2743,9 +2608,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true @@ -2810,9 +2672,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -2875,10 +2734,6 @@ packages: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} @@ -3141,10 +2996,6 @@ packages: javascript-stringify@2.1.0: resolution: {integrity: sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==} - jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - jiti@1.21.7: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true @@ -3174,9 +3025,6 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-parse-even-better-errors@3.0.2: resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -3184,9 +3032,6 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -3208,6 +3053,10 @@ packages: jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -3218,6 +3067,12 @@ packages: jszip@3.10.1: resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + jwa@1.4.2: + resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} + + jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + katex@0.16.22: resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==} hasBin: true @@ -3250,14 +3105,6 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} - engines: {node: '>=6.11.5'} - - loader-utils@2.0.4: - resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} - engines: {node: '>=8.9.0'} - loader-utils@3.3.1: resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} engines: {node: '>= 12.13.0'} @@ -3306,15 +3153,33 @@ packages: lodash.escape@3.2.0: resolution: {integrity: sha512-n1PZMXgaaDWZDSvuNZ/8XOcYO2hOKDqZel5adtR30VKQAtoWs/5AOeFA0vPV8moiPzlqe7F4cP2tzpFewQyelQ==} + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} lodash.isarray@3.0.4: resolution: {integrity: sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==} + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + lodash.isplainobject@3.2.0: resolution: {integrity: sha512-P4wZnho5curNqeEq/x292Pb57e1v+woR7DJ84DURelKB46lby8aDEGVobSaYtzHdQBWQrJSdxcCwjlGOvvdIyg==} + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + lodash.istypedarray@3.0.6: resolution: {integrity: sha512-lGWJ6N8AA3KSv+ZZxlTdn4f6A7kMfpJboeyvbFdE7IU9YAgweODqmOgdUHOA+c6lVWeVLysdaxciFXi+foVsWw==} @@ -3330,6 +3195,9 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + lodash.restparam@3.6.1: resolution: {integrity: sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==} @@ -3370,10 +3238,6 @@ packages: make-cancellable-promise@1.3.2: resolution: {integrity: sha512-GCXh3bq/WuMbS+Ky4JBPW1hYTOU+znU+Q5m9Pu+pI8EoUqIHk9+tviOKC6/qhHh8C4/As3tzJ69IF32kdz85ww==} - make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - make-event-props@1.6.2: resolution: {integrity: sha512-iDwf7mA03WPiR8QxvcVHmVWEPfMY1RZXerDVNCRYW7dUr2ppH3J58Rwb39/WG39yTZdRSxr3x+2v22tvI0VEvA==} @@ -3389,6 +3253,11 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + marked@14.0.0: + resolution: {integrity: sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==} + engines: {node: '>= 18'} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -3484,9 +3353,6 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - merge-class-names@1.4.2: - resolution: {integrity: sha512-bOl98VzwCGi25Gcn3xKxnR5p/WrhWFQB59MS/aGENcmUc6iSm96yrFDF0XSNurX9qN4LbJm0R9kfvsQ17i8zCw==} - merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} @@ -3708,9 +3574,9 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - mimic-response@2.1.0: - resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} - engines: {node: '>=8'} + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -3771,6 +3637,9 @@ packages: module-details-from-path@1.0.4: resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + monaco-editor@0.55.1: + resolution: {integrity: sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==} + morgan@1.10.0: resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} engines: {node: '>= 0.8.0'} @@ -3795,14 +3664,14 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nan@2.22.2: - resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} - nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + napi-build-utils@2.0.0: + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} + napi-postinstall@0.2.5: resolution: {integrity: sha512-kmsgUvCRIJohHjbZ3V8avP0I1Pekw329MVAMDzVxsrkjgdnqiwvMX5XwR+hWV66vsAtZ+iM+fVnq8RTQawUmCQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -3824,30 +3693,20 @@ packages: resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} engines: {node: '>= 0.6'} - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - netmask@2.0.2: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true + node-abi@3.85.0: + resolution: {integrity: sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==} + engines: {node: '>=10'} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - normalize-package-data@5.0.0: resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -3880,10 +3739,6 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - deprecated: This package is no longer supported. - object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -4030,9 +3885,9 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - path2d-polyfill@2.0.1: - resolution: {integrity: sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==} - engines: {node: '>=8'} + path2d@0.2.2: + resolution: {integrity: sha512-+vnG6S4dYcYxZd+CZxzXCNKdELYZSKfohrk98yajCo1PtRoDgCTrrwOvK1GT0UoAdVszagDVllQc0U1vaX4NUQ==} + engines: {node: '>=6'} pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -4043,16 +3898,8 @@ packages: pdf-lib@1.17.1: resolution: {integrity: sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==} - pdfjs-dist@2.12.313: - resolution: {integrity: sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA==} - peerDependencies: - worker-loader: ^3.0.8 - peerDependenciesMeta: - worker-loader: - optional: true - - pdfjs-dist@3.11.174: - resolution: {integrity: sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==} + pdfjs-dist@4.8.69: + resolution: {integrity: sha512-IHZsA4T7YElCKNNXtiLgqScw4zPd3pG9do8UrznC757gMd7UPeHSL2qwNNMJo4r79fl8oj1Xx+1nh2YkzdMpLQ==} engines: {node: '>=18'} peek-stream@1.1.3: @@ -4256,6 +4103,11 @@ packages: resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} engines: {node: '>=0.10.0'} + prebuild-install@7.1.3: + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} + engines: {node: '>=10'} + hasBin: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4338,9 +4190,6 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -4577,6 +4426,10 @@ packages: react: '>=16.9.0' react-dom: '>=16.9.0' + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: @@ -4597,11 +4450,15 @@ packages: '@types/react': '>=18' react: '>=18' - react-pdf@5.7.2: - resolution: {integrity: sha512-hdDwvf007V0i2rPCqQVS1fa70CXut17SN3laJYlRHzuqcu8sLLjEoeXihty6c0Ev5g1mw31b8OT8EwRw1s8C4g==} + react-pdf@9.2.1: + resolution: {integrity: sha512-AJt0lAIkItWEZRA5d/mO+Om4nPCuTiQ0saA+qItO967DTjmGjnhmF+Bi2tL286mOTfBlF5CyLzJ35KTMaDoH+A==} peerDependencies: - react: ^16.3.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.3.0 || ^17.0.0 || ^18.0.0 + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} @@ -4690,10 +4547,6 @@ packages: remixicon@4.6.0: resolution: {integrity: sha512-bKM5odjqE1yzVxEZGJE7F79WHhNrJFIKHXR+GG+P1IWXn8AnJZhl8SbIRDJsNAvIqx4VPkNwjuHfc42tutMDpQ==} - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - require-in-the-middle@5.2.0: resolution: {integrity: sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==} engines: {node: '>=6'} @@ -4783,14 +4636,6 @@ packages: scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - schema-utils@3.3.0: - resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} - engines: {node: '>= 10.13.0'} - - schema-utils@4.3.2: - resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==} - engines: {node: '>= 10.13.0'} - screenfull@5.2.0: resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} engines: {node: '>=0.10.0'} @@ -4816,16 +4661,10 @@ packages: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} - serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - serve-static@1.16.2: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-cookie-parser@2.7.1: resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} @@ -4884,8 +4723,8 @@ packages: simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - simple-get@3.1.1: - resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -4953,6 +4792,9 @@ packages: stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + state-local@1.0.7: + resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -5029,6 +4871,10 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -5057,10 +4903,6 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -5076,10 +4918,6 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - tapable@2.2.2: - resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==} - engines: {node: '>=6'} - tar-fs@2.1.3: resolution: {integrity: sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==} @@ -5091,22 +4929,6 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - terser-webpack-plugin@5.3.14: - resolution: {integrity: sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - terser@5.43.1: resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==} engines: {node: '>=10'} @@ -5132,9 +4954,6 @@ packages: tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - tiny-warning@1.0.3: - resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} - tinyglobby@0.2.14: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} @@ -5153,9 +4972,6 @@ packages: toml@3.0.0: resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -5197,6 +5013,9 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + turbo-stream@2.4.1: resolution: {integrity: sha512-v8kOJXpG3WoTN/+at8vK7erSzo6nW6CIaeOvNOkHQVDajfz1ZVeSxCbc6tOH4hrGZW7VUCV0TOXd8CPzYnYkrw==} @@ -5485,9 +5304,8 @@ packages: w3c-keyname@2.2.8: resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} - watchpack@2.4.4: - resolution: {integrity: sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==} - engines: {node: '>=10.13.0'} + warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -5502,26 +5320,6 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - webpack-sources@3.3.3: - resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} - engines: {node: '>=10.13.0'} - - webpack@5.99.9: - resolution: {integrity: sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -5548,9 +5346,6 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true - wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -6203,6 +5998,7 @@ snapshots: dependencies: '@jridgewell/gen-mapping': 0.3.11 '@jridgewell/trace-mapping': 0.3.28 + optional: true '@jridgewell/sourcemap-codec@1.5.3': {} @@ -6229,22 +6025,6 @@ snapshots: dependencies: '@lezer/common': 1.2.3 - '@mapbox/node-pre-gyp@1.0.11': - dependencies: - detect-libc: 2.0.4 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.7.2 - tar: 6.2.1 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - '@marijn/find-cluster-break@1.0.2': {} '@mdx-js/mdx@2.3.0': @@ -6269,6 +6049,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@monaco-editor/loader@1.7.0': + dependencies: + state-local: 1.0.7 + + '@monaco-editor/react@4.7.0(monaco-editor@0.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@monaco-editor/loader': 1.7.0 + monaco-editor: 0.55.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + '@napi-rs/wasm-runtime@0.2.11': dependencies: '@emnapi/core': 1.4.3 @@ -6453,28 +6244,6 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@react-pdf-viewer/core@3.12.0(pdfjs-dist@3.11.174)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - pdfjs-dist: 3.11.174 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@react-pdf-viewer/highlight@3.12.0(pdfjs-dist@3.11.174)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@3.11.174)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - - '@react-pdf-viewer/search@3.12.0(pdfjs-dist@3.11.174)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@3.11.174)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@remix-run/dev@2.16.8(@remix-run/react@2.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.8(typescript@5.8.3))(@types/node@24.0.8)(jiti@1.21.7)(terser@5.43.1)(typescript@5.8.3)(vite@6.3.5(@types/node@24.0.8)(jiti@1.21.7)(terser@5.43.1)(yaml@2.8.0))(yaml@2.8.0)': dependencies: '@babel/core': 7.27.7 @@ -6723,16 +6492,6 @@ snapshots: dependencies: '@types/ms': 2.1.0 - '@types/eslint-scope@3.7.7': - dependencies: - '@types/eslint': 9.6.1 - '@types/estree': 1.0.8 - - '@types/eslint@9.6.1': - dependencies: - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 - '@types/estree-jsx@1.0.5': dependencies: '@types/estree': 1.0.8 @@ -6751,6 +6510,11 @@ snapshots: '@types/json5@0.0.29': {} + '@types/jsonwebtoken@9.0.10': + dependencies: + '@types/ms': 2.1.0 + '@types/node': 24.0.8 + '@types/katex@0.16.7': {} '@types/mdast@3.0.15': @@ -6775,15 +6539,13 @@ snapshots: dependencies: '@types/react': 18.3.23 - '@types/react-pdf@7.0.0(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.9(esbuild@0.25.5))': + '@types/react-pdf@7.0.0(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - react-pdf: 5.7.2(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.9(esbuild@0.25.5)) + react-pdf: 9.2.1(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) transitivePeerDependencies: - '@types/react' - react - react-dom - - webpack - - worker-loader '@types/react@18.3.23': dependencies: @@ -6792,6 +6554,9 @@ snapshots: '@types/semver@7.7.0': {} + '@types/trusted-types@2.0.7': + optional: true + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -7024,94 +6789,11 @@ snapshots: '@web3-storage/multipart-parser@1.0.0': {} - '@webassemblyjs/ast@1.14.1': - dependencies: - '@webassemblyjs/helper-numbers': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - - '@webassemblyjs/floating-point-hex-parser@1.13.2': {} - - '@webassemblyjs/helper-api-error@1.13.2': {} - - '@webassemblyjs/helper-buffer@1.14.1': {} - - '@webassemblyjs/helper-numbers@1.13.2': - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.13.2 - '@webassemblyjs/helper-api-error': 1.13.2 - '@xtuc/long': 4.2.2 - - '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} - - '@webassemblyjs/helper-wasm-section@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/wasm-gen': 1.14.1 - - '@webassemblyjs/ieee754@1.13.2': - dependencies: - '@xtuc/ieee754': 1.2.0 - - '@webassemblyjs/leb128@1.13.2': - dependencies: - '@xtuc/long': 4.2.2 - - '@webassemblyjs/utf8@1.13.2': {} - - '@webassemblyjs/wasm-edit@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/helper-wasm-section': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-opt': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - '@webassemblyjs/wast-printer': 1.14.1 - - '@webassemblyjs/wasm-gen@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 - - '@webassemblyjs/wasm-opt@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - - '@webassemblyjs/wasm-parser@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-api-error': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 - - '@webassemblyjs/wast-printer@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@xtuc/long': 4.2.2 - '@xmldom/xmldom@0.8.10': {} - '@xtuc/ieee754@1.2.0': {} - - '@xtuc/long@4.2.2': {} - '@zxing/text-encoding@0.9.0': optional: true - abbrev@1.1.1: - optional: true - abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 @@ -7127,13 +6809,6 @@ snapshots: acorn@8.15.0: {} - agent-base@6.0.2: - dependencies: - debug: 4.4.1 - transitivePeerDependencies: - - supports-color - optional: true - agent-base@7.1.3: {} aggregate-error@3.1.0: @@ -7155,19 +6830,6 @@ snapshots: screenfull: 5.2.0 tslib: 2.8.1 - ajv-formats@2.1.1(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - - ajv-keywords@3.5.2(ajv@6.12.6): - dependencies: - ajv: 6.12.6 - - ajv-keywords@5.1.0(ajv@8.17.1): - dependencies: - ajv: 8.17.1 - fast-deep-equal: 3.1.3 - ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -7175,13 +6837,6 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.0.6 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - amp-message@0.1.2: dependencies: amp: 0.3.1 @@ -7267,15 +6922,6 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 - aproba@2.0.0: - optional: true - - are-we-there-yet@2.0.0: - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - optional: true - arg@5.0.2: {} argparse@1.0.10: @@ -7413,8 +7059,6 @@ snapshots: basic-ftp@5.0.5: {} - big.js@5.2.2: {} - binary-extensions@2.3.0: {} bl@4.1.0: @@ -7470,6 +7114,8 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.25.1) + buffer-equal-constant-time@1.0.1: {} + buffer-from@1.1.2: {} buffer@5.7.1: @@ -7519,14 +7165,10 @@ snapshots: caniuse-lite@1.0.30001726: {} - canvas@2.11.2: + canvas@3.2.0: dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - nan: 2.22.2 - simple-get: 3.1.1 - transitivePeerDependencies: - - encoding - - supports-color + node-addon-api: 7.1.1 + prebuild-install: 7.1.3 optional: true ccount@2.0.1: {} @@ -7567,8 +7209,6 @@ snapshots: chownr@2.0.0: {} - chrome-trace-event@1.0.4: {} - classnames@2.5.1: {} clean-stack@2.2.0: {} @@ -7585,6 +7225,8 @@ snapshots: clone@1.0.4: {} + clsx@2.1.1: {} + codemirror@6.0.2: dependencies: '@codemirror/autocomplete': 6.18.6 @@ -7601,9 +7243,6 @@ snapshots: color-name@1.1.4: {} - color-support@1.1.3: - optional: true - combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -7612,7 +7251,8 @@ snapshots: commander@2.15.1: {} - commander@2.20.3: {} + commander@2.20.3: + optional: true commander@4.1.1: {} @@ -7642,9 +7282,6 @@ snapshots: confbox@0.2.2: {} - console-control-strings@1.1.0: - optional: true - content-disposition@0.5.4: dependencies: safe-buffer: 5.2.1 @@ -7671,6 +7308,10 @@ snapshots: croner@4.1.97: {} + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.6 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -7733,13 +7374,16 @@ snapshots: dependencies: character-entities: 2.0.2 - decompress-response@4.2.1: + decompress-response@6.0.0: dependencies: - mimic-response: 2.1.0 + mimic-response: 3.1.0 optional: true dedent@1.6.0: {} + deep-extend@0.6.0: + optional: true + deep-is@0.1.4: {} deep-object-diff@1.1.9: {} @@ -7770,9 +7414,6 @@ snapshots: delayed-stream@1.0.0: {} - delegates@1.0.0: - optional: true - depd@2.0.0: {} dequal@2.0.3: {} @@ -7812,6 +7453,10 @@ snapshots: dependencies: jszip: 3.10.1 + dompurify@3.2.7: + optionalDependencies: + '@types/trusted-types': 2.0.7 + dotenv@16.6.1: {} duck@0.1.12: @@ -7833,6 +7478,10 @@ snapshots: eastasianwidth@0.2.0: {} + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + ee-first@1.1.1: {} electron-to-chromium@1.5.178: {} @@ -7841,8 +7490,6 @@ snapshots: emoji-regex@9.2.2: {} - emojis-list@3.0.0: {} - encodeurl@1.0.2: {} encodeurl@2.0.0: {} @@ -7851,11 +7498,6 @@ snapshots: dependencies: once: 1.4.0 - enhanced-resolve@5.18.2: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.2 - enquirer@2.3.6: dependencies: ansi-colors: 4.1.3 @@ -8177,11 +7819,6 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 - eslint-scope@5.1.1: - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 @@ -8248,8 +7885,6 @@ snapshots: dependencies: estraverse: 5.3.0 - estraverse@4.3.0: {} - estraverse@5.3.0: {} estree-util-attach-comments@2.1.1: @@ -8302,8 +7937,6 @@ snapshots: eventemitter2@6.4.9: {} - events@3.3.0: {} - execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -8318,6 +7951,9 @@ snapshots: exit-hook@2.2.1: {} + expand-template@2.0.3: + optional: true + express@4.21.2: dependencies: accepts: 1.3.8 @@ -8380,8 +8016,6 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-uri@3.0.6: {} - fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -8400,12 +8034,6 @@ snapshots: dependencies: flat-cache: 3.2.0 - file-loader@6.2.0(webpack@5.99.9(esbuild@0.25.5)): - dependencies: - loader-utils: 2.0.4 - schema-utils: 3.3.0 - webpack: 5.99.9(esbuild@0.25.5) - fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -8498,19 +8126,6 @@ snapshots: functions-have-names@1.2.3: {} - gauge@3.0.2: - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - optional: true - generic-names@4.0.0: dependencies: loader-utils: 3.3.1 @@ -8563,6 +8178,9 @@ snapshots: git-sha1@0.1.2: {} + github-from-package@0.0.0: + optional: true + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -8571,8 +8189,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob-to-regexp@0.4.1: {} - glob@10.4.5: dependencies: foreground-child: 3.3.1 @@ -8646,9 +8262,6 @@ snapshots: dependencies: has-symbols: 1.1.0 - has-unicode@2.0.1: - optional: true - hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -8784,14 +8397,6 @@ snapshots: transitivePeerDependencies: - supports-color - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.4.1 - transitivePeerDependencies: - - supports-color - optional: true - https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 @@ -9034,12 +8639,6 @@ snapshots: javascript-stringify@2.1.0: {} - jest-worker@27.5.1: - dependencies: - '@types/node': 24.0.8 - merge-stream: 2.0.0 - supports-color: 8.1.1 - jiti@1.21.7: {} js-cookie@3.0.5: {} @@ -9063,14 +8662,10 @@ snapshots: json-buffer@3.0.1: {} - json-parse-even-better-errors@2.3.1: {} - json-parse-even-better-errors@3.0.2: {} json-schema-traverse@0.4.1: {} - json-schema-traverse@1.0.0: {} - json-stable-stringify-without-jsonify@1.0.1: {} json-stringify-safe@5.0.1: @@ -9092,6 +8687,19 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jsonwebtoken@9.0.2: + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.7.2 + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.9 @@ -9110,6 +8718,17 @@ snapshots: readable-stream: 2.3.8 setimmediate: 1.0.5 + jwa@1.4.2: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@3.2.2: + dependencies: + jwa: 1.4.2 + safe-buffer: 5.2.1 + katex@0.16.22: dependencies: commander: 8.3.0 @@ -9139,14 +8758,6 @@ snapshots: lines-and-columns@1.2.4: {} - loader-runner@4.3.0: {} - - loader-utils@2.0.4: - dependencies: - big.js: 5.2.2 - emojis-list: 3.0.0 - json5: 2.2.3 - loader-utils@3.3.1: {} local-pkg@1.1.1: @@ -9189,16 +8800,28 @@ snapshots: dependencies: lodash._root: 3.0.1 + lodash.includes@4.3.0: {} + lodash.isarguments@3.1.0: {} lodash.isarray@3.0.4: {} + lodash.isboolean@3.0.3: {} + + lodash.isinteger@4.0.4: {} + + lodash.isnumber@3.0.3: {} + lodash.isplainobject@3.2.0: dependencies: lodash._basefor: 3.0.3 lodash.isarguments: 3.1.0 lodash.keysin: 3.0.8 + lodash.isplainobject@4.0.6: {} + + lodash.isstring@4.0.1: {} + lodash.istypedarray@3.0.6: {} lodash.keys@3.1.2: @@ -9228,6 +8851,8 @@ snapshots: lodash.merge@4.6.2: {} + lodash.once@4.1.1: {} + lodash.restparam@3.6.1: {} lodash.toplainobject@3.0.0: @@ -9268,11 +8893,6 @@ snapshots: make-cancellable-promise@1.3.2: {} - make-dir@3.1.0: - dependencies: - semver: 6.3.1 - optional: true - make-event-props@1.6.2: {} mammoth@1.9.1: @@ -9292,6 +8912,8 @@ snapshots: markdown-table@3.0.4: {} + marked@14.0.0: {} + math-intrinsics@1.1.0: {} mdast-util-definitions@5.1.2: @@ -9577,8 +9199,6 @@ snapshots: media-typer@0.3.0: {} - merge-class-names@1.4.2: {} - merge-descriptors@1.0.3: {} merge-refs@1.3.0(@types/react@18.3.23): @@ -10022,7 +9642,7 @@ snapshots: mimic-fn@2.1.0: {} - mimic-response@2.1.0: + mimic-response@3.1.0: optional: true minimatch@3.1.2: @@ -10079,6 +9699,11 @@ snapshots: module-details-from-path@1.0.4: {} + monaco-editor@0.55.1: + dependencies: + dompurify: 3.2.7 + marked: 14.0.0 + morgan@1.10.0: dependencies: basic-auth: 2.0.1 @@ -10105,11 +9730,11 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nan@2.22.2: - optional: true - nanoid@3.3.11: {} + napi-build-utils@2.0.0: + optional: true + napi-postinstall@0.2.5: {} natural-compare@1.4.0: {} @@ -10126,22 +9751,18 @@ snapshots: negotiator@0.6.4: {} - neo-async@2.6.2: {} - netmask@2.0.2: {} - node-fetch@2.7.0: + node-abi@3.85.0: dependencies: - whatwg-url: 5.0.0 + semver: 7.7.2 + optional: true + + node-addon-api@7.1.1: optional: true node-releases@2.0.19: {} - nopt@5.0.0: - dependencies: - abbrev: 1.1.1 - optional: true - normalize-package-data@5.0.0: dependencies: hosted-git-info: 6.1.3 @@ -10177,14 +9798,6 @@ snapshots: dependencies: path-key: 3.1.1 - npmlog@5.0.1: - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - optional: true - object-assign@4.1.1: {} object-hash@3.0.0: {} @@ -10353,7 +9966,7 @@ snapshots: path-type@4.0.0: {} - path2d-polyfill@2.0.1: + path2d@0.2.2: optional: true pathe@1.1.2: {} @@ -10367,15 +9980,10 @@ snapshots: pako: 1.0.11 tslib: 1.14.1 - pdfjs-dist@2.12.313: {} - - pdfjs-dist@3.11.174: + pdfjs-dist@4.8.69: optionalDependencies: - canvas: 2.11.2 - path2d-polyfill: 2.0.1 - transitivePeerDependencies: - - encoding - - supports-color + canvas: 3.2.0 + path2d: 0.2.2 peek-stream@1.1.3: dependencies: @@ -10621,6 +10229,22 @@ snapshots: dependencies: xtend: 4.0.2 + prebuild-install@7.1.3: + dependencies: + detect-libc: 2.0.4 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 2.0.0 + node-abi: 3.85.0 + pump: 3.0.3 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.3 + tunnel-agent: 0.6.0 + optional: true + prelude-ls@1.2.1: {} prettier@2.8.8: {} @@ -10702,10 +10326,6 @@ snapshots: queue-microtask@1.2.3: {} - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - range-parser@1.2.1: {} raw-body@2.5.2: @@ -11034,6 +10654,14 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + optional: true + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 @@ -11064,24 +10692,20 @@ snapshots: transitivePeerDependencies: - supports-color - react-pdf@5.7.2(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.99.9(esbuild@0.25.5)): + react-pdf@9.2.1(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.6 - file-loader: 6.2.0(webpack@5.99.9(esbuild@0.25.5)) + clsx: 2.1.1 + dequal: 2.0.3 make-cancellable-promise: 1.3.2 make-event-props: 1.6.2 - merge-class-names: 1.4.2 merge-refs: 1.3.0(@types/react@18.3.23) - pdfjs-dist: 2.12.313 - prop-types: 15.8.1 + pdfjs-dist: 4.8.69 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tiny-invariant: 1.3.3 - tiny-warning: 1.0.3 - transitivePeerDependencies: - - '@types/react' - - webpack - - worker-loader + warning: 4.0.3 + optionalDependencies: + '@types/react': 18.3.23 react-refresh@0.14.2: {} @@ -11246,8 +10870,6 @@ snapshots: remixicon@4.6.0: {} - require-from-string@2.0.2: {} - require-in-the-middle@5.2.0: dependencies: debug: 4.4.1 @@ -11358,19 +10980,6 @@ snapshots: dependencies: loose-envify: 1.4.0 - schema-utils@3.3.0: - dependencies: - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - - schema-utils@4.3.2: - dependencies: - '@types/json-schema': 7.0.15 - ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) - ajv-keywords: 5.1.0(ajv@8.17.1) - screenfull@5.2.0: {} scroll-into-view-if-needed@3.1.0: @@ -11403,10 +11012,6 @@ snapshots: transitivePeerDependencies: - supports-color - serialize-javascript@6.0.2: - dependencies: - randombytes: 2.1.0 - serve-static@1.16.2: dependencies: encodeurl: 2.0.0 @@ -11416,9 +11021,6 @@ snapshots: transitivePeerDependencies: - supports-color - set-blocking@2.0.0: - optional: true - set-cookie-parser@2.7.1: {} set-function-length@1.2.2: @@ -11490,9 +11092,9 @@ snapshots: simple-concat@1.0.1: optional: true - simple-get@3.1.1: + simple-get@4.0.1: dependencies: - decompress-response: 4.2.1 + decompress-response: 6.0.0 once: 1.4.0 simple-concat: 1.0.1 optional: true @@ -11555,6 +11157,8 @@ snapshots: stable-hash@0.0.5: {} + state-local@1.0.7: {} + statuses@2.0.1: {} stop-iteration-iterator@1.1.0: @@ -11657,6 +11261,9 @@ snapshots: strip-final-newline@2.0.0: {} + strip-json-comments@2.0.1: + optional: true + strip-json-comments@3.1.1: {} style-mod@4.1.2: {} @@ -11689,10 +11296,6 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - supports-preserve-symlinks-flag@1.0.0: {} systeminformation@5.27.7: @@ -11725,8 +11328,6 @@ snapshots: transitivePeerDependencies: - ts-node - tapable@2.2.2: {} - tar-fs@2.1.3: dependencies: chownr: 1.1.4 @@ -11751,23 +11352,13 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 - terser-webpack-plugin@5.3.14(esbuild@0.25.5)(webpack@5.99.9(esbuild@0.25.5)): - dependencies: - '@jridgewell/trace-mapping': 0.3.28 - jest-worker: 27.5.1 - schema-utils: 4.3.2 - serialize-javascript: 6.0.2 - terser: 5.43.1 - webpack: 5.99.9(esbuild@0.25.5) - optionalDependencies: - esbuild: 0.25.5 - terser@5.43.1: dependencies: '@jridgewell/source-map': 0.3.9 acorn: 8.15.0 commander: 2.20.3 source-map-support: 0.5.21 + optional: true text-table@0.2.0: {} @@ -11788,8 +11379,6 @@ snapshots: tiny-invariant@1.3.3: {} - tiny-warning@1.0.3: {} - tinyglobby@0.2.14: dependencies: fdir: 6.4.6(picomatch@4.0.2) @@ -11805,9 +11394,6 @@ snapshots: toml@3.0.0: {} - tr46@0.0.3: - optional: true - trim-lines@3.0.1: {} trough@2.2.0: {} @@ -11841,6 +11427,11 @@ snapshots: tslib@2.8.1: {} + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + optional: true + turbo-stream@2.4.1: {} tv4@1.3.0: {} @@ -12189,10 +11780,9 @@ snapshots: w3c-keyname@2.2.8: {} - watchpack@2.4.4: + warning@4.0.3: dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 + loose-envify: 1.4.0 wcwidth@1.0.1: dependencies: @@ -12208,48 +11798,6 @@ snapshots: web-streams-polyfill@3.3.3: {} - webidl-conversions@3.0.1: - optional: true - - webpack-sources@3.3.3: {} - - webpack@5.99.9(esbuild@0.25.5): - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/wasm-edit': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.15.0 - browserslist: 4.25.1 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.18.2 - es-module-lexer: 1.7.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 4.3.2 - tapable: 2.2.2 - terser-webpack-plugin: 5.3.14(esbuild@0.25.5)(webpack@5.99.9(esbuild@0.25.5)) - watchpack: 2.4.4 - webpack-sources: 3.3.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - optional: true - which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -12299,11 +11847,6 @@ snapshots: dependencies: isexe: 2.0.0 - wide-align@1.1.5: - dependencies: - string-width: 4.2.3 - optional: true - word-wrap@1.2.5: {} wrap-ansi@7.0.0: From a475000df58a3e4406160fdcea7282828697d6b6 Mon Sep 17 00:00:00 2001 From: PingChuan <1259732256@qq.com> Date: Tue, 25 Nov 2025 14:38:54 +0800 Subject: [PATCH 05/13] =?UTF-8?q?feat=EF=BC=9A=E5=AE=8C=E6=88=90=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E8=87=AA=E5=AE=9A=E4=B9=89Collabora=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E9=A1=B5=E9=9D=A2=E8=B7=B3=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/collabora/CollaboraViewer.tsx | 45 +++--- app/components/collabora/Uno.ts | 3 +- app/components/collabora/hooks.ts | 57 +------ app/components/collabora/lib/README.md | 15 +- app/components/collabora/lib/gotoPage.ts | 151 +++++++++++++++++++ app/components/collabora/lib/index.ts | 9 +- app/components/collabora/lib/navigation.ts | 29 ---- app/components/collabora/lib/pageInfo.ts | 21 --- app/components/collabora/types.ts | 3 - app/components/reviews/FilePreview.tsx | 19 ++- 10 files changed, 205 insertions(+), 147 deletions(-) create mode 100644 app/components/collabora/lib/gotoPage.ts diff --git a/app/components/collabora/CollaboraViewer.tsx b/app/components/collabora/CollaboraViewer.tsx index a899e7f..b5f9f3c 100644 --- a/app/components/collabora/CollaboraViewer.tsx +++ b/app/components/collabora/CollaboraViewer.tsx @@ -10,7 +10,7 @@ * @encoding UTF-8 */ -import { useRef, forwardRef, useImperativeHandle, useState, useEffect } from 'react'; +import { useRef, forwardRef, useImperativeHandle, useState } from 'react'; import type { CollaboraViewerProps, CollaboraViewerHandle } from './types'; import { useCollaboraConfig, useDocumentReady, useCollaboraUnoCommands } from './hooks'; import { sendUnoCommand } from './Uno'; @@ -54,20 +54,6 @@ export const CollaboraViewer = forwardRef iframeRef.current?.contentWindow || null, }), [unoCommands, isDocumentLoaded, mode]); - // 5. 将 sendUnoCommand 挂载到 window 对象,供调试面板和控制台使用 - useEffect(() => { - if (iframeRef.current?.contentWindow) { - (window as any).sendUno = (cmd: string, args: any = {}) => { - if (iframeRef.current?.contentWindow) { - sendUnoCommand(iframeRef.current.contentWindow, cmd, args); - } - }; - } - - return () => { - delete (window as any).sendUno; - }; - }, [isDocumentLoaded]); // 加载中状态 if (loading) { @@ -101,20 +87,15 @@ export const CollaboraViewer = forwardRef = {}; const raw = (unoArgs || '').trim(); if (raw !== '') { try { - args = JSON.parse(raw); + args = JSON.parse(raw) as Record; } catch (err) { try { // fallback: replace single quotes with double quotes and parse - args = JSON.parse(raw.replace(/'(.*?)'/g, '"$1"')); + args = JSON.parse(raw.replace(/'(.*?)'/g, '"$1"')) as Record; } catch (err2) { console.error('解析 UNO Args 失败:', err2); setUnoResult('Args 解析失败,请使用有效 JSON'); @@ -122,12 +103,22 @@ export const CollaboraViewer = forwardRef {/* UNO 命令测试面板 */} - {/*

+
{unoResult && {unoResult}} -
*/} +
{/* 文档加载提示 */} {!isDocumentLoaded && ( @@ -162,7 +153,8 @@ export const CollaboraViewer = forwardRef )} - {/* Collabora iframe */} + {/* Collabora iframe - tabIndex is needed for keyboard navigation */} + {/* eslint-disable jsx-a11y/no-noninteractive-tabindex */}