xmind

package module
v0.0.0-...-278de0e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2023 License: MIT Imports: 16 Imported by: 0

README

xmind

基于go语言的xmind接口

使用方法参考: example

本库主要加载xmind文件为json结构,保存文件时也用的json结构而不是xml结构

本库只做了最基本的主题添加功能,其他功能不考虑,有想法的自行实现,或者提PR

本库做了通用加载和通用保存方法,可以更灵活的与其他思维导图进行转换

参考: custom_test

安装命令行工具: go install github.com/jan-bar/xmind/cmd/xmind@latest

示例

  • 自定义json数据创建xmind
package main

import (
	"github.com/jan-bar/xmind"
)

func main() {
	data := `[{"a":"1","b":"main topic"},
{"a":"2","b":"topic1","c":"1"},{"a":"3","b":"topic2","c":"1"},
{"a":"4","b":"topic3","c":"2"},{"a":"5","b":"topic4","c":"2"},
{"a":"6","b":"topic5","c":"3"},{"a":"7","b":"topic6","c":"3"}
]`
	// 这里定义 a 表示节点id, b 表示主题内容, c 表示父节点id
	// 传入定好的json字符串,以及指定好json的key字符串就可以将任意json数据转换成xmind
	// 也可用用 data := []byte(`{}`) 传入字节数组
	st, err := xmind.LoadCustom(data, map[string]string{
		xmind.CustomKeyId:       "a",
		xmind.CustomKeyTitle:    "b",
		xmind.CustomKeyParentId: "c",
	})
	if err != nil {
		panic(err)
	}
	err = xmind.SaveSheets("custom.xmind", st)
	if err != nil {
		panic(err)
	}
}
  • 通过接口创建xmind对象,并保存xmind文件
package main

import (
	"github.com/jan-bar/xmind"
)

func main() {
	st1 := xmind.NewSheet("sheet1", "main 1 topic")
	st1.Add("123").Add("456").Add("789").OnTitle("123").
		Add("2sc").Add("345").OnTitle("456").AddLabel("label").
		Add("xzcv").Add("ewr").OnTitle("789").Add("saf").Add("xcv")

	st2 := xmind.NewSheet("sheet2", "main 2 topic")
	st2.Add("aaa").Add("ewr").AddNotes("notes")
	st2.OnTitle("ewr").Title = "xx-ewr\txvf\nwer" // 修改指定主题内容,其中包含特殊转义字符
	st2.Add("vbg").Add("qwe").OnTitle("aaa").
		Add("zxs", xmind.ParentMode). // 为节点添加父节点
		Add("cxv", xmind.BeforeMode). // 在节点之前添加兄弟节点
		Add("xcas", xmind.AfterMode). // 在节点之后添加兄弟节点
		OnTitle("vbg").Add("34").Add("xcv").OnTitle("qwe").
		Add("111").Add("222").Add("333")

	err := xmind.SaveSheets("create.xmind", st1, st2)
	if err != nil {
		panic(err)
	}

	src := st2.CId("zxs")
	st2.OnTitle("34").Move(src) // 将'zxs'节点移动到'34'节点作为子节点

	// 将'qwe'节点移动到'zxs'节点同级下方
	st2.OnTitle("zxs").Move(st2.CId("qwe"), xmind.AfterMode)

	err = xmind.SaveSheets("move1.xmind", st2)
	if err != nil {
		panic(err)
	}
}
  • 加载xmind文件
package main

import (
	"github.com/jan-bar/xmind"
)

func main() {
	// 支持4种方式的加载,详情看内部具体实现
	wb, err := xmind.LoadFile("TestCreateXmind.xmind")
	if err != nil {
		panic(err)
	}
	if len(wb.Topics) != 2 {
		return
	}

	// 在第一个sheet页修改一些数据
	wb.Topics[0].OnTitle("345").Add("111").Add("222").OnTitle("xcv").
		Add("xzcv").Add("werw")

	// 在第二个sheet页修改一些数据
	wb.Topics[1].OnTitle("34").Add("111").Add("222").OnTitle("aaa").
		Add("xzcv").Add("werw")

	// 可以用xmind打开这两个文件,比较一下不同
	err = wb.Save("TestLoadXmindJson.xmind")
	if err != nil {
		panic(err)
	}
}

Documentation

Index

Constants

View Source
const (
	DefaultMarkdownName   = "default"
	DefaultMarkdownFormat = "{{Repeat \"#\" ." + MarkdownKeyDeep +
		"}} {{." + CustomKeyTitle + "}}\n\n{{range $i,$v := ." + CustomKeyLabels +
		"}}> {{$v}}\n\n{{end}}{{range $i,$v := (SplitLines ." + CustomKeyNotes +
		" \"\\n\\r\")}}> {{$v}}\n\n{{end}}"

	MarkdownKeyDeep = "Deep" // 所在层级,>=1
)
View Source
const (
	CustomKeyId       = "Id"
	CustomKeyTitle    = "Title"
	CustomKeyParentId = "ParentId"
	CustomKeyIsRoot   = "IsRoot"
	CustomKeyLabels   = "Labels"
	CustomKeyNotes    = "Notes"
)

