Extract encoding as common code.

This commit is contained in:
Paulo Gustavo Veiga 2022-02-01 19:13:44 -08:00
parent 5d52bbfc54
commit 1cbd5d3f2e
10 changed files with 51 additions and 51 deletions

View File

@ -21,7 +21,7 @@ import SVGExporter from './SVGExporter';
/** /**
* Based on https://mybyways.com/blog/convert-svg-to-png-using-your-browser * Based on https://mybyways.com/blog/convert-svg-to-png-using-your-browser
*/ */
class BinaryImageExporter implements Exporter { class BinaryImageExporter extends Exporter {
svgElement: Element; svgElement: Element;
mindmap: Mindmap; mindmap: Mindmap;
@ -30,24 +30,22 @@ class BinaryImageExporter implements Exporter {
height: number; height: number;
imgFormat: string;
constructor(mindmap: Mindmap, svgElement: Element, width: number, height: number, imgFormat: 'image/png' | 'image/jpeg') { constructor(mindmap: Mindmap, svgElement: Element, width: number, height: number, imgFormat: 'image/png' | 'image/jpeg') {
super(imgFormat.split['/'][0], imgFormat);
this.svgElement = svgElement; this.svgElement = svgElement;
this.mindmap = mindmap; this.mindmap = mindmap;
this.imgFormat = imgFormat;
this.width = width; this.width = width;
this.height = height; this.height = height;
} }
extension(): string { export(): Promise<string> {
return this.imgFormat.split['/'][0]; throw new Error('Images can not be exporeted');
} }
async export(): Promise<string> { async exportAndEndcode(): Promise<string> {
const svgExporter = new SVGExporter(this.mindmap, this.svgElement); const svgExporter = new SVGExporter(this.svgElement);
const svgUrl = await svgExporter.export(); const svgUrl = await svgExporter.exportAndEncode();
// Get the device pixel ratio, falling back to 1. But, I will double the resolution to look nicer. // Get the device pixel ratio, falling back to 1. But, I will double the resolution to look nicer.
const dpr = (window.devicePixelRatio || 1) * 2; const dpr = (window.devicePixelRatio || 1) * 2;
@ -67,7 +65,7 @@ class BinaryImageExporter implements Exporter {
ctx.drawImage(img, 0, 0); ctx.drawImage(img, 0, 0);
const imgDataUri = canvas const imgDataUri = canvas
.toDataURL(this.imgFormat) .toDataURL(this.getContentType())
.replace('image/png', 'octet/stream'); .replace('image/png', 'octet/stream');
URL.revokeObjectURL(svgUrl); URL.revokeObjectURL(svgUrl);

View File

@ -15,9 +15,33 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
interface Exporter { abstract class Exporter {
export(): Promise<string>; private _extension: string;
extension(): string;
private _contentType: string;
constructor(extension: string, contentType: string) {
this._extension = extension;
this._contentType = contentType;
}
exportAndEncode(): Promise<string> {
const exportValue = this.export();
return exportValue.then((value: string) => {
const blob = new Blob([value], { type: this._contentType });
return URL.createObjectURL(blob);
});
}
abstract export(): Promise<string>;
extension(): string {
return this._extension;
}
getContentType(): string {
return this._contentType;
}
} }
export default Exporter; export default Exporter;

View File

@ -26,7 +26,7 @@ class ImageExpoterFactory {
let result; let result;
switch (type) { switch (type) {
case 'svg': { case 'svg': {
result = new SVGExporter(mindmap, svgElement); result = new SVGExporter(svgElement);
break; break;
} }
case 'png': { case 'png': {

View File

@ -21,19 +21,16 @@ import LinkModel from '../model/LinkModel';
import NoteModel from '../model/NoteModel'; import NoteModel from '../model/NoteModel';
import Exporter from './Exporter'; import Exporter from './Exporter';
class MDExporter implements Exporter { class MDExporter extends Exporter {
private mindmap: Mindmap; private mindmap: Mindmap;
private footNotes: string[] = []; private footNotes: string[] = [];
constructor(mindmap: Mindmap) { constructor(mindmap: Mindmap) {
super('md', 'text/markdown');
this.mindmap = mindmap; this.mindmap = mindmap;
} }
extension(): string {
return 'md';
}
private normalizeText(value: string): string { private normalizeText(value: string): string {
return value.replace('\n', ''); return value.replace('\n', '');
} }

View File

@ -15,23 +15,18 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { Mindmap } from '../..';
import Exporter from './Exporter'; import Exporter from './Exporter';
class SVGExporter implements Exporter { class SVGExporter extends Exporter {
private svgElement: Element; private svgElement: Element;
private prolog = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\n'; private prolog = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\n';
// eslint-disable-next-line @typescript-eslint/no-unused-vars constructor(svgElement: Element) {
constructor(mindmap: Mindmap, svgElement: Element, centerImgage = false) { super('svg', 'image/svg+xml');
this.svgElement = svgElement; this.svgElement = svgElement;
} }
extension(): string {
return 'svg';
}
export(): Promise<string> { export(): Promise<string> {
// Replace all images for in-line images ... // Replace all images for in-line images ...
let svgTxt: string = new XMLSerializer() let svgTxt: string = new XMLSerializer()
@ -48,10 +43,8 @@ class SVGExporter implements Exporter {
const svgElement = svgDoc.getElementsByTagName('svg')[0]; const svgElement = svgDoc.getElementsByTagName('svg')[0];
svgElement.setAttribute('style', 'background-color:white'); svgElement.setAttribute('style', 'background-color:white');
const svgResult = new XMLSerializer() const result = new XMLSerializer()
.serializeToString(svgDoc); .serializeToString(svgDoc);
const blob = new Blob([svgResult], { type: 'image/svg+xml' });
const result = URL.createObjectURL(blob);
return Promise.resolve(result); return Promise.resolve(result);
} }

View File

@ -21,7 +21,7 @@ import MDExporter from './MDExporter';
import TxtExporter from './TxtExporter'; import TxtExporter from './TxtExporter';
import WiseXMLExporter from './WiseXMLExporter'; import WiseXMLExporter from './WiseXMLExporter';
type textType = 'wxml' | 'txt' | 'mm' | 'csv' | 'md'; type textType = 'wxml' | 'txt' | 'mm' | 'csv' | 'md' | 'mmap';
class TextExporterFactory { class TextExporterFactory {
static create(type: textType, mindmap: Mindmap): Exporter { static create(type: textType, mindmap: Mindmap): Exporter {

View File

@ -20,27 +20,20 @@ import INodeModel from '../model/INodeModel';
import LinkModel from '../model/LinkModel'; import LinkModel from '../model/LinkModel';
import Exporter from './Exporter'; import Exporter from './Exporter';
class TxtExporter implements Exporter { class TxtExporter extends Exporter {
private mindmap: Mindmap; private mindmap: Mindmap;
constructor(mindmap: Mindmap) { constructor(mindmap: Mindmap) {
super('txt', 'text/pain');
this.mindmap = mindmap; this.mindmap = mindmap;
} }
extension(): string {
return 'txt';
}
export(): Promise<string> { export(): Promise<string> {
const { mindmap } = this; const { mindmap } = this;
const branches = mindmap.getBranches(); const branches = mindmap.getBranches();
const txtStr = this.traverseBranch('', branches); const txtStr = this.traverseBranch('', branches);
return Promise.resolve(txtStr);
// Encode as url response ...
const blob = new Blob([txtStr], { type: 'text/pain' });
const result = URL.createObjectURL(blob);
return Promise.resolve(result);
} }
private traverseBranch(prefix: string, branches: INodeModel[]) { private traverseBranch(prefix: string, branches: INodeModel[]) {

View File

@ -19,17 +19,14 @@ import { Mindmap } from '../..';
import XMLSerializerFactory from '../persistence/XMLSerializerFactory'; import XMLSerializerFactory from '../persistence/XMLSerializerFactory';
import Exporter from './Exporter'; import Exporter from './Exporter';
class WiseXMLExporter implements Exporter { class WiseXMLExporter extends Exporter {
mindmap: Mindmap; mindmap: Mindmap;
constructor(mindmap: Mindmap) { constructor(mindmap: Mindmap) {
super('wxml', 'application/xml');
this.mindmap = mindmap; this.mindmap = mindmap;
} }
extension(): string {
return 'wxml';
}
export(): Promise<string> { export(): Promise<string> {
const { mindmap } = this; const { mindmap } = this;
const serializer = XMLSerializerFactory const serializer = XMLSerializerFactory
@ -38,9 +35,7 @@ class WiseXMLExporter implements Exporter {
const xmlStr: string = new XMLSerializer() const xmlStr: string = new XMLSerializer()
.serializeToString(document); .serializeToString(document);
const blob = new Blob([xmlStr], { type: 'application/xml' }); return Promise.resolve(xmlStr);
const result = URL.createObjectURL(blob);
return Promise.resolve(result);
} }
} }
export default WiseXMLExporter; export default WiseXMLExporter;

View File

@ -26,7 +26,7 @@ describe('SVG export test execution', () => {
const svgDocument = parseXMLFile(svgPath, 'image/svg+xml'); const svgDocument = parseXMLFile(svgPath, 'image/svg+xml');
// Generate output ... // Generate output ...
const exporter = new SVGExporter(mindmap, svgDocument.documentElement); const exporter = new SVGExporter(svgDocument.documentElement);
await exporterAssert(testName, exporter); await exporterAssert(testName, exporter);
}); });
}); });

View File

@ -109,7 +109,7 @@ const ExportDialog = ({
throw new Error('Unsupported encoding'); throw new Error('Unsupported encoding');
} }
return exporter.export(); return exporter.exportAndEncode();
}; };
useEffect(() => { useEffect(() => {