universal_table/app/assets/javascripts/mind_map/jsmind/jsmind.format.js

534 lines
18 KiB
JavaScript
Executable File

import { __author__, __version__, logger, Direction } from './jsmind.common.js'
import { Mind } from './jsmind.mind.js'
import { Node } from './jsmind.node.js'
import { util } from './jsmind.util.js'
const DEFAULT_META = { name: 'jsMind', author: __author__, version: __version__ }
export const format = {
node_tree: {
example: {
meta: DEFAULT_META,
format: 'node_tree',
data: { id: 'root', topic: 'jsMind node_tree example' },
},
get_mind: function (source) {
var df = format.node_tree
var mind = new Mind()
mind.name = source.meta.name
mind.author = source.meta.author
mind.version = source.meta.version
df._parse(mind, source.data)
return mind
},
get_data: function (mind) {
var df = format.node_tree
var json = {}
json.meta = {
name: mind.name,
author: mind.author,
version: mind.version,
}
json.format = 'node_tree'
json.data = df._build_node(mind.root)
return json
},
_parse: function (mind, node_root) {
var df = format.node_tree
var data = df._extract_data(node_root)
mind.set_root(node_root.id, node_root.topic, data)
if ('children' in node_root) {
var children = node_root.children
for (var i = 0; i < children.length; i++) {
df._extract_subnode(mind, mind.root, children[i])
}
}
},
_extract_data: function (node_json) {
var data = {}
for (var k in node_json) {
if (
k == 'id' ||
k == 'topic' ||
k == 'children' ||
k == 'direction' ||
k == 'expanded'
) {
continue
}
data[k] = node_json[k]
}
return data
},
_extract_subnode: function (mind, node_parent, node_json) {
var df = format.node_tree
var data = df._extract_data(node_json)
var d = null
if (node_parent.isroot) {
d = node_json.direction == 'left' ? Direction.left : Direction.right
}
var node = mind.add_node(
node_parent,
node_json.id,
node_json.topic,
data,
d,
node_json.expanded
)
if (!!node_json['children']) {
var children = node_json.children
for (var i = 0; i < children.length; i++) {
df._extract_subnode(mind, node, children[i])
}
}
},
_build_node: function (node) {
var df = format.node_tree
if (!(node instanceof Node)) {
return
}
var o = {
id: node.id,
topic: node.topic,
expanded: node.expanded,
}
if (!!node.parent && node.parent.isroot) {
o.direction = node.direction == Direction.left ? 'left' : 'right'
}
if (node.data != null) {
var node_data = node.data
for (var k in node_data) {
o[k] = node_data[k]
}
}
var children = node.children
if (children.length > 0) {
o.children = []
for (var i = 0; i < children.length; i++) {
o.children.push(df._build_node(children[i]))
}
}
return o
},
},
node_array: {
example: {
meta: DEFAULT_META,
format: 'node_array',
data: [{ id: 'root', topic: 'jsMind node_array example', isroot: true }],
},
get_mind: function (source) {
var df = format.node_array
var mind = new Mind()
mind.name = source.meta.name
mind.author = source.meta.author
mind.version = source.meta.version
df._parse(mind, source.data)
return mind
},
get_data: function (mind) {
var df = format.node_array
var json = {}
json.meta = {
name: mind.name,
author: mind.author,
version: mind.version,
}
json.format = 'node_array'
json.data = []
df._array(mind, json.data)
return json
},
_parse: function (mind, node_array) {
var df = format.node_array
var nodes = node_array.slice(0)
// reverse array for improving looping performance
nodes.reverse()
var root_node = df._extract_root(mind, nodes)
if (!!root_node) {
df._extract_subnode(mind, root_node, nodes)
} else {
logger.error('root node can not be found')
}
},
_extract_root: function (mind, node_array) {
var df = format.node_array
var i = node_array.length
while (i--) {
if ('isroot' in node_array[i] && node_array[i].isroot) {
var root_json = node_array[i]
var data = df._extract_data(root_json)
var node = mind.set_root(root_json.id, root_json.topic, data)
node_array.splice(i, 1)
return node
}
}
return null
},
_extract_subnode: function (mind, parent_node, node_array) {
var df = format.node_array
var i = node_array.length
var node_json = null
var data = null
var extract_count = 0
while (i--) {
node_json = node_array[i]
if (node_json.parentid == parent_node.id) {
data = df._extract_data(node_json)
var d = null
var node_direction = node_json.direction
if (!!node_direction) {
d = node_direction == 'left' ? Direction.left : Direction.right
}
var node = mind.add_node(
parent_node,
node_json.id,
node_json.topic,
data,
d,
node_json.expanded
)
node_array.splice(i, 1)
extract_count++
var sub_extract_count = df._extract_subnode(mind, node, node_array)
if (sub_extract_count > 0) {
// reset loop index after extract subordinate node
i = node_array.length
extract_count += sub_extract_count
}
}
}
return extract_count
},
_extract_data: function (node_json) {
var data = {}
for (var k in node_json) {
if (
k == 'id' ||
k == 'topic' ||
k == 'parentid' ||
k == 'isroot' ||
k == 'direction' ||
k == 'expanded'
) {
continue
}
data[k] = node_json[k]
}
return data
},
_array: function (mind, node_array) {
var df = format.node_array
df._array_node(mind.root, node_array)
},
_array_node: function (node, node_array) {
var df = format.node_array
if (!(node instanceof Node)) {
return
}
var o = {
id: node.id,
topic: node.topic,
expanded: node.expanded,
}
if (!!node.parent) {
o.parentid = node.parent.id
}
if (node.isroot) {
o.isroot = true
}
if (!!node.parent && node.parent.isroot) {
o.direction = node.direction == Direction.left ? 'left' : 'right'
}
if (node.data != null) {
var node_data = node.data
for (var k in node_data) {
o[k] = node_data[k]
}
}
node_array.push(o)
var ci = node.children.length
for (var i = 0; i < ci; i++) {
df._array_node(node.children[i], node_array)
}
},
},
freemind: {
example: {
meta: DEFAULT_META,
format: 'freemind',
data: '<map version="1.0.1"><node ID="root" TEXT="jsMind freemind example"/></map>',
},
get_mind: function (source) {
var df = format.freemind
var mind = new Mind()
mind.name = source.meta.name
mind.author = source.meta.author
mind.version = source.meta.version
var xml = source.data
var xml_doc = df._parse_xml(xml)
var xml_root = df._find_root(xml_doc)
df._load_node(mind, null, xml_root)
return mind
},
get_data: function (mind) {
var df = format.freemind
var json = {}
json.meta = {
name: mind.name,
author: mind.author,
version: mind.version,
}
json.format = 'freemind'
var xml_lines = []
xml_lines.push('<map version="1.0.1">')
df._build_map(mind.root, xml_lines)
xml_lines.push('</map>')
json.data = xml_lines.join('')
return json
},
_parse_xml: function (xml) {
var xml_doc = null
if (window.DOMParser) {
var parser = new DOMParser()
xml_doc = parser.parseFromString(xml, 'text/xml')
} else {
// Internet Explorer
xml_doc = new ActiveXObject('Microsoft.XMLDOM')
xml_doc.async = false
xml_doc.loadXML(xml)
}
return xml_doc
},
_find_root: function (xml_doc) {
var nodes = xml_doc.childNodes
var node = null
var root = null
var n = null
for (var i = 0; i < nodes.length; i++) {
n = nodes[i]
if (n.nodeType == 1 && n.tagName == 'map') {
node = n
break
}
}
if (!!node) {
var ns = node.childNodes
node = null
for (var i = 0; i < ns.length; i++) {
n = ns[i]
if (n.nodeType == 1 && n.tagName == 'node') {
node = n
break
}
}
}
return node
},
_load_node: function (mind, parent_node, xml_node) {
var df = format.freemind
var node_id = xml_node.getAttribute('ID')
var node_topic = xml_node.getAttribute('TEXT')
var node_folded = xml_node.getAttribute('FOLDED')
// look for richcontent
if (node_topic == null) {
var topic_children = xml_node.childNodes
var topic_child = null
for (var i = 0; i < topic_children.length; i++) {
topic_child = topic_children[i]
if (topic_child.nodeType == 1 && topic_child.tagName === 'richcontent') {
node_topic = topic_child.textContent
break
}
}
}
var node_data = df._load_attributes(xml_node)
var node_expanded =
'expanded' in node_data ? node_data.expanded == 'true' : node_folded != 'true'
delete node_data.expanded
var node_position = xml_node.getAttribute('POSITION')
var node_direction = null
if (!!node_position) {
node_direction = node_position == 'left' ? Direction.left : Direction.right
}
var node = null
if (!!parent_node) {
node = mind.add_node(
parent_node,
node_id,
node_topic,
node_data,
node_direction,
node_expanded
)
} else {
node = mind.set_root(node_id, node_topic, node_data)
}
var children = xml_node.childNodes
var child = null
for (var i = 0; i < children.length; i++) {
child = children[i]
if (child.nodeType == 1 && child.tagName == 'node') {
df._load_node(mind, node, child)
}
}
},
_load_attributes: function (xml_node) {
var children = xml_node.childNodes
var attr = null
var attr_data = {}
for (var i = 0; i < children.length; i++) {
attr = children[i]
if (attr.nodeType == 1 && attr.tagName === 'attribute') {
attr_data[attr.getAttribute('NAME')] = attr.getAttribute('VALUE')
}
}
return attr_data
},
_build_map: function (node, xml_lines) {
var df = format.freemind
var pos = null
if (!!node.parent && node.parent.isroot) {
pos = node.direction === Direction.left ? 'left' : 'right'
}
xml_lines.push('<node')
xml_lines.push(' ID="' + node.id + '"')
if (!!pos) {
xml_lines.push(' POSITION="' + pos + '"')
}
if (!node.expanded) {
xml_lines.push(' FOLDED="true"')
}
xml_lines.push(' TEXT="' + df._escape(node.topic) + '">')
// for attributes
var node_data = node.data
if (node_data != null) {
for (var k in node_data) {
xml_lines.push('<attribute NAME="' + k + '" VALUE="' + node_data[k] + '"/>')
}
}
// for children
var children = node.children
for (var i = 0; i < children.length; i++) {
df._build_map(children[i], xml_lines)
}
xml_lines.push('</node>')
},
_escape: function (text) {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/'/g, '&apos;')
.replace(/"/g, '&quot;')
},
},
text: {
example: {
meta: DEFAULT_META,
format: 'text',
data: 'jsMind text example\n node1\n node1-sub\n node1-sub\n node2',
},
_line_regex: /\s*/,
get_mind: function (source) {
var df = format.text
var mind = new Mind()
mind.name = source.meta.name
mind.author = source.meta.author
mind.version = source.meta.version
var lines = source.data.split(/\n|\r/)
df._fill_nodes(mind, lines, 0, 0)
return mind
},
_fill_nodes: function (mind, lines) {
let node_path = []
let i = 0
while (i < lines.length) {
let line = lines[i]
let level = line.match(/\s*/)[0].length
let topic = line.substr(level)
if (level == 0 && node_path.length > 0) {
log.error('more than 1 root node was found: ' + topic)
return
}
if (level > node_path.length) {
log.error('a suspended node was found: ' + topic)
return
}
let diff = node_path.length - level
while (diff--) {
node_path.pop()
}
if (level == 0 && node_path.length == 0) {
let node = mind.set_root(util.uuid.newid(), topic)
node_path.push(node)
} else {
let node = mind.add_node(
node_path[level - 1],
util.uuid.newid(),
topic,
{},
null
)
node_path.push(node)
}
i++
}
node_path.length = 0
},
get_data: function (mind) {
var df = format.text
var json = {}
json.meta = {
name: mind.name,
author: mind.author,
version: mind.version,
}
json.format = 'text'
let lines = []
df._build_lines(lines, [mind.root], 0)
json.data = lines.join('\n')
return json
},
_build_lines: function (lines, nodes, level) {
let prefix = new Array(level + 1).join(' ')
for (let node of nodes) {
lines.push(prefix + node.topic)
if (!!node.children) {
format.text._build_lines(lines, node.children, level + 1)
}
}
},
},
}