Skip to content

Conversation

@Ovgodd
Copy link
Collaborator

@Ovgodd Ovgodd commented Dec 1, 2025

Purpose

Enable users to export an accessible HTML version of content, replacing the "Copy as HTML" option with a full export feature from the modal.

issue : 599

image

Proposal

  • Move "Copy as HTML" to the export modal
  • Add a new accessible HTML export format (.html in ZIP)
  • Embed media files (images, SVG, PDF, video/audio) in the ZIP with clean filenames
  • Update export modal UI and labels
  • Add E2E test to validate HTML export ZIP structure and content

@Ovgodd Ovgodd requested a review from AntoLC December 1, 2025 14:29
@Ovgodd Ovgodd self-assigned this Dec 1, 2025
@Ovgodd Ovgodd added the enhancement improve an existing feature label Dec 1, 2025
@Ovgodd Ovgodd changed the title Enhance/html copy to download ⚡️Enhance/html copy to download Dec 1, 2025
@Ovgodd Ovgodd force-pushed the enhance/html-copy-to-download branch from 98ffee7 to aac1cca Compare December 1, 2025 14:31
@Ovgodd Ovgodd marked this pull request as ready for review December 1, 2025 14:34
@github-actions
Copy link

github-actions bot commented Dec 1, 2025

Size Change: +26.8 kB (+0.65%)

Total Size: 4.14 MB

Filename Size Change
apps/impress/out/_next/static/chunks/1927.js 0 B -703 kB (removed) 🏆
apps/impress/out/_next/static/eb4c2de9/_buildManifest.js 0 B -906 B (removed) 🏆
apps/impress/out/_next/static/chunks/8323.js 730 kB +730 kB (new file) 🆕
apps/impress/out/_next/static/d79120e8/_buildManifest.js 906 B +906 B (new file) 🆕

compressed-size-action

@Ovgodd Ovgodd force-pushed the enhance/html-copy-to-download branch 4 times, most recently from c1b12d1 to 999c814 Compare December 1, 2025 15:19
Copy link
Collaborator

@AntoLC AntoLC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some cases where the mp3 and videos are not exported, I used this doc model:
https://www.blocknotejs.org/docs/features/blocks

Comment on lines 172 to 178
const fetched = await exportCorsResolveFileUrl(doc.id, src);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see you use the CORS proxy, but I think it works only with images:

if not content_type.startswith("image/"):
return drf.response.Response(
status=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
)

Copy link
Collaborator Author

@Ovgodd Ovgodd Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, I see, the current CORS proxy only supports images.
So that means external audio / video (when they’re not uploaded to our backend) are rejected and can’t be added to the HTML ZIP? ( as you said sometimes mp3 and vidéos are not exported )
In that case, should we update the backend proxy to also allow audio and video so these files can be exported too?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are 2 types of "link" (internal / external), if the resources are internal like https://docs.numerique.gouv.fr/media/..., we have to download them and put them in the zip files because they will not be accessible otherwise; on the other hand, if the resources are external like https://youtube.com/kefseklsfes.mp4, I don't think we should download them but just let the src as it was, moreover we don't have the hand on the external resources they could be huge (1go) or even infected.

Comment on lines 240 to 245
const zipBuffer = await cs.toBuffer(await download.createReadStream());

// ZIP files start with "PK\x03\x04"
expect(zipBuffer.length).toBeGreaterThan(4);
expect(zipBuffer[0]).toBe(0x50);
expect(zipBuffer[1]).toBe(0x4b);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we improve this part to check what is inside the zip file ?

The idea:

import JSZip from 'jszip';

// In your test:
const zipBuffer = await cs.toBuffer(await download.createReadStream());

// Unzip and inspect contents
const zip = await JSZip.loadAsync(zipBuffer);

// Check that index.html exists
const indexHtml = zip.file('index.html');
expect(indexHtml).not.toBeNull();

// Read and verify HTML content
const htmlContent = await indexHtml!.async('string');
expect(htmlContent).toContain('Hello HTML ZIP');

// Check for media files
const mediaFiles = zip.file(/^media\//);
expect(mediaFiles.length).toBeGreaterThan(0);

// Verify the SVG image is included
const svgFile = mediaFiles.find(f => f.name.endsWith('.svg'));
expect(svgFile).toBeDefined();

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I agree this is much better

@Ovgodd Ovgodd force-pushed the enhance/html-copy-to-download branch from fbdb37c to 882b7f3 Compare December 3, 2025 11:49
@Ovgodd Ovgodd requested a review from AntoLC December 3, 2025 11:49
@Ovgodd Ovgodd force-pushed the enhance/html-copy-to-download branch from 882b7f3 to 22ff23f Compare December 3, 2025 12:37
Comment on lines 172 to 178
const fetched = await exportCorsResolveFileUrl(doc.id, src);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are 2 types of "link" (internal / external), if the resources are internal like https://docs.numerique.gouv.fr/media/..., we have to download them and put them in the zip files because they will not be accessible otherwise; on the other hand, if the resources are external like https://youtube.com/kefseklsfes.mp4, I don't think we should download them but just let the src as it was, moreover we don't have the hand on the external resources they could be huge (1go) or even infected.

@Ovgodd Ovgodd force-pushed the enhance/html-copy-to-download branch from 22ff23f to 82629f7 Compare December 8, 2025 02:04
@Ovgodd Ovgodd requested a review from AntoLC December 8, 2025 02:38
Copy link
Collaborator

@AntoLC AntoLC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should open a issue to add a css in the zip file to get the look and feel of what we have in Docs; because it seems correct on a accessibility perspective (dom) but visually it is not usable.

@Ovgodd Ovgodd force-pushed the enhance/html-copy-to-download branch from 014fec0 to f0f499a Compare December 9, 2025 08:05
makes the option less visible as it's not useful to most users

Signed-off-by: Cyril <[email protected]>
replaced “copy as html” with export modal option and full media zip export

Signed-off-by: Cyril <[email protected]>
checks generated zip contains html and embedded media files

Signed-off-by: Cyril <[email protected]>
@Ovgodd Ovgodd force-pushed the enhance/html-copy-to-download branch from f0f499a to 9b03754 Compare December 9, 2025 08:24
@Ovgodd Ovgodd merged commit 9b03754 into main Dec 9, 2025
27 of 28 checks passed
@Ovgodd Ovgodd deleted the enhance/html-copy-to-download branch December 9, 2025 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement improve an existing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants