@examind/block-sdk 0.1.33 → 0.1.36

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.
Files changed (3) hide show
  1. package/dist/index.js +142 -93
  2. package/dist/index.mjs +137 -88
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -260,6 +260,37 @@ var FinancialStatementQuestionNodeHandler = class extends NodeHandler {
260
260
  }
261
261
  };
262
262
 
263
+ // src/typeGuards/isSerializedHeadingNode.ts
264
+ var isSerializedHeadingNode = (node) => {
265
+ return node?.type === "heading";
266
+ };
267
+
268
+ // src/exportToHtml/elementTypeToFormat.ts
269
+ var ELEMENT_TYPE_TO_FORMAT = {
270
+ center: "center",
271
+ end: "end",
272
+ justify: "justify",
273
+ left: "left",
274
+ right: "right",
275
+ start: "start"
276
+ };
277
+
278
+ // src/exportToHtml/HeadingNodeHandler.ts
279
+ var HeadingNodeHandler = class extends NodeHandler {
280
+ processNode(node) {
281
+ if (!isSerializedHeadingNode(node)) return null;
282
+ const children = [];
283
+ node.children.forEach((child) => {
284
+ const childString = traverse(child);
285
+ if (childString) {
286
+ children.push(childString);
287
+ }
288
+ });
289
+ const attribute = node.format ? ` style="text-align: ${ELEMENT_TYPE_TO_FORMAT[node.format]};"` : "";
290
+ return `<${node.tag}${attribute}>${children.join("")}</${node.tag}>`;
291
+ }
292
+ };
293
+
263
294
  // src/typeGuards/isSerializedHorizontalRuleNode.ts
