From a059b20881d3080d6958ef216cd8bd302fe57460 Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Sat, 6 Jul 2024 19:16:34 +0530 Subject: [PATCH 1/3] add html inlining function --- src/utils.js | 77 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 11 deletions(-) diff --git a/src/utils.js b/src/utils.js index f2ee655c..e9478230 100644 --- a/src/utils.js +++ b/src/utils.js @@ -430,16 +430,19 @@ export function getCompleteHtml(html, css, js, item, isForExport) { '">'; } - if (typeof js === 'string') { - contents += js ? ''; } - contents += '\n\n\n'; + contents += '\n\n'; return contents; } @@ -448,12 +451,14 @@ export function saveAsHtml(item) { var htmlPromise = computeHtml(item.html, item.htmlMode); var cssPromise = computeCss(item.css, item.cssMode); var jsPromise = computeJs(item.js, item.jsMode, false); - Promise.all([htmlPromise, cssPromise, jsPromise]).then(result => { + Promise.all([htmlPromise, cssPromise, jsPromise]).then(async result => { var html = result[0].code, css = result[1].code, js = result[2].code; - var fileContent = getCompleteHtml(html, css, js, item, true); + var fileContent = await inlineAssetsInHtml( + getCompleteHtml(html, css, js, item, true) + ); var d = new Date(); var fileName = [ @@ -480,6 +485,56 @@ export function saveAsHtml(item) { }); } +export async function inlineAssetsInHtml(html) { + const encodeFileToBase64 = async url => { + const response = await fetch(url); + const blob = await response.blob(); + const reader = new FileReader(); + + return new Promise((resolve, reject) => { + reader.onloadend = () => { + const base64String = reader.result.split(',')[1]; + const mimeType = blob.type; + resolve(`data:${mimeType};base64,${base64String}`); + }; + reader.onerror = reject; + reader.readAsDataURL(blob); + }); + }; + + const inlineAssets = async htmlContent => { + const parser = new DOMParser(); + const doc = parser.parseFromString(htmlContent, 'text/html'); + + const processElement = async (element, attr) => { + const url = element.getAttribute(attr); + if (url && !url.startsWith('data:')) { + try { + const encodedData = await encodeFileToBase64(url); + element.setAttribute(attr, encodedData); + } catch (error) { + console.error(`Failed to inline ${url}:`, error); + } + } + }; + + const images = Array.from(doc.querySelectorAll('img')); + const audios = Array.from(doc.querySelectorAll('audio')); + const videos = Array.from(doc.querySelectorAll('video')); + + await Promise.all([ + ...images.map(img => processElement(img, 'src')), + ...audios.map(audio => processElement(audio, 'src')), + ...videos.map(video => processElement(video, 'src')) + ]); + + return doc.documentElement.outerHTML; + }; + + const output = await inlineAssets(html); + // console.log(html, output); + return output; +} export function handleDownloadsPermission() { var d = deferred(); if (!window.IS_EXTENSION) { From 0ef0dfcf6d9525d19987e5324663631a1b03ece0 Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Sun, 7 Jul 2024 12:46:55 +0530 Subject: [PATCH 2/3] add dropdown to savehtml btn --- src/components/Footer.jsx | 41 +++++++++++++++++++++++++--------- src/components/app.jsx | 4 ++-- src/style.css | 46 +++++++++++++++++++++++++++++++++++++++ src/utils.js | 8 +++---- 4 files changed, 83 insertions(+), 16 deletions(-) diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx index 5e83e85d..8918d3ce 100644 --- a/src/components/Footer.jsx +++ b/src/components/Footer.jsx @@ -4,6 +4,7 @@ import { I18n } from '@lingui/react'; import { ProBadge } from './ProBadge'; import { HStack } from './Stack'; import { useEffect, useState } from 'preact/hooks'; +import { DropdownMenu } from './Dropdown'; const JS13K = props => { const [daysLeft, setDaysLeft] = useState(0); @@ -201,16 +202,36 @@ export const Footer = props => { ) : null}