mirror of
https://github.com/stackblitz-labs/bolt.diy
synced 2025-06-26 10:16:01 +00:00
feat: support uploading text and document files
This commit is contained in:
parent
95e62853a8
commit
9968b9c51b
@ -26,6 +26,7 @@ import type { ModelInfo } from '~/lib/modules/llm/types';
|
||||
import ProgressCompilation from './ProgressCompilation';
|
||||
import type { ProgressAnnotation } from '~/types/context';
|
||||
import type { ActionRunner } from '~/lib/runtime/action-runner';
|
||||
import { extractTextFromFile } from '~/utils/fileExtract';
|
||||
import { SupabaseChatAlert } from '~/components/chat/SupabaseAlert';
|
||||
import { expoUrlAtom } from '~/lib/stores/qrCodeStore';
|
||||
import { useStore } from '@nanostores/react';
|
||||
@ -64,6 +65,8 @@ interface BaseChatProps {
|
||||
setUploadedFiles?: (files: File[]) => void;
|
||||
imageDataList?: string[];
|
||||
setImageDataList?: (dataList: string[]) => void;
|
||||
textDataList?: string[];
|
||||
setTextDataList?: (dataList: string[]) => void;
|
||||
actionAlert?: ActionAlert;
|
||||
clearAlert?: () => void;
|
||||
supabaseAlert?: SupabaseAlert;
|
||||
@ -108,6 +111,8 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
||||
setUploadedFiles,
|
||||
imageDataList = [],
|
||||
setImageDataList,
|
||||
textDataList = [],
|
||||
setTextDataList,
|
||||
messages,
|
||||
actionAlert,
|
||||
clearAlert,
|
||||
@ -284,20 +289,28 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
||||
const handleFileUpload = () => {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = 'image/*';
|
||||
input.accept =
|
||||
'image/*,.pdf,.docx,.txt,.md,.js,.ts,.tsx,.html,.css,.json';
|
||||
|
||||
input.onchange = async (e) => {
|
||||
const file = (e.target as HTMLInputElement).files?.[0];
|
||||
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (e) => {
|
||||
const base64Image = e.target?.result as string;
|
||||
if (file.type.startsWith('image/')) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (ev) => {
|
||||
const base64Image = ev.target?.result as string;
|
||||
setUploadedFiles?.([...uploadedFiles, file]);
|
||||
setImageDataList?.([...imageDataList, base64Image]);
|
||||
setTextDataList?.([...textDataList, '']);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
const text = await extractTextFromFile(file);
|
||||
setUploadedFiles?.([...uploadedFiles, file]);
|
||||
setImageDataList?.([...imageDataList, base64Image]);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
setImageDataList?.([...imageDataList, '']);
|
||||
setTextDataList?.([...textDataList, text]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -312,20 +325,25 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
||||
}
|
||||
|
||||
for (const item of items) {
|
||||
if (item.type.startsWith('image/')) {
|
||||
if (item.kind === 'file') {
|
||||
const file = item.getAsFile();
|
||||
if (!file) continue;
|
||||
e.preventDefault();
|
||||
|
||||
const file = item.getAsFile();
|
||||
|
||||
if (file) {
|
||||
if (file.type.startsWith('image/')) {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (e) => {
|
||||
const base64Image = e.target?.result as string;
|
||||
reader.onload = (ev) => {
|
||||
const base64Image = ev.target?.result as string;
|
||||
setUploadedFiles?.([...uploadedFiles, file]);
|
||||
setImageDataList?.([...imageDataList, base64Image]);
|
||||
setTextDataList?.([...textDataList, '']);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
const text = await extractTextFromFile(file);
|
||||
setUploadedFiles?.([...uploadedFiles, file]);
|
||||
setImageDataList?.([...imageDataList, '']);
|
||||
setTextDataList?.([...textDataList, text]);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -432,6 +450,8 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
||||
setUploadedFiles={setUploadedFiles}
|
||||
imageDataList={imageDataList}
|
||||
setImageDataList={setImageDataList}
|
||||
textDataList={textDataList}
|
||||
setTextDataList={setTextDataList}
|
||||
textareaRef={textareaRef}
|
||||
input={input}
|
||||
handleInputChange={handleInputChange}
|
||||
|
@ -25,7 +25,8 @@ import { createSampler } from '~/utils/sampler';
|
||||
import { getTemplates, selectStarterTemplate } from '~/utils/selectStarterTemplate';
|
||||
import { logStore } from '~/lib/stores/logs';
|
||||
import { streamingState } from '~/lib/stores/streaming';
|
||||
import { filesToArtifacts } from '~/utils/fileUtils';
|
||||
import { filesToArtifacts, uploadedFilesToArtifacts } from '~/utils/fileUtils';
|
||||
import { escapeBoltTags } from '~/utils/projectCommands';
|
||||
import { supabaseConnection } from '~/lib/stores/supabase';
|
||||
import { defaultDesignScheme, type DesignScheme } from '~/types/design-scheme';
|
||||
import type { ElementInfo } from '~/components/workbench/Inspector';
|
||||
@ -123,6 +124,7 @@ export const ChatImpl = memo(
|
||||
const [chatStarted, setChatStarted] = useState(initialMessages.length > 0);
|
||||
const [uploadedFiles, setUploadedFiles] = useState<File[]>([]);
|
||||
const [imageDataList, setImageDataList] = useState<string[]>([]);
|
||||
const [textDataList, setTextDataList] = useState<string[]>([]);
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [fakeLoading, setFakeLoading] = useState(false);
|
||||
const files = useStore(workbenchStore.files);
|
||||
@ -353,7 +355,7 @@ export const ChatImpl = memo(
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${finalMessageContent}`,
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${uploadArtifact}${finalMessageContent}`,
|
||||
},
|
||||
...imageDataList.map((imageData) => ({
|
||||
type: 'image',
|
||||
@ -379,6 +381,7 @@ export const ChatImpl = memo(
|
||||
|
||||
setUploadedFiles([]);
|
||||
setImageDataList([]);
|
||||
setTextDataList([]);
|
||||
|
||||
resetEnhancer();
|
||||
|
||||
@ -398,7 +401,7 @@ export const ChatImpl = memo(
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${finalMessageContent}`,
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${uploadArtifact}${finalMessageContent}`,
|
||||
},
|
||||
...imageDataList.map((imageData) => ({
|
||||
type: 'image',
|
||||
@ -414,6 +417,7 @@ export const ChatImpl = memo(
|
||||
|
||||
setUploadedFiles([]);
|
||||
setImageDataList([]);
|
||||
setTextDataList([]);
|
||||
|
||||
resetEnhancer();
|
||||
|
||||
@ -430,6 +434,18 @@ export const ChatImpl = memo(
|
||||
|
||||
chatStore.setKey('aborted', false);
|
||||
|
||||
const uploadedMap: { [path: string]: string } = {};
|
||||
uploadedFiles.forEach((file, idx) => {
|
||||
const text = textDataList[idx];
|
||||
if (text) {
|
||||
uploadedMap[file.name] = escapeBoltTags(text);
|
||||
}
|
||||
});
|
||||
const uploadArtifact =
|
||||
Object.keys(uploadedMap).length > 0
|
||||
? uploadedFilesToArtifacts(uploadedMap, `uploaded-${Date.now()}`)
|
||||
: '';
|
||||
|
||||
if (modifiedFiles !== undefined) {
|
||||
const userUpdateArtifact = filesToArtifacts(modifiedFiles, `${Date.now()}`);
|
||||
append({
|
||||
@ -437,7 +453,7 @@ export const ChatImpl = memo(
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${userUpdateArtifact}${finalMessageContent}`,
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${uploadArtifact}${userUpdateArtifact}${finalMessageContent}`,
|
||||
},
|
||||
...imageDataList.map((imageData) => ({
|
||||
type: 'image',
|
||||
@ -453,7 +469,7 @@ export const ChatImpl = memo(
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${finalMessageContent}`,
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${uploadArtifact}${finalMessageContent}`,
|
||||
},
|
||||
...imageDataList.map((imageData) => ({
|
||||
type: 'image',
|
||||
@ -468,6 +484,7 @@ export const ChatImpl = memo(
|
||||
|
||||
setUploadedFiles([]);
|
||||
setImageDataList([]);
|
||||
setTextDataList([]);
|
||||
|
||||
resetEnhancer();
|
||||
|
||||
@ -565,6 +582,8 @@ export const ChatImpl = memo(
|
||||
setUploadedFiles={setUploadedFiles}
|
||||
imageDataList={imageDataList}
|
||||
setImageDataList={setImageDataList}
|
||||
textDataList={textDataList}
|
||||
setTextDataList={setTextDataList}
|
||||
actionAlert={actionAlert}
|
||||
clearAlert={() => workbenchStore.clearAlert()}
|
||||
supabaseAlert={supabaseAlert}
|
||||
|
@ -10,6 +10,7 @@ import { ScreenshotStateManager } from './ScreenshotStateManager';
|
||||
import { SendButton } from './SendButton.client';
|
||||
import { IconButton } from '~/components/ui/IconButton';
|
||||
import { toast } from 'react-toastify';
|
||||
import { extractTextFromFile } from '~/utils/fileExtract';
|
||||
import { SpeechRecognitionButton } from '~/components/chat/SpeechRecognition';
|
||||
import { SupabaseConnection } from './SupabaseConnection';
|
||||
import { ExpoQrModal } from '~/components/workbench/ExpoQrModal';
|
||||
@ -50,6 +51,8 @@ interface ChatBoxProps {
|
||||
setModel?: ((model: string) => void) | undefined;
|
||||
setUploadedFiles?: ((files: File[]) => void) | undefined;
|
||||
setImageDataList?: ((dataList: string[]) => void) | undefined;
|
||||
textDataList: string[];
|
||||
setTextDataList?: ((dataList: string[]) => void) | undefined;
|
||||
handleInputChange?: ((event: React.ChangeEvent<HTMLTextAreaElement>) => void) | undefined;
|
||||
handleStop?: (() => void) | undefined;
|
||||
enhancingPrompt?: boolean | undefined;
|
||||
@ -134,9 +137,11 @@ export const ChatBox: React.FC<ChatBoxProps> = (props) => {
|
||||
<FilePreview
|
||||
files={props.uploadedFiles}
|
||||
imageDataList={props.imageDataList}
|
||||
textDataList={props.textDataList}
|
||||
onRemove={(index) => {
|
||||
props.setUploadedFiles?.(props.uploadedFiles.filter((_, i) => i !== index));
|
||||
props.setImageDataList?.(props.imageDataList.filter((_, i) => i !== index));
|
||||
props.setTextDataList?.(props.textDataList.filter((_, i) => i !== index));
|
||||
}}
|
||||
/>
|
||||
<ClientOnly>
|
||||
@ -192,16 +197,22 @@ export const ChatBox: React.FC<ChatBoxProps> = (props) => {
|
||||
e.currentTarget.style.border = '1px solid var(--bolt-elements-borderColor)';
|
||||
|
||||
const files = Array.from(e.dataTransfer.files);
|
||||
files.forEach((file) => {
|
||||
files.forEach(async (file) => {
|
||||
if (file.type.startsWith('image/')) {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (e) => {
|
||||
const base64Image = e.target?.result as string;
|
||||
reader.onload = (ev) => {
|
||||
const base64Image = ev.target?.result as string;
|
||||
props.setUploadedFiles?.([...props.uploadedFiles, file]);
|
||||
props.setImageDataList?.([...props.imageDataList, base64Image]);
|
||||
props.setTextDataList?.([...props.textDataList, '']);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
const text = await extractTextFromFile(file);
|
||||
props.setUploadedFiles?.([...props.uploadedFiles, file]);
|
||||
props.setImageDataList?.([...props.imageDataList, '']);
|
||||
props.setTextDataList?.([...props.textDataList, text]);
|
||||
}
|
||||
});
|
||||
}}
|
||||
|
@ -3,10 +3,11 @@ import React from 'react';
|
||||
interface FilePreviewProps {
|
||||
files: File[];
|
||||
imageDataList: string[];
|
||||
textDataList: string[];
|
||||
onRemove: (index: number) => void;
|
||||
}
|
||||
|
||||
const FilePreview: React.FC<FilePreviewProps> = ({ files, imageDataList, onRemove }) => {
|
||||
const FilePreview: React.FC<FilePreviewProps> = ({ files, imageDataList, textDataList, onRemove }) => {
|
||||
if (!files || files.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@ -15,7 +16,7 @@ const FilePreview: React.FC<FilePreviewProps> = ({ files, imageDataList, onRemov
|
||||
<div className="flex flex-row overflow-x-auto mx-2 -mt-1 p-2 bg-bolt-elements-background-depth-3 border border-b-none border-bolt-elements-borderColor rounded-lg rounded-b-none">
|
||||
{files.map((file, index) => (
|
||||
<div key={file.name + file.size} className="mr-2 relative">
|
||||
{imageDataList[index] && (
|
||||
{imageDataList[index] ? (
|
||||
<div className="relative">
|
||||
<img src={imageDataList[index]} alt={file.name} className="max-h-20 rounded-lg" />
|
||||
<button
|
||||
@ -28,6 +29,19 @@ const FilePreview: React.FC<FilePreviewProps> = ({ files, imageDataList, onRemov
|
||||
<span className="truncate">{file.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="relative flex items-center justify-center w-20 h-20 bg-bolt-elements-background-depth-2 rounded-lg">
|
||||
<div className="i-ph:file-text text-xl" />
|
||||
<button
|
||||
onClick={() => onRemove(index)}
|
||||
className="absolute -top-1 -right-1 z-10 bg-black rounded-full w-5 h-5 shadow-md hover:bg-gray-900 transition-colors flex items-center justify-center"
|
||||
>
|
||||
<div className="i-ph:x w-3 h-3 text-gray-200" />
|
||||
</button>
|
||||
<div className="absolute bottom-0 w-full h-5 flex items-center px-2 rounded-b-lg text-bolt-elements-textTertiary font-thin text-xs">
|
||||
<span className="truncate">{file.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
31
app/utils/fileExtract.ts
Normal file
31
app/utils/fileExtract.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs';
|
||||
import pdfWorker from 'pdfjs-dist/build/pdf.worker.mjs';
|
||||
import mammoth from 'mammoth/mammoth.browser';
|
||||
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorker;
|
||||
|
||||
export async function extractTextFromFile(file: File): Promise<string> {
|
||||
if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) {
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
|
||||
const texts: string[] = [];
|
||||
for (let i = 1; i <= pdf.numPages; i++) {
|
||||
const page = await pdf.getPage(i);
|
||||
const content = await page.getTextContent();
|
||||
texts.push(content.items.map((item: any) => item.str).join(' '));
|
||||
}
|
||||
return texts.join('\n');
|
||||
}
|
||||
|
||||
if (
|
||||
file.type ===
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ||
|
||||
file.name.toLowerCase().endsWith('.docx')
|
||||
) {
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const result = await mammoth.extractRawText({ arrayBuffer });
|
||||
return result.value;
|
||||
}
|
||||
|
||||
return file.text();
|
||||
}
|
@ -119,3 +119,22 @@ ${files[filePath].content}
|
||||
</boltArtifact>
|
||||
`;
|
||||
};
|
||||
|
||||
export const uploadedFilesToArtifacts = (
|
||||
files: { [path: string]: string },
|
||||
id: string,
|
||||
): string => {
|
||||
return `
|
||||
<boltArtifact id="${id}" title="Uploaded Files">
|
||||
${Object.keys(files)
|
||||
.map(
|
||||
(filePath) => `
|
||||
<boltAction type="file" filePath="${filePath}">
|
||||
${files[filePath]}
|
||||
</boltAction>
|
||||
`,
|
||||
)
|
||||
.join('\n')}
|
||||
</boltArtifact>
|
||||
`;
|
||||
};
|
||||
|
@ -123,10 +123,12 @@
|
||||
"jspdf": "^2.5.2",
|
||||
"jszip": "^3.10.1",
|
||||
"lucide-react": "^0.485.0",
|
||||
"mammoth": "^1.9.1",
|
||||
"mime": "^4.0.4",
|
||||
"nanostores": "^0.10.3",
|
||||
"ollama-ai-provider": "^0.15.2",
|
||||
"path-browserify": "^1.0.1",
|
||||
"pdfjs-dist": "^5.3.31",
|
||||
"react": "^18.3.1",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-chartjs-2": "^5.3.0",
|
||||
|
194
pnpm-lock.yaml
194
pnpm-lock.yaml
@ -248,6 +248,9 @@ importers:
|
||||
lucide-react:
|
||||
specifier: ^0.485.0
|
||||
version: 0.485.0(react@18.3.1)
|
||||
mammoth:
|
||||
specifier: ^1.9.1
|
||||
version: 1.9.1
|
||||
mime:
|
||||
specifier: ^4.0.4
|
||||
version: 4.0.6
|
||||
@ -260,6 +263,9 @@ importers:
|
||||
path-browserify:
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
pdfjs-dist:
|
||||
specifier: ^5.3.31
|
||||
version: 5.3.31
|
||||
react:
|
||||
specifier: ^18.3.1
|
||||
version: 18.3.1
|
||||
@ -2095,6 +2101,70 @@ packages:
|
||||
nanostores: ^0.9.0 || ^0.10.0 || ^0.11.0
|
||||
react: '>=18.0.0'
|
||||
|
||||
'@napi-rs/canvas-android-arm64@0.1.70':
|
||||
resolution: {integrity: sha512-I/YOuQ0wbkVYxVaYtCgN42WKTYxNqFA0gTcTrHIGG1jfpDSyZWII/uHcjOo4nzd19io6Y4+/BqP8E5hJgf9OmQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.70':
|
||||
resolution: {integrity: sha512-4pPGyXetHIHkw2TOJHujt3mkCP8LdDu8+CT15ld9Id39c752RcI0amDHSuMLMQfAjvusA9B5kKxazwjMGjEJpQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@napi-rs/canvas-darwin-x64@0.1.70':
|
||||
resolution: {integrity: sha512-+2N6Os9LbkmDMHL+raknrUcLQhsXzc5CSXRbXws9C3pv/mjHRVszQ9dhFUUe9FjfPhCJznO6USVdwOtu7pOrzQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.70':
|
||||
resolution: {integrity: sha512-QjscX9OaKq/990sVhSMj581xuqLgiaPVMjjYvWaCmAJRkNQ004QfoSMEm3FoTqM4DRoquP8jvuEXScVJsc1rqQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.70':
|
||||
resolution: {integrity: sha512-LNakMOwwqwiHIwMpnMAbFRczQMQ7TkkMyATqFCOtUJNlE6LPP/QiUj/mlFrNbUn/hctqShJ60gWEb52ZTALbVw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.70':
|
||||
resolution: {integrity: sha512-wBTOllEYNfJCHOdZj9v8gLzZ4oY3oyPX8MSRvaxPm/s7RfEXxCyZ8OhJ5xAyicsDdbE5YBZqdmaaeP5+xKxvtg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.70':
|
||||
resolution: {integrity: sha512-GVUUPC8TuuFqHip0rxHkUqArQnlzmlXmTEBuXAWdgCv85zTCFH8nOHk/YCF5yo0Z2eOm8nOi90aWs0leJ4OE5Q==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.70':
|
||||
resolution: {integrity: sha512-/kvUa2lZRwGNyfznSn5t1ShWJnr/m5acSlhTV3eXECafObjl0VBuA1HJw0QrilLpb4Fe0VLywkpD1NsMoVDROQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.70':
|
||||
resolution: {integrity: sha512-aqlv8MLpycoMKRmds7JWCfVwNf1fiZxaU7JwJs9/ExjTD8lX2KjsO7CTeAj5Cl4aEuzxUWbJPUUE2Qu9cZ1vfg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.70':
|
||||
resolution: {integrity: sha512-Q9QU3WIpwBTVHk4cPfBjGHGU4U0llQYRXgJtFtYqqGNEOKVN4OT6PQ+ve63xwIPODMpZ0HHyj/KLGc9CWc3EtQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@napi-rs/canvas@0.1.70':
|
||||
resolution: {integrity: sha512-nD6NGa4JbNYSZYsTnLGrqe9Kn/lCkA4ybXt8sx5ojDqZjr2i0TWAHxx/vhgfjX+i3hCdKWufxYwi7CfXqtITSA==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
engines: {node: '>= 8'}
|
||||
@ -3683,6 +3753,9 @@ packages:
|
||||
arg@5.0.2:
|
||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
||||
|
||||
argparse@1.0.10:
|
||||
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
|
||||
|
||||
argparse@2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
|
||||
@ -3791,6 +3864,9 @@ packages:
|
||||
bluebird-lst@1.0.9:
|
||||
resolution: {integrity: sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==}
|
||||
|
||||
bluebird@3.4.7:
|
||||
resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==}
|
||||
|
||||
bluebird@3.7.2:
|
||||
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
|
||||
|
||||
@ -4407,6 +4483,9 @@ packages:
|
||||
diffie-hellman@5.0.3:
|
||||
resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==}
|
||||
|
||||
dingbat-to-unicode@1.0.1:
|
||||
resolution: {integrity: sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==}
|
||||
|
||||
dir-compare@4.2.0:
|
||||
resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==}
|
||||
|
||||
@ -4447,6 +4526,9 @@ packages:
|
||||
resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
duck@0.1.12:
|
||||
resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -5644,6 +5726,9 @@ packages:
|
||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||
hasBin: true
|
||||
|
||||
lop@0.4.2:
|
||||
resolution: {integrity: sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw==}
|
||||
|
||||
loupe@3.1.3:
|
||||
resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==}
|
||||
|
||||
@ -5684,6 +5769,11 @@ packages:
|
||||
resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
|
||||
mammoth@1.9.1:
|
||||
resolution: {integrity: sha512-4S2v1eP4Yo4so0zGNicJKcP93su3wDPcUk+xvkjSG75nlNjSkDJu8BhWQ+e54BROM0HfA6nPzJn12S6bq2Ko6w==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
hasBin: true
|
||||
|
||||
markdown-extensions@1.1.1:
|
||||
resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -6336,6 +6426,9 @@ packages:
|
||||
oniguruma-to-es@2.3.0:
|
||||
resolution: {integrity: sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==}
|
||||
|
||||
option@0.2.4:
|
||||
resolution: {integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==}
|
||||
|
||||
optionator@0.9.4:
|
||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@ -6445,6 +6538,10 @@ packages:
|
||||
resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
pdfjs-dist@5.3.31:
|
||||
resolution: {integrity: sha512-EhPdIjNX0fcdwYQO+e3BAAJPXt+XI29TZWC7COhIXs/K0JHcUt1Gdz1ITpebTwVMFiLsukdUZ3u0oTO7jij+VA==}
|
||||
engines: {node: '>=20.16.0 || >=22.3.0'}
|
||||
|
||||
pe-library@0.4.1:
|
||||
resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==}
|
||||
engines: {node: '>=12', npm: '>=6'}
|
||||
@ -7375,6 +7472,9 @@ packages:
|
||||
spdx-license-ids@3.0.21:
|
||||
resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==}
|
||||
|
||||
sprintf-js@1.0.3:
|
||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||
|
||||
sprintf-js@1.1.3:
|
||||
resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
|
||||
|
||||
@ -7717,6 +7817,9 @@ packages:
|
||||
unconfig@0.5.5:
|
||||
resolution: {integrity: sha512-VQZ5PT9HDX+qag0XdgQi8tJepPhXiR/yVOkn707gJDKo31lGjRilPREiQJ9Z6zd/Ugpv6ZvO5VxVIcatldYcNQ==}
|
||||
|
||||
underscore@1.13.7:
|
||||
resolution: {integrity: sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==}
|
||||
|
||||
undici-types@6.19.8:
|
||||
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
|
||||
|
||||
@ -8179,6 +8282,10 @@ packages:
|
||||
resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
xmlbuilder@10.1.1:
|
||||
resolution: {integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==}
|
||||
engines: {node: '>=4.0'}
|
||||
|
||||
xmlbuilder@15.1.1:
|
||||
resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==}
|
||||
engines: {node: '>=8.0'}
|
||||
@ -9967,6 +10074,50 @@ snapshots:
|
||||
nanostores: 0.10.3
|
||||
react: 18.3.1
|
||||
|
||||
'@napi-rs/canvas-android-arm64@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-darwin-arm64@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-darwin-x64@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-gnu@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-arm64-musl@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-riscv64-gnu@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-x64-gnu@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-linux-x64-musl@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas-win32-x64-msvc@0.1.70':
|
||||
optional: true
|
||||
|
||||
'@napi-rs/canvas@0.1.70':
|
||||
optionalDependencies:
|
||||
'@napi-rs/canvas-android-arm64': 0.1.70
|
||||
'@napi-rs/canvas-darwin-arm64': 0.1.70
|
||||
'@napi-rs/canvas-darwin-x64': 0.1.70
|
||||
'@napi-rs/canvas-linux-arm-gnueabihf': 0.1.70
|
||||
'@napi-rs/canvas-linux-arm64-gnu': 0.1.70
|
||||
'@napi-rs/canvas-linux-arm64-musl': 0.1.70
|
||||
'@napi-rs/canvas-linux-riscv64-gnu': 0.1.70
|
||||
'@napi-rs/canvas-linux-x64-gnu': 0.1.70
|
||||
'@napi-rs/canvas-linux-x64-musl': 0.1.70
|
||||
'@napi-rs/canvas-win32-x64-msvc': 0.1.70
|
||||
optional: true
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
dependencies:
|
||||
'@nodelib/fs.stat': 2.0.5
|
||||
@ -11967,6 +12118,10 @@ snapshots:
|
||||
|
||||
arg@5.0.2: {}
|
||||
|
||||
argparse@1.0.10:
|
||||
dependencies:
|
||||
sprintf-js: 1.0.3
|
||||
|
||||
argparse@2.0.1: {}
|
||||
|
||||
aria-hidden@1.2.4:
|
||||
@ -12063,6 +12218,8 @@ snapshots:
|
||||
dependencies:
|
||||
bluebird: 3.7.2
|
||||
|
||||
bluebird@3.4.7: {}
|
||||
|
||||
bluebird@3.7.2: {}
|
||||
|
||||
bn.js@4.12.1: {}
|
||||
@ -12748,6 +12905,8 @@ snapshots:
|
||||
miller-rabin: 4.0.1
|
||||
randombytes: 2.1.0
|
||||
|
||||
dingbat-to-unicode@1.0.1: {}
|
||||
|
||||
dir-compare@4.2.0:
|
||||
dependencies:
|
||||
minimatch: 3.1.2
|
||||
@ -12805,6 +12964,10 @@ snapshots:
|
||||
|
||||
dotenv@16.4.7: {}
|
||||
|
||||
duck@0.1.12:
|
||||
dependencies:
|
||||
underscore: 1.13.7
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@ -14338,6 +14501,12 @@ snapshots:
|
||||
dependencies:
|
||||
js-tokens: 4.0.0
|
||||
|
||||
lop@0.4.2:
|
||||
dependencies:
|
||||
duck: 0.1.12
|
||||
option: 0.2.4
|
||||
underscore: 1.13.7
|
||||
|
||||
loupe@3.1.3: {}
|
||||
|
||||
lowercase-keys@2.0.0: {}
|
||||
@ -14390,6 +14559,19 @@ snapshots:
|
||||
- bluebird
|
||||
- supports-color
|
||||
|
||||
mammoth@1.9.1:
|
||||
dependencies:
|
||||
'@xmldom/xmldom': 0.8.10
|
||||
argparse: 1.0.10
|
||||
base64-js: 1.5.1
|
||||
bluebird: 3.4.7
|
||||
dingbat-to-unicode: 1.0.1
|
||||
jszip: 3.10.1
|
||||
lop: 0.4.2
|
||||
path-is-absolute: 1.0.1
|
||||
underscore: 1.13.7
|
||||
xmlbuilder: 10.1.1
|
||||
|
||||
markdown-extensions@1.1.1: {}
|
||||
|
||||
markdown-table@3.0.4: {}
|
||||
@ -15466,6 +15648,8 @@ snapshots:
|
||||
regex: 5.1.1
|
||||
regex-recursion: 5.1.1
|
||||
|
||||
option@0.2.4: {}
|
||||
|
||||
optionator@0.9.4:
|
||||
dependencies:
|
||||
deep-is: 0.1.4
|
||||
@ -15581,6 +15765,10 @@ snapshots:
|
||||
safe-buffer: 5.2.1
|
||||
sha.js: 2.4.11
|
||||
|
||||
pdfjs-dist@5.3.31:
|
||||
optionalDependencies:
|
||||
'@napi-rs/canvas': 0.1.70
|
||||
|
||||
pe-library@0.4.1: {}
|
||||
|
||||
peek-stream@1.1.3:
|
||||
@ -16584,6 +16772,8 @@ snapshots:
|
||||
|
||||
spdx-license-ids@3.0.21: {}
|
||||
|
||||
sprintf-js@1.0.3: {}
|
||||
|
||||
sprintf-js@1.1.3: {}
|
||||
|
||||
ssri@10.0.6:
|
||||
@ -16910,6 +17100,8 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
underscore@1.13.7: {}
|
||||
|
||||
undici-types@6.19.8: {}
|
||||
|
||||
undici-types@6.20.0: {}
|
||||
@ -17439,6 +17631,8 @@ snapshots:
|
||||
|
||||
xml-name-validator@5.0.0: {}
|
||||
|
||||
xmlbuilder@10.1.1: {}
|
||||
|
||||
xmlbuilder@15.1.1: {}
|
||||
|
||||
xmlchars@2.2.0: {}
|
||||
|
Loading…
Reference in New Issue
Block a user