@gmb/bitmark-parser-generator 5.15.0 → 5.17.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/browser/bitmark-parser-generator.min.js +1 -1
- package/dist/browser/bundle-report.html +2 -2
- package/dist/browser/cjs/index.cjs +1596 -1443
- package/dist/browser/cjs/index.cjs.map +1 -1
- package/dist/browser/cjs/index.d.cts +50 -2
- package/dist/browser/esm/index.d.ts +50 -2
- package/dist/browser/esm/index.js +1595 -1443
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/cli/main.js +450 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +415 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -2
- package/dist/index.d.ts +50 -2
- package/dist/index.js +414 -3
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
package/dist/cli/main.js
CHANGED
|
@@ -10876,7 +10876,7 @@ var instance2 = new Config();
|
|
|
10876
10876
|
// src/generated/package_info.ts
|
|
10877
10877
|
var PACKAGE_INFO = {
|
|
10878
10878
|
"name": "@gmb/bitmark-parser-generator",
|
|
10879
|
-
"version": "5.
|
|
10879
|
+
"version": "5.17.0",
|
|
10880
10880
|
"license": "ISC"};
|
|
10881
10881
|
var Environment = {
|
|
10882
10882
|
unknown: "",
|
|
@@ -11107,6 +11107,16 @@ var TextMarkType = {
|
|
|
11107
11107
|
light: "light",
|
|
11108
11108
|
italic: "italic",
|
|
11109
11109
|
highlight: "highlight",
|
|
11110
|
+
highlightOrange: "highlightOrange",
|
|
11111
|
+
highlightYellow: "highlightYellow",
|
|
11112
|
+
highlightGreen: "highlightGreen",
|
|
11113
|
+
highlightBlue: "highlightBlue",
|
|
11114
|
+
highlightPurple: "highlightPurple",
|
|
11115
|
+
highlightPink: "highlightPink",
|
|
11116
|
+
highlightBrown: "highlightBrown",
|
|
11117
|
+
highlightBlack: "highlightBlack",
|
|
11118
|
+
highlightWhite: "highlightWhite",
|
|
11119
|
+
highlightGray: "highlightGray",
|
|
11110
11120
|
// Inline only styles
|
|
11111
11121
|
strike: "strike",
|
|
11112
11122
|
subscript: "subscript",
|
|
@@ -12601,6 +12611,16 @@ var STANDARD_MARK_TYPES = [
|
|
|
12601
12611
|
TextMarkType.highlight
|
|
12602
12612
|
];
|
|
12603
12613
|
var INLINE_MARK_TYPES = [
|
|
12614
|
+
TextMarkType.highlightOrange,
|
|
12615
|
+
TextMarkType.highlightYellow,
|
|
12616
|
+
TextMarkType.highlightGreen,
|
|
12617
|
+
TextMarkType.highlightBlue,
|
|
12618
|
+
TextMarkType.highlightPurple,
|
|
12619
|
+
TextMarkType.highlightPink,
|
|
12620
|
+
TextMarkType.highlightBrown,
|
|
12621
|
+
TextMarkType.highlightBlack,
|
|
12622
|
+
TextMarkType.highlightWhite,
|
|
12623
|
+
TextMarkType.highlightGray,
|
|
12604
12624
|
TextMarkType.strike,
|
|
12605
12625
|
TextMarkType.subscript,
|
|
12606
12626
|
TextMarkType.superscript,
|
|
@@ -39294,6 +39314,265 @@ var JsonFileGenerator = class {
|
|
|
39294
39314
|
this.generator.generateSync(_ast);
|
|
39295
39315
|
}
|
|
39296
39316
|
};
|
|
39317
|
+
|
|
39318
|
+
// src/generator/plainText/PlainTextGenerator.ts
|
|
39319
|
+
var TEXT_NODE_TYPES = new Set(Object.values(TextNodeType));
|
|
39320
|
+
var PlainTextGenerator = class {
|
|
39321
|
+
/**
|
|
39322
|
+
* Generate plain text from a string or JSON object.
|
|
39323
|
+
*
|
|
39324
|
+
* @param input - A string (plain or JSON-encoded) or a parsed JSON value.
|
|
39325
|
+
* @returns The extracted plain text.
|
|
39326
|
+
*/
|
|
39327
|
+
generate(input) {
|
|
39328
|
+
let data = input;
|
|
39329
|
+
if (typeof data === "string") {
|
|
39330
|
+
try {
|
|
39331
|
+
data = JSON.parse(data);
|
|
39332
|
+
} catch (_e) {
|
|
39333
|
+
return data;
|
|
39334
|
+
}
|
|
39335
|
+
}
|
|
39336
|
+
return this.walk(data).trim();
|
|
39337
|
+
}
|
|
39338
|
+
// ---------------------------------------------------------------------------
|
|
39339
|
+
// Private helpers
|
|
39340
|
+
// ---------------------------------------------------------------------------
|
|
39341
|
+
walk(value) {
|
|
39342
|
+
if (value == null) return "";
|
|
39343
|
+
if (typeof value === "string") return value;
|
|
39344
|
+
if (typeof value !== "object") return "";
|
|
39345
|
+
if (Array.isArray(value)) {
|
|
39346
|
+
if (value.length === 0) return "";
|
|
39347
|
+
if (this.isTextAst(value)) {
|
|
39348
|
+
return this.textAstToPlainText(value);
|
|
39349
|
+
}
|
|
39350
|
+
return value.map((v) => this.walk(v)).filter(Boolean).join("\n");
|
|
39351
|
+
}
|
|
39352
|
+
const obj = value;
|
|
39353
|
+
if (this.isTextNode(obj)) {
|
|
39354
|
+
return this.textNodeToPlainText(obj);
|
|
39355
|
+
}
|
|
39356
|
+
if (this.isBitWrapper(obj)) {
|
|
39357
|
+
return this.walk(obj["bit"]);
|
|
39358
|
+
}
|
|
39359
|
+
const parts = [];
|
|
39360
|
+
for (const val of Object.values(obj)) {
|
|
39361
|
+
if (val == null || typeof val !== "object") continue;
|
|
39362
|
+
const text = this.walk(val);
|
|
39363
|
+
if (text) parts.push(text);
|
|
39364
|
+
}
|
|
39365
|
+
return parts.join("\n");
|
|
39366
|
+
}
|
|
39367
|
+
// -- Type guards -----------------------------------------------------------
|
|
39368
|
+
isTextNode(obj) {
|
|
39369
|
+
return typeof obj["type"] === "string" && TEXT_NODE_TYPES.has(obj["type"]);
|
|
39370
|
+
}
|
|
39371
|
+
isTextAst(arr) {
|
|
39372
|
+
const first = arr[0];
|
|
39373
|
+
return typeof first === "object" && first !== null && !Array.isArray(first) && this.isTextNode(first);
|
|
39374
|
+
}
|
|
39375
|
+
isBitWrapper(obj) {
|
|
39376
|
+
return "bit" in obj && typeof obj["bit"] === "object" && obj["bit"] !== null && !Array.isArray(obj["bit"]);
|
|
39377
|
+
}
|
|
39378
|
+
// -- TextNode extraction ---------------------------------------------------
|
|
39379
|
+
textAstToPlainText(ast) {
|
|
39380
|
+
return ast.map((node) => this.textNodeToPlainText(node)).join("\n");
|
|
39381
|
+
}
|
|
39382
|
+
textNodeToPlainText(node) {
|
|
39383
|
+
const { type, text, content } = node;
|
|
39384
|
+
switch (type) {
|
|
39385
|
+
case TextNodeType.text:
|
|
39386
|
+
return this.textWithMarks(node);
|
|
39387
|
+
case TextNodeType.hardBreak:
|
|
39388
|
+
return "\n";
|
|
39389
|
+
// Block elements whose children are joined without extra separator
|
|
39390
|
+
case TextNodeType.paragraph:
|
|
39391
|
+
case TextNodeType.heading:
|
|
39392
|
+
case TextNodeType.section:
|
|
39393
|
+
case TextNodeType.gap:
|
|
39394
|
+
case TextNodeType.select:
|
|
39395
|
+
case TextNodeType.highlight:
|
|
39396
|
+
case TextNodeType.mark:
|
|
39397
|
+
case TextNodeType.codeBlock:
|
|
39398
|
+
return content ? content.map((c) => this.textNodeToPlainText(c)).join("") : text ?? "";
|
|
39399
|
+
// List items are handled by listToPlainText with indent context
|
|
39400
|
+
case TextNodeType.listItem:
|
|
39401
|
+
return content ? content.map((c) => this.textNodeToPlainText(c)).join("") : text ?? "";
|
|
39402
|
+
// Task item – handled by taskListToPlainText, but fallback if encountered standalone
|
|
39403
|
+
case TextNodeType.taskItem: {
|
|
39404
|
+
const checked = node.attrs?.checked ?? false;
|
|
39405
|
+
const prefix = checked ? "[x] " : "[ ] ";
|
|
39406
|
+
const itemText = content ? content.map((c) => this.textNodeToPlainText(c)).join("") : text ?? "";
|
|
39407
|
+
return `${prefix}${itemText}`;
|
|
39408
|
+
}
|
|
39409
|
+
// List containers – rendered with indent-aware helper
|
|
39410
|
+
case TextNodeType.noBulletList:
|
|
39411
|
+
case TextNodeType.bulletList:
|
|
39412
|
+
case TextNodeType.orderedList:
|
|
39413
|
+
case TextNodeType.orderedListRoman:
|
|
39414
|
+
case TextNodeType.orderedListRomanLower:
|
|
39415
|
+
case TextNodeType.letteredList:
|
|
39416
|
+
case TextNodeType.letteredListLower:
|
|
39417
|
+
return this.listToPlainText(node, 0);
|
|
39418
|
+
// Task list – rendered with indent-aware helper
|
|
39419
|
+
case TextNodeType.taskList:
|
|
39420
|
+
return this.taskListToPlainText(node, 0);
|
|
39421
|
+
// Images – return alt text when available
|
|
39422
|
+
case TextNodeType.image:
|
|
39423
|
+
case TextNodeType.imageInline: {
|
|
39424
|
+
const attrs = node.attrs;
|
|
39425
|
+
return attrs?.alt ?? "";
|
|
39426
|
+
}
|
|
39427
|
+
// LaTeX – return the formula source
|
|
39428
|
+
case TextNodeType.latex: {
|
|
39429
|
+
const latexAttrs = node.attrs;
|
|
39430
|
+
return latexAttrs?.formula ?? "";
|
|
39431
|
+
}
|
|
39432
|
+
default:
|
|
39433
|
+
return content ? content.map((c) => this.textNodeToPlainText(c)).join("") : text ?? "";
|
|
39434
|
+
}
|
|
39435
|
+
}
|
|
39436
|
+
listToPlainText(node, depth) {
|
|
39437
|
+
const { type, content } = node;
|
|
39438
|
+
if (!content || content.length === 0) return "";
|
|
39439
|
+
const indent = " ".repeat(depth);
|
|
39440
|
+
const start = node.attrs?.start ?? 1;
|
|
39441
|
+
const displayStart = start < 1 ? start + 1 : start;
|
|
39442
|
+
return content.map((child, i) => {
|
|
39443
|
+
const { inline, nested } = this.splitListItemContent(child, depth);
|
|
39444
|
+
const prefix = this.listItemPrefix(type, displayStart + i);
|
|
39445
|
+
const line = `${indent}${prefix}${inline}`;
|
|
39446
|
+
return nested ? `${line}
|
|
39447
|
+
${nested}` : line;
|
|
39448
|
+
}).join("\n");
|
|
39449
|
+
}
|
|
39450
|
+
taskListToPlainText(node, depth) {
|
|
39451
|
+
const { content } = node;
|
|
39452
|
+
if (!content || content.length === 0) return "";
|
|
39453
|
+
const indent = " ".repeat(depth);
|
|
39454
|
+
return content.map((child) => {
|
|
39455
|
+
const checked = child.attrs?.checked ?? false;
|
|
39456
|
+
const prefix = checked ? "[x] " : "[ ] ";
|
|
39457
|
+
const { inline, nested } = this.splitListItemContent(child, depth);
|
|
39458
|
+
const line = `${indent}${prefix}${inline}`;
|
|
39459
|
+
return nested ? `${line}
|
|
39460
|
+
${nested}` : line;
|
|
39461
|
+
}).join("\n");
|
|
39462
|
+
}
|
|
39463
|
+
splitListItemContent(item, depth) {
|
|
39464
|
+
const children = item.content ?? [];
|
|
39465
|
+
const inlineParts = [];
|
|
39466
|
+
const nestedParts = [];
|
|
39467
|
+
for (const child of children) {
|
|
39468
|
+
if (this.isListType(child.type)) {
|
|
39469
|
+
nestedParts.push(this.renderNestedList(child, depth + 1));
|
|
39470
|
+
} else {
|
|
39471
|
+
inlineParts.push(this.textNodeToPlainText(child));
|
|
39472
|
+
}
|
|
39473
|
+
}
|
|
39474
|
+
return {
|
|
39475
|
+
inline: inlineParts.join(""),
|
|
39476
|
+
nested: nestedParts.join("\n")
|
|
39477
|
+
};
|
|
39478
|
+
}
|
|
39479
|
+
isListType(type) {
|
|
39480
|
+
return type === TextNodeType.bulletList || type === TextNodeType.orderedList || type === TextNodeType.orderedListRoman || type === TextNodeType.orderedListRomanLower || type === TextNodeType.letteredList || type === TextNodeType.letteredListLower || type === TextNodeType.noBulletList || type === TextNodeType.taskList;
|
|
39481
|
+
}
|
|
39482
|
+
renderNestedList(node, depth) {
|
|
39483
|
+
if (node.type === TextNodeType.taskList) {
|
|
39484
|
+
return this.taskListToPlainText(node, depth);
|
|
39485
|
+
}
|
|
39486
|
+
return this.listToPlainText(node, depth);
|
|
39487
|
+
}
|
|
39488
|
+
listItemPrefix(listType, index) {
|
|
39489
|
+
switch (listType) {
|
|
39490
|
+
case TextNodeType.bulletList:
|
|
39491
|
+
return "\u2022 ";
|
|
39492
|
+
case TextNodeType.orderedList:
|
|
39493
|
+
return `${index}. `;
|
|
39494
|
+
case TextNodeType.orderedListRoman:
|
|
39495
|
+
return `${this.toRoman(index)}. `;
|
|
39496
|
+
case TextNodeType.orderedListRomanLower:
|
|
39497
|
+
return `${this.toRoman(index).toLowerCase()}. `;
|
|
39498
|
+
case TextNodeType.letteredList:
|
|
39499
|
+
return `${this.toLetter(index)}. `;
|
|
39500
|
+
case TextNodeType.letteredListLower:
|
|
39501
|
+
return `${this.toLetter(index).toLowerCase()}. `;
|
|
39502
|
+
case TextNodeType.noBulletList:
|
|
39503
|
+
default:
|
|
39504
|
+
return "";
|
|
39505
|
+
}
|
|
39506
|
+
}
|
|
39507
|
+
toRoman(num) {
|
|
39508
|
+
const romanNumerals = [
|
|
39509
|
+
[1e3, "M"],
|
|
39510
|
+
[900, "CM"],
|
|
39511
|
+
[500, "D"],
|
|
39512
|
+
[400, "CD"],
|
|
39513
|
+
[100, "C"],
|
|
39514
|
+
[90, "XC"],
|
|
39515
|
+
[50, "L"],
|
|
39516
|
+
[40, "XL"],
|
|
39517
|
+
[10, "X"],
|
|
39518
|
+
[9, "IX"],
|
|
39519
|
+
[5, "V"],
|
|
39520
|
+
[4, "IV"],
|
|
39521
|
+
[1, "I"]
|
|
39522
|
+
];
|
|
39523
|
+
let result = "";
|
|
39524
|
+
let remaining = num;
|
|
39525
|
+
for (const [value, numeral] of romanNumerals) {
|
|
39526
|
+
while (remaining >= value) {
|
|
39527
|
+
result += numeral;
|
|
39528
|
+
remaining -= value;
|
|
39529
|
+
}
|
|
39530
|
+
}
|
|
39531
|
+
return result;
|
|
39532
|
+
}
|
|
39533
|
+
toLetter(num) {
|
|
39534
|
+
let result = "";
|
|
39535
|
+
let remaining = num;
|
|
39536
|
+
while (remaining > 0) {
|
|
39537
|
+
remaining--;
|
|
39538
|
+
result = String.fromCharCode(65 + remaining % 26) + result;
|
|
39539
|
+
remaining = Math.floor(remaining / 26);
|
|
39540
|
+
}
|
|
39541
|
+
return result;
|
|
39542
|
+
}
|
|
39543
|
+
textWithMarks(node) {
|
|
39544
|
+
const { text, marks } = node;
|
|
39545
|
+
const parts = [];
|
|
39546
|
+
const linkMark = marks?.find((m) => m.type === "link");
|
|
39547
|
+
const href = linkMark?.attrs?.href;
|
|
39548
|
+
if (text && href && text !== href) {
|
|
39549
|
+
const hrefBare = href.replace(/^https?:\/\//, "");
|
|
39550
|
+
if (text.includes(hrefBare)) {
|
|
39551
|
+
parts.push(text.replace(hrefBare, href));
|
|
39552
|
+
} else if (text.includes(href)) {
|
|
39553
|
+
parts.push(text);
|
|
39554
|
+
} else {
|
|
39555
|
+
parts.push(`${text} ${href}`);
|
|
39556
|
+
}
|
|
39557
|
+
} else if (text) {
|
|
39558
|
+
parts.push(text);
|
|
39559
|
+
} else if (href) {
|
|
39560
|
+
parts.push(href);
|
|
39561
|
+
}
|
|
39562
|
+
if (marks) {
|
|
39563
|
+
for (const mark of marks) {
|
|
39564
|
+
if (mark.type === "footnote") {
|
|
39565
|
+
const footnote = mark;
|
|
39566
|
+
if (footnote.attrs?.content) {
|
|
39567
|
+
const footnoteText = footnote.attrs.content.map((c) => this.textNodeToPlainText(c)).join("");
|
|
39568
|
+
if (footnoteText) parts.push(footnoteText);
|
|
39569
|
+
}
|
|
39570
|
+
}
|
|
39571
|
+
}
|
|
39572
|
+
}
|
|
39573
|
+
return parts.join(" ");
|
|
39574
|
+
}
|
|
39575
|
+
};
|
|
39297
39576
|
var normalizeCardKey = (cardSetKey) => stringUtils.camelToKebab(cardSetKey);
|
|
39298
39577
|
var ConfigBuilder = class {
|
|
39299
39578
|
build(options) {
|
|
@@ -39995,7 +40274,25 @@ var Output = {
|
|
|
39995
40274
|
/**
|
|
39996
40275
|
* Output AST as a plain JS object, or a file
|
|
39997
40276
|
*/
|
|
39998
|
-
ast: "ast"
|
|
40277
|
+
ast: "ast",
|
|
40278
|
+
/**
|
|
40279
|
+
* Output plain text as a string, or a file
|
|
40280
|
+
*/
|
|
40281
|
+
text: "text"
|
|
40282
|
+
};
|
|
40283
|
+
var InputFormat = {
|
|
40284
|
+
/**
|
|
40285
|
+
* Input is bitmark
|
|
40286
|
+
*/
|
|
40287
|
+
bitmark: "bitmark",
|
|
40288
|
+
/**
|
|
40289
|
+
* Input is bitmarkText
|
|
40290
|
+
*/
|
|
40291
|
+
bitmarkText: "bitmarkText",
|
|
40292
|
+
/**
|
|
40293
|
+
* Input is plain text
|
|
40294
|
+
*/
|
|
40295
|
+
plainText: "plainText"
|
|
39999
40296
|
};
|
|
40000
40297
|
var BitmarkParserGenerator = class {
|
|
40001
40298
|
ast = new Ast();
|
|
@@ -40079,6 +40376,12 @@ var BitmarkParserGenerator = class {
|
|
|
40079
40376
|
* - input(JSON/AST) ==> output(bitmark)
|
|
40080
40377
|
* - input(bitmark) ==> output(JSON)
|
|
40081
40378
|
*
|
|
40379
|
+
* Output type can be overridden to one of the following:
|
|
40380
|
+
* - bitmark: output bitmark string
|
|
40381
|
+
* - json: output JSON as a plain JS object, or a file
|
|
40382
|
+
* - ast: output AST as a plain JS object, or a file
|
|
40383
|
+
* - text: output plain text as a string, or a file
|
|
40384
|
+
*
|
|
40082
40385
|
* By default, the result is returned as a string for bitmark, or a plain JS object for JSON/AST.
|
|
40083
40386
|
*
|
|
40084
40387
|
* The options can be used to write the output to a file and to set conversion options or override defaults.
|
|
@@ -40101,6 +40404,7 @@ var BitmarkParserGenerator = class {
|
|
|
40101
40404
|
const outputBitmark = outputFormat === Output.bitmark;
|
|
40102
40405
|
const outputJson = outputFormat === Output.json;
|
|
40103
40406
|
const outputAst = outputFormat === Output.ast;
|
|
40407
|
+
const outputText = outputFormat === Output.text;
|
|
40104
40408
|
const bitmarkParserType = BitmarkParserType.peggy;
|
|
40105
40409
|
let inStr = input;
|
|
40106
40410
|
const inputIsString = typeof input === "string";
|
|
@@ -40147,6 +40451,22 @@ var BitmarkParserGenerator = class {
|
|
|
40147
40451
|
}
|
|
40148
40452
|
}
|
|
40149
40453
|
};
|
|
40454
|
+
const bitmarkToText = (bitmarkStr) => {
|
|
40455
|
+
ast = this.bitmarkParser.toAst(bitmarkStr, {
|
|
40456
|
+
parserType: bitmarkParserType
|
|
40457
|
+
});
|
|
40458
|
+
const jsonGenerator = new JsonObjectGenerator(opts);
|
|
40459
|
+
const json = jsonGenerator.generateSync(ast);
|
|
40460
|
+
const textGenerator = new PlainTextGenerator();
|
|
40461
|
+
const str = textGenerator.generate(json);
|
|
40462
|
+
if (opts.outputFile) {
|
|
40463
|
+
fs3.writeFileSync(opts.outputFile, str, {
|
|
40464
|
+
encoding: "utf8"
|
|
40465
|
+
});
|
|
40466
|
+
} else {
|
|
40467
|
+
res = str;
|
|
40468
|
+
}
|
|
40469
|
+
};
|
|
40150
40470
|
const astToBitmark = (astJson) => {
|
|
40151
40471
|
if (opts.outputFile) {
|
|
40152
40472
|
const generator = new BitmarkFileGenerator(opts.outputFile, opts);
|
|
@@ -40169,6 +40489,19 @@ var BitmarkParserGenerator = class {
|
|
|
40169
40489
|
res = this.jsonStringifyPrettify(json, jsonOptions);
|
|
40170
40490
|
}
|
|
40171
40491
|
};
|
|
40492
|
+
const astToText = (astJson) => {
|
|
40493
|
+
const jsonGenerator = new JsonObjectGenerator(opts);
|
|
40494
|
+
const json = jsonGenerator.generateSync(astJson);
|
|
40495
|
+
const textGenerator = new PlainTextGenerator();
|
|
40496
|
+
const str = textGenerator.generate(json);
|
|
40497
|
+
if (opts.outputFile) {
|
|
40498
|
+
fs3.writeFileSync(opts.outputFile, str, {
|
|
40499
|
+
encoding: "utf8"
|
|
40500
|
+
});
|
|
40501
|
+
} else {
|
|
40502
|
+
res = str;
|
|
40503
|
+
}
|
|
40504
|
+
};
|
|
40172
40505
|
const jsonToBitmark = (astJson) => {
|
|
40173
40506
|
if (opts.outputFile) {
|
|
40174
40507
|
const generator = new BitmarkFileGenerator(opts.outputFile, opts);
|
|
@@ -40181,6 +40514,19 @@ var BitmarkParserGenerator = class {
|
|
|
40181
40514
|
const jsonToAst = (astJson) => {
|
|
40182
40515
|
res = this.jsonStringifyPrettify(astJson, jsonOptions);
|
|
40183
40516
|
};
|
|
40517
|
+
const jsonToText = (astJson) => {
|
|
40518
|
+
const jsonGenerator = new JsonObjectGenerator(opts);
|
|
40519
|
+
const json = jsonGenerator.generateSync(astJson);
|
|
40520
|
+
const textGenerator = new PlainTextGenerator();
|
|
40521
|
+
const str = textGenerator.generate(json);
|
|
40522
|
+
if (opts.outputFile) {
|
|
40523
|
+
fs3.writeFileSync(opts.outputFile, str, {
|
|
40524
|
+
encoding: "utf8"
|
|
40525
|
+
});
|
|
40526
|
+
} else {
|
|
40527
|
+
res = str;
|
|
40528
|
+
}
|
|
40529
|
+
};
|
|
40184
40530
|
const jsonToJson = (astJson) => {
|
|
40185
40531
|
astToJson(astJson);
|
|
40186
40532
|
};
|
|
@@ -40189,6 +40535,8 @@ var BitmarkParserGenerator = class {
|
|
|
40189
40535
|
bitmarkToBitmark(inStr);
|
|
40190
40536
|
} else if (outputAst) {
|
|
40191
40537
|
bitmarkToAst(inStr);
|
|
40538
|
+
} else if (outputText) {
|
|
40539
|
+
bitmarkToText(inStr);
|
|
40192
40540
|
} else {
|
|
40193
40541
|
bitmarkToJson(inStr);
|
|
40194
40542
|
}
|
|
@@ -40198,6 +40546,8 @@ var BitmarkParserGenerator = class {
|
|
|
40198
40546
|
astToAst(ast);
|
|
40199
40547
|
} else if (outputJson) {
|
|
40200
40548
|
astToJson(ast);
|
|
40549
|
+
} else if (outputText) {
|
|
40550
|
+
astToText(ast);
|
|
40201
40551
|
} else {
|
|
40202
40552
|
astToBitmark(ast);
|
|
40203
40553
|
}
|
|
@@ -40207,6 +40557,8 @@ var BitmarkParserGenerator = class {
|
|
|
40207
40557
|
jsonToJson(ast);
|
|
40208
40558
|
} else if (outputAst) {
|
|
40209
40559
|
jsonToAst(ast);
|
|
40560
|
+
} else if (outputText) {
|
|
40561
|
+
jsonToText(ast);
|
|
40210
40562
|
} else {
|
|
40211
40563
|
jsonToBitmark(ast);
|
|
40212
40564
|
}
|
|
@@ -40335,7 +40687,7 @@ var BitmarkParserGenerator = class {
|
|
|
40335
40687
|
return res;
|
|
40336
40688
|
}
|
|
40337
40689
|
/**
|
|
40338
|
-
* Convert bitmark text
|
|
40690
|
+
* Convert bitmark text to JSON, or JSON to bitmark text.
|
|
40339
40691
|
*
|
|
40340
40692
|
* Input type is detected automatically and may be:
|
|
40341
40693
|
* - string: bitmark text or JSON
|
|
@@ -40409,6 +40761,54 @@ var BitmarkParserGenerator = class {
|
|
|
40409
40761
|
}
|
|
40410
40762
|
return res;
|
|
40411
40763
|
}
|
|
40764
|
+
extractPlainText(input, options) {
|
|
40765
|
+
const dataIn = input;
|
|
40766
|
+
const inputFormat = options?.inputFormat;
|
|
40767
|
+
const isString2 = typeof input === "string";
|
|
40768
|
+
let data;
|
|
40769
|
+
const parseAutomatically = () => {
|
|
40770
|
+
let dataOut = dataIn;
|
|
40771
|
+
if (typeof dataIn === "string") {
|
|
40772
|
+
try {
|
|
40773
|
+
dataOut = JSON.parse(dataIn);
|
|
40774
|
+
} catch (_e) {
|
|
40775
|
+
let isBitmark = false;
|
|
40776
|
+
const bitmarkData = this.convert(dataIn, {
|
|
40777
|
+
outputFormat: Output.json
|
|
40778
|
+
});
|
|
40779
|
+
if (bitmarkData.length > 0) {
|
|
40780
|
+
const isError = bitmarkData[0].bit.type === BitType._error;
|
|
40781
|
+
if (!isError) {
|
|
40782
|
+
isBitmark = true;
|
|
40783
|
+
dataOut = bitmarkData;
|
|
40784
|
+
}
|
|
40785
|
+
}
|
|
40786
|
+
if (!isBitmark) {
|
|
40787
|
+
dataOut = this.convertText(dataIn, {
|
|
40788
|
+
textFormat: TextFormat.bitmarkText
|
|
40789
|
+
});
|
|
40790
|
+
}
|
|
40791
|
+
}
|
|
40792
|
+
}
|
|
40793
|
+
return dataOut;
|
|
40794
|
+
};
|
|
40795
|
+
if (inputFormat === InputFormat.bitmark) {
|
|
40796
|
+
data = this.convert(dataIn, {
|
|
40797
|
+
outputFormat: Output.json
|
|
40798
|
+
});
|
|
40799
|
+
} else if (inputFormat === InputFormat.bitmarkText) {
|
|
40800
|
+
data = this.convertText(dataIn, {
|
|
40801
|
+
textFormat: TextFormat.bitmarkText
|
|
40802
|
+
});
|
|
40803
|
+
} else if (inputFormat === InputFormat.plainText) {
|
|
40804
|
+
if (isString2) data = String(input);
|
|
40805
|
+
} else {
|
|
40806
|
+
data = parseAutomatically();
|
|
40807
|
+
}
|
|
40808
|
+
const generator = new PlainTextGenerator();
|
|
40809
|
+
const res = generator.generate(data);
|
|
40810
|
+
return res;
|
|
40811
|
+
}
|
|
40412
40812
|
/**
|
|
40413
40813
|
* Breakscape bitmark text.
|
|
40414
40814
|
*
|
|
@@ -40516,6 +40916,16 @@ var BitmarkParserGenerator = class {
|
|
|
40516
40916
|
}
|
|
40517
40917
|
return;
|
|
40518
40918
|
}
|
|
40919
|
+
textAstToPlainText(textAst, _options) {
|
|
40920
|
+
const textGenerator = new TextGenerator(BitmarkVersion.v3, {
|
|
40921
|
+
//
|
|
40922
|
+
});
|
|
40923
|
+
const res = textGenerator.generateSync(textAst, TextFormat.bitmarkText, TextLocation.body, {
|
|
40924
|
+
noBreakscaping: true,
|
|
40925
|
+
noMarkup: true
|
|
40926
|
+
});
|
|
40927
|
+
return res;
|
|
40928
|
+
}
|
|
40519
40929
|
/**
|
|
40520
40930
|
* Stringify / prettify a plain JS object to a JSON string, depending on the JSON options
|
|
40521
40931
|
*
|
|
@@ -40773,6 +41183,42 @@ Examples:
|
|
|
40773
41183
|
);
|
|
40774
41184
|
return cmd;
|
|
40775
41185
|
}
|
|
41186
|
+
var INPUT_FORMAT_CHOICES = enumChoices(InputFormat);
|
|
41187
|
+
function createExtractPlainTextCommand() {
|
|
41188
|
+
const bpg = new BitmarkParserGenerator();
|
|
41189
|
+
const cmd = new Command("extractPlainText").description("Extract plain text from bitmark, bitmark text, or JSON").argument(
|
|
41190
|
+
"[input]",
|
|
41191
|
+
"file to read, or text or json string. If not specified, input will be from <stdin>"
|
|
41192
|
+
).addOption(
|
|
41193
|
+
new Option(
|
|
41194
|
+
"-f, --inputFormat <format>",
|
|
41195
|
+
"force input format (auto-detected by default)"
|
|
41196
|
+
).choices([...INPUT_FORMAT_CHOICES])
|
|
41197
|
+
).option("-a, --append", "append to the output file (default is to overwrite)").option("-o, --output <file>", "output file. If not specified, output will be to <stdout>").action(async (input, options) => {
|
|
41198
|
+
try {
|
|
41199
|
+
const dataIn = await readInput(input);
|
|
41200
|
+
const result = bpg.extractPlainText(dataIn, {
|
|
41201
|
+
inputFormat: Enum(InputFormat).fromValue(options.inputFormat)
|
|
41202
|
+
});
|
|
41203
|
+
await writeOutput(result ?? "", options.output, options.append);
|
|
41204
|
+
} catch (error) {
|
|
41205
|
+
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
41206
|
+
process.exit(1);
|
|
41207
|
+
}
|
|
41208
|
+
}).addHelpText(
|
|
41209
|
+
"after",
|
|
41210
|
+
`
|
|
41211
|
+
Examples:
|
|
41212
|
+
$ bitmark-parser extractPlainText '[{"type":"paragraph","content":[{"text":"Hello World","type":"text"}],"attrs":{}}]'
|
|
41213
|
+
|
|
41214
|
+
$ bitmark-parser extractPlainText input.json
|
|
41215
|
+
|
|
41216
|
+
$ bitmark-parser extractPlainText input.json -o output.txt
|
|
41217
|
+
|
|
41218
|
+
$ bitmark-parser extractPlainText -f bitmark input.bitmark`
|
|
41219
|
+
);
|
|
41220
|
+
return cmd;
|
|
41221
|
+
}
|
|
40776
41222
|
var INFO_TYPE_CHOICES = (() => {
|
|
40777
41223
|
const choices = new Set(enumChoices(InfoType));
|
|
40778
41224
|
const ordered = [];
|
|
@@ -40900,6 +41346,7 @@ async function asyncInit() {
|
|
|
40900
41346
|
});
|
|
40901
41347
|
program.addCommand(createConvertCommand());
|
|
40902
41348
|
program.addCommand(createConvertTextCommand());
|
|
41349
|
+
program.addCommand(createExtractPlainTextCommand());
|
|
40903
41350
|
program.addCommand(createBreakscapeCommand());
|
|
40904
41351
|
program.addCommand(createUnbreakscapeCommand());
|
|
40905
41352
|
program.addCommand(createInfoCommand());
|