Added class freemind import

This commit is contained in:
Ezequiel-Vega 2022-03-08 14:30:34 -03:00
parent 0fcbf6d111
commit a2d655e0b9
11 changed files with 780 additions and 3 deletions

View File

@ -26,7 +26,7 @@
"lint": "eslint src --ext js,ts", "lint": "eslint src --ext js,ts",
"playground": "webpack serve --config webpack.playground.js", "playground": "webpack serve --config webpack.playground.js",
"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/import/*.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"
}, },

View File

@ -1,4 +1,4 @@
import { createDocument } from '@wisemapping/core-js'; import { createDocument, $assert } from '@wisemapping/core-js';
import Arrowlink from './Arrowlink'; import Arrowlink from './Arrowlink';
import Cloud from './Cloud'; import Cloud from './Cloud';
import Edge from './Edge'; import Edge from './Edge';
@ -7,7 +7,7 @@ import Icon from './Icon';
import Node, { Choise } from './Node'; import Node, { Choise } from './Node';
import Richcontent from './Richcontent'; import Richcontent from './Richcontent';
export default class Map { export default class Freemap {
protected node: Node; protected node: Node;
protected version: string; protected version: string;
@ -52,6 +52,115 @@ export default class Map {
return document; return document;
} }
loadFromDom(dom: Document): Freemap {
$assert(dom, 'dom can not be null');
const rootElem = dom.documentElement;
// Is a freemap?
$assert(
rootElem.tagName === 'map',
`This seem not to be a map document. Found tag: ${rootElem.tagName}`,
);
// Start the loading process...
const version = rootElem.getAttribute('version') || '1.0.1';
const freemap: Freemap = new Freemap();
freemap.setVesion(version);
const mainTopicElement = rootElem.firstElementChild;
const mainTopic: Node = this.domToNode(mainTopicElement) as Node;
freemap.setNode(mainTopic);
// Add all the topics nodes...
const childNodes = Array.from(mainTopicElement.childNodes);
const topicsNodes = childNodes
.filter(
(child: ChildNode) => child.nodeType === 1 && (child as Element).tagName === 'node',
)
.map((c) => c as Element);
topicsNodes.forEach((child) => {
const childNode = this.domToNode(child);
mainTopic.setArrowlinkOrCloudOrEdge(childNode);
});
return freemap;
}
private domToNode(nodeElem: Element): Choise {
if (nodeElem.tagName === 'node') {
const node: Node = new Node().loadFromElement(nodeElem);
if (nodeElem.childNodes.length > 0) {
const childElement = Array.from(nodeElem.childNodes)
.filter(
(child: ChildNode) => child.nodeType === 1 && (child as Element).tagName === 'node',
)
.map((c) => c as Element);
childElement.forEach((child) => {
const childNode = new Node().loadFromElement(child);
node.setArrowlinkOrCloudOrEdge(childNode);
});
}
return node;
}
if (nodeElem.tagName === 'font') {
const font: Font = new Font();
if (nodeElem.getAttribute('NAME')) font.setName(nodeElem.getAttribute('NAME'));
if (nodeElem.getAttribute('BOLD')) font.setBold(nodeElem.getAttribute('BOLD'));
if (nodeElem.getAttribute('ITALIC')) font.setItalic(nodeElem.getAttribute('ITALIC'));
if (nodeElem.getAttribute('SIZE')) font.setSize(nodeElem.getAttribute('SIZE'));
return font;
}
if (nodeElem.tagName === 'edge') {
const edge = new Edge();
if (nodeElem.getAttribute('COLOR')) edge.setColor(nodeElem.getAttribute('COLOR'));
if (nodeElem.getAttribute('STYLE')) edge.setStyle(nodeElem.getAttribute('STYLE'));
if (nodeElem.getAttribute('WIDTH')) edge.setWidth(nodeElem.getAttribute('WIDTH'));
return edge;
}
if (nodeElem.tagName === 'arrowlink') {
const arrowlink = new Arrowlink();
if (nodeElem.getAttribute('COLOR')) arrowlink.setColor(nodeElem.getAttribute('COLOR'));
if (nodeElem.getAttribute('DESTINATION')) arrowlink.setDestination(nodeElem.getAttribute('DESTINATION'));
if (nodeElem.getAttribute('ENDARROW')) arrowlink.setEndarrow(nodeElem.getAttribute('ENDARROW'));
if (nodeElem.getAttribute('ENDINCLINATION')) arrowlink.setEndinclination(nodeElem.getAttribute('ENDINCLINATION'));
if (nodeElem.getAttribute('ID')) arrowlink.setId(nodeElem.getAttribute('ID'));
if (nodeElem.getAttribute('STARTARROW')) arrowlink.setStartarrow(nodeElem.getAttribute('STARTARROW'));
if (nodeElem.getAttribute('STARTINCLINATION')) arrowlink.setStartinclination(nodeElem.getAttribute('STARTINCLINATION'));
return arrowlink;
}
if (nodeElem.tagName === 'cloud') {
const cloud = new Cloud();
if (nodeElem.getAttribute('COLOR')) cloud.setColor(nodeElem.getAttribute('COLOR'));
}
if (nodeElem.tagName === 'icon') {
const icon = new Icon();
if (nodeElem.getAttribute('BUILTIN')) icon.setBuiltin(nodeElem.getAttribute('BUILTIN'));
}
if (nodeElem.tagName === 'richcontent') {
const richcontent = new Richcontent();
if (nodeElem.getAttribute('TYPE')) richcontent.setType(nodeElem.getAttribute('TYPE'));
if (nodeElem.lastElementChild) richcontent.setHtml(String(nodeElem.lastElementChild));
}
const nodeDefault = new Node();
return nodeDefault;
}
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.setCentralTopic(false); childNode.setCentralTopic(false);

View File

@ -226,6 +226,46 @@ class Node {
return nodeElem; return nodeElem;
} }
loadFromElement(element: Element): Node {
const node = new Node();
const nodeId = element.getAttribute('ID');
const nodePosition = element.getAttribute('POSITION');
const nodeStyle = element.getAttribute('STYLE');
const nodeBGColor = element.getAttribute('BACKGROUND_COLOR');
const nodeColor = element.getAttribute('COLOR');
const nodeText = element.getAttribute('TEXT');
const nodeLink = element.getAttribute('LINK');
const nodeFolded = element.getAttribute('FOLDED');
const nodeCreated = element.getAttribute('CREATED');
const nodeModified = element.getAttribute('MODIFIED');
const nodeHgap = element.getAttribute('HGAP');
const nodeVgap = element.getAttribute('VGAP');
const nodeWcoords = element.getAttribute('WCOORDS');
const nodeWorder = element.getAttribute('WORDER');
const nodeVshift = element.getAttribute('VSHIFT');
const nodeEncryptedContent = element.getAttribute('ENCRYPTED_CONTENT');
if (nodeId) node.setId(nodeId);
if (nodePosition) node.setPosition(nodePosition);
if (nodeStyle) node.setStyle(nodeStyle);
if (nodeBGColor) node.setBackgorundColor(nodeBGColor);
if (nodeColor) node.setColor(nodeColor);
if (nodeText) node.setText(nodeText);
if (nodeLink) node.setLink(nodeLink);
if (nodeFolded) node.setFolded(nodeFolded);
if (nodeCreated) node.setCreated(nodeCreated);
if (nodeModified) node.setModified(nodeModified);
if (nodeHgap) node.setHgap(nodeHgap);
if (nodeVgap) node.setVgap(nodeVgap);
if (nodeWcoords) node.setWcoords(nodeWcoords);
if (nodeWorder) node.setWorder(nodeWorder);
if (nodeVshift) node.setVshift(nodeVshift);
if (nodeEncryptedContent) node.setEncryptedContent(nodeEncryptedContent);
return node;
}
} }
export type Choise = Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node export type Choise = Arrowlink | Cloud | Edge | Font | Hook | Icon | Richcontent | Node

View File

@ -8,4 +8,56 @@ export default class VersionNumber {
public getVersion(): string { public getVersion(): string {
return this.version; return this.version;
} }
public isGreaterThan(versionNumber: VersionNumber): boolean {
return this.compareTo(versionNumber) < 0;
}
public compareTo(otherObject: VersionNumber): number {
if (this.equals<VersionNumber>(otherObject)) {
return 0;
}
const ownTokinizer = this.getTokinizer();
const otherTokinizer = otherObject.getTokinizer();
for (let i = 0; i < ownTokinizer.length; i++) {
let ownNumber: number;
let ohterNumber: number;
try {
ownNumber = parseInt(ownTokinizer[i], 10);
ohterNumber = parseInt(otherTokinizer[i], 10);
} catch (e) {
return 1;
}
if (ownNumber > ohterNumber) {
return 1;
}
if (ownNumber < ohterNumber) {
return -1;
}
}
return -1;
}
public equals<T>(o: T): boolean {
if (o instanceof VersionNumber) {
return true;
}
if (!(o instanceof VersionNumber)) {
return false;
}
const versionNumber: VersionNumber = o as VersionNumber;
return !(this.version ? this.version !== versionNumber.version : versionNumber.version);
}
private getTokinizer(): Array<string> {
return this.getVersion().split('.');
}
} }

