@matter/general 0.13.1-alpha.0-20250508-047aa0277 → 0.13.1-alpha.0-20250509-28e1567e1
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/cjs/transaction/Transaction.d.ts +19 -19
- package/dist/cjs/util/FormattedText.d.ts +24 -1
- package/dist/cjs/util/FormattedText.d.ts.map +1 -1
- package/dist/cjs/util/FormattedText.js +118 -113
- package/dist/cjs/util/FormattedText.js.map +2 -2
- package/dist/esm/transaction/Transaction.d.ts +19 -19
- package/dist/esm/util/FormattedText.d.ts +24 -1
- package/dist/esm/util/FormattedText.d.ts.map +1 -1
- package/dist/esm/util/FormattedText.js +118 -113
- package/dist/esm/util/FormattedText.js.map +2 -2
- package/package.json +2 -2
- package/src/util/FormattedText.ts +137 -124
|
@@ -144,16 +144,16 @@ export declare const Transaction: {
|
|
|
144
144
|
*/
|
|
145
145
|
act<T>(via: string, actor: (transaction: Transaction) => MaybePromise<T>): MaybePromise<T>;
|
|
146
146
|
ReadOnly: {
|
|
147
|
-
"__#
|
|
148
|
-
"__#
|
|
149
|
-
"__#
|
|
150
|
-
"__#
|
|
151
|
-
"__#
|
|
152
|
-
"__#
|
|
153
|
-
"__#
|
|
154
|
-
"__#
|
|
155
|
-
"__#
|
|
156
|
-
"__#
|
|
147
|
+
"__#15442@#participants": Set<Participant>;
|
|
148
|
+
"__#15442@#roles": Map<{}, Participant>;
|
|
149
|
+
"__#15442@#resources": Set<Resource>;
|
|
150
|
+
"__#15442@#status": Status;
|
|
151
|
+
"__#15442@#waitingOn"?: Iterable<Transaction>;
|
|
152
|
+
"__#15442@#via": string;
|
|
153
|
+
"__#15442@#shared"?: import("../index.js").Observable<[]>;
|
|
154
|
+
"__#15442@#closed"?: import("../index.js").Observable<[]>;
|
|
155
|
+
"__#15442@#isAsync": boolean;
|
|
156
|
+
"__#15442@#reportingLocks": boolean;
|
|
157
157
|
close(): void;
|
|
158
158
|
readonly via: string;
|
|
159
159
|
readonly status: Status;
|
|
@@ -175,15 +175,15 @@ export declare const Transaction: {
|
|
|
175
175
|
waitFor(others: Set<Transaction>): Promise<void>;
|
|
176
176
|
toString(): string;
|
|
177
177
|
treatAsSlow(): void;
|
|
178
|
-
"__#
|
|
179
|
-
"__#
|
|
180
|
-
"__#
|
|
181
|
-
"__#
|
|
182
|
-
"__#
|
|
183
|
-
"__#
|
|
184
|
-
"__#
|
|
185
|
-
"__#
|
|
186
|
-
"__#
|
|
178
|
+
"__#15442@#finalize"(status: Status, why: string, finalizer: () => MaybePromise): Promise<void> | undefined;
|
|
179
|
+
"__#15442@#executePreCommit"(): MaybePromise<void>;
|
|
180
|
+
"__#15442@#executeCommit"(): MaybePromise;
|
|
181
|
+
"__#15442@#executeCommit1"(): MaybePromise;
|
|
182
|
+
"__#15442@#executeCommit2"(): Promise<void> | undefined;
|
|
183
|
+
"__#15442@#executePostCommit"(participants: Participant[]): MaybePromise;
|
|
184
|
+
"__#15442@#executeRollback"(): Promise<void> | undefined;
|
|
185
|
+
"__#15442@#locksChanged"(resources: Set<Resource>, how?: string): void;
|
|
186
|
+
"__#15442@#assertAvailable"(): void;
|
|
187
187
|
};
|
|
188
188
|
Status: typeof Status;
|
|
189
189
|
Resource: typeof Resource;
|
|
@@ -8,7 +8,30 @@ export { camelize, describeList, serialize } from "./String.js";
|
|
|
8
8
|
* Performs word wrap. Input is assumed to be a series of paragraphs separated by a newline. Output is an array of
|
|
9
9
|
* formatted lines.
|
|
10
10
|
*
|
|
11
|
-
* Contains specialized support for lists, ESDoc directives
|
|
11
|
+
* Contains specialized support for lists, ESDoc directives and ANSI escape codes.
|
|
12
12
|
*/
|
|
13
13
|
export declare function FormattedText(text: string, width?: number): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Types of things we consider "blocks". Most blocks are lists but we also support markdown-style quotes prefixed with
|
|
16
|
+
* ">".
|
|
17
|
+
*/
|
|
18
|
+
export declare enum BlockKind {
|
|
19
|
+
Simple = "simple",
|
|
20
|
+
Bullet1 = "\u2022",
|
|
21
|
+
Bullet2 = "\u25E6",
|
|
22
|
+
Bullet3 = "\u25AA",
|
|
23
|
+
Bullet4 = "\u25CB",
|
|
24
|
+
Bullet5 = "\u25CF",
|
|
25
|
+
Bullet6 = "\u2023",
|
|
26
|
+
Bullet7 = "\u2043",
|
|
27
|
+
Bullet8 = "\u25D8",
|
|
28
|
+
Quote = ">",
|
|
29
|
+
Number = "number",
|
|
30
|
+
LowerAlpha = "alpha",
|
|
31
|
+
UpperAlpha = "ALPHA",
|
|
32
|
+
LowerRoman = "roman",
|
|
33
|
+
UpperRoman = "ROMAN"
|
|
34
|
+
}
|
|
35
|
+
export declare const Bullets: BlockKind[];
|
|
36
|
+
export declare function looksLikeListItem(text: string): boolean;
|
|
14
37
|
//# sourceMappingURL=FormattedText.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormattedText.d.ts","sourceRoot":"","sources":["../../../src/util/FormattedText.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAM,YAGtD"}
|
|
1
|
+
{"version":3,"file":"FormattedText.d.ts","sourceRoot":"","sources":["../../../src/util/FormattedText.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAM,YAGtD;AAED;;;GAGG;AACH,oBAAY,SAAS;IACjB,MAAM,WAAW;IACjB,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,KAAK,MAAM;IACX,MAAM,WAAW;IACjB,UAAU,UAAU;IACpB,UAAU,UAAU;IACpB,UAAU,UAAU;IACpB,UAAU,UAAU;CACvB;AAED,eAAO,MAAM,OAAO,aAEU,CAAC;AAK/B,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,WAE7C"}
|
|
@@ -18,9 +18,12 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var FormattedText_exports = {};
|
|
20
20
|
__export(FormattedText_exports, {
|
|
21
|
+
BlockKind: () => BlockKind,
|
|
22
|
+
Bullets: () => Bullets,
|
|
21
23
|
FormattedText: () => FormattedText,
|
|
22
24
|
camelize: () => import_String.camelize,
|
|
23
25
|
describeList: () => import_String.describeList,
|
|
26
|
+
looksLikeListItem: () => looksLikeListItem,
|
|
24
27
|
serialize: () => import_String.serialize
|
|
25
28
|
});
|
|
26
29
|
module.exports = __toCommonJS(FormattedText_exports);
|
|
@@ -30,107 +33,97 @@ var import_String = require("./String.js");
|
|
|
30
33
|
* Copyright 2022-2025 Matter.js Authors
|
|
31
34
|
* SPDX-License-Identifier: Apache-2.0
|
|
32
35
|
*/
|
|
33
|
-
const
|
|
36
|
+
const INDENT = " ";
|
|
34
37
|
function FormattedText(text, width = 120) {
|
|
35
38
|
const structure = detectStructure(text);
|
|
36
|
-
return
|
|
39
|
+
return formatBlock(structure, width);
|
|
37
40
|
}
|
|
38
|
-
var
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
41
|
+
var BlockKind = /* @__PURE__ */ ((BlockKind2) => {
|
|
42
|
+
BlockKind2["Simple"] = "simple";
|
|
43
|
+
BlockKind2["Bullet1"] = "\u2022";
|
|
44
|
+
BlockKind2["Bullet2"] = "\u25E6";
|
|
45
|
+
BlockKind2["Bullet3"] = "\u25AA";
|
|
46
|
+
BlockKind2["Bullet4"] = "\u25CB";
|
|
47
|
+
BlockKind2["Bullet5"] = "\u25CF";
|
|
48
|
+
BlockKind2["Bullet6"] = "\u2023";
|
|
49
|
+
BlockKind2["Bullet7"] = "\u2043";
|
|
50
|
+
BlockKind2["Bullet8"] = "\u25D8";
|
|
51
|
+
BlockKind2["Quote"] = ">";
|
|
52
|
+
BlockKind2["Number"] = "number";
|
|
53
|
+
BlockKind2["LowerAlpha"] = "alpha";
|
|
54
|
+
BlockKind2["UpperAlpha"] = "ALPHA";
|
|
55
|
+
BlockKind2["LowerRoman"] = "roman";
|
|
56
|
+
BlockKind2["UpperRoman"] = "ROMAN";
|
|
57
|
+
return BlockKind2;
|
|
58
|
+
})(BlockKind || {});
|
|
59
|
+
const Bullets = Object.entries(BlockKind).filter(([key]) => key.startsWith("Bullet")).map(([, value]) => value);
|
|
60
|
+
const enumTest = "(?:\\d+|[ivx]+|[a-z])\\.";
|
|
61
|
+
const listItemTest = new RegExp(`^(?:[${Bullets.join("")}]|${enumTest})\\s`, "i");
|
|
62
|
+
function looksLikeListItem(text) {
|
|
63
|
+
return !!listItemTest.exec(text);
|
|
64
|
+
}
|
|
65
|
+
const Empty = {
|
|
66
|
+
kind: "simple" /* Simple */,
|
|
67
|
+
indentWidth: 0,
|
|
68
|
+
entries: []
|
|
69
|
+
};
|
|
70
|
+
function detectBlock(text, breadcrumb) {
|
|
71
|
+
const match = text.match(/^\s*(\S+)/);
|
|
72
|
+
if (!match) {
|
|
73
|
+
return;
|
|
62
74
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
75
|
+
const [, marker] = match;
|
|
76
|
+
if (Bullets.includes(marker) || marker === ">" /* Quote */) {
|
|
77
|
+
enterBlock(marker);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (detectEnumeration(/^\d+\.$/, "1", "number" /* Number */)) return;
|
|
81
|
+
if (detectEnumeration(/^[ivx]+\.$/, "i", "roman" /* LowerRoman */)) return;
|
|
82
|
+
if (detectEnumeration(/^[IVX]+\.$/, "I", "ROMAN" /* UpperRoman */)) return;
|
|
83
|
+
if (detectEnumeration(/^[a-z]+\.$/, "a", "alpha" /* LowerAlpha */)) return;
|
|
84
|
+
if (detectEnumeration(/^[A-Z]+\.$/, "A", "ALPHA" /* UpperAlpha */)) return;
|
|
85
|
+
breadcrumb.length = 1;
|
|
86
|
+
function enterBlock(kind) {
|
|
87
|
+
const level = breadcrumb.findIndex((entry) => entry.kind === kind);
|
|
88
|
+
if (level !== -1) {
|
|
89
|
+
breadcrumb.length = level + 1;
|
|
66
90
|
return;
|
|
67
91
|
}
|
|
92
|
+
const block = {
|
|
93
|
+
kind,
|
|
94
|
+
indentWidth: (breadcrumb[breadcrumb.length - 1]?.indentWidth ?? 0) + kind === ">" /* Quote */ ? 0 : 2,
|
|
95
|
+
entries: []
|
|
96
|
+
};
|
|
97
|
+
breadcrumb[breadcrumb.length - 1].entries.push(block);
|
|
98
|
+
breadcrumb.push(block);
|
|
68
99
|
}
|
|
69
|
-
function detectEnumeration(test,
|
|
70
|
-
if (!
|
|
100
|
+
function detectEnumeration(test, startsWith, kind) {
|
|
101
|
+
if (!marker.match(test)) {
|
|
71
102
|
return false;
|
|
72
103
|
}
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
104
|
+
if (!breadcrumb.find((block) => block.kind === kind)) {
|
|
105
|
+
if (marker !== `${startsWith}.`) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
76
108
|
}
|
|
77
|
-
|
|
109
|
+
enterBlock(kind);
|
|
110
|
+
return true;
|
|
78
111
|
}
|
|
79
|
-
if (detectEnumeration(/^\d+\./, "number" /* Number */, "1")) return;
|
|
80
|
-
if (detectEnumeration(/^[ivx]+\./, "roman" /* LowerRoman */, "i")) return;
|
|
81
|
-
if (detectEnumeration(/^[IVX]+\./, "ROMAN" /* UpperRoman */, "I")) return;
|
|
82
|
-
if (detectEnumeration(/^[a-z]+\./, "alpha" /* LowerAlpha */, "a")) return;
|
|
83
|
-
if (detectEnumeration(/^[A-Z]+\./, "ALPHA" /* UpperAlpha */, "A")) return;
|
|
84
|
-
listState.length = 0;
|
|
85
|
-
}
|
|
86
|
-
function extractPrefix(text) {
|
|
87
|
-
const match = text.match(/^(\S+)\s+($|\S.*$)/);
|
|
88
|
-
if (match) {
|
|
89
|
-
return { prefix: match[1], text: match[2] };
|
|
90
|
-
}
|
|
91
|
-
return { prefix: text, text: "" };
|
|
92
112
|
}
|
|
93
113
|
function detectStructure(text) {
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
const lines = text.split(/\n+/).map((line) => line.trimEnd());
|
|
115
|
+
if (!lines.some((p) => p)) {
|
|
116
|
+
return Empty;
|
|
96
117
|
}
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
118
|
+
const breadcrumb = [{ ...Empty, entries: [] }];
|
|
119
|
+
for (const line of lines) {
|
|
120
|
+
detectBlock(line, breadcrumb);
|
|
121
|
+
breadcrumb[breadcrumb.length - 1].entries.push(line.trim().replace(/\s+/g, " "));
|
|
100
122
|
}
|
|
101
|
-
|
|
102
|
-
let index = 0;
|
|
103
|
-
function processLevel() {
|
|
104
|
-
const level = listState.length;
|
|
105
|
-
const structure = {
|
|
106
|
-
prefixWidth: 0,
|
|
107
|
-
entries: []
|
|
108
|
-
};
|
|
109
|
-
while (index < paragraphs.length) {
|
|
110
|
-
detectList(paragraphs[index], listState);
|
|
111
|
-
if (listState.length < level) {
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
if (listState.length > level) {
|
|
115
|
-
structure.entries.push(processLevel());
|
|
116
|
-
if (listState.length < level || index >= paragraphs.length) {
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
structure.entries.push(paragraphs[index]);
|
|
121
|
-
if (level) {
|
|
122
|
-
const { prefix } = extractPrefix(paragraphs[index]);
|
|
123
|
-
if (prefix.length > structure.prefixWidth) {
|
|
124
|
-
structure.prefixWidth = prefix.length;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
index++;
|
|
128
|
-
}
|
|
129
|
-
return structure;
|
|
130
|
-
}
|
|
131
|
-
return processLevel();
|
|
123
|
+
return breadcrumb[0];
|
|
132
124
|
}
|
|
133
|
-
function wrapParagraph(input, into, wrapWidth,
|
|
125
|
+
function wrapParagraph(input, into, wrapWidth, initialPrefix, wrapPrefix) {
|
|
126
|
+
const prefixWidth = visibleWidthOf(initialPrefix);
|
|
134
127
|
const segments = input.split(/\s+/);
|
|
135
128
|
if (!segments) {
|
|
136
129
|
return;
|
|
@@ -146,35 +139,23 @@ function wrapParagraph(input, into, wrapWidth, padding, prefixWidth) {
|
|
|
146
139
|
}
|
|
147
140
|
}
|
|
148
141
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
wrapPrefix = "".padStart(prefixWidth + 1, " ");
|
|
152
|
-
} else {
|
|
153
|
-
wrapPrefix = "";
|
|
154
|
-
}
|
|
155
|
-
const line = Array();
|
|
156
|
-
let length = 0;
|
|
142
|
+
const line = [initialPrefix];
|
|
143
|
+
let width = prefixWidth;
|
|
157
144
|
let pushedOne = false;
|
|
158
|
-
let needWrapPrefix = false;
|
|
159
145
|
for (const s of segments) {
|
|
160
|
-
const
|
|
161
|
-
if (
|
|
146
|
+
const segmentWidth = visibleWidthOf(s);
|
|
147
|
+
if (width && width + segmentWidth > wrapWidth) {
|
|
162
148
|
addLine();
|
|
163
|
-
line.length =
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
if (!line.length && padding) {
|
|
167
|
-
line.push("".padStart(padding, " "));
|
|
168
|
-
length += padding;
|
|
149
|
+
line.length = 0;
|
|
150
|
+
width = prefixWidth;
|
|
169
151
|
}
|
|
170
|
-
if (
|
|
171
|
-
needWrapPrefix = false;
|
|
152
|
+
if (!line.length) {
|
|
172
153
|
line.push(wrapPrefix);
|
|
173
|
-
|
|
154
|
+
width = prefixWidth;
|
|
174
155
|
}
|
|
175
156
|
line.push(s);
|
|
176
157
|
line.push(" ");
|
|
177
|
-
|
|
158
|
+
width += segmentWidth + 1;
|
|
178
159
|
}
|
|
179
160
|
line.length = line.length - 1;
|
|
180
161
|
if (line.length) {
|
|
@@ -190,21 +171,45 @@ function wrapParagraph(input, into, wrapWidth, padding, prefixWidth) {
|
|
|
190
171
|
into.push(line.join(""));
|
|
191
172
|
}
|
|
192
173
|
}
|
|
193
|
-
function
|
|
174
|
+
function separatePrefixFromContent(text) {
|
|
175
|
+
const match = text.match(/^(\S+\s)\s*(\S.*$)/);
|
|
176
|
+
if (match) {
|
|
177
|
+
return { prefix: match[1], text: match[2] };
|
|
178
|
+
}
|
|
179
|
+
return { prefix: "", text };
|
|
180
|
+
}
|
|
181
|
+
function formatBlock(block, width) {
|
|
194
182
|
const lines = Array();
|
|
195
|
-
function formatLevel(
|
|
196
|
-
for (const entry of
|
|
183
|
+
function formatLevel(block2, parentPrefix) {
|
|
184
|
+
for (const entry of block2.entries) {
|
|
197
185
|
if (typeof entry == "string") {
|
|
198
|
-
|
|
186
|
+
let prefix, text;
|
|
187
|
+
if (block2.kind === "simple" /* Simple */) {
|
|
188
|
+
prefix = "";
|
|
189
|
+
text = entry;
|
|
190
|
+
} else {
|
|
191
|
+
({ prefix, text } = separatePrefixFromContent(entry));
|
|
192
|
+
}
|
|
193
|
+
wrapParagraph(
|
|
194
|
+
text,
|
|
195
|
+
lines,
|
|
196
|
+
width,
|
|
197
|
+
parentPrefix + prefix,
|
|
198
|
+
parentPrefix + " ".repeat(visibleWidthOf(prefix))
|
|
199
|
+
);
|
|
199
200
|
} else {
|
|
200
|
-
|
|
201
|
+
let childPrefix = parentPrefix;
|
|
202
|
+
if (entry.kind !== ">" /* Quote */ || parentPrefix !== "") {
|
|
203
|
+
childPrefix += INDENT;
|
|
204
|
+
}
|
|
205
|
+
formatLevel(entry, childPrefix);
|
|
201
206
|
}
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
|
-
formatLevel(
|
|
209
|
+
formatLevel(block, "");
|
|
205
210
|
return lines;
|
|
206
211
|
}
|
|
207
|
-
function
|
|
212
|
+
function visibleWidthOf(text) {
|
|
208
213
|
let length = 0;
|
|
209
214
|
for (let i = 0; i < text.length; ) {
|
|
210
215
|
switch (text[i]) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/util/FormattedText.ts"],
|
|
4
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,oBAAkD;AARlD;AAAA;AAAA;AAAA;AAAA;AAMA,MAAM,
|
|
5
|
-
"names": ["
|
|
4
|
+
"mappings": "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",
|
|
5
|
+
"names": ["BlockKind", "block"]
|
|
6
6
|
}
|
|
@@ -144,16 +144,16 @@ export declare const Transaction: {
|
|
|
144
144
|
*/
|
|
145
145
|
act<T>(via: string, actor: (transaction: Transaction) => MaybePromise<T>): MaybePromise<T>;
|
|
146
146
|
ReadOnly: {
|
|
147
|
-
"__#
|
|
148
|
-
"__#
|
|
149
|
-
"__#
|
|
150
|
-
"__#
|
|
151
|
-
"__#
|
|
152
|
-
"__#
|
|
153
|
-
"__#
|
|
154
|
-
"__#
|
|
155
|
-
"__#
|
|
156
|
-
"__#
|
|
147
|
+
"__#15442@#participants": Set<Participant>;
|
|
148
|
+
"__#15442@#roles": Map<{}, Participant>;
|
|
149
|
+
"__#15442@#resources": Set<Resource>;
|
|
150
|
+
"__#15442@#status": Status;
|
|
151
|
+
"__#15442@#waitingOn"?: Iterable<Transaction>;
|
|
152
|
+
"__#15442@#via": string;
|
|
153
|
+
"__#15442@#shared"?: import("../index.js").Observable<[]>;
|
|
154
|
+
"__#15442@#closed"?: import("../index.js").Observable<[]>;
|
|
155
|
+
"__#15442@#isAsync": boolean;
|
|
156
|
+
"__#15442@#reportingLocks": boolean;
|
|
157
157
|
close(): void;
|
|
158
158
|
readonly via: string;
|
|
159
159
|
readonly status: Status;
|
|
@@ -175,15 +175,15 @@ export declare const Transaction: {
|
|
|
175
175
|
waitFor(others: Set<Transaction>): Promise<void>;
|
|
176
176
|
toString(): string;
|
|
177
177
|
treatAsSlow(): void;
|
|
178
|
-
"__#
|
|
179
|
-
"__#
|
|
180
|
-
"__#
|
|
181
|
-
"__#
|
|
182
|
-
"__#
|
|
183
|
-
"__#
|
|
184
|
-
"__#
|
|
185
|
-
"__#
|
|
186
|
-
"__#
|
|
178
|
+
"__#15442@#finalize"(status: Status, why: string, finalizer: () => MaybePromise): Promise<void> | undefined;
|
|
179
|
+
"__#15442@#executePreCommit"(): MaybePromise<void>;
|
|
180
|
+
"__#15442@#executeCommit"(): MaybePromise;
|
|
181
|
+
"__#15442@#executeCommit1"(): MaybePromise;
|
|
182
|
+
"__#15442@#executeCommit2"(): Promise<void> | undefined;
|
|
183
|
+
"__#15442@#executePostCommit"(participants: Participant[]): MaybePromise;
|
|
184
|
+
"__#15442@#executeRollback"(): Promise<void> | undefined;
|
|
185
|
+
"__#15442@#locksChanged"(resources: Set<Resource>, how?: string): void;
|
|
186
|
+
"__#15442@#assertAvailable"(): void;
|
|
187
187
|
};
|
|
188
188
|
Status: typeof Status;
|
|
189
189
|
Resource: typeof Resource;
|
|
@@ -8,7 +8,30 @@ export { camelize, describeList, serialize } from "./String.js";
|
|
|
8
8
|
* Performs word wrap. Input is assumed to be a series of paragraphs separated by a newline. Output is an array of
|
|
9
9
|
* formatted lines.
|
|
10
10
|
*
|
|
11
|
-
* Contains specialized support for lists, ESDoc directives
|
|
11
|
+
* Contains specialized support for lists, ESDoc directives and ANSI escape codes.
|
|
12
12
|
*/
|
|
13
13
|
export declare function FormattedText(text: string, width?: number): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Types of things we consider "blocks". Most blocks are lists but we also support markdown-style quotes prefixed with
|
|
16
|
+
* ">".
|
|
17
|
+
*/
|
|
18
|
+
export declare enum BlockKind {
|
|
19
|
+
Simple = "simple",
|
|
20
|
+
Bullet1 = "\u2022",
|
|
21
|
+
Bullet2 = "\u25E6",
|
|
22
|
+
Bullet3 = "\u25AA",
|
|
23
|
+
Bullet4 = "\u25CB",
|
|
24
|
+
Bullet5 = "\u25CF",
|
|
25
|
+
Bullet6 = "\u2023",
|
|
26
|
+
Bullet7 = "\u2043",
|
|
27
|
+
Bullet8 = "\u25D8",
|
|
28
|
+
Quote = ">",
|
|
29
|
+
Number = "number",
|
|
30
|
+
LowerAlpha = "alpha",
|
|
31
|
+
UpperAlpha = "ALPHA",
|
|
32
|
+
LowerRoman = "roman",
|
|
33
|
+
UpperRoman = "ROMAN"
|
|
34
|
+
}
|
|
35
|
+
export declare const Bullets: BlockKind[];
|
|
36
|
+
export declare function looksLikeListItem(text: string): boolean;
|
|
14
37
|
//# sourceMappingURL=FormattedText.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormattedText.d.ts","sourceRoot":"","sources":["../../../src/util/FormattedText.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAM,YAGtD"}
|
|
1
|
+
{"version":3,"file":"FormattedText.d.ts","sourceRoot":"","sources":["../../../src/util/FormattedText.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAM,YAGtD;AAED;;;GAGG;AACH,oBAAY,SAAS;IACjB,MAAM,WAAW;IACjB,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,OAAO,WAAM;IACb,KAAK,MAAM;IACX,MAAM,WAAW;IACjB,UAAU,UAAU;IACpB,UAAU,UAAU;IACpB,UAAU,UAAU;IACpB,UAAU,UAAU;CACvB;AAED,eAAO,MAAM,OAAO,aAEU,CAAC;AAK/B,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,WAE7C"}
|
|
@@ -3,108 +3,98 @@
|
|
|
3
3
|
* Copyright 2022-2025 Matter.js Authors
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
const
|
|
6
|
+
const INDENT = " ";
|
|
7
7
|
import { camelize, describeList, serialize } from "./String.js";
|
|
8
8
|
function FormattedText(text, width = 120) {
|
|
9
9
|
const structure = detectStructure(text);
|
|
10
|
-
return
|
|
10
|
+
return formatBlock(structure, width);
|
|
11
11
|
}
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
12
|
+
var BlockKind = /* @__PURE__ */ ((BlockKind2) => {
|
|
13
|
+
BlockKind2["Simple"] = "simple";
|
|
14
|
+
BlockKind2["Bullet1"] = "\u2022";
|
|
15
|
+
BlockKind2["Bullet2"] = "\u25E6";
|
|
16
|
+
BlockKind2["Bullet3"] = "\u25AA";
|
|
17
|
+
BlockKind2["Bullet4"] = "\u25CB";
|
|
18
|
+
BlockKind2["Bullet5"] = "\u25CF";
|
|
19
|
+
BlockKind2["Bullet6"] = "\u2023";
|
|
20
|
+
BlockKind2["Bullet7"] = "\u2043";
|
|
21
|
+
BlockKind2["Bullet8"] = "\u25D8";
|
|
22
|
+
BlockKind2["Quote"] = ">";
|
|
23
|
+
BlockKind2["Number"] = "number";
|
|
24
|
+
BlockKind2["LowerAlpha"] = "alpha";
|
|
25
|
+
BlockKind2["UpperAlpha"] = "ALPHA";
|
|
26
|
+
BlockKind2["LowerRoman"] = "roman";
|
|
27
|
+
BlockKind2["UpperRoman"] = "ROMAN";
|
|
28
|
+
return BlockKind2;
|
|
29
|
+
})(BlockKind || {});
|
|
30
|
+
const Bullets = Object.entries(BlockKind).filter(([key]) => key.startsWith("Bullet")).map(([, value]) => value);
|
|
31
|
+
const enumTest = "(?:\\d+|[ivx]+|[a-z])\\.";
|
|
32
|
+
const listItemTest = new RegExp(`^(?:[${Bullets.join("")}]|${enumTest})\\s`, "i");
|
|
33
|
+
function looksLikeListItem(text) {
|
|
34
|
+
return !!listItemTest.exec(text);
|
|
35
|
+
}
|
|
36
|
+
const Empty = {
|
|
37
|
+
kind: "simple" /* Simple */,
|
|
38
|
+
indentWidth: 0,
|
|
39
|
+
entries: []
|
|
40
|
+
};
|
|
41
|
+
function detectBlock(text, breadcrumb) {
|
|
42
|
+
const match = text.match(/^\s*(\S+)/);
|
|
43
|
+
if (!match) {
|
|
44
|
+
return;
|
|
36
45
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
const [, marker] = match;
|
|
47
|
+
if (Bullets.includes(marker) || marker === ">" /* Quote */) {
|
|
48
|
+
enterBlock(marker);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (detectEnumeration(/^\d+\.$/, "1", "number" /* Number */)) return;
|
|
52
|
+
if (detectEnumeration(/^[ivx]+\.$/, "i", "roman" /* LowerRoman */)) return;
|
|
53
|
+
if (detectEnumeration(/^[IVX]+\.$/, "I", "ROMAN" /* UpperRoman */)) return;
|
|
54
|
+
if (detectEnumeration(/^[a-z]+\.$/, "a", "alpha" /* LowerAlpha */)) return;
|
|
55
|
+
if (detectEnumeration(/^[A-Z]+\.$/, "A", "ALPHA" /* UpperAlpha */)) return;
|
|
56
|
+
breadcrumb.length = 1;
|
|
57
|
+
function enterBlock(kind) {
|
|
58
|
+
const level = breadcrumb.findIndex((entry) => entry.kind === kind);
|
|
59
|
+
if (level !== -1) {
|
|
60
|
+
breadcrumb.length = level + 1;
|
|
40
61
|
return;
|
|
41
62
|
}
|
|
63
|
+
const block = {
|
|
64
|
+
kind,
|
|
65
|
+
indentWidth: (breadcrumb[breadcrumb.length - 1]?.indentWidth ?? 0) + kind === ">" /* Quote */ ? 0 : 2,
|
|
66
|
+
entries: []
|
|
67
|
+
};
|
|
68
|
+
breadcrumb[breadcrumb.length - 1].entries.push(block);
|
|
69
|
+
breadcrumb.push(block);
|
|
42
70
|
}
|
|
43
|
-
function detectEnumeration(test,
|
|
44
|
-
if (!
|
|
71
|
+
function detectEnumeration(test, startsWith, kind) {
|
|
72
|
+
if (!marker.match(test)) {
|
|
45
73
|
return false;
|
|
46
74
|
}
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
75
|
+
if (!breadcrumb.find((block) => block.kind === kind)) {
|
|
76
|
+
if (marker !== `${startsWith}.`) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
50
79
|
}
|
|
51
|
-
|
|
80
|
+
enterBlock(kind);
|
|
81
|
+
return true;
|
|
52
82
|
}
|
|
53
|
-
if (detectEnumeration(/^\d+\./, "number" /* Number */, "1")) return;
|
|
54
|
-
if (detectEnumeration(/^[ivx]+\./, "roman" /* LowerRoman */, "i")) return;
|
|
55
|
-
if (detectEnumeration(/^[IVX]+\./, "ROMAN" /* UpperRoman */, "I")) return;
|
|
56
|
-
if (detectEnumeration(/^[a-z]+\./, "alpha" /* LowerAlpha */, "a")) return;
|
|
57
|
-
if (detectEnumeration(/^[A-Z]+\./, "ALPHA" /* UpperAlpha */, "A")) return;
|
|
58
|
-
listState.length = 0;
|
|
59
|
-
}
|
|
60
|
-
function extractPrefix(text) {
|
|
61
|
-
const match = text.match(/^(\S+)\s+($|\S.*$)/);
|
|
62
|
-
if (match) {
|
|
63
|
-
return { prefix: match[1], text: match[2] };
|
|
64
|
-
}
|
|
65
|
-
return { prefix: text, text: "" };
|
|
66
83
|
}
|
|
67
84
|
function detectStructure(text) {
|
|
68
|
-
|
|
69
|
-
|
|
85
|
+
const lines = text.split(/\n+/).map((line) => line.trimEnd());
|
|
86
|
+
if (!lines.some((p) => p)) {
|
|
87
|
+
return Empty;
|
|
70
88
|
}
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
89
|
+
const breadcrumb = [{ ...Empty, entries: [] }];
|
|
90
|
+
for (const line of lines) {
|
|
91
|
+
detectBlock(line, breadcrumb);
|
|
92
|
+
breadcrumb[breadcrumb.length - 1].entries.push(line.trim().replace(/\s+/g, " "));
|
|
74
93
|
}
|
|
75
|
-
|
|
76
|
-
let index = 0;
|
|
77
|
-
function processLevel() {
|
|
78
|
-
const level = listState.length;
|
|
79
|
-
const structure = {
|
|
80
|
-
prefixWidth: 0,
|
|
81
|
-
entries: []
|
|
82
|
-
};
|
|
83
|
-
while (index < paragraphs.length) {
|
|
84
|
-
detectList(paragraphs[index], listState);
|
|
85
|
-
if (listState.length < level) {
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
if (listState.length > level) {
|
|
89
|
-
structure.entries.push(processLevel());
|
|
90
|
-
if (listState.length < level || index >= paragraphs.length) {
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
structure.entries.push(paragraphs[index]);
|
|
95
|
-
if (level) {
|
|
96
|
-
const { prefix } = extractPrefix(paragraphs[index]);
|
|
97
|
-
if (prefix.length > structure.prefixWidth) {
|
|
98
|
-
structure.prefixWidth = prefix.length;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
index++;
|
|
102
|
-
}
|
|
103
|
-
return structure;
|
|
104
|
-
}
|
|
105
|
-
return processLevel();
|
|
94
|
+
return breadcrumb[0];
|
|
106
95
|
}
|
|
107
|
-
function wrapParagraph(input, into, wrapWidth,
|
|
96
|
+
function wrapParagraph(input, into, wrapWidth, initialPrefix, wrapPrefix) {
|
|
97
|
+
const prefixWidth = visibleWidthOf(initialPrefix);
|
|
108
98
|
const segments = input.split(/\s+/);
|
|
109
99
|
if (!segments) {
|
|
110
100
|
return;
|
|
@@ -120,35 +110,23 @@ function wrapParagraph(input, into, wrapWidth, padding, prefixWidth) {
|
|
|
120
110
|
}
|
|
121
111
|
}
|
|
122
112
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
wrapPrefix = "".padStart(prefixWidth + 1, " ");
|
|
126
|
-
} else {
|
|
127
|
-
wrapPrefix = "";
|
|
128
|
-
}
|
|
129
|
-
const line = Array();
|
|
130
|
-
let length = 0;
|
|
113
|
+
const line = [initialPrefix];
|
|
114
|
+
let width = prefixWidth;
|
|
131
115
|
let pushedOne = false;
|
|
132
|
-
let needWrapPrefix = false;
|
|
133
116
|
for (const s of segments) {
|
|
134
|
-
const
|
|
135
|
-
if (
|
|
117
|
+
const segmentWidth = visibleWidthOf(s);
|
|
118
|
+
if (width && width + segmentWidth > wrapWidth) {
|
|
136
119
|
addLine();
|
|
137
|
-
line.length =
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
if (!line.length && padding) {
|
|
141
|
-
line.push("".padStart(padding, " "));
|
|
142
|
-
length += padding;
|
|
120
|
+
line.length = 0;
|
|
121
|
+
width = prefixWidth;
|
|
143
122
|
}
|
|
144
|
-
if (
|
|
145
|
-
needWrapPrefix = false;
|
|
123
|
+
if (!line.length) {
|
|
146
124
|
line.push(wrapPrefix);
|
|
147
|
-
|
|
125
|
+
width = prefixWidth;
|
|
148
126
|
}
|
|
149
127
|
line.push(s);
|
|
150
128
|
line.push(" ");
|
|
151
|
-
|
|
129
|
+
width += segmentWidth + 1;
|
|
152
130
|
}
|
|
153
131
|
line.length = line.length - 1;
|
|
154
132
|
if (line.length) {
|
|
@@ -164,21 +142,45 @@ function wrapParagraph(input, into, wrapWidth, padding, prefixWidth) {
|
|
|
164
142
|
into.push(line.join(""));
|
|
165
143
|
}
|
|
166
144
|
}
|
|
167
|
-
function
|
|
145
|
+
function separatePrefixFromContent(text) {
|
|
146
|
+
const match = text.match(/^(\S+\s)\s*(\S.*$)/);
|
|
147
|
+
if (match) {
|
|
148
|
+
return { prefix: match[1], text: match[2] };
|
|
149
|
+
}
|
|
150
|
+
return { prefix: "", text };
|
|
151
|
+
}
|
|
152
|
+
function formatBlock(block, width) {
|
|
168
153
|
const lines = Array();
|
|
169
|
-
function formatLevel(
|
|
170
|
-
for (const entry of
|
|
154
|
+
function formatLevel(block2, parentPrefix) {
|
|
155
|
+
for (const entry of block2.entries) {
|
|
171
156
|
if (typeof entry == "string") {
|
|
172
|
-
|
|
157
|
+
let prefix, text;
|
|
158
|
+
if (block2.kind === "simple" /* Simple */) {
|
|
159
|
+
prefix = "";
|
|
160
|
+
text = entry;
|
|
161
|
+
} else {
|
|
162
|
+
({ prefix, text } = separatePrefixFromContent(entry));
|
|
163
|
+
}
|
|
164
|
+
wrapParagraph(
|
|
165
|
+
text,
|
|
166
|
+
lines,
|
|
167
|
+
width,
|
|
168
|
+
parentPrefix + prefix,
|
|
169
|
+
parentPrefix + " ".repeat(visibleWidthOf(prefix))
|
|
170
|
+
);
|
|
173
171
|
} else {
|
|
174
|
-
|
|
172
|
+
let childPrefix = parentPrefix;
|
|
173
|
+
if (entry.kind !== ">" /* Quote */ || parentPrefix !== "") {
|
|
174
|
+
childPrefix += INDENT;
|
|
175
|
+
}
|
|
176
|
+
formatLevel(entry, childPrefix);
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
179
|
}
|
|
178
|
-
formatLevel(
|
|
180
|
+
formatLevel(block, "");
|
|
179
181
|
return lines;
|
|
180
182
|
}
|
|
181
|
-
function
|
|
183
|
+
function visibleWidthOf(text) {
|
|
182
184
|
let length = 0;
|
|
183
185
|
for (let i = 0; i < text.length; ) {
|
|
184
186
|
switch (text[i]) {
|
|
@@ -215,9 +217,12 @@ function visibleLengthOf(text) {
|
|
|
215
217
|
return length;
|
|
216
218
|
}
|
|
217
219
|
export {
|
|
220
|
+
BlockKind,
|
|
221
|
+
Bullets,
|
|
218
222
|
FormattedText,
|
|
219
223
|
camelize,
|
|
220
224
|
describeList,
|
|
225
|
+
looksLikeListItem,
|
|
221
226
|
serialize
|
|
222
227
|
};
|
|
223
228
|
//# sourceMappingURL=FormattedText.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/util/FormattedText.ts"],
|
|
4
|
-
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,MAAM,
|
|
5
|
-
"names": ["
|
|
4
|
+
"mappings": "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",
|
|
5
|
+
"names": ["BlockKind", "block"]
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matter/general",
|
|
3
|
-
"version": "0.13.1-alpha.0-
|
|
3
|
+
"version": "0.13.1-alpha.0-20250509-28e1567e1",
|
|
4
4
|
"description": "Non-Matter support for Matter.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"iot",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@noble/curves": "^1.8.2"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@matter/testing": "0.13.1-alpha.0-
|
|
39
|
+
"@matter/testing": "0.13.1-alpha.0-20250509-28e1567e1"
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
42
|
"dist/**/*",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const INDENT = " ";
|
|
8
8
|
|
|
9
9
|
export { camelize, describeList, serialize } from "./String.js";
|
|
10
10
|
|
|
@@ -12,14 +12,19 @@ export { camelize, describeList, serialize } from "./String.js";
|
|
|
12
12
|
* Performs word wrap. Input is assumed to be a series of paragraphs separated by a newline. Output is an array of
|
|
13
13
|
* formatted lines.
|
|
14
14
|
*
|
|
15
|
-
* Contains specialized support for lists, ESDoc directives
|
|
15
|
+
* Contains specialized support for lists, ESDoc directives and ANSI escape codes.
|
|
16
16
|
*/
|
|
17
17
|
export function FormattedText(text: string, width = 120) {
|
|
18
18
|
const structure = detectStructure(text);
|
|
19
|
-
return
|
|
19
|
+
return formatBlock(structure, width);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Types of things we consider "blocks". Most blocks are lists but we also support markdown-style quotes prefixed with
|
|
24
|
+
* ">".
|
|
25
|
+
*/
|
|
26
|
+
export enum BlockKind {
|
|
27
|
+
Simple = "simple",
|
|
23
28
|
Bullet1 = "•",
|
|
24
29
|
Bullet2 = "◦",
|
|
25
30
|
Bullet3 = "▪",
|
|
@@ -28,6 +33,7 @@ enum ListType {
|
|
|
28
33
|
Bullet6 = "‣",
|
|
29
34
|
Bullet7 = "⁃",
|
|
30
35
|
Bullet8 = "◘",
|
|
36
|
+
Quote = ">",
|
|
31
37
|
Number = "number",
|
|
32
38
|
LowerAlpha = "alpha",
|
|
33
39
|
UpperAlpha = "ALPHA",
|
|
@@ -35,115 +41,114 @@ enum ListType {
|
|
|
35
41
|
UpperRoman = "ROMAN",
|
|
36
42
|
}
|
|
37
43
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (existing == -1) {
|
|
42
|
-
listState.push(listType);
|
|
43
|
-
} else {
|
|
44
|
-
listState.length = existing + 1;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
for (const value of Object.values(ListType)) {
|
|
49
|
-
if (text[0] === value && text[1] === " ") {
|
|
50
|
-
enterList(text[0] as ListType);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function detectEnumeration(test: RegExp, listType: ListType, first: string) {
|
|
56
|
-
if (!text.match(test)) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (listState.indexOf(listType) != -1 || text.startsWith(`${first}.`)) {
|
|
61
|
-
enterList(listType);
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
44
|
+
export const Bullets = Object.entries(BlockKind)
|
|
45
|
+
.filter(([key]) => key.startsWith("Bullet"))
|
|
46
|
+
.map(([, value]) => value);
|
|
67
47
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (detectEnumeration(/^[IVX]+\./, ListType.UpperRoman, "I")) return;
|
|
71
|
-
if (detectEnumeration(/^[a-z]+\./, ListType.LowerAlpha, "a")) return;
|
|
72
|
-
if (detectEnumeration(/^[A-Z]+\./, ListType.UpperAlpha, "A")) return;
|
|
48
|
+
const enumTest = "(?:\\d+|[ivx]+|[a-z])\\.";
|
|
49
|
+
const listItemTest = new RegExp(`^(?:[${Bullets.join("")}]|${enumTest})\\s`, "i");
|
|
73
50
|
|
|
74
|
-
|
|
51
|
+
export function looksLikeListItem(text: string) {
|
|
52
|
+
return !!listItemTest.exec(text);
|
|
75
53
|
}
|
|
76
54
|
|
|
77
|
-
type
|
|
78
|
-
|
|
79
|
-
|
|
55
|
+
type Block = {
|
|
56
|
+
kind: BlockKind;
|
|
57
|
+
indentWidth: number;
|
|
58
|
+
entries: (string | Block)[];
|
|
80
59
|
};
|
|
81
60
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return { prefix: text, text: "" };
|
|
88
|
-
}
|
|
61
|
+
const Empty: Block = {
|
|
62
|
+
kind: BlockKind.Simple,
|
|
63
|
+
indentWidth: 0,
|
|
64
|
+
entries: [],
|
|
65
|
+
};
|
|
89
66
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Detect block prefixes. This is designed to handle scavenged, poorly formatted text so does not use indentation. It
|
|
69
|
+
* just focus on the prefix characters of the paragraph/line (which are the same thing as paragraphs do not include
|
|
70
|
+
* newlines).
|
|
71
|
+
*/
|
|
72
|
+
function detectBlock(text: string, breadcrumb: Block[]) {
|
|
73
|
+
const match = text.match(/^\s*(\S+)/);
|
|
74
|
+
if (!match) {
|
|
75
|
+
return;
|
|
93
76
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
77
|
+
|
|
78
|
+
const [, marker] = match;
|
|
79
|
+
|
|
80
|
+
if (Bullets.includes(marker as BlockKind) || marker === BlockKind.Quote) {
|
|
81
|
+
enterBlock(marker as BlockKind);
|
|
82
|
+
return;
|
|
97
83
|
}
|
|
98
84
|
|
|
99
|
-
|
|
100
|
-
|
|
85
|
+
if (detectEnumeration(/^\d+\.$/, "1", BlockKind.Number)) return;
|
|
86
|
+
if (detectEnumeration(/^[ivx]+\.$/, "i", BlockKind.LowerRoman)) return;
|
|
87
|
+
if (detectEnumeration(/^[IVX]+\.$/, "I", BlockKind.UpperRoman)) return;
|
|
88
|
+
if (detectEnumeration(/^[a-z]+\.$/, "a", BlockKind.LowerAlpha)) return;
|
|
89
|
+
if (detectEnumeration(/^[A-Z]+\.$/, "A", BlockKind.UpperAlpha)) return;
|
|
90
|
+
|
|
91
|
+
// Not in a block
|
|
92
|
+
breadcrumb.length = 1;
|
|
93
|
+
|
|
94
|
+
function enterBlock(kind: BlockKind) {
|
|
95
|
+
// If we are already in block of this kind, ensure it is the deepest level
|
|
96
|
+
const level = breadcrumb.findIndex(entry => entry.kind === kind);
|
|
97
|
+
if (level !== -1) {
|
|
98
|
+
breadcrumb.length = level + 1;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
// Need to start a new block
|
|
103
|
+
const block = {
|
|
104
|
+
kind,
|
|
105
|
+
indentWidth: (breadcrumb[breadcrumb.length - 1]?.indentWidth ?? 0) + kind === BlockKind.Quote ? 0 : 2,
|
|
106
106
|
entries: [],
|
|
107
|
-
}
|
|
107
|
+
};
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
breadcrumb[breadcrumb.length - 1].entries.push(block);
|
|
110
|
+
breadcrumb.push(block);
|
|
111
|
+
}
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
function detectEnumeration(test: RegExp, startsWith: string, kind: BlockKind) {
|
|
114
|
+
if (!marker.match(test)) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
118
|
+
// Only consider enumeration if a.) we are already in same type of enumeration, or b.) the marker is the first
|
|
119
|
+
// element of the enumeration (e.g. "1." or "i.")
|
|
120
|
+
if (!breadcrumb.find(block => block.kind === kind)) {
|
|
121
|
+
if (marker !== `${startsWith}.`) {
|
|
122
|
+
return false;
|
|
123
123
|
}
|
|
124
|
+
}
|
|
124
125
|
|
|
125
|
-
|
|
126
|
-
|
|
126
|
+
enterBlock(kind);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
127
130
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Builds a block structure by detecting lists and/or quoted sections.
|
|
133
|
+
*/
|
|
134
|
+
function detectStructure(text: string): Block {
|
|
135
|
+
const lines = text.split(/\n+/).map(line => line.trimEnd());
|
|
136
|
+
if (!lines.some(p => p)) {
|
|
137
|
+
return Empty;
|
|
138
|
+
}
|
|
135
139
|
|
|
136
|
-
|
|
137
|
-
index++;
|
|
138
|
-
}
|
|
140
|
+
const breadcrumb: Block[] = [{ ...Empty, entries: [] }];
|
|
139
141
|
|
|
140
|
-
|
|
142
|
+
for (const line of lines) {
|
|
143
|
+
detectBlock(line, breadcrumb);
|
|
144
|
+
breadcrumb[breadcrumb.length - 1].entries.push(line.trim().replace(/\s+/g, " "));
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
return
|
|
147
|
+
return breadcrumb[0];
|
|
144
148
|
}
|
|
145
149
|
|
|
146
|
-
function wrapParagraph(input: string, into: string[], wrapWidth: number,
|
|
150
|
+
function wrapParagraph(input: string, into: string[], wrapWidth: number, initialPrefix: string, wrapPrefix: string) {
|
|
151
|
+
const prefixWidth = visibleWidthOf(initialPrefix);
|
|
147
152
|
const segments = input.split(/\s+/);
|
|
148
153
|
if (!segments) {
|
|
149
154
|
return;
|
|
@@ -163,50 +168,32 @@ function wrapParagraph(input: string, into: string[], wrapWidth: number, padding
|
|
|
163
168
|
}
|
|
164
169
|
}
|
|
165
170
|
|
|
166
|
-
// Configure for list prefix formatting
|
|
167
|
-
let wrapPrefix: string;
|
|
168
|
-
if (prefixWidth) {
|
|
169
|
-
// After wrapping this prefix will pad out subsequent entries
|
|
170
|
-
wrapPrefix = "".padStart(prefixWidth + 1, " ");
|
|
171
|
-
} else {
|
|
172
|
-
// No prefix
|
|
173
|
-
wrapPrefix = "";
|
|
174
|
-
}
|
|
175
|
-
|
|
176
171
|
// Wrapping setup. Track the portions of the line and current length
|
|
177
|
-
const line =
|
|
178
|
-
let
|
|
172
|
+
const line = [initialPrefix];
|
|
173
|
+
let width = prefixWidth;
|
|
179
174
|
|
|
180
175
|
// Perform actual wrapping
|
|
181
176
|
let pushedOne = false;
|
|
182
|
-
let needWrapPrefix = false;
|
|
183
177
|
for (const s of segments) {
|
|
184
|
-
const
|
|
178
|
+
const segmentWidth = visibleWidthOf(s);
|
|
185
179
|
|
|
186
180
|
// If we'll extend too far, start on a new line
|
|
187
|
-
if (
|
|
181
|
+
if (width && width + segmentWidth > wrapWidth) {
|
|
188
182
|
addLine();
|
|
189
|
-
line.length =
|
|
190
|
-
|
|
183
|
+
line.length = 0;
|
|
184
|
+
width = prefixWidth;
|
|
191
185
|
}
|
|
192
186
|
|
|
193
|
-
// Add
|
|
194
|
-
if (!line.length
|
|
195
|
-
line.push("".padStart(padding, " "));
|
|
196
|
-
length += padding;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Add wrap prefix if this is a new line in a list
|
|
200
|
-
if (needWrapPrefix) {
|
|
201
|
-
needWrapPrefix = false;
|
|
187
|
+
// Add wrap prefix if this is a new line
|
|
188
|
+
if (!line.length) {
|
|
202
189
|
line.push(wrapPrefix);
|
|
203
|
-
|
|
190
|
+
width = prefixWidth;
|
|
204
191
|
}
|
|
205
192
|
|
|
206
193
|
// Add to the line
|
|
207
194
|
line.push(s);
|
|
208
195
|
line.push(" ");
|
|
209
|
-
|
|
196
|
+
width += segmentWidth + 1;
|
|
210
197
|
}
|
|
211
198
|
|
|
212
199
|
// If there is a remaining line, add it
|
|
@@ -227,25 +214,51 @@ function wrapParagraph(input: string, into: string[], wrapWidth: number, padding
|
|
|
227
214
|
}
|
|
228
215
|
}
|
|
229
216
|
|
|
230
|
-
function
|
|
217
|
+
function separatePrefixFromContent(text: string) {
|
|
218
|
+
const match = text.match(/^(\S+\s)\s*(\S.*$)/);
|
|
219
|
+
if (match) {
|
|
220
|
+
return { prefix: match[1], text: match[2] };
|
|
221
|
+
}
|
|
222
|
+
return { prefix: "", text };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function formatBlock(block: Block, width: number) {
|
|
231
226
|
const lines = Array<string>();
|
|
232
227
|
|
|
233
|
-
function formatLevel(
|
|
234
|
-
for (const entry of
|
|
228
|
+
function formatLevel(block: Block, parentPrefix: string) {
|
|
229
|
+
for (const entry of block.entries) {
|
|
235
230
|
if (typeof entry == "string") {
|
|
236
|
-
|
|
231
|
+
let prefix, text;
|
|
232
|
+
if (block.kind === BlockKind.Simple) {
|
|
233
|
+
prefix = "";
|
|
234
|
+
text = entry;
|
|
235
|
+
} else {
|
|
236
|
+
({ prefix, text } = separatePrefixFromContent(entry));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
wrapParagraph(
|
|
240
|
+
text,
|
|
241
|
+
lines,
|
|
242
|
+
width,
|
|
243
|
+
parentPrefix + prefix,
|
|
244
|
+
parentPrefix + " ".repeat(visibleWidthOf(prefix)),
|
|
245
|
+
);
|
|
237
246
|
} else {
|
|
238
|
-
|
|
247
|
+
let childPrefix = parentPrefix;
|
|
248
|
+
if (entry.kind !== BlockKind.Quote || parentPrefix !== "") {
|
|
249
|
+
childPrefix += INDENT;
|
|
250
|
+
}
|
|
251
|
+
formatLevel(entry, childPrefix);
|
|
239
252
|
}
|
|
240
253
|
}
|
|
241
254
|
}
|
|
242
255
|
|
|
243
|
-
formatLevel(
|
|
256
|
+
formatLevel(block, "");
|
|
244
257
|
|
|
245
258
|
return lines;
|
|
246
259
|
}
|
|
247
260
|
|
|
248
|
-
function
|
|
261
|
+
function visibleWidthOf(text: string) {
|
|
249
262
|
let length = 0;
|
|
250
263
|
for (let i = 0; i < text.length; ) {
|
|
251
264
|
switch (text[i]) {
|