@code.store/arcxp-sdk-ts 5.3.0 → 5.3.2

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.
@@ -26,6 +26,7 @@ export type WrapHandler = (node: Node, content: ContentElementType<'text'>) => C
26
26
  * using the `handle()` and `wrap()` methods.
27
27
  */
28
28
  export declare class HTMLProcessor {
29
+ protected blockElementTags: string[];
29
30
  protected parallelProcessing: boolean;
30
31
  protected handlers: {
31
32
  node: Map<string, NodeHandler>;
@@ -1,2 +1,3 @@
1
1
  export * from './content-elements.js';
2
2
  export * as HTML from './html/index.js';
3
+ export * as XML from './xml/index.js';
@@ -5,6 +5,7 @@ export type CElement = ArcTypes.ANS.AnElementThatCanBeListedAsPartOfContentEleme
5
5
  export type NodeHandler = (node: xmldoc.XmlNodeBase) => MaybePromise<CElement[] | undefined>;
6
6
  export type WrapHandler = (node: xmldoc.XmlElement, content: string) => string;
7
7
  export declare class XMLProcessor {
8
+ protected blockElementTags: string[];
8
9
  protected handlers: {
9
10
  node: Map<string, NodeHandler>;
10
11
  wrap: Map<string, WrapHandler>;
package/dist/index.cjs CHANGED
@@ -11,6 +11,7 @@ var FormData = require('form-data');
11
11
  var ws = require('ws');
12
12
  var nodeHtmlParser = require('node-html-parser');
13
13
  var htmlEntities = require('html-entities');
14
+ var xmldoc = require('xmldoc');
14
15
  var encode = require('base32-encode');
15
16
  var uuid = require('uuid');
16
17
  var assert = require('node:assert');
@@ -34,6 +35,7 @@ function _interopNamespaceDefault(e) {
34
35
 
35
36
  var rateLimit__namespace = /*#__PURE__*/_interopNamespaceDefault(rateLimit);
36
37
  var ws__namespace = /*#__PURE__*/_interopNamespaceDefault(ws);
38
+ var xmldoc__namespace = /*#__PURE__*/_interopNamespaceDefault(xmldoc);
37
39
 
38
40
  const safeJSONStringify = (data) => {
39
41
  try {
@@ -913,7 +915,7 @@ const ArcAPI = (options) => {
913
915
  return API;
914
916
  };
915
917
 
916
- const ContentElement = {
918
+ const ContentElement$1 = {
917
919
  divider: () => {
918
920
  return {
919
921
  type: 'divider',
@@ -1145,7 +1147,7 @@ const ContentElement = {
1145
1147
  },
1146
1148
  };
1147
1149
 
1148
- const BLOCK_ELEMENT_TAGS = [
1150
+ const BLOCK_ELEMENT_TAGS$1 = [
1149
1151
  'ADDRESS',
1150
1152
  'ARTICLE',
1151
1153
  'ASIDE',
@@ -1184,7 +1186,7 @@ const BLOCK_ELEMENT_TAGS = [
1184
1186
 
1185
1187
  var html_constants = /*#__PURE__*/Object.freeze({
1186
1188
  __proto__: null,
1187
- BLOCK_ELEMENT_TAGS: BLOCK_ELEMENT_TAGS
1189
+ BLOCK_ELEMENT_TAGS: BLOCK_ELEMENT_TAGS$1
1188
1190
  });
1189
1191
 
1190
1192
  const socialRegExps = {
@@ -1228,27 +1230,27 @@ function createSocial(url = '') {
1228
1230
  const embeds = [];
1229
1231
  const instagram = instagramURLParser(url);
1230
1232
  if (instagram) {
1231
- embeds.push(ContentElement.instagram(instagram));
1233
+ embeds.push(ContentElement$1.instagram(instagram));
1232
1234
  }
1233
1235
  const twitter = twitterURLParser(url);
1234
1236
  if (twitter) {
1235
- embeds.push(ContentElement.twitter(twitter));
1237
+ embeds.push(ContentElement$1.twitter(twitter));
1236
1238
  }
1237
1239
  const tiktok = tiktokURLParser(url);
1238
1240
  if (tiktok) {
1239
- embeds.push(ContentElement.tiktok(tiktok));
1241
+ embeds.push(ContentElement$1.tiktok(tiktok));
1240
1242
  }
1241
1243
  const youtube = youtubeURLParser(url);
1242
1244
  if (youtube) {
1243
- embeds.push(ContentElement.youtube(youtube));
1245
+ embeds.push(ContentElement$1.youtube(youtube));
1244
1246
  }
1245
1247
  const facebookPost = facebookPostURLParser(url);
1246
1248
  if (facebookPost) {
1247
- embeds.push(ContentElement.facebook_post(facebookPost));
1249
+ embeds.push(ContentElement$1.facebook_post(facebookPost));
1248
1250
  }
1249
1251
  const facebookVideo = facebookVideoURLParser(url);
1250
1252
  if (facebookVideo) {
1251
- embeds.push(ContentElement.facebook_video(facebookVideo));
1253
+ embeds.push(ContentElement$1.facebook_video(facebookVideo));
1252
1254
  }
1253
1255
  return embeds;
1254
1256
  }
@@ -1272,7 +1274,7 @@ var ContentElements = /*#__PURE__*/Object.freeze({
1272
1274
  youtubeURLParser: youtubeURLParser
1273
1275
  });
1274
1276
 
1275
- const isTextNode = (node) => {
1277
+ const isTextNode$1 = (node) => {
1276
1278
  return node instanceof nodeHtmlParser.TextNode;
1277
1279
  };
1278
1280
  const isHTMLElement = (node) => {
@@ -1306,7 +1308,7 @@ var html_utils = /*#__PURE__*/Object.freeze({
1306
1308
  htmlToText: htmlToText,
1307
1309
  isCommentNode: isCommentNode,
1308
1310
  isHTMLElement: isHTMLElement,
1309
- isTextNode: isTextNode,
1311
+ isTextNode: isTextNode$1,
1310
1312
  nodeTagIn: nodeTagIn,
1311
1313
  nodeTagIs: nodeTagIs
1312
1314
  });
@@ -1335,6 +1337,7 @@ var html_utils = /*#__PURE__*/Object.freeze({
1335
1337
  */
1336
1338
  class HTMLProcessor {
1337
1339
  constructor() {
1340
+ this.blockElementTags = BLOCK_ELEMENT_TAGS$1;
1338
1341
  this.parallelProcessing = true;
1339
1342
  this.handlers = {
1340
1343
  node: new Map(),
@@ -1454,7 +1457,7 @@ class HTMLProcessor {
1454
1457
  }
1455
1458
  });
1456
1459
  this.handle('text', (node) => {
1457
- if (isTextNode(node)) {
1460
+ if (isTextNode$1(node)) {
1458
1461
  return this.createText(node);
1459
1462
  }
1460
1463
  });
@@ -1632,23 +1635,23 @@ class HTMLProcessor {
1632
1635
  return [];
1633
1636
  }
1634
1637
  async handleTable(node) {
1635
- return [ContentElement.raw_html(node.toString())];
1638
+ return [ContentElement$1.raw_html(node.toString())];
1636
1639
  }
1637
1640
  async handleIframe(node) {
1638
- return [ContentElement.raw_html(node.toString())];
1641
+ return [ContentElement$1.raw_html(node.toString())];
1639
1642
  }
1640
1643
  async handleImage(node) {
1641
- return [ContentElement.raw_html(node.toString())];
1644
+ return [ContentElement$1.raw_html(node.toString())];
1642
1645
  }
1643
1646
  async handleBreak(_) {
1644
- return [ContentElement.divider()];
1647
+ return [ContentElement$1.divider()];
1645
1648
  }
1646
1649
  async createQuote(node) {
1647
1650
  const items = await this.handleNested(node);
1648
- return [ContentElement.quote(items)];
1651
+ return [ContentElement$1.quote(items)];
1649
1652
  }
1650
1653
  async createText(node) {
1651
- const text = ContentElement.text(node.text);
1654
+ const text = ContentElement$1.text(node.text);
1652
1655
  return [text];
1653
1656
  }
1654
1657
  filterListItems(items) {
@@ -1656,16 +1659,16 @@ class HTMLProcessor {
1656
1659
  }
1657
1660
  async createList(node, type) {
1658
1661
  const items = await this.handleNested(node);
1659
- return [ContentElement.list(type, this.filterListItems(items))];
1662
+ return [ContentElement$1.list(type, this.filterListItems(items))];
1660
1663
  }
1661
1664
  async createHeader(node) {
1662
1665
  const level = +node.tagName.split('H')[1] || 3;
1663
- return [ContentElement.header(node.innerText, level)];
1666
+ return [ContentElement$1.header(node.innerText, level)];
1664
1667
  }
1665
1668
  isBlockElement(node) {
1666
1669
  if (!isHTMLElement(node))
1667
1670
  return false;
1668
- const defaultBlockElements = new Set(BLOCK_ELEMENT_TAGS);
1671
+ const defaultBlockElements = new Set(this.blockElementTags);
1669
1672
  return defaultBlockElements.has(node.tagName);
1670
1673
  }
1671
1674
  warn(metadata, message) {
@@ -1673,17 +1676,241 @@ class HTMLProcessor {
1673
1676
  }
1674
1677
  }
1675
1678
 
1676
- var index$3 = /*#__PURE__*/Object.freeze({
1679
+ var index$4 = /*#__PURE__*/Object.freeze({
1677
1680
  __proto__: null,
1678
1681
  Constants: html_constants,
1679
1682
  HTMLProcessor: HTMLProcessor,
1680
1683
  Utils: html_utils
1681
1684
  });
1682
1685
 
1686
+ const BLOCK_ELEMENT_TAGS = ['paragraph', 'line', 'header', 'ul', 'ol', 'li', 'embed', 'iframe', 'table'];
1687
+
1688
+ var xml_constants = /*#__PURE__*/Object.freeze({
1689
+ __proto__: null,
1690
+ BLOCK_ELEMENT_TAGS: BLOCK_ELEMENT_TAGS
1691
+ });
1692
+
1693
+ const isXmlElement = (node) => {
1694
+ return node?.type === 'element';
1695
+ };
1696
+ const isTextNode = (node) => {
1697
+ return node?.type === 'text';
1698
+ };
1699
+ const nodeNameIs = (node, name) => {
1700
+ return isXmlElement(node) && node.name === name;
1701
+ };
1702
+ const nodeNameIn = (node, names) => {
1703
+ return isXmlElement(node) && names.includes(node.name);
1704
+ };
1705
+
1706
+ var xml_utils = /*#__PURE__*/Object.freeze({
1707
+ __proto__: null,
1708
+ isTextNode: isTextNode,
1709
+ isXmlElement: isXmlElement,
1710
+ nodeNameIn: nodeNameIn,
1711
+ nodeNameIs: nodeNameIs
1712
+ });
1713
+
1714
+ const ContentElement = ContentElement$1;
1715
+ class XMLProcessor {
1716
+ constructor() {
1717
+ this.blockElementTags = BLOCK_ELEMENT_TAGS;
1718
+ this.handlers = {
1719
+ node: new Map(),
1720
+ wrap: new Map(),
1721
+ };
1722
+ }
1723
+ init() {
1724
+ // wrappers are used to wrap the content of nested text nodes
1725
+ // in a specific way
1726
+ this.wrap('link', (node, content) => {
1727
+ return `<a href="${node.attr.url || node.attr.href || '/'}">${content}</a>`;
1728
+ });
1729
+ this.wrap('header', (_node, content) => {
1730
+ return `<h3>${content}</h3>`;
1731
+ });
1732
+ this.wrap('emphasize', (_node, content) => {
1733
+ return `<i>${content}</i>`;
1734
+ });
1735
+ this.wrap('strong', (_node, content) => {
1736
+ return `<b>${content}</b>`;
1737
+ });
1738
+ // handlers are used to handle specific nodes
1739
+ // and return a list of content elements
1740
+ this.handle('default', (node) => {
1741
+ if (nodeNameIn(node, ['section', 'paragraph', 'line', 'header', 'emphasize', 'strong', 'link', 'li'])) {
1742
+ return this.handleNested(node);
1743
+ }
1744
+ });
1745
+ this.handle('text', (node) => {
1746
+ if (isTextNode(node)) {
1747
+ return [ContentElement.text(node.text)];
1748
+ }
1749
+ });
1750
+ this.handle('list', async (node) => {
1751
+ if (nodeNameIn(node, ['ul', 'ol'])) {
1752
+ const listType = node.name === 'ul' ? 'unordered' : 'ordered';
1753
+ return this.createList(node, listType);
1754
+ }
1755
+ });
1756
+ this.handle('table', (node) => {
1757
+ if (nodeNameIs(node, 'table')) {
1758
+ return this.handleTable(node);
1759
+ }
1760
+ });
1761
+ }
1762
+ async parse(xml) {
1763
+ const doc = new xmldoc__namespace.XmlDocument(xml);
1764
+ const elements = await this.process(doc);
1765
+ return elements || [];
1766
+ }
1767
+ handle(name, handler) {
1768
+ if (this.handlers.node.has(name)) {
1769
+ throw new Error(`${name} node handler already set`);
1770
+ }
1771
+ this.handlers.node.set(name, handler);
1772
+ }
1773
+ wrap(name, handler) {
1774
+ if (this.handlers.wrap.has(name)) {
1775
+ throw new Error(`${name} wrap handler already set`);
1776
+ }
1777
+ this.handlers.wrap.set(name, handler);
1778
+ }
1779
+ addTextAdditionalProperties(c, parent) {
1780
+ const additionalProperties = c.additional_properties || {};
1781
+ const parentNodeIsBlockElement = this.isBlockElement(parent);
1782
+ c.additional_properties = {
1783
+ ...c.additional_properties,
1784
+ isBlockElement: additionalProperties.isBlockElement || parentNodeIsBlockElement,
1785
+ };
1786
+ return c;
1787
+ }
1788
+ wrapChildrenTextNodes(node, elements) {
1789
+ const wrapped = [];
1790
+ for (const c of elements) {
1791
+ if (!isTextCE(c)) {
1792
+ wrapped.push(c);
1793
+ continue;
1794
+ }
1795
+ this.addTextAdditionalProperties(c, node);
1796
+ const handler = this.handlers.wrap.get(node.name);
1797
+ if (handler) {
1798
+ wrapped.push({
1799
+ ...c,
1800
+ content: handler(node, c.content),
1801
+ });
1802
+ }
1803
+ else {
1804
+ wrapped.push(c);
1805
+ }
1806
+ }
1807
+ return wrapped;
1808
+ }
1809
+ async handleNested(node) {
1810
+ const children = await Promise.all(node.children.map((child) => this.process(child)));
1811
+ const filtered = children.filter(Boolean).flat();
1812
+ const merged = this.mergeParagraphs(filtered);
1813
+ const wrapped = this.wrapChildrenTextNodes(node, merged);
1814
+ return wrapped;
1815
+ }
1816
+ async process(node) {
1817
+ let isKnownNode = false;
1818
+ const elements = [];
1819
+ for (const [name, handler] of this.handlers.node.entries()) {
1820
+ try {
1821
+ const result = await handler(node);
1822
+ if (Array.isArray(result)) {
1823
+ // if handler returns an array of elements, it means that the node was handled properly, even if there is no elements inside
1824
+ isKnownNode = true;
1825
+ elements.push(...result);
1826
+ break;
1827
+ }
1828
+ }
1829
+ catch (error) {
1830
+ this.warn({ node: node.toString(), error: error.toString(), name }, 'HandlerError');
1831
+ }
1832
+ }
1833
+ if (isKnownNode)
1834
+ return elements;
1835
+ this.warn({ node: node.toString(), type: node.type }, 'UnknownNodeError');
1836
+ }
1837
+ mergeParagraphs(items) {
1838
+ const merged = [];
1839
+ let toMerge = [];
1840
+ const merge = () => {
1841
+ if (!toMerge.length)
1842
+ return;
1843
+ const paragraph = toMerge.reduce((acc, p) => {
1844
+ return {
1845
+ ...p,
1846
+ content: acc.content + p.content,
1847
+ };
1848
+ }, { type: 'text', content: '' });
1849
+ merged.push(paragraph);
1850
+ toMerge = [];
1851
+ };
1852
+ for (let i = 0; i < items.length; i++) {
1853
+ const item = items[i];
1854
+ const isBlockElement = item.additional_properties?.isBlockElement;
1855
+ if (isTextCE(item) && !isBlockElement) {
1856
+ toMerge.push(item);
1857
+ }
1858
+ else {
1859
+ merge();
1860
+ merged.push(item);
1861
+ }
1862
+ }
1863
+ merge();
1864
+ return merged;
1865
+ }
1866
+ async handleTable(node) {
1867
+ const html = node.toString({ html: true });
1868
+ return [ContentElement.raw_html(html)];
1869
+ }
1870
+ async createQuote(node) {
1871
+ const items = await this.handleNested(node);
1872
+ return [ContentElement.quote(items)];
1873
+ }
1874
+ async createList(node, type) {
1875
+ const items = await this.handleNested(node);
1876
+ return [ContentElement.list(type, items)];
1877
+ }
1878
+ getNodeInnerText(node) {
1879
+ return node.children.map((n) => this.htmlFromNode(n).innerText.trim());
1880
+ }
1881
+ getNodeInnerHTML(node) {
1882
+ return node.children.map((n) => this.htmlFromNode(n).innerHTML.trim());
1883
+ }
1884
+ htmlFromNode(node) {
1885
+ return nodeHtmlParser.parse(node.toString({ html: true }));
1886
+ }
1887
+ getDecodedHTMLFromInnerNodes(node) {
1888
+ const encodedHtml = this.getNodeInnerText(node).join('');
1889
+ const decoded = decodeHTMLEntities(encodedHtml);
1890
+ return decoded;
1891
+ }
1892
+ isBlockElement(node) {
1893
+ const defaultBlockElements = new Set(this.blockElementTags);
1894
+ if (defaultBlockElements.has(node.name))
1895
+ return true;
1896
+ }
1897
+ warn(metadata, message) {
1898
+ console.warn(metadata, message);
1899
+ }
1900
+ }
1901
+
1902
+ var index$3 = /*#__PURE__*/Object.freeze({
1903
+ __proto__: null,
1904
+ Constants: xml_constants,
1905
+ Utils: xml_utils,
1906
+ XMLProcessor: XMLProcessor
1907
+ });
1908
+
1683
1909
  var index$2 = /*#__PURE__*/Object.freeze({
1684
1910
  __proto__: null,
1685
- ContentElement: ContentElement,
1686
- HTML: index$3
1911
+ ContentElement: ContentElement$1,
1912
+ HTML: index$4,
1913
+ XML: index$3
1687
1914
  });
1688
1915
 
1689
1916
  /**