View File

@ -0,0 +1,10 @@
import IconModel from '../model/IconModel';
export default class FreemindIconConverter {
private static freeIdToIcon: Map<string, IconModel> = new Map<string, IconModel>();
public static toWiseId(iconId: string): number | null {
const result: IconModel = this.freeIdToIcon.get(iconId);
return result ? result.getId() : null;
}
}

View File

@ -0,0 +1,406 @@
import Importer from './Importer';
import Mindmap from '../model/Mindmap';
import RelationshipModel from '../model/RelationshipModel';
import NodeModel from '../model/NodeModel';
import { TopicShape } from '../model/INodeModel';
import LinkModel from '../model/LinkModel';
import IconModel from '../model/IconModel';
import FreemindConstant from '../export/freemind/FreemindConstant';
import FreemindMap from '../export/freemind/Map';
import FreemindNode, { Choise } from '../export/freemind/Node';
import FreemindFont from '../export/freemind/Font';
import FreemindEdge from '../export/freemind/Edge';
import FreemindIcon from '../export/freemind/Icon';
import FreemindHook from '../export/freemind/Hook';
import FreemindRichcontent from '../export/freemind/Richcontent';
import FreemindArrowLink from '../export/freemind/Arrowlink';
import VersionNumber from '../export/freemind/importer/VersionNumber';
import FreemindIconConverter from './FreemindIconConverter';
import NoteModel from '../model/NoteModel';
export default class FreemindImporter extends Importer {
private mindmap: Mindmap;
private freemindMap: FreemindMap;
private nodesmap: Map<string, NodeModel>;
private relationship: Array<RelationshipModel>;
private currentId: number;
constructor(map: FreemindMap) {
super();
this.freemindMap = map;
}
import(nameMap: string, description: string): Promise<Mindmap> {
this.mindmap = new Mindmap(nameMap);
this.nodesmap = new Map<string, NodeModel>();
this.relationship = new Array<RelationshipModel>();
const version: string = this.freemindMap.getVersion();
if (!version || version.startsWith('freeplane')) {
throw new Error('You seems to be be trying to import a Freeplane map. FreePlane is not supported format.');
} else {
const mapVersion: VersionNumber = new VersionNumber(version);
if (mapVersion.isGreaterThan(FreemindConstant.SUPPORTED_FREEMIND_VERSION)) {
throw new Error(`FreeMind version ${mapVersion.getVersion()} is not supported.`);
}
}
const freeNode: FreemindNode = this.freemindMap.getNode();
this.mindmap.setVersion(FreemindConstant.CODE_VERSION);
const wiseTopic = this.mindmap.createNode('CentralTopic', 0);
wiseTopic.setId(this.currentId++);
wiseTopic.setPosition(0, 0);
this.convertNodeProperties(freeNode, wiseTopic);
wiseTopic.setShapeType(TopicShape.ROUNDED_RECT);
this.nodesmap.set(freeNode.getId(), wiseTopic);
this.convertChildNodes(freeNode, wiseTopic, this.mindmap, 1);
this.addRelationship(this.mindmap);
this.mindmap.setDescription(description);
return Promise.resolve(this.mindmap);
}
private addRelationship(mindmap: Mindmap): void {
const mapRelaitonship: Array<RelationshipModel> = mindmap.getRelationships();
mapRelaitonship.forEach((relationship: RelationshipModel) => {
this.fixRelationshipControlPoints(relationship);
// Fix dest ID
const destId: string = relationship.getDestCtrlPoint();
const destTopic: NodeModel = this.nodesmap.get(destId);
relationship.setDestCtrlPoint(destTopic.getId());
// Fix src ID
const srcId: string = relationship.getSrcCtrlPoint();
const srcTopic: NodeModel = this.nodesmap.get(srcId);
relationship.setSrcCtrlPoint(srcTopic.getId());
mapRelaitonship.push(relationship);
});
}
private fixRelationshipControlPoints(relationship: RelationshipModel): void {
const srcTopic: NodeModel = this.nodesmap.get(relationship.getToNode().toString());
const destNode: NodeModel = this.nodesmap.get(relationship.getFromNode().toString());
// Fix x coord
const srcCtrlPoint: string = relationship.getSrcCtrlPoint();
if (srcCtrlPoint) {
const coords = srcTopic.getPosition();
if (coords.x < 0) {
const x = coords.x * -1;
relationship.setSrcCtrlPoint(`${x},${coords.y}`);
// Fix coord
if (srcTopic.getOrder() && srcTopic.getOrder() % 2 !== 0) {
const y = coords.y * -1;
relationship.setSrcCtrlPoint(`${coords.x},${y}`);
}
}
}
const destCtrlPoint: string = relationship.getDestCtrlPoint();
if (destCtrlPoint) {
const coords = destNode.getPosition();
if (coords.x < 0) {
const x = coords.x * -1;
relationship.setDestCtrlPoint(`${x},${coords.y}`);
}
if (destNode.getOrder() && destNode.getOrder() % 2 !== 0) {
const y = coords.y * -1;
relationship.setDestCtrlPoint(`${coords.x},${y}`);
}
}
}
private convertNodeProperties(freeNode: FreemindNode, wiseTopic: NodeModel): void {
const text: string = freeNode.getText();
wiseTopic.setText(text);
const bgColor: string = freeNode.getBackgorundColor();
wiseTopic.setBackgroundColor(bgColor);
const shape = this.getShapeFromFreeNode(freeNode);
wiseTopic.setShapeType(shape);
// Check for style...
const fontStyle = this.generateFontStyle(freeNode, null);
if (fontStyle) {
wiseTopic.setFontStyle(fontStyle);
}
// Is there any link...
const url: string = freeNode.getLink();
if (url) {
const link: LinkModel = new LinkModel({ url });
wiseTopic.addFeature(link);
}
const folded = Boolean(freeNode.getFolded());
wiseTopic.setChildrenShrunken(folded);
}
private convertChildNodes(freeParent: FreemindNode, wiseParent: NodeModel, mindmap: Mindmap, depth: number): void {
const freeChilden = freeParent.getArrowlinkOrCloudOrEdge();
let currentWiseTopic: NodeModel = wiseParent;
let order = 0;
let firstLevelRightOrder = 0;
let firstLevelLeftOrder = 1;
freeChilden.forEach((child) => {
if (child instanceof FreemindNode) {
const freeChild: FreemindNode = child as FreemindNode;
const wiseChild = mindmap.createNode('MainTopic', this.currentId++);
this.nodesmap.set(freeChild.getId(), wiseChild);
let norder: number;
if (depth !== 1) {
norder = order++;
} else if (freeChild.getPosition() && freeChild.getPosition() === FreemindConstant.POSITION_LEFT) {
norder = firstLevelLeftOrder;
firstLevelLeftOrder += 2;
} else {
norder = firstLevelRightOrder;
firstLevelRightOrder += 2;
}
wiseChild.setOrder(norder);
// Convert node position...
const childrenCountSameSide = this.getChildrenCountSameSide(freeChilden, freeChild);
const position: {x: number, y: number} = this.convertPosition(wiseParent, freeChild, depth, norder, childrenCountSameSide);
wiseChild.setPosition(position.x, position.y);
// Convert the rest of the node properties...
this.convertNodeProperties(freeChild, wiseChild);
this.convertChildNodes(freeChild, wiseChild, mindmap, depth + 1);
if (wiseChild !== wiseParent) {
wiseParent.append(wiseChild);
}
currentWiseTopic = wiseChild;
}
if (child instanceof FreemindFont) {
const font: FreemindFont = child as FreemindFont;
const fontStyle: string = this.generateFontStyle(freeParent, font);
if (fontStyle) {
currentWiseTopic.setFontStyle(fontStyle);
}
}
if (child instanceof FreemindEdge) {
const edge: FreemindEdge = child as FreemindEdge;
currentWiseTopic.setBackgroundColor(edge.getColor());
}
if (child instanceof FreemindIcon) {
const freeIcon: FreemindIcon = child as FreemindIcon;
const iconId: string = freeIcon.getBuiltin();
const wiseIconId = FreemindIconConverter.toWiseId(iconId);
if (wiseIconId) {
const mindmapIcon: IconModel = new IconModel({ id: wiseIconId });
currentWiseTopic.addFeature(mindmapIcon);
}
}
if (child instanceof FreemindHook) {
const hook: FreemindHook = child as FreemindHook;
const mindmapNote: NoteModel = new NoteModel({ text: '' });
let textNote: string = hook.getText();
if (!textNote) {
textNote = FreemindConstant.EMPTY_NOTE;
mindmapNote.setText(textNote);
currentWiseTopic.addFeature(mindmapNote);
}
}
if (child instanceof FreemindRichcontent) {
const content: FreemindRichcontent = child as FreemindRichcontent;
const type: string = content.getType();
if (type === FreemindConstant.NODE_TYPE) {
const text = this.html2text(content);
currentWiseTopic.setText(text);
} else {
let text = this.html2text(content);
const mindmapNote: NoteModel = new NoteModel({ text: '' });
text = text || FreemindConstant.EMPTY_NOTE;
mindmapNote.setText(text);
currentWiseTopic.addFeature(mindmapNote);
}
}
if (child instanceof FreemindArrowLink) {
const arrow: FreemindArrowLink = child as FreemindArrowLink;
const relationship: RelationshipModel = new RelationshipModel(0, 0);
const destId: string = arrow.getDestination();
relationship.setSrcCtrlPoint(destId);
relationship.setDestCtrlPoint(freeParent.getId());
const endinclination: string = arrow.getEndInclination();
if (endinclination) {
const inclination: Array<string> = endinclination.split(';');
relationship.setDestCtrlPoint(`${inclination[0]},${inclination[1]}`);
}
const startinclination: string = arrow.getStartinclination();
if (startinclination) {
const inclination: Array<string> = startinclination.split(';');
relationship.setSrcCtrlPoint(`${inclination[0]},${inclination[1]}`);
}
const endarrow: string = arrow.getEndarrow();
if (endarrow) {
relationship.setEndArrow(endarrow.toLowerCase() !== 'none');
}
const startarrow: string = arrow.getStartarrow();
if (startarrow) {
relationship.setStartArrow(startarrow.toLowerCase() !== 'none');
}
relationship.setLineType(3);
this.relationship.push(relationship);
}
});
}
private getChildrenCountSameSide(freeChilden: Array<Choise>, freeChild: FreemindNode): number {
let result = 0;
let childSide: string = freeChild.getPosition();
if (!childSide) {
childSide = FreemindConstant.POSITION_RIGHT;
}
freeChilden.forEach((child) => {
if (child instanceof FreemindNode) {
const node: FreemindNode = child as FreemindNode;
let side = node.getPosition();
if (!side) {
side = FreemindConstant.POSITION_RIGHT;
}
if (childSide === side) {
result++;
}
}
});
return result;
}
private getShapeFromFreeNode(node: FreemindNode): string {
let result: string = node.getStyle();
if (result === 'bubble') {
result = TopicShape.ROUNDED_RECT;
} else if (node.getBackgorundColor()) {
result = TopicShape.RECTANGLE;
} else {
result = TopicShape.LINE;
}
return result;
}
private generateFontStyle(node: FreemindNode, font: FreemindFont | undefined): string {
const fontStyle: Array<string> = [];
// Font family
if (font) {
fontStyle.push(font.getName());
}
fontStyle.push(';');
// Font Size
if (font) {
const fontSize: number = ((!font.getSize() || parseInt(font.getSize(), 10) < 8) ? FreemindConstant.FONT_SIZE_NORMAL : parseInt(font.getSize(), 10));
let wiseFontSize: number = FreemindConstant.FONT_SIZE_SMALL;
if (fontSize >= 24) {
wiseFontSize = FreemindConstant.FONT_SIZE_HUGE;
}
if (fontSize >= 16) {
wiseFontSize = FreemindConstant.FONT_SIZE_LARGE;
}
if (fontSize >= 8) {
wiseFontSize = FreemindConstant.FONT_SIZE_NORMAL;
}
fontStyle.push(wiseFontSize.toString());
}
fontStyle.push(';');
// Font Color
const color: string = node.getColor();
if (color && color !== '') {
fontStyle.push(color);
}
fontStyle.push(';');
// Font Italic
if (font) {
const hasItalic = Boolean(font.getItalic());
fontStyle.push(hasItalic ? FreemindConstant.ITALIC : '');
}
fontStyle.push(';');
const result: string = fontStyle.join('');
return result;
}
private convertPosition(wiseParent: NodeModel, freeChild: FreemindNode, depth: number, order: number, childrenCount: number): {x: number, y: number} {
let x: number = FreemindConstant.CENTRAL_TO_TOPIC_DISTANCE + ((depth - 1) * FreemindConstant.TOPIC_TO_TOPIC_DISTANCE);
if (depth === 1) {
const side: string = freeChild.getPosition();
x *= (side && FreemindConstant.POSITION_LEFT === side ? -1 : 1);
} else {
const position = wiseParent.getPosition();
x *= position.x < 0 ? 1 : -1;
}
let y: number;
if (depth === 1) {
if (order % 2 === 0) {
const multiplier = ((order + 1) - childrenCount) * 2;
y = multiplier * FreemindConstant.ROOT_LEVEL_TOPIC_HEIGHT;
} else {
const multiplier = (order - childrenCount) * 2;
y = multiplier * FreemindConstant.ROOT_LEVEL_TOPIC_HEIGHT;
}
} else {
const position = wiseParent.getPosition();
y = position.y - ((childrenCount / 2) * FreemindConstant.SECOND_LEVEL_TOPIC_HEIGHT - (order * FreemindConstant.SECOND_LEVEL_TOPIC_HEIGHT));
}
return {
x,
y,
};
}
private html2text(content: FreemindRichcontent): string {
const parser = new DOMParser();
const doc = parser.parseFromString(content.getHtml(), 'text/html');
doc.querySelector('br').append('\\n');
doc.querySelector('p').append('\\n');
doc.querySelector('div').append('\\n');
return doc.textContent.replace('\\\\n', '\\n').trim();
}
}

