Merge pull request #622 from SVG-Edit/issues/603
commit
e83fa3f97e
|
@ -0,0 +1,78 @@
|
|||
/* globals seAlert */
|
||||
/**
|
||||
* @file ext-opensave.js
|
||||
*
|
||||
* @license MIT
|
||||
*
|
||||
* @copyright 2020 OptimistikSAS
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {module:svgcanvas.EventHandler}
|
||||
* @param {external:Window} wind
|
||||
* @param {module:svgcanvas.SvgCanvas#event:saved} svg The SVG source
|
||||
* @listens module:svgcanvas.SvgCanvas#event:saved
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'opensave',
|
||||
init ({ encode64 }) {
|
||||
const svgEditor = this;
|
||||
|
||||
svgEditor.setCustomHandlers({
|
||||
save (win, svg) {
|
||||
this.showSaveWarning = false;
|
||||
|
||||
// by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs)
|
||||
// can just provide their own custom save handler and might not want the XML prolog
|
||||
svg = '<?xml version="1.0"?>\n' + svg;
|
||||
|
||||
// Since saving SVGs by opening a new window was removed in Chrome use artificial link-click
|
||||
// https://stackoverflow.com/questions/45603201/window-is-not-allowed-to-navigate-top-frame-navigations-to-data-urls
|
||||
const a = document.createElement('a');
|
||||
a.href = 'data:image/svg+xml;base64,' + encode64(svg);
|
||||
a.download = 'icon.svg';
|
||||
a.style.display = 'none';
|
||||
document.body.append(a); // Need to append for Firefox
|
||||
|
||||
a.click();
|
||||
|
||||
// Alert will only appear the first time saved OR the
|
||||
// first time the bug is encountered
|
||||
const done = this.configObj.pref('save_notice_done');
|
||||
|
||||
if (done !== 'all') {
|
||||
const note = svgEditor.i18next.t('notification.saveFromBrowser', { type: 'SVG' });
|
||||
|
||||
this.configObj.pref('save_notice_done', 'all');
|
||||
if (done !== 'part') {
|
||||
seAlert(note);
|
||||
}
|
||||
}
|
||||
},
|
||||
async open () {
|
||||
const ok = await this.openPrep();
|
||||
if (ok === 'Cancel') { return; }
|
||||
this.svgCanvas.clear();
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.addEventListener('change', (e) => {
|
||||
// getting a hold of the file reference
|
||||
const file = e.target.files[0];
|
||||
// setting up the reader
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(file, 'UTF-8');
|
||||
// here we tell the reader what to do when it's done reading...
|
||||
reader.addEventListener('load', async (readerEvent) => {
|
||||
const content = readerEvent.target.result;
|
||||
await this.loadSvgString(content);
|
||||
this.updateCanvas();
|
||||
});
|
||||
});
|
||||
input.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
|
@ -101,7 +101,109 @@ exports[`use all parts of svg-edit > check tool_shape #0`] = `
|
|||
</svg>
|
||||
`;
|
||||
|
||||
exports[`use all parts of svg-edit > check mode_connect #0`] = `
|
||||
exports[`use all parts of svg-edit > check tool_rect_square #0`] = `
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
width="640"
|
||||
height="480"
|
||||
id="svgcontent"
|
||||
overflow="visible"
|
||||
x="640"
|
||||
y="480"
|
||||
viewBox="0 0 640 480"
|
||||
>
|
||||
<g class="layer" style="pointer-events:all">
|
||||
<title style="pointer-events:inherit">Layer 1</title>
|
||||
<line
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
style="pointer-events:inherit"
|
||||
x1="200"
|
||||
y1="200"
|
||||
x2="220"
|
||||
y2="220"
|
||||
id="svg_1"
|
||||
fill-opacity="1"
|
||||
stroke-opacity="1"
|
||||
transform="rotate(43.2643 210 210)"
|
||||
></line>
|
||||
<path
|
||||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
style="pointer-events:inherit"
|
||||
d="m309.60653833763354,262.7975086895094 c37.05917105721012,-106.31729401658639 182.2582183141481,0 0,136.6936637356111 c-182.2582183141481,-136.6936637356111 -37.05917105721012,-243.0109577521975 0,-136.6936637356111 z"
|
||||
id="svg_2"
|
||||
fill-opacity="1"
|
||||
stroke-opacity="1"
|
||||
></path>
|
||||
<rect
|
||||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
opacity="0.5"
|
||||
style="pointer-events:inherit"
|
||||
x="296"
|
||||
y="136"
|
||||
width="150"
|
||||
height="120"
|
||||
id="svg_3"
|
||||
>
|
||||
<animate
|
||||
attributeName="opacity"
|
||||
begin="indefinite"
|
||||
dur="0.2"
|
||||
fill="freeze"
|
||||
to="1"
|
||||
></animate>
|
||||
</rect>
|
||||
<rect
|
||||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
opacity="0.5"
|
||||
style="pointer-events:inherit"
|
||||
x="446"
|
||||
y="76"
|
||||
width="180"
|
||||
height="180"
|
||||
id="svg_4"
|
||||
>
|
||||
<animate
|
||||
attributeName="opacity"
|
||||
begin="indefinite"
|
||||
dur="0.2"
|
||||
fill="freeze"
|
||||
to="1"
|
||||
></animate>
|
||||
</rect>
|
||||
<rect
|
||||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
opacity="0.5"
|
||||
style="pointer-events:inherit"
|
||||
x="216"
|
||||
y="156"
|
||||
width="100"
|
||||
height="100"
|
||||
id="svg_5"
|
||||
>
|
||||
<animate
|
||||
attributeName="opacity"
|
||||
begin="indefinite"
|
||||
dur="0.2"
|
||||
fill="freeze"
|
||||
to="1"
|
||||
></animate>
|
||||
</rect>
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`use all parts of svg-edit > check tool_image #0`] = `
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
|
@ -156,13 +258,37 @@ exports[`use all parts of svg-edit > check mode_connect #0`] = `
|
|||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
opacity="0.5"
|
||||
style="pointer-events:inherit"
|
||||
x="446"
|
||||
y="76"
|
||||
width="180"
|
||||
height="180"
|
||||
id="svg_4"
|
||||
fill-opacity="1"
|
||||
stroke-opacity="1"
|
||||
></rect>
|
||||
<rect
|
||||
fill="#FF0000"
|
||||
stroke="#000000"
|
||||
stroke-width="5"
|
||||
style="pointer-events:inherit"
|
||||
x="216"
|
||||
y="156"
|
||||
width="100"
|
||||
height="100"
|
||||
id="svg_5"
|
||||
fill-opacity="1"
|
||||
stroke-opacity="1"
|
||||
></rect>
|
||||
<image
|
||||
x="296"
|
||||
y="176"
|
||||
width="20"
|
||||
height="20"
|
||||
id="svg_6"
|
||||
opacity="0.5"
|
||||
style="pointer-events:inherit"
|
||||
xlink:href="./images/logo.svg"
|
||||
>
|
||||
<animate
|
||||
attributeName="opacity"
|
||||
|
@ -171,7 +297,7 @@ exports[`use all parts of svg-edit > check mode_connect #0`] = `
|
|||
fill="freeze"
|
||||
to="1"
|
||||
></animate>
|
||||
</rect>
|
||||
</image>
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
|
|
|
@ -49,7 +49,7 @@ describe('use all parts of svg-edit', function () {
|
|||
.trigger('mouseup', { force: true });
|
||||
cy.get('#svgcontent').toMatchSnapshot();
|
||||
});
|
||||
it('check mode_connect', function () {
|
||||
it('check tool_rect_square', function () {
|
||||
cy.get('#tool_rect').click({ force: true });
|
||||
cy.get('#svgcontent')
|
||||
.trigger('mousedown', 100, -60, { force: true })
|
||||
|
@ -60,24 +60,32 @@ describe('use all parts of svg-edit', function () {
|
|||
.trigger('mousedown', 250, -60, { force: true })
|
||||
.trigger('mousemove', 430, 120, { force: true })
|
||||
.trigger('mouseup', { force: true });
|
||||
cy.get('#tool_select').click({ force: true });
|
||||
cy.get('#mode_connect').click({ force: true });
|
||||
|
||||
cy.get('#tool_fhrect')
|
||||
.click({ force: true });
|
||||
cy.get('#svgcontent')
|
||||
.trigger('mousedown', -10, -10, { force: true })
|
||||
.trigger('mousemove', -180, -180, { force: true })
|
||||
.trigger('mouseup', { force: true });
|
||||
.trigger('mousedown', 20, 80, { force: true })
|
||||
.trigger('mousemove', 120, 80, { force: true })
|
||||
.trigger('mousemove', 120, 180, { force: true })
|
||||
.trigger('mousemove', 20, 180, { force: true })
|
||||
.trigger('mousemove', 20, 80, { force: true })
|
||||
.trigger('mouseup', 20, 80, { force: true });
|
||||
cy.get('#svgcontent').toMatchSnapshot();
|
||||
});
|
||||
/* it('check tool_image', function () {
|
||||
it('check tool_image', function () {
|
||||
|
||||
cy.get('#tool_image').click({ force: true });
|
||||
cy.get('#svgcontent')
|
||||
.trigger('mousemove', 100, 100, { force: true })
|
||||
.trigger('mousedown', 100, 100, { force: true })
|
||||
.trigger('mousemove', 120, 120, { force: true })
|
||||
.trigger('mouseup', { force: true });
|
||||
cy.on('window:confirm', () => true);
|
||||
// eslint-disable-next-line promise/catch-or-return
|
||||
cy.window()
|
||||
// eslint-disable-next-line promise/always-return
|
||||
.then(($win) => {
|
||||
cy.stub($win, 'prompt').returns('./images/logo.svg');
|
||||
cy.contains('OK');
|
||||
});
|
||||
cy.get('#svgcontent').toMatchSnapshot();
|
||||
}); */
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"license": "(MIT AND Apache-2.0 AND ISC AND LGPL-3.0-or-later AND X11)",
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "7.12.1",
|
||||
"browser-fs-access": "^0.20.4",
|
||||
"canvg": "3.0.7",
|
||||
"core-js": "3.16.2",
|
||||
"elix": "15.0.0",
|
||||
|
@ -5299,6 +5300,11 @@
|
|||
"node": ">= 10.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/browser-fs-access": {
|
||||
"version": "0.20.4",
|
||||
"resolved": "https://registry.npmjs.org/browser-fs-access/-/browser-fs-access-0.20.4.tgz",
|
||||
"integrity": "sha512-rSbY1AIoDe+fvYZ1LiRDdKBnytfsd1nN/GKS/DRZAhaJkz3cfbp14IHw5lk4FFWBelD6Sw6EtdnAI990ZuBZjg=="
|
||||
},
|
||||
"node_modules/browser-pack": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz",
|
||||
|
@ -26396,6 +26402,11 @@
|
|||
"duplexer": "0.1.1"
|
||||
}
|
||||
},
|
||||
"browser-fs-access": {
|
||||
"version": "0.20.4",
|
||||
"resolved": "https://registry.npmjs.org/browser-fs-access/-/browser-fs-access-0.20.4.tgz",
|
||||
"integrity": "sha512-rSbY1AIoDe+fvYZ1LiRDdKBnytfsd1nN/GKS/DRZAhaJkz3cfbp14IHw5lk4FFWBelD6Sw6EtdnAI990ZuBZjg=="
|
||||
},
|
||||
"browser-pack": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz",
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
],
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "7.12.1",
|
||||
"browser-fs-access": "^0.20.4",
|
||||
"canvg": "3.0.7",
|
||||
"core-js": "3.16.2",
|
||||
"elix": "15.0.0",
|
||||
|
|
|
@ -180,38 +180,6 @@ class Editor extends EditorStartup {
|
|||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allows one to override default SVGEdit `open`, `save`, and
|
||||
* `export` editor behaviors.
|
||||
* @function module:SVGthis.setCustomHandlers
|
||||
* @param {module:SVGthis.CustomHandler} opts Extension mechanisms may call `setCustomHandlers` with three functions: `opts.open`, `opts.save`, and `opts.exportImage`
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {PlainObject} opts
|
||||
* @returns {Promise<PlainObject>}
|
||||
*/
|
||||
setCustomHandlers(opts) {
|
||||
return this.ready(() => {
|
||||
if (opts.open) {
|
||||
this.svgCanvas.open = opts.open.bind(this);
|
||||
}
|
||||
if (opts.save) {
|
||||
this.showSaveWarning = false;
|
||||
this.svgCanvas.bind('saved', opts.save.bind(this));
|
||||
}
|
||||
if (opts.exportImage) {
|
||||
this.customExportImage = opts.exportImage.bind(this);
|
||||
this.svgCanvas.bind('exported', this.customExportImage); // canvg and our RGBColor will be available to the method
|
||||
}
|
||||
if (opts.exportPDF) {
|
||||
this.customExportPDF = opts.exportPDF.bind(this);
|
||||
this.svgCanvas.bind('exportedPDF', this.customExportPDF); // jsPDF and our RGBColor will be available to the method
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @function module:SVGthis.randomizeIds
|
||||
* @param {boolean} arg
|
||||
|
|
|
@ -129,20 +129,6 @@ class MainMenu {
|
|||
this.editor.updateCanvas();
|
||||
this.hidePreferences();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
clickSave() {
|
||||
// In the future, more options can be provided here
|
||||
const saveOpts = {
|
||||
images: this.editor.configObj.pref("img_save"),
|
||||
round_digits: 6
|
||||
};
|
||||
this.editor.svgCanvas.save(saveOpts);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param e
|
||||
|
@ -210,16 +196,6 @@ class MainMenu {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, this.editor.svgCanvas.open() is a no-op. It is up to an extension
|
||||
* mechanism (opera widget, etc.) to call `setCustomHandlers()` which
|
||||
* will make it do something.
|
||||
* @returns {void}
|
||||
*/
|
||||
clickOpen() {
|
||||
this.editor.svgCanvas.open();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
|
@ -307,9 +283,6 @@ class MainMenu {
|
|||
// eslint-disable-next-line no-unsanitized/property
|
||||
template.innerHTML = `
|
||||
<se-menu id="main_button" label="SVG-Edit" src="${imgPath}/logo.svg" alt="logo">
|
||||
<se-menu-item id="tool_clear" label="${i18next.t('tools.new_doc')}" shortcut="N" src="${imgPath}/new.svg"></se-menu-item>
|
||||
<se-menu-item id="tool_open" label="${i18next.t('tools.open_doc')}" src="${imgPath}/open.svg"></se-menu-item>
|
||||
<se-menu-item id="tool_save" label="${i18next.t('tools.save_doc')}" shortcut="S" src="${imgPath}/saveImg.svg"></se-menu-item>
|
||||
<se-menu-item id="tool_import" label="${i18next.t('tools.import_doc')}" src="${imgPath}/importImg.svg"></se-menu-item>
|
||||
<se-menu-item id="tool_export" label="${i18next.t('tools.export_img')}" src="${imgPath}/export.svg"></se-menu-item>
|
||||
<se-menu-item id="tool_docprops" label="${i18next.t('tools.docprops')}" shortcut="D" src="${imgPath}/docprop.svg"></se-menu-item>
|
||||
|
@ -324,29 +297,10 @@ class MainMenu {
|
|||
* Associate all button actions as well as non-button keyboard shortcuts.
|
||||
*/
|
||||
|
||||
$id("tool_clear").addEventListener("click", this.clickClear.bind(this));
|
||||
$id("tool_open").addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
this.clickOpen();
|
||||
window.dispatchEvent(new CustomEvent("openImage"));
|
||||
});
|
||||
$id("tool_import").addEventListener("click", () => {
|
||||
this.clickImport();
|
||||
window.dispatchEvent(new CustomEvent("importImages"));
|
||||
});
|
||||
$id("tool_save").addEventListener(
|
||||
"click",
|
||||
function() {
|
||||
const $editorDialog = $id("se-svg-editor-dialog");
|
||||
const editingsource = $editorDialog.getAttribute("dialog") === "open";
|
||||
if (editingsource) {
|
||||
this.saveSourceEditor();
|
||||
} else {
|
||||
this.clickSave();
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
// this.clickExport.bind(this)
|
||||
$id("tool_export").addEventListener("click", function() {
|
||||
document
|
||||
.getElementById("se-export-dialog")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* globals seAlert */
|
||||
/* globals seConfirm */
|
||||
/**
|
||||
* @file ext-opensave.js
|
||||
*
|
||||
|
@ -15,64 +15,167 @@
|
|||
* @listens module:svgcanvas.SvgCanvas#event:saved
|
||||
* @returns {void}
|
||||
*/
|
||||
import { fileOpen, fileSave } from 'browser-fs-access';
|
||||
|
||||
const name = "opensave";
|
||||
let handle = null;
|
||||
|
||||
const loadExtensionTranslation = async function (svgEditor) {
|
||||
let translationModule;
|
||||
const lang = svgEditor.configObj.pref('lang');
|
||||
try {
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/${lang}.js`);
|
||||
} catch (_error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`Missing translation (${lang}) for ${name} - using 'en'`);
|
||||
// eslint-disable-next-line no-unsanitized/method
|
||||
translationModule = await import(`./locale/en.js`);
|
||||
}
|
||||
svgEditor.i18next.addResourceBundle(lang, 'translation', translationModule.default, true, true);
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'opensave',
|
||||
init ({ encode64 }) {
|
||||
name,
|
||||
async init(_S) {
|
||||
const svgEditor = this;
|
||||
const { imgPath } = svgEditor.configObj.curConfig;
|
||||
const { svgCanvas } = svgEditor;
|
||||
const { $id } = svgCanvas;
|
||||
await loadExtensionTranslation(svgEditor);
|
||||
|
||||
svgEditor.setCustomHandlers({
|
||||
save (win, svg) {
|
||||
this.showSaveWarning = false;
|
||||
/**
|
||||
* @fires module:svgcanvas.SvgCanvas#event:ext_onNewDocument
|
||||
* @returns {void}
|
||||
*/
|
||||
const clickClear = async function () {
|
||||
const [ x, y ] = svgEditor.configObj.curConfig.dimensions;
|
||||
const ok = await seConfirm(svgEditor.i18next.t('notification.QwantToClear'));
|
||||
if (ok === "Cancel") {
|
||||
return;
|
||||
}
|
||||
svgEditor.leftPanel.clickSelect();
|
||||
svgEditor.svgCanvas.clear();
|
||||
svgEditor.svgCanvas.setResolution(x, y);
|
||||
svgEditor.updateCanvas(true);
|
||||
svgEditor.zoomImage();
|
||||
svgEditor.layersPanel.populateLayers();
|
||||
svgEditor.topPanel.updateContextPanel();
|
||||
svgEditor.svgCanvas.runExtensions("onNewDocument");
|
||||
};
|
||||
|
||||
// by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs)
|
||||
// can just provide their own custom save handler and might not want the XML prolog
|
||||
svg = '<?xml version="1.0"?>\n' + svg;
|
||||
/**
|
||||
* By default, this.editor.svgCanvas.open() is a no-op. It is up to an extension
|
||||
* mechanism (opera widget, etc.) to call `setCustomHandlers()` which
|
||||
* will make it do something.
|
||||
* @returns {void}
|
||||
*/
|
||||
const clickOpen = async function () {
|
||||
// ask user before clearing an unsaved SVG
|
||||
const response = await svgEditor.openPrep();
|
||||
if (response === 'Cancel') { return; }
|
||||
svgCanvas.clear();
|
||||
try {
|
||||
const blob = await fileOpen({
|
||||
mimeTypes: [ 'image/*' ]
|
||||
});
|
||||
const svgContent = await blob.text();
|
||||
await svgEditor.loadSvgString(svgContent);
|
||||
svgEditor.updateCanvas();
|
||||
} catch (err) {
|
||||
if (err.name !== 'AbortError') {
|
||||
return console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Since saving SVGs by opening a new window was removed in Chrome use artificial link-click
|
||||
// https://stackoverflow.com/questions/45603201/window-is-not-allowed-to-navigate-top-frame-navigations-to-data-urls
|
||||
const a = document.createElement('a');
|
||||
a.href = 'data:image/svg+xml;base64,' + encode64(svg);
|
||||
a.download = 'icon.svg';
|
||||
a.style.display = 'none';
|
||||
document.body.append(a); // Need to append for Firefox
|
||||
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
|
||||
const byteCharacters = atob(b64Data);
|
||||
const byteArrays = [];
|
||||
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
|
||||
const slice = byteCharacters.slice(offset, offset + sliceSize);
|
||||
const byteNumbers = new Array(slice.length);
|
||||
for (let i = 0; i < slice.length; i++) {
|
||||
byteNumbers[i] = slice.charCodeAt(i);
|
||||
}
|
||||
const byteArray = new Uint8Array(byteNumbers);
|
||||
byteArrays.push(byteArray);
|
||||
}
|
||||
const blob = new Blob(byteArrays, { type: contentType });
|
||||
return blob;
|
||||
};
|
||||
|
||||
a.click();
|
||||
|
||||
// Alert will only appear the first time saved OR the
|
||||
// first time the bug is encountered
|
||||
const done = this.configObj.pref('save_notice_done');
|
||||
|
||||
if (done !== 'all') {
|
||||
const note = svgEditor.i18next.t('notification.saveFromBrowser', { type: 'SVG' });
|
||||
|
||||
this.configObj.pref('save_notice_done', 'all');
|
||||
if (done !== 'part') {
|
||||
seAlert(note);
|
||||
/**
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
const clickSave = async function (type, _) {
|
||||
const $editorDialog = $id("se-svg-editor-dialog");
|
||||
const editingsource = $editorDialog.getAttribute("dialog") === "open";
|
||||
if (editingsource) {
|
||||
svgEditor.saveSourceEditor();
|
||||
} else {
|
||||
// In the future, more options can be provided here
|
||||
const saveOpts = {
|
||||
images: svgEditor.configObj.pref("img_save"),
|
||||
round_digits: 6
|
||||
};
|
||||
// remove the selected outline before serializing
|
||||
svgCanvas.clearSelection();
|
||||
// Update save options if provided
|
||||
if (saveOpts) {
|
||||
const saveOptions = svgCanvas.mergeDeep(svgCanvas.getSvgOption(), saveOpts);
|
||||
for (const [ key, value ] of Object.entries(saveOptions)) {
|
||||
svgCanvas.setSvgOption(key, value);
|
||||
}
|
||||
}
|
||||
svgCanvas.setSvgOption('apply', true);
|
||||
|
||||
// no need for doctype, see https://jwatt.org/svg/authoring/#doctype-declaration
|
||||
const svg = '<?xml version="1.0"?>\n' + svgCanvas.svgCanvasToString();
|
||||
const b64Data = svgCanvas.encode64(svg);
|
||||
const blob = b64toBlob(b64Data, 'image/svg+xml');
|
||||
try {
|
||||
if(type === "save" && handle !== null) {
|
||||
const throwIfExistingHandleNotGood = false;
|
||||
handle = await fileSave(blob, {
|
||||
fileName: 'icon.svg',
|
||||
extensions: [ '.svg' ]
|
||||
}, handle, throwIfExistingHandleNotGood);
|
||||
} else {
|
||||
handle = await fileSave(blob, {
|
||||
fileName: 'icon.svg',
|
||||
extensions: [ '.svg' ]
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.name !== 'AbortError') {
|
||||
return console.error(err);
|
||||
}
|
||||
}
|
||||
},
|
||||
async open () {
|
||||
const ok = await this.openPrep();
|
||||
if (ok === 'Cancel') { return; }
|
||||
this.svgCanvas.clear();
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.addEventListener('change', (e) => {
|
||||
// getting a hold of the file reference
|
||||
const file = e.target.files[0];
|
||||
// setting up the reader
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(file, 'UTF-8');
|
||||
// here we tell the reader what to do when it's done reading...
|
||||
reader.addEventListener('load', async (readerEvent) => {
|
||||
const content = readerEvent.target.result;
|
||||
await this.loadSvgString(content);
|
||||
this.updateCanvas();
|
||||
});
|
||||
});
|
||||
input.click();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
name: svgEditor.i18next.t(`${name}:name`),
|
||||
// The callback should be used to load the DOM with the appropriate UI items
|
||||
callback() {
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
const buttonTemplate = `
|
||||
<se-menu-item id="tool_clear" label="${svgEditor.i18next.t('opensave.new_doc')}" shortcut="N" src="${imgPath}/new.svg"></se-menu-item>`;
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), buttonTemplate, 0);
|
||||
const openButtonTemplate = `<se-menu-item id="tool_open" label="${svgEditor.i18next.t('opensave.open_image_doc')}" src="${imgPath}/open.svg"></se-menu-item>`;
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), openButtonTemplate, 1);
|
||||
const saveButtonTemplate = `<se-menu-item id="tool_save" label="${svgEditor.i18next.t('opensave.save_doc')}" shortcut="S" src="${imgPath}/saveImg.svg"></se-menu-item>`;
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), saveButtonTemplate, 2);
|
||||
const saveAsButtonTemplate = `<se-menu-item id="tool_save_as" label="${svgEditor.i18next.t('opensave.save_as_doc')}" src="${imgPath}/saveImg.svg"></se-menu-item>`;
|
||||
svgCanvas.insertChildAtIndex($id('main_button'), saveAsButtonTemplate, 3);
|
||||
// handler
|
||||
$id("tool_clear").addEventListener("click", clickClear.bind(this));
|
||||
$id("tool_open").addEventListener("click", clickOpen.bind(this));
|
||||
$id("tool_save").addEventListener("click", clickSave.bind(this, "save"));
|
||||
$id("tool_save_as").addEventListener("click", clickSave.bind(this, "saveas"));
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
opensave: {
|
||||
new_doc: 'New Image',
|
||||
open_image_doc: 'Open SVG',
|
||||
save_doc: 'Save SVG',
|
||||
save_as_doc: 'Save as SVG'
|
||||
}
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
opensave: {
|
||||
new_doc: 'Nouvelle image',
|
||||
open_image_doc: 'Ouvrir le SVG',
|
||||
save_doc: 'Enregistrer l\'image',
|
||||
save_as_doc: 'Enregistrer en tant qu\'image'
|
||||
}
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
opensave: {
|
||||
new_doc: '新图片',
|
||||
open_image_doc: '打开 SVG',
|
||||
save_doc: '保存图像',
|
||||
save_as_doc: '另存为图像'
|
||||
}
|
||||
};
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'grootste voorwerp',
|
||||
selected_objects: 'verkose voorwerpe',
|
||||
smallest_object: 'kleinste voorwerp',
|
||||
new_doc: 'Nuwe Beeld',
|
||||
open_doc: 'Open Beeld',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Slaan Beeld',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Rig Middel',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'أكبر كائن',
|
||||
selected_objects: 'انتخب الأجسام',
|
||||
smallest_object: 'أصغر كائن',
|
||||
new_doc: 'صورة جديدة',
|
||||
open_doc: 'فتح الصورة',
|
||||
export_img: 'Export',
|
||||
save_doc: 'حفظ صورة',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'محاذاة القاع',
|
||||
align_center: 'مركز محاذاة',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'largest object',
|
||||
selected_objects: 'selected objects',
|
||||
smallest_object: 'smallest object',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Open SVG',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Align Center',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'найбуйнейшы аб'ект',
|
||||
selected_objects: 'выбранымі аб'ектамі',
|
||||
smallest_object: 'маленькі аб'ект',
|
||||
new_doc: 'Новае выява',
|
||||
open_doc: 'Адкрыць выява',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Захаваць малюнак',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Лінаваць па ніжнім краю',
|
||||
align_center: 'Лінаваць па цэнтру',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'най-големият обект',
|
||||
selected_objects: 'избраните обекти',
|
||||
smallest_object: 'най-малката обект',
|
||||
new_doc: 'Ню Имидж',
|
||||
open_doc: 'Отворете изображението',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Привеждане Отдолу',
|
||||
align_center: 'Подравняване в средата',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Obrir imatge',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Guardar imatge',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Alinear baix',
|
||||
align_center: 'Alinear al centre',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Delwedd Agored',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Cadw Delwedd',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Alinio Gwaelod',
|
||||
align_center: 'Alinio Center',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'største objekt',
|
||||
selected_objects: 'valgte objekter',
|
||||
smallest_object: 'mindste objekt',
|
||||
new_doc: 'Nyt billede',
|
||||
open_doc: 'Open SVG',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Gem billede',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Juster Bottom',
|
||||
align_center: 'Centrer',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Άνοιγμα εικόνας',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Αποθήκευση εικόνας',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Στοίχισηκάτω',
|
||||
align_center: 'Στοίχισηστοκέντρο',
|
||||
|
|
|
@ -108,11 +108,8 @@ export default {
|
|||
largest_object: 'largest object',
|
||||
selected_objects: 'selected objects',
|
||||
smallest_object: 'smallest object',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Open SVG',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Align Center',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Pildi avamine',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Salvesta pilt',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Viia Bottom',
|
||||
align_center: 'Keskele joondamine',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'باز کردن تصویر ',
|
||||
export_img: 'Export',
|
||||
save_doc: 'ذخیره تصویر ',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'تراز پایین',
|
||||
align_center: 'وسط چین',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'Suurin kohde',
|
||||
selected_objects: 'valittujen objektien',
|
||||
smallest_object: 'pienin kohde',
|
||||
new_doc: 'Uusi kuva',
|
||||
open_doc: 'Avaa kuva',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Keskitä',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Ôfbielding iepenje',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Ôfbielding bewarje',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Ûnder útlijne',
|
||||
align_center: 'Midden útlijne',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Íomhá Oscailte',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Sábháil Íomhá',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Cineál Bun',
|
||||
align_center: 'Ailínigh sa Lár',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Abrir Imaxe',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Gardar Imaxe',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align bottom',
|
||||
align_center: 'Centrar',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'פתח תמונה',
|
||||
export_img: 'Export',
|
||||
save_doc: 'שמור תמונה',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'יישור תחתון',
|
||||
align_center: 'ישור לאמצע',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'छवि खोलें',
|
||||
export_img: 'Export',
|
||||
save_doc: 'सहेजें छवि',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'तलमेंपंक्तिबद्धकरें',
|
||||
align_center: 'मध्य में समंजित करें',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Otvori sliku',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Spremanje slike',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Poravnaj dolje',
|
||||
align_center: 'Centriraj',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Kép megnyitása',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Kép mentése más',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Alulra igazítás',
|
||||
align_center: 'Középre igazítás',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'largest object',
|
||||
selected_objects: 'elected objects',
|
||||
smallest_object: 'smallest object',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Open SVG',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Align Center',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'objek terbesar',
|
||||
selected_objects: 'objek terpilih',
|
||||
smallest_object: 'objek terkecil',
|
||||
new_doc: 'Gambar Baru',
|
||||
open_doc: 'Membuka Image',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Rata Bottom',
|
||||
align_center: 'Rata Tengah',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'stærsti hlutinn',
|
||||
selected_objects: 'kjörinn hlutir',
|
||||
smallest_object: 'lítill hluti',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Opna mynd',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Spara Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Jafna Bottom',
|
||||
align_center: 'Jafna Center',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'イメージを開く',
|
||||
export_img: 'Export',
|
||||
save_doc: '画像を保存',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: '下揃え',
|
||||
align_center: '中央揃え',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: '오픈 이미지',
|
||||
export_img: 'Export',
|
||||
save_doc: '이미지 저장',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: '히프 정렬',
|
||||
align_center: '정렬 센터',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'didžiausias objektas',
|
||||
selected_objects: 'išrinktas objektai',
|
||||
smallest_object: 'mažiausias objektą',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Atidaryti atvaizdą',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Išsaugoti nuotrauką',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Lygiuoti apačioje',
|
||||
align_center: 'Lygiuoti',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'lielākais objekts',
|
||||
selected_objects: 'ievēlēts objekti',
|
||||
smallest_object: 'mazākais objekts',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Open SVG',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Līdzināt Bottom',
|
||||
align_center: 'Līdzināt uz centru',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Отвори слика',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Зачувај слика',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Центрирано',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'objek terbesar',
|
||||
selected_objects: 'objek terpilih',
|
||||
smallest_object: 'objek terkecil',
|
||||
new_doc: 'Imej Baru',
|
||||
open_doc: 'Membuka Image',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Rata Bottom',
|
||||
align_center: 'Rata Tengah',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'akbar oġġett',
|
||||
selected_objects: 'oġġetti elett',
|
||||
smallest_object: 'iżgħar oġġett',
|
||||
new_doc: 'Image New',
|
||||
open_doc: 'Open SVG',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Image Save',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Tallinja Bottom',
|
||||
align_center: 'Tallinja Center',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'største objekt',
|
||||
selected_objects: 'velges objekter',
|
||||
smallest_object: 'minste objekt',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Åpne Image',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Lagre bilde',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Midtstill',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Abrir Imagem',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Salvar Imagem',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Alinhar ao centro',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Otvoriť obrázok',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Uložiť obrázok',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Zarovnať element na stránku',
|
||||
align_bottom: 'Zarovnať dole',
|
||||
align_center: 'Zarovnať na stred',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'madh objekt',
|
||||
selected_objects: 'objektet e zgjedhur',
|
||||
smallest_object: 'objektit më të vogël',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Image Hapur',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Image Ruaj',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Align Center',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Отвори слике',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Сачувај слика',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Поравнај доле',
|
||||
align_center: 'Поравнај по центру',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'största objekt',
|
||||
selected_objects: 'valda objekt',
|
||||
smallest_object: 'minsta objektet',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Öppna bild',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Centrera',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'ukubwa object',
|
||||
selected_objects: 'waliochaguliwa vitu',
|
||||
smallest_object: 'minsta object',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Open SVG',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Align Center',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'largest object',
|
||||
selected_objects: 'selected objects',
|
||||
smallest_object: 'smallest object',
|
||||
new_doc: 'New Image',
|
||||
open_doc: 'Open SVG',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Align Center',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'ภาพเปิด',
|
||||
export_img: 'Export',
|
||||
save_doc: 'บันทึกรูปภาพ',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'ด้านล่างชิด',
|
||||
align_center: 'จัดแนวกึ่งกลาง',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Buksan ang Image',
|
||||
export_img: 'Export',
|
||||
save_doc: 'I-save ang Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Pantayin sa Ibaba',
|
||||
align_center: 'Pantayin sa Gitna',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Aç Resim',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Görüntüyü Kaydet',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Ortala',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Відкрити зображення',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Зберегти малюнок',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Вирівняти по нижньому краю',
|
||||
align_center: 'Вирівняти по центру',
|
||||
|
|
|
@ -107,11 +107,8 @@ export default {
|
|||
largest_object: 'lớn nhất đối tượng',
|
||||
selected_objects: 'bầu các đối tượng',
|
||||
smallest_object: 'nhỏ đối tượng',
|
||||
new_doc: 'Hình mới',
|
||||
open_doc: 'Mở Image',
|
||||
export_img: 'Export',
|
||||
save_doc: 'Save Image',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'Align Bottom',
|
||||
align_center: 'Căn giữa',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: 'Open בילד',
|
||||
export_img: 'Export',
|
||||
save_doc: 'היט בילד',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: 'יינרייען באָטטאָם',
|
||||
align_center: 'יינרייען צענטער',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: '打开图像',
|
||||
export_img: 'Export',
|
||||
save_doc: '保存图像',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: '底部对齐',
|
||||
align_center: '居中对齐',
|
||||
|
|
|
@ -111,7 +111,7 @@ export default {
|
|||
open_doc: '打開圖像',
|
||||
export_img: 'Export',
|
||||
save_doc: '保存圖像',
|
||||
import_doc: 'Import Image',
|
||||
import_doc: 'Import SVG',
|
||||
align_to_page: 'Align Element to Page',
|
||||
align_bottom: '底部對齊',
|
||||
align_center: '居中對齊',
|
||||
|
|
|
@ -191,6 +191,7 @@ class TopPanel {
|
|||
this.hideTool("container_panel");
|
||||
this.hideTool("use_panel");
|
||||
this.hideTool("a_panel");
|
||||
this.hideTool("xy_panel");
|
||||
if (elem) {
|
||||
const elname = elem.nodeName;
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ const svgWhiteList_ = {
|
|||
stop: [ 'class', 'id', 'offset', 'requiredFeatures', 'stop-opacity', 'style', 'systemLanguage', 'stop-color', 'gradientUnits', 'gradientTransform' ],
|
||||
svg: [ 'class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'version', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'xmlns:oi', 'oi:animations', 'y', 'stroke-linejoin', 'fill-rule', 'aria-label', 'stroke-width', 'fill-rule' ],
|
||||
switch: [ 'class', 'id', 'requiredFeatures', 'systemLanguage' ],
|
||||
symbol: [ 'class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'overflow', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox' ],
|
||||
symbol: [ 'class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'overflow', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox', 'width', 'height' ],
|
||||
text: [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y' ],
|
||||
textPath: [ 'class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href' ],
|
||||
title: [],
|
||||
|
|
|
@ -743,15 +743,17 @@ export const convertToGroup = function (elem) {
|
|||
// Not ideal, but works
|
||||
ts += ' translate(' + (pos.x || 0) + ',' + (pos.y || 0) + ')';
|
||||
|
||||
const prev = $elem.prev();
|
||||
const prev = $elem.previousElementSibling;
|
||||
|
||||
// Remove <use> element
|
||||
batchCmd.addSubCommand(new RemoveElementCommand($elem[0], $elem[0].nextSibling, $elem[0].parentNode));
|
||||
batchCmd.addSubCommand(new RemoveElementCommand($elem, $elem.nextElementSibling, $elem.parentNode));
|
||||
$elem.remove();
|
||||
|
||||
// See if other elements reference this symbol
|
||||
const svgcontent = elementContext_.getSVGContent();
|
||||
const hasMore = svgcontent.querySelectorAll('use:data(symbol)').length;
|
||||
// const hasMore = svgcontent.querySelectorAll('use:data(symbol)').length;
|
||||
// @todo review this logic
|
||||
const hasMore = svgcontent.querySelectorAll('use').length;
|
||||
|
||||
const g = elementContext_.getDOMDocument().createElementNS(NS.SVG, 'g');
|
||||
const childs = elem.childNodes;
|
||||
|
|
|
@ -678,31 +678,6 @@ export const embedImage = function (src) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Serializes the current drawing into SVG XML text and passes it to the 'saved' handler.
|
||||
* This function also includes the XML prolog. Clients of the `SvgCanvas` bind their save
|
||||
* function to the 'saved' event.
|
||||
* @function module:svgcanvas.SvgCanvas#save
|
||||
* @param {module:svgcanvas.SaveOptions} opts
|
||||
* @fires module:svgcanvas.SvgCanvas#event:saved
|
||||
* @returns {void}
|
||||
*/
|
||||
export const save = function (opts) {
|
||||
// remove the selected outline before serializing
|
||||
svgCanvas.clearSelection();
|
||||
// Update save options if provided
|
||||
if (opts) {
|
||||
const saveOptions = svgCanvas.mergeDeep(svgContext_.getSvgOption(), opts);
|
||||
for (const [ key, value ] of Object.entries(saveOptions)) {
|
||||
svgContext_.setSvgOption(key, value);
|
||||
}
|
||||
}
|
||||
svgContext_.setSvgOption('apply', true);
|
||||
|
||||
// no need for doctype, see https://jwatt.org/svg/authoring/#doctype-declaration
|
||||
const str = svgCanvas.svgCanvasToString();
|
||||
svgContext_.call('saved', str);
|
||||
};
|
||||
/**
|
||||
* @typedef {PlainObject} module:svgcanvas.IssuesAndCodes
|
||||
* @property {string[]} issueCodes The locale-independent code names
|
||||
|
|
|
@ -80,7 +80,7 @@ import {
|
|||
convertToNum, getTypeMap, init as unitsInit
|
||||
} from '../common/units.js';
|
||||
import {
|
||||
svgCanvasToString, svgToString, setSvgString, save, exportPDF, setUseDataMethod,
|
||||
svgCanvasToString, svgToString, setSvgString, exportPDF, setUseDataMethod,
|
||||
init as svgInit, importSvgString, embedImage, rasterExport,
|
||||
uniquifyElemsMethod, removeUnusedDefElemsMethod, convertGradientsMethod
|
||||
} from './svg-exec.js';
|
||||
|
@ -188,6 +188,8 @@ class SvgCanvas {
|
|||
this.$id = $id;
|
||||
this.$qq = $qq;
|
||||
this.$qa = $qa;
|
||||
this.encode64 = encode64;
|
||||
this.decode64 = decode64;
|
||||
this.stringToHTML = stringToHTML;
|
||||
this.insertChildAtIndex = insertChildAtIndex;
|
||||
this.getClosest = getClosest;
|
||||
|
@ -1365,6 +1367,8 @@ class SvgCanvas {
|
|||
/**
|
||||
* Group: Serialization.
|
||||
*/
|
||||
this.getSvgOption = () => { return saveOptions; };
|
||||
this.setSvgOption = (key, value) => { saveOptions[key] = value; };
|
||||
|
||||
svgInit(
|
||||
/**
|
||||
|
@ -1379,8 +1383,8 @@ class SvgCanvas {
|
|||
getCurrentGroup() { return currentGroup; },
|
||||
getCurConfig() { return curConfig; },
|
||||
getNsMap() { return nsMap; },
|
||||
getSvgOption() { return saveOptions; },
|
||||
setSvgOption(key, value) { saveOptions[key] = value; },
|
||||
getSvgOption: this.getSvgOption,
|
||||
setSvgOption: this.setSvgOption,
|
||||
getSvgOptionApply() { return saveOptions.apply; },
|
||||
getSvgOptionImages() { return saveOptions.images; },
|
||||
getEncodableImages(key) { return encodableImages[key]; },
|
||||
|
@ -1448,26 +1452,6 @@ class SvgCanvas {
|
|||
lastGoodImgUrl = val;
|
||||
};
|
||||
|
||||
/**
|
||||
* Does nothing by default, handled by optional widget/extension.
|
||||
* @function module:svgcanvas.SvgCanvas#open
|
||||
* @returns {void}
|
||||
*/
|
||||
this.open = function () {
|
||||
/* empty fn */
|
||||
};
|
||||
|
||||
/**
|
||||
* Serializes the current drawing into SVG XML text and passes it to the 'saved' handler.
|
||||
* This function also includes the XML prolog. Clients of the `SvgCanvas` bind their save
|
||||
* function to the 'saved' event.
|
||||
* @function module:svgcanvas.SvgCanvas#save
|
||||
* @param {module:svgcanvas.SaveOptions} opts
|
||||
* @fires module:svgcanvas.SvgCanvas#event:saved
|
||||
* @returns {void}
|
||||
*/
|
||||
this.save = save;
|
||||
|
||||
/**
|
||||
* @typedef {PlainObject} module:svgcanvas.IssuesAndCodes
|
||||
* @property {string[]} issueCodes The locale-independent code names
|
||||
|
|
Loading…
Reference in New Issue