feat: implement secure image upload pipeline and backend XSS guard (Stage 2 Task A)
This commit is contained in:
@@ -50,12 +50,11 @@ export async function initEditor(elementId, dotNetHelper, initialMarkdown) {
|
||||
[Crepe.Feature.ImageBlock]: {
|
||||
onUpload: async (file) => {
|
||||
try {
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
const uint8Array = new Uint8Array(arrayBuffer);
|
||||
const url = await dotNetHelper.invokeMethodAsync('UploadImageFromJs', file.name, file.type, uint8Array);
|
||||
const streamRef = DotNet.createJSStreamReference(file);
|
||||
const url = await dotNetHelper.invokeMethodAsync('UploadImageFromJs', file.name, file.type, streamRef);
|
||||
return url;
|
||||
} catch (err) {
|
||||
console.error("[Milkdown] Failed to upload image from JS:", err);
|
||||
console.error("[Milkdown] Failed to upload image from JS (onUpload):", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -63,6 +62,36 @@ export async function initEditor(elementId, dotNetHelper, initialMarkdown) {
|
||||
}
|
||||
});
|
||||
|
||||
// Configure custom uploader using the uploadConfig context slice
|
||||
crepe.editor.config((ctx) => {
|
||||
try {
|
||||
ctx.update('uploadConfig', (prev) => ({
|
||||
...prev,
|
||||
uploader: async (files, schema) => {
|
||||
const nodes = [];
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
if (file.type.startsWith('image/')) {
|
||||
try {
|
||||
const streamRef = DotNet.createJSStreamReference(file);
|
||||
const uploadedUrl = await dotNetHelper.invokeMethodAsync('UploadImageFromJs', file.name, file.type, streamRef);
|
||||
if (uploadedUrl) {
|
||||
const node = schema.nodes.image.create({ src: uploadedUrl, alt: file.name });
|
||||
nodes.push(node);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("[Milkdown] Failed to upload image in custom uploader:", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
}));
|
||||
} catch (err) {
|
||||
console.error("[Milkdown] Failed to configure uploadConfig uploader:", err);
|
||||
}
|
||||
});
|
||||
|
||||
// Store the editor instance in the map
|
||||
editorCache.set(elementId, crepe);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user