@mudlet/mudlet-web 0.3.1 → 0.4.1
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 +8 -0
- package/dist-lib/assets/qt-resources/index.d.ts +16 -0
- package/dist-lib/branding.d.ts +1 -1
- package/dist-lib/hooks/useMudSession.d.ts +1 -1
- package/dist-lib/hooks/useOutput.d.ts +3 -1
- package/dist-lib/import/defaultPackages.d.ts +35 -2
- package/dist-lib/import/defaults/generic_mapper/generic_mapper.mpackage +0 -0
- package/dist-lib/import/defaults/gui-drop/gui-drop.mpackage +0 -0
- package/dist-lib/import/defaults/{run-lua-code.mpackage → mudlet-base-ui/mudlet-base-ui.mpackage} +0 -0
- package/dist-lib/import/defaults/run-lua-code/run-lua-code.mpackage +0 -0
- package/dist-lib/import/packageExport.d.ts +71 -0
- package/dist-lib/import/packageInstaller.d.ts +4 -1
- package/dist-lib/index.js +45929 -40688
- package/dist-lib/logging/SessionLogger.d.ts +66 -1
- package/dist-lib/map/MapStore.d.ts +32 -4
- package/dist-lib/map/mapImageExport.d.ts +1 -1
- package/dist-lib/map/mapZoom.d.ts +71 -0
- package/dist-lib/mud/ItemIdSequence.d.ts +23 -0
- package/dist-lib/mud/MudSession.d.ts +113 -11
- package/dist-lib/mud/PatternEngine.d.ts +6 -1
- package/dist-lib/mud/commandSplit.d.ts +16 -0
- package/dist-lib/mud/connection/LineAssembler.d.ts +56 -0
- package/dist-lib/mud/connection/MudClient.d.ts +120 -16
- package/dist-lib/mud/connection/TelnetNegotiator.d.ts +39 -0
- package/dist-lib/mud/connection/telnetByteTags.d.ts +35 -0
- package/dist-lib/mud/events.d.ts +19 -4
- package/dist-lib/mud/games/bundledGames.d.ts +29 -0
- package/dist-lib/mud/games/gameIcons.d.ts +5 -0
- package/dist-lib/mud/keybindings/KeyEngine.d.ts +9 -2
- package/dist-lib/mud/keybindings/browserReservedKeys.d.ts +5 -1
- package/dist-lib/mud/keybindings/keyEventTarget.d.ts +17 -0
- package/dist-lib/mud/keybindings/qtKeys.d.ts +2 -0
- package/dist-lib/mud/protocol/charLoginFlow.d.ts +68 -0
- package/dist-lib/mud/protocol/charset.d.ts +27 -5
- package/dist-lib/mud/protocol/constants.d.ts +1 -0
- package/dist-lib/mud/protocol/gmcp.d.ts +19 -3
- package/dist-lib/mud/protocol/index.d.ts +1 -1
- package/dist-lib/mud/protocol/mxp.d.ts +28 -5
- package/dist-lib/mud/replay/ReplayPlayer.d.ts +17 -0
- package/dist-lib/mud/text/Console.d.ts +64 -0
- package/dist-lib/mud/text/FormatState.d.ts +66 -3
- package/dist-lib/mud/text/hyperlinkVisibility.d.ts +35 -0
- package/dist-lib/mud/text/osc8Docs.d.ts +23 -0
- package/dist-lib/mud/text/serverWrap.d.ts +191 -0
- package/dist-lib/mud/timers/TimerEngine.d.ts +43 -12
- package/dist-lib/mud/triggers/TriggerEngine.d.ts +112 -3
- package/dist-lib/scripting/EngineHost.d.ts +56 -3
- package/dist-lib/scripting/IScriptingRuntime.d.ts +16 -0
- package/dist-lib/scripting/MxpFrameManager.d.ts +118 -0
- package/dist-lib/scripting/ScriptingAPI.d.ts +323 -54
- package/dist-lib/scripting/ScriptingEngine.d.ts +180 -23
- package/dist-lib/scripting/http/HttpService.d.ts +51 -1
- package/dist-lib/scripting/lua/LuaRuntime.d.ts +151 -2
- package/dist-lib/scripting/lua/bindings/map.d.ts +0 -12
- package/dist-lib/scripting/lua/utf8Patterns.d.ts +59 -0
- package/dist-lib/storage/index.d.ts +1 -1
- package/dist-lib/storage/persistentStorage.d.ts +10 -0
- package/dist-lib/storage/schema.d.ts +116 -0
- package/dist-lib/styles.css +1 -1
- package/dist-lib/ui/BundledGameGrid.d.ts +21 -0
- package/dist-lib/ui/CommandBar.d.ts +7 -1
- package/dist-lib/ui/ConnectionGrid.d.ts +4 -1
- package/dist-lib/ui/FilePickerModal.d.ts +3 -3
- package/dist-lib/ui/HelpModal.d.ts +11 -0
- package/dist-lib/ui/LogBrowserModal.d.ts +4 -1
- package/dist-lib/ui/PlayerMarkerPreview.d.ts +20 -0
- package/dist-lib/ui/Toolbar.d.ts +2 -1
- package/dist-lib/ui/VfsPickerModal.d.ts +26 -0
- package/dist-lib/ui/components/FileSourceButton.d.ts +47 -0
- package/dist-lib/ui/components/index.d.ts +1 -0
- package/dist-lib/ui/helpTopics.d.ts +19 -0
- package/dist-lib/ui/labels/LabelManager.d.ts +7 -0
- package/dist-lib/ui/layout/ScriptWindow.d.ts +11 -2
- package/dist-lib/ui/markdown.d.ts +10 -1
- package/dist-lib/ui/output/OutputArea.d.ts +11 -1
- package/dist-lib/ui/output/OutputContextMenu.d.ts +3 -1
- package/dist-lib/ui/output/OutputRenderer.d.ts +7 -1
- package/dist-lib/ui/output/OutputSearchBar.d.ts +25 -0
- package/dist-lib/ui/output/StickyOutputPanel.d.ts +5 -1
- package/dist-lib/ui/output/outputSearch.d.ts +130 -0
- package/dist-lib/ui/search/matcher.d.ts +15 -0
- package/dist-lib/ui/search/useDebounced.d.ts +3 -0
- package/dist-lib/ui/tts/TtsManager.d.ts +3 -0
- package/dist-lib/ui/useCommandHistory.d.ts +4 -2
- package/dist-lib/ui/useOpenProfiles.d.ts +26 -0
- package/dist-lib/ui/video/VideoManager.d.ts +17 -0
- package/dist-lib/ui/windows/WindowManager.d.ts +132 -2
- package/dist-lib/ui/windows/panels/MapPanel.d.ts +4 -1
- package/dist-lib/ui/windows/panels/PackageExportModal.d.ts +18 -0
- package/dist-lib/ui/windows/panels/TextPanel.d.ts +3 -1
- package/dist-lib/ui/windows/types.d.ts +35 -0
- package/dist-lib/utils/describeThrown.d.ts +22 -0
- package/dist-lib/utils/fontLoader.d.ts +5 -0
- package/dist-lib/vite.js +22 -0
- package/package.json +10 -6
- package/dist-lib/scripting/lua/mudlet-lua/generic-mapper/generic_mapper.mpackage +0 -0
- package/dist-lib/ui/windows/panels/VfsModulePickerModal.d.ts +0 -8
|
@@ -29,9 +29,16 @@ export interface MxpFrameCommand {
|
|
|
29
29
|
name: string;
|
|
30
30
|
/** Upper-cased attribute keys → raw string values. Flag attributes
|
|
31
31
|
* (`INTERNAL`/`EXTERNAL`/`FLOATING`) are present with value `"true"`.
|
|
32
|
-
* `ACTION` is `open` (default) / `close` / `
|
|
33
|
-
* `LEFT`/`TOP`/`WIDTH`/`HEIGHT`. */
|
|
32
|
+
* `ACTION` is `open` (default) / `close` / `focus`; geometry lives in
|
|
33
|
+
* `ALIGN`/`LEFT`/`TOP`/`WIDTH`/`HEIGHT`. */
|
|
34
34
|
attrs: Record<string, string>;
|
|
35
|
+
/** Name of the `<DEST>` frame that was open when this tag was seen, if any.
|
|
36
|
+
* A `<FRAME>` nested inside a `<DEST>` is laid out *inside* that frame
|
|
37
|
+
* rather than against the main window — Mudlet's `mCurrentDestination`
|
|
38
|
+
* check in TMxpFrameManager::layoutInternalFrame. The parser batches frames
|
|
39
|
+
* and redirects into separate arrays, so the association has to travel with
|
|
40
|
+
* the command. */
|
|
41
|
+
dest?: string;
|
|
35
42
|
}
|
|
36
43
|
/** Text the parser redirected into a named frame via `<DEST>…</DEST>`. */
|
|
37
44
|
export interface MxpRedirect {
|
|
@@ -41,6 +48,9 @@ export interface MxpRedirect {
|
|
|
41
48
|
segments: BufferSegment[];
|
|
42
49
|
/** Plain text of the redirected run. */
|
|
43
50
|
plain: string;
|
|
51
|
+
/** Clickable regions inside this run, offset into `plain`. Separate from
|
|
52
|
+
* `MxpLineResult.links` because the two index different strings. */
|
|
53
|
+
links: MxpLink[];
|
|
44
54
|
/** `EOL` attr (or the network line ended mid-DEST): the write is a complete
|
|
45
55
|
* line. */
|
|
46
56
|
eol: boolean;
|
|
@@ -84,6 +94,8 @@ export declare class MxpParser {
|
|
|
84
94
|
private mxpColorStack;
|
|
85
95
|
/** Partial tag/entity held from the end of the previous line. */
|
|
86
96
|
private pendingTag;
|
|
97
|
+
/** Whether the line being parsed came off the socket — see {@link parseLine}. */
|
|
98
|
+
private fromServer;
|
|
87
99
|
/** Active `<DEST>` target frame (persists across lines until `</DEST>`), or
|
|
88
100
|
* null when output flows to the main window. While set, appended text and
|
|
89
101
|
* flushed runs route to `destOut`/`destPlain` instead of `out`/`plain`. */
|
|
@@ -103,9 +115,10 @@ export declare class MxpParser {
|
|
|
103
115
|
private redirects;
|
|
104
116
|
/** `<SOUND>`/`<MUSIC>` commands accumulated this line. */
|
|
105
117
|
private sounds;
|
|
106
|
-
/** Redirected-text scratch — the current `<DEST>` run's segments/plain. */
|
|
118
|
+
/** Redirected-text scratch — the current `<DEST>` run's segments/plain/links. */
|
|
107
119
|
private destOut;
|
|
108
120
|
private destPlain;
|
|
121
|
+
private destLinks;
|
|
109
122
|
constructor(opts: {
|
|
110
123
|
send: (raw: string) => void;
|
|
111
124
|
presets?: HyperlinkPresetRegistry;
|
|
@@ -113,6 +126,9 @@ export declare class MxpParser {
|
|
|
113
126
|
* tag's attributes resolved the way Mudlet resolves them (see
|
|
114
127
|
* {@link elementEventAttrs}). Backs the Lua `mxp` table. */
|
|
115
128
|
onElementEvent?: (name: string, attrs: Record<string, string>) => void;
|
|
129
|
+
/** Columns the main window wraps at — how wide `<HR>` draws its rule.
|
|
130
|
+
* Mudlet's `TMxpClient::getWrapWidth`, whose own fallback is 80. */
|
|
131
|
+
wrapWidth?: () => number;
|
|
116
132
|
});
|
|
117
133
|
/**
|
|
118
134
|
* Lock the parser to secure line mode (or release the lock). Mudlet does
|
|
@@ -127,8 +143,15 @@ export declare class MxpParser {
|
|
|
127
143
|
reset(): void;
|
|
128
144
|
/** Parse one raw line (post telnet-strip, post UTF-8 decode), which may carry
|
|
129
145
|
* ANSI SGR, MXP tags, `ESC[#z` modes, and entities. `baseSnapshot` is the
|
|
130
|
-
* carried pen from the previous line.
|
|
131
|
-
|
|
146
|
+
* carried pen from the previous line.
|
|
147
|
+
*
|
|
148
|
+
* `fromServer` false means the line was synthesised locally (feedTriggers).
|
|
149
|
+
* Such a line's `ESC[#z` is consumed but does not switch mode, matching
|
|
150
|
+
* Mudlet's `isFromServer` gate on `mMxpProcessor.setMode` — otherwise a
|
|
151
|
+
* script feeding a captured game line would leave the parser in whatever
|
|
152
|
+
* mode that capture ended on, and the next real tag would be discarded as
|
|
153
|
+
* unsafe. */
|
|
154
|
+
parseLine(rawLine: string, baseSnapshot?: FormatStateSnapshot, fromServer?: boolean): MxpLineResult;
|
|
132
155
|
private effectiveMode;
|
|
133
156
|
private resetTransientMode;
|
|
134
157
|
private appendText;
|
|
@@ -27,5 +27,22 @@ export declare class ReplayPlayer {
|
|
|
27
27
|
/** Stop playback and drop any pending chunk. Idempotent; onDone is not
|
|
28
28
|
* fired for an aborted replay. */
|
|
29
29
|
abort(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Deliver every chunk that has come due, without waiting for its setTimeout.
|
|
32
|
+
*
|
|
33
|
+
* The counterpart of TimerEngine.pumpDue, and there for the same caller: a
|
|
34
|
+
* script blocked in waitForEvent/pumpEvents is not running the event loop,
|
|
35
|
+
* so the pending timeout below can never land and a replay started from such
|
|
36
|
+
* a script would sit at chunk zero forever. Mudlet has no equivalent problem
|
|
37
|
+
* — its nested QEventLoop keeps driving the replay timer along with
|
|
38
|
+
* everything else — so this is what standing in for that loop costs.
|
|
39
|
+
*
|
|
40
|
+
* Returns the number of chunks delivered.
|
|
41
|
+
*/
|
|
42
|
+
pumpDue(now?: number): number;
|
|
43
|
+
/** When the pending chunk is due, in epoch ms; null when none is scheduled. */
|
|
44
|
+
private dueAt;
|
|
45
|
+
/** Feed the chunk at `index` and schedule the one after it. */
|
|
46
|
+
private deliverPending;
|
|
30
47
|
private scheduleNext;
|
|
31
48
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { FormatState } from './FormatState';
|
|
2
2
|
import { AnsiAwareBuffer } from './FormatState';
|
|
3
3
|
import type { FormatStateSnapshot } from './FormatState';
|
|
4
|
+
/** Longest run of characters one echo or insert may add to a line. Mudlet's
|
|
5
|
+
* `TBuffer::MAX_CHARACTERS_PER_ECHO`. */
|
|
6
|
+
export declare const MAX_CHARACTERS_PER_ECHO = 1000000;
|
|
4
7
|
/**
|
|
5
8
|
* Self-contained text output entity — equivalent of Mudlet's TConsole.
|
|
6
9
|
* Owns format state, line history, and cursor position.
|
|
@@ -36,6 +39,13 @@ export declare class Console {
|
|
|
36
39
|
get batchDeleteSize(): number;
|
|
37
40
|
setBatchDeleteSize(n: number): void;
|
|
38
41
|
echo(text: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Move every newline-terminated line out of the in-flight `partial` and
|
|
44
|
+
* into history, leaving whatever follows the last newline as the new
|
|
45
|
+
* partial. Shared by `echo` and by `insertText`, which can put a newline
|
|
46
|
+
* into the line being built just as an echo can.
|
|
47
|
+
*/
|
|
48
|
+
private promotePartialLines;
|
|
39
49
|
/**
|
|
40
50
|
* Append a pre-built complete line buffer to history. Used by the network
|
|
41
51
|
* trigger pipeline: the line has already been parsed and is being added as
|
|
@@ -55,6 +65,14 @@ export declare class Console {
|
|
|
55
65
|
* `selectCurrentLine` sees the pasted line.
|
|
56
66
|
*/
|
|
57
67
|
appendBuffer(buffer: AnsiAwareBuffer): void;
|
|
68
|
+
/**
|
|
69
|
+
* The one way a completed line enters history. An OSC 8 link set to reveal
|
|
70
|
+
* itself after a delay is written into the buffer as spaces here and gets
|
|
71
|
+
* its text back when the delay is up — Mudlet does the same, so that a
|
|
72
|
+
* script reading the line back sees what the player can see rather than the
|
|
73
|
+
* secret behind it.
|
|
74
|
+
*/
|
|
75
|
+
private store;
|
|
58
76
|
private evict;
|
|
59
77
|
/** Drain newly completed lines to hand to the renderer. */
|
|
60
78
|
takeLines(): AnsiAwareBuffer[];
|
|
@@ -82,12 +100,32 @@ export declare class Console {
|
|
|
82
100
|
clearPartial(): void;
|
|
83
101
|
private get cursor();
|
|
84
102
|
private get followingEnd();
|
|
103
|
+
/**
|
|
104
|
+
* Whether the line under the cursor is the in-flight `partial` — an echo
|
|
105
|
+
* that hasn't seen its newline yet — rather than a finished history line.
|
|
106
|
+
*
|
|
107
|
+
* The distinction matters to every cursor-line operation, not just the
|
|
108
|
+
* readers: Mudlet's cursor sits on the line being built, so `insertText`,
|
|
109
|
+
* `replace` and friends have to reach it there. Reading it but not writing
|
|
110
|
+
* it made `prefix()`/`suffix()` on an unfinished line silent no-ops.
|
|
111
|
+
*/
|
|
112
|
+
private get onPartialLine();
|
|
85
113
|
getLine(): string;
|
|
86
114
|
getBuffer(): AnsiAwareBuffer | null;
|
|
115
|
+
/** The buffer the cursor is on: the partial when it is following the end,
|
|
116
|
+
* otherwise the history line it was parked on. */
|
|
117
|
+
private currentBuffer;
|
|
87
118
|
/** Per-line prompt flag on the current cursor line. Mirrors Mudlet's TBuffer
|
|
88
119
|
* behaviour: `isPrompt()` follows the cursor, so moveCursor + isPrompt can
|
|
89
120
|
* inspect any historical line's prompt status, not just the most recent. */
|
|
90
121
|
cursorOnPrompt(): boolean;
|
|
122
|
+
/** Whether the cursor was left one slot beyond the last line — the state
|
|
123
|
+
* deleteLine() leaves behind when it removes the line the cursor was on and
|
|
124
|
+
* there is nothing after it to shift up. Distinct from the ordinary
|
|
125
|
+
* "following the end" cursor (index -1), which every read treats as the last
|
|
126
|
+
* line. Reads cursorIdx rather than `cursor`, which clamps and so can never
|
|
127
|
+
* report either state. */
|
|
128
|
+
cursorPastEnd(): boolean;
|
|
91
129
|
deleteLine(): void;
|
|
92
130
|
/**
|
|
93
131
|
* Insert `text` at the cursor (Mudlet `insertText`). Embedded `\n` split the
|
|
@@ -124,6 +162,13 @@ export declare class Console {
|
|
|
124
162
|
* `keepHorizontal` move never reports past the end of a shorter line.
|
|
125
163
|
*/
|
|
126
164
|
getCursorColumn(): number;
|
|
165
|
+
/**
|
|
166
|
+
* The column as it was set, unclamped. Mudlet keeps `mUserCursor.x()` raw
|
|
167
|
+
* and only the operations that write through it decide what a column past
|
|
168
|
+
* the end of the line means — `paste` pads out to it, which the clamped
|
|
169
|
+
* reading above cannot express.
|
|
170
|
+
*/
|
|
171
|
+
getCursorColumnRaw(): number;
|
|
127
172
|
setCursorColumn(col: number): boolean;
|
|
128
173
|
/** Mark cursor as positioned at the end of existing rendered content, so the
|
|
129
174
|
* next leading `\n` is treated as cursor advance rather than a blank line.
|
|
@@ -179,5 +224,24 @@ export declare class Console {
|
|
|
179
224
|
* every continuation, matching setWindowWrapIndent /
|
|
180
225
|
* setWindowWrapHangingIndent.
|
|
181
226
|
*/
|
|
227
|
+
/**
|
|
228
|
+
* The wrap this console applies to a line as it is stored — the console's
|
|
229
|
+
* own `setWindowWrap` width, so a line longer than it becomes several
|
|
230
|
+
* buffer lines rather than one long one that only *looks* wrapped.
|
|
231
|
+
*
|
|
232
|
+
* Off (width 0) unless a script sets one, which is the state nearly every
|
|
233
|
+
* console is in: the renderer wraps to the panel's real pixel width, and
|
|
234
|
+
* splitting on a column nobody chose would only fight it. Mudlet always
|
|
235
|
+
* splits because its buffer IS its layout.
|
|
236
|
+
*/
|
|
237
|
+
setWrapWidth(width: number, indent?: number, hangingIndent?: number): void;
|
|
238
|
+
private wrapWidth;
|
|
239
|
+
private wrapIndent;
|
|
240
|
+
private wrapHangingIndent;
|
|
241
|
+
/**
|
|
242
|
+
* Split one completed line to the console's wrap width, newest-last. With no
|
|
243
|
+
* width set — the usual case — this is the line itself, untouched.
|
|
244
|
+
*/
|
|
245
|
+
private toStoredLines;
|
|
182
246
|
wrapLine(lineNumber: number, wrapAt?: number, indent?: number, hangingIndent?: number): boolean;
|
|
183
247
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type OscPaletteOp } from "./ansiEscapes";
|
|
2
|
-
import { HyperlinkPresetRegistry, type HyperlinkConfig } from "./hyperlinkConfig";
|
|
2
|
+
import { HyperlinkPresetRegistry, type HyperlinkConfig, type UnderlineStyle } from "./hyperlinkConfig";
|
|
3
3
|
/** Apply OSC 4/104 palette operations to the global colour tables. Palette
|
|
4
4
|
* changes affect text parsed *after* this point — which is exactly document
|
|
5
5
|
* order, since lines are fed to the parser in the order the server sent them. */
|
|
@@ -53,6 +53,9 @@ export interface HexColor {
|
|
|
53
53
|
color: string;
|
|
54
54
|
}
|
|
55
55
|
export type FormatColor = IndexedColor | RgbColor | HexColor;
|
|
56
|
+
/** One SGR parameter: a number, or its sub-parameters when it carried any
|
|
57
|
+
* (`4:3` → `[4, 3]`). See {@link parseSgrCodes}. */
|
|
58
|
+
export type SgrParam = number | number[];
|
|
56
59
|
export type DimEasing = 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out';
|
|
57
60
|
export interface DimEffect {
|
|
58
61
|
startOpacity: number;
|
|
@@ -66,6 +69,9 @@ export interface FormatStateSnapshot {
|
|
|
66
69
|
bold?: boolean;
|
|
67
70
|
italic?: boolean;
|
|
68
71
|
underline?: boolean;
|
|
72
|
+
/** Which underline SGR asked for (`4:1`..`4:5`). Only meaningful while
|
|
73
|
+
* `underline` is set; absent means the plain solid one. */
|
|
74
|
+
underlineStyle?: UnderlineStyle;
|
|
69
75
|
inverse?: boolean;
|
|
70
76
|
strikethrough?: boolean;
|
|
71
77
|
overline?: boolean;
|
|
@@ -84,11 +90,11 @@ declare function cloneState(state?: FormatStateSnapshot): FormatStateSnapshot |
|
|
|
84
90
|
declare function statesEqual(a?: FormatStateSnapshot, b?: FormatStateSnapshot): boolean;
|
|
85
91
|
export declare class FormatState {
|
|
86
92
|
static DEFAULT: {};
|
|
87
|
-
foreground?: FormatColor;
|
|
88
93
|
background?: FormatColor;
|
|
89
94
|
bold?: boolean;
|
|
90
95
|
italic?: boolean;
|
|
91
96
|
underline?: boolean;
|
|
97
|
+
underlineStyle?: UnderlineStyle;
|
|
92
98
|
inverse?: boolean;
|
|
93
99
|
strikethrough?: boolean;
|
|
94
100
|
overline?: boolean;
|
|
@@ -96,13 +102,66 @@ export declare class FormatState {
|
|
|
96
102
|
rapidBlink?: boolean;
|
|
97
103
|
dim?: DimEffect;
|
|
98
104
|
hyperlink?: FormatHyperlink;
|
|
105
|
+
private fgNormal?;
|
|
106
|
+
private fgLight?;
|
|
107
|
+
/** True while the foreground is the profile's own — as it starts, and as
|
|
108
|
+
* SGR 0 and SGR 39 leave it. Bold never brightens a default foreground. */
|
|
109
|
+
private fgIsDefault;
|
|
110
|
+
private _foreground?;
|
|
111
|
+
/** The foreground in force, both variants already resolved. */
|
|
112
|
+
get foreground(): FormatColor | undefined;
|
|
113
|
+
/** Writing the foreground from outside the SGR decoder — `setFgColor`, MXP
|
|
114
|
+
* colour attributes, link styling — names one colour and knows nothing of
|
|
115
|
+
* the bold pair, so it becomes both variants. Without that a later bold
|
|
116
|
+
* would re-resolve to whatever the escape stream had left behind and undo
|
|
117
|
+
* the write. */
|
|
118
|
+
set foreground(color: FormatColor | undefined);
|
|
99
119
|
constructor(initial?: FormatStateSnapshot);
|
|
100
120
|
private applySnapshot;
|
|
101
121
|
reset(): void;
|
|
102
122
|
toSnapshot(): FormatStateSnapshot;
|
|
103
|
-
applySgr(params:
|
|
123
|
+
applySgr(params: SgrParam[]): void;
|
|
124
|
+
/**
|
|
125
|
+
* Apply one SGR parameter that carried sub-parameters (`4:3`, `38:5:196`).
|
|
126
|
+
*
|
|
127
|
+
* Only the underline styles need reading apart from the flat form: an
|
|
128
|
+
* extended colour means the same written either way, so it is handed back to
|
|
129
|
+
* the ordinary path with its sub-parameters flattened.
|
|
130
|
+
*/
|
|
131
|
+
private applySgrGroup;
|
|
132
|
+
/**
|
|
133
|
+
* `38:…` / `48:…` — an extended colour written with sub-parameters.
|
|
134
|
+
*
|
|
135
|
+
* The colon form carries one element the semicolon form does not: a colour
|
|
136
|
+
* space identifier sits between the `2` and the red component, almost always
|
|
137
|
+
* empty (`38:2::255:0:0`). So the components are the 4th, 5th and 6th
|
|
138
|
+
* sub-parameters here where they are the 3rd, 4th and 5th parameters there.
|
|
139
|
+
* Missing components are zero, as in Mudlet's decodeSGR38.
|
|
140
|
+
*/
|
|
141
|
+
private applyExtendedColorGroup;
|
|
142
|
+
/** Record a foreground and the colour bold should show instead of it, then
|
|
143
|
+
* resolve which of the two is in force. Pass the same colour twice when it
|
|
144
|
+
* has no brighter twin. */
|
|
145
|
+
private setForeground;
|
|
146
|
+
/** Pick the variant the current bold state calls for. Mudlet writes each
|
|
147
|
+
* cell as `(!mIsDefaultColor && mBold) ? light : normal` — a default
|
|
148
|
+
* foreground stays default however bold the text is. */
|
|
149
|
+
private resolveForeground;
|
|
104
150
|
setHyperlink(link?: FormatHyperlink): void;
|
|
105
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Split an SGR sequence into its parameters. `;` separates parameters and `:`
|
|
154
|
+
* their sub-parameters (ECMA-48 / ITU T.416), so a parameter that carries
|
|
155
|
+
* sub-parameters comes back as an array and a plain one as a number.
|
|
156
|
+
*
|
|
157
|
+
* The distinction matters for exactly one reason, but it matters a lot: `4:3` is
|
|
158
|
+
* a *curly underline*, one parameter with a sub-parameter, while `4;3` is an
|
|
159
|
+
* underline followed by italics. Flattening both — which mudix did, to make
|
|
160
|
+
* `38:5:1` work alongside `38;5;1` — turned every styled underline into an
|
|
161
|
+
* accidental italic. Extended colours still read either form, since applySgr
|
|
162
|
+
* looks ahead across parameters for the `38;5;n` spelling.
|
|
163
|
+
*/
|
|
164
|
+
export declare function parseSgrCodes(sequence: string): SgrParam[];
|
|
106
165
|
/**
|
|
107
166
|
* A run of text with its visual attributes resolved to concrete CSS colour
|
|
108
167
|
* strings — the shape a canvas/image renderer wants. `color`/`background` are
|
|
@@ -165,6 +224,10 @@ export declare class AnsiAwareBuffer {
|
|
|
165
224
|
remove(range: [number, number]): this;
|
|
166
225
|
/** @internal */
|
|
167
226
|
getSegments(): BufferSegment[];
|
|
227
|
+
/** Whether any segment carries an OSC 8 link with `visibility` settings.
|
|
228
|
+
* A cheap pre-check (no cloning, no grouping) for the concealment pass,
|
|
229
|
+
* which every stored line goes through. */
|
|
230
|
+
hasVisibilityLink(): boolean;
|
|
168
231
|
toHyperlinkSegments(): {
|
|
169
232
|
text: string;
|
|
170
233
|
hyperlink?: FormatHyperlink;
|
|
@@ -15,8 +15,15 @@
|
|
|
15
15
|
* (owned by the session) conceals them when the matching session event fires.
|
|
16
16
|
* The first occurrence of each trigger is skipped: it's the response to the very
|
|
17
17
|
* command the click sent, not a fresh event.
|
|
18
|
+
*
|
|
19
|
+
* **The buffer half.** Hiding an element is not enough for a *delayed reveal*:
|
|
20
|
+
* Mudlet writes such a link into its buffer as spaces and puts the text back
|
|
21
|
+
* when the delay is up, so a script reading the line back (`getLines`) sees what
|
|
22
|
+
* the player sees rather than the secret. {@link concealDelayedReveals} does the
|
|
23
|
+
* same to a stored line here — see the section at the foot of this file.
|
|
18
24
|
*/
|
|
19
25
|
import type { VisibilitySettings } from "./hyperlinkConfig";
|
|
26
|
+
import type { AnsiAwareBuffer } from "./FormatState";
|
|
20
27
|
/** Wire one link element's visibility behaviour. Call *after* the element's base
|
|
21
28
|
* style has been applied (it may set `visibility: hidden`, which a later
|
|
22
29
|
* `cssText` assignment would wipe). */
|
|
@@ -35,3 +42,31 @@ export declare class HyperlinkVisibilityController {
|
|
|
35
42
|
onOutput(): void;
|
|
36
43
|
private fire;
|
|
37
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Whether a link with these settings is written concealed and revealed later.
|
|
47
|
+
*
|
|
48
|
+
* Only the timed reveals are, unlike Mudlet, which also conceals a reveal armed
|
|
49
|
+
* on an expire trigger. mudix drives expire triggers off the rendered element
|
|
50
|
+
* (see {@link HyperlinkVisibilityController}), and that path only ever conceals
|
|
51
|
+
* — a link the buffer blanked with nothing to un-blank it would lose its text
|
|
52
|
+
* for good, which is worse than showing it early.
|
|
53
|
+
*/
|
|
54
|
+
export declare function startsConcealed(vis: VisibilitySettings): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Blank out every delayed-reveal link on a freshly stored line and schedule the
|
|
57
|
+
* text to come back. Called once per line as it enters a console's history.
|
|
58
|
+
*/
|
|
59
|
+
export declare function concealDelayedReveals(line: AnsiAwareBuffer): void;
|
|
60
|
+
/**
|
|
61
|
+
* Put back the text of every concealed link whose delay has elapsed, and arm a
|
|
62
|
+
* timer for the earliest one still waiting. Returns true when a line changed.
|
|
63
|
+
*
|
|
64
|
+
* Also the hook the busted harness drives: a spec runs as one synchronous call
|
|
65
|
+
* on top of the event loop, so no `setTimeout` of ours can fire until it
|
|
66
|
+
* returns, and `pumpEvents` calls in here instead.
|
|
67
|
+
*/
|
|
68
|
+
export declare function pumpDelayedReveals(now?: number): boolean;
|
|
69
|
+
/** Drop everything still waiting — a profile teardown, or a test resetting
|
|
70
|
+
* between cases. The lines themselves are left as they are; they are going
|
|
71
|
+
* away with the console. */
|
|
72
|
+
export declare function resetDelayedReveals(): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mudlet's `!osc8-docs` easter egg — the worked OSC 8 examples banner
|
|
3
|
+
* (`TBuffer::injectOSC8DocumentationExamples`).
|
|
4
|
+
*
|
|
5
|
+
* A line printed through the echo family that holds the phrase is swallowed and
|
|
6
|
+
* this banner goes into the MAIN console instead, whichever window the echo was
|
|
7
|
+
* addressed to. It is the one page of OSC 8 documentation that can be read
|
|
8
|
+
* without leaving the client, so every escape in it is load-bearing: the text is
|
|
9
|
+
* a verbatim port of Mudlet's, kept one source line per array entry so the two
|
|
10
|
+
* can be diffed after a re-sync.
|
|
11
|
+
*
|
|
12
|
+
* Not every printing path reaches it — what the game sends and what a trigger
|
|
13
|
+
* echoes onto the matched line print the phrase as ordinary text, exactly as in
|
|
14
|
+
* Mudlet, where those go through `commitLine()` rather than `appendLine()`.
|
|
15
|
+
*/
|
|
16
|
+
/** The phrase itself, split so that this file does not set off its own check
|
|
17
|
+
* when something echoes a line of it. */
|
|
18
|
+
export declare const OSC8_DOCS_PHRASE: string;
|
|
19
|
+
/** Once a second at most — an echo and the server response that repeats it must
|
|
20
|
+
* not print the banner twice. Mudlet's `mLastOSC8DocsInjectionTime` window. */
|
|
21
|
+
export declare const OSC8_DOCS_DEBOUNCE_MS = 1000;
|
|
22
|
+
/** The banner as one blob, ready to hand to `Console.echo`. */
|
|
23
|
+
export declare function osc8DocumentationExamples(): string;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Undoing the game's own line wrapping — Mudlet's `undoServerWrap` /
|
|
3
|
+
* `undoServerWrapWidth` (`TBuffer.cpp`).
|
|
4
|
+
*
|
|
5
|
+
* Many MUDs word-wrap their output server-side at a fixed column. That makes
|
|
6
|
+
* triggers awkward to write (a phrase can be split across two "lines" that were
|
|
7
|
+
* never separate) and pins the display to the game's width instead of the
|
|
8
|
+
* window's. Turning the option on holds back any line that ends where the game's
|
|
9
|
+
* wrapper would have broken it and glues the continuation on, so triggers and
|
|
10
|
+
* rendering see one whole logical line.
|
|
11
|
+
*
|
|
12
|
+
* The heuristics live here as pure functions over *visible* text so they can be
|
|
13
|
+
* tested directly, and so the pipeline glue in `ScriptingEngine` stays readable.
|
|
14
|
+
*
|
|
15
|
+
* **Visible text, not raw.** Mudlet judges `mMudLine`, which is plain characters
|
|
16
|
+
* with the styling held alongside in a `TChar` buffer. mudix keeps styling
|
|
17
|
+
* inline as ANSI escapes, so every predicate here takes text that has been put
|
|
18
|
+
* through {@link visibleText} first — otherwise a colour-heavy line would be
|
|
19
|
+
* measured as far longer than the player sees, and its escape punctuation would
|
|
20
|
+
* drag the letter ratio below the prose threshold.
|
|
21
|
+
*/
|
|
22
|
+
/** How far below the configured column a line may end and still count as
|
|
23
|
+
* ending *at* it. The game breaks at the last space that fits, so a wrapped
|
|
24
|
+
* segment falls up to a word short. Mudlet's `csmServerWrapSlack`. */
|
|
25
|
+
export declare const SERVER_WRAP_SLACK = 15;
|
|
26
|
+
/** Refuse to keep joining past this visible length — a runaway join would
|
|
27
|
+
* otherwise swallow a whole screen. Mudlet's `csmServerWrapMaxJoinedLength`. */
|
|
28
|
+
export declare const SERVER_WRAP_MAX_JOINED_LENGTH = 10000;
|
|
29
|
+
/** How much clear room the continuation's first word must have had on the line
|
|
30
|
+
* above before that line counts as one the game ended itself. Mudlet's
|
|
31
|
+
* `csmServerWrapFitTolerance` — only *clear* room disproves a wrap, because a
|
|
32
|
+
* segment inside the join band already sits up to {@link SERVER_WRAP_SLACK}
|
|
33
|
+
* short of the column. */
|
|
34
|
+
export declare const SERVER_WRAP_FIT_TOLERANCE = 8;
|
|
35
|
+
/** Longest run of digits a bare list label may carry (`1.`, `12)`, `999.`).
|
|
36
|
+
* Mudlet's `csmMaxListNumberDigits`. Bracketed labels are exempt — `[1366]` is
|
|
37
|
+
* a label however long it runs, where a bare `1364.` is as likely a price. */
|
|
38
|
+
export declare const MAX_LIST_NUMBER_DIGITS = 3;
|
|
39
|
+
/** How much of a held game line's opening is kept for comparing a continuation
|
|
40
|
+
* against. Mudlet's `csmServerWrapSegmentStartChars` — only the first
|
|
41
|
+
* {@link SERVER_WRAP_REPEATED_WORDS} shared words and the spaces after them
|
|
42
|
+
* have to fall inside it, and that leaves room for it even where a long name
|
|
43
|
+
* is one of them. */
|
|
44
|
+
export declare const SERVER_WRAP_SEGMENT_START_CHARS = 48;
|
|
45
|
+
/** How many opening words a continuation has to share with the held segment
|
|
46
|
+
* before it is a message the game re-prefixed rather than a wrap. Mudlet's
|
|
47
|
+
* `csmServerWrapRepeatedWords` — one is far too common in prose to prove
|
|
48
|
+
* anything. */
|
|
49
|
+
export declare const SERVER_WRAP_REPEATED_WORDS = 2;
|
|
50
|
+
/** How long a held-back line waits for its continuation before being committed
|
|
51
|
+
* on its own. Mudlet's `csmServerWrapFlushDelayMs`. */
|
|
52
|
+
export declare const SERVER_WRAP_FLUSH_DELAY_MS = 300;
|
|
53
|
+
/** Bounds on `undoServerWrapWidth`, matching Mudlet's `setConfig` validation
|
|
54
|
+
* (and the `qBound` its profile-XML import applies). */
|
|
55
|
+
export declare const SERVER_WRAP_WIDTH_MIN = 20;
|
|
56
|
+
export declare const SERVER_WRAP_WIDTH_MAX = 500;
|
|
57
|
+
/** Mudlet's `Host::mUndoServerWrapWidth` default. */
|
|
58
|
+
export declare const SERVER_WRAP_WIDTH_DEFAULT = 80;
|
|
59
|
+
/** Strip ANSI/OSC escapes so a line can be measured and classified the way the
|
|
60
|
+
* player sees it. Uses the shared scanner, so it skips CSI, OSC, DCS-family and
|
|
61
|
+
* short escapes alike rather than guessing at a regex. */
|
|
62
|
+
export declare function visibleText(line: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Mudlet `TBuffer::endsAtServerWrapColumn`. True when a segment's visible length
|
|
65
|
+
* lands in the `[width - slack, width]` band — i.e. where the game's own word
|
|
66
|
+
* wrap would have broken it.
|
|
67
|
+
*/
|
|
68
|
+
export declare function endsAtServerWrapColumn(visibleLength: number, width: number): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Mudlet `TBuffer::looksLikeWrappedProse`. Word-wrapped prose breaks *between
|
|
71
|
+
* words*, so a wrapped segment ends in a word (or a sentence mark that happened
|
|
72
|
+
* to land on the wrap column) and is mostly letters. ASCII art, dividers and
|
|
73
|
+
* table borders also run right up to the screen width but end in — and are full
|
|
74
|
+
* of — symbols; gluing those back together would mangle them.
|
|
75
|
+
*
|
|
76
|
+
* `visible` must already be ANSI-stripped.
|
|
77
|
+
*/
|
|
78
|
+
export declare function looksLikeWrappedProse(visible: string): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Mudlet `TBuffer::segmentEndsSettledSentence`. Where a game swallows the space
|
|
81
|
+
* it breaks at, a segment that finishes a sentence right on the wrap column
|
|
82
|
+
* looks exactly like one the game ended there itself — and games end lines on
|
|
83
|
+
* sentences all the time: a room description, the exits line below it, the
|
|
84
|
+
* object line below that. Joining those runs separate lines into one and breaks
|
|
85
|
+
* triggers anchored to their starts.
|
|
86
|
+
*
|
|
87
|
+
* A kept break space is the one piece of evidence that settles it, so only a
|
|
88
|
+
* sentence with nothing at all after it is refused — the check reads the very
|
|
89
|
+
* last character rather than the last non-space one. What that costs is a
|
|
90
|
+
* genuine wrap landing exactly after a sentence staying split, which reads as a
|
|
91
|
+
* break at a sentence boundary; far cheaper than the joins it prevents.
|
|
92
|
+
*
|
|
93
|
+
* This belongs at the *hold* decision only: continuations legitimately end
|
|
94
|
+
* sentences, so {@link looksLikeWrappedProse} must keep accepting them.
|
|
95
|
+
*
|
|
96
|
+
* `visible` must already be ANSI-stripped.
|
|
97
|
+
*/
|
|
98
|
+
export declare function segmentEndsSettledSentence(visible: string): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Mudlet `TBuffer::continuationRepeatsSegmentOpening`. Games that wrap a tell,
|
|
101
|
+
* say or channel message themselves put the whole prefix back on every physical
|
|
102
|
+
* line of it (`Anne teilt Dir mit: …`). Those lines break mid-sentence at the
|
|
103
|
+
* wrap column and leave no room for the next word, so every other check reads
|
|
104
|
+
* them as one wrapped paragraph and the join buries the prefix in the middle of
|
|
105
|
+
* it. The repeated opening is what gives them away — two words of it, because
|
|
106
|
+
* prose starts line after line with the same article or pronoun and one proves
|
|
107
|
+
* nothing.
|
|
108
|
+
*
|
|
109
|
+
* `segmentStart` is the held *game line's* opening (see
|
|
110
|
+
* {@link SERVER_WRAP_SEGMENT_START_CHARS}), not the joined paragraph's: a
|
|
111
|
+
* continuation is compared against the line it actually follows.
|
|
112
|
+
*
|
|
113
|
+
* Both strings must already be ANSI-stripped.
|
|
114
|
+
*/
|
|
115
|
+
export declare function continuationRepeatsSegmentOpening(segmentStart: string, visibleNext: string): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Mudlet `TBuffer::startsWithListMarker`. A list entry reads exactly like
|
|
118
|
+
* wrapped prose — a sentence that can end right at the wrap column — so only its
|
|
119
|
+
* marker tells a list apart from a paragraph.
|
|
120
|
+
*
|
|
121
|
+
* Every form accepted here has to be one the game's own word wrap could not
|
|
122
|
+
* produce at the start of a continuation. The ambiguous ones are deliberately
|
|
123
|
+
* left out: a spaced dash opens a continuation whenever the wrap lands on it,
|
|
124
|
+
* and a parenthesised number is as often an aside as a label, so it is capped at
|
|
125
|
+
* {@link MAX_LIST_NUMBER_DIGITS} like a bare one. Only `[...]` is exempt from
|
|
126
|
+
* the cap — nothing writes `[2500]` mid-sentence.
|
|
127
|
+
*
|
|
128
|
+
* `visible` must already be ANSI-stripped.
|
|
129
|
+
*/
|
|
130
|
+
export declare function startsWithListMarker(visible: string): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Mudlet `TBuffer::pendingLineHadRoomForNextWord`. Word wrap breaks a line for
|
|
133
|
+
* one reason only: the next word did not fit. So a continuation whose first word
|
|
134
|
+
* would have gone on the game line above it is not a continuation at all — the
|
|
135
|
+
* game ended that line itself. Without this, two sentences that each stop short
|
|
136
|
+
* of the wrap column read exactly like one wrapped paragraph.
|
|
137
|
+
*
|
|
138
|
+
* `heldSegmentLength` is the length of the last *game line* joined into the held
|
|
139
|
+
* text, not of the held text itself: once a paragraph has been joined the held
|
|
140
|
+
* text is longer than the wrap column, and the line the next word would have
|
|
141
|
+
* landed on is the one the game last sent.
|
|
142
|
+
*
|
|
143
|
+
* Both strings must already be ANSI-stripped.
|
|
144
|
+
*/
|
|
145
|
+
export declare function pendingLineHadRoomForNextWord(visiblePending: string, heldSegmentLength: number, visibleNext: string, width: number): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Mudlet's guard before joining: a genuine continuation of wrapped prose starts
|
|
148
|
+
* with a word — or with the single space some games move the break to instead of
|
|
149
|
+
* swallowing it. *Deeper* indentation, a segment that isn't prose at all, a list
|
|
150
|
+
* entry, or a first word that would have fitted on the line above all mean the
|
|
151
|
+
* held line was complete after all and must be committed on its own first.
|
|
152
|
+
*
|
|
153
|
+
* `visibleNext` must already be ANSI-stripped.
|
|
154
|
+
*/
|
|
155
|
+
export declare function shouldCommitPendingBeforeJoin(visibleNext: string, nextIsProse: boolean, fit?: {
|
|
156
|
+
visiblePending: string;
|
|
157
|
+
heldSegmentLength: number;
|
|
158
|
+
segmentStart: string;
|
|
159
|
+
width: number;
|
|
160
|
+
}): boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Mudlet `TBuffer::joinPendingServerWrapOntoCurrent`. Concatenates the held line
|
|
163
|
+
* and its continuation, restoring the space the game's wrapper swallowed when
|
|
164
|
+
* neither side already carries one.
|
|
165
|
+
*
|
|
166
|
+
* Operates on the **raw** lines (escapes and all): mudix's styling is inline, so
|
|
167
|
+
* a plain concatenation carries each half's colour across untouched — the
|
|
168
|
+
* `TChar`-buffer splice Mudlet needs has no equivalent here. The space-insertion
|
|
169
|
+
* test looks at the visible text so a trailing colour reset can't hide the space
|
|
170
|
+
* that is already there.
|
|
171
|
+
*/
|
|
172
|
+
export declare function joinWrappedLines(pending: string, next: string): string;
|
|
173
|
+
/** Lines shorter than this carry no signal about a wrap column. */
|
|
174
|
+
export declare const WRAP_DETECT_MIN_LENGTH = 40;
|
|
175
|
+
/** Evaluate the collected sample only once every this many recorded lines. */
|
|
176
|
+
export declare const WRAP_DETECT_SAMPLE_INTERVAL = 100;
|
|
177
|
+
/** How many lines must sit at the ceiling before it's believable. */
|
|
178
|
+
export declare const WRAP_DETECT_THRESHOLD = 40;
|
|
179
|
+
/** A plausible wrap column has to fall in this range. */
|
|
180
|
+
export declare const WRAP_DETECT_CEILING_MIN = 60;
|
|
181
|
+
export declare const WRAP_DETECT_CEILING_MAX = 160;
|
|
182
|
+
/**
|
|
183
|
+
* Given the tally of observed line lengths, report the game's apparent wrap
|
|
184
|
+
* column, or null when the evidence doesn't support one.
|
|
185
|
+
*
|
|
186
|
+
* The ceiling is the longest length seen more than incidentally (≥3 times); it
|
|
187
|
+
* has to be a plausible screen width, carry enough lines just below it, and have
|
|
188
|
+
* almost nothing beyond it — a game that regularly emits longer lines is not
|
|
189
|
+
* wrapping at that column.
|
|
190
|
+
*/
|
|
191
|
+
export declare function detectWrapCeiling(counts: ReadonlyMap<number, number>): number | null;
|