View File

@ -0,0 +1,5 @@
import Mindmap from '../model/Mindmap';
export default abstract class Importer {
abstract import(nameMap: string, description: string): Promise<Mindmap>;
}

View File

@ -0,0 +1,19 @@
import FreemindImporter from './FreemindImporter';
import FreemindMap from '../export/freemind/Map';
import Importer from './Importer';
type textType = 'mm';
type mapType = FreemindMap
export default class TextImporterFactory {
static create(type: textType, map: mapType): Importer {
let result: Importer;
switch (type) {
case 'mm':
result = new FreemindImporter(map);
return result;
default:
throw new Error(`Unsupported type ${type}`);
}
}
}

View File

@ -0,0 +1,36 @@
import path from 'path';
import fs from 'fs';
// eslint-disable-next-line import/no-extraneous-dependencies
import { test } from '@jest/globals';
import { parseXMLFile } from '../export/Helper';
import FreemindMap from '../../../src/components/export/freemind/Map';
import TextImporterFactory from '../../../src/components/import/TextImporterFactory';
import XMLSerializerFactory from '../../../src/components/persistence/XMLSerializerFactory';
import Mindmap from '../../../src/components/model/Mindmap';
const testNames = fs
.readdirSync(path.resolve(__dirname, './input/'))
.map((filename: string) => filename.split('.')[0]);
describe('MMa import test execution', () => {
test.each(testNames)('Importing %p suite', async (testName: string) => {
// load freemap...
const freemapPath = path.resolve(__dirname, `./input/${testName}.mm`);
const mapDocument = parseXMLFile(freemapPath, 'text/xml');
const freemap: FreemindMap = new FreemindMap().loadFromDom(mapDocument);
// Load mindmap DOM..
const mindmapPath = path.resolve(__dirname, `./expected/${testName}.wxml`);
const mindmapMapDocument = parseXMLFile(mindmapPath, 'text/xml');
// Convert to mindmap...
const serializer = XMLSerializerFactory.createInstanceFromDocument(mindmapMapDocument);
const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName);
const importer = TextImporterFactory.create('mm', freemap);
const mindmapImport: Mindmap = await importer.import(testName, '');
expect(mindmapImport).toStrictEqual(mindmap);
});
});

