{"id":13626457,"url":"https://github.com/xmindltd/xmind-sdk-js","last_synced_at":"2026-01-28T16:14:08.668Z","repository":{"id":34939856,"uuid":"189134345","full_name":"xmindltd/xmind-sdk-js","owner":"xmindltd","description":"This is a lightweight official software development kit to help people who wants to build the mapping file without the UI client and It's also supported to run in Browser or Node.js.","archived":false,"fork":false,"pushed_at":"2024-10-29T16:07:32.000Z","size":1567,"stargazers_count":488,"open_issues_count":14,"forks_count":66,"subscribers_count":13,"default_branch":"master","last_synced_at":"2026-01-08T06:50:19.416Z","etag":null,"topics":["mindmap","mindmapping","sdk","xmind","xmind-sdk","xmind-sdk-js","xmind-sdk-ts"],"latest_commit_sha":null,"homepage":"https://xmind.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xmindltd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-29T02:16:03.000Z","updated_at":"2026-01-07T01:59:40.000Z","dependencies_parsed_at":"2023-09-23T12:25:29.884Z","dependency_job_id":"ad9fd1db-ef03-4e34-8b82-adf74101a952","html_url":"https://github.com/xmindltd/xmind-sdk-js","commit_stats":{"total_commits":279,"total_committers":6,"mean_commits":46.5,"dds":"0.10752688172043012","last_synced_commit":"d35e820a2d09995c69bbb452d4edc42b09a13946"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"purl":"pkg:github/xmindltd/xmind-sdk-js","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmindltd%2Fxmind-sdk-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmindltd%2Fxmind-sdk-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmindltd%2Fxmind-sdk-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmindltd%2Fxmind-sdk-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xmindltd","download_url":"https://codeload.github.com/xmindltd/xmind-sdk-js/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmindltd%2Fxmind-sdk-js/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28846921,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T15:15:36.453Z","status":"ssl_error","status_checked_at":"2026-01-28T15:15:13.020Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mindmap","mindmapping","sdk","xmind","xmind-sdk","xmind-sdk-js","xmind-sdk-ts"],"created_at":"2024-08-01T21:02:19.457Z","updated_at":"2026-01-28T16:14:08.652Z","avatar_url":"https://github.com/xmindltd.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# 📦 📦 📦 ![](https://assets.xmind.net/www/assets/images/xmind-logo-dark-7a5ac2ec22.svg)\n\n[![CodeQL](https://github.com/xmindltd/xmind-sdk-js/actions/workflows/codeql.yml/badge.svg?branch=master)](https://github.com/xmindltd/xmind-sdk-js/actions/workflows/codeql.yml)\n[![Build status](https://ci.appveyor.com/api/projects/status/qll0sp4ny7bl7yo0/branch/master?svg=true)](https://ci.appveyor.com/project/danielsss/xmind-sdk-js/branch/master)\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/a0cef4ab9b024a97b4ef2970fec29158)](https://www.codacy.com/gh/xmindltd/xmind-sdk-js/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=xmindltd/xmind-sdk-js\u0026amp;utm_campaign=Badge_Grade)\n![npm](https://img.shields.io/npm/v/xmind)\n![GitHub](https://img.shields.io/github/license/xmindltd/xmind-sdk-js.svg)\n[![npm (scoped)](https://img.shields.io/badge/XMind-ZEN-red.svg)](https://xmind.app)\n\nThis project is a lightweight official software development kit for JavaScript/Typescript which is available for browsers and Node.js.\n\nThis library implements various functions which are similar to our UI applications, and You might know the basic concepts of this library if you've used the application before.\n\nIn order to use it conveniently, an essential concept you should know is that everything is a component and each one of them has a unique component ID. You can add a child node under the components, however, the Markers and Notes can only be attached to the components.\n\nEventually, Our UI apps could be used to open the `*.xmind` file generated by this tool.\n\n\n## Recommendations\n\n* [Xmind AI](https://xmind.works) - It's a lightweight online `Mind-Map` tool comes with AI features which helps you to build everything you wanted.\n* [Xmind-generator](https://github.com/xmindltd/xmind-generator) — If you are looking for a tool specifically designed for `Mind-Map` generation, `Xmind Generator` is an official package that prioritizes this functionality, featuring a modern and lightweight API.\n\n\n## Supported Platforms\n\n* Linux  \n* Win32  \n* Browser (Not Fully Supported)\n\n## Usage and Getting Started\n\n### Node.js\n\n```shell\n$ npm i --save xmind\n```\n\n\u003e NOTICE: The `xmind-sdk` is renamed to `xmind` from the version: 2.0.0\n\u003e\n\u003e Please, use `npm i --save xmind` to replace with it if you were using the `xmind-sdk`. \n\n\n```js\nconst { Workbook, Topic, Marker } = require('xmind');\n```\n\n### Browser or Vue.js\n\n```jsx harmony\nimport { Workbook, Topic, Marker } from 'xmind';\n```\n\n```html\n// HTML\n// Latest version\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/xmind/dist/xmind.min.js\"\u003e\u003c/script\u003e\n// Specify version\n\u003c!-- script src=\"https://cdn.jsdelivr.net/npm/xmind@2.2.26/dist/xmind.min.js\"\u003e\u003c/script --\u003e\n\n\u003cscript\u003e\n  const { Workbook, Topic, Marker } = window;\n\u003c/script\u003e\n```\n\n\n### More Examples \n\n\nSee [example directory](./example).\n\n```js\nconst { Workbook, Topic, Marker, Zipper } = require('xmind');\n\nconst [ workbook, marker ] = [new Workbook(), new Marker()];\n\nconst topic = new Topic({sheet: workbook.createSheet('sheet title', 'Central Topic')});\nconst zipper = new Zipper({path: '/tmp', workbook, filename: 'MyFirstMap'});\n\n// topic.on() default: `central topic`\ntopic.add({title: 'main topic 1'});\n\ntopic\n  .on(topic.cid(/*In default, the componentId is last element*/))\n  \n  // add subtopics under `main topic 1`\n  .add({title: 'subtopic 1'})\n  .add({title: 'subtopic 2'})\n   \n   // attach text note to `main topic 1`\n  .note('This is a note attached on main topic 1')\n  \n  // attach a marker flag to `subtopic 1`\n  .on(topic.cid('subtopic 1'))\n  .marker(marker.week('fri'))\n   \n   // add a component of the summary that contains two sub topics\n  .summary({title: 'subtopic summary', edge: topic.cid('subtopic 2')})\n  \nzipper.save().then(status =\u003e status \u0026\u0026 console.log('Saved /tmp/MyFirstMap.xmind'));\n```\n\n\n## Workbook\n\nThe workbook is a temporary storage where all the data are written.\n\n### Methods\n\n#### .createSheet(sheetTitle, topicTitle?) =\u003e `Sheet`\n\nOnce the workbook is created, then there's a way to build a sheet containing a `root topic`.\nIn addition, you can customize their titles by parameters.\n\n\n| Name | Type | Default | Required |\n|:---- |:----:|:-------:|:--------:|\n| sheetTitle | String | `-` | Y |\n| topicTitle | String | `Central Topic` | N |\n\n#### .createSheets(options: Object[]) =\u003e `Object[]`\n\nYou can use this method to create sheets in bulk.\n\n\n| Name | Type | Default | Required |\n|:---- |:----:|:-------:|:--------:|\n| sheetTitle | String | `-` | Y |\n| topicTitle | String | `Central Topic` | N |\n\nIt returns an object of sheet identifier([Click here to check how it uses](./example/example.fully.js)).\n\n```typescript\nconst sheets = workbook.createSheets([\n  {s: 'SheetTitle1', t: 'RootTopicTitle1'},\n  {s: 'SheetTitle2', t: 'RootTopicTitle2'}\n]);\nconsole.info(sheets);\n// [\n//   { id: string, title: string },\n//   { id: string, title: string }\n//   ...\n// ]\n```\n\n#### .getSheets() =\u003e `Object[]`\n\nIt allows you to get back the identifier of the sheet anytime and anywhere.\n\n#### .getSheet(id: string) =\u003e `Sheet`\n\nYou can get an instance of the sheet with an existed sheet ID.\n\n#### .theme(sheetTitle, themeName) =\u003e Boolean\n\nThe `UI client` has many theme styles and this library also offers some of them, such as `robust / snowbrush / business`.\n\n| Name | Type | Default | Required |\n|:---- |:----:|:-------:|:--------:|\n| sheetTitle | String | null | Y |\n| themeName | String | null | Y |\n\n#### .toJSON()\n\nGet component's data from the workbook in the form of `JSON`.\n\n#### .toString()\n\nGet component's data from the workbook in the form of `STRING`.\n\n#### .validate() =\u003e `{status: Boolean, errors: Array\u003cobject\u003e | null}`\n\nThis is the way to prove that all data are available and complete.\n\nThe `status` indicates the result of validation which is `true` if it's correct, otherwise `false` returns.\n\n## Topic\n\nThe `Topic` is an important constructor function that implements most of the methods.\nAnd you're going to depend on it during most operations.\n\n### Topic Options\n\n* options.sheet \u003c= `workbook.createSheet(...)`\n\nYou may wonder why we need to offer the `options.sheet` manually? The reason is that `Topic` is implemented independently and most of the methods depend on the instance of the sheet.\n\nIn the UI client, you also need to draw the mind map on the sheet.\n\n\u003e usage:\n\u003e \n\u003e ```js\n\u003e const {Topic, Workbook} = require('xmind');\n\u003e const wb = new Workbook();\n\u003e \n\u003e new Topic({sheet: wb.createSheet('Sheet-1', 'topic-1')});\n\u003e ```\n\n### Methods\n\n#### .on(componentId?) =\u003e Topic\n\nSet the component to be parent node. If there isn't component ID, the `Central Topic` will become as parent node.\n\n#### .cid(title?, options?: { customId?: string, parentId?: string }) =\u003e String\n\nUse this method to get componentId.\n\n\u003e You should use `customId` or `parentId` for getting the `componentId` if there are some duplicated topic titles.\n\nIf you don't specify the title in the period of calling `.cid()`,\nthe last `componentId` that you've added would be returned.\n\n#### .cids() =\u003e {$cid: $title}\n\nIt will return all the `key/value`s in once.\n\n#### .add(options) =\u003e Topic\n\nAdd a topic component under parent node.\n\n| Name | Type |                       Default                       | Required |\n|:----:|:----:|:---------------------------------------------------:|:--------:|\n| options.title | String |                        null                         | Y |\n| options.parentId | String |     The previous topic that you've operated on      | N |\n| options.customId | String | It would be useful if you have the same topic title | N |\n\n\n#### .note(text, del?) =\u003e Topic\n\nAttach a text to parent node.\n\n| Name | Type | Default | Required | Description |\n|:----:|:----:|:-------:|:--------:|:------------|\n| text | String | null | Y | text message |\n| del | Boolean | false | N | detach the note from current parent node if the `del` is true |\n\n#### .addLabel(text) =\u003e Topic\n\nAdd label text to the component, also you can add label to the same component many times.\n\n| Name | Type | Default | Required | Description |\n|:----:|:----:|:-------:|:--------:|:------------|\n| text | String | null | Y | label text string |\n\n\n#### .removeLabels(componentId?) =\u003e Topic\n\nRemove all the labels from the component.\n\n\u003e If you don't give the componentId, then remove labels from the currently component.\n\n| Name | Type | Default | Required | Description |\n|:----:|:----:|:-------:|:--------:|:------------|\n| componentId | String | null | N | - |\n\n#### .marker(object) =\u003e Topic\n\nAttach a marker flag to the parent node.\nMoreover, you can detach a marker flag from the parent node by setting `object.del` as `true`.\nDefault: `false`\n\nExample:\n\n```js\nconst {Marker} = require('xmind');\nconst marker = new Marker();\n// add\ntopic.marker(marker.smiley('cry'));\n// del\ntopic.marker(Object.assign({}, marker.smiley('cry'), {del: true}));\n```\n\n\u003e [Use `Marker Object` to generate the object](#marker-flags)\n\n\n#### .image() =\u003e key\n\nYou can use `.image()` to get `image key` back.\n\nHowever, you need to write image into manifest by `zip.updateManifestMetadata()` or `dumper.updateManifestMetadata()`.\n\n\u003e [See image example](./example/example.image.js)\n\u003e [See image in browser example](./example/example.image.browser.html)\n\n#### .summary(options) =\u003e Topic\n\nAttach a summary component to parent node including all children. In the meantime, the `edge` can be used to set the scope of summary component.\n\u003e **Important**\n\u003e \n\u003e The summary doesn't allow to be added under `Central Topic`\n\u003e \n\u003e The `edge` must parallel to parent node\n\n| Name | Type | Default | Required |\n|:---- |:----:|:-------:|:--------:|\n| options.title | String | null | Y |\n| options.edge | String | null | N | \n\n\n\u003e [About `edge`](./docs/edge.graphic.txt)\n\n\n#### .destroy(componentId) =\u003e Topic\n\nDestroy a component from the map tree.\n\n\u003e **Important**\n\u003e\n\u003e All children would be destroyed along with it \n\n\n## Marker flags\n\nWe provide an instance of `Marker` that includes all the markers. Such as:\n\n###### .priority(name: `string`)\n\n###### .smiley(name: `string`)\n\n###### .task(name: `string`)\n\n###### .flag(name: `string`)\n\n###### .star(name: `string`)\n\n###### .people(name: `string`)\n\n###### .arrow(name: `string`)\n\n###### .symbol(name: `string`)\n\n###### .month(name: `string`)\n\n###### .week(name: `string`)\n\n###### .half(name: `string`)\n\n###### .other(name: `string`)\n\n\u003e **The `name` of marker is available [!here](./docs/icons.md)**\n\u003e \n\u003e You can also use the **Marker.groups** and **Marker.names** to find out available names of Marker.\n\n\n### Static methods\n\n#### Marker.groups() =\u003e Array\\\u003cgroupName\\\u003e\n\nList available group names.\n\n#### Marker.names(groupName) =\u003e Array\\\u003cname\\\u003e\n\n* Get the flag names by `groupName`.\n\n\n## Zipper\n\nThe module of `Zipper` only works under backend.\n\n\u003e [!See `Dumper` in browser environment](#dumper)\n\n### Zipper Options\n\n| Name | Type | Default | Required | Description | \n|:---- |:----:|:-------:|:--------:|:------------|\n| options.path | String | `-` | Y | The path is where to save the `.xmind` file |\n| options.workbook | Workbook | `-` | Y | The instance of Workbook |\n| options.filename | String | default | N | `default.xmind` |\n\n#### .updateManifestMetadata(key, content) =\u003e Zipper\n\nUpdate manifest for image insertion.\n\n| Name | Type | Default | Required | Description | \n|:---- |:----:|:-------:|:--------:|:------------|\n| key | String | null | Y | The key only can get by topic.image() |\n| content | Buffer | null | Y | The buffer data of image |\n\n#### .removeManifestMetadata(key) =\u003e Zipper\n\nRemove a pair of key / value from manifest.\n\n#### .save() =\u003e Promise\\\u003cboolean\\\u003e\n\nSave components to the logic disk in the form of zip.\n\n## Dumper\n\nThe module of `Dumper` only works under browser.\n\n### Dumper methods\n\n#### .dumping() =\u003e Array\u003c{filename: string, value: string}\u003e\n\nReturn an array of objects composed of file content.\nIn order to open it in the official software,\nyou need to compress these files in the form of zip with the suffix `.xmind`.\n\n\u003e **Important**\n\u003e \n\u003e Don't include top level folders, otherwise the software can't extract files\n\n#### .updateManifestMetadata(key, content, creator) =\u003e Promise\\\u003cvoid\\\u003e\n\nUpdate manifest for image insertion.\n\n| Name | Type | Default | Required | Description |\n|:---- |:----:|:-------:|:--------:|:------------|\n| key | string | null | Y | The key only can get by topic.image() |\n| content | File \\| Blob \\| ArrayBuffer | null | Y | The data of image |\n| creator | FileCreator | | Y | To specify how to save the file |\n\nwhere `FileCreator` is\n\n```typescript\ninterface FileCreator {\n  /**\n   * Hint that should create a folder-like structure, enter the folder if exists\n   * @param name - Folder name\n   */\n  folder(name: string): Promise\u003cvoid\u003e\n  \n  /**\n   * Hint that should create a file-like object with `content`, update the file if exists\n   * @param name Filename\n   */\n  file(name: string, content: File | Blob | ArrayBuffer): Promise\u003cvoid\u003e\n}\n```\n\n## Contributing\nThank you for being interested in the SDK.\n\nIf you have any problems or suggestions, please let's know. 🙂\n\nWe also welcome you to submit a pull request for any big or small issues.\n\n## License\n\nSee the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmindltd%2Fxmind-sdk-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxmindltd%2Fxmind-sdk-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmindltd%2Fxmind-sdk-js/lists"}