Variables

View Source
var RootIsNull = errors.New("RootTopic is null")

Functions

func CustomIncrId

func CustomIncrId() func(TopicID) string

CustomIncrId 自定义生成自增数字id方案

func SaveCustom

func SaveCustom(sheet *Topic, custom map[string]string, v interface{},
	genId func(id TopicID) string) error

SaveCustom 自定义字段,将数据写入指定对象中

param
  sheet: xmind的sheet数据
  custom: map[string]string{
    CustomKeyId:       "id",     // 以该json tag字段作为主题ID
    CustomKeyTitle:    "title",  // 以该json tag字段作为主题内容
    CustomKeyParentId: "parent", // 以该json tag字段作为判断父节点的依据
        // "parentId",表示根节点不添加父节点id
        // "parentId,xx",表示根节点添加值为空的父节点id
    CustomKeyIsRoot: "isRoot",   // 以该json tag字段,true表示为根节点
        // "",表示所有节点都不添加
        // "isRoot,xx",表示只添加根节点
    CustomKeyLabels: "labels", // 以该json tag字段作为标签
    CustomKeyNotes:  "notes",  // 以该json tag字段作为备注
  }
  v: 可以为 *string,*[]byte,*[]Nodes{} 这几种类型
  genId: 外部自定义生成id方案,自动生成的id是参照xmind,可能有点长
return
  error: 返回错误

func SaveCustomWorkbook

func SaveCustomWorkbook(output io.Writer, wk *WorkBook,
	custom map[string]string, genId func(id TopicID) string) error

SaveCustomWorkbook 保存workbook到自定义json中

func SaveSheets

func SaveSheets(path string, sheet ...*Topic) error

SaveSheets 保存多个sheet画布到一个xmind文件

Types

type AddMode

type AddMode uint8
const (
	SubMode    AddMode = iota // 默认方式,当前主题添加子主题
	BeforeMode                // 在当前主题之前插入
	AfterMode                 // 在当前主题之后插入
	ParentMode                // 为当前主题插入父主题
)

func (AddMode) In

func (am AddMode) In() AddMode

In 判断 AddMode 不在范围内时重置为 SubMode

type Children

type Children struct {
	Attached []*Topic `json:"attached" xml:"topics>topic"`
}

下面的结构支持从xml和json中解析xmind文件 但只支持生成json的xmind文件,没有做直接生成xml文件的方法

type ContentStruct

type ContentStruct struct {
	Content string `json:"content" xml:"content"`
}

下面的结构支持从xml和json中解析xmind文件 但只支持生成json的xmind文件,没有做直接生成xml文件的方法

func (*ContentStruct) UnmarshalXML

func (cs *ContentStruct) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type Notes

type Notes struct {
	Plain ContentStruct `json:"plain" xml:"plain"`
}

下面的结构支持从xml和json中解析xmind文件 但只支持生成json的xmind文件,没有做直接生成xml文件的方法

type StructureClass

type StructureClass string

下面的结构支持从xml和json中解析xmind文件 但只支持生成json的xmind文件,没有做直接生成xml文件的方法

const (
	ContentJson = "content.json"
	ContentXml  = "content.xml"
	Manifest    = "manifest.json"
	Metadata    = "metadata.json"
	Thumbnails  = "Thumbnails"
	Resources   = "resources"

	StructMapUnbalanced       StructureClass = "org.xmind.ui.map.unbalanced"       // 思维导图
	StructMap                 StructureClass = "org.xmind.ui.map"                  // 平衡图(向下)
	StructMapClockwise        StructureClass = "org.xmind.ui.map.clockwise"        // 平衡图(顺时针)
	StructMapAnticlockwise    StructureClass = "org.xmind.ui.map.anticlockwise"    // 平衡图(逆时针)
	StructOrgChartDown        StructureClass = "org.xmind.ui.org-chart.down"       // 组织结构图(向下)
	StructOrgChartUp          StructureClass = "org.xmind.ui.org-chart.up"         // 组织结构图(向上)
	StructTreeRight           StructureClass = "org.xmind.ui.tree.right"           // 树状图(向右)
	StructTreeLeft            StructureClass = "org.xmind.ui.tree.left"            // 树状图(向左)
	StructLogicRight          StructureClass = "org.xmind.ui.logic.right"          // 逻辑图(向右)
	StructLogicLeft           StructureClass = "org.xmind.ui.logic.left"           // 逻辑图(向左)
	StructTimelineHorizontal  StructureClass = "org.xmind.ui.timeline.horizontal"  // 水平时间轴
	StructTimelineVertical    StructureClass = "org.xmind.ui.timeline.vertical"    // 垂直时间轴
	StructFishHoneLeftHeaded  StructureClass = "org.xmind.ui.fishbone.leftHeaded"  // 鱼骨图(头向左)
	StructFishHoneRightHeaded StructureClass = "org.xmind.ui.fishbone.rightHeaded" // 鱼骨图(头向左)
	StructSpreadsheet         StructureClass = "org.xmind.ui.spreadsheet"          // 矩阵(行)
	StructSpreadsheetColumn   StructureClass = "org.xmind.ui.spreadsheet.column"   // 矩阵(列)
)