View File

@ -0,0 +1,49 @@
<map name="58984" version="tango">
<topic central="true" text="SaberMás" id="1">
<topic position="271,-39" order="8" text="Utilización de medios de expresión artística, digitales y analógicos"
id="5"/>
<topic position="-181,-17" order="5" text="Precio también limitado: 100-120?" id="9"/>
<topic position="132,165" order="14" text="Talleres temáticos" id="2">
<topic position="242,57" order="0" text="Naturaleza" id="13">
<topic position="362,57" order="0" text="Animales, Plantas, Piedras" id="17"/>
</topic>
<topic position="245,84" order="1" text="Arqueología" id="21"/>
<topic position="236,138" order="3" text="Energía" id="18"/>
<topic position="244,192" order="5" text="Astronomía" id="16"/>
<topic position="245,219" order="6" text="Arquitectura" id="20"/>
<topic position="234,246" order="7" text="Cocina" id="11"/>
<topic position="234,273" order="8" text="Poesía" id="24"/>
<topic position="256,111" order="2" text="Culturas Antiguas" id="25">
<topic position="378,111" order="0" text="Egipto, Grecia, China..." id="26"/>
</topic>
<topic position="248,165" order="4" text="Paleontología" id="38"/>
</topic>
<topic position="-168,-49" order="3" text="Duración limitada: 5-6 semanas" id="6"/>
<topic position="-181,16" order="7" text="Niños y niñas que quieren saber más" id="7"/>
<topic position="-184,-81" order="1" text="Alternativa a otras actividades de ocio" id="8"/>
<topic position="255,-6" order="10" text="Uso de la tecnología durante todo el proceso de aprendizaje" id="23"/>
<topic position="336,-137" order="2"
text="Estructura PBL: aprendemos cuando buscamos respuestas a nuestras propias preguntas " id="3"/>
<topic position="238,-105" order="4" text="Trabajo basado en la experimentación y en la investigación" id="4"/>
<topic position="-201,48" order="9" text="De 8 a 12 años, sin separación por edades" id="10"/>
<topic position="-146,81" order="11" text="Máximo 10/1 por taller" id="19"/>
<topic position="211,-72" order="6" text="Actividades centradas en el contexto cercano" id="37"/>
<topic position="303,27" order="12"
text="Flexibilidad en el uso de las lenguas de trabajo (inglés, castellano, esukara?)" id="22"/>
<topic position="206,-220" order="0" text="Complementamos el trabajo de la escuela" shape="rounded rectagle"
id="27">
<note><![CDATA[Todos los contenidos de los talleres están relacionados con el currículo de la enseñanza básica.
A diferencia de la práctica tradicional, pretendemos ahondar en el conocimiento partiendo de lo que realmente interesa al niño o niña,
ayudándole a que encuentre respuesta a las preguntas que él o ella se plantea.
Por ese motivo, SaberMás proyecta estar al lado de los niños que necesitan una motivación extra para entender la escuela y fluir en ella,
y también al lado de aquellos a quienes la curiosidad y las ganas de saber les lleva más allá.]]></note>
<topic position="477,-220" order="2" text="Cada uno va a su ritmo, y cada cual pone sus límites" id="30"/>
<topic position="425,-193" order="3" text="Aprendemos todos de todos" id="31"/>
<topic position="440,-167" order="4" text="Valoramos lo que hemos aprendido" id="33"/>
<topic position="468,-273" order="0" text="SaberMás trabaja con, desde y para la motivación" shape="line"
id="28"/>
<topic position="458,-247" order="1" text="Trabajamos en equipo en nuestros proyectos " id="32"/>
</topic>
</topic>
</map>

View File

@ -0,0 +1,51 @@
<map version="1.0.1">
<node ID="ID_1" TEXT="SaberMás">
<node ID="ID_5" POSITION="right" STYLE="fork" TEXT="Utilización de medios de expresión artística, digitales y analógicos"/>
<node ID="ID_9" POSITION="left" STYLE="fork" TEXT="Precio también limitado: 100-120?"/>
<node ID="ID_2" POSITION="right" STYLE="fork" TEXT="Talleres temáticos">
<node ID="ID_13" POSITION="right" STYLE="fork" TEXT="Naturaleza">
<node ID="ID_17" POSITION="right" STYLE="fork" TEXT="Animales, Plantas, Piedras"/>
</node>
<node ID="ID_21" POSITION="right" STYLE="fork" TEXT="Arqueología"/>
<node ID="ID_18" POSITION="right" STYLE="fork" TEXT="Energía"/>
<node ID="ID_16" POSITION="right" STYLE="fork" TEXT="Astronomía"/>
<node ID="ID_20" POSITION="right" STYLE="fork" TEXT="Arquitectura"/>
<node ID="ID_11" POSITION="right" STYLE="fork" TEXT="Cocina"/>
<node ID="ID_24" POSITION="right" STYLE="fork" TEXT="Poesía"/>
<node ID="ID_25" POSITION="right" STYLE="fork" TEXT="Culturas Antiguas">
<node ID="ID_26" POSITION="right" STYLE="fork" TEXT="Egipto, Grecia, China..."/>
</node>
<node ID="ID_38" POSITION="right" STYLE="fork" TEXT="Paleontología"/>
</node>
<node ID="ID_6" POSITION="left" STYLE="fork" TEXT="Duración limitada: 5-6 semanas"/>
<node ID="ID_7" POSITION="left" STYLE="fork" TEXT="Niños y niñas que quieren saber más"/>
<node ID="ID_8" POSITION="left" STYLE="fork" TEXT="Alternativa a otras actividades de ocio"/>
<node ID="ID_23" POSITION="right" STYLE="fork" TEXT="Uso de la tecnología durante todo el proceso de aprendizaje"/>
<node ID="ID_3" POSITION="right" STYLE="fork" TEXT="Estructura PBL: aprendemos cuando buscamos respuestas a nuestras propias preguntas "/>
<node ID="ID_4" POSITION="right" STYLE="fork" TEXT="Trabajo basado en la experimentación y en la investigación"/>
<node ID="ID_10" POSITION="left" STYLE="fork" TEXT="De 8 a 12 años, sin separación por edades"/>
<node ID="ID_19" POSITION="left" STYLE="fork" TEXT="Máximo 10/1 por taller"/>
<node ID="ID_37" POSITION="right" STYLE="fork" TEXT="Actividades centradas en el contexto cercano"/>
<node ID="ID_22" POSITION="right" STYLE="fork" TEXT="Flexibilidad en el uso de las lenguas de trabajo (inglés, castellano, esukara?)"/>
<node ID="ID_27" POSITION="right" STYLE="bubble" TEXT="Complementamos el trabajo de la escuela">
<richcontent TYPE="NOTE">
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<p>Todos los contenidos de los talleres están relacionados con el currículo de la enseñanza básica.</p>
<p>A diferencia de la práctica tradicional, pretendemos ahondar en el conocimiento partiendo de lo que realmente interesa al niño o niña,</p>
<p>ayudándole a que encuentre respuesta a las preguntas que él o ella se plantea.</p>
<p></p>
<p>Por ese motivo, SaberMás proyecta estar al lado de los niños que necesitan una motivación extra para entender la escuela y fluir en ella,</p>
<p>y también al lado de aquellos a quienes la curiosidad y las ganas de saber les lleva más allá.</p>
</body>
</html>
</richcontent>
<node ID="ID_30" POSITION="right" STYLE="fork" TEXT="Cada uno va a su ritmo, y cada cual pone sus límites"/>
<node ID="ID_31" POSITION="right" STYLE="fork" TEXT="Aprendemos todos de todos"/>
<node ID="ID_33" POSITION="right" STYLE="fork" TEXT="Valoramos lo que hemos aprendido"/>
<node ID="ID_28" POSITION="right" TEXT="SaberMás trabaja con, desde y para la motivación"/>
<node ID="ID_32" POSITION="right" STYLE="fork" TEXT="Trabajamos en equipo en nuestros proyectos "/>
</node>
</node>
</map>