svg-layout-designer-react/src/Components/Editor/Actions/Save.ts

83 lines
2.9 KiB
TypeScript

import { GetCircularReplacer } from '../../../utils/saveload';
import { ID } from '../../SVG/SVG';
import { type IEditorState } from '../../../Interfaces/IEditorState';
import { SHOW_SELECTOR_TEXT } from '../../../utils/default';
export function SaveEditorAsJSON(
editorState: IEditorState
): void {
const exportName = 'state.json';
const spaces = import.meta.env.DEV
? 4
: 0;
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (window.Worker) {
// use webworker for the stringify to avoid freezing
const myWorker = new Worker('workers/worker.js');
myWorker.postMessage({ editorState, spaces });
myWorker.onmessage = (event) => {
const data = event.data;
const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(data)}`;
CreateDownloadNode(exportName, dataStr);
myWorker.terminate();
};
return;
}
const data = JSON.stringify(editorState, GetCircularReplacer(), spaces);
const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(data)}`;
CreateDownloadNode(exportName, dataStr);
}
export function SaveEditorAsSVG(): void {
const svgWrapper = document.getElementById(ID) as HTMLElement;
let svg = svgWrapper.querySelector('svg') as SVGSVGElement;
if (svg === undefined) {
throw new Error('[SaveEditorAsSVG] Missing <svg> element');
}
// Recover svg from SVG Viewer
svg = svg.cloneNode(true) as SVGSVGElement;
svg.removeAttribute('height');
svg.removeAttribute('width');
const mainSvg = svg.children[1].children;
svg.replaceChildren(...mainSvg);
// remove the selector
// TODO: Fix this with SelectorMode != Nothing or with some html magic
const group = svg.children[svg.children.length - 1];
group.removeChild(group.children[group.children.length - 1]);
if (SHOW_SELECTOR_TEXT) {
group.removeChild(group.children[group.children.length - 1]);
}
// get svg source.
const serializer = new XMLSerializer();
let source = serializer.serializeToString(svg);
// add name spaces.
if (source.match(/^<svg[^>]+xmlns="http:\/\/www\.w3\.org\/2000\/svg"/) == null) {
source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
}
if (source.match(/^<svg[^>]+"http:\/\/www\.w3\.org\/1999\/xlink"/) == null) {
source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
}
// add xml declaration
source = `<?xml version="1.0" standalone="no"?>\r\n${source}`;
// convert svg source to URI data scheme.
const url = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(source)}`;
CreateDownloadNode('state.svg', url);
}
function CreateDownloadNode(filename: string, datastring: string): void {
const downloadAnchorNode = document.createElement('a');
downloadAnchorNode.href = datastring;
downloadAnchorNode.download = filename;
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
downloadAnchorNode.remove();
}