@tooee/view 0.11.0 → 0.12.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/dist/components/subviews/markdown-subview.d.ts +3 -1
- package/dist/components/subviews/markdown-subview.d.ts.map +1 -1
- package/dist/components/subviews/markdown-subview.js +18 -4
- package/dist/components/subviews/markdown-subview.js.map +1 -1
- package/dist/components/view-screen.d.ts +3 -1
- package/dist/components/view-screen.d.ts.map +1 -1
- package/dist/components/view-screen.js +2 -2
- package/dist/components/view-screen.js.map +1 -1
- package/dist/folds/fold-model.d.ts +5 -0
- package/dist/folds/fold-model.d.ts.map +1 -1
- package/dist/folds/fold-model.js +9 -0
- package/dist/folds/fold-model.js.map +1 -1
- package/dist/folds/markdown-heading-folds.d.ts +3 -0
- package/dist/folds/markdown-heading-folds.d.ts.map +1 -1
- package/dist/folds/markdown-heading-folds.js +6 -2
- package/dist/folds/markdown-heading-folds.js.map +1 -1
- package/dist/folds/use-folds.d.ts +30 -5
- package/dist/folds/use-folds.d.ts.map +1 -1
- package/dist/folds/use-folds.js +65 -75
- package/dist/folds/use-folds.js.map +1 -1
- package/dist/launch.d.ts +2 -0
- package/dist/launch.d.ts.map +1 -1
- package/dist/launch.js.map +1 -1
- package/dist/outline/markdown-outline.d.ts +24 -0
- package/dist/outline/markdown-outline.d.ts.map +1 -0
- package/dist/outline/markdown-outline.js +25 -0
- package/dist/outline/markdown-outline.js.map +1 -0
- package/dist/outline/outline-panel.d.ts +17 -0
- package/dist/outline/outline-panel.d.ts.map +1 -0
- package/dist/outline/outline-panel.js +106 -0
- package/dist/outline/outline-panel.js.map +1 -0
- package/dist/outline/use-outline.d.ts +53 -0
- package/dist/outline/use-outline.d.ts.map +1 -0
- package/dist/outline/use-outline.js +131 -0
- package/dist/outline/use-outline.js.map +1 -0
- package/dist/standalone-router.d.ts.map +1 -1
- package/dist/standalone-router.js +1 -1
- package/dist/standalone-router.js.map +1 -1
- package/dist/view.d.ts +3 -1
- package/dist/view.d.ts.map +1 -1
- package/dist/view.js +2 -2
- package/dist/view.js.map +1 -1
- package/package.json +14 -13
- package/src/components/subviews/markdown-subview.tsx +21 -2
- package/src/components/view-screen.tsx +4 -0
- package/src/folds/fold-model.ts +14 -0
- package/src/folds/markdown-heading-folds.ts +7 -2
- package/src/folds/use-folds.ts +95 -81
- package/src/launch.tsx +2 -0
- package/src/outline/markdown-outline.ts +45 -0
- package/src/outline/outline-panel.tsx +171 -0
- package/src/outline/use-outline.ts +188 -0
- package/src/standalone-router.tsx +1 -0
- package/src/view.tsx +4 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { FoldActions } from "../folds/use-folds.js";
|
|
3
|
+
import type { OutlineEntry } from "./markdown-outline.js";
|
|
4
|
+
import type { OutlineState } from "./use-outline.js";
|
|
5
|
+
/** One outline line: indent, current-heading marker and text, cut to `width` columns. */
|
|
6
|
+
export declare const outlineLabel: (entry: OutlineEntry, current: boolean, closed: boolean, width: number) => string;
|
|
7
|
+
/**
|
|
8
|
+
* The outline as a side panel. A controlled group with one panel: the panel
|
|
9
|
+
* is active only while the outline has focus, so the document keeps the root
|
|
10
|
+
* surface the rest of the time. Built-in Tab switching is off, so Tab keeps
|
|
11
|
+
* its multi-select meaning in the document.
|
|
12
|
+
*/
|
|
13
|
+
export declare const OutlinePanel: ({ outline, foldActions, }: {
|
|
14
|
+
outline: OutlineState;
|
|
15
|
+
foldActions: FoldActions;
|
|
16
|
+
}) => ReactNode;
|
|
17
|
+
//# sourceMappingURL=outline-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outline-panel.d.ts","sourceRoot":"","sources":["../../src/outline/outline-panel.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AASrD,yFAAyF;AACzF,eAAO,MAAM,YAAY,UAChB,YAAY,WACV,OAAO,UACR,OAAO,SACR,MAAM,KACZ,MAMF,CAAC;AA0GF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,8BAGtB;IACD,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;CAC1B,KAAG,SAoBH,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { useActions } from "@tooee/commands";
|
|
3
|
+
import { Panel, PanelGroup } from "@tooee/panels";
|
|
4
|
+
import { useTheme } from "@tooee/themes";
|
|
5
|
+
import { useEffect, useRef } from "react";
|
|
6
|
+
import { foldActionDefinitions } from "../folds/use-folds.js";
|
|
7
|
+
const OUTLINE_PANEL_ID = "outline";
|
|
8
|
+
const INDENT = " ";
|
|
9
|
+
/** Columns the panel border and the list padding take from the panel width. */
|
|
10
|
+
const OUTLINE_CHROME_WIDTH = 4;
|
|
11
|
+
const entryId = (entry) => `outline-entry-${entry.row}`;
|
|
12
|
+
/** One outline line: indent, current-heading marker and text, cut to `width` columns. */
|
|
13
|
+
export const outlineLabel = function outlineLabel(entry, current, closed, width) {
|
|
14
|
+
const suffix = closed ? " ⋯" : "";
|
|
15
|
+
const label = `${INDENT.repeat(entry.level)}${current ? "▸ " : " "}${entry.text}`;
|
|
16
|
+
const room = Math.max(1, width - suffix.length);
|
|
17
|
+
const cut = label.length > room ? `${label.slice(0, Math.max(0, room - 1))}…` : label;
|
|
18
|
+
return `${cut}${suffix}`;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The panel-owned outline commands. They register on the outline panel's
|
|
22
|
+
* surface, so they only dispatch while the outline has focus, and they shadow
|
|
23
|
+
* the root commands on the same keys. `g o` closes the outline here, because
|
|
24
|
+
* the panel's `g g` holds the `g` chord. The fold keys act on the selected
|
|
25
|
+
* heading's section, so the panel registers the whole `z` set.
|
|
26
|
+
*/
|
|
27
|
+
const OutlineCommands = function OutlineCommands({ outline, foldActions, }) {
|
|
28
|
+
const next = () => {
|
|
29
|
+
outline.move(1);
|
|
30
|
+
};
|
|
31
|
+
const previous = () => {
|
|
32
|
+
outline.move(-1);
|
|
33
|
+
};
|
|
34
|
+
const first = () => {
|
|
35
|
+
outline.select(0);
|
|
36
|
+
};
|
|
37
|
+
const last = () => {
|
|
38
|
+
outline.select(outline.entries.length - 1);
|
|
39
|
+
};
|
|
40
|
+
const jump = () => {
|
|
41
|
+
outline.jump(outline.selectedIndex);
|
|
42
|
+
};
|
|
43
|
+
const commands = [
|
|
44
|
+
["j", "outline.down", "Next heading", next],
|
|
45
|
+
["down", "outline.down-arrow", "Next heading", next],
|
|
46
|
+
["k", "outline.up", "Previous heading", previous],
|
|
47
|
+
["up", "outline.up-arrow", "Previous heading", previous],
|
|
48
|
+
["g g", "outline.first", "First heading", first],
|
|
49
|
+
["shift+g", "outline.last", "Last heading", last],
|
|
50
|
+
["enter", "outline.jump", "Jump to heading", jump],
|
|
51
|
+
["escape", "outline.focus-content", "Return to document", outline.focusContent],
|
|
52
|
+
["g o", "outline.close", "Close outline", outline.close],
|
|
53
|
+
];
|
|
54
|
+
const selectedRow = () => outline.entries[outline.selectedIndex]?.row;
|
|
55
|
+
useActions([
|
|
56
|
+
...commands.map(([hotkey, id, title, run]) => ({
|
|
57
|
+
category: "Outline",
|
|
58
|
+
handler: run,
|
|
59
|
+
hotkey,
|
|
60
|
+
id,
|
|
61
|
+
modes: ["cursor"],
|
|
62
|
+
title,
|
|
63
|
+
})),
|
|
64
|
+
...foldActionDefinitions(foldActions, selectedRow, "outline.fold", "No fold at heading"),
|
|
65
|
+
]);
|
|
66
|
+
return null;
|
|
67
|
+
};
|
|
68
|
+
const OutlineList = function OutlineList({ outline }) {
|
|
69
|
+
const { theme } = useTheme();
|
|
70
|
+
const scrollRef = useRef(null);
|
|
71
|
+
const textWidth = Math.max(1, outline.width - OUTLINE_CHROME_WIDTH);
|
|
72
|
+
const selected = outline.entries[outline.selectedIndex];
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (selected !== undefined) {
|
|
75
|
+
scrollRef.current?.scrollChildIntoView(entryId(selected));
|
|
76
|
+
}
|
|
77
|
+
}, [selected]);
|
|
78
|
+
if (outline.entries.length === 0) {
|
|
79
|
+
return _jsx("text", { content: "No headings", fg: theme.textMuted, paddingLeft: 1 });
|
|
80
|
+
}
|
|
81
|
+
return (_jsx("scrollbox", { ref: scrollRef, style: { flexGrow: 1 }, focused: false, verticalScrollbarOptions: { visible: false }, children: outline.entries.map((entry, index) => {
|
|
82
|
+
const current = index === outline.currentIndex;
|
|
83
|
+
const highlighted = outline.focused && index === outline.selectedIndex;
|
|
84
|
+
return (_jsx("box", { id: entryId(entry), paddingLeft: 1, paddingRight: 1, backgroundColor: highlighted ? theme.cursorLine : undefined, onMouseDown: (event) => {
|
|
85
|
+
event.stopPropagation();
|
|
86
|
+
outline.jump(index);
|
|
87
|
+
}, children: _jsx("text", { content: outlineLabel(entry, current, outline.closedRows.has(entry.row), textWidth), fg: current ? theme.accent : theme.text }) }, entry.row));
|
|
88
|
+
}) }));
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* The outline as a side panel. A controlled group with one panel: the panel
|
|
92
|
+
* is active only while the outline has focus, so the document keeps the root
|
|
93
|
+
* surface the rest of the time. Built-in Tab switching is off, so Tab keeps
|
|
94
|
+
* its multi-select meaning in the document.
|
|
95
|
+
*/
|
|
96
|
+
export const OutlinePanel = function OutlinePanel({ outline, foldActions, }) {
|
|
97
|
+
if (!outline.visible) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
// The only panel asks for activation on a mouse-down inside it.
|
|
101
|
+
const handleActivePanelChange = () => {
|
|
102
|
+
outline.focus();
|
|
103
|
+
};
|
|
104
|
+
return (_jsx(PanelGroup, { activePanelId: outline.focused ? OUTLINE_PANEL_ID : null, onActivePanelChange: handleActivePanelChange, switchKeys: null, children: _jsxs(Panel, { id: OUTLINE_PANEL_ID, title: "Outline", style: { flexShrink: 0, width: outline.width }, children: [_jsx(OutlineCommands, { outline: outline, foldActions: foldActions }), _jsx(OutlineList, { outline: outline })] }) }));
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=outline-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outline-panel.js","sourceRoot":"","sources":["../../src/outline/outline-panel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { FlatBlock } from "@tooee/renderers";
|
|
2
|
+
import type { DocumentController, NavigationState } from "@tooee/shell";
|
|
3
|
+
import type { FoldState } from "../folds/use-folds.js";
|
|
4
|
+
import type { OutlineEntry } from "./markdown-outline.js";
|
|
5
|
+
/** Below this terminal width the outline is not shown. */
|
|
6
|
+
export declare const OUTLINE_MIN_TERMINAL_WIDTH = 60;
|
|
7
|
+
/**
|
|
8
|
+
* Lines of the document kept above a heading after a jump. The heading lands
|
|
9
|
+
* near the top of the view, with a little of the text before it for context.
|
|
10
|
+
*/
|
|
11
|
+
export declare const OUTLINE_JUMP_MARGIN = 3;
|
|
12
|
+
/** Columns for the outline at a terminal width, or 0 when the terminal is too narrow. */
|
|
13
|
+
export declare const outlineWidth: (terminalWidth: number) => number;
|
|
14
|
+
/** State and actions of a document outline. */
|
|
15
|
+
export interface OutlineState {
|
|
16
|
+
entries: readonly OutlineEntry[];
|
|
17
|
+
/** Entry of the heading that contains the document cursor, or -1. */
|
|
18
|
+
currentIndex: number;
|
|
19
|
+
/** Entry the outline highlights as selected: the current heading unless the outline has focus. */
|
|
20
|
+
selectedIndex: number;
|
|
21
|
+
/** Full-array rows whose own heading fold is closed. */
|
|
22
|
+
closedRows: ReadonlySet<number>;
|
|
23
|
+
/** True when the outline is open and the terminal is wide enough to show it. */
|
|
24
|
+
visible: boolean;
|
|
25
|
+
/** True when the visible outline owns keyboard input. */
|
|
26
|
+
focused: boolean;
|
|
27
|
+
/** Outline width in columns, or 0 when the terminal is too narrow. */
|
|
28
|
+
width: number;
|
|
29
|
+
focus: () => void;
|
|
30
|
+
focusContent: () => void;
|
|
31
|
+
close: () => void;
|
|
32
|
+
move: (delta: number) => void;
|
|
33
|
+
select: (index: number) => void;
|
|
34
|
+
/** Move the document cursor to an entry's heading and give focus back to the content. */
|
|
35
|
+
jump: (index: number) => void;
|
|
36
|
+
}
|
|
37
|
+
interface UseOutlineOptions {
|
|
38
|
+
blocks: readonly FlatBlock[];
|
|
39
|
+
folds: FoldState<FlatBlock>;
|
|
40
|
+
navigation: Pick<NavigationState, "cursor" | "setCursor">;
|
|
41
|
+
/** Scrolls a jumped-to heading near the top of the document view. */
|
|
42
|
+
revealRow: DocumentController<FlatBlock>["revealRow"];
|
|
43
|
+
initialOpen?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Outline state for a Markdown document, and the root `g o` command that
|
|
47
|
+
* opens, focuses and closes it. A jump to a heading inside closed folds opens
|
|
48
|
+
* those folds, then moves the cursor once the new rows are in place. Every
|
|
49
|
+
* jump scrolls the heading to near the top of the view.
|
|
50
|
+
*/
|
|
51
|
+
export declare const useMarkdownOutline: ({ blocks, folds, navigation, revealRow, initialOpen, }: UseOutlineOptions) => OutlineState;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=use-outline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-outline.d.ts","sourceRoot":"","sources":["../../src/outline/use-outline.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAIxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAM1D,0DAA0D;AAC1D,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAC7C;;;GAGG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,yFAAyF;AACzF,eAAO,MAAM,YAAY,kBAAwC,MAAM,KAAG,MAKzE,CAAC;AAEF,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,aAAa,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,gFAAgF;IAChF,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAC;IACjB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,yFAAyF;IACzF,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAED,UAAU,iBAAiB;IACzB,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5B,UAAU,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,WAAW,CAAC,CAAC;IAC1D,qEAAqE;IACrE,SAAS,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,CAAC;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,2DAM5B,iBAAiB,KAAG,YA+GtB,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { useTerminalDimensions } from "@opentui/react";
|
|
2
|
+
import { useCommand } from "@tooee/commands";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { closedFoldsHiding } from "../folds/fold-model.js";
|
|
5
|
+
import { markdownOutline, outlineIndexAt } from "./markdown-outline.js";
|
|
6
|
+
/** Outline width in columns, border included. */
|
|
7
|
+
const OUTLINE_WIDTH = 32;
|
|
8
|
+
/** The outline never takes more than this share of the terminal width. */
|
|
9
|
+
const OUTLINE_MAX_SHARE = 0.4;
|
|
10
|
+
/** Below this terminal width the outline is not shown. */
|
|
11
|
+
export const OUTLINE_MIN_TERMINAL_WIDTH = 60;
|
|
12
|
+
/**
|
|
13
|
+
* Lines of the document kept above a heading after a jump. The heading lands
|
|
14
|
+
* near the top of the view, with a little of the text before it for context.
|
|
15
|
+
*/
|
|
16
|
+
export const OUTLINE_JUMP_MARGIN = 3;
|
|
17
|
+
/** Columns for the outline at a terminal width, or 0 when the terminal is too narrow. */
|
|
18
|
+
export const outlineWidth = function outlineWidth(terminalWidth) {
|
|
19
|
+
if (terminalWidth < OUTLINE_MIN_TERMINAL_WIDTH) {
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
return Math.min(OUTLINE_WIDTH, Math.floor(terminalWidth * OUTLINE_MAX_SHARE));
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Outline state for a Markdown document, and the root `g o` command that
|
|
26
|
+
* opens, focuses and closes it. A jump to a heading inside closed folds opens
|
|
27
|
+
* those folds, then moves the cursor once the new rows are in place. Every
|
|
28
|
+
* jump scrolls the heading to near the top of the view.
|
|
29
|
+
*/
|
|
30
|
+
export const useMarkdownOutline = function useMarkdownOutline({ blocks, folds, navigation, revealRow, initialOpen = false, }) {
|
|
31
|
+
const entries = useMemo(() => markdownOutline(blocks), [blocks]);
|
|
32
|
+
const { width: terminalWidth } = useTerminalDimensions();
|
|
33
|
+
const width = outlineWidth(terminalWidth);
|
|
34
|
+
const [open, setOpen] = useState(initialOpen);
|
|
35
|
+
const [focusRequested, setFocusRequested] = useState(false);
|
|
36
|
+
const [selected, setSelected] = useState(0);
|
|
37
|
+
const { closedKeys, ranges, setClosedKeys, view } = folds;
|
|
38
|
+
const { cursor, setCursor } = navigation;
|
|
39
|
+
const visible = open && width > 0;
|
|
40
|
+
const moveTo = useCallback((index) => {
|
|
41
|
+
setCursor(index);
|
|
42
|
+
revealRow(index, { align: "start", margin: OUTLINE_JUMP_MARGIN });
|
|
43
|
+
}, [setCursor, revealRow]);
|
|
44
|
+
const focused = visible && focusRequested;
|
|
45
|
+
const sourceRow = cursor === null ? undefined : view.visibleToSource[cursor];
|
|
46
|
+
const currentIndex = sourceRow === undefined ? -1 : outlineIndexAt(entries, sourceRow);
|
|
47
|
+
const selectedIndex = focused ? Math.min(selected, entries.length - 1) : currentIndex;
|
|
48
|
+
const closedRows = useMemo(() => new Set(ranges.filter((range) => closedKeys.has(range.key)).map((range) => range.start)), [ranges, closedKeys]);
|
|
49
|
+
// A jump that opens folds waits for the new fold view, then moves the
|
|
50
|
+
// cursor. This effect runs after the controller's own rows effect, so the
|
|
51
|
+
// store already holds the new rows.
|
|
52
|
+
const pendingRowRef = useRef(null);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
const row = pendingRowRef.current;
|
|
55
|
+
const index = row === null ? -1 : (view.sourceToVisible[row] ?? -1);
|
|
56
|
+
if (index !== -1) {
|
|
57
|
+
pendingRowRef.current = null;
|
|
58
|
+
moveTo(index);
|
|
59
|
+
}
|
|
60
|
+
}, [view, moveTo]);
|
|
61
|
+
const focus = () => {
|
|
62
|
+
setSelected(Math.max(currentIndex, 0));
|
|
63
|
+
setFocusRequested(true);
|
|
64
|
+
};
|
|
65
|
+
const focusContent = () => {
|
|
66
|
+
setFocusRequested(false);
|
|
67
|
+
};
|
|
68
|
+
const close = () => {
|
|
69
|
+
setOpen(false);
|
|
70
|
+
setFocusRequested(false);
|
|
71
|
+
};
|
|
72
|
+
const select = (index) => {
|
|
73
|
+
setSelected(Math.max(0, Math.min(index, entries.length - 1)));
|
|
74
|
+
};
|
|
75
|
+
const move = (delta) => {
|
|
76
|
+
select(selectedIndex + delta);
|
|
77
|
+
};
|
|
78
|
+
const jump = (index) => {
|
|
79
|
+
const entry = entries[index];
|
|
80
|
+
setFocusRequested(false);
|
|
81
|
+
if (entry === undefined) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const hiding = closedFoldsHiding(ranges, closedKeys, entry.row);
|
|
85
|
+
if (hiding.length === 0) {
|
|
86
|
+
moveTo(view.sourceToVisible[entry.row] ?? 0);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const next = new Set(closedKeys);
|
|
90
|
+
for (const key of hiding) {
|
|
91
|
+
next.delete(key);
|
|
92
|
+
}
|
|
93
|
+
pendingRowRef.current = entry.row;
|
|
94
|
+
setClosedKeys(next);
|
|
95
|
+
};
|
|
96
|
+
useCommand({
|
|
97
|
+
category: "Outline",
|
|
98
|
+
handler: (ctx) => {
|
|
99
|
+
if (width === 0) {
|
|
100
|
+
ctx.toast?.toast({ level: "info", message: "The outline needs a wider terminal" });
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (open && focused) {
|
|
104
|
+
close();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
setOpen(true);
|
|
108
|
+
focus();
|
|
109
|
+
},
|
|
110
|
+
hotkey: "g o",
|
|
111
|
+
id: "outline.toggle",
|
|
112
|
+
modes: ["cursor"],
|
|
113
|
+
title: "Toggle outline",
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
close,
|
|
117
|
+
closedRows,
|
|
118
|
+
currentIndex,
|
|
119
|
+
entries,
|
|
120
|
+
focus,
|
|
121
|
+
focusContent,
|
|
122
|
+
focused,
|
|
123
|
+
jump,
|
|
124
|
+
move,
|
|
125
|
+
select,
|
|
126
|
+
selectedIndex,
|
|
127
|
+
visible,
|
|
128
|
+
width,
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=use-outline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-outline.js","sourceRoot":"","sources":["../../src/outline/use-outline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGxE,iDAAiD;AACjD,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,0EAA0E;AAC1E,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,0DAA0D;AAC1D,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAC7C;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,yFAAyF;AACzF,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,YAAY,CAAC,aAAqB;IACrE,IAAI,aAAa,GAAG,0BAA0B,EAAE,CAAC;QAC/C,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,iBAAiB,CAAC,CAAC,CAAC;AAChF,CAAC,CAAC;AAmCF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,kBAAkB,CAAC,EAC5D,MAAM,EACN,KAAK,EACL,UAAU,EACV,SAAS,EACT,WAAW,GAAG,KAAK,GACD;IAClB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,qBAAqB,EAAE,CAAC;IACzD,MAAM,KAAK,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;IAC1C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE5C,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAC1D,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,UAAU,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,KAAa,EAAE,EAAE;QAChB,SAAS,CAAC,KAAK,CAAC,CAAC;QACjB,SAAS,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACpE,CAAC,EACD,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAC;IACF,MAAM,OAAO,GAAG,OAAO,IAAI,cAAc,CAAC;IAC1C,MAAM,SAAS,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7E,MAAM,YAAY,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACvF,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;IACtF,MAAM,UAAU,GAAG,OAAO,CACxB,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAC9F,CAAC,MAAM,EAAE,UAAU,CAAC,CACrB,CAAC;IAEF,sEAAsE;IACtE,0EAA0E;IAC1E,oCAAoC;IACpC,MAAM,aAAa,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAClD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC;QAClC,MAAM,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpE,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,aAAa,CAAC,OAAO,GAAG,IAAI,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAEnB,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;QACvC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,OAAO,CAAC,KAAK,CAAC,CAAC;QACf,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE;QAC/B,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE;QAC7B,MAAM,CAAC,aAAa,GAAG,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QACjC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,aAAa,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC;QAClC,aAAa,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC,CAAC;IAEF,UAAU,CAAC;QACT,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACf,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBAChB,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC,CAAC;gBACnF,OAAO;YACT,CAAC;YACD,IAAI,IAAI,IAAI,OAAO,EAAE,CAAC;gBACpB,KAAK,EAAE,CAAC;gBACR,OAAO;YACT,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC;YACd,KAAK,EAAE,CAAC;QACV,CAAC;QACD,MAAM,EAAE,KAAK;QACb,EAAE,EAAE,gBAAgB;QACpB,KAAK,EAAE,CAAC,QAAQ,CAAC;QACjB,KAAK,EAAE,gBAAgB;KACxB,CAAC,CAAC;IAEH,OAAO;QACL,KAAK;QACL,UAAU;QACV,YAAY;QACZ,OAAO;QACP,KAAK;QACL,YAAY;QACZ,OAAO;QACP,IAAI;QACJ,IAAI;QACJ,MAAM;QACN,aAAa;QACb,OAAO;QACP,KAAK;KACN,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standalone-router.d.ts","sourceRoot":"","sources":["../src/standalone-router.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAS,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAM5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAwBrD,UAAU,gBAAgB;IACxB,aAAa,EAAE,eAAe,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,eAAO,MAAM,sBAAsB,YACxB,iBAAiB,KACzB,
|
|
1
|
+
{"version":3,"file":"standalone-router.d.ts","sourceRoot":"","sources":["../src/standalone-router.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAS,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAM5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAwBrD,UAAU,gBAAgB;IACxB,aAAa,EAAE,eAAe,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,eAAO,MAAM,sBAAsB,YACxB,iBAAiB,KACzB,gBA0EF,CAAC"}
|
|
@@ -69,7 +69,7 @@ export const createStandaloneRouter = function createStandaloneRouter(options) {
|
|
|
69
69
|
title: "Follow Markdown link",
|
|
70
70
|
when: (context) => context.view?.format === "markdown",
|
|
71
71
|
});
|
|
72
|
-
return (_jsx(View, { actions: options.actions, codeBlockRenderers: options.codeBlockRenderers, contentProvider: provider, onMarkdownLinkActivate: activate, renderers: options.renderers }, `${stack.length}:${documentPath ?? ""}`));
|
|
72
|
+
return (_jsx(View, { actions: options.actions, codeBlockRenderers: options.codeBlockRenderers, contentProvider: provider, onMarkdownLinkActivate: activate, outline: options.outline, renderers: options.renderers }, `${stack.length}:${documentPath ?? ""}`));
|
|
73
73
|
};
|
|
74
74
|
const documentRoute = createRoute({
|
|
75
75
|
component: DocumentScreen,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standalone-router.js","sourceRoot":"","sources":["../src/standalone-router.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"standalone-router.js","sourceRoot":"","sources":["../src/standalone-router.tsx"],"names":[],"mappings":"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"}
|
package/dist/view.d.ts
CHANGED
|
@@ -13,7 +13,9 @@ interface ViewProps {
|
|
|
13
13
|
codeBlockRenderers?: Record<string, CodeBlockRenderer>;
|
|
14
14
|
/** Handles primary-button activation of inline Markdown links. */
|
|
15
15
|
onMarkdownLinkActivate?: MarkdownLinkActivateHandler;
|
|
16
|
+
/** Open the heading outline beside Markdown content at start. Other formats ignore it. */
|
|
17
|
+
outline?: boolean;
|
|
16
18
|
}
|
|
17
|
-
export declare const View: ({ contentProvider, actions, renderers, codeBlockRenderers, onMarkdownLinkActivate, }: ViewProps) => ReactNode;
|
|
19
|
+
export declare const View: ({ contentProvider, actions, renderers, codeBlockRenderers, onMarkdownLinkActivate, outline, }: ViewProps) => ReactNode;
|
|
18
20
|
export {};
|
|
19
21
|
//# sourceMappingURL=view.d.ts.map
|
package/dist/view.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAavC,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAEhG,UAAU,SAAS;IACjB,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC5C;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACvD,kEAAkE;IAClE,sBAAsB,CAAC,EAAE,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAavC,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAEhG,UAAU,SAAS;IACjB,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC5C;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACvD,kEAAkE;IAClE,sBAAsB,CAAC,EAAE,2BAA2B,CAAC;IACrD,0FAA0F;IAC1F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,IAAI,kGAOd,SAAS,KAAG,SAqFd,CAAC"}
|
package/dist/view.js
CHANGED
|
@@ -6,7 +6,7 @@ import { MarkdownSubview, CodeSubview, TableSubview, ImageSubview, DiffSubview,
|
|
|
6
6
|
import { ViewState } from "./components/view-state.js";
|
|
7
7
|
import { useContentLoader } from "./hooks/use-content-loader.js";
|
|
8
8
|
import { isCustomContent } from "./types.js";
|
|
9
|
-
export const View = function View({ contentProvider, actions, renderers, codeBlockRenderers, onMarkdownLinkActivate, }) {
|
|
9
|
+
export const View = function View({ contentProvider, actions, renderers, codeBlockRenderers, onMarkdownLinkActivate, outline, }) {
|
|
10
10
|
const { theme } = useTheme();
|
|
11
11
|
const { content, streaming, error, providerMarks, reload } = useContentLoader(contentProvider);
|
|
12
12
|
const [userMarks, setUserMarks] = useState([]);
|
|
@@ -50,7 +50,7 @@ export const View = function View({ contentProvider, actions, renderers, codeBlo
|
|
|
50
50
|
}
|
|
51
51
|
switch (content.format) {
|
|
52
52
|
case "markdown": {
|
|
53
|
-
return (_jsx(MarkdownSubview, { content: content, codeBlockRenderers: mergedCodeBlockRenderers, onLinkActivate: onMarkdownLinkActivate, ...shared }));
|
|
53
|
+
return (_jsx(MarkdownSubview, { content: content, codeBlockRenderers: mergedCodeBlockRenderers, onLinkActivate: onMarkdownLinkActivate, outline: outline, ...shared }));
|
|
54
54
|
}
|
|
55
55
|
case "code":
|
|
56
56
|
case "text": {
|
package/dist/view.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGvD,OAAO,EACL,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,aAAa,GACd,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tooee/view",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Terminal content viewer for markdown, code, text, images, and tables",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -40,18 +40,19 @@
|
|
|
40
40
|
"typecheck": "tsc --noEmit"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@tooee/choose": "0.
|
|
44
|
-
"@tooee/commands": "0.
|
|
45
|
-
"@tooee/config": "0.
|
|
46
|
-
"@tooee/diff": "0.
|
|
47
|
-
"@tooee/layout": "0.
|
|
48
|
-
"@tooee/marks": "0.
|
|
49
|
-
"@tooee/overlays": "0.
|
|
50
|
-
"@tooee/
|
|
51
|
-
"@tooee/
|
|
52
|
-
"@tooee/
|
|
53
|
-
"@tooee/
|
|
54
|
-
"@tooee/
|
|
43
|
+
"@tooee/choose": "0.12.0",
|
|
44
|
+
"@tooee/commands": "0.12.0",
|
|
45
|
+
"@tooee/config": "0.12.0",
|
|
46
|
+
"@tooee/diff": "0.12.0",
|
|
47
|
+
"@tooee/layout": "0.12.0",
|
|
48
|
+
"@tooee/marks": "0.12.0",
|
|
49
|
+
"@tooee/overlays": "0.12.0",
|
|
50
|
+
"@tooee/panels": "0.12.0",
|
|
51
|
+
"@tooee/renderers": "0.12.0",
|
|
52
|
+
"@tooee/router": "0.12.0",
|
|
53
|
+
"@tooee/search": "0.12.0",
|
|
54
|
+
"@tooee/shell": "0.12.0",
|
|
55
|
+
"@tooee/themes": "0.12.0",
|
|
55
56
|
"@xstate/store": "^4.2.3",
|
|
56
57
|
"@xstate/store-react": "^2",
|
|
57
58
|
"marked": "^18.0.14"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TextBufferRenderable } from "@opentui/core";
|
|
2
|
+
import { useTerminalDimensions } from "@opentui/react";
|
|
2
3
|
import { useBuildCommandContext, useCommand } from "@tooee/commands";
|
|
3
4
|
import { MarkdownView, flattenMarkdown, getFlatBlockText } from "@tooee/renderers";
|
|
4
5
|
import type { CodeBlockRenderer, FlatBlock } from "@tooee/renderers";
|
|
@@ -7,8 +8,10 @@ import { useMemo, useRef } from "react";
|
|
|
7
8
|
import type { ReactNode } from "react";
|
|
8
9
|
|
|
9
10
|
import { markdownHeadingFoldRanges } from "../../folds/markdown-heading-folds.js";
|
|
10
|
-
import { useFoldCommands, useFoldState } from "../../folds/use-folds.js";
|
|
11
|
+
import { useFoldActions, useFoldCommands, useFoldState } from "../../folds/use-folds.js";
|
|
11
12
|
import { useContentDocument } from "../../hooks/use-content-document.js";
|
|
13
|
+
import { OutlinePanel } from "../../outline/outline-panel.js";
|
|
14
|
+
import { useMarkdownOutline } from "../../outline/use-outline.js";
|
|
12
15
|
import type { MarkdownContent, MarkdownLinkActivateHandler } from "../../types.js";
|
|
13
16
|
import { ViewScreen } from "../view-screen.js";
|
|
14
17
|
import type { SubviewProps } from "./types.js";
|
|
@@ -17,6 +20,8 @@ interface MarkdownSubviewProps extends SubviewProps {
|
|
|
17
20
|
content: MarkdownContent;
|
|
18
21
|
codeBlockRenderers?: Record<string, CodeBlockRenderer>;
|
|
19
22
|
onLinkActivate?: MarkdownLinkActivateHandler;
|
|
23
|
+
/** Open the heading outline beside the document at start. */
|
|
24
|
+
outline?: boolean;
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
/** Columns moved per h/l press when scrolling a wide block horizontally. */
|
|
@@ -44,6 +49,7 @@ export const MarkdownSubview = function MarkdownSubview({
|
|
|
44
49
|
content,
|
|
45
50
|
codeBlockRenderers,
|
|
46
51
|
onLinkActivate,
|
|
52
|
+
outline: initialOutline = false,
|
|
47
53
|
decorations,
|
|
48
54
|
actions,
|
|
49
55
|
...screen
|
|
@@ -70,7 +76,18 @@ export const MarkdownSubview = function MarkdownSubview({
|
|
|
70
76
|
],
|
|
71
77
|
}
|
|
72
78
|
);
|
|
73
|
-
|
|
79
|
+
const foldActions = useFoldActions(folds, document.navigation);
|
|
80
|
+
useFoldCommands(folds, foldActions, document.navigation);
|
|
81
|
+
// Declared after the controller, so its jump effect runs after the
|
|
82
|
+
// controller has taken the new rows.
|
|
83
|
+
const outline = useMarkdownOutline({
|
|
84
|
+
blocks,
|
|
85
|
+
folds,
|
|
86
|
+
initialOpen: initialOutline,
|
|
87
|
+
navigation: document.navigation,
|
|
88
|
+
revealRow: document.revealRow,
|
|
89
|
+
});
|
|
90
|
+
const { width: terminalWidth } = useTerminalDimensions();
|
|
74
91
|
const buildCommandContext = useBuildCommandContext();
|
|
75
92
|
const handleLinkActivate = onLinkActivate
|
|
76
93
|
? (href: string) => onLinkActivate(href, buildCommandContext())
|
|
@@ -114,6 +131,7 @@ export const MarkdownSubview = function MarkdownSubview({
|
|
|
114
131
|
controller={document}
|
|
115
132
|
actions={actions}
|
|
116
133
|
statusItems={statusItems}
|
|
134
|
+
aside={<OutlinePanel outline={outline} foldActions={foldActions} />}
|
|
117
135
|
{...screen}
|
|
118
136
|
>
|
|
119
137
|
<MarkdownView
|
|
@@ -127,6 +145,7 @@ export const MarkdownSubview = function MarkdownSubview({
|
|
|
127
145
|
codeBlockRenderers={codeBlockRenderers}
|
|
128
146
|
onLinkActivate={handleLinkActivate}
|
|
129
147
|
imageBasePath={content.imageBasePath}
|
|
148
|
+
width={outline.visible ? terminalWidth - outline.width : undefined}
|
|
130
149
|
/>
|
|
131
150
|
</ViewScreen>
|
|
132
151
|
);
|
|
@@ -21,6 +21,8 @@ export interface ViewScreenProps<T> {
|
|
|
21
21
|
setMarkSet: (set: MarkSet) => void;
|
|
22
22
|
clearMarkNamespace: (namespace: string) => void;
|
|
23
23
|
clearAllUserMarks: () => void;
|
|
24
|
+
/** Optional side region beside the content, such as the Markdown outline. */
|
|
25
|
+
aside?: ReactNode;
|
|
24
26
|
children: ReactNode;
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -41,6 +43,7 @@ export const ViewScreen = function ViewScreen<T>({
|
|
|
41
43
|
setMarkSet,
|
|
42
44
|
clearMarkNamespace,
|
|
43
45
|
clearAllUserMarks,
|
|
46
|
+
aside,
|
|
44
47
|
children,
|
|
45
48
|
}: ViewScreenProps<T>): ReactNode {
|
|
46
49
|
useProvideViewCommandContext({
|
|
@@ -71,6 +74,7 @@ export const ViewScreen = function ViewScreen<T>({
|
|
|
71
74
|
statusItems={items}
|
|
72
75
|
actions={actions}
|
|
73
76
|
context={{ kind: content.format, reload, title: content.title }}
|
|
77
|
+
aside={aside}
|
|
74
78
|
>
|
|
75
79
|
{children}
|
|
76
80
|
</DocumentScreen>
|
package/src/folds/fold-model.ts
CHANGED
|
@@ -70,6 +70,20 @@ export const foldsAt = function foldsAt(
|
|
|
70
70
|
.toSorted((left, right) => right.start - left.start || left.end - right.end);
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Keys of the closed ranges that hide `row`: closed ranges whose body
|
|
75
|
+
* (`start + 1 ..= end`) contains it. Opening them all makes `row` visible.
|
|
76
|
+
*/
|
|
77
|
+
export const closedFoldsHiding = function closedFoldsHiding(
|
|
78
|
+
ranges: readonly FoldRange[],
|
|
79
|
+
closedKeys: ReadonlySet<Key>,
|
|
80
|
+
row: number
|
|
81
|
+
): Key[] {
|
|
82
|
+
return ranges
|
|
83
|
+
.filter((range) => closedKeys.has(range.key) && range.start < row && row <= range.end)
|
|
84
|
+
.map((range) => range.key);
|
|
85
|
+
};
|
|
86
|
+
|
|
73
87
|
/**
|
|
74
88
|
* The full-array row the cursor should rest on once `view` applies: `row`
|
|
75
89
|
* itself when it stays visible, otherwise the nearest visible row before it,
|
|
@@ -3,13 +3,18 @@ import type { Tokens } from "marked";
|
|
|
3
3
|
|
|
4
4
|
import type { FoldRange } from "./fold-model.js";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/** The Marked heading token of a flattened block, or `null` when the block is not a heading. */
|
|
7
|
+
export const headingToken = function headingToken(block: FlatBlock): Tokens.Heading | null {
|
|
7
8
|
if (block.token.type !== "heading") {
|
|
8
9
|
return null;
|
|
9
10
|
}
|
|
10
11
|
// SAFETY: Marked creates a Heading token for the checked "heading" discriminator.
|
|
11
12
|
// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- Marked's Generic fallback prevents discriminator narrowing
|
|
12
|
-
return
|
|
13
|
+
return block.token as Tokens.Heading;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const headingDepth = function headingDepth(block: FlatBlock): number | null {
|
|
17
|
+
return headingToken(block)?.depth ?? null;
|
|
13
18
|
};
|
|
14
19
|
|
|
15
20
|
/**
|