type Style

type Style struct {
	Properties struct{} `json:"properties"`
	Id         TopicID  `json:"id"`
}

下面的结构支持从xml和json中解析xmind文件 但只支持生成json的xmind文件,没有做直接生成xml文件的方法

type Topic

type Topic struct {
	RootTopic      *Topic         `json:"rootTopic,omitempty" xml:"topic"`
	Children       *Children      `json:"children,omitempty" xml:"children,omitempty"`
	Notes          *Notes         `json:"notes,omitempty" xml:"notes,omitempty"`
	ID             TopicID        `json:"id" xml:"id,attr"`
	Title          string         `json:"title" xml:"title"`
	StructureClass StructureClass `json:"structureClass,omitempty" xml:"structure-class,attr"`
	Style          Style          `json:"style"`
	Labels         []string       `json:"labels,omitempty" xml:"labels>label,omitempty"`
	// contains filtered or unexported fields
}

下面的结构支持从xml和json中解析xmind文件 但只支持生成json的xmind文件,没有做直接生成xml文件的方法

func LoadCustom

func LoadCustom(data interface{}, custom map[string]string) (sheet *Topic, err error)

LoadCustom 根据符合要求的任意结构加载

param
  data:
    方式1:
      使用如下方式进行调用,根节点没有父节点,其他节点均设置父节点ID
      LoadCustom([]Nodes{{"root","top"},{"123","one","root"}},map[string]string{
        CustomKeyId:       "id",
        CustomKeyTitle:    "topic",
        CustomKeyParentId: "parentId",
      })
      测试如下结构
      type Nodes struct {
         ID       string `json:"id"`
         Topic    string `json:"topic"`
         ParentId string `json:"parentId"`
         Labels []string `json:"labels"`
         Notes    string `json:"notes"`
      }
    方式2:
      传json string: data := `[
        {"a":"1","b":"main topic","labels":["l1","l2"],"notes":"notes"},
        {"a":"2","b":"topic1","c":"1"},
        {"a":"3","b":"topic2","c":"1"},
        {"a":"4","b":"topic3","c":"2"},
        {"a":"5","b":"topic4","c":"2"},
        {"a":"6","b":"topic5","c":"3"},
        {"a":"7","b":"topic6","c":"3"}]`
      LoadCustom(data,map[string]string{
        CustomKeyId:       "id",       // 以该json tag字段作为主题ID
        CustomKeyTitle:    "topic",    // 以该json tag字段作为主题内容
        CustomKeyParentId: "parentId", // 以该json tag字段作为判断父节点的依据
        CustomKeyIsRoot:   "isRoot",   // 以该json tag字段,bool类型,true表示根节点,false表示普通节点
        CustomKeyLabels:   "labels",   // 以该json tag字段作为主题标签
        CustomKeyNotes:    "notes",    // 以该json tag字段作为主题备注
      })
return
  *Topic: 生成的主题地址
  error: 返回错误

func NewSheet

func NewSheet(sheetTitle, centralTopicTitle string, structureClass ...StructureClass) *Topic

NewSheet 创建一个画布

param
  sheetTitle: 画布名称
  centralTopicTitle: 中心主题
  structureClass: 整体样式
return
  *Topic: 中心主题地址

func (*Topic) Add

func (st *Topic) Add(title string, modes ...AddMode) *Topic

Add 为当前主题添加主题

param
  title: 主题内容
  mode: 添加主题方式,不传则默认添加子主题
return
  *Topic: 当前主题地址

func (*Topic) AddLabel

func (st *Topic) AddLabel(label ...string) *Topic

AddLabel 在当前主题上加label标签

param
  label: 标签内容
return
  *Topic: 当前主题地址

func (*Topic) AddNotes

func (st *Topic) AddNotes(notes string) *Topic

AddNotes 在当前主题上加notes备注

param
  Notes: 备注内通内容
return
  *Topic: 当前主题地址

func (*Topic) CId

func (st *Topic) CId(title string) TopicID

