@@ -13,21 +13,24 @@ import {
1313import { DocumentProps , pdf } from '@react-pdf/renderer' ;
1414import jsonemoji from 'emoji-datasource-apple' assert { type : 'json' } ;
1515import i18next from 'i18next' ;
16+ import JSZip from 'jszip' ;
1617import { cloneElement , isValidElement , useMemo , useState } from 'react' ;
1718import { useTranslation } from 'react-i18next' ;
1819import { css } from 'styled-components' ;
1920
2021import { Box , ButtonCloseModal , Text } from '@/components' ;
22+ import { useMediaUrl } from '@/core' ;
2123import { useEditorStore } from '@/docs/doc-editor' ;
2224import { Doc , useTrans } from '@/docs/doc-management' ;
25+ import { fallbackLng } from '@/i18n/config' ;
2326
2427import { exportCorsResolveFileUrl } from '../api/exportResolveFileUrl' ;
2528import { TemplatesOrdering , useTemplates } from '../api/useTemplates' ;
2629import { docxDocsSchemaMappings } from '../mappingDocx' ;
2730import { odtDocsSchemaMappings } from '../mappingODT' ;
2831import { pdfDocsSchemaMappings } from '../mappingPDF' ;
2932import {
30- deriveMediaFilename ,
33+ addMediaFilesToZip ,
3134 downloadFile ,
3235 generateHtmlDocument ,
3336} from '../utils' ;
@@ -57,6 +60,7 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
5760 DocDownloadFormat . PDF ,
5861 ) ;
5962 const { untitledDocument } = useTrans ( ) ;
63+ const mediaUrl = useMediaUrl ( ) ;
6064
6165 const templateOptions = useMemo ( ( ) => {
6266 const templateOptions = ( templates ?. pages || [ ] )
@@ -155,58 +159,32 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
155159 const domParser = new DOMParser ( ) ;
156160 const parsedDocument = domParser . parseFromString ( fullHtml , 'text/html' ) ;
157161
158- const mediaFiles : { filename : string ; blob : Blob } [ ] = [ ] ;
159- const mediaElements = Array . from (
160- parsedDocument . querySelectorAll <
161- | HTMLImageElement
162- | HTMLVideoElement
163- | HTMLAudioElement
164- | HTMLSourceElement
165- > ( 'img, video, audio, source' ) ,
166- ) ;
167-
168- await Promise . all (
169- mediaElements . map ( async ( element , index ) => {
170- const src = element . getAttribute ( 'src' ) ;
171-
172- if ( ! src ) {
173- return ;
174- }
162+ const zip = new JSZip ( ) ;
175163
176- const fetched = await exportCorsResolveFileUrl ( doc . id , src ) ;
164+ await addMediaFilesToZip ( parsedDocument , zip , mediaUrl ) ;
177165
178- if ( ! ( fetched instanceof Blob ) ) {
179- return ;
180- }
181-
182- const filename = deriveMediaFilename ( {
183- src,
184- index,
185- blob : fetched ,
186- } ) ;
187- element . setAttribute ( 'src' , filename ) ;
188- mediaFiles . push ( { filename, blob : fetched } ) ;
189- } ) ,
190- ) ;
191-
192- const lang = i18next . language || 'fr' ;
166+ const lang = i18next . language || fallbackLng ;
167+ const editorHtmlWithLocalMedia = parsedDocument . body . innerHTML ;
193168
194169 const htmlContent = generateHtmlDocument (
195170 documentTitle ,
196171 editorHtmlWithLocalMedia ,
197172 lang ,
198173 ) ;
199174
200- blobExport = new Blob ( [ htmlContent ] , {
201- type : 'text/html;charset=utf-8' ,
202- } ) ;
175+ zip . file ( 'index.html' , htmlContent ) ;
176+
177+ blobExport = await zip . generateAsync ( { type : 'blob' } ) ;
203178 } else {
204179 toast ( t ( 'The export failed' ) , VariantType . ERROR ) ;
205180 setIsExporting ( false ) ;
206181 return ;
207182 }
208183
209- downloadFile ( blobExport , `${ filename } .${ format } ` ) ;
184+ const downloadExtension =
185+ format === DocDownloadFormat . HTML ? 'zip' : format ;
186+
187+ downloadFile ( blobExport , `${ filename } .${ downloadExtension } ` ) ;
210188
211189 toast (
212190 t ( 'Your {{format}} was downloaded succesfully' , {
@@ -283,7 +261,9 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
283261 className = "--docs--modal-export-content"
284262 >
285263 < Text $variation = "secondary" $size = "sm" as = "p" >
286- { t ( 'Download your document in a .docx, .odt or .pdf format.' ) }
264+ { t (
265+ 'Download your document in a .docx, .odt, .pdf or .html(zip) format.' ,
266+ ) }
287267 </ Text >
288268 < Select
289269 clearable = { false }
0 commit comments