Fix error rendered a children node

This commit is contained in:
Ezequiel-Vega 2022-02-18 13:08:08 -03:00
parent d8fbf4ecc9
commit df26a52047
6 changed files with 82 additions and 77 deletions

View File

@ -10,7 +10,7 @@ import FreemindConstant from './freemind/FreemindConstant';
import VersionNumber from './freemind/importer/VersionNumber'; import VersionNumber from './freemind/importer/VersionNumber';
import ObjectFactory from './freemind/ObjectFactory'; import ObjectFactory from './freemind/ObjectFactory';
import FreemindMap from './freemind/Map'; import FreemindMap from './freemind/Map';
import FreeminNode, { Choise } from './freemind/Node'; import FreeminNode from './freemind/Node';
import Arrowlink from './freemind/Arrowlink'; import Arrowlink from './freemind/Arrowlink';
import Richcontent from './freemind/Richcontent'; import Richcontent from './freemind/Richcontent';
import Icon from './freemind/Icon'; import Icon from './freemind/Icon';
@ -19,7 +19,7 @@ import Font from './freemind/Font';
type PositionNodeType = {x: number, y: number} type PositionNodeType = {x: number, y: number}
class FreemindExporter implements Exporter { class FreemindExporter extends Exporter {
private mindmap: Mindmap; private mindmap: Mindmap;
private nodeMap: Map<number, FreeminNode> = null; private nodeMap: Map<number, FreeminNode> = null;
@ -31,9 +31,18 @@ class FreemindExporter implements Exporter {
private static wisweToFreeFontSize: Map<number, number> = new Map<number, number>(); private static wisweToFreeFontSize: Map<number, number> = new Map<number, number>();
constructor(mindmap: Mindmap) { constructor(mindmap: Mindmap) {
super(FreemindConstant.SUPPORTED_FREEMIND_VERSION.getVersion(), 'application/xml');
this.mindmap = mindmap; this.mindmap = mindmap;
} }
exportAndEncode(): Promise<string> {
throw new Error('Method not implemented.');
}
getContentType(): string {
throw new Error('Method not implemented.');
}
static { static {
this.wisweToFreeFontSize.set(6, 10); this.wisweToFreeFontSize.set(6, 10);
this.wisweToFreeFontSize.set(8, 12); this.wisweToFreeFontSize.set(8, 12);
@ -73,7 +82,7 @@ class FreemindExporter implements Exporter {
if (centralTopic) { if (centralTopic) {
this.nodeMap.set(centralTopic.getId(), main); this.nodeMap.set(centralTopic.getId(), main);
this.setTopicPropertiesToNode(main, centralTopic, true); this.setTopicPropertiesToNode({ freemindNode: main, mindmapTopic: centralTopic, isRoot: true });
this.addNodeFromTopic(centralTopic, main); this.addNodeFromTopic(centralTopic, main);
} }
@ -91,9 +100,7 @@ class FreemindExporter implements Exporter {
if (relationship.getStartArrow() && relationship.getStartArrow()) arrowlink.setStartarrow('Default'); if (relationship.getStartArrow() && relationship.getStartArrow()) arrowlink.setStartarrow('Default');
const cloudEdge: Array<Choise> = srcNode.getArrowlinkOrCloudOrEdge(); srcNode.setArrowlinkOrCloudOrEdge(arrowlink);
cloudEdge.push(arrowlink);
} }
}); });
@ -103,37 +110,18 @@ class FreemindExporter implements Exporter {
return Promise.resolve(xmlToString); return Promise.resolve(xmlToString);
} }
private addNodeFromTopic(mainTopic: INodeModel, destNode: FreeminNode): void { private setTopicPropertiesToNode({ freemindNode, mindmapTopic, isRoot }: { freemindNode: FreeminNode; mindmapTopic: INodeModel; isRoot: boolean; }): 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()}`); freemindNode.setId(`ID_${mindmapTopic.getId()}`);
const text = mindmapTopic.getText(); const text = mindmapTopic.getText();
if (text) {
if (!text.includes('\n')) { if (!text.includes('\n')) {
freemindNode.setText(text); freemindNode.setText(text);
} else { } else {
const richcontent: Richcontent = this.buildRichcontent(text, 'NODE'); const richcontent: Richcontent = this.buildRichcontent(text, 'NODE');
freemindNode.getArrowlinkOrCloudOrEdge().push(richcontent); freemindNode.setArrowlinkOrCloudOrEdge(richcontent);
}
} }
const wiseShape: string = mindmapTopic.getShapeType(); const wiseShape: string = mindmapTopic.getShapeType();
@ -141,7 +129,7 @@ class FreemindExporter implements Exporter {
freemindNode.setBackgorundColor(this.rgbToHex(mindmapTopic.getBackgroundColor())); freemindNode.setBackgorundColor(this.rgbToHex(mindmapTopic.getBackgroundColor()));
} }
if (wiseShape && !wiseShape) { if (wiseShape) {
const isRootRoundedRectangle = isRoot && TopicShape.ROUNDED_RECT !== wiseShape; const isRootRoundedRectangle = isRoot && TopicShape.ROUNDED_RECT !== wiseShape;
const notIsRootLine = !isRoot && TopicShape.LINE !== wiseShape; const notIsRootLine = !isRoot && TopicShape.LINE !== wiseShape;
@ -159,13 +147,37 @@ class FreemindExporter implements Exporter {
this.addEdgeNode(freemindNode, mindmapTopic); this.addEdgeNode(freemindNode, mindmapTopic);
} }
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({ freemindNode: newNode, mindmapTopic: currentTopic, isRoot: false });
destNode.setArrowlinkOrCloudOrEdge(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 buildRichcontent(text: string, type: string): Richcontent { private buildRichcontent(text: string, type: string): Richcontent {
const richconent: Richcontent = this.objectFactory.createRichcontent(); const richconent: Richcontent = this.objectFactory.createRichcontent();
richconent.setType(type); richconent.setType(type);
const textSplit = text.split('\n');
let html = '<html><body>'; let html = '<html><body>';
text.split('\n').forEach((line: string) => { textSplit.forEach((line: string) => {
html += `<p>${line.trim()}</p>`; html += `<p>${line.trim()}</p>`;
}); });
@ -183,7 +195,7 @@ class FreemindExporter implements Exporter {
const freemindIcon: Icon = new Icon(); const freemindIcon: Icon = new Icon();
branches branches
.filter((node: INodeModel) => node.getText !== undefined) .filter((node: INodeModel) => node.getText())
.forEach((node: INodeModel) => { .forEach((node: INodeModel) => {
node.getFeatures().forEach((feature: FeatureModel) => { node.getFeatures().forEach((feature: FeatureModel) => {
const type = feature.getType(); const type = feature.getType();
@ -196,13 +208,13 @@ class FreemindExporter implements Exporter {
if (type === 'note') { if (type === 'note') {
const note = feature as NoteModel; const note = feature as NoteModel;
const richcontent: Richcontent = this.buildRichcontent(note.getText(), 'NOTE'); const richcontent: Richcontent = this.buildRichcontent(note.getText(), 'NOTE');
freemindNode.getArrowlinkOrCloudOrEdge().push(richcontent); freemindNode.setArrowlinkOrCloudOrEdge(richcontent);
} }
if (type === 'icon') { if (type === 'icon') {
const icon = feature as IconModel; const icon = feature as IconModel;
freemindIcon.setBuiltin(icon.getIconType()); freemindIcon.setBuiltin(icon.getIconType());
freemindNode.getArrowlinkOrCloudOrEdge().push(freemindIcon); freemindNode.setArrowlinkOrCloudOrEdge(freemindIcon);
} }
}); });
}); });
@ -212,7 +224,7 @@ class FreemindExporter implements Exporter {
if (mindmapTopic.getBorderColor()) { if (mindmapTopic.getBorderColor()) {
const edgeNode: Edge = this.objectFactory.createEdge(); const edgeNode: Edge = this.objectFactory.createEdge();
edgeNode.setColor(this.rgbToHex(mindmapTopic.getBorderColor())); edgeNode.setColor(this.rgbToHex(mindmapTopic.getBorderColor()));
freemainMap.getArrowlinkOrCloudOrEdge().push(edgeNode); freemainMap.setArrowlinkOrCloudOrEdge(edgeNode);
} }
} }
@ -267,7 +279,7 @@ class FreemindExporter implements Exporter {
if (font.getSize() === null) { if (font.getSize() === null) {
font.setSize(FreemindExporter.wisweToFreeFontSize.get(8).toString()); font.setSize(FreemindExporter.wisweToFreeFontSize.get(8).toString());
} }
freemindNode.getArrowlinkOrCloudOrEdge().push(font); freemindNode.setArrowlinkOrCloudOrEdge(font);
} }
} }
} }

View File

@ -5,6 +5,7 @@ import Edge from './Edge';
import Font from './Font'; import Font from './Font';
import Icon from './Icon'; import Icon from './Icon';
import Node, { Choise } from './Node'; import Node, { Choise } from './Node';
import Richcontent from './Richcontent';
export default class Map { export default class Map {
protected node: Node; protected node: Node;
@ -38,7 +39,6 @@ export default class Map {
// Create main node // Create main node
const mainNode: Node = this.node; const mainNode: Node = this.node;
mainNode.setCentralNode(true);
const mainNodeElem = mainNode.toXml(document); const mainNodeElem = mainNode.toXml(document);
mapElem.appendChild(mainNodeElem); mapElem.appendChild(mainNodeElem);
@ -53,14 +53,16 @@ export default class Map {
private nodeToXml(childNode: Choise, parentNode: HTMLElement, document: Document): HTMLElement { private nodeToXml(childNode: Choise, parentNode: HTMLElement, document: Document): HTMLElement {
if (childNode instanceof Node) { if (childNode instanceof Node) {
childNode.setCentralNode(false);
const childNodeXml = childNode.toXml(document); const childNodeXml = childNode.toXml(document);
parentNode.appendChild(childNodeXml); parentNode.appendChild(childNodeXml);
childNode.getArrowlinkOrCloudOrEdge().forEach((node: Choise) => { const childrens = childNode.getArrowlinkOrCloudOrEdge();
if (childrens.length > 0) {
childrens.forEach((node: Choise) => {
const nodeXml = this.nodeToXml(node, childNodeXml, document); const nodeXml = this.nodeToXml(node, childNodeXml, document);
childNodeXml.appendChild(nodeXml); childNodeXml.appendChild(nodeXml);
}); });
}
return childNodeXml; return childNodeXml;
} }
@ -100,6 +102,13 @@ export default class Map {
return childNodeXml; return childNodeXml;
} }
if (childNode instanceof Richcontent) {
const childNodeXml = childNode.toXml(document);
parentNode.appendChild(childNodeXml);
return childNodeXml;
}
return parentNode; return parentNode;
} }
} }

View File

@ -41,8 +41,6 @@ class Node {
protected ENCRYPTED_CONTENT: string; protected ENCRYPTED_CONTENT: string;
protected centralNode: boolean;
getArrowlinkOrCloudOrEdge(): Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node> { getArrowlinkOrCloudOrEdge(): Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node> {
if (!this.arrowlinkOrCloudOrEdge) { if (!this.arrowlinkOrCloudOrEdge) {
this.arrowlinkOrCloudOrEdge = new Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this>(); this.arrowlinkOrCloudOrEdge = new Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this>();
@ -114,12 +112,8 @@ class Node {
return this.ENCRYPTED_CONTENT; return this.ENCRYPTED_CONTENT;
} }
getCentralNode(): boolean { setArrowlinkOrCloudOrEdge(value: Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this): void {
return this.centralNode; this.getArrowlinkOrCloudOrEdge().push(value);
}
setArrowlinkOrCloudOrEdge(value: Array<Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | this>): void {
this.arrowlinkOrCloudOrEdge = value;
} }
setBackgorundColor(value: string): void { setBackgorundColor(value: string): void {
@ -186,25 +180,16 @@ class Node {
this.ENCRYPTED_CONTENT = value; this.ENCRYPTED_CONTENT = value;
} }
setCentralNode(value: boolean): void {
this.centralNode = value;
}
toXml(document: Document): HTMLElement { toXml(document: Document): HTMLElement {
// Set node attributes // Set node attributes
const nodeElem = document.createElement('node'); const nodeElem = document.createElement('node');
if (this.centralNode) { if (this.ID) nodeElem.setAttribute('ID', this.ID);
nodeElem.setAttribute('ID', this.ID); if (this.POSITION) nodeElem.setAttribute('POSITION', this.POSITION);
nodeElem.setAttribute('TEXT', this.TEXT); if (this.STYLE) nodeElem.setAttribute('STYLE', this.STYLE);
if (this.BACKGROUND_COLOR) nodeElem.setAttribute('BACKGROUND_COLOR', this.BACKGROUND_COLOR);
return nodeElem; if (this.COLOR) nodeElem.setAttribute('COLOR', this.COLOR);
} if (this.TEXT) nodeElem.setAttribute('TEXT', this.TEXT);
nodeElem.setAttribute('ID', this.ID);
nodeElem.setAttribute('POSITION', this.POSITION);
nodeElem.setAttribute('STYLE', this.STYLE);
nodeElem.setAttribute('TEXT', this.TEXT);
return nodeElem; return nodeElem;
} }

View File

@ -25,6 +25,11 @@ export default class Richcontent {
richcontentElem.setAttribute('TYPE', this.type); richcontentElem.setAttribute('TYPE', this.type);
if (this.html) {
const htmlElement: HTMLElement = document.createElement(this.html);
richcontentElem.appendChild(htmlElement);
}
return richcontentElem; return richcontentElem;
} }
} }

View File

@ -60,7 +60,7 @@ describe('MD export test execution', () => {
describe('MM export test execution', () => { describe('MM export test execution', () => {
test.each(testNames)('Exporting %p suite', async (testName: string) => { test.each(testNames)('Exporting %p suite', async (testName: string) => {
// Load mindmap DOM... // Load mindmap DOM..
const mindmapPath = path.resolve(__dirname, `./input/${testName}.wxml`); const mindmapPath = path.resolve(__dirname, `./input/${testName}.wxml`);
const mapDocument = parseXMLFile(mindmapPath, 'text/xml'); const mapDocument = parseXMLFile(mindmapPath, 'text/xml');

View File

@ -1,7 +1 @@
<map version="1.0.1"> <map version="1.0.1"><node ID="ID_0" TEXT="i18n"><node ID="ID_1" POSITION="right" TEXT="Este es un é con acento"/><node ID="ID_2" POSITION="left" TEXT="Este es una ñ"/><node ID="ID_3" POSITION="right" TEXT="這是一個樣本 Japanise。"/></node></map>
<node ID="ID_0" TEXT="i18n">
<node ID="ID_1" POSITION="right" TEXT="Este es un &#233; con acento"/>
<node ID="ID_2" POSITION="left" TEXT="Este es una &#241;"/>
<node ID="ID_3" POSITION="right" TEXT="&#36889;&#26159;&#19968;&#20491;&#27171;&#26412; Japanise&#12290;"/>
</node>
</map>