mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-25 23:54:55 +01:00
Exporter Wisemaping to Freemind
This commit is contained in:
parent
7d7bb9c8b0
commit
4943623ab8
@ -28,7 +28,8 @@
|
|||||||
"cy:run": "cypress run",
|
"cy:run": "cypress run",
|
||||||
"test:unit": "jest ./test/unit/export/*.ts ./test/unit/layout/*.js",
|
"test:unit": "jest ./test/unit/export/*.ts ./test/unit/layout/*.js",
|
||||||
"test:integration": "start-server-and-test playground http-get://localhost:8083 cy:run",
|
"test:integration": "start-server-and-test playground http-get://localhost:8083 cy:run",
|
||||||
"test": "yarn test:unit && yarn test:integration"
|
"test": "yarn test:unit && yarn test:integration",
|
||||||
|
"generate": "ts-node ./src/components/export/freemind/generatedClasses.ts"
|
||||||
},
|
},
|
||||||
"private": false,
|
"private": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -69,6 +70,7 @@
|
|||||||
"start-server-and-test": "^1.14.0",
|
"start-server-and-test": "^1.14.0",
|
||||||
"ts-jest": "^27.1.2",
|
"ts-jest": "^27.1.2",
|
||||||
"ts-loader": "^9.2.6",
|
"ts-loader": "^9.2.6",
|
||||||
|
"ts-node": "^10.4.0",
|
||||||
"webpack": "^5.44.0",
|
"webpack": "^5.44.0",
|
||||||
"webpack-bundle-analyzer": "^4.5.0",
|
"webpack-bundle-analyzer": "^4.5.0",
|
||||||
"webpack-cli": "^4.7.2",
|
"webpack-cli": "^4.7.2",
|
||||||
|
302
packages/mindplot/src/components/export/FreemindExporter.ts
Normal file
302
packages/mindplot/src/components/export/FreemindExporter.ts
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
import { Mindmap } from '../..';
|
||||||
|
import INodeModel, { TopicShape } from '../model/INodeModel';
|
||||||
|
import RelationshipModel from '../model/RelationshipModel';
|
||||||
|
import IconModel from '../model/IconModel';
|
||||||
|
import FeatureModel from '../model/FeatureModel';
|
||||||
|
import LinkModel from '../model/LinkModel';
|
||||||
|
import NoteModel from '../model/NoteModel';
|
||||||
|
import Exporter from './Exporter';
|
||||||
|
import FreemindConstant from './freemind/FreemindConstant';
|
||||||
|
import VersionNumber from './freemind/importer/VersionNumber';
|
||||||
|
import ObjectFactory from './freemind/ObjectFactory';
|
||||||
|
import FreemindMap from './freemind/Map';
|
||||||
|
import FreeminNode, { Choise } from './freemind/Node';
|
||||||
|
import Arrowlink from './freemind/Arrowlink';
|
||||||
|
import Richcontent from './freemind/Richcontent';
|
||||||
|
import Icon from './freemind/Icon';
|
||||||
|
import Edge from './freemind/Edge';
|
||||||
|
import Font from './freemind/Font';
|
||||||
|
|
||||||
|
type PositionNodeType = {x: number, y: number}
|
||||||
|
|
||||||
|
class FreemindExporter implements Exporter {
|
||||||
|
private mindmap: Mindmap;
|
||||||
|
|
||||||
|
private nodeMap: Map<number, FreeminNode> = null;
|
||||||
|
|
||||||
|
private version: VersionNumber = FreemindConstant.SUPPORTED_FREEMIND_VERSION;
|
||||||
|
|
||||||
|
private objectFactory: ObjectFactory;
|
||||||
|
|
||||||
|
private static wisweToFreeFontSize: Map<number, number> = new Map<number, number>();
|
||||||
|
|
||||||
|
constructor(mindmap: Mindmap) {
|
||||||
|
this.mindmap = mindmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
this.wisweToFreeFontSize.set(6, 10);
|
||||||
|
this.wisweToFreeFontSize.set(8, 12);
|
||||||
|
this.wisweToFreeFontSize.set(10, 18);
|
||||||
|
this.wisweToFreeFontSize.set(15, 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static parserXMLString(xmlStr: string, mimeType: DOMParserSupportedType): Document {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const xmlDoc = parser.parseFromString(xmlStr, mimeType);
|
||||||
|
|
||||||
|
// Is there any parsing error ?.
|
||||||
|
if (xmlDoc.getElementsByTagName('parsererror').length > 0) {
|
||||||
|
const xmmStr = new XMLSerializer().serializeToString(xmlDoc);
|
||||||
|
console.log(xmmStr);
|
||||||
|
throw new Error(`Unexpected error parsing: ${xmlStr}. Error: ${xmmStr}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xmlDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(): string {
|
||||||
|
return 'mm';
|
||||||
|
}
|
||||||
|
|
||||||
|
async export(): Promise<string> {
|
||||||
|
this.objectFactory = new ObjectFactory();
|
||||||
|
this.nodeMap = new Map();
|
||||||
|
|
||||||
|
const freemainMap: FreemindMap = this.objectFactory.createMap();
|
||||||
|
freemainMap.setVesion(this.getVersionNumber());
|
||||||
|
|
||||||
|
const main: FreeminNode = this.objectFactory.createNode();
|
||||||
|
freemainMap.setNode(main);
|
||||||
|
|
||||||
|
const centralTopic: INodeModel = this.mindmap.getCentralTopic();
|
||||||
|
|
||||||
|
if (centralTopic) {
|
||||||
|
this.nodeMap.set(centralTopic.getId(), main);
|
||||||
|
this.setTopicPropertiesToNode(main, centralTopic, true);
|
||||||
|
this.addNodeFromTopic(centralTopic, main);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relationships: Array<RelationshipModel> = this.mindmap.getRelationships();
|
||||||
|
relationships.forEach((relationship: RelationshipModel) => {
|
||||||
|
const srcNode: FreeminNode = this.nodeMap.get(relationship.getFromNode());
|
||||||
|
const destNode: FreeminNode = this.nodeMap.get(relationship.getToNode());
|
||||||
|
|
||||||
|
if (srcNode && destNode) {
|
||||||
|
const arrowlink: Arrowlink = this.objectFactory.crateArrowlink();
|
||||||
|
|
||||||
|
arrowlink.setDestination(destNode.getId());
|
||||||
|
|
||||||
|
if (relationship.getEndArrow() && relationship.getEndArrow()) arrowlink.setEndarrow('Default');
|
||||||
|
|
||||||
|
if (relationship.getStartArrow() && relationship.getStartArrow()) arrowlink.setStartarrow('Default');
|
||||||
|
|
||||||
|
const cloudEdge: Array<Choise> = srcNode.getArrowlinkOrCloudOrEdge();
|
||||||
|
|
||||||
|
cloudEdge.push(arrowlink);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const freeToXml = freemainMap.toXml();
|
||||||
|
const xmlToString = new XMLSerializer().serializeToString(freeToXml);
|
||||||
|
|
||||||
|
return Promise.resolve(xmlToString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addNodeFromTopic(mainTopic: INodeModel, destNode: FreeminNode): void {
|
||||||
|
const curretnTopics: Array<INodeModel> = mainTopic.getChildren();
|
||||||
|
|
||||||
|
curretnTopics.forEach((currentTopic: INodeModel) => {
|
||||||
|
const newNode: FreeminNode = this.objectFactory.createNode();
|
||||||
|
this.nodeMap.set(currentTopic.getId(), newNode);
|
||||||
|
|
||||||
|
this.setTopicPropertiesToNode(newNode, currentTopic, false);
|
||||||
|
|
||||||
|
destNode.getArrowlinkOrCloudOrEdge().push(newNode);
|
||||||
|
|
||||||
|
this.addNodeFromTopic(currentTopic, newNode);
|
||||||
|
|
||||||
|
const position: PositionNodeType = currentTopic.getPosition();
|
||||||
|
if (position) {
|
||||||
|
const xPos: number = position.x;
|
||||||
|
newNode.setPosition((xPos < 0 ? 'left' : 'right'));
|
||||||
|
} else newNode.setPosition('left');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private setTopicPropertiesToNode(freemindNode: FreeminNode, mindmapTopic: INodeModel, isRoot: boolean): void {
|
||||||
|
freemindNode.setId(`ID_${mindmapTopic.getId()}`);
|
||||||
|
|
||||||
|
const text = mindmapTopic.getText();
|
||||||
|
|
||||||
|
if (!text.includes('\n')) {
|
||||||
|
freemindNode.setText(text);
|
||||||
|
} else {
|
||||||
|
const richcontent: Richcontent = this.buildRichcontent(text, 'NODE');
|
||||||
|
freemindNode.getArrowlinkOrCloudOrEdge().push(richcontent);
|
||||||
|
}
|
||||||
|
|
||||||
|
const wiseShape: string = mindmapTopic.getShapeType();
|
||||||
|
if (wiseShape && TopicShape.LINE !== wiseShape) {
|
||||||
|
freemindNode.setBackgorundColor(this.rgbToHex(mindmapTopic.getBackgroundColor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wiseShape && !wiseShape) {
|
||||||
|
const isRootRoundedRectangle = isRoot && TopicShape.ROUNDED_RECT !== wiseShape;
|
||||||
|
const notIsRootLine = !isRoot && TopicShape.LINE !== wiseShape;
|
||||||
|
|
||||||
|
if (isRootRoundedRectangle || notIsRootLine) {
|
||||||
|
let style: string = wiseShape;
|
||||||
|
if (TopicShape.ROUNDED_RECT === style || TopicShape.ELLIPSE === style) {
|
||||||
|
style = 'bubble';
|
||||||
|
}
|
||||||
|
freemindNode.setStyle(style);
|
||||||
|
}
|
||||||
|
} else if (!isRoot) freemindNode.setStyle('fork');
|
||||||
|
|
||||||
|
this.addFeautreNode(freemindNode, mindmapTopic);
|
||||||
|
this.addFontNode(freemindNode, mindmapTopic);
|
||||||
|
this.addEdgeNode(freemindNode, mindmapTopic);
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildRichcontent(text: string, type: string): Richcontent {
|
||||||
|
const richconent: Richcontent = this.objectFactory.createRichcontent();
|
||||||
|
|
||||||
|
richconent.setType(type);
|
||||||
|
let html = '<html><body>';
|
||||||
|
|
||||||
|
text.split('\n').forEach((line: string) => {
|
||||||
|
html += `<p>${line.trim()}</p>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
html += '</body></html>';
|
||||||
|
|
||||||
|
const richconentDocument: Document = FreemindExporter.parserXMLString(html, 'application/xml');
|
||||||
|
const xmlResult = new XMLSerializer().serializeToString(richconentDocument);
|
||||||
|
richconent.setHtml(xmlResult);
|
||||||
|
|
||||||
|
return richconent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private addFeautreNode(freemindNode: FreeminNode, mindmapTopic: INodeModel): void {
|
||||||
|
const branches: Array<INodeModel> = mindmapTopic.getChildren();
|
||||||
|
const freemindIcon: Icon = new Icon();
|
||||||
|
|
||||||
|
branches
|
||||||
|
.filter((node: INodeModel) => node.getText !== undefined)
|
||||||
|
.forEach((node: INodeModel) => {
|
||||||
|
node.getFeatures().forEach((feature: FeatureModel) => {
|
||||||
|
const type = feature.getType();
|
||||||
|
|
||||||
|
if (type === 'link') {
|
||||||
|
const link = feature as LinkModel;
|
||||||
|
freemindNode.setLink(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'note') {
|
||||||
|
const note = feature as NoteModel;
|
||||||
|
const richcontent: Richcontent = this.buildRichcontent(note.getText(), 'NOTE');
|
||||||
|
freemindNode.getArrowlinkOrCloudOrEdge().push(richcontent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'icon') {
|
||||||
|
const icon = feature as IconModel;
|
||||||
|
freemindIcon.setBuiltin(icon.getIconType());
|
||||||
|
freemindNode.getArrowlinkOrCloudOrEdge().push(freemindIcon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private addEdgeNode(freemainMap: FreeminNode, mindmapTopic: INodeModel): void {
|
||||||
|
if (mindmapTopic.getBorderColor()) {
|
||||||
|
const edgeNode: Edge = this.objectFactory.createEdge();
|
||||||
|
edgeNode.setColor(this.rgbToHex(mindmapTopic.getBorderColor()));
|
||||||
|
freemainMap.getArrowlinkOrCloudOrEdge().push(edgeNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private addFontNode(freemindNode: FreeminNode, mindmapTopic: INodeModel): void {
|
||||||
|
const fontStyle: string = mindmapTopic.getFontStyle();
|
||||||
|
if (fontStyle) {
|
||||||
|
const font: Font = this.objectFactory.createFont();
|
||||||
|
const part: Array<string> = fontStyle.split(';', 6);
|
||||||
|
const countParts: number = part.length;
|
||||||
|
let fontNodeNeeded = false;
|
||||||
|
|
||||||
|
if (!fontStyle.endsWith(FreemindConstant.EMPTY_FONT_STYLE)) {
|
||||||
|
let idx = 0;
|
||||||
|
|
||||||
|
if (idx < countParts && part[idx].length !== 0) {
|
||||||
|
font.setName(part[idx]);
|
||||||
|
fontNodeNeeded = true;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if (idx < countParts && part[idx].length !== 0) {
|
||||||
|
const size: string = part[idx];
|
||||||
|
if (size) {
|
||||||
|
const wiseSize: number = parseInt(size, 10);
|
||||||
|
const freeSize: number = FreemindExporter.wisweToFreeFontSize.get(wiseSize);
|
||||||
|
|
||||||
|
if (freeSize) {
|
||||||
|
font.setSize(freeSize.toString());
|
||||||
|
fontNodeNeeded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if (idx < countParts && part[idx].length !== 0) {
|
||||||
|
freemindNode.setColor(this.rgbToHex(part[idx]));
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if (idx < countParts && part[idx].length !== 0) {
|
||||||
|
font.setBold(String(true));
|
||||||
|
fontNodeNeeded = true;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if (idx < countParts && part[idx].length !== 0) {
|
||||||
|
font.setItalic(String(true));
|
||||||
|
fontNodeNeeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fontNodeNeeded) {
|
||||||
|
if (font.getSize() === null) {
|
||||||
|
font.setSize(FreemindExporter.wisweToFreeFontSize.get(8).toString());
|
||||||
|
}
|
||||||
|
freemindNode.getArrowlinkOrCloudOrEdge().push(font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private rgbToHex(color: string): string {
|
||||||
|
let result: string = color;
|
||||||
|
if (result) {
|
||||||
|
const isRgb = new RegExp('^rgb\\([0-9]{1,3}, [0-9]{1,3}, [0-9]{1,3}\\)$');
|
||||||
|
|
||||||
|
if (isRgb.test(result)) {
|
||||||
|
const rgb: string[] = color.substring(4, color.length - 1).split(',');
|
||||||
|
const r: string = rgb[0].trim();
|
||||||
|
const g: string = rgb[1].trim();
|
||||||
|
const b: string = rgb[2].trim();
|
||||||
|
|
||||||
|
result = `#${r.length === 1 ? `0${r}` : r}${g.length === 1 ? `0${g}` : g}${b.length === 1 ? `0${b}` : b}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getVersion(): VersionNumber {
|
||||||
|
return this.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getVersionNumber(): string {
|
||||||
|
return this.getVersion().getVersion();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FreemindExporter;
|
@ -20,6 +20,7 @@ import Exporter from './Exporter';
|
|||||||
import MDExporter from './MDExporter';
|
import MDExporter from './MDExporter';
|
||||||
import TxtExporter from './TxtExporter';
|
import TxtExporter from './TxtExporter';
|
||||||
import WiseXMLExporter from './WiseXMLExporter';
|
import WiseXMLExporter from './WiseXMLExporter';
|
||||||
|
import FreemindExporter from './FreemindExporter';
|
||||||
|
|
||||||
type textType = 'wxml' | 'txt' | 'mm' | 'csv' | 'md';
|
type textType = 'wxml' | 'txt' | 'mm' | 'csv' | 'md';
|
||||||
|
|
||||||
@ -36,6 +37,9 @@ class TextExporterFactory {
|
|||||||
case 'md':
|
case 'md':
|
||||||
result = new MDExporter(mindmap);
|
result = new MDExporter(mindmap);
|
||||||
break;
|
break;
|
||||||
|
case 'mm':
|
||||||
|
result = new FreemindExporter(mindmap);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported type ${type}`);
|
throw new Error(`Unsupported type ${type}`);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
export default class Arrowlink {
|
||||||
|
protected COLOR: string;
|
||||||
|
|
||||||
|
protected DESTINATION: string;
|
||||||
|
|
||||||
|
protected ENDARROW: string;
|
||||||
|
|
||||||
|
protected ENDINCLINATION: string;
|
||||||
|
|
||||||
|
protected ID: string;
|
||||||
|
|
||||||
|
protected STARTARROW: string;
|
||||||
|
|
||||||
|
protected STARTINCLINATION: string;
|
||||||
|
|
||||||
|
getColor(): string {
|
||||||
|
return this.COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDestination(): string {
|
||||||
|
return this.DESTINATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEndarrow(): string {
|
||||||
|
return this.ENDARROW;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEndInclination(): string {
|
||||||
|
return this.ENDINCLINATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
getId(): string {
|
||||||
|
return this.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStartarrow(): string {
|
||||||
|
return this.STARTARROW;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStartinclination(): string {
|
||||||
|
return this.STARTINCLINATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor(value: string): void {
|
||||||
|
this.COLOR = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDestination(value: string): void {
|
||||||
|
this.DESTINATION = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEndarrow(value: string): void {
|
||||||
|
this.ENDARROW = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEndinclination(value: string): void {
|
||||||
|
this.ENDINCLINATION = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setId(value: string): void {
|
||||||
|
this.ID = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStartarrow(value: string): void {
|
||||||
|
this.STARTARROW = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStartinclination(value: string): void {
|
||||||
|
this.STARTINCLINATION = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
toXml(document: Document): HTMLElement {
|
||||||
|
const arrowlinkElem = document.createElement('arrowlink');
|
||||||
|
|
||||||
|
arrowlinkElem.setAttribute('DESTINATION', this.DESTINATION);
|
||||||
|
arrowlinkElem.setAttribute('STARTARROW', this.STARTARROW);
|
||||||
|
|
||||||
|
if (this.COLOR) arrowlinkElem.setAttribute('COLOR', this.COLOR);
|
||||||
|
if (this.ENDINCLINATION) arrowlinkElem.setAttribute('ENDINCLINATION', this.ENDINCLINATION);
|
||||||
|
if (this.ENDARROW) arrowlinkElem.setAttribute('ENDARROW', this.ENDARROW);
|
||||||
|
if (this.ID) arrowlinkElem.setAttribute('ID', this.ID);
|
||||||
|
if (this.STARTINCLINATION) arrowlinkElem.setAttribute('STARTINCLINATION', this.STARTINCLINATION);
|
||||||
|
|
||||||
|
return arrowlinkElem;
|
||||||
|
}
|
||||||
|
}
|
20
packages/mindplot/src/components/export/freemind/Cloud.ts
Normal file
20
packages/mindplot/src/components/export/freemind/Cloud.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
export default class Cloud {
|
||||||
|
protected COLOR: string;
|
||||||
|
|
||||||
|
getColor(): string {
|
||||||
|
return this.COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor(value: string): void {
|
||||||
|
this.COLOR = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
toXml(document: Document): HTMLElement {
|
||||||
|
// Set node attributes
|
||||||
|
const cloudElem = document.createElement('cloud');
|
||||||
|
|
||||||
|
cloudElem.setAttribute('COLOR', this.COLOR);
|
||||||
|
|
||||||
|
return cloudElem;
|
||||||
|
}
|
||||||
|
}
|
42
packages/mindplot/src/components/export/freemind/Edge.ts
Normal file
42
packages/mindplot/src/components/export/freemind/Edge.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
export default class Edge {
|
||||||
|
protected COLOR: string;
|
||||||
|
|
||||||
|
protected STYLE: string;
|
||||||
|
|
||||||
|
protected WIDTH: string;
|
||||||
|
|
||||||
|
getColor(): string {
|
||||||
|
return this.COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStyle(): string {
|
||||||
|
return this.STYLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
getWidth(): string {
|
||||||
|
return this.WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor(value: string): void {
|
||||||
|
this.COLOR = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStyle(value: string): void {
|
||||||
|
this.STYLE = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setWidth(value: string): void {
|
||||||
|
this.WIDTH = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
toXml(document: Document): HTMLElement {
|
||||||
|
// Set node attributes
|
||||||
|
const edgeElem = document.createElement('edge');
|
||||||
|
|
||||||
|
edgeElem.setAttribute('COLOR', this.COLOR);
|
||||||
|
if (this.STYLE) edgeElem.setAttribute('STYLE', this.STYLE);
|
||||||
|
if (this.WIDTH) edgeElem.setAttribute('WIDTH', this.WIDTH);
|
||||||
|
|
||||||
|
return edgeElem;
|
||||||
|
}
|
||||||
|
}
|
53
packages/mindplot/src/components/export/freemind/Font.ts
Normal file
53
packages/mindplot/src/components/export/freemind/Font.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
export default class Font {
|
||||||
|
protected BOLD?: string;
|
||||||
|
|
||||||
|
protected ITALIC?: string;
|
||||||
|
|
||||||
|
protected NAME?: string;
|
||||||
|
|
||||||
|
protected SIZE: string;
|
||||||
|
|
||||||
|
getBold(): string {
|
||||||
|
return this.BOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
getItalic(): string {
|
||||||
|
return this.ITALIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName(): string {
|
||||||
|
return this.NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSize(): string {
|
||||||
|
return this.SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBold(value: string): void {
|
||||||
|
this.BOLD = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setItalic(value: string): void {
|
||||||
|
this.ITALIC = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setName(value: string): void {
|
||||||
|
this.NAME = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSize(value: string): void {
|
||||||
|
this.SIZE = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
toXml(document: Document): HTMLElement {
|
||||||
|
const fontElem = document.createElement('font');
|
||||||
|
|
||||||
|
fontElem.setAttribute('SIZE', this.SIZE);
|
||||||
|
|
||||||
|
if (this.BOLD) fontElem.setAttribute('BOLD', this.BOLD);
|
||||||
|
if (this.ITALIC) fontElem.setAttribute('ITALIC', this.ITALIC);
|
||||||
|
if (this.NAME) fontElem.setAttribute('NAME', this.NAME);
|
||||||
|
|
||||||
|
return fontElem;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
import VersionNumber from './importer/VersionNumber';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
LAST_SUPPORTED_FREEMIND_VERSION: '1.0.1',
|
||||||
|
|
||||||
|
SUPPORTED_FREEMIND_VERSION: new VersionNumber('1.0.1'),
|
||||||
|
|
||||||
|
CODE_VERSION: 'tango',
|
||||||
|
|
||||||
|
SECOND_LEVEL_TOPIC_HEIGHT: 25,
|
||||||
|
|
||||||
|
ROOT_LEVEL_TOPIC_HEIGHT: 25,
|
||||||
|
|
||||||
|
CENTRAL_TO_TOPIC_DISTANCE: 200,
|
||||||
|
|
||||||
|
TOPIC_TO_TOPIC_DISTANCE: 90,
|
||||||
|
|
||||||
|
FONT_SIZE_HUGE: 15,
|
||||||
|
|
||||||
|
FONT_SIZE_LARGE: 10,
|
||||||
|
|
||||||
|
FONT_SIZE_NORMAL: 8,
|
||||||
|
|
||||||
|
FONT_SIZE_SMALL: 6,
|
||||||
|
|
||||||
|
NODE_TYPE: 'NODE',
|
||||||
|
|
||||||
|
BOLD: 'bold',
|
||||||
|
|
||||||
|
ITALIC: 'italic',
|
||||||
|
|
||||||
|
EMPTY_FONT_STYLE: ',,,,,',
|
||||||
|
|
||||||
|
EMPTY_NOTE: '',
|
||||||
|
|
||||||
|
POSITION_LEFT: 'left',
|
||||||
|
|
||||||
|
POSITION_RIGHT: 'right',
|
||||||
|
};
|
33
packages/mindplot/src/components/export/freemind/Hook.ts
Normal file
33
packages/mindplot/src/components/export/freemind/Hook.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import Parameters from './Parameters';
|
||||||
|
|
||||||
|
export default class Hook {
|
||||||
|
protected PARAMETERS: Parameters;
|
||||||
|
|
||||||
|
protected TEXT: string;
|
||||||
|
|
||||||
|
protected NAME: string;
|
||||||
|
|
||||||
|
getParameters(): Parameters {
|
||||||
|
return this.PARAMETERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
getText(): string {
|
||||||
|
return this.TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName(): string {
|
||||||
|
return this.NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
setParameters(value: Parameters): void {
|
||||||
|
this.PARAMETERS = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(value: string): void {
|
||||||
|
this.TEXT = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setName(value: string): void {
|
||||||
|
this.NAME = value;
|
||||||
|
}
|
||||||
|
}
|
20
packages/mindplot/src/components/export/freemind/Icon.ts
Normal file
20
packages/mindplot/src/components/export/freemind/Icon.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
export default class Icon {
|
||||||
|
protected BUILTIN: string;
|
||||||
|
|
||||||
|
getBuiltin(): string {
|
||||||
|
return this.BUILTIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBuiltin(value: string): void {
|
||||||
|
this.BUILTIN = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
toXml(document: Document): HTMLElement {
|
||||||
|
// Set node attributes
|
||||||
|
const iconElem = document.createElement('icon');
|
||||||
|
|
||||||
|
iconElem.setAttribute('BUILTIN', this.BUILTIN);
|
||||||
|
|
||||||
|
return iconElem;
|
||||||
|
}
|
||||||
|
}
|
105
packages/mindplot/src/components/export/freemind/Map.ts
Normal file
105
packages/mindplot/src/components/export/freemind/Map.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import { createDocument } from '@wisemapping/core-js';
|
||||||
|
import Arrowlink from './Arrowlink';
|
||||||
|
import Cloud from './Cloud';
|
||||||
|
import Edge from './Edge';
|
||||||
|
import Font from './Font';
|
||||||
|
import Icon from './Icon';
|
||||||
|
import Node, { Choise } from './Node';
|
||||||
|
|
||||||
|
export default class Map {
|
||||||
|
protected node: Node;
|
||||||
|
|
||||||
|
protected version: string;
|
||||||
|
|
||||||
|
getNode(): Node {
|
||||||
|
return this.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
getVersion(): string {
|
||||||
|
return this.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
setNode(value: Node) {
|
||||||
|
this.node = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setVesion(value: string) {
|
||||||
|
this.version = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
toXml(): Document {
|
||||||
|
const document = createDocument();
|
||||||
|
|
||||||
|
// Set map attributes
|
||||||
|
const mapElem = document.createElement('map');
|
||||||
|
mapElem.setAttribute('version', this.version);
|
||||||
|
|
||||||
|
document.appendChild(mapElem);
|
||||||
|
|
||||||
|
// Create main node
|
||||||
|
const mainNode: Node = this.node;
|
||||||
|
mainNode.setCentralNode(true);
|
||||||
|
const mainNodeElem = mainNode.toXml(document);
|
||||||
|
mapElem.appendChild(mainNodeElem);
|
||||||
|
|
||||||
|
const childNodes: Array<Choise> = mainNode.getArrowlinkOrCloudOrEdge();
|
||||||
|
childNodes.forEach((childNode: Choise) => {
|
||||||
|
const node = this.nodeToXml(childNode, mainNodeElem, document);
|
||||||
|
mainNodeElem.appendChild(node);
|
||||||
|
});
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
private nodeToXml(childNode: Choise, parentNode: HTMLElement, document: Document): HTMLElement {
|
||||||
|
if (childNode instanceof Node) {
|
||||||
|
childNode.setCentralNode(false);
|
||||||
|
const childNodeXml = childNode.toXml(document);
|
||||||
|
parentNode.appendChild(childNodeXml);
|
||||||
|
|
||||||
|
childNode.getArrowlinkOrCloudOrEdge().forEach((node: Choise) => {
|
||||||
|
const nodeXml = this.nodeToXml(node, childNodeXml, document);
|
||||||
|
childNodeXml.appendChild(nodeXml);
|
||||||
|
});
|
||||||
|
|
||||||
|
return childNodeXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childNode instanceof Font) {
|
||||||
|
const childNodeXml = childNode.toXml(document);
|
||||||
|
parentNode.appendChild(childNodeXml);
|
||||||
|
|
||||||
|
return childNodeXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childNode instanceof Edge) {
|
||||||
|
const childNodeXml = childNode.toXml(document);
|
||||||
|
parentNode.appendChild(childNodeXml);
|
||||||
|
|
||||||
|
return childNodeXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childNode instanceof Arrowlink) {
|
||||||
|
const childNodeXml = childNode.toXml(document);
|
||||||
|
parentNode.appendChild(childNodeXml);
|
||||||
|
|
||||||
|
return childNodeXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childNode instanceof Cloud) {
|
||||||
|
const childNodeXml = childNode.toXml(document);
|
||||||
|
parentNode.appendChild(childNodeXml);
|
||||||
|
|
||||||
|
return childNodeXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childNode instanceof Icon) {
|
||||||
|
const childNodeXml = childNode.toXml(document);
|
||||||
|
parentNode.appendChild(childNodeXml);
|
||||||
|
|
||||||
|
return childNodeXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parentNode;
|
||||||
|
}
|
||||||
|
}
|
215
packages/mindplot/src/components/export/freemind/Node.ts
Normal file
215
packages/mindplot/src/components/export/freemind/Node.ts
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
import Arrowlink from './Arrowlink';
|
||||||
|
import Cloud from './Cloud';
|
||||||
|
import Edge from './Edge';
|
||||||
|
import Font from './Font';
|
||||||
|
import Hook from './Hook';
|
||||||
|
import Icon from './Icon';
|
||||||
|
import Richcontent from './Richcontent';
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
protected arrowlinkOrCloudOrEdge: Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this>;
|
||||||
|
|
||||||
|
protected BACKGROUND_COLOR: string;
|
||||||
|
|
||||||
|
protected COLOR: string;
|
||||||
|
|
||||||
|
protected FOLDED: string;
|
||||||
|
|
||||||
|
protected ID: string;
|
||||||
|
|
||||||
|
protected LINK: string;
|
||||||
|
|
||||||
|
protected POSITION: string;
|
||||||
|
|
||||||
|
protected STYLE: string;
|
||||||
|
|
||||||
|
protected TEXT: string;
|
||||||
|
|
||||||
|
protected CREATED: string;
|
||||||
|
|
||||||
|
protected MODIFIED: string;
|
||||||
|
|
||||||
|
protected HGAP: string;
|
||||||
|
|
||||||
|
protected VGAP: string;
|
||||||
|
|
||||||
|
protected WCOORDS: string;
|
||||||
|
|
||||||
|
protected WORDER: string;
|
||||||
|
|
||||||
|
protected VSHIFT: string;
|
||||||
|
|
||||||
|
protected ENCRYPTED_CONTENT: string;
|
||||||
|
|
||||||
|
protected centralNode: boolean;
|
||||||
|
|
||||||
|
getArrowlinkOrCloudOrEdge(): Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node> {
|
||||||
|
if (!this.arrowlinkOrCloudOrEdge) {
|
||||||
|
this.arrowlinkOrCloudOrEdge = new Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this>();
|
||||||
|
}
|
||||||
|
return this.arrowlinkOrCloudOrEdge;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBackgorundColor(): string {
|
||||||
|
return this.BACKGROUND_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
getColor(): string {
|
||||||
|
return this.COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFolded(): string {
|
||||||
|
return this.FOLDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
getId(): string {
|
||||||
|
return this.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLink(): string {
|
||||||
|
return this.LINK;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPosition(): string {
|
||||||
|
return this.POSITION;
|
||||||
|
}
|
||||||
|
|
||||||
|
getStyle(): string {
|
||||||
|
return this.STYLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
getText(): string {
|
||||||
|
return this.TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCreated(): string {
|
||||||
|
return this.CREATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
getModified(): string {
|
||||||
|
return this.MODIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
getHgap(): string {
|
||||||
|
return this.HGAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
getVgap(): string {
|
||||||
|
return this.VGAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
getWcoords(): string {
|
||||||
|
return this.WCOORDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
getWorder(): string {
|
||||||
|
return this.WORDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
getVshift(): string {
|
||||||
|
return this.VSHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEncryptedContent(): string {
|
||||||
|
return this.ENCRYPTED_CONTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCentralNode(): boolean {
|
||||||
|
return this.centralNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
setArrowlinkOrCloudOrEdge(value: Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this>): void {
|
||||||
|
this.arrowlinkOrCloudOrEdge = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBackgorundColor(value: string): void {
|
||||||
|
this.BACKGROUND_COLOR = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setColor(value: string): void {
|
||||||
|
this.COLOR = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFolded(value: string): void {
|
||||||
|
this.FOLDED = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setId(value: string): void {
|
||||||
|
this.ID = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLink(value): void {
|
||||||
|
this.LINK = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPosition(value: string): void {
|
||||||
|
this.POSITION = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStyle(value: string): void {
|
||||||
|
this.STYLE = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(value: string): void {
|
||||||
|
this.TEXT = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCreated(value: string): void {
|
||||||
|
this.CREATED = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setModified(value: string): void {
|
||||||
|
this.MODIFIED = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHgap(value: string): void {
|
||||||
|
this.HGAP = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setVgap(value: string): void {
|
||||||
|
this.VGAP = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setWcoords(value: string): void {
|
||||||
|
this.WCOORDS = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setWorder(value: string): void {
|
||||||
|
this.WORDER = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setVshift(value: string): void {
|
||||||
|
this.VSHIFT = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEncryptedContent(value: string): void {
|
||||||
|
this.ENCRYPTED_CONTENT = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCentralNode(value: boolean): void {
|
||||||
|
this.centralNode = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
toXml(document: Document): HTMLElement {
|
||||||
|
// Set node attributes
|
||||||
|
const nodeElem = document.createElement('node');
|
||||||
|
|
||||||
|
if (this.centralNode) {
|
||||||
|
nodeElem.setAttribute('ID', this.ID);
|
||||||
|
nodeElem.setAttribute('TEXT', this.TEXT);
|
||||||
|
|
||||||
|
return nodeElem;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeElem.setAttribute('ID', this.ID);
|
||||||
|
nodeElem.setAttribute('POSITION', this.POSITION);
|
||||||
|
nodeElem.setAttribute('STYLE', this.STYLE);
|
||||||
|
nodeElem.setAttribute('TEXT', this.TEXT);
|
||||||
|
|
||||||
|
return nodeElem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Choise = Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node
|
||||||
|
|
||||||
|
export default Node;
|
@ -0,0 +1,51 @@
|
|||||||
|
import Arrowlink from './Arrowlink';
|
||||||
|
import Cloud from './Cloud';
|
||||||
|
import Edge from './Edge';
|
||||||
|
import Font from './Font';
|
||||||
|
import Hook from './Hook';
|
||||||
|
import Icon from './Icon';
|
||||||
|
import Richcontent from './Richcontent';
|
||||||
|
import Map from './Map';
|
||||||
|
import Node from './Node';
|
||||||
|
|
||||||
|
export default class ObjectFactory {
|
||||||
|
public createParameters(): void {
|
||||||
|
console.log('parameters');
|
||||||
|
}
|
||||||
|
|
||||||
|
public crateArrowlink(): Arrowlink {
|
||||||
|
return new Arrowlink();
|
||||||
|
}
|
||||||
|
|
||||||
|
public createCloud(): Cloud {
|
||||||
|
return new Cloud();
|
||||||
|
}
|
||||||
|
|
||||||
|
public createEdge(): Edge {
|
||||||
|
return new Edge();
|
||||||
|
}
|
||||||
|
|
||||||
|
public createFont(): Font {
|
||||||
|
return new Font();
|
||||||
|
}
|
||||||
|
|
||||||
|
public createHook(): Hook {
|
||||||
|
return new Hook();
|
||||||
|
}
|
||||||
|
|
||||||
|
public createIcon(): Icon {
|
||||||
|
return new Icon();
|
||||||
|
}
|
||||||
|
|
||||||
|
public createRichcontent(): Richcontent {
|
||||||
|
return new Richcontent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public createMap(): Map {
|
||||||
|
return new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
public createNode(): Node {
|
||||||
|
return new Node();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
export default class Parameters {
|
||||||
|
protected REMINDUSERAT: number;
|
||||||
|
|
||||||
|
getReminduserat(): number {
|
||||||
|
return this.REMINDUSERAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
setReminduserat(value: number): void {
|
||||||
|
this.REMINDUSERAT = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
export default class Richcontent {
|
||||||
|
protected html: string;
|
||||||
|
|
||||||
|
protected type: string;
|
||||||
|
|
||||||
|
getHtml(): string {
|
||||||
|
return this.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
getType(): string {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
setHtml(value: string): void {
|
||||||
|
this.html = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setType(value: string): void {
|
||||||
|
this.type = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
toXml(document: Document): HTMLElement {
|
||||||
|
// Set node attributes
|
||||||
|
const richcontentElem = document.createElement('richcontent');
|
||||||
|
|
||||||
|
richcontentElem.setAttribute('TYPE', this.type);
|
||||||
|
|
||||||
|
return richcontentElem;
|
||||||
|
}
|
||||||
|
}
|
150
packages/mindplot/src/components/export/freemind/freemind_0.9.0.xsd
Executable file
150
packages/mindplot/src/components/export/freemind/freemind_0.9.0.xsd
Executable file
@ -0,0 +1,150 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
|
||||||
|
|
||||||
|
<xs:element name='Parameters'>
|
||||||
|
<xs:complexType>
|
||||||
|
<!--Is the time management plugin.-->
|
||||||
|
<xs:attribute name='REMINDUSERAT' type='xs:integer' use='optional'/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<!--Used for node notes.-->
|
||||||
|
<xs:element name='text' type="xs:string"/>
|
||||||
|
|
||||||
|
<xs:element name='arrowlink'>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name='COLOR' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='DESTINATION' type='xs:string' use='required'/>
|
||||||
|
<xs:attribute name='ENDARROW' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='ENDINCLINATION' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='ID' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='STARTARROW' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='STARTINCLINATION' type='xs:string' use='optional'/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name='cloud'>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name='COLOR' type='xs:string' use='optional'/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name='edge'>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name='COLOR' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='STYLE' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='WIDTH' type='xs:string' use='optional'/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name='font'>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name='BOLD' use='optional'>
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base='xs:string'>
|
||||||
|
<xs:enumeration value='true'/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name='ITALIC' use='optional'>
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base='xs:string'>
|
||||||
|
<xs:enumeration value='true'/>
|
||||||
|
<xs:enumeration value='false'/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name='NAME' type='xs:string' use='required'/>
|
||||||
|
<xs:attribute name='SIZE' use='required' type='xs:integer'/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name='hook'>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element ref='Parameters' minOccurs='0' maxOccurs='1'/>
|
||||||
|
<xs:element ref='text' minOccurs='0' maxOccurs='1'/>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name='NAME' type='xs:string' use='required'/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name='icon'>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name='BUILTIN' type='xs:string' use='required'/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name='richcontent'>
|
||||||
|
<xs:complexType>
|
||||||
|
<!-- And contains XHTML as unique child:-->
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name='html' minOccurs='1' maxOccurs='1' type="xs:anyType"/>
|
||||||
|
</xs:sequence>
|
||||||
|
<!--Currently, only NODE or NOTE is allowed.-->
|
||||||
|
<xs:attribute name='TYPE' use='required'>
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base='xs:string'>
|
||||||
|
<xs:enumeration value='NODE'/>
|
||||||
|
<xs:enumeration value='NOTE'/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name='map'>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element ref='node'/>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute name='version' type='xs:string' use='required'/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
<xs:element name='node'>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:choice minOccurs='0' maxOccurs='unbounded'>
|
||||||
|
<xs:element ref='arrowlink'/>
|
||||||
|
<xs:element ref='cloud'/>
|
||||||
|
<xs:element ref='edge'/>
|
||||||
|
<xs:element ref='font'/>
|
||||||
|
<xs:element ref='hook'/>
|
||||||
|
<xs:element ref='icon'/>
|
||||||
|
<xs:element ref='node'/>
|
||||||
|
<!-- For nodes with extended formatting content or for notes to nodes. -->
|
||||||
|
<xs:element ref='richcontent'/>
|
||||||
|
</xs:choice>
|
||||||
|
<xs:attribute name='BACKGROUND_COLOR' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='COLOR' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='FOLDED' use='optional'>
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base='xs:string'>
|
||||||
|
<xs:enumeration value='true'/>
|
||||||
|
<xs:enumeration value='false'/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name='ID' type='xs:ID' use='optional'/>
|
||||||
|
<xs:attribute name='LINK' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='POSITION' use='optional'>
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base='xs:string'>
|
||||||
|
<xs:enumeration value='left'/>
|
||||||
|
<xs:enumeration value='right'/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name='STYLE' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='TEXT' type='xs:string' use='required'/>
|
||||||
|
<xs:attribute name='CREATED' type='xs:integer' use='optional'/>
|
||||||
|
<xs:attribute name='MODIFIED' type='xs:integer' use='optional'/>
|
||||||
|
<xs:attribute name='HGAP' type='xs:integer' use='optional'/>
|
||||||
|
<xs:attribute name='VGAP' type='xs:integer' use='optional'/>
|
||||||
|
<xs:attribute name='WCOORDS' type='xs:string' use='optional'/>
|
||||||
|
<xs:attribute name='WORDER' type='xs:integer' use='optional'/>
|
||||||
|
|
||||||
|
<xs:attribute name='VSHIFT' type='xs:integer' use='optional'/>
|
||||||
|
<xs:attribute name='ENCRYPTED_CONTENT' type='xs:string' use='optional'/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
@ -0,0 +1,3 @@
|
|||||||
|
import { generateTemplateClassesFromXSD } from 'xsd2ts';
|
||||||
|
|
||||||
|
generateTemplateClassesFromXSD('./freemind_0.9.0');
|
@ -0,0 +1,11 @@
|
|||||||
|
export default class VersionNumber {
|
||||||
|
protected version: string;
|
||||||
|
|
||||||
|
constructor(version: string) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getVersion(): string {
|
||||||
|
return this.version;
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,8 @@ import { parseXMLFile, setupBlob, exporterAssert } from './Helper';
|
|||||||
|
|
||||||
setupBlob();
|
setupBlob();
|
||||||
|
|
||||||
const testNames = fs.readdirSync(path.resolve(__dirname, './input/'))
|
const testNames = fs
|
||||||
|
.readdirSync(path.resolve(__dirname, './input/'))
|
||||||
.filter((f) => f.endsWith('.wxml'))
|
.filter((f) => f.endsWith('.wxml'))
|
||||||
.map((filename: string) => filename.split('.')[0]);
|
.map((filename: string) => filename.split('.')[0]);
|
||||||
|
|
||||||
@ -56,3 +57,18 @@ describe('MD export test execution', () => {
|
|||||||
await exporterAssert(testName, exporter);
|
await exporterAssert(testName, exporter);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('MM export test execution', () => {
|
||||||
|
test.each(testNames)('Exporting %p suite', async (testName: string) => {
|
||||||
|
// Load mindmap DOM...
|
||||||
|
const mindmapPath = path.resolve(__dirname, `./input/${testName}.wxml`);
|
||||||
|
const mapDocument = parseXMLFile(mindmapPath, 'text/xml');
|
||||||
|
|
||||||
|
// Convert to mindmap...
|
||||||
|
const serializer = XMLSerializerFactory.createInstanceFromDocument(mapDocument);
|
||||||
|
const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName);
|
||||||
|
|
||||||
|
const exporter = TextExporterFactory.create('mm', mindmap);
|
||||||
|
await exporterAssert(testName, exporter);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
76
yarn.lock
76
yarn.lock
@ -1017,6 +1017,18 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
|
"@cspotcode/source-map-consumer@0.8.0":
|
||||||
|
version "0.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b"
|
||||||
|
integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==
|
||||||
|
|
||||||
|
"@cspotcode/source-map-support@0.7.0":
|
||||||
|
version "0.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5"
|
||||||
|
integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==
|
||||||
|
dependencies:
|
||||||
|
"@cspotcode/source-map-consumer" "0.8.0"
|
||||||
|
|
||||||
"@cypress/request@^2.88.10", "@cypress/request@^2.88.6":
|
"@cypress/request@^2.88.10", "@cypress/request@^2.88.6":
|
||||||
version "2.88.10"
|
version "2.88.10"
|
||||||
resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce"
|
resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce"
|
||||||
@ -2494,6 +2506,26 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||||
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
||||||
|
|
||||||
|
"@tsconfig/node10@^1.0.7":
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9"
|
||||||
|
integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==
|
||||||
|
|
||||||
|
"@tsconfig/node12@^1.0.7":
|
||||||
|
version "1.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c"
|
||||||
|
integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==
|
||||||
|
|
||||||
|
"@tsconfig/node14@^1.0.0":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2"
|
||||||
|
integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==
|
||||||
|
|
||||||
|
"@tsconfig/node16@^1.0.2":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e"
|
||||||
|
integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==
|
||||||
|
|
||||||
"@types/aria-query@^4.2.0":
|
"@types/aria-query@^4.2.0":
|
||||||
version "4.2.2"
|
version "4.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc"
|
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc"
|
||||||
@ -3282,30 +3314,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.1.tgz#0de2875ac31b46b6c5bb1ae0a7d7f0ba5678dffe"
|
resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.1.tgz#0de2875ac31b46b6c5bb1ae0a7d7f0ba5678dffe"
|
||||||
integrity sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==
|
integrity sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==
|
||||||
|
|
||||||
"@wisemapping/mindplot@^0.4.15":
|
|
||||||
version "0.4.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/@wisemapping/mindplot/-/mindplot-0.4.15.tgz#d4a7aa3a96bd5a91ec7f800eb392be820d97510b"
|
|
||||||
integrity sha512-4buCwA9VezQylHkZ4c7JB+MBqGAOzOnBUZEjeqkg5hZMSt0mobMD3inp+tStJbZtQQbt7p6KJ/04+ewHmGlBag==
|
|
||||||
dependencies:
|
|
||||||
"@types/jquery" "^3.5.11"
|
|
||||||
"@wisemapping/core-js" "^0.4.0"
|
|
||||||
"@wisemapping/web2d" "^0.4.0"
|
|
||||||
jest "^27.4.5"
|
|
||||||
jquery "3.6.0"
|
|
||||||
lodash "^4.17.21"
|
|
||||||
|
|
||||||
"@wisemapping/mindplot@^0.4.15":
|
|
||||||
version "0.4.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/@wisemapping/mindplot/-/mindplot-0.4.15.tgz#d4a7aa3a96bd5a91ec7f800eb392be820d97510b"
|
|
||||||
integrity sha512-4buCwA9VezQylHkZ4c7JB+MBqGAOzOnBUZEjeqkg5hZMSt0mobMD3inp+tStJbZtQQbt7p6KJ/04+ewHmGlBag==
|
|
||||||
dependencies:
|
|
||||||
"@types/jquery" "^3.5.11"
|
|
||||||
"@wisemapping/core-js" "^0.4.0"
|
|
||||||
"@wisemapping/web2d" "^0.4.0"
|
|
||||||
jest "^27.4.5"
|
|
||||||
jquery "3.6.0"
|
|
||||||
lodash "^4.17.21"
|
|
||||||
|
|
||||||
"@xtuc/ieee754@^1.2.0":
|
"@xtuc/ieee754@^1.2.0":
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
||||||
@ -3374,7 +3382,7 @@ acorn-walk@^7.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
||||||
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
||||||
|
|
||||||
acorn-walk@^8.0.0:
|
acorn-walk@^8.0.0, acorn-walk@^8.1.1:
|
||||||
version "8.2.0"
|
version "8.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
|
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
|
||||||
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
|
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
|
||||||
@ -13554,6 +13562,24 @@ ts-loader@^9.2.6:
|
|||||||
micromatch "^4.0.0"
|
micromatch "^4.0.0"
|
||||||
semver "^7.3.4"
|
semver "^7.3.4"
|
||||||
|
|
||||||
|
ts-node@^10.4.0:
|
||||||
|
version "10.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7"
|
||||||
|
integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==
|
||||||
|
dependencies:
|
||||||
|
"@cspotcode/source-map-support" "0.7.0"
|
||||||
|
"@tsconfig/node10" "^1.0.7"
|
||||||
|
"@tsconfig/node12" "^1.0.7"
|
||||||
|
"@tsconfig/node14" "^1.0.0"
|
||||||
|
"@tsconfig/node16" "^1.0.2"
|
||||||
|
acorn "^8.4.1"
|
||||||
|
acorn-walk "^8.1.1"
|
||||||
|
arg "^4.1.0"
|
||||||
|
create-require "^1.1.0"
|
||||||
|
diff "^4.0.1"
|
||||||
|
make-error "^1.1.1"
|
||||||
|
yn "3.1.1"
|
||||||
|
|
||||||
ts-node@^9.0.0:
|
ts-node@^9.0.0:
|
||||||
version "9.1.1"
|
version "9.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
|
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
|
||||||
|
Loading…
Reference in New Issue
Block a user