92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
|
|
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
|
|
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(
|
|
history: IHistoryState[],
|
|
historyCurrentStep: number,
|
|
configuration: IConfiguration
|
|
): void {
|
|
const exportName = 'state.json';
|
|
const spaces = import.meta.env.DEV
|
|
? 4
|
|
: 0;
|
|
const editorState: IEditorState = {
|
|
history,
|
|
historyCurrentStep,
|
|
configuration
|
|
};
|
|
|
|
// 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();
|
|
}
|