Skip to content
Snippets Groups Projects
Verified Commit 591882a0 authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

feat: Enhance viewer functionality and support for binary downloads

Summary of changes
- Added content setting for binary data types, including 'application/octet-stream'.
- Integrated a download button in the viewer to handle the downloading of binary contents with appropriate labels based on document locale.
- Improved the viewer's markdown processing functionality.
- Updated file imports for better consistency and readability.

Changes
- In development/issues/closed/309.mjs:
    - Added a setting for 'application/octet-stream' support within the viewer.
    - Removed unnecessary commented-out code for clarity.
    - Enhanced the testing of functionality for binary content handling.

Changes
- In source/components/content/viewer.mjs:
    - Refactored the `setContent` method to handle binary data and included error handling for unsupported media types.
    - Added `setDownload` method to create a functional download button embedded within the viewer.
    - Incorporated a method for dynamic internationalization of the download button label based on the document's locale.
    - Cleaned up code formatting for better readability and maintenance.
parent a67a21f2
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,7 @@ import "../../../source/components/style/typography.pcss"; ...@@ -14,6 +14,7 @@ import "../../../source/components/style/typography.pcss";
import "../../../source/components/content/viewer.mjs"; import "../../../source/components/content/viewer.mjs";
const v = document.getElementById("mainer"); const v = document.getElementById("mainer");
console.log(v) console.log(v)
// //
...@@ -33,6 +34,10 @@ console.log(v) ...@@ -33,6 +34,10 @@ console.log(v)
// const url = new URL(`data:text/markdown;base64,${btoa(markdownText)}`); // const url = new URL(`data:text/markdown;base64,${btoa(markdownText)}`);
// v.setContent(url, "text/markdown", "base64"); // v.setContent(url, "text/markdown", "base64");
const content = "zpl-demo"
v.setContent(content, "application/oct33et-stream", "base64");
//const url = new URL("data:text/plain;base64,SGVsbG8gV29ybGQh"); // base64 encoded string for "Hello World!" //const url = new URL("data:text/plain;base64,SGVsbG8gV29ybGQh"); // base64 encoded string for "Hello World!"
//v.setContent(url, "text/plain", "base64"); //v.setContent(url, "text/plain", "base64");
...@@ -83,10 +88,10 @@ console.log(v) ...@@ -83,10 +88,10 @@ console.log(v)
// Simple MP3 audio file encoded in base64 // Simple MP3 audio file encoded in base64
// Minimal base64-encoded test video // Minimal base64-encoded test video
// Base64 encoded simple ping sound (44.1kHz, 16-bit, mono) // Base64 encoded simple ping sound (44.1kHz, 16-bit, mono)
const miniAudioBase64 = "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjIwLjEwMAAAAAAAAAAAAAAA//uQZAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAACcQCA////////////AYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID////////////////////////8AAAAZTGF2YzU4LjM1AAAAAAAAAAAAAAAAJAYAAAAAAAAAAnHyhqwaAAAAAAD/+7DEAAAHHA8iABBwALkNH1AiMmYiIn+JwQgkCYP4fwfBAMcEAQDgQg/B8//y4Pv//gg/+CAIcHwQDg+D4IAAAAD4IBgYGFAIUC4Pg+CAIAgCAIAuD//8HwQf//Ag/YEAwgwLhQDAoGIAz+MUzmX2bOuGicww1HUErAYcESGDJEKeLWg0Kw4EhwsShwWFDBgNB0BQoDgqGEwOAwIAYEQ0mOlI1JyBJI4/k6lQqEBYYgw8QkQzGAmPmyMpGR6RHCUBDgCGg4FwsJBYLBYBQ0RQGi0iJCwvNBdKnR4bwEXFxcXBMLhYLhcKhUJhITExISScTSQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//sQxNYDwAABpBwAACAAADSAAAAETEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU="; // const miniAudioBase64 = "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjIwLjEwMAAAAAAAAAAAAAAA//uQZAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAACcQCA////////////AYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID////////////////////////8AAAAZTGF2YzU4LjM1AAAAAAAAAAAAAAAAJAYAAAAAAAAAAnHyhqwaAAAAAAD/+7DEAAAHHA8iABBwALkNH1AiMmYiIn+JwQgkCYP4fwfBAMcEAQDgQg/B8//y4Pv//gg/+CAIcHwQDg+D4IAAAAD4IBgYGFAIUC4Pg+CAIAgCAIAuD//8HwQf//Ag/YEAwgwLhQDAoGIAz+MUzmX2bOuGicww1HUErAYcESGDJEKeLWg0Kw4EhwsShwWFDBgNB0BQoDgqGEwOAwIAYEQ0mOlI1JyBJI4/k6lQqEBYYgw8QkQzGAmPmyMpGR6RHCUBDgCGg4FwsJBYLBYBQ0RQGi0iJCwvNBdKnR4bwEXFxcXBMLhYLhcKhUJhITExISScTSQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//sQxNYDwAABpBwAACAAADSAAAAETEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=";
//
const url = new URL(`data:audio/mp3;base64,${miniAudioBase64}`); // const url = new URL(`data:audio/mp3;base64,${miniAudioBase64}`);
v.setContent(url, "audio/mp3", "base64"); // v.setContent(url, "audio/mp3", "base64");
// const minimalVideoBase64 = "AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAAu1tZGF0AAACoAYF//+c3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTYgbG9va2FoZWFkX3RocmVhZHM9MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2NvbXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50PTI1MCBrZXlpbnRfbWluPTEwIHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAKYWVpegAVpD//+e5VrHBPqGP9IjQ1ErQWdyI5BQAAAAMAAAMAAANiAAA/AAADAAA6xQS1AAFr6v7oCKDAAAADOwAAAwAAAwB7AAA9AAAAAwAACywAAAAABowDGBHE84cFC6BnGJObADwQ6JCSNs5wOEMFLFNXBALRqRK33vh/+kRBagRa/qE/YqRQ+kRCAUW1ZUB/q2Qb+kR2uP8I/0h2vxj5oJAxM94/hYtpIFoAAAADAAADAAlYABO0AAADAAADABRWN3xTBGgTAAAABgAAAwUYLJwAAQBxtSxpJ1CZT4dCZ/6RUgRo9IiAAAAABgCAAAAXc3R0cwAAAAAAAAABAAAAAQAAAAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAFHN0c3oAAAAAAAAABAsAAAACAAAAFHN0Y28AAAAAAAAAAQAAAAEAAAABAAAAAQAAABRzdHNzAAAAAAAAAAEAAAABAAAAEHNzaWEAAAAAABBzc2QAAAAAAAAAAQAAAA8AAAACbWRpYQAAAABtZGhkAAAAABdoZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAAVmlkZW9IYW5kbGVyAAAAAmxtaW5mAAAAFHZtaGQAAAABAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAAIsc3RibAAAALRzdHNkAAAAAAAAAAEAAACkYXZjMQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAEYAcAASAAAAEgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABj//wAAADNhdmNDAWQACv/hABlnZAAKrNlCmXv4wRAAAAAMAEAAAAMBA8SJmQEABGjxIf+AAAEaAAAADCBAKG5iKQABAAVo8SH/gAABGgAAAA5AQChOYilIAAAGaPEh/4AAARoAAAAPAEAoTmIpAAAAGj8IIAIQEBYQAAAAGHhwYWMAAAAAAAAAAgAAAAEAABAOAAAAABxhdmMxAAAAAAAAAgAAAAEAABAsAAAAAAEYAXAAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAzYXZjQwFkAAr/4QAZZmQACqzZQpl7+MEQAAAACXwAAAgIDC9mAAABGjxIf+AAAEaAAAAMEEAobmIpAAEABWjxIf+AAAEaAAAADkBAKE5iKUgAAAZo8SH/gAABGgAAAA8AQChOYikAAAAaPwggAhAQFhAAAAAYeHBhYwAAAAAAAAACAAAAAwAAEA4AAAAAHGaDLZVzJGhE"; // const minimalVideoBase64 = "AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAAu1tZGF0AAACoAYF//+c3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTYgbG9va2FoZWFkX3RocmVhZHM9MSBzbGljZWRfdGhyZWFkcz0wIG5yPTAgZGVjaW1hdGU9MSBpbnRlcmxhY2VkPTAgYmx1cmF5X2NvbXBhdD0wIGNvbnN0cmFpbmVkX2ludHJhPTAgYmZyYW1lcz0zIGJfcHlyYW1pZD0yIGJfYWRhcHQ9MSBiX2JpYXM9MCBkaXJlY3Q9MSB3ZWlnaHRiPTEgb3Blbl9nb3A9MCB3ZWlnaHRwPTIga2V5aW50PTI1MCBrZXlpbnRfbWluPTEwIHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAKYWVpegAVpD//+e5VrHBPqGP9IjQ1ErQWdyI5BQAAAAMAAAMAAANiAAA/AAADAAA6xQS1AAFr6v7oCKDAAAADOwAAAwAAAwB7AAA9AAAAAwAACywAAAAABowDGBHE84cFC6BnGJObADwQ6JCSNs5wOEMFLFNXBALRqRK33vh/+kRBagRa/qE/YqRQ+kRCAUW1ZUB/q2Qb+kR2uP8I/0h2vxj5oJAxM94/hYtpIFoAAAADAAADAAlYABO0AAADAAADABRWN3xTBGgTAAAABgAAAwUYLJwAAQBxtSxpJ1CZT4dCZ/6RUgRo9IiAAAAABgCAAAAXc3R0cwAAAAAAAAABAAAAAQAAAAAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAFHN0c3oAAAAAAAAABAsAAAACAAAAFHN0Y28AAAAAAAAAAQAAAAEAAAABAAAAAQAAABRzdHNzAAAAAAAAAAEAAAABAAAAEHNzaWEAAAAAABBzc2QAAAAAAAAAAQAAAA8AAAACbWRpYQAAAABtZGhkAAAAABdoZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAAVmlkZW9IYW5kbGVyAAAAAmxtaW5mAAAAFHZtaGQAAAABAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAAIsc3RibAAAALRzdHNkAAAAAAAAAAEAAACkYXZjMQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAEYAcAASAAAAEgAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABj//wAAADNhdmNDAWQACv/hABlnZAAKrNlCmXv4wRAAAAAMAEAAAAMBA8SJmQEABGjxIf+AAAEaAAAADCBAKG5iKQABAAVo8SH/gAABGgAAAA5AQChOYilIAAAGaPEh/4AAARoAAAAPAEAoTmIpAAAAGj8IIAIQEBYQAAAAGHhwYWMAAAAAAAAAAgAAAAEAABAOAAAAABxhdmMxAAAAAAAAAgAAAAEAABAsAAAAAAEYAXAAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAzYXZjQwFkAAr/4QAZZmQACqzZQpl7+MEQAAAACXwAAAgIDC9mAAABGjxIf+AAAEaAAAAMEEAobmIpAAEABWjxIf+AAAEaAAAADkBAKE5iKUgAAAZo8SH/gAABGgAAAA8AQChOYikAAAAaPwggAhAQFhAAAAAYeHBhYwAAAAAAAAACAAAAAwAAEA4AAAAAHGaDLZVzJGhE";
// //
......
...@@ -26,6 +26,9 @@ import { MediaType, parseMediaType } from "../../types/mediatype.mjs"; ...@@ -26,6 +26,9 @@ import { MediaType, parseMediaType } from "../../types/mediatype.mjs";
import {MarkdownToHTML} from "../../text/markdown-parser.mjs"; import {MarkdownToHTML} from "../../text/markdown-parser.mjs";
import "../layout/tabs.mjs"; import "../layout/tabs.mjs";
import "./viewer/message.mjs"; import "./viewer/message.mjs";
import {getLocaleOfDocument} from "../../dom/locale.mjs";
import {Button} from "../form/button.mjs";
import {findTargetElementFromEvent} from "../../dom/events.mjs";
export {Viewer}; export {Viewer};
...@@ -83,16 +86,19 @@ class Viewer extends CustomElement { ...@@ -83,16 +86,19 @@ class Viewer extends CustomElement {
classes: { classes: {
viewer: "", viewer: "",
}, },
labels: getLabels(),
renderers: { renderers: {
image: this.setImage, image: this.setImage,
html: this.setHTML, html: this.setHTML,
pdf: this.setPDF, pdf: this.setPDF,
download: this.setDownload,
plaintext: this.setPlainText, plaintext: this.setPlainText,
markdown: this.setMarkdown, markdown: this.setMarkdown,
audio: this.setAudio, audio: this.setAudio,
video: this.setVideo, video: this.setVideo,
message: this.setMessage, message: this.setMessage,
}, },
}); });
} }
...@@ -201,7 +207,14 @@ class Viewer extends CustomElement { ...@@ -201,7 +207,14 @@ class Viewer extends CustomElement {
break; break;
default: default:
this.setOption("content", content);
// Handle octet-stream as a generic binary data type
if (checkRenderer("download", mediaTypeObject.toString())) {
renderers.download.call(this, content);
break;
}
this.setOption("content", content + "!!");
break; break;
} }
break; break;
...@@ -428,6 +441,49 @@ class Viewer extends CustomElement { ...@@ -428,6 +441,49 @@ class Viewer extends CustomElement {
this.setOption("content", html); this.setOption("content", html);
} }
/**
* Sets the download functionality for the viewer.
* @param data
* @param filename
*/
setDownload(data, filename = "download") {
const rawData = data;
if (isBlob(data)) {
data = URL.createObjectURL(data);
} else if (isURL(data)) {
// nothing to do
} else if (isString(data)) {
// nothing to do
} else {
this.dispatchEvent(
new CustomEvent("viewer-error", {detail: "Blob or URL expected"}),
);
throw new Error("Blob or URL expected");
}
const button = `<monster-button data-monster-role="download">` + this.getOption('labels.download') + `</monster-button>`;
this.setOption("content", button);
this.addEventListener("click", (event) => {
const element = findTargetElementFromEvent(event, "data-monster-role", "download");
if (element instanceof Button) {
const anchor = document.createElement("a");
anchor.href = URL.createObjectURL(new Blob([rawData]))
anchor.download = filename;
anchor.style.display = "none";
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
}
})
}
/** /**
* Sets the content for displaying an email message. * Sets the content for displaying an email message.
* The data is expected to be an object with a structure containing * The data is expected to be an object with a structure containing
...@@ -705,6 +761,110 @@ function initEventHandler() { ...@@ -705,6 +761,110 @@ function initEventHandler() {
return this; return this;
} }
function getLabels() {
switch (getLocaleOfDocument().language) {
case "de": // German
return {
download: "Herunterladen",
};
case "es": // Spanish
return {
download: "Descargar",
};
case "zh": // Mandarin
return {
download: "下载",
};
case "hi": // Hindi
return {
download: "下载",
};
case "bn": // Bengali
return {
download: "ডাউনলোড",
};
case "pt": // Portuguese
return {
download: "Baixar",
};
case "ru": // Russian
return {
download: "Скачать",
};
case "ja": // Japanese
return {
download: "ダウンロード",
};
case "pa": // Western Punjabi
return {
download: "ਡਾਊਨਲੋਡ",
};
case "mr": // Marathi
return {
download: "डाउनलोड",
};
case "fr": // French
return {
download: "Télécharger",
};
case "it": // Italian
return {
download: "Scarica",
};
case "nl": // Dutch
return {
download: "Downloaden",
};
case "sv": // Swedish
return {
download: "Ladda ner",
};
case "pl": // Polish
return {
download: "Ściągnij",
};
case "da": // Danish
return {
download: "Lad ned",
};
case "fi": // Finnish
return {
download: "Lataa",
};
case "no": // Norwegian
return {
download: "Laste ned",
};
case "cs": // Czech
return {
download: "Stáhnout",
};
default:
return {
download: "Download",
};
}
}
/** /**
* @private * @private
* @return {string} * @return {string}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment