@gmb/bitmark-parser-generator 5.14.0 → 5.16.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/index.cjs CHANGED
@@ -48,6 +48,7 @@ __export(index_exports, {
48
48
  InfoFormat: () => InfoFormat,
49
49
  InfoType: () => InfoType,
50
50
  Input: () => Input,
51
+ InputFormat: () => InputFormat,
51
52
  JsonFileGenerator: () => JsonFileGenerator,
52
53
  JsonGenerator: () => JsonGenerator,
53
54
  JsonParser: () => JsonParser,
@@ -1272,6 +1273,7 @@ var propertyKeys = {
1272
1273
  property_availableClassifications: "@availableClassifications",
1273
1274
  property_brandColor: "@brandColor",
1274
1275
  property_brandColorName: "@brandColorName",
1276
+ property_backgroundImage: "@backgroundImage",
1275
1277
  property_blockId: "@blockId",
1276
1278
  property_book: "@book",
1277
1279
  property_bookAlias: "@bookAlias",
@@ -1568,7 +1570,8 @@ var resourceKeys = {
1568
1570
  resource_imagePlaceholder: "&imagePlaceholder",
1569
1571
  resource_previewImage: "&previewImage",
1570
1572
  resource_previewVideo: "&previewVideo",
1571
- resource_coverImage: "&coverImage"
1573
+ resource_coverImage: "&coverImage",
1574
+ resource_backgroundImage: "&backgroundImage"
1572
1575
  };
1573
1576
 
1574
1577
  // src/model/enum/ResourceType.ts
@@ -1798,7 +1801,8 @@ var ResourceType = {
1798
1801
  platformBackgroundImage: "platformBackgroundImage",
1799
1802
  previewImage: "previewImage",
1800
1803
  previewVideo: "previewVideo",
1801
- coverImage: "coverImage"
1804
+ coverImage: "coverImage",
1805
+ backgroundImage: "backgroundImage"
1802
1806
  };
1803
1807
  function resourceTypeToConfigKey(type) {
1804
1808
  return `&${stringUtils.kebabToCamel(type)}`;
@@ -3840,6 +3844,22 @@ var GROUPS = {
3840
3844
  }
3841
3845
  ]
3842
3846
  },
3847
+ {
3848
+ key: ConfigKey.property_backgroundImage,
3849
+ description: "The background image(s) of the book",
3850
+ format: TagFormat.plainText,
3851
+ maxCount: Count.infinity
3852
+ },
3853
+ {
3854
+ key: ConfigKey.resource_backgroundImage,
3855
+ description: "The background image of the book",
3856
+ chain: [
3857
+ {
3858
+ key: ConfigKey.group_resourceImageCommon,
3859
+ description: "Common image properties for the background image resource"
3860
+ }
3861
+ ]
3862
+ },
3843
3863
  {
3844
3864
  key: ConfigKey.property_coverColor,
3845
3865
  description: "The cover color of the book",
@@ -10962,7 +10982,7 @@ var instance2 = new Config();
10962
10982
  // src/generated/package_info.ts
10963
10983
  var PACKAGE_INFO = {
10964
10984
  "name": "@gmb/bitmark-parser-generator",
10965
- "version": "5.14.0",
10985
+ "version": "5.16.0",
10966
10986
  "author": "Get More Brain Ltd",
10967
10987
  "license": "ISC",
10968
10988
  "description": "A bitmark parser and generator using Peggy.js"
@@ -11352,6 +11372,8 @@ var NodeType = {
11352
11372
  avatarImage: "avatarImage",
11353
11373
  backgroundWallpaper: "backgroundWallpaper",
11354
11374
  backgroundWallpaperValue: "backgroundWallpaperValue",
11375
+ backgroundImage: "backgroundImage",
11376
+ backgroundImageValue: "backgroundImageValue",
11355
11377
  bitLevel: "bitLevel",
11356
11378
  // bit level
11357
11379
  bitmarkAst: "bitmarkAst",
@@ -23656,6 +23678,7 @@ var ResourceBuilder = class extends BaseBuilder {
23656
23678
  case ResourceType.platformBackgroundImage:
23657
23679
  case ResourceType.previewImage:
23658
23680
  case ResourceType.coverImage:
23681
+ case ResourceType.backgroundImage:
23659
23682
  node = this.imageResource(context, finalData, type);
23660
23683
  break;
23661
23684
  // case ResourceType.imageResponsive: {
@@ -24935,6 +24958,12 @@ var Builder = class extends BaseBuilder {
24935
24958
  data.coverColor,
24936
24959
  options
24937
24960
  ),
24961
+ backgroundImage: typeof data.backgroundImage === "string" || Array.isArray(data.backgroundImage) ? this.toAstProperty(
24962
+ bitType,
24963
+ ConfigKey.property_backgroundImage,
24964
+ instance4.asArray(data.backgroundImage),
24965
+ options
24966
+ ) : this.toImageResource(context, data.backgroundImage),
24938
24967
  publications: this.toAstProperty(
24939
24968
  bitType,
24940
24969
  ConfigKey.property_publications,
@@ -29008,6 +29037,62 @@ var BitmarkGenerator = class extends AstWalkerGenerator {
29008
29037
  ignoreTrue: propertyConfig.defaultValue === "true"
29009
29038
  });
29010
29039
  }
29040
+ // bitmarkAst -> bits -> bitsValue -> backgroundImage (when it's a resource object or property array)
29041
+ enter_backgroundImage(node, route) {
29042
+ const value = node.value;
29043
+ if (value && typeof value === "object" && !Array.isArray(value) && "type" in value) {
29044
+ const resource = value;
29045
+ this.writeNL();
29046
+ this.writePropertyStyleResource(node.key, resource);
29047
+ return true;
29048
+ }
29049
+ if (Array.isArray(value)) {
29050
+ if (value == null) return true;
29051
+ const parent = this.getParentNode(route);
29052
+ if (parent?.key !== NodeType.bitsValue) return true;
29053
+ const bitType = this.getBitType(route);
29054
+ if (!bitType) return true;
29055
+ const config = instance2.getBitConfig(bitType);
29056
+ const propertyConfig = instance2.getTagConfigForTag(
29057
+ config.tags,
29058
+ ConfigKey.property_backgroundImage
29059
+ );
29060
+ if (!propertyConfig) return true;
29061
+ this.writeNL_IfNotChain(route);
29062
+ this.writeProperty(propertyConfig.tag, value, route, {
29063
+ format: propertyConfig.format ?? TagFormat.plainText,
29064
+ array: propertyConfig.array ?? false,
29065
+ writeEmpty: true,
29066
+ ignoreFalse: propertyConfig.defaultValue === "false",
29067
+ ignoreTrue: propertyConfig.defaultValue === "true"
29068
+ });
29069
+ }
29070
+ return true;
29071
+ }
29072
+ // bitmarkAst -> bits -> bitsValue -> backgroundImage (when it's a property string)
29073
+ // This is called when backgroundImage is a simple string value
29074
+ leaf_backgroundImage(node, route) {
29075
+ const value = node.value;
29076
+ if (value == null) return;
29077
+ const parent = this.getParentNode(route);
29078
+ if (parent?.key !== NodeType.bitsValue) return;
29079
+ const bitType = this.getBitType(route);
29080
+ if (!bitType) return;
29081
+ const config = instance2.getBitConfig(bitType);
29082
+ const propertyConfig = instance2.getTagConfigForTag(
29083
+ config.tags,
29084
+ ConfigKey.property_backgroundImage
29085
+ );
29086
+ if (!propertyConfig) return;
29087
+ this.writeNL_IfNotChain(route);
29088
+ this.writeProperty(propertyConfig.tag, node.value, route, {
29089
+ format: propertyConfig.format ?? TagFormat.plainText,
29090
+ array: propertyConfig.array ?? false,
29091
+ writeEmpty: true,
29092
+ ignoreFalse: propertyConfig.defaultValue === "false",
29093
+ ignoreTrue: propertyConfig.defaultValue === "true"
29094
+ });
29095
+ }
29011
29096
  exit_imagePlaceholder(_node, _route) {
29012
29097
  }
29013
29098
  // bitmarkAst -> bits -> bitsValue -> posterImage
@@ -30621,6 +30706,12 @@ var JsonGenerator = class extends AstWalkerGenerator {
30621
30706
  array: Array.isArray(node.value)
30622
30707
  });
30623
30708
  }
30709
+ // bitmarkAst -> bits -> bitsValue -> backgroundImage
30710
+ enter_backgroundImage(node, route) {
30711
+ return this.standardHandler(node, route, NodeType.bitsValue, {
30712
+ array: Array.isArray(node.value)
30713
+ });
30714
+ }
30624
30715
  // bitmarkAst -> bits -> bitsValue -> resources
30625
30716
  enter_resources(node, route) {
30626
30717
  const resources = node.value;
@@ -35089,7 +35180,7 @@ function resourceContentProcessor(context, _contentDepth, tagsConfig, content, t
35089
35180
  ...tags2
35090
35181
  });
35091
35182
  if (resource) {
35092
- if (configKey === ConfigKey.resource_backgroundWallpaper || configKey === ConfigKey.resource_imagePlaceholder || configKey === ConfigKey.resource_platformIcon || configKey === ConfigKey.resource_platformLogo || configKey === ConfigKey.resource_platformBackgroundImage || configKey === ConfigKey.resource_previewImage || configKey === ConfigKey.resource_previewVideo || configKey === ConfigKey.resource_coverImage) {
35183
+ if (configKey === ConfigKey.resource_backgroundWallpaper || configKey === ConfigKey.resource_imagePlaceholder || configKey === ConfigKey.resource_platformIcon || configKey === ConfigKey.resource_platformLogo || configKey === ConfigKey.resource_platformBackgroundImage || configKey === ConfigKey.resource_previewImage || configKey === ConfigKey.resource_previewVideo || configKey === ConfigKey.resource_coverImage || configKey === ConfigKey.resource_backgroundImage) {
35093
35184
  if (target.propertyStyleResources) {
35094
35185
  if (target.propertyStyleResources[resourceType]) {
35095
35186
  if (!Array.isArray(target.propertyStyleResources[resourceType])) {
@@ -39714,6 +39805,265 @@ var JsonFileGenerator = class {
39714
39805
  }
39715
39806
  };
39716
39807
 
39808
+ // src/generator/plainText/PlainTextGenerator.ts
39809
+ var TEXT_NODE_TYPES = new Set(Object.values(TextNodeType));
39810
+ var PlainTextGenerator = class {
39811
+ /**
39812
+ * Generate plain text from a string or JSON object.
39813
+ *
39814
+ * @param input - A string (plain or JSON-encoded) or a parsed JSON value.
39815
+ * @returns The extracted plain text.
39816
+ */
39817
+ generate(input) {
39818
+ let data = input;
39819
+ if (typeof data === "string") {
39820
+ try {
39821
+ data = JSON.parse(data);
39822
+ } catch (_e) {
39823
+ return data;
39824
+ }
39825
+ }
39826
+ return this.walk(data).trim();
39827
+ }
39828
+ // ---------------------------------------------------------------------------
39829
+ // Private helpers
39830
+ // ---------------------------------------------------------------------------
39831
+ walk(value) {
39832
+ if (value == null) return "";
39833
+ if (typeof value === "string") return value;
39834
+ if (typeof value !== "object") return "";
39835
+ if (Array.isArray(value)) {
39836
+ if (value.length === 0) return "";
39837
+ if (this.isTextAst(value)) {
39838
+ return this.textAstToPlainText(value);
39839
+ }
39840
+ return value.map((v) => this.walk(v)).filter(Boolean).join("\n");
39841
+ }
39842
+ const obj = value;
39843
+ if (this.isTextNode(obj)) {
39844
+ return this.textNodeToPlainText(obj);
39845
+ }
39846
+ if (this.isBitWrapper(obj)) {
39847
+ return this.walk(obj["bit"]);
39848
+ }
39849
+ const parts = [];
39850
+ for (const val of Object.values(obj)) {
39851
+ if (val == null || typeof val !== "object") continue;
39852
+ const text = this.walk(val);
39853
+ if (text) parts.push(text);
39854
+ }
39855
+ return parts.join("\n");
39856
+ }
39857
+ // -- Type guards -----------------------------------------------------------
39858
+ isTextNode(obj) {
39859
+ return typeof obj["type"] === "string" && TEXT_NODE_TYPES.has(obj["type"]);
39860
+ }
39861
+ isTextAst(arr) {
39862
+ const first = arr[0];
39863
+ return typeof first === "object" && first !== null && !Array.isArray(first) && this.isTextNode(first);
39864
+ }
39865
+ isBitWrapper(obj) {
39866
+ return "bit" in obj && typeof obj["bit"] === "object" && obj["bit"] !== null && !Array.isArray(obj["bit"]);
39867
+ }
39868
+ // -- TextNode extraction ---------------------------------------------------
39869
+ textAstToPlainText(ast) {
39870
+ return ast.map((node) => this.textNodeToPlainText(node)).join("\n");
39871
+ }
39872
+ textNodeToPlainText(node) {
39873
+ const { type, text, content } = node;
39874
+ switch (type) {
39875
+ case TextNodeType.text:
39876
+ return this.textWithMarks(node);
39877
+ case TextNodeType.hardBreak:
39878
+ return "\n";
39879
+ // Block elements whose children are joined without extra separator
39880
+ case TextNodeType.paragraph:
39881
+ case TextNodeType.heading:
39882
+ case TextNodeType.section:
39883
+ case TextNodeType.gap:
39884
+ case TextNodeType.select:
39885
+ case TextNodeType.highlight:
39886
+ case TextNodeType.mark:
39887
+ case TextNodeType.codeBlock:
39888
+ return content ? content.map((c) => this.textNodeToPlainText(c)).join("") : text ?? "";
39889
+ // List items are handled by listToPlainText with indent context
39890
+ case TextNodeType.listItem:
39891
+ return content ? content.map((c) => this.textNodeToPlainText(c)).join("") : text ?? "";
39892
+ // Task item – handled by taskListToPlainText, but fallback if encountered standalone
39893
+ case TextNodeType.taskItem: {
39894
+ const checked = node.attrs?.checked ?? false;
39895
+ const prefix = checked ? "[x] " : "[ ] ";
39896
+ const itemText = content ? content.map((c) => this.textNodeToPlainText(c)).join("") : text ?? "";
39897
+ return `${prefix}${itemText}`;
39898
+ }
39899
+ // List containers – rendered with indent-aware helper
39900
+ case TextNodeType.noBulletList:
39901
+ case TextNodeType.bulletList:
39902
+ case TextNodeType.orderedList:
39903
+ case TextNodeType.orderedListRoman:
39904
+ case TextNodeType.orderedListRomanLower:
39905
+ case TextNodeType.letteredList:
39906
+ case TextNodeType.letteredListLower:
39907
+ return this.listToPlainText(node, 0);
39908
+ // Task list – rendered with indent-aware helper
39909
+ case TextNodeType.taskList:
39910
+ return this.taskListToPlainText(node, 0);
39911
+ // Images – return alt text when available
39912
+ case TextNodeType.image:
39913
+ case TextNodeType.imageInline: {
39914
+ const attrs = node.attrs;
39915
+ return attrs?.alt ?? "";
39916
+ }
39917
+ // LaTeX – return the formula source
39918
+ case TextNodeType.latex: {
39919
+ const latexAttrs = node.attrs;
39920
+ return latexAttrs?.formula ?? "";
39921
+ }
39922
+ default:
39923
+ return content ? content.map((c) => this.textNodeToPlainText(c)).join("") : text ?? "";
39924
+ }
39925
+ }
39926
+ listToPlainText(node, depth) {
39927
+ const { type, content } = node;
39928
+ if (!content || content.length === 0) return "";
39929
+ const indent = " ".repeat(depth);
39930
+ const start = node.attrs?.start ?? 1;
39931
+ const displayStart = start < 1 ? start + 1 : start;
39932
+ return content.map((child, i) => {
39933
+ const { inline, nested } = this.splitListItemContent(child, depth);
39934
+ const prefix = this.listItemPrefix(type, displayStart + i);
39935
+ const line = `${indent}${prefix}${inline}`;
39936
+ return nested ? `${line}
39937
+ ${nested}` : line;
39938
+ }).join("\n");
39939
+ }
39940
+ taskListToPlainText(node, depth) {
39941
+ const { content } = node;
39942
+ if (!content || content.length === 0) return "";
39943
+ const indent = " ".repeat(depth);
39944
+ return content.map((child) => {
39945
+ const checked = child.attrs?.checked ?? false;
39946
+ const prefix = checked ? "[x] " : "[ ] ";
39947
+ const { inline, nested } = this.splitListItemContent(child, depth);
39948
+ const line = `${indent}${prefix}${inline}`;
39949
+ return nested ? `${line}
39950
+ ${nested}` : line;
39951
+ }).join("\n");
39952
+ }
39953
+ splitListItemContent(item, depth) {
39954
+ const children = item.content ?? [];
39955
+ const inlineParts = [];
39956
+ const nestedParts = [];
39957
+ for (const child of children) {
39958
+ if (this.isListType(child.type)) {
39959
+ nestedParts.push(this.renderNestedList(child, depth + 1));
39960
+ } else {
39961
+ inlineParts.push(this.textNodeToPlainText(child));
39962
+ }
39963
+ }
39964
+ return {
39965
+ inline: inlineParts.join(""),
39966
+ nested: nestedParts.join("\n")
39967
+ };
39968
+ }
39969
+ isListType(type) {
39970
+ 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;
39971
+ }
39972
+ renderNestedList(node, depth) {
39973
+ if (node.type === TextNodeType.taskList) {
39974
+ return this.taskListToPlainText(node, depth);
39975
+ }
39976
+ return this.listToPlainText(node, depth);
39977
+ }
39978
+ listItemPrefix(listType, index) {
39979
+ switch (listType) {
39980
+ case TextNodeType.bulletList:
39981
+ return "\u2022 ";
39982
+ case TextNodeType.orderedList:
39983
+ return `${index}. `;
39984
+ case TextNodeType.orderedListRoman:
39985
+ return `${this.toRoman(index)}. `;
39986
+ case TextNodeType.orderedListRomanLower:
39987
+ return `${this.toRoman(index).toLowerCase()}. `;
39988
+ case TextNodeType.letteredList:
39989
+ return `${this.toLetter(index)}. `;
39990
+ case TextNodeType.letteredListLower:
39991
+ return `${this.toLetter(index).toLowerCase()}. `;
39992
+ case TextNodeType.noBulletList:
39993
+ default:
39994
+ return "";
39995
+ }
39996
+ }
39997
+ toRoman(num) {
39998
+ const romanNumerals = [
39999
+ [1e3, "M"],
40000
+ [900, "CM"],
40001
+ [500, "D"],
40002
+ [400, "CD"],
40003
+ [100, "C"],
40004
+ [90, "XC"],
40005
+ [50, "L"],
40006
+ [40, "XL"],
40007
+ [10, "X"],
40008
+ [9, "IX"],
40009
+ [5, "V"],
40010
+ [4, "IV"],
40011
+ [1, "I"]
40012
+ ];
40013
+ let result = "";
40014
+ let remaining = num;
40015
+ for (const [value, numeral] of romanNumerals) {
40016
+ while (remaining >= value) {
40017
+ result += numeral;
40018
+ remaining -= value;
40019
+ }
40020
+ }
40021
+ return result;
40022
+ }
40023
+ toLetter(num) {
40024
+ let result = "";
40025
+ let remaining = num;
40026
+ while (remaining > 0) {
40027
+ remaining--;
40028
+ result = String.fromCharCode(65 + remaining % 26) + result;
40029
+ remaining = Math.floor(remaining / 26);
40030
+ }
40031
+ return result;
40032
+ }
40033
+ textWithMarks(node) {
40034
+ const { text, marks } = node;
40035
+ const parts = [];
40036
+ const linkMark = marks?.find((m) => m.type === "link");
40037
+ const href = linkMark?.attrs?.href;
40038
+ if (text && href && text !== href) {
40039
+ const hrefBare = href.replace(/^https?:\/\//, "");
40040
+ if (text.includes(hrefBare)) {
40041
+ parts.push(text.replace(hrefBare, href));
40042
+ } else if (text.includes(href)) {
40043
+ parts.push(text);
40044
+ } else {
40045
+ parts.push(`${text} ${href}`);
40046
+ }
40047
+ } else if (text) {
40048
+ parts.push(text);
40049
+ } else if (href) {
40050
+ parts.push(href);
40051
+ }
40052
+ if (marks) {
40053
+ for (const mark of marks) {
40054
+ if (mark.type === "footnote") {
40055
+ const footnote = mark;
40056
+ if (footnote.attrs?.content) {
40057
+ const footnoteText = footnote.attrs.content.map((c) => this.textNodeToPlainText(c)).join("");
40058
+ if (footnoteText) parts.push(footnoteText);
40059
+ }
40060
+ }
40061
+ }
40062
+ }
40063
+ return parts.join(" ");
40064
+ }
40065
+ };
40066
+
39717
40067
  // src/info/ConfigBuilder.ts
39718
40068
  var import_node_path3 = __toESM(require("path"), 1);
39719
40069
  var import_superenum50 = require("@ncoderz/superenum");
@@ -40423,7 +40773,25 @@ var Output = {
40423
40773
  /**
40424
40774
  * Output AST as a plain JS object, or a file
40425
40775
  */
40426
- ast: "ast"
40776
+ ast: "ast",
40777
+ /**
40778
+ * Output plain text as a string, or a file
40779
+ */
40780
+ text: "text"
40781
+ };
40782
+ var InputFormat = {
40783
+ /**
40784
+ * Input is bitmark
40785
+ */
40786
+ bitmark: "bitmark",
40787
+ /**
40788
+ * Input is bitmarkText
40789
+ */
40790
+ bitmarkText: "bitmarkText",
40791
+ /**
40792
+ * Input is plain text
40793
+ */
40794
+ plainText: "plainText"
40427
40795
  };
40428
40796
  var BitmarkParserGenerator = class {
40429
40797
  constructor() {
@@ -40525,6 +40893,12 @@ var BitmarkParserGenerator = class {
40525
40893
  * - input(JSON/AST) ==> output(bitmark)
40526
40894
  * - input(bitmark) ==> output(JSON)
40527
40895
  *
40896
+ * Output type can be overridden to one of the following:
40897
+ * - bitmark: output bitmark string
40898
+ * - json: output JSON as a plain JS object, or a file
40899
+ * - ast: output AST as a plain JS object, or a file
40900
+ * - text: output plain text as a string, or a file
40901
+ *
40528
40902
  * By default, the result is returned as a string for bitmark, or a plain JS object for JSON/AST.
40529
40903
  *
40530
40904
  * The options can be used to write the output to a file and to set conversion options or override defaults.
@@ -40547,6 +40921,7 @@ var BitmarkParserGenerator = class {
40547
40921
  const outputBitmark = outputFormat === Output.bitmark;
40548
40922
  const outputJson = outputFormat === Output.json;
40549
40923
  const outputAst = outputFormat === Output.ast;
40924
+ const outputText = outputFormat === Output.text;
40550
40925
  const bitmarkParserType = BitmarkParserType.peggy;
40551
40926
  let inStr = input;
40552
40927
  const inputIsString = typeof input === "string";
@@ -40593,6 +40968,22 @@ var BitmarkParserGenerator = class {
40593
40968
  }
40594
40969
  }
40595
40970
  };
40971
+ const bitmarkToText = (bitmarkStr) => {
40972
+ ast = this.bitmarkParser.toAst(bitmarkStr, {
40973
+ parserType: bitmarkParserType
40974
+ });
40975
+ const jsonGenerator = new JsonObjectGenerator(opts);
40976
+ const json = jsonGenerator.generateSync(ast);
40977
+ const textGenerator = new PlainTextGenerator();
40978
+ const str = textGenerator.generate(json);
40979
+ if (opts.outputFile) {
40980
+ import_fs_extra4.default.writeFileSync(opts.outputFile, str, {
40981
+ encoding: "utf8"
40982
+ });
40983
+ } else {
40984
+ res = str;
40985
+ }
40986
+ };
40596
40987
  const astToBitmark = (astJson) => {
40597
40988
  if (opts.outputFile) {
40598
40989
  const generator = new BitmarkFileGenerator(opts.outputFile, opts);
@@ -40615,6 +41006,19 @@ var BitmarkParserGenerator = class {
40615
41006
  res = this.jsonStringifyPrettify(json, jsonOptions);
40616
41007
  }
40617
41008
  };
41009
+ const astToText = (astJson) => {
41010
+ const jsonGenerator = new JsonObjectGenerator(opts);
41011
+ const json = jsonGenerator.generateSync(astJson);
41012
+ const textGenerator = new PlainTextGenerator();
41013
+ const str = textGenerator.generate(json);
41014
+ if (opts.outputFile) {
41015
+ import_fs_extra4.default.writeFileSync(opts.outputFile, str, {
41016
+ encoding: "utf8"
41017
+ });
41018
+ } else {
41019
+ res = str;
41020
+ }
41021
+ };
40618
41022
  const jsonToBitmark = (astJson) => {
40619
41023
  if (opts.outputFile) {
40620
41024
  const generator = new BitmarkFileGenerator(opts.outputFile, opts);
@@ -40627,6 +41031,19 @@ var BitmarkParserGenerator = class {
40627
41031
  const jsonToAst = (astJson) => {
40628
41032
  res = this.jsonStringifyPrettify(astJson, jsonOptions);
40629
41033
  };
41034
+ const jsonToText = (astJson) => {
41035
+ const jsonGenerator = new JsonObjectGenerator(opts);
41036
+ const json = jsonGenerator.generateSync(astJson);
41037
+ const textGenerator = new PlainTextGenerator();
41038
+ const str = textGenerator.generate(json);
41039
+ if (opts.outputFile) {
41040
+ import_fs_extra4.default.writeFileSync(opts.outputFile, str, {
41041
+ encoding: "utf8"
41042
+ });
41043
+ } else {
41044
+ res = str;
41045
+ }
41046
+ };
40630
41047
  const jsonToJson = (astJson) => {
40631
41048
  astToJson(astJson);
40632
41049
  };
@@ -40635,6 +41052,8 @@ var BitmarkParserGenerator = class {
40635
41052
  bitmarkToBitmark(inStr);
40636
41053
  } else if (outputAst) {
40637
41054
  bitmarkToAst(inStr);
41055
+ } else if (outputText) {
41056
+ bitmarkToText(inStr);
40638
41057
  } else {
40639
41058
  bitmarkToJson(inStr);
40640
41059
  }
@@ -40644,6 +41063,8 @@ var BitmarkParserGenerator = class {
40644
41063
  astToAst(ast);
40645
41064
  } else if (outputJson) {
40646
41065
  astToJson(ast);
41066
+ } else if (outputText) {
41067
+ astToText(ast);
40647
41068
  } else {
40648
41069
  astToBitmark(ast);
40649
41070
  }
@@ -40653,6 +41074,8 @@ var BitmarkParserGenerator = class {
40653
41074
  jsonToJson(ast);
40654
41075
  } else if (outputAst) {
40655
41076
  jsonToAst(ast);
41077
+ } else if (outputText) {
41078
+ jsonToText(ast);
40656
41079
  } else {
40657
41080
  jsonToBitmark(ast);
40658
41081
  }
@@ -40781,7 +41204,7 @@ var BitmarkParserGenerator = class {
40781
41204
  return res;
40782
41205
  }
40783
41206
  /**
40784
- * Convert bitmark text from JSON, or JSON to bitmark text.
41207
+ * Convert bitmark text to JSON, or JSON to bitmark text.
40785
41208
  *
40786
41209
  * Input type is detected automatically and may be:
40787
41210
  * - string: bitmark text or JSON
@@ -40855,6 +41278,54 @@ var BitmarkParserGenerator = class {
40855
41278
  }
40856
41279
  return res;
40857
41280
  }
41281
+ extractPlainText(input, options) {
41282
+ const dataIn = input;
41283
+ const inputFormat = options?.inputFormat;
41284
+ const isString2 = typeof input === "string";
41285
+ let data;
41286
+ const parseAutomatically = () => {
41287
+ let dataOut = dataIn;
41288
+ if (typeof dataIn === "string") {
41289
+ try {
41290
+ dataOut = JSON.parse(dataIn);
41291
+ } catch (_e) {
41292
+ let isBitmark = false;
41293
+ const bitmarkData = this.convert(dataIn, {
41294
+ outputFormat: Output.json
41295
+ });
41296
+ if (bitmarkData.length > 0) {
41297
+ const isError = bitmarkData[0].bit.type === BitType._error;
41298
+ if (!isError) {
41299
+ isBitmark = true;
41300
+ dataOut = bitmarkData;
41301
+ }
41302
+ }
41303
+ if (!isBitmark) {
41304
+ dataOut = this.convertText(dataIn, {
41305
+ textFormat: TextFormat.bitmarkText
41306
+ });
41307
+ }
41308
+ }
41309
+ }
41310
+ return dataOut;
41311
+ };
41312
+ if (inputFormat === InputFormat.bitmark) {
41313
+ data = this.convert(dataIn, {
41314
+ outputFormat: Output.json
41315
+ });
41316
+ } else if (inputFormat === InputFormat.bitmarkText) {
41317
+ data = this.convertText(dataIn, {
41318
+ textFormat: TextFormat.bitmarkText
41319
+ });
41320
+ } else if (inputFormat === InputFormat.plainText) {
41321
+ if (isString2) data = String(input);
41322
+ } else {
41323
+ data = parseAutomatically();
41324
+ }
41325
+ const generator = new PlainTextGenerator();
41326
+ const res = generator.generate(data);
41327
+ return res;
41328
+ }
40858
41329
  /**
40859
41330
  * Breakscape bitmark text.
40860
41331
  *
@@ -40962,6 +41433,16 @@ var BitmarkParserGenerator = class {
40962
41433
  }
40963
41434
  return;
40964
41435
  }
41436
+ textAstToPlainText(textAst, _options) {
41437
+ const textGenerator = new TextGenerator(BitmarkVersion.v3, {
41438
+ //
41439
+ });
41440
+ const res = textGenerator.generateSync(textAst, TextFormat.bitmarkText, TextLocation.body, {
41441
+ noBreakscaping: true,
41442
+ noMarkup: true
41443
+ });
41444
+ return res;
41445
+ }
40965
41446
  /**
40966
41447
  * Get the supported bits as a formatted strings
40967
41448
  *
@@ -41032,6 +41513,7 @@ init();
41032
41513
  InfoFormat,
41033
41514
  InfoType,
41034
41515
  Input,
41516
+ InputFormat,
41035
41517
  JsonFileGenerator,
41036
41518
  JsonGenerator,
41037
41519
  JsonParser,