264
295
  var isSerializedHorizontalRuleNode = (node) => {
265
296
  return node?.type === "horizontalrule";
@@ -613,14 +644,6 @@ function isSerializedTableCellNode(node) {
613
644
  }
614
645
 
615
646
  // src/exportToHtml/ParagraphNodeHandler.ts
616
- var ELEMENT_TYPE_TO_FORMAT = {
617
- center: "center",
618
- end: "end",
619
- justify: "justify",
620
- left: "left",
621
- right: "right",
622
- start: "start"
623
- };
624
647
  var ParagraphNodeHandler = class extends NodeHandler {
625
648
  shouldAvoidParagraphWrap(node) {
626
649
  if (node === void 0) return false;
@@ -686,8 +709,9 @@ var SimulationQuestionNodeHandler = class extends NodeHandler {
686
709
  if (!isSerializedSimulationQuestionNode(node)) return null;
687
710
  const aiChatModelAttr = node.aiChatModel ? ` data-x-ai-chat-model="${node.aiChatModel}"` : "";
688
711
  const aiSystemMessage = node.aiSystemMessage ? `<x-ai-system-message>${node.aiSystemMessage}</x-ai-system-message>` : "";
689
- const step2Instructions = node.step2Instructions ? `<x-step2-instructions>${node.step2Instructions}</x-step2-instructions>` : "";
690
- return `<x-simulation id="${node.id}" data-x-prompt data-x-points="${node.points}"${aiChatModelAttr}>${aiSystemMessage}${step2Instructions}</x-simulation>`;
712
+ const disableChatAttr = node.disableChat ? ` data-x-disable-chat="true"` : "";
713
+ const commentInstructions = node.commentInstructions ? `<x-comment-instructions>${node.commentInstructions}</x-comment-instructions>` : "";
714
+ return `<x-simulation id="${node.id}" data-x-prompt data-x-points="${node.points}"${aiChatModelAttr}${disableChatAttr}>${aiSystemMessage}${commentInstructions}</x-simulation>`;
691
715
  }
692
716
  };
693
717
 
@@ -931,7 +955,7 @@ var VariableNodeHandler = class extends NodeHandler {
931
955
 
932
956
  // src/exportToHtml/traverse.ts
933
957
  var builder = new NodeHandlerChainBuilder();
934
- var nodeHandlerChain = builder.addHandler(CustomQuestionNodeHandler).addHandler(EssayQuestionNodeHandler).addHandler(FillInTheBlankQuestionNodeHandler).addHandler(FillInTheBlankSpaceNodeHandler).addHandler(FinancialStatementQuestionNodeHandler).addHandler(HorizontalRuleNodeHandler).addHandler(ImageNodeHandler).addHandler(JournalEntryQuestionNodeHandler).addHandler(LineBreakNodeHandler).addHandler(LinkNodeHandler).addHandler(ListNodeHandler).addHandler(ListItemNodeHandler).addHandler(MatchingQuestionNodeHandler).addHandler(MultipleOptionQuestionNodeHandler).addHandler(ParagraphNodeHandler).addHandler(ShortAnswerQuestionNodeHandler).addHandler(SimulationQuestionNodeHandler).addHandler(TableCellNodeHandler).addHandler(TableNodeHandler).addHandler(TableRowNodeHandler).addHandler(TextNodeHandler).addHandler(VariableNodeHandler).build();
958
+ var nodeHandlerChain = builder.addHandler(CustomQuestionNodeHandler).addHandler(EssayQuestionNodeHandler).addHandler(FillInTheBlankQuestionNodeHandler).addHandler(FillInTheBlankSpaceNodeHandler).addHandler(FinancialStatementQuestionNodeHandler).addHandler(HeadingNodeHandler).addHandler(HorizontalRuleNodeHandler).addHandler(ImageNodeHandler).addHandler(JournalEntryQuestionNodeHandler).addHandler(LineBreakNodeHandler).addHandler(LinkNodeHandler).addHandler(ListNodeHandler).addHandler(ListItemNodeHandler).addHandler(MatchingQuestionNodeHandler).addHandler(MultipleOptionQuestionNodeHandler).addHandler(ParagraphNodeHandler).addHandler(ShortAnswerQuestionNodeHandler).addHandler(SimulationQuestionNodeHandler).addHandler(TableCellNodeHandler).addHandler(TableNodeHandler).addHandler(TableRowNodeHandler).addHandler(TextNodeHandler).addHandler(VariableNodeHandler).build();
935
959
  var traverse = (node, metadata) => {
936
960
  return nodeHandlerChain.handle(node, metadata);
937
961
  };
@@ -950,7 +974,7 @@ function exportToHtml(editorState) {
950
974
  }
951
975
 
952
976
  // src/importFromHtml/index.ts
953
- var import_node_html_parser28 = require("node-html-parser");
977
+ var import_node_html_parser29 = require("node-html-parser");
954
978
 
955
979
  // src/importFromHtml/createEmptyParagraphNode.ts
956
980
  function createEmptyParagraphNode(format = "") {
@@ -1518,12 +1542,61 @@ var FormattedNodeHandler = class extends NodeHandler2 {
1518
1542
  }
1519
1543
  };
1520
1544
 
1521
- // src/importFromHtml/HorizontalRuleNodeHandler.ts
1545
+ // src/importFromHtml/HeadingNodeHandler.ts
1522
1546
  var import_node_html_parser9 = require("node-html-parser");
1547
+
1548
+ // src/importFromHtml/extractTextAlignment.ts
1549
+ var TEXT_ALIGN_TO_FORMAT = {
1550
+ center: "center",
1551
+ end: "end",
1552
+ justify: "justify",
1553
+ left: "left",
1554
+ right: "right",
1555
+ start: "start"
1556
+ };
1557
+ function extractTextAlignment(element) {
1558
+ if (!element.hasAttribute("style")) return "";
1559
+ const styleAttr = element.getAttribute("style");
1560
+ const textAlignMatch = styleAttr?.match(/text-align:\s*([^;]+)/i);
1561
+ if (textAlignMatch && textAlignMatch[1]) {
1562
+ const textAlign = textAlignMatch[1].trim();
1563
+ if (textAlign in TEXT_ALIGN_TO_FORMAT) {
1564
+ return TEXT_ALIGN_TO_FORMAT[textAlign];
1565
+ }
1566
+ }
1567
+ return "";
1568
+ }
1569
+
1570
+ // src/importFromHtml/HeadingNodeHandler.ts
1571
+ var TAG_HEADINGS = ["h1", "h2", "h3", "h4", "h5", "h6"];
1572
+ var HeadingNodeHandler2 = class extends NodeHandler2 {
1573
+ processNode(node) {
1574
+ if (!(node instanceof import_node_html_parser9.HTMLElement) || !TAG_HEADINGS.includes(node.tagName.toLowerCase())) {
1575
+ return null;
1576
+ }
1577
+ const headingNode = {
1578
+ type: "heading",
1579
+ version: 1,
1580
+ format: extractTextAlignment(node),
1581
+ tag: node.tagName.toLowerCase(),
1582
+ children: [],
1583
+ direction: "ltr",
1584
+ indent: 0
1585
+ };
1586
+ node.childNodes.forEach((child) => {
1587
+ const processedChildren = traverse2(child);
1588
+ headingNode.children.push(...processedChildren);
1589
+ });
1590
+ return headingNode;
1591
+ }
1592
+ };
1593
+
1594
+ // src/importFromHtml/HorizontalRuleNodeHandler.ts
1595
+ var import_node_html_parser10 = require("node-html-parser");
1523
1596
  var TAG_HR = "hr";
1524
1597
  var HorizontalRuleNodeHandler2 = class extends NodeHandler2 {
1525
1598
  processNode(node) {
1526
- if (!(node instanceof import_node_html_parser9.HTMLElement) || node.tagName !== TAG_HR.toUpperCase()) {
1599
+ if (!(node instanceof import_node_html_parser10.HTMLElement) || node.tagName !== TAG_HR.toUpperCase()) {
1527
1600
  return null;
1528
1601
  }
1529
1602
  const horizontalRuleNode = {
@@ -1535,11 +1608,11 @@ var HorizontalRuleNodeHandler2 = class extends NodeHandler2 {
1535
1608
  };
1536
1609
 
1537
1610
  // src/importFromHtml/ImageNodeHandler.ts
1538
- var import_node_html_parser10 = require("node-html-parser");
1611
+ var import_node_html_parser11 = require("node-html-parser");
1539
1612
  var TAG_IMG = "img";
1540
1613
  var ImageNodeHandler2 = class extends NodeHandler2 {
1541
1614
  processNode(node) {
1542
- if (!(node instanceof import_node_html_parser10.HTMLElement) || node.tagName !== TAG_IMG.toUpperCase()) {
1615
+ if (!(node instanceof import_node_html_parser11.HTMLElement) || node.tagName !== TAG_IMG.toUpperCase()) {
1543
1616
  return null;
1544
1617
  }
1545
1618
  return createImageNode(
@@ -1555,11 +1628,11 @@ var ImageNodeHandler2 = class extends NodeHandler2 {
1555
1628
 
1556
1629
  // src/importFromHtml/JournalEntryQuestionNodeHandler.ts
1557
1630
  var import_nanoid6 = require("nanoid");
1558
- var import_node_html_parser12 = require("node-html-parser");
1631
+ var import_node_html_parser13 = require("node-html-parser");
1559
1632
 
1560
1633
  // src/importFromHtml/createOnePerLineDistractorNode.ts
1561
1634
  var import_nanoid5 = require("nanoid");
1562
- var import_node_html_parser11 = require("node-html-parser");
1635
+ var import_node_html_parser12 = require("node-html-parser");
1563
1636
  function extractDistractorId(id) {
1564
1637
  if (!id) return null;
1565
1638
  const parts = id.split("|");
@@ -1572,7 +1645,7 @@ var createOnePerLineDistractorNode = (node) => {
1572
1645
  distractorEditor.editorState.root.children = [];
1573
1646
  let distractorId = null;
1574
1647
  distractors.forEach((distractor) => {
1575
- if (!(distractor instanceof import_node_html_parser11.HTMLElement)) return;
1648
+ if (!(distractor instanceof import_node_html_parser12.HTMLElement)) return;
1576
1649
  distractorId = distractorId ?? extractDistractorId(distractor.getAttribute("id"));
1577
1650
  distractorEditor.editorState.root.children.push(
1578
1651
  ...createNestedNodesFromHtml(distractor)
@@ -1590,7 +1663,7 @@ var createOnePerLineDistractorNode = (node) => {
1590
1663
  // src/importFromHtml/JournalEntryQuestionNodeHandler.ts
1591
1664
  var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1592
1665
  processNode(node) {
1593
- if (!(node instanceof import_node_html_parser12.HTMLElement) || node.tagName !== "x-journal-entry".toUpperCase())
1666
+ if (!(node instanceof import_node_html_parser13.HTMLElement) || node.tagName !== "x-journal-entry".toUpperCase())
1594
1667
  return null;
1595
1668
  const jsonNode = {
1596
1669
  id: node.getAttribute("id") ?? (0, import_nanoid6.nanoid)(),
@@ -1605,7 +1678,7 @@ var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1605
1678
  };
1606
1679
  const lineItems = node.querySelectorAll("x-line-item");
1607
1680
  lineItems.forEach((lineItem) => {
1608
- if (!(lineItem instanceof import_node_html_parser12.HTMLElement)) return;
1681
+ if (!(lineItem instanceof import_node_html_parser13.HTMLElement)) return;
1609
1682
  const accountElement = lineItem.querySelector("x-account");
1610
1683
  const debitElement = lineItem.querySelector("x-debit");
1611
1684
  const creditElement = lineItem.querySelector("x-credit");
@@ -1634,10 +1707,10 @@ var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1634
1707
  };
1635
1708
 
1636
1709
  // src/importFromHtml/LineBreakNodeHandler.ts
1637
- var import_node_html_parser13 = require("node-html-parser");
1710
+ var import_node_html_parser14 = require("node-html-parser");
1638
1711
  var LineBreakNodeHandler2 = class extends NodeHandler2 {
1639
1712
  processNode(node) {
1640
- if (!(node instanceof import_node_html_parser13.HTMLElement)) return null;
1713
+ if (!(node instanceof import_node_html_parser14.HTMLElement)) return null;
1641
1714
  if (node.tagName !== "BR") return null;
1642
1715
  return {
1643
1716
  type: "linebreak",
@@ -1647,11 +1720,11 @@ var LineBreakNodeHandler2 = class extends NodeHandler2 {
1647
1720
  };
1648
1721
 
1649
1722
  // src/importFromHtml/LinkNodeHandler.ts
1650
- var import_node_html_parser14 = require("node-html-parser");
1723
+ var import_node_html_parser15 = require("node-html-parser");
1651
1724
  var TAG_A = "a";
1652
1725
  var LinkNodeHandler2 = class extends NodeHandler2 {
1653
1726
  processNode(node) {
1654
- if (!(node instanceof import_node_html_parser14.HTMLElement) || node.tagName !== TAG_A.toUpperCase()) {
1727
+ if (!(node instanceof import_node_html_parser15.HTMLElement) || node.tagName !== TAG_A.toUpperCase()) {
1655
1728
  return null;
1656
1729
  }
1657
1730
  const url = node.getAttribute("href") || "";
@@ -1680,10 +1753,10 @@ var LinkNodeHandler2 = class extends NodeHandler2 {
1680
1753
  };
1681
1754
 
1682
1755
  // src/importFromHtml/ListItemNodeHandler.ts
1683
- var import_node_html_parser15 = require("node-html-parser");
1756
+ var import_node_html_parser16 = require("node-html-parser");
1684
1757
  var ListItemNodeHandler2 = class extends NodeHandler2 {
1685
1758
  processNode(node) {
1686
- if (!(node instanceof import_node_html_parser15.HTMLElement)) return null;
1759
+ if (!(node instanceof import_node_html_parser16.HTMLElement)) return null;
1687
1760
  if (node.tagName !== "LI") return null;
1688
1761
  const jsonNode = {
1689
1762
  type: "listitem",
@@ -1704,10 +1777,10 @@ var ListItemNodeHandler2 = class extends NodeHandler2 {
1704
1777
  };
1705
1778
 
1706
1779
  // src/importFromHtml/ListNodeHandler.ts
1707
- var import_node_html_parser16 = require("node-html-parser");
1780
+ var import_node_html_parser17 = require("node-html-parser");
1708
1781
  var ListNodeHandler2 = class extends NodeHandler2 {
1709
1782
  processNode(node) {
1710
- if (!(node instanceof import_node_html_parser16.HTMLElement)) return null;
1783
+ if (!(node instanceof import_node_html_parser17.HTMLElement)) return null;
1711
1784
  if (node.tagName !== "UL" && node.tagName !== "OL") return null;
1712
1785
  const tag = node.tagName.toLowerCase();
1713
1786
  const listType = tag === "ol" ? "number" : "bullet";
@@ -1725,7 +1798,7 @@ var ListNodeHandler2 = class extends NodeHandler2 {
1725
1798
  };
1726
1799
  let itemIndex = 1;
1727
1800
  node.childNodes.forEach((child) => {
1728
- if (child instanceof import_node_html_parser16.HTMLElement && child.tagName === "LI") {
1801
+ if (child instanceof import_node_html_parser17.HTMLElement && child.tagName === "LI") {
1729
1802
  const listItemNode = {
1730
1803
  type: "listitem",
1731
1804
  version: 1,
@@ -1750,10 +1823,10 @@ var ListNodeHandler2 = class extends NodeHandler2 {
1750
1823
 
1751
1824
  // src/importFromHtml/MatchingQuestionNodeHandler.ts
1752
1825
  var import_nanoid7 = require("nanoid");
1753
- var import_node_html_parser17 = require("node-html-parser");
1826
+ var import_node_html_parser18 = require("node-html-parser");
1754
1827
  var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1755
1828
  processNode(node) {
1756
- if (!(node instanceof import_node_html_parser17.HTMLElement) || node.tagName !== "x-matching".toUpperCase())
1829
+ if (!(node instanceof import_node_html_parser18.HTMLElement) || node.tagName !== "x-matching".toUpperCase())
1757
1830
  return null;
1758
1831
  const jsonNode = {
1759
1832
  id: node.getAttribute("id") ?? (0, import_nanoid7.nanoid)(),
@@ -1766,7 +1839,7 @@ var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1766
1839
  };
1767
1840
  const matches = node.querySelectorAll("x-match");
1768
1841
  matches.forEach((match) => {
1769
- if (!(match instanceof import_node_html_parser17.HTMLElement)) return;
1842
+ if (!(match instanceof import_node_html_parser18.HTMLElement)) return;
1770
1843
  const premise = match.querySelector("x-premise");
1771
1844
  const option = match.querySelector("x-option");
1772
1845
  if (!premise || !option) return;
@@ -1789,10 +1862,10 @@ var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1789
1862
 
1790
1863
  // src/importFromHtml/MultipleOptionQuestionNodeHandler.ts
1791
1864
  var import_nanoid8 = require("nanoid");
1792
- var import_node_html_parser18 = require("node-html-parser");
1865
+ var import_node_html_parser19 = require("node-html-parser");
1793
1866
  var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1794
1867
  processNode(node) {
1795
- if (!(node instanceof import_node_html_parser18.HTMLElement)) return null;
1868
+ if (!(node instanceof import_node_html_parser19.HTMLElement)) return null;
1796
1869
  if (node.tagName === "x-multiple-choice".toUpperCase())
1797
1870
  return this.processMultipleChoiceNode(node);
1798
1871
  else if (node.tagName === "x-multiple-answers".toUpperCase())
@@ -1832,7 +1905,7 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1832
1905
  processOptions(node, jsonNode) {
1833
1906
  const childNodes = node.childNodes;
1834
1907
  childNodes.forEach((child) => {
1835
- if (!(child instanceof import_node_html_parser18.HTMLElement)) return;
1908
+ if (!(child instanceof import_node_html_parser19.HTMLElement)) return;
1836
1909
  if (child.tagName !== "x-option".toUpperCase()) return;
1837
1910
  jsonNode.options.push({
1838
1911
  id: child.getAttribute("id") ?? (0, import_nanoid8.nanoid)(),
@@ -1844,48 +1917,28 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1844
1917
  };
1845
1918
 
1846
1919
  // src/importFromHtml/ParagraphNodeHandler.ts
1847
- var import_node_html_parser19 = require("node-html-parser");
1848
- var TEXT_ALIGN_TO_FORMAT = {
1849
- center: "center",
1850
- end: "end",
1851
- justify: "justify",
1852
- left: "left",
1853
- right: "right",
1854
- start: "start"
1855
- };
1920
+ var import_node_html_parser20 = require("node-html-parser");
1856
1921
  var ParagraphNodeHandler2 = class extends NodeHandler2 {
1857
- extractTextAlignment(element) {
1858
- if (!element.hasAttribute("style")) return "";
1859
- const styleAttr = element.getAttribute("style");
1860
- const textAlignMatch = styleAttr?.match(/text-align:\s*([^;]+)/i);
1861
- if (textAlignMatch && textAlignMatch[1]) {
1862
- const textAlign = textAlignMatch[1].trim();
1863
- if (textAlign in TEXT_ALIGN_TO_FORMAT) {
1864
- return TEXT_ALIGN_TO_FORMAT[textAlign];
1865
- }
1866
- }
1867
- return "";
1868
- }
1869
1922
  processImageNode(node) {
1870
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser19.HTMLElement && node.childNodes[0].tagName === "IMG") {
1923
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser20.HTMLElement && node.childNodes[0].tagName === "IMG") {
1871
1924
  return traverse2(node.childNodes[0]);
1872
1925
  }
1873
1926
  return null;
1874
1927
  }
1875
1928
  processSpanImageNode(node) {
1876
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser19.HTMLElement && node.childNodes[0].tagName === "SPAN" && node.childNodes[0].childNodes.length === 1 && node.childNodes[0].childNodes[0] instanceof import_node_html_parser19.HTMLElement && node.childNodes[0].childNodes[0].tagName === "IMG") {
1929
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser20.HTMLElement && node.childNodes[0].tagName === "SPAN" && node.childNodes[0].childNodes.length === 1 && node.childNodes[0].childNodes[0] instanceof import_node_html_parser20.HTMLElement && node.childNodes[0].childNodes[0].tagName === "IMG") {
1877
1930
  return traverse2(node.childNodes[0].childNodes[0]);
1878
1931
  }
1879
1932
  return null;
1880
1933
  }
1881
1934
  processNode(node) {
1882
- if (!(node instanceof import_node_html_parser19.HTMLElement)) return null;
1935
+ if (!(node instanceof import_node_html_parser20.HTMLElement)) return null;
1883
1936
  if (node.tagName !== "P") return null;
1884
1937
  const imageNode = this.processImageNode(node) ?? this.processSpanImageNode(node);
1885
1938
  if (imageNode) return imageNode;
1886
1939
  const jsonNode = createEmptyParagraphNode();
1887
- jsonNode.format = this.extractTextAlignment(node);
1888
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser19.HTMLElement && node.childNodes[0].tagName === "BR")
1940
+ jsonNode.format = extractTextAlignment(node);
1941
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser20.HTMLElement && node.childNodes[0].tagName === "BR")
1889
1942
  return jsonNode;
1890
1943
  node.childNodes.forEach((child) => {
1891
1944
  const processedChildren = traverse2(child);
@@ -1897,10 +1950,10 @@ var ParagraphNodeHandler2 = class extends NodeHandler2 {
1897
1950
 
1898
1951
  // src/importFromHtml/ShortAnswerQuestionNodeHandler.ts
1899
1952
  var import_nanoid9 = require("nanoid");
1900
- var import_node_html_parser20 = require("node-html-parser");
1953
+ var import_node_html_parser21 = require("node-html-parser");
1901
1954
  var ShortAnswerQuestionNodeHandler2 = class extends NodeHandler2 {
1902
1955
  processNode(node) {
1903
- if (!(node instanceof import_node_html_parser20.HTMLElement) || node.tagName !== "x-short-answer".toUpperCase())
1956
+ if (!(node instanceof import_node_html_parser21.HTMLElement) || node.tagName !== "x-short-answer".toUpperCase())
1904
1957
  return null;
1905
1958
  return {
1906
1959
  id: node.getAttribute("id") ?? (0, import_nanoid9.nanoid)(),
@@ -1916,44 +1969,40 @@ var ShortAnswerQuestionNodeHandler2 = class extends NodeHandler2 {
1916
1969
  };
1917
1970
 
1918
1971
  // src/importFromHtml/SimulationQuestionNodeHandler.ts
1919
- var import_node_html_parser21 = require("node-html-parser");
1972
+ var import_node_html_parser22 = require("node-html-parser");
1920
1973
  var TAG_X_SIMULATION = "x-simulation";
1921
1974
  var TAG_X_SYSTEM_MESSAGE2 = "x-ai-system-message";
1975
+ var TAG_X_COMMENT_INSTRUCTIONS = "x-comment-instructions";
1922
1976
  var TAG_X_STEP2_INSTRUCTIONS = "x-step2-instructions";
1977
+ var findFirstNonEmptyInnerHtml = (root, elementNames) => elementNames.map((name) => root.querySelector(name)).find((el) => el?.innerHTML.trim().length)?.innerHTML.trim() ?? null;
1923
1978
  var SimulationQuestionNodeHandler2 = class extends NodeHandler2 {
1924
1979
  processNode(node) {
1925
- if (!(node instanceof import_node_html_parser21.HTMLElement) || node.tagName !== TAG_X_SIMULATION.toUpperCase()) {
1980
+ if (!(node instanceof import_node_html_parser22.HTMLElement) || node.tagName !== TAG_X_SIMULATION.toUpperCase()) {
1926
1981
  return null;
1927
1982
  }
1928
1983
  const jsonNode = {
1929
1984
  id: node.getAttribute("id") || "",
1930
1985
  points: Number(node.getAttribute("data-x-points") || 0),
1931
1986
  aiChatModel: node.getAttribute("data-x-ai-chat-model") || null,
1932
- step2Instructions: "",
1933
- aiSystemMessage: "",
1987
+ aiSystemMessage: findFirstNonEmptyInnerHtml(node, [TAG_X_SYSTEM_MESSAGE2]) ?? "",
1988
+ disableChat: node.getAttribute("data-x-disable-chat") === "true",
1989
+ commentInstructions: findFirstNonEmptyInnerHtml(node, [
1990
+ TAG_X_COMMENT_INSTRUCTIONS,
1991
+ TAG_X_STEP2_INSTRUCTIONS
1992
+ ]) ?? "",
1934
1993
  type: "simulation-question",
1935
1994
  version: 1
1936
1995
  };
1937
- const systemMessageElement = node.querySelector(
1938
- TAG_X_SYSTEM_MESSAGE2
1939
- );
1940
- if (systemMessageElement)
1941
- jsonNode.aiSystemMessage = systemMessageElement.innerHTML;
1942
- const step2InstructionsElement = node.querySelector(
1943
- TAG_X_STEP2_INSTRUCTIONS
1944
- );
1945
- if (step2InstructionsElement)
1946
- jsonNode.step2Instructions = step2InstructionsElement.innerHTML;
1947
1996
  return jsonNode;
1948
1997
  }
1949
1998
  };
1950
1999
 
1951
2000
  // src/importFromHtml/SpanNodeHandler.ts
1952
- var import_node_html_parser22 = require("node-html-parser");
1953
- var TextNode = import_node_html_parser22.parse.TextNode;
2001
+ var import_node_html_parser23 = require("node-html-parser");
2002
+ var TextNode = import_node_html_parser23.parse.TextNode;
1954
2003
  var SpanNodeHandler = class extends NodeHandler2 {
1955
2004
  processNode(node) {
1956
- if (!(node instanceof import_node_html_parser22.HTMLElement) || node.tagName !== "SPAN")
2005
+ if (!(node instanceof import_node_html_parser23.HTMLElement) || node.tagName !== "SPAN")
1957
2006
  return null;
1958
2007
  const styleAttr = node.getAttribute("style") || "";
1959
2008
  if (node.childNodes.length === 1 && node.childNodes[0] instanceof TextNode) {
@@ -2015,7 +2064,7 @@ var SpanNodeHandler = class extends NodeHandler2 {
2015
2064
  };
2016
2065
 
2017
2066
  // src/importFromHtml/TableCellNodeHandler.ts
2018
- var import_node_html_parser23 = require("node-html-parser");
2067
+ var import_node_html_parser24 = require("node-html-parser");
2019
2068
 
2020
2069
  // src/utils/styleUtils.ts
2021
2070
  var extractStyleValue = (styleAttr, property, isNumeric = false, unit = "") => {
@@ -2064,7 +2113,7 @@ function createEmptyTableCellNode(isHeader = false) {
2064
2113
 
2065
2114
  // src/importFromHtml/TableCellNodeHandler.ts
2066
2115
  var isHtmlTableCellElement = (node) => {
2067
- return node instanceof import_node_html_parser23.HTMLElement && (node.tagName === "TD" || node.tagName === "TH");
2116
+ return node instanceof import_node_html_parser24.HTMLElement && (node.tagName === "TD" || node.tagName === "TH");
2068
2117
  };
2069
2118
  var TableCellNodeHandler2 = class extends NodeHandler2 {
2070
2119
  processNode(node) {
@@ -2106,10 +2155,10 @@ var TableCellNodeHandler2 = class extends NodeHandler2 {
2106
2155
  };
2107
2156
 
2108
2157
  // src/importFromHtml/TableNodeHandler.ts
2109
- var import_node_html_parser24 = require("node-html-parser");
2158
+ var import_node_html_parser25 = require("node-html-parser");
2110
2159
  var REFERENCE_TABLE_WIDTH = 720;
2111
2160
  var MINIMUM_REFERENCE_TABLE_WIDTH = 500;
2112
- var isHtmlTableElement = (node) => node instanceof import_node_html_parser24.HTMLElement && node.tagName === "TABLE";
2161
+ var isHtmlTableElement = (node) => node instanceof import_node_html_parser25.HTMLElement && node.tagName === "TABLE";
2113
2162
  var TableNodeHandler2 = class extends NodeHandler2 {
2114
2163
  processNode(node) {
2115
2164
  if (!isHtmlTableElement(node)) return null;
@@ -2264,9 +2313,9 @@ var TableNodeHandler2 = class extends NodeHandler2 {
2264
2313
  };
2265
2314
 
2266
2315
  // src/importFromHtml/TableRowNodeHandler.ts
2267
- var import_node_html_parser25 = require("node-html-parser");
2316
+ var import_node_html_parser26 = require("node-html-parser");
2268
2317
  var isHtmlTableRowElement = (node) => {
2269
- return node instanceof import_node_html_parser25.HTMLElement && node.tagName === "TR";
2318
+ return node instanceof import_node_html_parser26.HTMLElement && node.tagName === "TR";
2270
2319
  };
2271
2320
  var TableRowNodeHandler2 = class extends NodeHandler2 {
2272
2321
  processNode(node) {
@@ -2289,8 +2338,8 @@ var TableRowNodeHandler2 = class extends NodeHandler2 {
2289
2338
  };
2290
2339
 
2291
2340
  // src/importFromHtml/TextNodeHandler.ts
2292
- var import_node_html_parser26 = require("node-html-parser");
2293
- var TextNode2 = import_node_html_parser26.parse.TextNode;
2341
+ var import_node_html_parser27 = require("node-html-parser");
2342
+ var TextNode2 = import_node_html_parser27.parse.TextNode;
2294
2343
  var TextNodeHandler2 = class extends NodeHandler2 {
2295
2344
  processNode(node) {
2296
2345
  if (!(node instanceof TextNode2)) return null;
@@ -2309,10 +2358,10 @@ var TextNodeHandler2 = class extends NodeHandler2 {
2309
2358
  };
2310
2359
 
2311
2360
  // src/importFromHtml/VariableNodeHandler.ts
2312
- var import_node_html_parser27 = require("node-html-parser");
2361
+ var import_node_html_parser28 = require("node-html-parser");
2313
2362
  var VariableNodeHandler2 = class extends NodeHandler2 {
2314
2363
  processNode(node) {
2315
- if (!(node instanceof import_node_html_parser27.HTMLElement) || !node.tagName) return null;
2364
+ if (!(node instanceof import_node_html_parser28.HTMLElement) || !node.tagName) return null;
2316
2365
  if (node.tagName !== "x-param".toUpperCase()) return null;
2317
2366
  return {
2318
2367
  variableName: node.getAttribute("data-x-name") || "undefined",
@@ -2325,7 +2374,7 @@ var VariableNodeHandler2 = class extends NodeHandler2 {
2325
2374
 
2326
2375
  // src/importFromHtml/traverse.ts
2327
2376
  var builder2 = new NodeHandlerChainBuilder();
2328
- var nodeHandlerChain2 = builder2.addHandler(CustomQuestionNodeHandler2).addHandler(DivNodeHandler).addHandler(EssayQuestionNodeHandler2).addHandler(FillInTheBlankQuestionNodeHandler2).addHandler(FillInTheBlankSpaceNodeHandler2).addHandler(FinancialStatementQuestionNodeHandler2).addHandler(FormattedNodeHandler).addHandler(ImageNodeHandler2).addHandler(HorizontalRuleNodeHandler2).addHandler(JournalEntryQuestionNodeHandler2).addHandler(LineBreakNodeHandler2).addHandler(LinkNodeHandler2).addHandler(ListNodeHandler2).addHandler(ListItemNodeHandler2).addHandler(MatchingQuestionNodeHandler2).addHandler(MultipleOptionQuestionNodeHandler2).addHandler(ParagraphNodeHandler2).addHandler(ShortAnswerQuestionNodeHandler2).addHandler(SimulationQuestionNodeHandler2).addHandler(SpanNodeHandler).addHandler(TableCellNodeHandler2).addHandler(TableNodeHandler2).addHandler(TableRowNodeHandler2).addHandler(TextNodeHandler2).addHandler(VariableNodeHandler2).build();
2377
+ var nodeHandlerChain2 = builder2.addHandler(CustomQuestionNodeHandler2).addHandler(DivNodeHandler).addHandler(EssayQuestionNodeHandler2).addHandler(FillInTheBlankQuestionNodeHandler2).addHandler(FillInTheBlankSpaceNodeHandler2).addHandler(FinancialStatementQuestionNodeHandler2).addHandler(FormattedNodeHandler).addHandler(ImageNodeHandler2).addHandler(HeadingNodeHandler2).addHandler(HorizontalRuleNodeHandler2).addHandler(JournalEntryQuestionNodeHandler2).addHandler(LineBreakNodeHandler2).addHandler(LinkNodeHandler2).addHandler(ListNodeHandler2).addHandler(ListItemNodeHandler2).addHandler(MatchingQuestionNodeHandler2).addHandler(MultipleOptionQuestionNodeHandler2).addHandler(ParagraphNodeHandler2).addHandler(ShortAnswerQuestionNodeHandler2).addHandler(SimulationQuestionNodeHandler2).addHandler(SpanNodeHandler).addHandler(TableCellNodeHandler2).addHandler(TableNodeHandler2).addHandler(TableRowNodeHandler2).addHandler(TextNodeHandler2).addHandler(VariableNodeHandler2).build();
2329
2378
  function traverse2(node) {
2330
2379
  const result = nodeHandlerChain2.handle(node);
2331
2380
  if (result === null) return [];
@@ -2343,7 +2392,7 @@ function processChildren(node) {
2343
2392
  return result;
2344
2393
  }
2345
2394
  function processHtml(html) {
2346
- const root = (0, import_node_html_parser28.parse)(html);
2395
+ const root = (0, import_node_html_parser29.parse)(html);
2347
2396
  return processChildren(root);
2348
2397
  }
2349
2398
  function importFromHtml(html) {
package/dist/index.mjs CHANGED
@@ -233,6 +233,37 @@ var FinancialStatementQuestionNodeHandler = class extends NodeHandler {
233
233
  }
234
234
  };
235
235
 
236
+ // src/typeGuards/isSerializedHeadingNode.ts
237
+ var isSerializedHeadingNode = (node) => {
238
+ return node?.type === "heading";
239
+ };
240
+
241
+ // src/exportToHtml/elementTypeToFormat.ts
242
+ var ELEMENT_TYPE_TO_FORMAT = {
243
+ center: "center",
244
+ end: "end",
245
+ justify: "justify",
246
+ left: "left",
247
+ right: "right",
248
+ start: "start"
249
+ };
250
+
251
+ // src/exportToHtml/HeadingNodeHandler.ts
252
+ var HeadingNodeHandler = class extends NodeHandler {
253
+ processNode(node) {
254
+ if (!isSerializedHeadingNode(node)) return null;
255
+ const children = [];
256
+ node.children.forEach((child) => {
257
+ const childString = traverse(child);
258
+ if (childString) {
259
+ children.push(childString);
260
+ }
261
+ });
262
+ const attribute = node.format ? ` style="text-align: ${ELEMENT_TYPE_TO_FORMAT[node.format]};"` : "";
263
+ return `<${node.tag}${attribute}>${children.join("")}</${node.tag}>`;
264
+ }
265
+ };
266
+
236
267
  // src/typeGuards/isSerializedHorizontalRuleNode.ts
237
268
  var isSerializedHorizontalRuleNode = (node) => {
238
269
  return node?.type === "horizontalrule";
@@ -586,14 +617,6 @@ function isSerializedTableCellNode(node) {
586
617
  }
587
618
 
588
619
  // src/exportToHtml/ParagraphNodeHandler.ts
589
- var ELEMENT_TYPE_TO_FORMAT = {
590
- center: "center",
591
- end: "end",
592
- justify: "justify",
593
- left: "left",
594
- right: "right",
595
- start: "start"
596
- };
597
620
  var ParagraphNodeHandler = class extends NodeHandler {
598
621
  shouldAvoidParagraphWrap(node) {
599
622
  if (node === void 0) return false;
@@ -659,8 +682,9 @@ var SimulationQuestionNodeHandler = class extends NodeHandler {
659
682
  if (!isSerializedSimulationQuestionNode(node)) return null;
660
683
  const aiChatModelAttr = node.aiChatModel ? ` data-x-ai-chat-model="${node.aiChatModel}"` : "";
661
684
  const aiSystemMessage = node.aiSystemMessage ? `<x-ai-system-message>${node.aiSystemMessage}</x-ai-system-message>` : "";
662
- const step2Instructions = node.step2Instructions ? `<x-step2-instructions>${node.step2Instructions}</x-step2-instructions>` : "";
663
- return `<x-simulation id="${node.id}" data-x-prompt data-x-points="${node.points}"${aiChatModelAttr}>${aiSystemMessage}${step2Instructions}</x-simulation>`;
685
+ const disableChatAttr = node.disableChat ? ` data-x-disable-chat="true"` : "";
686
+ const commentInstructions = node.commentInstructions ? `<x-comment-instructions>${node.commentInstructions}</x-comment-instructions>` : "";
687
+ return `<x-simulation id="${node.id}" data-x-prompt data-x-points="${node.points}"${aiChatModelAttr}${disableChatAttr}>${aiSystemMessage}${commentInstructions}</x-simulation>`;
664
688
  }
665
689
  };
666
690
 
@@ -904,7 +928,7 @@ var VariableNodeHandler = class extends NodeHandler {
904
928
 
905
929
  // src/exportToHtml/traverse.ts
906
930
  var builder = new NodeHandlerChainBuilder();
907
- var nodeHandlerChain = builder.addHandler(CustomQuestionNodeHandler).addHandler(EssayQuestionNodeHandler).addHandler(FillInTheBlankQuestionNodeHandler).addHandler(FillInTheBlankSpaceNodeHandler).addHandler(FinancialStatementQuestionNodeHandler).addHandler(HorizontalRuleNodeHandler).addHandler(ImageNodeHandler).addHandler(JournalEntryQuestionNodeHandler).addHandler(LineBreakNodeHandler).addHandler(LinkNodeHandler).addHandler(ListNodeHandler).addHandler(ListItemNodeHandler).addHandler(MatchingQuestionNodeHandler).addHandler(MultipleOptionQuestionNodeHandler).addHandler(ParagraphNodeHandler).addHandler(ShortAnswerQuestionNodeHandler).addHandler(SimulationQuestionNodeHandler).addHandler(TableCellNodeHandler).addHandler(TableNodeHandler).addHandler(TableRowNodeHandler).addHandler(TextNodeHandler).addHandler(VariableNodeHandler).build();
931
+ var nodeHandlerChain = builder.addHandler(CustomQuestionNodeHandler).addHandler(EssayQuestionNodeHandler).addHandler(FillInTheBlankQuestionNodeHandler).addHandler(FillInTheBlankSpaceNodeHandler).addHandler(FinancialStatementQuestionNodeHandler).addHandler(HeadingNodeHandler).addHandler(HorizontalRuleNodeHandler).addHandler(ImageNodeHandler).addHandler(JournalEntryQuestionNodeHandler).addHandler(LineBreakNodeHandler).addHandler(LinkNodeHandler).addHandler(ListNodeHandler).addHandler(ListItemNodeHandler).addHandler(MatchingQuestionNodeHandler).addHandler(MultipleOptionQuestionNodeHandler).addHandler(ParagraphNodeHandler).addHandler(ShortAnswerQuestionNodeHandler).addHandler(SimulationQuestionNodeHandler).addHandler(TableCellNodeHandler).addHandler(TableNodeHandler).addHandler(TableRowNodeHandler).addHandler(TextNodeHandler).addHandler(VariableNodeHandler).build();
908
932
  var traverse = (node, metadata) => {
909
933
  return nodeHandlerChain.handle(node, metadata);
910
934
  };
@@ -1491,12 +1515,61 @@ var FormattedNodeHandler = class extends NodeHandler2 {
1491
1515
  }
1492
1516
  };
1493
1517
 
1494
- // src/importFromHtml/HorizontalRuleNodeHandler.ts
1518
+ // src/importFromHtml/HeadingNodeHandler.ts
1495
1519
  import { HTMLElement as HTMLElement9 } from "node-html-parser";
1520
+
1521
+ // src/importFromHtml/extractTextAlignment.ts
1522
+ var TEXT_ALIGN_TO_FORMAT = {
1523
+ center: "center",
1524
+ end: "end",
1525
+ justify: "justify",
1526
+ left: "left",
1527
+ right: "right",
1528
+ start: "start"
1529
+ };
1530
+ function extractTextAlignment(element) {
1531
+ if (!element.hasAttribute("style")) return "";
1532
+ const styleAttr = element.getAttribute("style");
1533
+ const textAlignMatch = styleAttr?.match(/text-align:\s*([^;]+)/i);
1534
+ if (textAlignMatch && textAlignMatch[1]) {
1535
+ const textAlign = textAlignMatch[1].trim();
1536
+ if (textAlign in TEXT_ALIGN_TO_FORMAT) {
1537
+ return TEXT_ALIGN_TO_FORMAT[textAlign];
1538
+ }
1539
+ }
1540
+ return "";
1541
+ }
1542
+
1543
+ // src/importFromHtml/HeadingNodeHandler.ts
1544
+ var TAG_HEADINGS = ["h1", "h2", "h3", "h4", "h5", "h6"];
1545
+ var HeadingNodeHandler2 = class extends NodeHandler2 {
1546
+ processNode(node) {
1547
+ if (!(node instanceof HTMLElement9) || !TAG_HEADINGS.includes(node.tagName.toLowerCase())) {
1548
+ return null;
1549
+ }
1550
+ const headingNode = {
1551
+ type: "heading",
1552
+ version: 1,
1553
+ format: extractTextAlignment(node),
1554
+ tag: node.tagName.toLowerCase(),
1555
+ children: [],
1556
+ direction: "ltr",
1557
+ indent: 0
1558
+ };
1559
+ node.childNodes.forEach((child) => {
1560
+ const processedChildren = traverse2(child);
1561
+ headingNode.children.push(...processedChildren);
1562
+ });
1563
+ return headingNode;
1564
+ }
1565
+ };
1566
+
1567
+ // src/importFromHtml/HorizontalRuleNodeHandler.ts
1568
+ import { HTMLElement as HTMLElement10 } from "node-html-parser";
1496
1569
  var TAG_HR = "hr";
1497
1570
  var HorizontalRuleNodeHandler2 = class extends NodeHandler2 {
1498
1571
  processNode(node) {
1499
- if (!(node instanceof HTMLElement9) || node.tagName !== TAG_HR.toUpperCase()) {
1572
+ if (!(node instanceof HTMLElement10) || node.tagName !== TAG_HR.toUpperCase()) {
1500
1573
  return null;
1501
1574
  }
1502
1575
  const horizontalRuleNode = {
@@ -1508,11 +1581,11 @@ var HorizontalRuleNodeHandler2 = class extends NodeHandler2 {
1508
1581
  };
1509
1582
 
1510
1583
  // src/importFromHtml/ImageNodeHandler.ts
1511
- import { HTMLElement as HTMLElement10 } from "node-html-parser";
1584
+ import { HTMLElement as HTMLElement11 } from "node-html-parser";
1512
1585
  var TAG_IMG = "img";
1513
1586
  var ImageNodeHandler2 = class extends NodeHandler2 {
1514
1587
  processNode(node) {
1515
- if (!(node instanceof HTMLElement10) || node.tagName !== TAG_IMG.toUpperCase()) {
1588
+ if (!(node instanceof HTMLElement11) || node.tagName !== TAG_IMG.toUpperCase()) {
1516
1589
  return null;
1517
1590
  }
1518
1591
  return createImageNode(
@@ -1528,11 +1601,11 @@ var ImageNodeHandler2 = class extends NodeHandler2 {
1528
1601
 
1529
1602
  // src/importFromHtml/JournalEntryQuestionNodeHandler.ts
1530
1603
  import { nanoid as nanoid6 } from "nanoid";
1531
- import { HTMLElement as HTMLElement12 } from "node-html-parser";
1604
+ import { HTMLElement as HTMLElement13 } from "node-html-parser";
1532
1605
 
1533
1606
  // src/importFromHtml/createOnePerLineDistractorNode.ts
1534
1607
  import { nanoid as nanoid5 } from "nanoid";
1535
- import { HTMLElement as HTMLElement11 } from "node-html-parser";
1608
+ import { HTMLElement as HTMLElement12 } from "node-html-parser";
1536
1609
  function extractDistractorId(id) {
1537
1610
  if (!id) return null;
1538
1611
  const parts = id.split("|");
@@ -1545,7 +1618,7 @@ var createOnePerLineDistractorNode = (node) => {
1545
1618
  distractorEditor.editorState.root.children = [];
1546
1619
  let distractorId = null;
1547
1620
  distractors.forEach((distractor) => {
1548
- if (!(distractor instanceof HTMLElement11)) return;
1621
+ if (!(distractor instanceof HTMLElement12)) return;
1549
1622
  distractorId = distractorId ?? extractDistractorId(distractor.getAttribute("id"));
1550
1623
  distractorEditor.editorState.root.children.push(
1551
1624
  ...createNestedNodesFromHtml(distractor)
@@ -1563,7 +1636,7 @@ var createOnePerLineDistractorNode = (node) => {
1563
1636
  // src/importFromHtml/JournalEntryQuestionNodeHandler.ts
1564
1637
  var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1565
1638
  processNode(node) {
1566
- if (!(node instanceof HTMLElement12) || node.tagName !== "x-journal-entry".toUpperCase())
1639
+ if (!(node instanceof HTMLElement13) || node.tagName !== "x-journal-entry".toUpperCase())
1567
1640
  return null;
1568
1641
  const jsonNode = {
1569
1642
  id: node.getAttribute("id") ?? nanoid6(),
@@ -1578,7 +1651,7 @@ var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1578
1651
  };
1579
1652
  const lineItems = node.querySelectorAll("x-line-item");
1580
1653
  lineItems.forEach((lineItem) => {
1581
- if (!(lineItem instanceof HTMLElement12)) return;
1654
+ if (!(lineItem instanceof HTMLElement13)) return;
1582
1655
  const accountElement = lineItem.querySelector("x-account");
1583
1656
  const debitElement = lineItem.querySelector("x-debit");
1584
1657
  const creditElement = lineItem.querySelector("x-credit");
@@ -1607,10 +1680,10 @@ var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1607
1680
  };
1608
1681
 
1609
1682
  // src/importFromHtml/LineBreakNodeHandler.ts
1610
- import { HTMLElement as HTMLElement13 } from "node-html-parser";
1683
+ import { HTMLElement as HTMLElement14 } from "node-html-parser";
1611
1684
  var LineBreakNodeHandler2 = class extends NodeHandler2 {
1612
1685
  processNode(node) {
1613
- if (!(node instanceof HTMLElement13)) return null;
1686
+ if (!(node instanceof HTMLElement14)) return null;
1614
1687
  if (node.tagName !== "BR") return null;
1615
1688
  return {
1616
1689
  type: "linebreak",
@@ -1620,11 +1693,11 @@ var LineBreakNodeHandler2 = class extends NodeHandler2 {
1620
1693
  };
1621
1694
 
1622
1695
  // src/importFromHtml/LinkNodeHandler.ts
1623
- import { HTMLElement as HTMLElement14 } from "node-html-parser";
1696
+ import { HTMLElement as HTMLElement15 } from "node-html-parser";
1624
1697
  var TAG_A = "a";
1625
1698
  var LinkNodeHandler2 = class extends NodeHandler2 {
1626
1699
  processNode(node) {
1627
- if (!(node instanceof HTMLElement14) || node.tagName !== TAG_A.toUpperCase()) {
1700
+ if (!(node instanceof HTMLElement15) || node.tagName !== TAG_A.toUpperCase()) {
1628
1701
  return null;
1629
1702
  }
1630
1703
  const url = node.getAttribute("href") || "";
@@ -1653,10 +1726,10 @@ var LinkNodeHandler2 = class extends NodeHandler2 {
1653
1726
  };
1654
1727
 
1655
1728
  // src/importFromHtml/ListItemNodeHandler.ts
1656
- import { HTMLElement as HTMLElement15 } from "node-html-parser";
1729
+ import { HTMLElement as HTMLElement16 } from "node-html-parser";
1657
1730
  var ListItemNodeHandler2 = class extends NodeHandler2 {
1658
1731
  processNode(node) {
1659
- if (!(node instanceof HTMLElement15)) return null;
1732
+ if (!(node instanceof HTMLElement16)) return null;
1660
1733
  if (node.tagName !== "LI") return null;
1661
1734
  const jsonNode = {
1662
1735
  type: "listitem",
@@ -1677,10 +1750,10 @@ var ListItemNodeHandler2 = class extends NodeHandler2 {
1677
1750
  };
1678
1751
 
1679
1752
  // src/importFromHtml/ListNodeHandler.ts
1680
- import { HTMLElement as HTMLElement16 } from "node-html-parser";
1753
+ import { HTMLElement as HTMLElement17 } from "node-html-parser";
1681
1754
  var ListNodeHandler2 = class extends NodeHandler2 {
1682
1755
  processNode(node) {
1683
- if (!(node instanceof HTMLElement16)) return null;
1756
+ if (!(node instanceof HTMLElement17)) return null;
1684
1757
  if (node.tagName !== "UL" && node.tagName !== "OL") return null;
1685
1758
  const tag = node.tagName.toLowerCase();
1686
1759
  const listType = tag === "ol" ? "number" : "bullet";
@@ -1698,7 +1771,7 @@ var ListNodeHandler2 = class extends NodeHandler2 {
1698
1771
  };
1699
1772
  let itemIndex = 1;
1700
1773
  node.childNodes.forEach((child) => {
1701
- if (child instanceof HTMLElement16 && child.tagName === "LI") {
1774
+ if (child instanceof HTMLElement17 && child.tagName === "LI") {
1702
1775
  const listItemNode = {
1703
1776
  type: "listitem",
1704
1777
  version: 1,
@@ -1723,10 +1796,10 @@ var ListNodeHandler2 = class extends NodeHandler2 {
1723
1796
 
1724
1797
  // src/importFromHtml/MatchingQuestionNodeHandler.ts
1725
1798
  import { nanoid as nanoid7 } from "nanoid";
1726
- import { HTMLElement as HTMLElement17 } from "node-html-parser";
1799
+ import { HTMLElement as HTMLElement18 } from "node-html-parser";
1727
1800
  var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1728
1801
  processNode(node) {
1729
- if (!(node instanceof HTMLElement17) || node.tagName !== "x-matching".toUpperCase())
1802
+ if (!(node instanceof HTMLElement18) || node.tagName !== "x-matching".toUpperCase())
1730
1803
  return null;
1731
1804
  const jsonNode = {
1732
1805
  id: node.getAttribute("id") ?? nanoid7(),
@@ -1739,7 +1812,7 @@ var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1739
1812
  };
1740
1813
  const matches = node.querySelectorAll("x-match");
1741
1814
  matches.forEach((match) => {
1742
- if (!(match instanceof HTMLElement17)) return;
1815
+ if (!(match instanceof HTMLElement18)) return;
1743
1816
  const premise = match.querySelector("x-premise");
1744
1817
  const option = match.querySelector("x-option");
1745
1818
  if (!premise || !option) return;
@@ -1762,10 +1835,10 @@ var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1762
1835
 
1763
1836
  // src/importFromHtml/MultipleOptionQuestionNodeHandler.ts
1764
1837
  import { nanoid as nanoid8 } from "nanoid";
1765
- import { HTMLElement as HTMLElement18 } from "node-html-parser";
1838
+ import { HTMLElement as HTMLElement19 } from "node-html-parser";
1766
1839
  var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1767
1840
  processNode(node) {
1768
- if (!(node instanceof HTMLElement18)) return null;
1841
+ if (!(node instanceof HTMLElement19)) return null;
1769
1842
  if (node.tagName === "x-multiple-choice".toUpperCase())
1770
1843
  return this.processMultipleChoiceNode(node);
1771
1844
  else if (node.tagName === "x-multiple-answers".toUpperCase())
@@ -1805,7 +1878,7 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1805
1878
  processOptions(node, jsonNode) {
1806
1879
  const childNodes = node.childNodes;
1807
1880
  childNodes.forEach((child) => {
1808
- if (!(child instanceof HTMLElement18)) return;
1881
+ if (!(child instanceof HTMLElement19)) return;
1809
1882
  if (child.tagName !== "x-option".toUpperCase()) return;
1810
1883
  jsonNode.options.push({
1811
1884
  id: child.getAttribute("id") ?? nanoid8(),
@@ -1817,48 +1890,28 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1817
1890
  };
1818
1891
 
1819
1892
  // src/importFromHtml/ParagraphNodeHandler.ts
1820
- import { HTMLElement as HTMLElement19 } from "node-html-parser";
1821
- var TEXT_ALIGN_TO_FORMAT = {
1822
- center: "center",
1823
- end: "end",
1824
- justify: "justify",
1825
- left: "left",
1826
- right: "right",
1827
- start: "start"
1828
- };
1893
+ import { HTMLElement as HTMLElement20 } from "node-html-parser";
1829
1894
  var ParagraphNodeHandler2 = class extends NodeHandler2 {
1830
- extractTextAlignment(element) {
1831
- if (!element.hasAttribute("style")) return "";
1832
- const styleAttr = element.getAttribute("style");
1833
- const textAlignMatch = styleAttr?.match(/text-align:\s*([^;]+)/i);
1834
- if (textAlignMatch && textAlignMatch[1]) {
1835
- const textAlign = textAlignMatch[1].trim();
1836
- if (textAlign in TEXT_ALIGN_TO_FORMAT) {
1837
- return TEXT_ALIGN_TO_FORMAT[textAlign];
1838
- }
1839
- }
1840
- return "";
1841
- }
1842
1895
  processImageNode(node) {
1843
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement19 && node.childNodes[0].tagName === "IMG") {
1896
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement20 && node.childNodes[0].tagName === "IMG") {
1844
1897
  return traverse2(node.childNodes[0]);
1845
1898
  }
1846
1899
  return null;
1847
1900
  }
1848
1901
  processSpanImageNode(node) {
1849
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement19 && node.childNodes[0].tagName === "SPAN" && node.childNodes[0].childNodes.length === 1 && node.childNodes[0].childNodes[0] instanceof HTMLElement19 && node.childNodes[0].childNodes[0].tagName === "IMG") {
1902
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement20 && node.childNodes[0].tagName === "SPAN" && node.childNodes[0].childNodes.length === 1 && node.childNodes[0].childNodes[0] instanceof HTMLElement20 && node.childNodes[0].childNodes[0].tagName === "IMG") {
1850
1903
  return traverse2(node.childNodes[0].childNodes[0]);
1851
1904
  }
1852
1905
  return null;
1853
1906
  }
1854
1907
  processNode(node) {
1855
- if (!(node instanceof HTMLElement19)) return null;
1908
+ if (!(node instanceof HTMLElement20)) return null;
1856
1909
  if (node.tagName !== "P") return null;
1857
1910
  const imageNode = this.processImageNode(node) ?? this.processSpanImageNode(node);
1858
1911
  if (imageNode) return imageNode;
1859
1912
  const jsonNode = createEmptyParagraphNode();
1860
- jsonNode.format = this.extractTextAlignment(node);
1861
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement19 && node.childNodes[0].tagName === "BR")
1913
+ jsonNode.format = extractTextAlignment(node);
1914
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement20 && node.childNodes[0].tagName === "BR")
1862
1915
  return jsonNode;
1863
1916
  node.childNodes.forEach((child) => {
1864
1917
  const processedChildren = traverse2(child);
@@ -1870,10 +1923,10 @@ var ParagraphNodeHandler2 = class extends NodeHandler2 {
1870
1923
 
1871
1924
  // src/importFromHtml/ShortAnswerQuestionNodeHandler.ts
1872
1925
  import { nanoid as nanoid9 } from "nanoid";
1873
- import { HTMLElement as HTMLElement20 } from "node-html-parser";
1926
+ import { HTMLElement as HTMLElement21 } from "node-html-parser";
1874
1927
  var ShortAnswerQuestionNodeHandler2 = class extends NodeHandler2 {
1875
1928
  processNode(node) {
1876
- if (!(node instanceof HTMLElement20) || node.tagName !== "x-short-answer".toUpperCase())
1929
+ if (!(node instanceof HTMLElement21) || node.tagName !== "x-short-answer".toUpperCase())
1877
1930
  return null;
1878
1931
  return {
1879
1932
  id: node.getAttribute("id") ?? nanoid9(),
@@ -1889,44 +1942,40 @@ var ShortAnswerQuestionNodeHandler2 = class extends NodeHandler2 {
1889
1942
  };
1890
1943
 
1891
1944
  // src/importFromHtml/SimulationQuestionNodeHandler.ts
1892
- import { HTMLElement as HTMLElement21 } from "node-html-parser";
1945
+ import { HTMLElement as HTMLElement22 } from "node-html-parser";
1893
1946
  var TAG_X_SIMULATION = "x-simulation";
1894
1947
  var TAG_X_SYSTEM_MESSAGE2 = "x-ai-system-message";
1948
+ var TAG_X_COMMENT_INSTRUCTIONS = "x-comment-instructions";
1895
1949
  var TAG_X_STEP2_INSTRUCTIONS = "x-step2-instructions";
1950
+ var findFirstNonEmptyInnerHtml = (root, elementNames) => elementNames.map((name) => root.querySelector(name)).find((el) => el?.innerHTML.trim().length)?.innerHTML.trim() ?? null;
1896
1951
  var SimulationQuestionNodeHandler2 = class extends NodeHandler2 {
1897
1952
  processNode(node) {
1898
- if (!(node instanceof HTMLElement21) || node.tagName !== TAG_X_SIMULATION.toUpperCase()) {
1953
+ if (!(node instanceof HTMLElement22) || node.tagName !== TAG_X_SIMULATION.toUpperCase()) {
1899
1954
  return null;
1900
1955
  }
1901
1956
  const jsonNode = {
1902
1957
  id: node.getAttribute("id") || "",
1903
1958
  points: Number(node.getAttribute("data-x-points") || 0),
1904
1959
  aiChatModel: node.getAttribute("data-x-ai-chat-model") || null,
1905
- step2Instructions: "",
1906
- aiSystemMessage: "",
1960
+ aiSystemMessage: findFirstNonEmptyInnerHtml(node, [TAG_X_SYSTEM_MESSAGE2]) ?? "",
1961
+ disableChat: node.getAttribute("data-x-disable-chat") === "true",
1962
+ commentInstructions: findFirstNonEmptyInnerHtml(node, [
1963
+ TAG_X_COMMENT_INSTRUCTIONS,
1964
+ TAG_X_STEP2_INSTRUCTIONS
1965
+ ]) ?? "",
1907
1966
  type: "simulation-question",
1908
1967
  version: 1
1909
1968
  };
1910
- const systemMessageElement = node.querySelector(
1911
- TAG_X_SYSTEM_MESSAGE2
1912
- );
1913
- if (systemMessageElement)
1914
- jsonNode.aiSystemMessage = systemMessageElement.innerHTML;
1915
- const step2InstructionsElement = node.querySelector(
1916
- TAG_X_STEP2_INSTRUCTIONS
1917
- );
1918
- if (step2InstructionsElement)
1919
- jsonNode.step2Instructions = step2InstructionsElement.innerHTML;
1920
1969
  return jsonNode;
1921
1970
  }
1922
1971
  };
1923
1972
 
1924
1973
  // src/importFromHtml/SpanNodeHandler.ts
1925
- import { HTMLElement as HTMLElement22, parse } from "node-html-parser";
1974
+ import { HTMLElement as HTMLElement23, parse } from "node-html-parser";
1926
1975
  var TextNode = parse.TextNode;
1927
1976
  var SpanNodeHandler = class extends NodeHandler2 {
1928
1977
  processNode(node) {
1929
- if (!(node instanceof HTMLElement22) || node.tagName !== "SPAN")
1978
+ if (!(node instanceof HTMLElement23) || node.tagName !== "SPAN")
1930
1979
  return null;
1931
1980
  const styleAttr = node.getAttribute("style") || "";
1932
1981
  if (node.childNodes.length === 1 && node.childNodes[0] instanceof TextNode) {
@@ -1988,7 +2037,7 @@ var SpanNodeHandler = class extends NodeHandler2 {
1988
2037
  };
1989
2038
 
1990
2039
  // src/importFromHtml/TableCellNodeHandler.ts
1991
- import { HTMLElement as HTMLElement23 } from "node-html-parser";
2040
+ import { HTMLElement as HTMLElement24 } from "node-html-parser";
1992
2041
 
1993
2042
  // src/utils/styleUtils.ts
1994
2043
  var extractStyleValue = (styleAttr, property, isNumeric = false, unit = "") => {
@@ -2037,7 +2086,7 @@ function createEmptyTableCellNode(isHeader = false) {
2037
2086
 
2038
2087
  // src/importFromHtml/TableCellNodeHandler.ts
2039
2088
  var isHtmlTableCellElement = (node) => {
2040
- return node instanceof HTMLElement23 && (node.tagName === "TD" || node.tagName === "TH");
2089
+ return node instanceof HTMLElement24 && (node.tagName === "TD" || node.tagName === "TH");
2041
2090
  };
2042
2091
  var TableCellNodeHandler2 = class extends NodeHandler2 {
2043
2092
  processNode(node) {
@@ -2079,10 +2128,10 @@ var TableCellNodeHandler2 = class extends NodeHandler2 {
2079
2128
  };
2080
2129
 
2081
2130
  // src/importFromHtml/TableNodeHandler.ts
2082
- import { HTMLElement as HTMLElement24 } from "node-html-parser";
2131
+ import { HTMLElement as HTMLElement25 } from "node-html-parser";
2083
2132
  var REFERENCE_TABLE_WIDTH = 720;
2084
2133
  var MINIMUM_REFERENCE_TABLE_WIDTH = 500;
2085
- var isHtmlTableElement = (node) => node instanceof HTMLElement24 && node.tagName === "TABLE";
2134
+ var isHtmlTableElement = (node) => node instanceof HTMLElement25 && node.tagName === "TABLE";
2086
2135
  var TableNodeHandler2 = class extends NodeHandler2 {
2087
2136
  processNode(node) {
2088
2137
  if (!isHtmlTableElement(node)) return null;
@@ -2237,9 +2286,9 @@ var TableNodeHandler2 = class extends NodeHandler2 {
2237
2286
  };
2238
2287
 
2239
2288
  // src/importFromHtml/TableRowNodeHandler.ts
2240
- import { HTMLElement as HTMLElement25 } from "node-html-parser";
2289
+ import { HTMLElement as HTMLElement26 } from "node-html-parser";
2241
2290
  var isHtmlTableRowElement = (node) => {
2242
- return node instanceof HTMLElement25 && node.tagName === "TR";
2291
+ return node instanceof HTMLElement26 && node.tagName === "TR";
2243
2292
  };
2244
2293
  var TableRowNodeHandler2 = class extends NodeHandler2 {
2245
2294
  processNode(node) {
@@ -2282,10 +2331,10 @@ var TextNodeHandler2 = class extends NodeHandler2 {
2282
2331
  };
2283
2332
 
2284
2333
  // src/importFromHtml/VariableNodeHandler.ts
2285
- import { HTMLElement as HTMLElement26 } from "node-html-parser";
2334
+ import { HTMLElement as HTMLElement27 } from "node-html-parser";
2286
2335
  var VariableNodeHandler2 = class extends NodeHandler2 {
2287
2336
  processNode(node) {
2288
- if (!(node instanceof HTMLElement26) || !node.tagName) return null;
2337
+ if (!(node instanceof HTMLElement27) || !node.tagName) return null;
2289
2338
  if (node.tagName !== "x-param".toUpperCase()) return null;
2290
2339
  return {
2291
2340
  variableName: node.getAttribute("data-x-name") || "undefined",
@@ -2298,7 +2347,7 @@ var VariableNodeHandler2 = class extends NodeHandler2 {
2298
2347
 
2299
2348
  // src/importFromHtml/traverse.ts
2300
2349
  var builder2 = new NodeHandlerChainBuilder();
2301
- var nodeHandlerChain2 = builder2.addHandler(CustomQuestionNodeHandler2).addHandler(DivNodeHandler).addHandler(EssayQuestionNodeHandler2).addHandler(FillInTheBlankQuestionNodeHandler2).addHandler(FillInTheBlankSpaceNodeHandler2).addHandler(FinancialStatementQuestionNodeHandler2).addHandler(FormattedNodeHandler).addHandler(ImageNodeHandler2).addHandler(HorizontalRuleNodeHandler2).addHandler(JournalEntryQuestionNodeHandler2).addHandler(LineBreakNodeHandler2).addHandler(LinkNodeHandler2).addHandler(ListNodeHandler2).addHandler(ListItemNodeHandler2).addHandler(MatchingQuestionNodeHandler2).addHandler(MultipleOptionQuestionNodeHandler2).addHandler(ParagraphNodeHandler2).addHandler(ShortAnswerQuestionNodeHandler2).addHandler(SimulationQuestionNodeHandler2).addHandler(SpanNodeHandler).addHandler(TableCellNodeHandler2).addHandler(TableNodeHandler2).addHandler(TableRowNodeHandler2).addHandler(TextNodeHandler2).addHandler(VariableNodeHandler2).build();
2350
+ var nodeHandlerChain2 = builder2.addHandler(CustomQuestionNodeHandler2).addHandler(DivNodeHandler).addHandler(EssayQuestionNodeHandler2).addHandler(FillInTheBlankQuestionNodeHandler2).addHandler(FillInTheBlankSpaceNodeHandler2).addHandler(FinancialStatementQuestionNodeHandler2).addHandler(FormattedNodeHandler).addHandler(ImageNodeHandler2).addHandler(HeadingNodeHandler2).addHandler(HorizontalRuleNodeHandler2).addHandler(JournalEntryQuestionNodeHandler2).addHandler(LineBreakNodeHandler2).addHandler(LinkNodeHandler2).addHandler(ListNodeHandler2).addHandler(ListItemNodeHandler2).addHandler(MatchingQuestionNodeHandler2).addHandler(MultipleOptionQuestionNodeHandler2).addHandler(ParagraphNodeHandler2).addHandler(ShortAnswerQuestionNodeHandler2).addHandler(SimulationQuestionNodeHandler2).addHandler(SpanNodeHandler).addHandler(TableCellNodeHandler2).addHandler(TableNodeHandler2).addHandler(TableRowNodeHandler2).addHandler(TextNodeHandler2).addHandler(VariableNodeHandler2).build();
2302
2351
  function traverse2(node) {
2303
2352
  const result = nodeHandlerChain2.handle(node);
2304
2353
  if (result === null) return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@examind/block-sdk",
3
- "version": "0.1.33",
3
+ "version": "0.1.36",
4
4
  "@comment version": [
5
5
  "Don't specify package version here. It will be injected by publish workflow."
6
6
  ],
@@ -21,7 +21,7 @@
21
21
  "peerDependencies": {
22
22
  "nanoid": ">=3.0.0",
23
23
  "node-html-parser": ">=6.0.0",
24
- "@examind/block-types": "^0.1.33"
24
+ "@examind/block-types": "^0.1.36"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@eslint/js": "^9.17.0",
@@ -36,7 +36,7 @@
36
36
  "tsup": "^8.3.5",
37
37
  "typescript": "^5.7.2",
38
38
  "typescript-eslint": "^8.18.2",
39
- "@examind/block-types": "0.1.33"
39
+ "@examind/block-types": "0.1.36"
40
40
  },
41
41
  "dependencies": {
42
42
  "lodash-es": "4.17.21"