@restless-dreams/orbit 0.1.0 → 0.2.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/README.md +5 -2
- package/dist/bin/orbit.js +2972 -213
- package/dist/bin/orbit.js.map +25 -13
- package/dist/{chunk-mtrnm0yc.js → chunk-fkdfgtx9.js} +3156 -2854
- package/dist/chunk-fkdfgtx9.js.map +75 -0
- package/dist/{chunk-7n00wx0t.js → chunk-y748hzcr.js} +2 -2
- package/dist/{chunk-0gwh723s.js → chunk-zze4tc9n.js} +2 -2
- package/dist/core/branch-colors.d.ts +57 -0
- package/dist/core/document-source.d.ts +1 -1
- package/dist/core/editing.d.ts +8 -5
- package/dist/core/engine/scene.d.ts +5 -4
- package/dist/core/engine/views.d.ts +10 -2
- package/dist/core/index.d.ts +10 -0
- package/dist/core/input-controller.d.ts +7 -0
- package/dist/core/languages.d.ts +2 -0
- package/dist/core/node-attributes.d.ts +1 -1
- package/dist/core/other-apps/freemind.d.ts +8 -0
- package/dist/core/other-apps/icons.d.ts +16 -0
- package/dist/core/other-apps/ideas.d.ts +76 -0
- package/dist/core/other-apps/import.d.ts +28 -0
- package/dist/core/other-apps/inflate.d.ts +22 -0
- package/dist/core/other-apps/markup.d.ts +51 -0
- package/dist/core/other-apps/notes.d.ts +80 -0
- package/dist/core/other-apps/opml.d.ts +26 -0
- package/dist/core/other-apps/reading.d.ts +36 -0
- package/dist/core/other-apps/xmind.d.ts +14 -0
- package/dist/core/other-apps/zip.d.ts +37 -0
- package/dist/core/print-layout.d.ts +70 -0
- package/dist/core/renderer/content-painter.d.ts +30 -0
- package/dist/core/renderer/dom.d.ts +15 -0
- package/dist/core/renderer/families.d.ts +35 -0
- package/dist/core/renderer/label-painter.d.ts +93 -0
- package/dist/core/renderer/node-painter.d.ts +113 -0
- package/dist/core/renderer/numbers.d.ts +2 -0
- package/dist/core/renderer/options.d.ts +12 -0
- package/dist/core/renderer/rings-and-links.d.ts +23 -0
- package/dist/core/renderer/scene-helpers.d.ts +33 -0
- package/dist/core/renderer/trees.d.ts +22 -0
- package/dist/core/svg-renderer.d.ts +6 -109
- package/dist/core/types.d.ts +9 -1
- package/dist/core/web-page/page.d.ts +2 -1
- package/dist/core/web-page/runtime.d.ts +1 -1
- package/dist/index.js +2935 -26
- package/dist/index.js.map +18 -6
- package/dist/marked/index.js +2 -2
- package/dist/react/index.js +2 -2
- package/dist/web-page.js +79 -79
- package/llms-full.txt +205 -5
- package/llms.txt +2 -1
- package/package.json +1 -1
- package/skills/orbit/SKILL.md +1 -1
- package/skills/orbit/references/editing.md +2 -1
- package/skills/orbit/references/format.md +28 -0
- package/skills/orbit/references/guide.md +25 -1
- package/skills/orbit/references/import-export.md +115 -0
- package/skills/orbit/references/languages.md +1 -0
- package/skills/orbit/references/recipes.md +9 -0
- package/skills/orbit/references/theming.md +15 -0
- package/dist/chunk-mtrnm0yc.js.map +0 -63
- /package/dist/{chunk-7n00wx0t.js.map → chunk-y748hzcr.js.map} +0 -0
- /package/dist/{chunk-0gwh723s.js.map → chunk-zze4tc9n.js.map} +0 -0
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
exportDisplay,
|
|
18
18
|
escapeXml,
|
|
19
19
|
MapExtensions
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-fkdfgtx9.js";
|
|
21
21
|
|
|
22
22
|
// src/core/render-to-svg.ts
|
|
23
23
|
var MAX_SVG_EXPORT_SIZE = 1e6;
|
|
@@ -79,4 +79,4 @@ var emptyMap = (title, message, viewport, tokens, responsive) => {
|
|
|
79
79
|
export { renderToSVGString2 };
|
|
80
80
|
|
|
81
81
|
//# debugId=FAD148488126235164756E2164756E21
|
|
82
|
-
//# sourceMappingURL=chunk-
|
|
82
|
+
//# sourceMappingURL=chunk-y748hzcr.js.map
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
parseOrbit2,
|
|
10
10
|
wordsFor,
|
|
11
11
|
OrbitSVGRenderer2
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-fkdfgtx9.js";
|
|
13
13
|
|
|
14
14
|
// src/core/auto-render.ts
|
|
15
15
|
var DEFAULT_SELECTOR = ".orbit-mind-map[data-orbit], pre > code.language-orbit, pre.orbit-rendered[data-orbit-source], orbit-map";
|
|
@@ -405,4 +405,4 @@ var applyClassNames = (element, className) => {
|
|
|
405
405
|
export { renderOrbitElement2, renderOrbitMarkdownBlocks2, defineOrbitMapElement2 };
|
|
406
406
|
|
|
407
407
|
//# debugId=46D6FAE5FFE8EFBC64756E2164756E21
|
|
408
|
-
//# sourceMappingURL=chunk-
|
|
408
|
+
//# sourceMappingURL=chunk-zze4tc9n.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which of the palette's colors each top-level node takes, and how edits
|
|
3
|
+
* keep them. The root takes the palette's first color, and top-level nodes
|
|
4
|
+
* take the others in turn, cycling. A node with a `paletteColor` takes that
|
|
5
|
+
* one instead and gives up its turn, so the nodes after it keep theirs.
|
|
6
|
+
* Edits write a `paletteColor` where a node's turn would change, so adding,
|
|
7
|
+
* moving or removing a node never gives the others new colors.
|
|
8
|
+
*/
|
|
9
|
+
import type { OrbitNode } from './types.js';
|
|
10
|
+
/** A node's own color, or its type's: what it shows instead of the palette's. */
|
|
11
|
+
export type OwnColor = (node: OrbitNode) => string | undefined;
|
|
12
|
+
/** What an edit needs to keep top-level nodes' colors. */
|
|
13
|
+
export interface BranchColorRules {
|
|
14
|
+
/** How many colors top-level nodes take turns with: the palette's, after the root's (see `branchPalette`). */
|
|
15
|
+
count: number;
|
|
16
|
+
/** A node's own color or its type's, which it shows instead of the palette's. Default: its `color`. */
|
|
17
|
+
ownColor?: OwnColor;
|
|
18
|
+
}
|
|
19
|
+
/** Each top-level node's palette number before an edit, from `branchColorsBefore`. */
|
|
20
|
+
export type BranchColors = Map<OrbitNode, number>;
|
|
21
|
+
/** The node an edit was about, for `keepBranchColors`. */
|
|
22
|
+
export interface EditedBranch {
|
|
23
|
+
node: OrbitNode;
|
|
24
|
+
/** Whether the node keeps the color it had (a move), rather than taking one no other top-level node has (a new node). */
|
|
25
|
+
keepsColor: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** The colors top-level nodes take turns with: every palette color after the root's, or the only one. */
|
|
28
|
+
export declare const branchPalette: (palette: readonly string[]) => string[];
|
|
29
|
+
/** Whether a value is a palette number: a whole number from 1. */
|
|
30
|
+
export declare const isPaletteNumber: (value: unknown) => value is number;
|
|
31
|
+
/** The color a palette number names among `colors` (from `branchPalette`), cycling. */
|
|
32
|
+
export declare const paletteColorOf: (colors: readonly string[], paletteNumber: number) => string;
|
|
33
|
+
/**
|
|
34
|
+
* The palette number each of `branches` takes its color from: its
|
|
35
|
+
* `paletteColor`, or else the next number in turn that none of them has as
|
|
36
|
+
* its `paletteColor`. Nodes with a color or type of their own take a turn
|
|
37
|
+
* too, so the nodes after them have the colors they'd have without one.
|
|
38
|
+
*/
|
|
39
|
+
export declare const branchNumbers: (branches: readonly OrbitNode[], count: number) => Map<OrbitNode, number>;
|
|
40
|
+
/** Each top-level node's palette number, to keep through an edit with `keepBranchColors`. */
|
|
41
|
+
export declare const branchColorsBefore: (root: OrbitNode, rules: BranchColorRules) => BranchColors;
|
|
42
|
+
/**
|
|
43
|
+
* After an edit, gives every top-level node that was there before the color
|
|
44
|
+
* it had, writing its palette number as its `paletteColor` where its turn
|
|
45
|
+
* changed. The node the edit was about keeps its color when it moved within
|
|
46
|
+
* the top level, takes one no other top-level node has when it's new there
|
|
47
|
+
* (while there is one), and drops its `paletteColor` when it left the top
|
|
48
|
+
* level, to take its new branch's color. Nodes showing a color or type of
|
|
49
|
+
* their own are left as they are, and a `paletteColor` is written only where
|
|
50
|
+
* a color would change otherwise.
|
|
51
|
+
*
|
|
52
|
+
* An edit that would write more numbers than the palette has colors writes
|
|
53
|
+
* none: that happens only where the top level has more nodes than colors,
|
|
54
|
+
* which repeat there anyway, and a big orbit's every node would get one.
|
|
55
|
+
* Returns the nodes it changed.
|
|
56
|
+
*/
|
|
57
|
+
export declare const keepBranchColors: (root: OrbitNode, before: BranchColors, rules: BranchColorRules, edited?: EditedBranch) => OrbitNode[];
|
|
@@ -43,7 +43,7 @@ export type NodeShape = {
|
|
|
43
43
|
lead: boolean;
|
|
44
44
|
};
|
|
45
45
|
/** A node's own fields, as they were read: to tell which ones an edit changed. */
|
|
46
|
-
export type NodeFields = Pick<OrbitNode, 'id' | 'text' | 'icon' | 'link' | 'status' | 'tags' | 'color' | 'priority' | 'collapsed' | 'type' | 'typeVersion' | 'note' | 'noteFormat' | 'image' | 'video' | 'embed' | 'attrs'>;
|
|
46
|
+
export type NodeFields = Pick<OrbitNode, 'id' | 'text' | 'icon' | 'link' | 'status' | 'tags' | 'color' | 'paletteColor' | 'priority' | 'collapsed' | 'type' | 'typeVersion' | 'note' | 'noteFormat' | 'image' | 'video' | 'embed' | 'attrs'>;
|
|
47
47
|
export interface NodeRecord {
|
|
48
48
|
shape: NodeShape;
|
|
49
49
|
/** The title line, 0-based; null for a generated root without a lead paragraph. */
|
package/dist/core/editing.d.ts
CHANGED
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
* Changes to a map's tree, behind the renderer's `addNode`, `updateNode`,
|
|
3
3
|
* `removeNode` and `moveNode`, and the map tools, which make them on a map
|
|
4
4
|
* that isn't drawn too. Ids follow the parsers' rules, so a map saved with
|
|
5
|
-
* `toMarkdown()` reads back with the same ids.
|
|
5
|
+
* `toMarkdown()` reads back with the same ids. Given the palette's rules,
|
|
6
|
+
* each change keeps the colors of the top-level nodes it doesn't change
|
|
7
|
+
* (see `keepBranchColors`).
|
|
6
8
|
*/
|
|
7
9
|
import type { OrbitNewNode, OrbitNode, OrbitNodeInput } from './types.js';
|
|
10
|
+
import { type BranchColorRules } from './branch-colors.js';
|
|
8
11
|
/** Every id in the tree. */
|
|
9
12
|
export declare const nodeIds: (root: OrbitNode) => Set<string>;
|
|
10
13
|
/** `base` when no node has it, otherwise `base-2`, `base-3`…, the way the parsers number repeated titles. */
|
|
@@ -33,7 +36,7 @@ export declare const insertChild: (parent: OrbitNode, node: OrbitNode, parentLev
|
|
|
33
36
|
/** Takes `node` out of `parent`'s children. */
|
|
34
37
|
export declare const detachChild: (parent: OrbitNode, node: OrbitNode) => void;
|
|
35
38
|
/** Adds `input`, with its children, under `parentId` at `index` among its children (default: last). Null when there's no such parent. */
|
|
36
|
-
export declare const addToTree: (root: OrbitNode, parentId: string, input: OrbitNewNode, index?: number) => {
|
|
39
|
+
export declare const addToTree: (root: OrbitNode, parentId: string, input: OrbitNewNode, index?: number, colors?: BranchColorRules) => {
|
|
37
40
|
node: OrbitNode;
|
|
38
41
|
parent: OrbitNode;
|
|
39
42
|
} | null;
|
|
@@ -42,12 +45,12 @@ export declare const addToTree: (root: OrbitNode, parentId: string, input: Orbit
|
|
|
42
45
|
* node a new id when its id came from its text and no link points at it,
|
|
43
46
|
* so the saved map needs no id attribute. Null when there's no such node.
|
|
44
47
|
*/
|
|
45
|
-
export declare const updateInTree: (root: OrbitNode, id: string, changes: OrbitNodeInput) => {
|
|
48
|
+
export declare const updateInTree: (root: OrbitNode, id: string, changes: OrbitNodeInput, colors?: BranchColorRules) => {
|
|
46
49
|
node: OrbitNode;
|
|
47
50
|
previousId: string;
|
|
48
51
|
} | null;
|
|
49
52
|
/** Takes `id` and everything under it out of the tree. Null when there's no such node, or for the root. */
|
|
50
|
-
export declare const removeFromTree: (root: OrbitNode, id: string) => {
|
|
53
|
+
export declare const removeFromTree: (root: OrbitNode, id: string, colors?: BranchColorRules) => {
|
|
51
54
|
node: OrbitNode;
|
|
52
55
|
parent: OrbitNode;
|
|
53
56
|
} | null;
|
|
@@ -56,7 +59,7 @@ export declare const removeFromTree: (root: OrbitNode, id: string) => {
|
|
|
56
59
|
* its children (default: last). Null when either node is missing, the node
|
|
57
60
|
* is the root, or `parentId` is inside it.
|
|
58
61
|
*/
|
|
59
|
-
export declare const moveInTree: (root: OrbitNode, id: string, parentId: string, index?: number) => {
|
|
62
|
+
export declare const moveInTree: (root: OrbitNode, id: string, parentId: string, index?: number, colors?: BranchColorRules) => {
|
|
60
63
|
node: OrbitNode;
|
|
61
64
|
from: OrbitNode;
|
|
62
65
|
to: OrbitNode;
|
|
@@ -129,10 +129,11 @@ export declare const CROWDED_ORBIT = 48;
|
|
|
129
129
|
export declare const fitScene: (scene: Scene, viewport: Viewport, insets?: Insets, below?: number) => Camera;
|
|
130
130
|
/**
|
|
131
131
|
* One color per node, the same in every view. The root uses the first
|
|
132
|
-
* palette entry;
|
|
133
|
-
* their branch's color, mixed toward the
|
|
134
|
-
* `shade-dark` by position so siblings stay
|
|
135
|
-
* color always wins: its `color`, or its
|
|
132
|
+
* palette entry; top-level branches take the others in turn (see
|
|
133
|
+
* `branchNumbers`); deeper nodes use their branch's color, mixed toward the
|
|
134
|
+
* theme's `shade-light` or `shade-dark` by position so siblings stay
|
|
135
|
+
* distinguishable. A node's own color always wins: its `color`, or its
|
|
136
|
+
* type's (see `ownColor`); then its `paletteColor`.
|
|
136
137
|
*/
|
|
137
138
|
export declare const assignNodeColors: (tree: OrbitNode, palette: string[], ownColor?: (node: OrbitNode) => string | undefined) => Map<string, string>;
|
|
138
139
|
/** How much of the branch color each sibling keeps, and what the rest is mixed with. */
|
|
@@ -80,14 +80,20 @@ export declare const createDefinitions: (ids: ViewIds) => SVGDefsElement;
|
|
|
80
80
|
export declare const turnShading: (defs: SVGDefsElement, ids: ViewIds, turn: number) => void;
|
|
81
81
|
/** Labels and the assistive name of a node, in the map's language (English without one). */
|
|
82
82
|
export declare const describeNode: (node: OrbitNode, hiddenChildren: number, visibleChildren: number, extensions?: MapExtensions, words?: OrbitWords) => string;
|
|
83
|
-
/**
|
|
84
|
-
|
|
83
|
+
/**
|
|
84
|
+
* The on-screen radius (px) below which flat bodies are specks, at
|
|
85
|
+
* `pixelRatio` device pixels per px: bigger for a `plainCrowded` planet, one
|
|
86
|
+
* of a crowded orbit without badges (a status, a note's marker, a play button).
|
|
87
|
+
*/
|
|
88
|
+
export declare const speckRadius: (pixelRatio: number, plainCrowded?: boolean) => number;
|
|
85
89
|
/** What every node is drawn with this frame, besides its own place (see `NodeView.update`). */
|
|
86
90
|
export interface NodeDrawing {
|
|
87
91
|
/** In an orbit turned as one, the degrees it's turned (see `OrbitTurn`). */
|
|
88
92
|
turn?: number;
|
|
89
93
|
/** The on-screen radius (px) below which flat bodies are specks (see `speckRadius`). */
|
|
90
94
|
speckRadius: number;
|
|
95
|
+
/** The same for a crowded orbit's planets without badges. */
|
|
96
|
+
crowdedSpeckRadius: number;
|
|
91
97
|
/**
|
|
92
98
|
* How many more nodes may become specks, or stop being them, this frame.
|
|
93
99
|
* The rest wait for the next: a zoom across the size where a whole orbit
|
|
@@ -119,6 +125,8 @@ export declare class NodeView {
|
|
|
119
125
|
readonly typeName: string | undefined;
|
|
120
126
|
/** Shows a picture (an image, or a video's thumbnail) rather than a plain color. */
|
|
121
127
|
hasImage: boolean;
|
|
128
|
+
/** Shows a status, a note's marker or a play button: a crowded orbit's planet with one stays a body down to the usual size (see `speckRadius`). */
|
|
129
|
+
private readonly hasBadges;
|
|
122
130
|
private readonly body;
|
|
123
131
|
private readonly disc;
|
|
124
132
|
private readonly shade;
|
package/dist/core/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export { documentToRendererOptions } from './document-options.js';
|
|
|
11
11
|
export { OrbitSVGRenderer } from './svg-renderer.js';
|
|
12
12
|
export { createOrbitMap } from './create.js';
|
|
13
13
|
export { renderToSVGString } from './render-to-svg.js';
|
|
14
|
+
export { PRINT_THEMES, printTheme, renderPrintLayout } from './print-layout.js';
|
|
15
|
+
export type { OrbitPrintOptions } from './print-layout.js';
|
|
14
16
|
export { exportWebPage } from './web-page/page.js';
|
|
15
17
|
export type { OrbitWebPageOptions } from './web-page/page.js';
|
|
16
18
|
export { createMapTools } from './map-tools/tools.js';
|
|
@@ -18,6 +20,14 @@ export type { MapTools, MapToolsOptions, MapToolResult } from './map-tools/tools
|
|
|
18
20
|
export type { MapToolDefinition, MapToolFormats, MapToolName, MapToolProvider } from './map-tools/definitions.js';
|
|
19
21
|
export type { MapToolProperty, MapToolSchema } from './map-tools/input.js';
|
|
20
22
|
export type { RenderToSVGOptions } from './render-to-svg.js';
|
|
23
|
+
export { detectImportFormat, importMap } from './other-apps/import.js';
|
|
24
|
+
export { importOPML, exportOPML } from './other-apps/opml.js';
|
|
25
|
+
export type { OrbitOPMLOptions } from './other-apps/opml.js';
|
|
26
|
+
export { importFreeMind } from './other-apps/freemind.js';
|
|
27
|
+
export { importXMind } from './other-apps/xmind.js';
|
|
28
|
+
export { IMPORT_ERROR_CODES, IMPORT_WARNING_CODES, OrbitImportError } from './other-apps/ideas.js';
|
|
29
|
+
export type { OrbitImportErrorCode, OrbitImportWarning, OrbitImportWarningCode } from './other-apps/ideas.js';
|
|
30
|
+
export type { OrbitImport, OrbitImportedMap, OrbitImportFormat, OrbitImportOptions } from './other-apps/reading.js';
|
|
21
31
|
export { renderNoteMarkdown } from './ui/note-markdown.js';
|
|
22
32
|
export type { NoteRenderContext as OrbitNoteOptions } from './ui/note-markdown.js';
|
|
23
33
|
export type { CreateOrbitMapOptions } from './create.js';
|
|
@@ -66,6 +66,13 @@ export declare class InputController {
|
|
|
66
66
|
private engaged;
|
|
67
67
|
private startPoint;
|
|
68
68
|
private lastPoint;
|
|
69
|
+
/**
|
|
70
|
+
* Where the map was on the page when the pointers now down first touched
|
|
71
|
+
* it. Asking again on every move would make the browser lay out the whole
|
|
72
|
+
* map each time, thousands of elements on a big one, and a pointer can
|
|
73
|
+
* move several times a frame.
|
|
74
|
+
*/
|
|
75
|
+
private gestureRectangle;
|
|
69
76
|
private lastPinchDistance;
|
|
70
77
|
private lastPinchCenter;
|
|
71
78
|
private suppressNextClick;
|
package/dist/core/languages.d.ts
CHANGED
|
@@ -125,6 +125,8 @@ export interface OrbitStrings {
|
|
|
125
125
|
openLink: string;
|
|
126
126
|
/** A link to another idea of the map: `{name}` is that idea, or `theIdea` when it has no text. */
|
|
127
127
|
goTo: string;
|
|
128
|
+
/** The same link printed, where it can't be followed: `{name}` is that idea. */
|
|
129
|
+
seeIdea: string;
|
|
128
130
|
/** The detail sheet's name when the idea has no text. */
|
|
129
131
|
details: string;
|
|
130
132
|
close: string;
|
|
@@ -15,7 +15,7 @@ export declare const readImage: (value: unknown) => ImageMedia | undefined;
|
|
|
15
15
|
export declare const readVideo: (value: unknown) => VideoMedia | undefined;
|
|
16
16
|
export declare const readEmbed: (value: unknown) => EmbedMedia | undefined;
|
|
17
17
|
/** The attributes every node takes, in `<!-- orbit … -->` blocks and in YAML. */
|
|
18
|
-
export declare const NODE_ATTRIBUTE_KEYS: readonly ["color", "icon", "status", "priority", "tags", "collapsed", "link", "note", "noteFormat", "image", "video", "embed", "caption", "id", "type"];
|
|
18
|
+
export declare const NODE_ATTRIBUTE_KEYS: readonly ["color", "paletteColor", "icon", "status", "priority", "tags", "collapsed", "link", "note", "noteFormat", "image", "video", "embed", "caption", "id", "type"];
|
|
19
19
|
/** Keys a flavor accepts besides the node attributes, and the words that stand in for them. */
|
|
20
20
|
export interface AttributeVocabulary {
|
|
21
21
|
keys: readonly string[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FreeMind and Freeplane maps (`.mm`): nodes with their text (plain, or
|
|
3
|
+
* HTML), notes and Freeplane's details, links and arrow links, folds, icons,
|
|
4
|
+
* background colors, attributes and pictures.
|
|
5
|
+
*/
|
|
6
|
+
import { type OrbitImport, type OrbitImportOptions } from './reading.js';
|
|
7
|
+
/** A FreeMind or Freeplane map, from its file's bytes or text. */
|
|
8
|
+
export declare const importFreeMind: (data: Uint8Array | string, options?: OrbitImportOptions) => OrbitImport;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Other apps' icons and markers, as Orbit says the same thing: an emoji for
|
|
3
|
+
* the idea's icon, a priority, or a status. An icon with no meaning here
|
|
4
|
+
* returns null, and the reader warns that it was left out.
|
|
5
|
+
*/
|
|
6
|
+
export type IconMeaning = {
|
|
7
|
+
icon: string;
|
|
8
|
+
} | {
|
|
9
|
+
priority: number;
|
|
10
|
+
} | {
|
|
11
|
+
status: string;
|
|
12
|
+
};
|
|
13
|
+
/** A FreeMind or Freeplane icon's meaning: `full-3` is priority 3, `100%` done, `emoji-1F680` 🚀. */
|
|
14
|
+
export declare const freeMindIcon: (name: string) => IconMeaning | null;
|
|
15
|
+
/** An XMind marker's meaning: `priority-2` is priority 2, `task-done` done, `flag-red` 🚩. */
|
|
16
|
+
export declare const xmindMarker: (markerId: string) => IconMeaning | null;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What every reader of another app's file builds: a tree of ideas with what
|
|
3
|
+
* Orbit can show of each, the warnings for what it can't, and the step that
|
|
4
|
+
* turns the tree into an Orbit document, with ids the parsers would give it
|
|
5
|
+
* and links between ideas pointing at those ids.
|
|
6
|
+
*/
|
|
7
|
+
import type { OrbitDocument } from '../types.js';
|
|
8
|
+
import { type ImportedNote } from './notes.js';
|
|
9
|
+
/** Every kind of warning reading another app's map gives. */
|
|
10
|
+
export declare const IMPORT_WARNING_CODES: readonly ["floating-ideas-moved", "summaries-moved", "callouts-moved", "boundaries-in-notes", "links-in-notes", "missing-link-targets", "icons-not-kept", "pictures-not-kept", "attachments-not-kept", "local-links-not-kept", "encrypted-branches-not-read", "formatting-not-kept"];
|
|
11
|
+
export type OrbitImportWarningCode = (typeof IMPORT_WARNING_CODES)[number];
|
|
12
|
+
/** Something the other app's map had that Orbit keeps another way, or can't keep. */
|
|
13
|
+
export interface OrbitImportWarning {
|
|
14
|
+
code: OrbitImportWarningCode;
|
|
15
|
+
message: string;
|
|
16
|
+
/** How many places in the map it's about. */
|
|
17
|
+
count: number;
|
|
18
|
+
}
|
|
19
|
+
/** Every reason a file can't be read as a map. */
|
|
20
|
+
export declare const IMPORT_ERROR_CODES: readonly ["unknown-format", "unreadable", "empty", "password-protected", "too-large"];
|
|
21
|
+
export type OrbitImportErrorCode = (typeof IMPORT_ERROR_CODES)[number];
|
|
22
|
+
/** A file that can't be read as a map at all. */
|
|
23
|
+
export declare class OrbitImportError extends Error {
|
|
24
|
+
readonly code: OrbitImportErrorCode;
|
|
25
|
+
constructor(code: OrbitImportErrorCode, message: string);
|
|
26
|
+
}
|
|
27
|
+
/** The most ideas a map read from another app may have. */
|
|
28
|
+
export declare const MAX_IMPORTED_IDEAS = 100000;
|
|
29
|
+
/** The deepest a map read from another app may go. */
|
|
30
|
+
export declare const MAX_IMPORTED_DEPTH = 500;
|
|
31
|
+
/** A link from one idea to another, by the other app's id for it. */
|
|
32
|
+
export interface IdeaLink {
|
|
33
|
+
target: string;
|
|
34
|
+
/** What the other app calls the link, if anything. */
|
|
35
|
+
label?: string;
|
|
36
|
+
}
|
|
37
|
+
/** An idea as a reader finds it, before it becomes a node. */
|
|
38
|
+
export interface ImportedIdea {
|
|
39
|
+
text: string;
|
|
40
|
+
/** The other app's id for it, which links between ideas point at. */
|
|
41
|
+
sourceId?: string;
|
|
42
|
+
/** Its note, in parts: they're joined in order. */
|
|
43
|
+
notes: ImportedNote[];
|
|
44
|
+
/** A web or mail address. */
|
|
45
|
+
link?: string;
|
|
46
|
+
/** Links to other ideas: the first one becomes the idea's link when it has none, the others go in its note. */
|
|
47
|
+
ideaLinks: IdeaLink[];
|
|
48
|
+
collapsed?: boolean;
|
|
49
|
+
status?: string;
|
|
50
|
+
priority?: number;
|
|
51
|
+
tags: string[];
|
|
52
|
+
/** Emoji for its icons, in order: Orbit shows the first. */
|
|
53
|
+
icons: string[];
|
|
54
|
+
color?: string;
|
|
55
|
+
/** Its picture: a web address, or a file in the map's `media`. */
|
|
56
|
+
image?: string;
|
|
57
|
+
children: ImportedIdea[];
|
|
58
|
+
}
|
|
59
|
+
export declare const newIdea: (text: string) => ImportedIdea;
|
|
60
|
+
/** The warnings for one map, each kind counted once with a few examples. */
|
|
61
|
+
export declare class ImportReport {
|
|
62
|
+
private readonly found;
|
|
63
|
+
add(code: OrbitImportWarningCode, example?: string): void;
|
|
64
|
+
/** The warnings in the order of `IMPORT_WARNING_CODES`. */
|
|
65
|
+
get warnings(): OrbitImportWarning[];
|
|
66
|
+
}
|
|
67
|
+
/** A title on one line, as Orbit keeps titles: line breaks, tabs and runs of spaces become one space; other spaces stay as they are. */
|
|
68
|
+
export declare const oneLine: (text: string) => string;
|
|
69
|
+
/** A link in a note to the idea with this id in the other app: it points at the idea's Orbit id once the map is built. */
|
|
70
|
+
export declare const sourceLink: (sourceId: string) => string;
|
|
71
|
+
/**
|
|
72
|
+
* The tree as an Orbit document: titles on one line, an emoji at the start
|
|
73
|
+
* of a title as the idea's icon (as Orbit's markdown reads it), ids from the
|
|
74
|
+
* titles as the parsers give them, and links between ideas pointing at them.
|
|
75
|
+
*/
|
|
76
|
+
export declare const buildDocument: (rootIdea: ImportedIdea, report: ImportReport) => OrbitDocument;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps from other apps: OPML from outliners and most mind map apps,
|
|
3
|
+
* FreeMind and Freeplane's `.mm`, and XMind's `.xmind`. `importMap` tells
|
|
4
|
+
* the format from the file's name or what it holds and reads it into Orbit
|
|
5
|
+
* maps, with the pictures inside the file and warnings for what Orbit keeps
|
|
6
|
+
* another way or couldn't keep.
|
|
7
|
+
*/
|
|
8
|
+
import type { OrbitImport, OrbitImportFormat, OrbitImportOptions } from './reading.js';
|
|
9
|
+
/**
|
|
10
|
+
* The format of another app's map, from what the file holds, then from its
|
|
11
|
+
* name; null when it's none Orbit reads. Orbit's own markdown and YAML, and
|
|
12
|
+
* its zips, are null too: read those with `parseOrbit`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const detectImportFormat: (data: Uint8Array | string, name?: string) => OrbitImportFormat | null;
|
|
15
|
+
/**
|
|
16
|
+
* Another app's map as Orbit maps: OPML, FreeMind and Freeplane, or XMind.
|
|
17
|
+
* Pass the file's bytes (its text works for OPML and `.mm`) and its name.
|
|
18
|
+
* Throws an `OrbitImportError` for a file it can't read: one in no format it
|
|
19
|
+
* knows (`unknown-format`), a damaged one (`unreadable`), one with no ideas
|
|
20
|
+
* (`empty`), an XMind workbook with a password (`password-protected`), or one
|
|
21
|
+
* past its limits (`too-large`).
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* const { maps } = importMap(bytes, { name: 'Trip.xmind' });
|
|
25
|
+
* const markdown = serializeOrbitMarkdown(maps[0].document);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare const importMap: (data: Uint8Array | string, options?: OrbitImportOptions) => OrbitImport;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inflate (RFC 1951), the compression inside zip files, read synchronously
|
|
3
|
+
* and without `DecompressionStream`: the oldest browsers Orbit draws in
|
|
4
|
+
* can't decompress raw deflate data, and a command line has no need to wait.
|
|
5
|
+
* Codes are decoded the canonical way, a bit at a time, which is plenty fast
|
|
6
|
+
* for the few megabytes a map holds.
|
|
7
|
+
*/
|
|
8
|
+
/** Data that isn't valid deflate data, or holds more than it said it would. */
|
|
9
|
+
export declare class InflateError extends Error {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Raw deflate data, inflated. `expected` sizes the output when it's known
|
|
14
|
+
* (a zip entry says so); the output never grows past `limit`, so a small
|
|
15
|
+
* file can't unpack into an enormous one.
|
|
16
|
+
*/
|
|
17
|
+
export declare const inflate: (data: Uint8Array, options?: {
|
|
18
|
+
expected?: number;
|
|
19
|
+
limit?: number;
|
|
20
|
+
}) => Uint8Array;
|
|
21
|
+
/** The CRC-32 zip files check their entries with. */
|
|
22
|
+
export declare const crc32: (bytes: Uint8Array) => number;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A small XML reader for other apps' map files, and a forgiving reader for
|
|
3
|
+
* the HTML in their notes. Neither loads anything a file points to: XML
|
|
4
|
+
* reads its five entities and numeric references only, HTML adds a fixed
|
|
5
|
+
* table of common named ones, a DOCTYPE is skipped without reading what it
|
|
6
|
+
* declares, and the size of the input and the depth of nesting are capped.
|
|
7
|
+
*/
|
|
8
|
+
export interface MarkupElement {
|
|
9
|
+
/** The element's name as written, with its prefix: `xhtml:p`. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** The name without a prefix, lowercased in HTML: `p`. */
|
|
12
|
+
localName: string;
|
|
13
|
+
/** Attributes by name as written, values decoded. */
|
|
14
|
+
attributes: Record<string, string>;
|
|
15
|
+
children: MarkupNode[];
|
|
16
|
+
}
|
|
17
|
+
/** An element, or text. */
|
|
18
|
+
export type MarkupNode = MarkupElement | string;
|
|
19
|
+
/** A file that isn't well-formed XML, or too big or too deep to read. */
|
|
20
|
+
export declare class MarkupError extends Error {
|
|
21
|
+
/** The 1-based line of the problem. */
|
|
22
|
+
readonly line: number;
|
|
23
|
+
constructor(message: string, line: number);
|
|
24
|
+
}
|
|
25
|
+
/** The most characters a file may have: far beyond any map, short of exhausting memory. */
|
|
26
|
+
export declare const MAX_MARKUP_LENGTH: number;
|
|
27
|
+
/** The deepest nesting read: deeper files are refused rather than risking the stack. */
|
|
28
|
+
export declare const MAX_MARKUP_DEPTH = 1000;
|
|
29
|
+
/**
|
|
30
|
+
* An XML file's bytes as text, in the encoding its byte order mark or its
|
|
31
|
+
* declaration names (UTF-8 when neither does). Old OPML files are often
|
|
32
|
+
* ISO-8859-1. A file that isn't valid UTF-8 and names no encoding is read as
|
|
33
|
+
* Windows-1252, which every byte is.
|
|
34
|
+
*/
|
|
35
|
+
export declare const decodeMarkup: (bytes: Uint8Array) => string;
|
|
36
|
+
/**
|
|
37
|
+
* The document element of an XML file. Throws a `MarkupError` for a file
|
|
38
|
+
* that isn't well-formed, so a damaged map is refused rather than read in part.
|
|
39
|
+
*/
|
|
40
|
+
export declare const parseXml: (text: string) => MarkupElement;
|
|
41
|
+
/** A piece of HTML, as the children of an element named `#fragment`. Never throws for markup it can read some way. */
|
|
42
|
+
export declare const parseHtml: (text: string) => MarkupElement;
|
|
43
|
+
export declare const isElement: (node: MarkupNode) => node is MarkupElement;
|
|
44
|
+
/** The element's child elements, all of them or those with one local name. */
|
|
45
|
+
export declare const childElements: (element: MarkupElement, localName?: string) => MarkupElement[];
|
|
46
|
+
/** The element's first child element with this local name. */
|
|
47
|
+
export declare const childElement: (element: MarkupElement, localName: string) => MarkupElement | undefined;
|
|
48
|
+
/** An attribute by its name without a prefix: `href` finds `xlink:href`. */
|
|
49
|
+
export declare const attributeOf: (element: MarkupElement, localName: string) => string | undefined;
|
|
50
|
+
/** All the text inside an element, as written. */
|
|
51
|
+
export declare const textContent: (node: MarkupNode) => string;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notes and titles from other apps. HTML notes become markdown (paragraphs,
|
|
3
|
+
* headings, lists, quotes, code, bold, italic, strikethrough, links and
|
|
4
|
+
* pictures), never HTML. When markdown would show the note's text any other
|
|
5
|
+
* way (a `*` or `_` in it, a line that starts like a list), the note is kept
|
|
6
|
+
* as plain text instead, exactly as written: formatting can be lost, words
|
|
7
|
+
* never are.
|
|
8
|
+
*/
|
|
9
|
+
import { type MarkupElement, type MarkupNode } from './markup.js';
|
|
10
|
+
/** A note as Orbit keeps it. */
|
|
11
|
+
export interface ImportedNote {
|
|
12
|
+
text: string;
|
|
13
|
+
format: 'markdown' | 'plain';
|
|
14
|
+
}
|
|
15
|
+
/** Inline content, as the note's reader shows it. */
|
|
16
|
+
export type NoteInline = {
|
|
17
|
+
kind: 'text';
|
|
18
|
+
text: string;
|
|
19
|
+
} | {
|
|
20
|
+
kind: 'break';
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'strong' | 'emphasis' | 'strike';
|
|
23
|
+
children: NoteInline[];
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'code';
|
|
26
|
+
text: string;
|
|
27
|
+
} | {
|
|
28
|
+
kind: 'link';
|
|
29
|
+
href: string;
|
|
30
|
+
children: NoteInline[];
|
|
31
|
+
} | {
|
|
32
|
+
kind: 'image';
|
|
33
|
+
src: string;
|
|
34
|
+
alt: string;
|
|
35
|
+
};
|
|
36
|
+
/** A block of a note. */
|
|
37
|
+
export type NoteBlock = {
|
|
38
|
+
kind: 'paragraph';
|
|
39
|
+
inline: NoteInline[];
|
|
40
|
+
} | {
|
|
41
|
+
kind: 'heading';
|
|
42
|
+
level: number;
|
|
43
|
+
inline: NoteInline[];
|
|
44
|
+
} | {
|
|
45
|
+
kind: 'list';
|
|
46
|
+
ordered: boolean;
|
|
47
|
+
items: NoteBlock[][];
|
|
48
|
+
} | {
|
|
49
|
+
kind: 'quote';
|
|
50
|
+
blocks: NoteBlock[];
|
|
51
|
+
} | {
|
|
52
|
+
kind: 'code';
|
|
53
|
+
text: string;
|
|
54
|
+
};
|
|
55
|
+
/** How addresses in a note are kept. */
|
|
56
|
+
export interface NoteAddresses {
|
|
57
|
+
/** The address a link keeps, or null for its text alone. Default: web and mail addresses, and `#` links. */
|
|
58
|
+
link?: (href: string) => string | null;
|
|
59
|
+
/** The address a picture keeps, or null for its description alone. Default: web addresses. */
|
|
60
|
+
picture?: (src: string) => string | null;
|
|
61
|
+
}
|
|
62
|
+
/** Web and mail addresses, and links within the map. */
|
|
63
|
+
export declare const isKeptLink: (href: string) => boolean;
|
|
64
|
+
/** An address as a link keeps it: `www.example.com` is a web address; a file or anything else is null. */
|
|
65
|
+
export declare const keptAddress: (href: string) => string | null;
|
|
66
|
+
/** An HTML note (an element, or HTML as text) as an Orbit note; undefined when it holds no text. */
|
|
67
|
+
export declare const noteFromHtml: (html: MarkupElement | string, addresses?: NoteAddresses) => ImportedNote | undefined;
|
|
68
|
+
/** A plain text note: markdown when it reads the same as markdown, otherwise plain, as written. */
|
|
69
|
+
export declare const noteFromPlainText: (text: string | undefined) => ImportedNote | undefined;
|
|
70
|
+
/** Blocks as a note: markdown when every word reads back as written, otherwise plain text. */
|
|
71
|
+
export declare const noteFromBlocks: (blocks: NoteBlock[], addresses?: NoteAddresses) => ImportedNote | undefined;
|
|
72
|
+
/** Two or more notes as one: markdown if all are, otherwise plain text, separated by blank lines. */
|
|
73
|
+
export declare const joinNotes: (notes: (ImportedNote | undefined)[]) => ImportedNote | undefined;
|
|
74
|
+
/** A title from HTML: what a reader sees, on one line, and the address of its first link. */
|
|
75
|
+
export declare const titleFromHtml: (html: MarkupElement | string) => {
|
|
76
|
+
text: string;
|
|
77
|
+
link?: string;
|
|
78
|
+
};
|
|
79
|
+
/** The note's blocks, from HTML nodes. */
|
|
80
|
+
export declare const readBlocks: (nodes: MarkupNode[], addresses: NoteAddresses) => NoteBlock[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OPML, the outline format outliners and most mind map apps read and write.
|
|
3
|
+
* Reading keeps each outline's text, its note (`_note`, the convention
|
|
4
|
+
* OmniOutliner started and Workflowy, Dynalist and MindNode follow), its
|
|
5
|
+
* done or todo state (`_status`, `_complete`, `complete`), its link
|
|
6
|
+
* (`type="link"`'s `url`, a feed's `htmlUrl` or `xmlUrl`) and its categories
|
|
7
|
+
* as tags. Writing gives the same back, so a map Orbit writes reads back the
|
|
8
|
+
* same, and other apps read its text, notes, links and checkboxes.
|
|
9
|
+
*/
|
|
10
|
+
import type { OrbitDocument } from '../types.js';
|
|
11
|
+
import { type OrbitImport, type OrbitImportOptions } from './reading.js';
|
|
12
|
+
/** An OPML file, from its bytes or text. */
|
|
13
|
+
export declare const importOPML: (data: Uint8Array | string, options?: OrbitImportOptions) => OrbitImport;
|
|
14
|
+
export interface OrbitOPMLOptions {
|
|
15
|
+
/** The outline's title, in its head. Default: the map's `title`, or its root's text. */
|
|
16
|
+
title?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A map as OPML: the root is the one top outline, each node an outline
|
|
20
|
+
* with its icon and text, its note in `_note`, its link as `type="link"`
|
|
21
|
+
* with a `url`, its status in `_status` (`checked`, `unchecked` and
|
|
22
|
+
* `indeterminate` for done, todo and active; any other word as it is) and
|
|
23
|
+
* `_complete`, and its tags as `category`. Pictures, videos, colors and
|
|
24
|
+
* priorities have no place in OPML: a zip or the map's own file keeps them.
|
|
25
|
+
*/
|
|
26
|
+
export declare const exportOPML: (input: string | OrbitDocument, options?: OrbitOPMLOptions) => string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What reading another app's map gives back, and the first steps every
|
|
3
|
+
* reader shares: a file's bytes as text, and its XML read, with problems
|
|
4
|
+
* reported as `OrbitImportError`s.
|
|
5
|
+
*/
|
|
6
|
+
import type { OrbitDocument } from '../types.js';
|
|
7
|
+
import { type OrbitImportWarning } from './ideas.js';
|
|
8
|
+
import { type MarkupElement } from './markup.js';
|
|
9
|
+
/** The other apps' formats Orbit reads. */
|
|
10
|
+
export type OrbitImportFormat = 'opml' | 'freemind' | 'xmind';
|
|
11
|
+
export interface OrbitImportOptions {
|
|
12
|
+
/** The file's name: its extension tells the format, and a map with no single center is named after it. */
|
|
13
|
+
name?: string;
|
|
14
|
+
/** The file's format, when you know it. Default: from the name, then from what the file holds. */
|
|
15
|
+
format?: OrbitImportFormat;
|
|
16
|
+
/** The name of the center Orbit adds to a map with several top ideas and nothing to name it after. Default "Untitled map". */
|
|
17
|
+
untitled?: string;
|
|
18
|
+
}
|
|
19
|
+
/** One map read from another app's file. */
|
|
20
|
+
export interface OrbitImportedMap {
|
|
21
|
+
document: OrbitDocument;
|
|
22
|
+
/** Pictures from inside the file, by the address the map gives them: `media/sunrise.png`. Save them next to the map. */
|
|
23
|
+
media: Record<string, Uint8Array>;
|
|
24
|
+
/** What the other app had that Orbit keeps another way, or couldn't keep. */
|
|
25
|
+
warnings: OrbitImportWarning[];
|
|
26
|
+
}
|
|
27
|
+
/** What reading another app's file gives. */
|
|
28
|
+
export interface OrbitImport {
|
|
29
|
+
format: OrbitImportFormat;
|
|
30
|
+
/** The file's maps: one, or one for each sheet of an XMind workbook. */
|
|
31
|
+
maps: OrbitImportedMap[];
|
|
32
|
+
}
|
|
33
|
+
/** An XML file's top element, which must be `rootName`; `what` names the file in errors ("an OPML file"). */
|
|
34
|
+
export declare const readXmlFile: (data: Uint8Array | string, rootName: string, what: string) => MarkupElement;
|
|
35
|
+
/** A file's name without its folder or a map's extension: `notes/Trip.opml` is `Trip`. */
|
|
36
|
+
export declare const baseName: (name: string | undefined) => string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XMind workbooks (`.xmind`): zip archives holding `content.json` (XMind
|
|
3
|
+
* 2020 and later, and XMind Zen) or `content.xml` (XMind 8 and earlier),
|
|
4
|
+
* with their pictures. Each sheet becomes a map: its topics with their notes,
|
|
5
|
+
* labels, markers, links, folds, fill colors and pictures, floating topics,
|
|
6
|
+
* summaries and callouts under the topics they belong with, and
|
|
7
|
+
* relationships as links.
|
|
8
|
+
*/
|
|
9
|
+
import type { OrbitImport, OrbitImportOptions } from './reading.js';
|
|
10
|
+
/**
|
|
11
|
+
* An XMind workbook, from its bytes; or its `content.json` or `content.xml`
|
|
12
|
+
* as text, which reads without pictures.
|
|
13
|
+
*/
|
|
14
|
+
export declare const importXMind: (data: Uint8Array | string, options?: OrbitImportOptions) => OrbitImport;
|