CId 根据主题内容获取第一个匹配到的主题ID

param
  title: 主题内容
return
  TopicID: 匹配title的主题ID,有多个相同title时只返回第一个匹配成功的结果

func (*Topic) CIds

func (st *Topic) CIds(title string) (res []TopicID)

CIds 根据主题内容获取所有匹配到的主题ID

param
  title: 主题内容
return
  res: 匹配到title的所有主题ID

func (*Topic) IsCent

func (st *Topic) IsCent() bool

IsCent 判断当前节点是中心主题

return
  bool: true表示该节点为中心主题,否则为普通节点

func (*Topic) Move

func (st *Topic) Move(componentId TopicID, modes ...AddMode) *Topic

Move 将指定节点移动到当前节点对应位置

param
  componentId: 要移动过来的节点
  modes: 移动过来的添加方式,不传则默认移动为最后一个子主题
return
  *Topic: 当前主题地址

func (*Topic) On

func (st *Topic) On(componentId ...TopicID) *Topic

On 根据主题ID切换主题地址

param
  componentId: 主题ID,不传时切换到中心主题
return
  *Topic: 匹配主题地址

func (*Topic) OnTitle

func (st *Topic) OnTitle(title string) *Topic

OnTitle 根据主题内容切换主题地址

param
  title: 主题内容,为空时切换到中心主题
return
  *Topic: 匹配主题地址

func (*Topic) Parent

func (st *Topic) Parent(componentId ...TopicID) *Topic

Parent 返回父节点地址,如果传参则返回指定ID的父节点 找不到父主题,或父主题为nil时需要外部自行判断

func (*Topic) Range

func (st *Topic) Range(f func(int, *Topic) error) error

Range 从当前节点递归遍历子节点

param
  f: 外部的回调

func (*Topic) Remove

func (st *Topic) Remove(title string) *Topic

Remove 删除指定主题内容节点

param
  title: 待删除子主题内容
return
  *Topic: 当前主题地址

func (*Topic) RemoveByID

func (st *Topic) RemoveByID(componentId TopicID) *Topic

RemoveByID 删除指定主题ID的节点

param
  title: 待删除子主题内容
return
  *Topic: 当前主题地址

特别注意,删除主题成功会自动定位到中心主题上,如果需要切换需要显示使用 On 操作

func (*Topic) RemoveChildren

func (st *Topic) RemoveChildren()

RemoveChildren 递归删除所有子节点

func (*Topic) Resources

func (st *Topic) Resources() map[TopicID]string

Resources 返回所有主题的ID和内容资源

return
  res: 返回所有主题ID和资源

func (*Topic) UpSheet

func (st *Topic) UpSheet(sheetTitle, centralTopicTitle string, structureClass ...StructureClass)

UpSheet 更新画布,可以在任何节点主题执行

param
  sheetTitle: 画布名称
  centralTopicTitle: 中心主题
  structureClass: 整体样式

type TopicID

type TopicID string

下面的结构支持从xml和json中解析xmind文件 但只支持生成json的xmind文件,没有做直接生成xml文件的方法

const (
	CentKey TopicID = "" // 中心主题地址Key,开放给调用者

)

func GetId

func GetId() TopicID

func (TopicID) IsOrdinary

func (t TopicID) IsOrdinary() bool

IsOrdinary 普通节点ID长度固定为26,其他长度均为特殊节点

func (TopicID) MarshalJSON

func (t TopicID) MarshalJSON() ([]byte, error)

type WorkBook

type WorkBook struct {
	XMLName xml.Name `xml:"xmap-content"`
	Topics  []*Topic `json:"sheet" xml:"sheet"`
}

下面的结构支持从xml和json中解析xmind文件 但只支持生成json的xmind文件,没有做直接生成xml文件的方法

func LoadCustomWorkbook

func LoadCustomWorkbook(input io.Reader, custom map[string]string) (*WorkBook, error)

LoadCustomWorkbook 加载自定义workbook的json

func LoadFile

func LoadFile(path string) (*WorkBook, error)

LoadFile 从文件加载xmind数据 当文件为

*.xmind 时会尝试读取压缩包的[content.json,content.xml]文件
*.*     时会直接按照[*.json,*.xml]这几种格式读取

func LoadFrom

func LoadFrom(input interface{}) (*WorkBook, error)

LoadFrom 从文件或io.Reader对象中加载xmind

func (*WorkBook) Save

func (wk *WorkBook) Save(path string) error

Save 保存对象为 *.xmind 文件

func (*WorkBook) SaveTo

func (wk *WorkBook) SaveTo(w io.Writer) error

SaveTo 将xmind保存到io.Writer对象,使用更灵活

func (*WorkBook) SaveToMarkdown

func (wk *WorkBook) SaveToMarkdown(w io.Writer, format map[string]string) error

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL