Feature:支持导入和导出为markdown格式文件

This commit is contained in:
wanglin2
2023-03-24 10:13:24 +08:00
parent cabe286ebb
commit 5fa0ff7b5c
7 changed files with 1080 additions and 8 deletions

View File

@@ -5,9 +5,13 @@ import KeyboardNavigation from './src/KeyboardNavigation.js'
import Export from './src/Export.js'
import Drag from './src/Drag.js'
import Select from './src/Select.js'
import AssociativeLine from './src/AssociativeLine'
import RichText from './src/RichText'
import xmind from './src/parse/xmind.js'
import markdown from './src/parse/markdown.js'
MindMap.xmind = xmind
MindMap.markdown = markdown
MindMap
.usePlugin(MiniMap)
@@ -16,5 +20,7 @@ MindMap
.usePlugin(KeyboardNavigation)
.usePlugin(Export)
.usePlugin(Select)
.usePlugin(AssociativeLine)
.usePlugin(RichText)
export default MindMap

File diff suppressed because it is too large Load Diff

View File

@@ -31,6 +31,7 @@
"html2canvas": "^1.4.1",
"jspdf": "^2.5.1",
"jszip": "^3.10.1",
"mdast-util-from-markdown": "^1.3.0",
"quill": "^1.3.6",
"uuid": "^9.0.0",
"xml-js": "^1.6.11"

View File

@@ -2,6 +2,7 @@ import { imgToDataUrl, downloadFile } from './utils'
import JsPDF from 'jspdf'
import { SVG } from '@svgdotjs/svg.js'
import drawBackgroundImageToCanvas from './utils/simulateCSSBackgroundInCanvas'
import { transformToMarkdown } from './parse/toMarkdown'
const URL = window.URL || window.webkitURL || window
// 导出类
@@ -236,6 +237,14 @@ class Export {
smm(name, withConfig) {
return this.json(name, withConfig)
}
// markdown文件
md() {
let data = this.mindMap.getData()
let content = transformToMarkdown(data)
let blob = new Blob([content])
return URL.createObjectURL(blob)
}
}
Export.instanceName = 'doExport'

View File

@@ -0,0 +1,7 @@
import { transformToMarkdown } from './toMarkdown'
import { transformMarkdownTo } from './markdownTo'
export default {
transformToMarkdown,
transformMarkdownTo
}

View File

@@ -0,0 +1,98 @@
import { fromMarkdown } from 'mdast-util-from-markdown'
// 处理list的情况
const handleList = node => {
let list = []
let walk = (arr, newArr) => {
for (let i = 0; i < arr.length; i++) {
let cur = arr[i]
let node = {}
node.data = {
// 节点内容
text: cur.children[0].children[0].value
}
node.children = []
newArr.push(node)
if (cur.children.length > 1) {
for (let j = 1; j < cur.children.length; j++) {
let cur2 = cur.children[j]
if (cur2.type === 'list') {
walk(cur2.children, node.children)
}
}
}
}
}
walk(node.children, list)
return list
}
// 将markdown转换成节点树
export const transformMarkdownTo = async md => {
const tree = fromMarkdown(md)
let root = {
children: []
}
let childrenQueue = [root.children]
let currentChildren = root.children
let depthQueue = [-1]
let currentDepth = -1
for (let i = 0; i < tree.children.length; i++) {
let cur = tree.children[i]
if (cur.type === 'heading') {
if (!cur.children[0]) continue
// 创建新节点
let node = {}
node.data = {
// 节点内容
text: cur.children[0].value
}
node.children = []
// 如果当前的层级大于上一个节点的层级,那么是其子节点
if (cur.depth > currentDepth) {
// 添加到上一个节点的子节点列表里
currentChildren.push(node)
// 更新当前栈和数据
childrenQueue.push(node.children)
currentChildren = node.children
depthQueue.push(cur.depth)
currentDepth = cur.depth
} else if (cur.depth === currentDepth) {
// 如果当前层级等于上一个节点的层级,说明它们是同级节点
// 将上一个节点出栈
childrenQueue.pop()
currentChildren = childrenQueue[childrenQueue.length - 1]
depthQueue.pop()
currentDepth = depthQueue[depthQueue.length - 1]
// 追加到上上个节点的子节点列表里
currentChildren.push(node)
// 更新当前栈和数据
childrenQueue.push(node.children)
currentChildren = node.children
depthQueue.push(cur.depth)
currentDepth = cur.depth
} else {
// 如果当前层级小于上一个节点的层级,那么一直出栈,直到遇到比当前层级小的节点
while (depthQueue.length) {
childrenQueue.pop()
currentChildren = childrenQueue[childrenQueue.length - 1]
depthQueue.pop()
currentDepth = depthQueue[depthQueue.length - 1]
if (currentDepth < cur.depth) {
// 追加到该节点的子节点列表里
currentChildren.push(node)
// 更新当前栈和数据
childrenQueue.push(node.children)
currentChildren = node.children
depthQueue.push(cur.depth)
currentDepth = cur.depth
break
}
}
}
} else if (cur.type === 'list') {
currentChildren.push(...handleList(cur))
}
}
return root.children[0]
}

View File

@@ -0,0 +1,53 @@
import { walk } from '../utils'
let el = null
const getText = str => {
if (!el) {
el = document.createElement('div')
}
el.innerHTML = str
return el.textContent
}
const getTitleMark = level => {
return new Array(level).fill('#').join('')
}
const getIndentMark = level => {
return new Array(level - 6).fill(' ').join('') + '*'
}
// 转换成markdown格式
export const transformToMarkdown = root => {
let content = ''
walk(
root,
null,
(node, parent, isRoot, layerIndex) => {
let level = layerIndex + 1
let text = node.data.richText ? getText(node.data.text) : node.data.text
if (level <= 6) {
content += getTitleMark(level)
} else {
content += getIndentMark(level)
}
content += ' ' + text
// 概要
let generalization = node.data.generalization
if (generalization && generalization.text) {
let generalizationText = generalization.richText
? getText(generalization.text)
: generalization.text
content += `[${generalizationText}]`
}
content += '\n\n'
// 备注
if (node.data.note) {
content += node.data.note + '\n\n'
}
},
() => {},
true
)
return content
}