@ateeducacion/mind-elixir-export-mermaid 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +139 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Área de Tecnología Educativa (Gobierno de Canarias) and contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Mind Elixir export to Mermaid
|
|
2
|
+
|
|
3
|
+
[](https://github.com/ateeducacion/mind-elixir-export-mermaid/actions/workflows/ci.yml)
|
|
4
|
+
[](https://codecov.io/gh/ateeducacion/mind-elixir-export-mermaid)
|
|
5
|
+
[](https://www.npmjs.com/package/@ateeducacion/mind-elixir-export-mermaid)
|
|
6
|
+
[](https://github.com/ateeducacion/mind-elixir-export-mermaid/actions/workflows/publish.yml)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
Converts [Mind Elixir](https://github.com/SSShooter/mind-elixir-core) mind maps to
|
|
10
|
+
[Mermaid `mindmap`](https://mermaid.js.org/syntax/mindmap.html) source.
|
|
11
|
+
|
|
12
|
+
Mermaid text is tiny, and it can be rendered to a sharp, lightweight SVG by
|
|
13
|
+
[Mermaid](https://mermaid.js.org) or by [Pele](https://github.com/obsidianmd/pele), which
|
|
14
|
+
needs no DOM and also runs on a server. GitHub, GitLab, Obsidian, Notion and many
|
|
15
|
+
documentation tools display it as well. For a 16-node map, the SVG that Pele renders from
|
|
16
|
+
this output is 8 KB (1.7 KB gzip), against 84 KB for a PNG screenshot of the same map.
|
|
17
|
+
|
|
18
|
+
No runtime dependencies, no DOM, and it works in browsers, Node.js, Bun and Deno.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npm install @ateeducacion/mind-elixir-export-mermaid
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Use
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import MindElixir from "mind-elixir";
|
|
30
|
+
import { mindElixirToMermaid } from "@ateeducacion/mind-elixir-export-mermaid";
|
|
31
|
+
|
|
32
|
+
const mind = new MindElixir({ el: "#map" });
|
|
33
|
+
mind.init(MindElixir.new("Science"));
|
|
34
|
+
|
|
35
|
+
const source = mindElixirToMermaid(mind.getData());
|
|
36
|
+
// mindmap
|
|
37
|
+
// n0(("Science"))
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
It takes the data returned by `mind.getData()`, or a single node and its descendants.
|
|
41
|
+
|
|
42
|
+
Render it with Pele:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { render } from "pele";
|
|
46
|
+
|
|
47
|
+
const { svg } = render(source);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
or with Mermaid:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import mermaid from "mermaid";
|
|
54
|
+
|
|
55
|
+
const { svg } = await mermaid.render("mindmap", source);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Options
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
mindElixirToMermaid(data, {
|
|
62
|
+
rootShape: "circle",
|
|
63
|
+
nodeShape: "rounded",
|
|
64
|
+
shape: (node, depth) => (depth === 1 ? "cloud" : undefined),
|
|
65
|
+
className: (node) => (node.branchColor === "#c0392b" ? "red" : undefined),
|
|
66
|
+
icon: (node) => (node.tags?.includes("book") ? "fa fa-book" : undefined),
|
|
67
|
+
markdown: true,
|
|
68
|
+
omitCollapsed: false,
|
|
69
|
+
indent: 2,
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
| Option | Default | Description |
|
|
74
|
+
| ------------------------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
75
|
+
| `rootShape` | `"circle"` | Shape of the root: `square`, `rounded`, `circle`, `bang`, `cloud` or `hexagon`. |
|
|
76
|
+
| `nodeShape` | `"rounded"` | Shape of the other nodes. |
|
|
77
|
+
| `shape(node, depth)` | | Shape of one node; return `undefined` to use the defaults. |
|
|
78
|
+
| `className(node, depth)` | | CSS classes written as `:::name` (letters, digits, `-` and `_`). |
|
|
79
|
+
| `icon(node, depth)` | | Icon classes written as `::icon(...)`, for example `"fa fa-book"`. |
|
|
80
|
+
| `markdown` | `false` | Write [markdown strings](https://mermaid.js.org/syntax/mindmap.html#markdown-strings), keeping bold (`fontWeight: "bold"`), italic (`fontStyle: "italic"`) and line breaks. Otherwise line breaks become spaces. |
|
|
81
|
+
| `omitCollapsed` | `false` | Leave out the children of folded nodes (`expanded: false`). |
|
|
82
|
+
| `indent` | `2` | Spaces per level, from 1 to 8. |
|
|
83
|
+
|
|
84
|
+
`escapeLabel(text, markdown?)` is exported too, for building labels by hand.
|
|
85
|
+
|
|
86
|
+
## What is exported
|
|
87
|
+
|
|
88
|
+
The hierarchy, the order and the text of every node. Text is written with Mermaid's
|
|
89
|
+
entity codes (`#quot;`, `#lt;`, `#35;`, …), so a topic can contain quotes, brackets,
|
|
90
|
+
`#`, `*`, `_` or HTML-like text and still renders exactly as typed, never as markup.
|
|
91
|
+
|
|
92
|
+
Mermaid's `mindmap` syntax has no equivalent for per-node colours and font styles (other
|
|
93
|
+
than bold and italic in markdown mode), branch sides, folded state, arrows, summaries,
|
|
94
|
+
links, images or tags, so those are not exported. Keep the Mind Elixir data as the source
|
|
95
|
+
of your map and use this output as a view of it. The `className` option can carry some of
|
|
96
|
+
that information as CSS classes if your page styles them.
|
|
97
|
+
|
|
98
|
+
Invalid input throws a `TypeError`, and an invalid option, class name or icon throws a
|
|
99
|
+
`RangeError`, rather than writing source that Mermaid cannot parse.
|
|
100
|
+
|
|
101
|
+
## Background
|
|
102
|
+
|
|
103
|
+
This package was proposed in
|
|
104
|
+
[mind-elixir-core#386](https://github.com/SSShooter/mind-elixir-core/issues/386). Thanks
|
|
105
|
+
to [@SSShooter](https://github.com/SSShooter) for Mind Elixir and for the suggestion to
|
|
106
|
+
make it a separate package. It is used by [eXeLearning](https://github.com/exelearning/exelearning),
|
|
107
|
+
an open-source authoring tool for educational content, whose published content needs a
|
|
108
|
+
static image of each mind map.
|
|
109
|
+
|
|
110
|
+
## Develop
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
npm ci
|
|
114
|
+
npm run check # format, typecheck, tests with 100% coverage, build
|
|
115
|
+
npm run test:package # pack, install the tarball in an empty project and import it
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
[MIT](LICENSE)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts Mind Elixir mind maps to Mermaid `mindmap` source.
|
|
3
|
+
*
|
|
4
|
+
* The output can be rendered to SVG by Mermaid (https://mermaid.js.org) or by Pele
|
|
5
|
+
* (https://github.com/obsidianmd/pele), and is understood by GitHub, GitLab, Obsidian and
|
|
6
|
+
* other tools. It keeps the hierarchy, the order and the text of the map. Mermaid mindmaps
|
|
7
|
+
* have no per-node colours, branch sides, arrows or summaries, so those are not exported.
|
|
8
|
+
*/
|
|
9
|
+
/** The fields of a Mind Elixir node this module reads (compatible with `NodeObj`). */
|
|
10
|
+
export interface MindElixirNode {
|
|
11
|
+
topic: string;
|
|
12
|
+
children?: readonly MindElixirNode[] | undefined;
|
|
13
|
+
expanded?: boolean | undefined;
|
|
14
|
+
style?: {
|
|
15
|
+
fontWeight?: string | undefined;
|
|
16
|
+
fontStyle?: string | undefined;
|
|
17
|
+
} | undefined;
|
|
18
|
+
}
|
|
19
|
+
/** The fields of Mind Elixir data this module reads (compatible with `MindElixirData`). */
|
|
20
|
+
export interface MindElixirData {
|
|
21
|
+
nodeData: MindElixirNode;
|
|
22
|
+
}
|
|
23
|
+
/** Mermaid mindmap node shapes. */
|
|
24
|
+
export type MermaidShape = "square" | "rounded" | "circle" | "bang" | "cloud" | "hexagon";
|
|
25
|
+
/**
|
|
26
|
+
* Options. `N` is the node type of your data (Mind Elixir's `NodeObj`, for example), which
|
|
27
|
+
* the callbacks receive.
|
|
28
|
+
*/
|
|
29
|
+
export interface MermaidExportOptions<N extends MindElixirNode = MindElixirNode> {
|
|
30
|
+
/** Shape of the root node. Default: `"circle"`. */
|
|
31
|
+
rootShape?: MermaidShape;
|
|
32
|
+
/** Shape of the other nodes. Default: `"rounded"`. */
|
|
33
|
+
nodeShape?: MermaidShape;
|
|
34
|
+
/** Shape of one node, overriding the two options above when it returns a shape. */
|
|
35
|
+
shape?: (node: N, depth: number) => MermaidShape | undefined;
|
|
36
|
+
/** CSS classes for a node, written as `:::name`. Names may contain letters, digits, `-` and `_`. */
|
|
37
|
+
className?: (node: N, depth: number) => string | readonly string[] | undefined;
|
|
38
|
+
/** Icon classes for a node, written as `::icon(...)`, for example `"fa fa-book"`. */
|
|
39
|
+
icon?: (node: N, depth: number) => string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Write labels as Mermaid markdown strings, which keep bold (`fontWeight: "bold"`),
|
|
42
|
+
* italic (`fontStyle: "italic"`) and line breaks. Default: `false` (plain labels, line
|
|
43
|
+
* breaks become spaces).
|
|
44
|
+
*/
|
|
45
|
+
markdown?: boolean;
|
|
46
|
+
/** Leave out the children of folded nodes (`expanded: false`). Default: `false`. */
|
|
47
|
+
omitCollapsed?: boolean;
|
|
48
|
+
/** Spaces per level. Default: `2`. */
|
|
49
|
+
indent?: number;
|
|
50
|
+
}
|
|
51
|
+
/** Escapes a topic for a quoted Mermaid label. */
|
|
52
|
+
export declare function escapeLabel(text: string, markdown?: boolean): string;
|
|
53
|
+
/**
|
|
54
|
+
* Converts Mind Elixir data (as returned by `mind.getData()`) or a single node and its
|
|
55
|
+
* descendants to Mermaid `mindmap` source.
|
|
56
|
+
*
|
|
57
|
+
* @throws {TypeError} when the input is not a Mind Elixir node or data.
|
|
58
|
+
* @throws {RangeError} when an option or a class name/icon returned by a callback is invalid.
|
|
59
|
+
*/
|
|
60
|
+
export declare function mindElixirToMermaid<N extends MindElixirNode>(data: {
|
|
61
|
+
nodeData: N;
|
|
62
|
+
} | N, options?: MermaidExportOptions<N>): string;
|
|
63
|
+
export default mindElixirToMermaid;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts Mind Elixir mind maps to Mermaid `mindmap` source.
|
|
3
|
+
*
|
|
4
|
+
* The output can be rendered to SVG by Mermaid (https://mermaid.js.org) or by Pele
|
|
5
|
+
* (https://github.com/obsidianmd/pele), and is understood by GitHub, GitLab, Obsidian and
|
|
6
|
+
* other tools. It keeps the hierarchy, the order and the text of the map. Mermaid mindmaps
|
|
7
|
+
* have no per-node colours, branch sides, arrows or summaries, so those are not exported.
|
|
8
|
+
*/
|
|
9
|
+
const SHAPES = {
|
|
10
|
+
square: ["[", "]"],
|
|
11
|
+
rounded: ["(", ")"],
|
|
12
|
+
circle: ["((", "))"],
|
|
13
|
+
bang: [")", "("],
|
|
14
|
+
cloud: ["))", "(("],
|
|
15
|
+
hexagon: ["{{", "}}"],
|
|
16
|
+
};
|
|
17
|
+
const CLASS_NAME = /^[A-Za-z_][\w-]*$/;
|
|
18
|
+
const ICON = /^[\w -]+$/;
|
|
19
|
+
/**
|
|
20
|
+
* Mermaid entity codes for the characters Mermaid would otherwise read as syntax, markup,
|
|
21
|
+
* entities or formatting (Pele formats `*` and `_` even outside markdown strings). `#` comes
|
|
22
|
+
* first, so the codes added afterwards are not encoded again.
|
|
23
|
+
*/
|
|
24
|
+
const ENTITIES = [
|
|
25
|
+
[/#/g, "#35;"],
|
|
26
|
+
[/"/g, "#quot;"],
|
|
27
|
+
[/</g, "#lt;"],
|
|
28
|
+
[/>/g, "#gt;"],
|
|
29
|
+
[/'/g, "#39;"],
|
|
30
|
+
[/`/g, "#96;"],
|
|
31
|
+
[/\*/g, "#42;"],
|
|
32
|
+
[/_/g, "#95;"],
|
|
33
|
+
];
|
|
34
|
+
/** Escapes a topic for a quoted Mermaid label. */
|
|
35
|
+
export function escapeLabel(text, markdown = false) {
|
|
36
|
+
let label = String(text).replace(/\r\n?/g, "\n").replace(/\t/g, " ");
|
|
37
|
+
for (const [pattern, code] of ENTITIES)
|
|
38
|
+
label = label.replace(pattern, code);
|
|
39
|
+
if (markdown) {
|
|
40
|
+
label = label
|
|
41
|
+
.split("\n")
|
|
42
|
+
.map((line) => line.trim())
|
|
43
|
+
.join("\n")
|
|
44
|
+
.trim();
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
label = label.replace(/\s*\n\s*/g, " ").trim();
|
|
48
|
+
}
|
|
49
|
+
// An empty quoted label is a syntax error
|
|
50
|
+
return label || " ";
|
|
51
|
+
}
|
|
52
|
+
function label(node, markdown) {
|
|
53
|
+
const text = escapeLabel(node.topic, markdown);
|
|
54
|
+
if (!markdown)
|
|
55
|
+
return `"${text}"`;
|
|
56
|
+
let formatted = text;
|
|
57
|
+
if (text.trim()) {
|
|
58
|
+
if (node.style?.fontStyle === "italic")
|
|
59
|
+
formatted = `*${formatted}*`;
|
|
60
|
+
if (node.style?.fontWeight === "bold")
|
|
61
|
+
formatted = `**${formatted}**`;
|
|
62
|
+
}
|
|
63
|
+
return `"\`${formatted}\`"`;
|
|
64
|
+
}
|
|
65
|
+
function classes(value) {
|
|
66
|
+
if (value === undefined)
|
|
67
|
+
return [];
|
|
68
|
+
const names = (typeof value === "string" ? value.split(/\s+/) : [...value]).filter(Boolean);
|
|
69
|
+
for (const name of names) {
|
|
70
|
+
if (!CLASS_NAME.test(name))
|
|
71
|
+
throw new RangeError(`Invalid Mermaid class name: ${JSON.stringify(name)}`);
|
|
72
|
+
}
|
|
73
|
+
return names;
|
|
74
|
+
}
|
|
75
|
+
function isNode(value) {
|
|
76
|
+
return (typeof value === "object" &&
|
|
77
|
+
value !== null &&
|
|
78
|
+
typeof value.topic === "string");
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Converts Mind Elixir data (as returned by `mind.getData()`) or a single node and its
|
|
82
|
+
* descendants to Mermaid `mindmap` source.
|
|
83
|
+
*
|
|
84
|
+
* @throws {TypeError} when the input is not a Mind Elixir node or data.
|
|
85
|
+
* @throws {RangeError} when an option or a class name/icon returned by a callback is invalid.
|
|
86
|
+
*/
|
|
87
|
+
export function mindElixirToMermaid(data, options = {}) {
|
|
88
|
+
const root = isNode(data)
|
|
89
|
+
? data
|
|
90
|
+
: data?.nodeData;
|
|
91
|
+
if (!isNode(root))
|
|
92
|
+
throw new TypeError("Expected Mind Elixir data or a node with a string topic");
|
|
93
|
+
const indent = options.indent ?? 2;
|
|
94
|
+
if (!Number.isInteger(indent) || indent < 1 || indent > 8) {
|
|
95
|
+
throw new RangeError("indent must be an integer from 1 to 8");
|
|
96
|
+
}
|
|
97
|
+
const markdown = options.markdown === true;
|
|
98
|
+
const rootShape = options.rootShape ?? "circle";
|
|
99
|
+
const nodeShape = options.nodeShape ?? "rounded";
|
|
100
|
+
for (const shape of [rootShape, nodeShape]) {
|
|
101
|
+
if (!(shape in SHAPES))
|
|
102
|
+
throw new RangeError(`Unknown Mermaid shape: ${JSON.stringify(shape)}`);
|
|
103
|
+
}
|
|
104
|
+
const lines = ["mindmap"];
|
|
105
|
+
let count = 0;
|
|
106
|
+
// Iterative, so a very deep map cannot overflow the call stack
|
|
107
|
+
const stack = [
|
|
108
|
+
{ node: root, depth: 0 },
|
|
109
|
+
];
|
|
110
|
+
while (stack.length > 0) {
|
|
111
|
+
const { node: current, depth } = stack.pop();
|
|
112
|
+
// Every node of the map has the caller's node type
|
|
113
|
+
const node = current;
|
|
114
|
+
if (!isNode(node))
|
|
115
|
+
throw new TypeError("Every node must have a string topic");
|
|
116
|
+
const shape = options.shape?.(node, depth) ?? (depth === 0 ? rootShape : nodeShape);
|
|
117
|
+
const brackets = SHAPES[shape];
|
|
118
|
+
if (!brackets)
|
|
119
|
+
throw new RangeError(`Unknown Mermaid shape: ${JSON.stringify(shape)}`);
|
|
120
|
+
const pad = " ".repeat(indent * (depth + 1));
|
|
121
|
+
lines.push(`${pad}n${count++}${brackets[0]}${label(node, markdown)}${brackets[1]}`);
|
|
122
|
+
const icon = options.icon?.(node, depth);
|
|
123
|
+
if (icon !== undefined) {
|
|
124
|
+
if (!ICON.test(icon))
|
|
125
|
+
throw new RangeError(`Invalid Mermaid icon: ${JSON.stringify(icon)}`);
|
|
126
|
+
lines.push(`${pad}::icon(${icon})`);
|
|
127
|
+
}
|
|
128
|
+
const names = classes(options.className?.(node, depth));
|
|
129
|
+
if (names.length > 0)
|
|
130
|
+
lines.push(`${pad}:::${names.join(" ")}`);
|
|
131
|
+
if (options.omitCollapsed && node.expanded === false)
|
|
132
|
+
continue;
|
|
133
|
+
const children = node.children ?? [];
|
|
134
|
+
for (let i = children.length - 1; i >= 0; i--)
|
|
135
|
+
stack.push({ node: children[i], depth: depth + 1 });
|
|
136
|
+
}
|
|
137
|
+
return lines.join("\n");
|
|
138
|
+
}
|
|
139
|
+
export default mindElixirToMermaid;
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ateeducacion/mind-elixir-export-mermaid",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Export Mind Elixir mind maps to Mermaid mindmap syntax, for lightweight vector output with Mermaid or Pele",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Ernesto Serrano",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ateeducacion/mind-elixir-export-mermaid.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/ateeducacion/mind-elixir-export-mermaid#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/ateeducacion/mind-elixir-export-mermaid/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mind-elixir",
|
|
17
|
+
"mermaid",
|
|
18
|
+
"mindmap",
|
|
19
|
+
"mind-map",
|
|
20
|
+
"pele",
|
|
21
|
+
"svg",
|
|
22
|
+
"export"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"default": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
38
|
+
"sideEffects": false,
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=20"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsc -p tsconfig.build.json",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"format": "prettier --write .",
|
|
49
|
+
"format:check": "prettier --check .",
|
|
50
|
+
"test": "vitest run --coverage",
|
|
51
|
+
"test:watch": "vitest",
|
|
52
|
+
"check": "npm run format:check && npm run typecheck && npm test && npm run build",
|
|
53
|
+
"prepack": "npm run build",
|
|
54
|
+
"test:package": "node scripts/test-package.mjs"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/node": "26.6.4",
|
|
58
|
+
"@vitest/coverage-v8": "5.0.3",
|
|
59
|
+
"mind-elixir": "5.15.1",
|
|
60
|
+
"pele": "1.6.0",
|
|
61
|
+
"prettier": "3.9.9",
|
|
62
|
+
"typescript": "7.0.2",
|
|
63
|
+
"vitest": "5.0.3"
|
|
64
|
+
}
|
|
65
|
+
}
|