@examind/block-sdk 0.1.22 → 0.1.24

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 +148 -118
  2. package/dist/index.mjs +143 -113
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -156,7 +156,8 @@ var FillInTheBlankSpaceNodeHandler = class extends NodeHandler {
156
156
  `data-x-case-sensitive="${!!node.caseSensitive}"`,
157
157
  `data-x-errors-allowed="${node.errorsAllowed ?? 0}"`,
158
158
  `data-x-min-decimals="${node.minDecimals ?? ""}"`,
159
- `data-x-error-tolerance="${node.errorTolerance ?? 0}"`,
159
+ `data-x-error-tolerance="${(node.errorTolerance ?? 0) / 100}"`,
160
+ // Divide by 100 to convert percentage to rate
160
161
  `data-x-distractors="${node.distractors ?? ""}"`
161
162
  ];
162
163
  return attributes.join(" ");
@@ -338,6 +339,20 @@ function isSerializedJournalEntryQuestionNode(node) {
338
339
  return node?.type === "journal-entry-question" && "id" in node && typeof node.id === "string" && "points" in node && typeof node.points === "number" && "journalType" in node && typeof node.journalType === "string" && "lineItems" in node && Array.isArray(node.lineItems);
339
340
  }
340
341
 
342
+ // src/exportToHtml/createHtmlFromOnePerLineDistractorNodes.ts
343
+ function createHtmlFromOnePerLineDistractorNodes(distractorNodes, parentNode) {
344
+ const distractors = distractorNodes.map((node) => {
345
+ const distractorAccounts = createHtmlFromNestedEditor(
346
+ node.content,
347
+ { parentNode }
348
+ );
349
+ return distractorAccounts.split("<br>").filter((a) => a.trim()).map(
350
+ (a, i) => `<x-distractor id="${node.id}|${i}">${a}</x-distractor>`
351
+ ).join("");
352
+ }).join("");
353
+ return distractors;
354
+ }
355
+
341
356
  // src/exportToHtml/JournalEntryQuestionNodeHandler.ts
342
357
  var JournalEntryQuestionNodeHandler = class extends NodeHandler {
343
358
  processNode(node) {
@@ -391,16 +406,14 @@ var JournalEntryQuestionNodeHandler = class extends NodeHandler {
391
406
  return `<x-line-item id="${item.id}"><x-account>${accountContent}</x-account><x-debit>${debitContent}</x-debit><x-credit>${creditContent}</x-credit></x-line-item>`;
392
407
  }
393
408
  processDistractors(node) {
394
- const distractors = node.lineItems.filter((item) => !item.correct).map((item) => {
395
- const distractorAccounts = createHtmlFromNestedEditor(
396
- item.account,
397
- { parentNode: node }
398
- );
399
- return distractorAccounts.split("<br>").filter((a) => a.trim()).map(
400
- (a, i) => `<x-distractor id="${item.id}|${i}">${a}</x-distractor>`
401
- ).join("");
402
- }).join("");
403
- return distractors;
409
+ const distractorNodes = node.lineItems.filter((item) => !item.correct).map((item) => ({
410
+ id: item.id,
411
+ content: item.account
412
+ }));
413
+ return createHtmlFromOnePerLineDistractorNodes(
414
+ distractorNodes,
415
+ node
416
+ );
404
417
  }
405
418
  };
406
419
 
@@ -511,13 +524,14 @@ var MatchingQuestionNodeHandler = class extends NodeHandler {
511
524
  ).join("");
512
525
  }
513
526
  createDistractorsHtml(node) {
514
- const metadata = { parentNode: node };
515
- return node.items.filter((item) => !item.correct).map(
516
- (item) => `<x-distractor id="${item.id}">${createHtmlFromNestedEditor(
517
- item.itemOptionContent,
518
- metadata
519
- )}</x-distractor>`
520
- ).join("");
527
+ const distractorNodes = node.items.filter((item) => !item.correct).map((item) => ({
528
+ id: item.id,
529
+ content: item.itemOptionContent
530
+ }));
531
+ return createHtmlFromOnePerLineDistractorNodes(
532
+ distractorNodes,
533
+ node
534
+ );
521
535
  }
522
536
  };
523
537
 
@@ -933,7 +947,7 @@ function exportToHtml(editorState) {
933
947
  }
934
948
 
935
949
  // src/importFromHtml/index.ts
936
- var import_node_html_parser26 = require("node-html-parser");
950
+ var import_node_html_parser27 = require("node-html-parser");
937
951
 
938
952
  // src/importFromHtml/createEmptyParagraphNode.ts
939
953
  function createEmptyParagraphNode(format = "") {
@@ -1016,7 +1030,7 @@ var createCaptionNode = (caption) => {
1016
1030
  return [];
1017
1031
  }
1018
1032
  const captionNode = createEmptyParagraphNode("center");
1019
- captionNode.children = caption.split("\n").reduce((nodes, line, index, lines) => {
1033
+ captionNode.children = caption.split("<br>").reduce((nodes, line, index, lines) => {
1020
1034
  nodes.push({
1021
1035
  detail: 0,
1022
1036
  format: 0,
@@ -1112,7 +1126,7 @@ function processImageNodeContainer(node) {
1112
1126
  extractWidth(imageNode),
1113
1127
  extractFlexAlign(node),
1114
1128
  hasBorder(imageNode),
1115
- captionNode?.text
1129
+ captionNode?.innerHTML
1116
1130
  )
1117
1131
  ];
1118
1132
  }
@@ -1264,11 +1278,18 @@ var FillInTheBlankSpaceNodeHandler2 = class extends NodeHandler2 {
1264
1278
  errorsAllowed: node.getAttribute("data-x-errors-allowed") ? Number(node.getAttribute("data-x-errors-allowed")) : void 0
1265
1279
  };
1266
1280
  }
1281
+ parseErrorToleranceAttr(attr) {
1282
+ const value = Number(attr);
1283
+ if (isNaN(value)) return 0;
1284
+ else return value * 100;
1285
+ }
1267
1286
  processNumberSpace(node, baseNode) {
1268
1287
  return {
1269
1288
  ...baseNode,
1270
1289
  minDecimals: node.getAttribute("data-x-min-decimals") ? Number(node.getAttribute("data-x-min-decimals")) : void 0,
1271
- errorTolerance: node.getAttribute("data-x-error-tolerance") ? Number(node.getAttribute("data-x-error-tolerance")) : void 0
1290
+ errorTolerance: this.parseErrorToleranceAttr(
1291
+ node.getAttribute("data-x-error-tolerance")
1292
+ )
1272
1293
  };
1273
1294
  }
1274
1295
  processDropdownSpace(node, baseNode) {
@@ -1504,22 +1525,49 @@ var ImageNodeHandler2 = class extends NodeHandler2 {
1504
1525
  };
1505
1526
 
1506
1527
  // src/importFromHtml/JournalEntryQuestionNodeHandler.ts
1528
+ var import_nanoid6 = require("nanoid");
1529
+ var import_node_html_parser11 = require("node-html-parser");
1530
+
1531
+ // src/importFromHtml/createOnePerLineDistractorNode.ts
1507
1532
  var import_nanoid5 = require("nanoid");
1508
1533
  var import_node_html_parser10 = require("node-html-parser");
1509
- var extractDistractorId = (id) => {
1534
+ function extractDistractorId(id) {
1510
1535
  if (!id) return null;
1511
1536
  const parts = id.split("|");
1512
- return parts.length === 2 ? parts[0] : null;
1537
+ return parts[0] ? parts[0] : null;
1538
+ }
1539
+ var createOnePerLineDistractorNode = (node) => {
1540
+ const distractorEditor = createNestedEditorFromHtml(null);
1541
+ const distractors = node.querySelectorAll("x-distractor");
1542
+ const emptyDistractorEditorChildren = distractorEditor.editorState.root.children;
1543
+ distractorEditor.editorState.root.children = [];
1544
+ let distractorId = null;
1545
+ distractors.forEach((distractor) => {
1546
+ if (!(distractor instanceof import_node_html_parser10.HTMLElement)) return;
1547
+ distractorId = distractorId ?? extractDistractorId(distractor.getAttribute("id"));
1548
+ distractorEditor.editorState.root.children.push(
1549
+ ...createNestedNodesFromHtml(distractor)
1550
+ );
1551
+ });
1552
+ if (!distractorEditor.editorState.root.children.length) {
1553
+ distractorEditor.editorState.root.children = emptyDistractorEditorChildren;
1554
+ }
1555
+ return {
1556
+ id: distractorId ?? (0, import_nanoid5.nanoid)(),
1557
+ content: distractorEditor
1558
+ };
1513
1559
  };
1560
+
1561
+ // src/importFromHtml/JournalEntryQuestionNodeHandler.ts
1514
1562
  var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1515
1563
  processNode(node) {
1516
- if (!(node instanceof import_node_html_parser10.HTMLElement) || node.tagName !== "x-journal-entry".toUpperCase())
1564
+ if (!(node instanceof import_node_html_parser11.HTMLElement) || node.tagName !== "x-journal-entry".toUpperCase())
1517
1565
  return null;
1518
1566
  const noEntryRequiredCorrect = node.getAttribute("data-x-no-entry-required-correct") === "true";
1519
1567
  const noEntryRequiredDistractor = node.getAttribute("data-x-no-entry-required-distractor") === "true";
1520
1568
  const journalType = noEntryRequiredCorrect ? "noEntryRequiredCorrect" : noEntryRequiredDistractor ? "noEntryRequiredDistractor" : "default";
1521
1569
  const jsonNode = {
1522
- id: node.getAttribute("id") ?? (0, import_nanoid5.nanoid)(),
1570
+ id: node.getAttribute("id") ?? (0, import_nanoid6.nanoid)(),
1523
1571
  points: Number(node.getAttribute("data-x-points") ?? 1),
1524
1572
  journalType,
1525
1573
  errorTolerance: node.getAttribute("data-x-error-tolerance") ? Number(node.getAttribute("data-x-error-tolerance")) : void 0,
@@ -1529,54 +1577,39 @@ var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1529
1577
  };
1530
1578
  const lineItems = node.querySelectorAll("x-line-item");
1531
1579
  lineItems.forEach((lineItem) => {
1532
- if (!(lineItem instanceof import_node_html_parser10.HTMLElement)) return;
1580
+ if (!(lineItem instanceof import_node_html_parser11.HTMLElement)) return;
1533
1581
  const accountElement = lineItem.querySelector("x-account");
1534
1582
  const debitElement = lineItem.querySelector("x-debit");
1535
1583
  const creditElement = lineItem.querySelector("x-credit");
1536
1584
  if (!accountElement) return;
1537
- const item2 = {
1538
- id: lineItem.getAttribute("id") ?? (0, import_nanoid5.nanoid)(),
1585
+ const item = {
1586
+ id: lineItem.getAttribute("id") ?? (0, import_nanoid6.nanoid)(),
1539
1587
  correct: true,
1540
1588
  account: createNestedEditorFromHtml(accountElement)
1541
1589
  };
1542
1590
  if (debitElement) {
1543
- item2.debit = createNestedEditorFromHtml(debitElement);
1591
+ item.debit = createNestedEditorFromHtml(debitElement);
1544
1592
  }
1545
1593
  if (creditElement) {
1546
- item2.credit = createNestedEditorFromHtml(creditElement);
1594
+ item.credit = createNestedEditorFromHtml(creditElement);
1547
1595
  }
1548
- jsonNode.lineItems.push(item2);
1596
+ jsonNode.lineItems.push(item);
1549
1597
  });
1550
- const distractorEditor = createNestedEditorFromHtml(null);
1551
- const distractors = node.querySelectorAll("x-distractor");
1552
- const emptyDistractorEditorChildren = distractorEditor.editorState.root.children;
1553
- distractorEditor.editorState.root.children = [];
1554
- let distractorId = null;
1555
- distractors.forEach((distractor) => {
1556
- if (!(distractor instanceof import_node_html_parser10.HTMLElement)) return;
1557
- distractorId = distractorId ?? extractDistractorId(distractor.getAttribute("id"));
1558
- distractorEditor.editorState.root.children.push(
1559
- ...createNestedNodesFromHtml(distractor)
1560
- );
1561
- });
1562
- if (!distractorEditor.editorState.root.children.length) {
1563
- distractorEditor.editorState.root.children = emptyDistractorEditorChildren;
1564
- }
1565
- const item = {
1566
- id: distractorId ?? (0, import_nanoid5.nanoid)(),
1598
+ const distractorNode = createOnePerLineDistractorNode(node);
1599
+ jsonNode.lineItems.push({
1600
+ id: distractorNode.id,
1567
1601
  correct: false,
1568
- account: distractorEditor
1569
- };
1570
- jsonNode.lineItems.push(item);
1602
+ account: distractorNode.content
1603
+ });
1571
1604
  return jsonNode;
1572
1605
  }
1573
1606
  };
1574
1607
 
1575
1608
  // src/importFromHtml/LineBreakNodeHandler.ts
1576
- var import_node_html_parser11 = require("node-html-parser");
1609
+ var import_node_html_parser12 = require("node-html-parser");
1577
1610
  var LineBreakNodeHandler2 = class extends NodeHandler2 {
1578
1611
  processNode(node) {
1579
- if (!(node instanceof import_node_html_parser11.HTMLElement)) return null;
1612
+ if (!(node instanceof import_node_html_parser12.HTMLElement)) return null;
1580
1613
  if (node.tagName !== "BR") return null;
1581
1614
  return {
1582
1615
  type: "linebreak",
@@ -1586,11 +1619,11 @@ var LineBreakNodeHandler2 = class extends NodeHandler2 {
1586
1619
  };
1587
1620
 
1588
1621
  // src/importFromHtml/LinkNodeHandler.ts
1589
- var import_node_html_parser12 = require("node-html-parser");
1622
+ var import_node_html_parser13 = require("node-html-parser");
1590
1623
  var TAG_A = "a";
1591
1624
  var LinkNodeHandler2 = class extends NodeHandler2 {
1592
1625
  processNode(node) {
1593
- if (!(node instanceof import_node_html_parser12.HTMLElement) || node.tagName !== TAG_A.toUpperCase()) {
1626
+ if (!(node instanceof import_node_html_parser13.HTMLElement) || node.tagName !== TAG_A.toUpperCase()) {
1594
1627
  return null;
1595
1628
  }
1596
1629
  const url = node.getAttribute("href") || "";
@@ -1619,10 +1652,10 @@ var LinkNodeHandler2 = class extends NodeHandler2 {
1619
1652
  };
1620
1653
 
1621
1654
  // src/importFromHtml/ListItemNodeHandler.ts
1622
- var import_node_html_parser13 = require("node-html-parser");
1655
+ var import_node_html_parser14 = require("node-html-parser");
1623
1656
  var ListItemNodeHandler2 = class extends NodeHandler2 {
1624
1657
  processNode(node) {
1625
- if (!(node instanceof import_node_html_parser13.HTMLElement)) return null;
1658
+ if (!(node instanceof import_node_html_parser14.HTMLElement)) return null;
1626
1659
  if (node.tagName !== "LI") return null;
1627
1660
  const jsonNode = {
1628
1661
  type: "listitem",
@@ -1643,10 +1676,10 @@ var ListItemNodeHandler2 = class extends NodeHandler2 {
1643
1676
  };
1644
1677
 
1645
1678
  // src/importFromHtml/ListNodeHandler.ts
1646
- var import_node_html_parser14 = require("node-html-parser");
1679
+ var import_node_html_parser15 = require("node-html-parser");
1647
1680
  var ListNodeHandler2 = class extends NodeHandler2 {
1648
1681
  processNode(node) {
1649
- if (!(node instanceof import_node_html_parser14.HTMLElement)) return null;
1682
+ if (!(node instanceof import_node_html_parser15.HTMLElement)) return null;
1650
1683
  if (node.tagName !== "UL" && node.tagName !== "OL") return null;
1651
1684
  const tag = node.tagName.toLowerCase();
1652
1685
  const listType = tag === "ol" ? "number" : "bullet";
@@ -1664,7 +1697,7 @@ var ListNodeHandler2 = class extends NodeHandler2 {
1664
1697
  };
1665
1698
  let itemIndex = 1;
1666
1699
  node.childNodes.forEach((child) => {
1667
- if (child instanceof import_node_html_parser14.HTMLElement && child.tagName === "LI") {
1700
+ if (child instanceof import_node_html_parser15.HTMLElement && child.tagName === "LI") {
1668
1701
  const listItemNode = {
1669
1702
  type: "listitem",
1670
1703
  version: 1,
@@ -1688,14 +1721,14 @@ var ListNodeHandler2 = class extends NodeHandler2 {
1688
1721
  };
1689
1722
 
1690
1723
  // src/importFromHtml/MatchingQuestionNodeHandler.ts
1691
- var import_nanoid6 = require("nanoid");
1692
- var import_node_html_parser15 = require("node-html-parser");
1724
+ var import_nanoid7 = require("nanoid");
1725
+ var import_node_html_parser16 = require("node-html-parser");
1693
1726
  var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1694
1727
  processNode(node) {
1695
- if (!(node instanceof import_node_html_parser15.HTMLElement) || node.tagName !== "x-matching".toUpperCase())
1728
+ if (!(node instanceof import_node_html_parser16.HTMLElement) || node.tagName !== "x-matching".toUpperCase())
1696
1729
  return null;
1697
1730
  const jsonNode = {
1698
- id: node.getAttribute("id") ?? (0, import_nanoid6.nanoid)(),
1731
+ id: node.getAttribute("id") ?? (0, import_nanoid7.nanoid)(),
1699
1732
  pointsPerMatch: Number(
1700
1733
  node.getAttribute("data-x-points-per-match") ?? 1
1701
1734
  ),
@@ -1703,38 +1736,35 @@ var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1703
1736
  type: "matching-question",
1704
1737
  version: 1
1705
1738
  };
1706
- const childNodes = node.childNodes;
1707
- childNodes.forEach((child) => {
1708
- if (!(child instanceof import_node_html_parser15.HTMLElement)) return;
1709
- if (child.tagName === "x-match".toUpperCase()) {
1710
- const premise = child.querySelector("x-premise");
1711
- const option = child.querySelector("x-option");
1712
- if (!premise || !option) return;
1713
- jsonNode.items.push({
1714
- id: premise.getAttribute("id") ?? (0, import_nanoid6.nanoid)(),
1715
- correct: true,
1716
- itemPremiseContent: createNestedEditorFromHtml(premise),
1717
- itemOptionContent: createNestedEditorFromHtml(option)
1718
- });
1719
- }
1720
- if (child.tagName === "x-distractor".toUpperCase()) {
1721
- jsonNode.items.push({
1722
- id: child.getAttribute("id") ?? (0, import_nanoid6.nanoid)(),
1723
- correct: false,
1724
- itemOptionContent: createNestedEditorFromHtml(child)
1725
- });
1726
- }
1739
+ const matches = node.querySelectorAll("x-match");
1740
+ matches.forEach((match) => {
1741
+ if (!(match instanceof import_node_html_parser16.HTMLElement)) return;
1742
+ const premise = match.querySelector("x-premise");
1743
+ const option = match.querySelector("x-option");
1744
+ if (!premise || !option) return;
1745
+ jsonNode.items.push({
1746
+ id: premise.getAttribute("id") ?? (0, import_nanoid7.nanoid)(),
1747
+ correct: true,
1748
+ itemPremiseContent: createNestedEditorFromHtml(premise),
1749
+ itemOptionContent: createNestedEditorFromHtml(option)
1750
+ });
1751
+ });
1752
+ const distractorNode = createOnePerLineDistractorNode(node);
1753
+ jsonNode.items.push({
1754
+ id: distractorNode.id,
1755
+ correct: false,
1756
+ itemOptionContent: distractorNode.content
1727
1757
  });
1728
1758
  return jsonNode;
1729
1759
  }
1730
1760
  };
1731
1761
 
1732
1762
  // src/importFromHtml/MultipleOptionQuestionNodeHandler.ts
1733
- var import_nanoid7 = require("nanoid");
1734
- var import_node_html_parser16 = require("node-html-parser");
1763
+ var import_nanoid8 = require("nanoid");
1764
+ var import_node_html_parser17 = require("node-html-parser");
1735
1765
  var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1736
1766
  processNode(node) {
1737
- if (!(node instanceof import_node_html_parser16.HTMLElement)) return null;
1767
+ if (!(node instanceof import_node_html_parser17.HTMLElement)) return null;
1738
1768
  if (node.tagName === "x-multiple-choice".toUpperCase())
1739
1769
  return this.processMultipleChoiceNode(node);
1740
1770
  else if (node.tagName === "x-multiple-answers".toUpperCase())
@@ -1744,7 +1774,7 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1744
1774
  processMultipleChoiceNode(node) {
1745
1775
  const jsonNode = {
1746
1776
  options: [],
1747
- id: node.getAttribute("id") ?? (0, import_nanoid7.nanoid)(),
1777
+ id: node.getAttribute("id") ?? (0, import_nanoid8.nanoid)(),
1748
1778
  questionType: "multiple-choice",
1749
1779
  points: Number(node.getAttribute("data-x-points") || 0),
1750
1780
  choices: node.getAttribute("data-x-choices") ? Number(node.getAttribute("data-x-choices")) : void 0,
@@ -1758,7 +1788,7 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1758
1788
  processMultipleAnswersNode(node) {
1759
1789
  const jsonNode = {
1760
1790
  options: [],
1761
- id: node.getAttribute("id") ?? (0, import_nanoid7.nanoid)(),
1791
+ id: node.getAttribute("id") ?? (0, import_nanoid8.nanoid)(),
1762
1792
  questionType: "multiple-answers",
1763
1793
  points: Number(node.getAttribute("data-x-points") || 0),
1764
1794
  correctChoices: node.getAttribute("data-x-correct-choices") ? Number(node.getAttribute("data-x-correct-choices")) : void 0,
@@ -1774,10 +1804,10 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1774
1804
  processOptions(node, jsonNode) {
1775
1805
  const childNodes = node.childNodes;
1776
1806
  childNodes.forEach((child) => {
1777
- if (!(child instanceof import_node_html_parser16.HTMLElement)) return;
1807
+ if (!(child instanceof import_node_html_parser17.HTMLElement)) return;
1778
1808
  if (child.tagName !== "x-option".toUpperCase()) return;
1779
1809
  jsonNode.options.push({
1780
- id: child.getAttribute("id") ?? (0, import_nanoid7.nanoid)(),
1810
+ id: child.getAttribute("id") ?? (0, import_nanoid8.nanoid)(),
1781
1811
  correct: child.getAttribute("data-x-correct") === "true",
1782
1812
  content: createNestedEditorFromHtml(child)
1783
1813
  });
@@ -1786,7 +1816,7 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1786
1816
  };
1787
1817
 
1788
1818
  // src/importFromHtml/ParagraphNodeHandler.ts
1789
- var import_node_html_parser17 = require("node-html-parser");
1819
+ var import_node_html_parser18 = require("node-html-parser");
1790
1820
  var TEXT_ALIGN_TO_FORMAT = {
1791
1821
  center: "center",
1792
1822
  end: "end",
@@ -1809,25 +1839,25 @@ var ParagraphNodeHandler2 = class extends NodeHandler2 {
1809
1839
  return "";
1810
1840
  }
1811
1841
  processImageNode(node) {
1812
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser17.HTMLElement && node.childNodes[0].tagName === "IMG") {
1842
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser18.HTMLElement && node.childNodes[0].tagName === "IMG") {
1813
1843
  return traverse2(node.childNodes[0]);
1814
1844
  }
1815
1845
  return null;
1816
1846
  }
1817
1847
  processSpanImageNode(node) {
1818
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser17.HTMLElement && node.childNodes[0].tagName === "SPAN" && node.childNodes[0].childNodes.length === 1 && node.childNodes[0].childNodes[0] instanceof import_node_html_parser17.HTMLElement && node.childNodes[0].childNodes[0].tagName === "IMG") {
1848
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser18.HTMLElement && node.childNodes[0].tagName === "SPAN" && node.childNodes[0].childNodes.length === 1 && node.childNodes[0].childNodes[0] instanceof import_node_html_parser18.HTMLElement && node.childNodes[0].childNodes[0].tagName === "IMG") {
1819
1849
  return traverse2(node.childNodes[0].childNodes[0]);
1820
1850
  }
1821
1851
  return null;
1822
1852
  }
1823
1853
  processNode(node) {
1824
- if (!(node instanceof import_node_html_parser17.HTMLElement)) return null;
1854
+ if (!(node instanceof import_node_html_parser18.HTMLElement)) return null;
1825
1855
  if (node.tagName !== "P") return null;
1826
1856
  const imageNode = this.processImageNode(node) ?? this.processSpanImageNode(node);
1827
1857
  if (imageNode) return imageNode;
1828
1858
  const jsonNode = createEmptyParagraphNode();
1829
1859
  jsonNode.format = this.extractTextAlignment(node);
1830
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser17.HTMLElement && node.childNodes[0].tagName === "BR")
1860
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof import_node_html_parser18.HTMLElement && node.childNodes[0].tagName === "BR")
1831
1861
  return jsonNode;
1832
1862
  node.childNodes.forEach((child) => {
1833
1863
  const processedChildren = traverse2(child);
@@ -1838,14 +1868,14 @@ var ParagraphNodeHandler2 = class extends NodeHandler2 {
1838
1868
  };
1839
1869
 
1840
1870
  // src/importFromHtml/ShortAnswerQuestionNodeHandler.ts
1841
- var import_nanoid8 = require("nanoid");
1842
- var import_node_html_parser18 = require("node-html-parser");
1871
+ var import_nanoid9 = require("nanoid");
1872
+ var import_node_html_parser19 = require("node-html-parser");
1843
1873
  var ShortAnswerQuestionNodeHandler2 = class extends NodeHandler2 {
1844
1874
  processNode(node) {
1845
- if (!(node instanceof import_node_html_parser18.HTMLElement) || node.tagName !== "x-short-answer".toUpperCase())
1875
+ if (!(node instanceof import_node_html_parser19.HTMLElement) || node.tagName !== "x-short-answer".toUpperCase())
1846
1876
  return null;
1847
1877
  return {
1848
- id: node.getAttribute("id") ?? (0, import_nanoid8.nanoid)(),
1878
+ id: node.getAttribute("id") ?? (0, import_nanoid9.nanoid)(),
1849
1879
  points: Number(node.getAttribute("data-x-points") ?? 1),
1850
1880
  maxWords: Number(node.getAttribute("data-x-max-words") ?? 100),
1851
1881
  notes: createNestedEditorFromHtml(
@@ -1858,13 +1888,13 @@ var ShortAnswerQuestionNodeHandler2 = class extends NodeHandler2 {
1858
1888
  };
1859
1889
 
1860
1890
  // src/importFromHtml/SimulationQuestionNodeHandler.ts
1861
- var import_node_html_parser19 = require("node-html-parser");
1891
+ var import_node_html_parser20 = require("node-html-parser");
1862
1892
  var TAG_X_SIMULATION = "x-simulation";
1863
1893
  var TAG_X_SYSTEM_MESSAGE2 = "x-ai-system-message";
1864
1894
  var TAG_X_STEP2_INSTRUCTIONS = "x-step2-instructions";
1865
1895
  var SimulationQuestionNodeHandler2 = class extends NodeHandler2 {
1866
1896
  processNode(node) {
1867
- if (!(node instanceof import_node_html_parser19.HTMLElement) || node.tagName !== TAG_X_SIMULATION.toUpperCase()) {
1897
+ if (!(node instanceof import_node_html_parser20.HTMLElement) || node.tagName !== TAG_X_SIMULATION.toUpperCase()) {
1868
1898
  return null;
1869
1899
  }
1870
1900
  const jsonNode = {
@@ -1891,11 +1921,11 @@ var SimulationQuestionNodeHandler2 = class extends NodeHandler2 {
1891
1921
  };
1892
1922
 
1893
1923
  // src/importFromHtml/SpanNodeHandler.ts
1894
- var import_node_html_parser20 = require("node-html-parser");
1895
- var TextNode = import_node_html_parser20.parse.TextNode;
1924
+ var import_node_html_parser21 = require("node-html-parser");
1925
+ var TextNode = import_node_html_parser21.parse.TextNode;
1896
1926
  var SpanNodeHandler = class extends NodeHandler2 {
1897
1927
  processNode(node) {
1898
- if (!(node instanceof import_node_html_parser20.HTMLElement) || node.tagName !== "SPAN")
1928
+ if (!(node instanceof import_node_html_parser21.HTMLElement) || node.tagName !== "SPAN")
1899
1929
  return null;
1900
1930
  const styleAttr = node.getAttribute("style") || "";
1901
1931
  if (node.childNodes.length === 1 && node.childNodes[0] instanceof TextNode) {
@@ -1955,7 +1985,7 @@ var SpanNodeHandler = class extends NodeHandler2 {
1955
1985
  };
1956
1986
 
1957
1987
  // src/importFromHtml/TableCellNodeHandler.ts
1958
- var import_node_html_parser21 = require("node-html-parser");
1988
+ var import_node_html_parser22 = require("node-html-parser");
1959
1989
 
1960
1990
  // src/utils/styleUtils.ts
1961
1991
  var extractStyleValue = (styleAttr, property, isNumeric = false, unit = "") => {
@@ -2004,7 +2034,7 @@ function createEmptyTableCellNode(isHeader = false) {
2004
2034
 
2005
2035
  // src/importFromHtml/TableCellNodeHandler.ts
2006
2036
  var isHtmlTableCellElement = (node) => {
2007
- return node instanceof import_node_html_parser21.HTMLElement && (node.tagName === "TD" || node.tagName === "TH");
2037
+ return node instanceof import_node_html_parser22.HTMLElement && (node.tagName === "TD" || node.tagName === "TH");
2008
2038
  };
2009
2039
  var TableCellNodeHandler2 = class extends NodeHandler2 {
2010
2040
  processNode(node) {
@@ -2046,10 +2076,10 @@ var TableCellNodeHandler2 = class extends NodeHandler2 {
2046
2076
  };
2047
2077
 
2048
2078
  // src/importFromHtml/TableNodeHandler.ts
2049
- var import_node_html_parser22 = require("node-html-parser");
2079
+ var import_node_html_parser23 = require("node-html-parser");
2050
2080
  var REFERENCE_TABLE_WIDTH = 720;
2051
2081
  var MINIMUM_REFERENCE_TABLE_WIDTH = 500;
2052
- var isHtmlTableElement = (node) => node instanceof import_node_html_parser22.HTMLElement && node.tagName === "TABLE";
2082
+ var isHtmlTableElement = (node) => node instanceof import_node_html_parser23.HTMLElement && node.tagName === "TABLE";
2053
2083
  var TableNodeHandler2 = class extends NodeHandler2 {
2054
2084
  processNode(node) {
2055
2085
  if (!isHtmlTableElement(node)) return null;
@@ -2204,9 +2234,9 @@ var TableNodeHandler2 = class extends NodeHandler2 {
2204
2234
  };
2205
2235
 
2206
2236
  // src/importFromHtml/TableRowNodeHandler.ts
2207
- var import_node_html_parser23 = require("node-html-parser");
2237
+ var import_node_html_parser24 = require("node-html-parser");
2208
2238
  var isHtmlTableRowElement = (node) => {
2209
- return node instanceof import_node_html_parser23.HTMLElement && node.tagName === "TR";
2239
+ return node instanceof import_node_html_parser24.HTMLElement && node.tagName === "TR";
2210
2240
  };
2211
2241
  var TableRowNodeHandler2 = class extends NodeHandler2 {
2212
2242
  processNode(node) {
@@ -2229,8 +2259,8 @@ var TableRowNodeHandler2 = class extends NodeHandler2 {
2229
2259
  };
2230
2260
 
2231
2261
  // src/importFromHtml/TextNodeHandler.ts
2232
- var import_node_html_parser24 = require("node-html-parser");
2233
- var TextNode2 = import_node_html_parser24.parse.TextNode;
2262
+ var import_node_html_parser25 = require("node-html-parser");
2263
+ var TextNode2 = import_node_html_parser25.parse.TextNode;
2234
2264
  var TextNodeHandler2 = class extends NodeHandler2 {
2235
2265
  processNode(node) {
2236
2266
  if (node instanceof TextNode2 && !!node.parentNode.tagName) {
@@ -2253,10 +2283,10 @@ var TextNodeHandler2 = class extends NodeHandler2 {
2253
2283
  };
2254
2284
 
2255
2285
  // src/importFromHtml/VariableNodeHandler.ts
2256
- var import_node_html_parser25 = require("node-html-parser");
2286
+ var import_node_html_parser26 = require("node-html-parser");
2257
2287
  var VariableNodeHandler2 = class extends NodeHandler2 {
2258
2288
  processNode(node) {
2259
- if (!(node instanceof import_node_html_parser25.HTMLElement) || !node.tagName) return null;
2289
+ if (!(node instanceof import_node_html_parser26.HTMLElement) || !node.tagName) return null;
2260
2290
  if (node.tagName !== "x-param".toUpperCase()) return null;
2261
2291
  return {
2262
2292
  variableName: node.getAttribute("data-x-name") || "undefined",
@@ -2287,7 +2317,7 @@ function processChildren(node) {
2287
2317
  return result;
2288
2318
  }
2289
2319
  function processHtml(html) {
2290
- const root = (0, import_node_html_parser26.parse)(html);
2320
+ const root = (0, import_node_html_parser27.parse)(html);
2291
2321
  return processChildren(root);
2292
2322
  }
2293
2323
  function importFromHtml(html) {
package/dist/index.mjs CHANGED
@@ -129,7 +129,8 @@ var FillInTheBlankSpaceNodeHandler = class extends NodeHandler {
129
129
  `data-x-case-sensitive="${!!node.caseSensitive}"`,
130
130
  `data-x-errors-allowed="${node.errorsAllowed ?? 0}"`,
131
131
  `data-x-min-decimals="${node.minDecimals ?? ""}"`,
132
- `data-x-error-tolerance="${node.errorTolerance ?? 0}"`,
132
+ `data-x-error-tolerance="${(node.errorTolerance ?? 0) / 100}"`,
133
+ // Divide by 100 to convert percentage to rate
133
134
  `data-x-distractors="${node.distractors ?? ""}"`
134
135
  ];
135
136
  return attributes.join(" ");
@@ -311,6 +312,20 @@ function isSerializedJournalEntryQuestionNode(node) {
311
312
  return node?.type === "journal-entry-question" && "id" in node && typeof node.id === "string" && "points" in node && typeof node.points === "number" && "journalType" in node && typeof node.journalType === "string" && "lineItems" in node && Array.isArray(node.lineItems);
312
313
  }
313
314
 
315
+ // src/exportToHtml/createHtmlFromOnePerLineDistractorNodes.ts
316
+ function createHtmlFromOnePerLineDistractorNodes(distractorNodes, parentNode) {
317
+ const distractors = distractorNodes.map((node) => {
318
+ const distractorAccounts = createHtmlFromNestedEditor(
319
+ node.content,
320
+ { parentNode }
321
+ );
322
+ return distractorAccounts.split("<br>").filter((a) => a.trim()).map(
323
+ (a, i) => `<x-distractor id="${node.id}|${i}">${a}</x-distractor>`
324
+ ).join("");
325
+ }).join("");
326
+ return distractors;
327
+ }
328
+
314
329
  // src/exportToHtml/JournalEntryQuestionNodeHandler.ts
315
330
  var JournalEntryQuestionNodeHandler = class extends NodeHandler {
316
331
  processNode(node) {
@@ -364,16 +379,14 @@ var JournalEntryQuestionNodeHandler = class extends NodeHandler {
364
379
  return `<x-line-item id="${item.id}"><x-account>${accountContent}</x-account><x-debit>${debitContent}</x-debit><x-credit>${creditContent}</x-credit></x-line-item>`;
365
380
  }
366
381
  processDistractors(node) {
367
- const distractors = node.lineItems.filter((item) => !item.correct).map((item) => {
368
- const distractorAccounts = createHtmlFromNestedEditor(
369
- item.account,
370
- { parentNode: node }
371
- );
372
- return distractorAccounts.split("<br>").filter((a) => a.trim()).map(
373
- (a, i) => `<x-distractor id="${item.id}|${i}">${a}</x-distractor>`
374
- ).join("");
375
- }).join("");
376
- return distractors;
382
+ const distractorNodes = node.lineItems.filter((item) => !item.correct).map((item) => ({
383
+ id: item.id,
384
+ content: item.account
385
+ }));
386
+ return createHtmlFromOnePerLineDistractorNodes(
387
+ distractorNodes,
388
+ node
389
+ );
377
390
  }
378
391
  };
379
392
 
@@ -484,13 +497,14 @@ var MatchingQuestionNodeHandler = class extends NodeHandler {
484
497
  ).join("");
485
498
  }
486
499
  createDistractorsHtml(node) {
487
- const metadata = { parentNode: node };
488
- return node.items.filter((item) => !item.correct).map(
489
- (item) => `<x-distractor id="${item.id}">${createHtmlFromNestedEditor(
490
- item.itemOptionContent,
491
- metadata
492
- )}</x-distractor>`
493
- ).join("");
500
+ const distractorNodes = node.items.filter((item) => !item.correct).map((item) => ({
501
+ id: item.id,
502
+ content: item.itemOptionContent
503
+ }));
504
+ return createHtmlFromOnePerLineDistractorNodes(
505
+ distractorNodes,
506
+ node
507
+ );
494
508
  }
495
509
  };
496
510
 
@@ -989,7 +1003,7 @@ var createCaptionNode = (caption) => {
989
1003
  return [];
990
1004
  }
991
1005
  const captionNode = createEmptyParagraphNode("center");
992
- captionNode.children = caption.split("\n").reduce((nodes, line, index, lines) => {
1006
+ captionNode.children = caption.split("<br>").reduce((nodes, line, index, lines) => {
993
1007
  nodes.push({
994
1008
  detail: 0,
995
1009
  format: 0,
@@ -1085,7 +1099,7 @@ function processImageNodeContainer(node) {
1085
1099
  extractWidth(imageNode),
1086
1100
  extractFlexAlign(node),
1087
1101
  hasBorder(imageNode),
1088
- captionNode?.text
1102
+ captionNode?.innerHTML
1089
1103
  )
1090
1104
  ];
1091
1105
  }
@@ -1237,11 +1251,18 @@ var FillInTheBlankSpaceNodeHandler2 = class extends NodeHandler2 {
1237
1251
  errorsAllowed: node.getAttribute("data-x-errors-allowed") ? Number(node.getAttribute("data-x-errors-allowed")) : void 0
1238
1252
  };
1239
1253
  }
1254
+ parseErrorToleranceAttr(attr) {
1255
+ const value = Number(attr);
1256
+ if (isNaN(value)) return 0;
1257
+ else return value * 100;
1258
+ }
1240
1259
  processNumberSpace(node, baseNode) {
1241
1260
  return {
1242
1261
  ...baseNode,
1243
1262
  minDecimals: node.getAttribute("data-x-min-decimals") ? Number(node.getAttribute("data-x-min-decimals")) : void 0,
1244
- errorTolerance: node.getAttribute("data-x-error-tolerance") ? Number(node.getAttribute("data-x-error-tolerance")) : void 0
1263
+ errorTolerance: this.parseErrorToleranceAttr(
1264
+ node.getAttribute("data-x-error-tolerance")
1265
+ )
1245
1266
  };
1246
1267
  }
1247
1268
  processDropdownSpace(node, baseNode) {
@@ -1477,22 +1498,49 @@ var ImageNodeHandler2 = class extends NodeHandler2 {
1477
1498
  };
1478
1499
 
1479
1500
  // src/importFromHtml/JournalEntryQuestionNodeHandler.ts
1501
+ import { nanoid as nanoid6 } from "nanoid";
1502
+ import { HTMLElement as HTMLElement11 } from "node-html-parser";
1503
+
1504
+ // src/importFromHtml/createOnePerLineDistractorNode.ts
1480
1505
  import { nanoid as nanoid5 } from "nanoid";
1481
1506
  import { HTMLElement as HTMLElement10 } from "node-html-parser";
1482
- var extractDistractorId = (id) => {
1507
+ function extractDistractorId(id) {
1483
1508
  if (!id) return null;
1484
1509
  const parts = id.split("|");
1485
- return parts.length === 2 ? parts[0] : null;
1510
+ return parts[0] ? parts[0] : null;
1511
+ }
1512
+ var createOnePerLineDistractorNode = (node) => {
1513
+ const distractorEditor = createNestedEditorFromHtml(null);
1514
+ const distractors = node.querySelectorAll("x-distractor");
1515
+ const emptyDistractorEditorChildren = distractorEditor.editorState.root.children;
1516
+ distractorEditor.editorState.root.children = [];
1517
+ let distractorId = null;
1518
+ distractors.forEach((distractor) => {
1519
+ if (!(distractor instanceof HTMLElement10)) return;
1520
+ distractorId = distractorId ?? extractDistractorId(distractor.getAttribute("id"));
1521
+ distractorEditor.editorState.root.children.push(
1522
+ ...createNestedNodesFromHtml(distractor)
1523
+ );
1524
+ });
1525
+ if (!distractorEditor.editorState.root.children.length) {
1526
+ distractorEditor.editorState.root.children = emptyDistractorEditorChildren;
1527
+ }
1528
+ return {
1529
+ id: distractorId ?? nanoid5(),
1530
+ content: distractorEditor
1531
+ };
1486
1532
  };
1533
+
1534
+ // src/importFromHtml/JournalEntryQuestionNodeHandler.ts
1487
1535
  var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1488
1536
  processNode(node) {
1489
- if (!(node instanceof HTMLElement10) || node.tagName !== "x-journal-entry".toUpperCase())
1537
+ if (!(node instanceof HTMLElement11) || node.tagName !== "x-journal-entry".toUpperCase())
1490
1538
  return null;
1491
1539
  const noEntryRequiredCorrect = node.getAttribute("data-x-no-entry-required-correct") === "true";
1492
1540
  const noEntryRequiredDistractor = node.getAttribute("data-x-no-entry-required-distractor") === "true";
1493
1541
  const journalType = noEntryRequiredCorrect ? "noEntryRequiredCorrect" : noEntryRequiredDistractor ? "noEntryRequiredDistractor" : "default";
1494
1542
  const jsonNode = {
1495
- id: node.getAttribute("id") ?? nanoid5(),
1543
+ id: node.getAttribute("id") ?? nanoid6(),
1496
1544
  points: Number(node.getAttribute("data-x-points") ?? 1),
1497
1545
  journalType,
1498
1546
  errorTolerance: node.getAttribute("data-x-error-tolerance") ? Number(node.getAttribute("data-x-error-tolerance")) : void 0,
@@ -1502,54 +1550,39 @@ var JournalEntryQuestionNodeHandler2 = class extends NodeHandler2 {
1502
1550
  };
1503
1551
  const lineItems = node.querySelectorAll("x-line-item");
1504
1552
  lineItems.forEach((lineItem) => {
1505
- if (!(lineItem instanceof HTMLElement10)) return;
1553
+ if (!(lineItem instanceof HTMLElement11)) return;
1506
1554
  const accountElement = lineItem.querySelector("x-account");
1507
1555
  const debitElement = lineItem.querySelector("x-debit");
1508
1556
  const creditElement = lineItem.querySelector("x-credit");
1509
1557
  if (!accountElement) return;
1510
- const item2 = {
1511
- id: lineItem.getAttribute("id") ?? nanoid5(),
1558
+ const item = {
1559
+ id: lineItem.getAttribute("id") ?? nanoid6(),
1512
1560
  correct: true,
1513
1561
  account: createNestedEditorFromHtml(accountElement)
1514
1562
  };
1515
1563
  if (debitElement) {
1516
- item2.debit = createNestedEditorFromHtml(debitElement);
1564
+ item.debit = createNestedEditorFromHtml(debitElement);
1517
1565
  }
1518
1566
  if (creditElement) {
1519
- item2.credit = createNestedEditorFromHtml(creditElement);
1567
+ item.credit = createNestedEditorFromHtml(creditElement);
1520
1568
  }
1521
- jsonNode.lineItems.push(item2);
1522
- });
1523
- const distractorEditor = createNestedEditorFromHtml(null);
1524
- const distractors = node.querySelectorAll("x-distractor");
1525
- const emptyDistractorEditorChildren = distractorEditor.editorState.root.children;
1526
- distractorEditor.editorState.root.children = [];
1527
- let distractorId = null;
1528
- distractors.forEach((distractor) => {
1529
- if (!(distractor instanceof HTMLElement10)) return;
1530
- distractorId = distractorId ?? extractDistractorId(distractor.getAttribute("id"));
1531
- distractorEditor.editorState.root.children.push(
1532
- ...createNestedNodesFromHtml(distractor)
1533
- );
1569
+ jsonNode.lineItems.push(item);
1534
1570
  });
1535
- if (!distractorEditor.editorState.root.children.length) {
1536
- distractorEditor.editorState.root.children = emptyDistractorEditorChildren;
1537
- }
1538
- const item = {
1539
- id: distractorId ?? nanoid5(),
1571
+ const distractorNode = createOnePerLineDistractorNode(node);
1572
+ jsonNode.lineItems.push({
1573
+ id: distractorNode.id,
1540
1574
  correct: false,
1541
- account: distractorEditor
1542
- };
1543
- jsonNode.lineItems.push(item);
1575
+ account: distractorNode.content
1576
+ });
1544
1577
  return jsonNode;
1545
1578
  }
1546
1579
  };
1547
1580
 
1548
1581
  // src/importFromHtml/LineBreakNodeHandler.ts
1549
- import { HTMLElement as HTMLElement11 } from "node-html-parser";
1582
+ import { HTMLElement as HTMLElement12 } from "node-html-parser";
1550
1583
  var LineBreakNodeHandler2 = class extends NodeHandler2 {
1551
1584
  processNode(node) {
1552
- if (!(node instanceof HTMLElement11)) return null;
1585
+ if (!(node instanceof HTMLElement12)) return null;
1553
1586
  if (node.tagName !== "BR") return null;
1554
1587
  return {
1555
1588
  type: "linebreak",
@@ -1559,11 +1592,11 @@ var LineBreakNodeHandler2 = class extends NodeHandler2 {
1559
1592
  };
1560
1593
 
1561
1594
  // src/importFromHtml/LinkNodeHandler.ts
1562
- import { HTMLElement as HTMLElement12 } from "node-html-parser";
1595
+ import { HTMLElement as HTMLElement13 } from "node-html-parser";
1563
1596
  var TAG_A = "a";
1564
1597
  var LinkNodeHandler2 = class extends NodeHandler2 {
1565
1598
  processNode(node) {
1566
- if (!(node instanceof HTMLElement12) || node.tagName !== TAG_A.toUpperCase()) {
1599
+ if (!(node instanceof HTMLElement13) || node.tagName !== TAG_A.toUpperCase()) {
1567
1600
  return null;
1568
1601
  }
1569
1602
  const url = node.getAttribute("href") || "";
@@ -1592,10 +1625,10 @@ var LinkNodeHandler2 = class extends NodeHandler2 {
1592
1625
  };
1593
1626
 
1594
1627
  // src/importFromHtml/ListItemNodeHandler.ts
1595
- import { HTMLElement as HTMLElement13 } from "node-html-parser";
1628
+ import { HTMLElement as HTMLElement14 } from "node-html-parser";
1596
1629
  var ListItemNodeHandler2 = class extends NodeHandler2 {
1597
1630
  processNode(node) {
1598
- if (!(node instanceof HTMLElement13)) return null;
1631
+ if (!(node instanceof HTMLElement14)) return null;
1599
1632
  if (node.tagName !== "LI") return null;
1600
1633
  const jsonNode = {
1601
1634
  type: "listitem",
@@ -1616,10 +1649,10 @@ var ListItemNodeHandler2 = class extends NodeHandler2 {
1616
1649
  };
1617
1650
 
1618
1651
  // src/importFromHtml/ListNodeHandler.ts
1619
- import { HTMLElement as HTMLElement14 } from "node-html-parser";
1652
+ import { HTMLElement as HTMLElement15 } from "node-html-parser";
1620
1653
  var ListNodeHandler2 = class extends NodeHandler2 {
1621
1654
  processNode(node) {
1622
- if (!(node instanceof HTMLElement14)) return null;
1655
+ if (!(node instanceof HTMLElement15)) return null;
1623
1656
  if (node.tagName !== "UL" && node.tagName !== "OL") return null;
1624
1657
  const tag = node.tagName.toLowerCase();
1625
1658
  const listType = tag === "ol" ? "number" : "bullet";
@@ -1637,7 +1670,7 @@ var ListNodeHandler2 = class extends NodeHandler2 {
1637
1670
  };
1638
1671
  let itemIndex = 1;
1639
1672
  node.childNodes.forEach((child) => {
1640
- if (child instanceof HTMLElement14 && child.tagName === "LI") {
1673
+ if (child instanceof HTMLElement15 && child.tagName === "LI") {
1641
1674
  const listItemNode = {
1642
1675
  type: "listitem",
1643
1676
  version: 1,
@@ -1661,14 +1694,14 @@ var ListNodeHandler2 = class extends NodeHandler2 {
1661
1694
  };
1662
1695
 
1663
1696
  // src/importFromHtml/MatchingQuestionNodeHandler.ts
1664
- import { nanoid as nanoid6 } from "nanoid";
1665
- import { HTMLElement as HTMLElement15 } from "node-html-parser";
1697
+ import { nanoid as nanoid7 } from "nanoid";
1698
+ import { HTMLElement as HTMLElement16 } from "node-html-parser";
1666
1699
  var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1667
1700
  processNode(node) {
1668
- if (!(node instanceof HTMLElement15) || node.tagName !== "x-matching".toUpperCase())
1701
+ if (!(node instanceof HTMLElement16) || node.tagName !== "x-matching".toUpperCase())
1669
1702
  return null;
1670
1703
  const jsonNode = {
1671
- id: node.getAttribute("id") ?? nanoid6(),
1704
+ id: node.getAttribute("id") ?? nanoid7(),
1672
1705
  pointsPerMatch: Number(
1673
1706
  node.getAttribute("data-x-points-per-match") ?? 1
1674
1707
  ),
@@ -1676,38 +1709,35 @@ var MatchingQuestionNodeHandler2 = class extends NodeHandler2 {
1676
1709
  type: "matching-question",
1677
1710
  version: 1
1678
1711
  };
1679
- const childNodes = node.childNodes;
1680
- childNodes.forEach((child) => {
1681
- if (!(child instanceof HTMLElement15)) return;
1682
- if (child.tagName === "x-match".toUpperCase()) {
1683
- const premise = child.querySelector("x-premise");
1684
- const option = child.querySelector("x-option");
1685
- if (!premise || !option) return;
1686
- jsonNode.items.push({
1687
- id: premise.getAttribute("id") ?? nanoid6(),
1688
- correct: true,
1689
- itemPremiseContent: createNestedEditorFromHtml(premise),
1690
- itemOptionContent: createNestedEditorFromHtml(option)
1691
- });
1692
- }
1693
- if (child.tagName === "x-distractor".toUpperCase()) {
1694
- jsonNode.items.push({
1695
- id: child.getAttribute("id") ?? nanoid6(),
1696
- correct: false,
1697
- itemOptionContent: createNestedEditorFromHtml(child)
1698
- });
1699
- }
1712
+ const matches = node.querySelectorAll("x-match");
1713
+ matches.forEach((match) => {
1714
+ if (!(match instanceof HTMLElement16)) return;
1715
+ const premise = match.querySelector("x-premise");
1716
+ const option = match.querySelector("x-option");
1717
+ if (!premise || !option) return;
1718
+ jsonNode.items.push({
1719
+ id: premise.getAttribute("id") ?? nanoid7(),
1720
+ correct: true,
1721
+ itemPremiseContent: createNestedEditorFromHtml(premise),
1722
+ itemOptionContent: createNestedEditorFromHtml(option)
1723
+ });
1724
+ });
1725
+ const distractorNode = createOnePerLineDistractorNode(node);
1726
+ jsonNode.items.push({
1727
+ id: distractorNode.id,
1728
+ correct: false,
1729
+ itemOptionContent: distractorNode.content
1700
1730
  });
1701
1731
  return jsonNode;
1702
1732
  }
1703
1733
  };
1704
1734
 
1705
1735
  // src/importFromHtml/MultipleOptionQuestionNodeHandler.ts
1706
- import { nanoid as nanoid7 } from "nanoid";
1707
- import { HTMLElement as HTMLElement16 } from "node-html-parser";
1736
+ import { nanoid as nanoid8 } from "nanoid";
1737
+ import { HTMLElement as HTMLElement17 } from "node-html-parser";
1708
1738
  var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1709
1739
  processNode(node) {
1710
- if (!(node instanceof HTMLElement16)) return null;
1740
+ if (!(node instanceof HTMLElement17)) return null;
1711
1741
  if (node.tagName === "x-multiple-choice".toUpperCase())
1712
1742
  return this.processMultipleChoiceNode(node);
1713
1743
  else if (node.tagName === "x-multiple-answers".toUpperCase())
@@ -1717,7 +1747,7 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1717
1747
  processMultipleChoiceNode(node) {
1718
1748
  const jsonNode = {
1719
1749
  options: [],
1720
- id: node.getAttribute("id") ?? nanoid7(),
1750
+ id: node.getAttribute("id") ?? nanoid8(),
1721
1751
  questionType: "multiple-choice",
1722
1752
  points: Number(node.getAttribute("data-x-points") || 0),
1723
1753
  choices: node.getAttribute("data-x-choices") ? Number(node.getAttribute("data-x-choices")) : void 0,
@@ -1731,7 +1761,7 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1731
1761
  processMultipleAnswersNode(node) {
1732
1762
  const jsonNode = {
1733
1763
  options: [],
1734
- id: node.getAttribute("id") ?? nanoid7(),
1764
+ id: node.getAttribute("id") ?? nanoid8(),
1735
1765
  questionType: "multiple-answers",
1736
1766
  points: Number(node.getAttribute("data-x-points") || 0),
1737
1767
  correctChoices: node.getAttribute("data-x-correct-choices") ? Number(node.getAttribute("data-x-correct-choices")) : void 0,
@@ -1747,10 +1777,10 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1747
1777
  processOptions(node, jsonNode) {
1748
1778
  const childNodes = node.childNodes;
1749
1779
  childNodes.forEach((child) => {
1750
- if (!(child instanceof HTMLElement16)) return;
1780
+ if (!(child instanceof HTMLElement17)) return;
1751
1781
  if (child.tagName !== "x-option".toUpperCase()) return;
1752
1782
  jsonNode.options.push({
1753
- id: child.getAttribute("id") ?? nanoid7(),
1783
+ id: child.getAttribute("id") ?? nanoid8(),
1754
1784
  correct: child.getAttribute("data-x-correct") === "true",
1755
1785
  content: createNestedEditorFromHtml(child)
1756
1786
  });
@@ -1759,7 +1789,7 @@ var MultipleOptionQuestionNodeHandler2 = class extends NodeHandler2 {
1759
1789
  };
1760
1790
 
1761
1791
  // src/importFromHtml/ParagraphNodeHandler.ts
1762
- import { HTMLElement as HTMLElement17 } from "node-html-parser";
1792
+ import { HTMLElement as HTMLElement18 } from "node-html-parser";
1763
1793
  var TEXT_ALIGN_TO_FORMAT = {
1764
1794
  center: "center",
1765
1795
  end: "end",
@@ -1782,25 +1812,25 @@ var ParagraphNodeHandler2 = class extends NodeHandler2 {
1782
1812
  return "";
1783
1813
  }
1784
1814
  processImageNode(node) {
1785
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement17 && node.childNodes[0].tagName === "IMG") {
1815
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement18 && node.childNodes[0].tagName === "IMG") {
1786
1816
  return traverse2(node.childNodes[0]);
1787
1817
  }
1788
1818
  return null;
1789
1819
  }
1790
1820
  processSpanImageNode(node) {
1791
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement17 && node.childNodes[0].tagName === "SPAN" && node.childNodes[0].childNodes.length === 1 && node.childNodes[0].childNodes[0] instanceof HTMLElement17 && node.childNodes[0].childNodes[0].tagName === "IMG") {
1821
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement18 && node.childNodes[0].tagName === "SPAN" && node.childNodes[0].childNodes.length === 1 && node.childNodes[0].childNodes[0] instanceof HTMLElement18 && node.childNodes[0].childNodes[0].tagName === "IMG") {
1792
1822
  return traverse2(node.childNodes[0].childNodes[0]);
1793
1823
  }
1794
1824
  return null;
1795
1825
  }
1796
1826
  processNode(node) {
1797
- if (!(node instanceof HTMLElement17)) return null;
1827
+ if (!(node instanceof HTMLElement18)) return null;
1798
1828
  if (node.tagName !== "P") return null;
1799
1829
  const imageNode = this.processImageNode(node) ?? this.processSpanImageNode(node);
1800
1830
  if (imageNode) return imageNode;
1801
1831
  const jsonNode = createEmptyParagraphNode();
1802
1832
  jsonNode.format = this.extractTextAlignment(node);
1803
- if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement17 && node.childNodes[0].tagName === "BR")
1833
+ if (node.childNodes.length === 1 && node.childNodes[0] instanceof HTMLElement18 && node.childNodes[0].tagName === "BR")
1804
1834
  return jsonNode;
1805
1835
  node.childNodes.forEach((child) => {
1806
1836
  const processedChildren = traverse2(child);
@@ -1811,14 +1841,14 @@ var ParagraphNodeHandler2 = class extends NodeHandler2 {
1811
1841
  };
1812
1842
 
1813
1843
  // src/importFromHtml/ShortAnswerQuestionNodeHandler.ts
1814
- import { nanoid as nanoid8 } from "nanoid";
1815
- import { HTMLElement as HTMLElement18 } from "node-html-parser";
1844
+ import { nanoid as nanoid9 } from "nanoid";
1845
+ import { HTMLElement as HTMLElement19 } from "node-html-parser";
1816
1846
  var ShortAnswerQuestionNodeHandler2 = class extends NodeHandler2 {
1817
1847
  processNode(node) {
1818
- if (!(node instanceof HTMLElement18) || node.tagName !== "x-short-answer".toUpperCase())
1848
+ if (!(node instanceof HTMLElement19) || node.tagName !== "x-short-answer".toUpperCase())
1819
1849
  return null;
1820
1850
  return {
1821
- id: node.getAttribute("id") ?? nanoid8(),
1851
+ id: node.getAttribute("id") ?? nanoid9(),
1822
1852
  points: Number(node.getAttribute("data-x-points") ?? 1),
1823
1853
  maxWords: Number(node.getAttribute("data-x-max-words") ?? 100),
1824
1854
  notes: createNestedEditorFromHtml(
@@ -1831,13 +1861,13 @@ var ShortAnswerQuestionNodeHandler2 = class extends NodeHandler2 {
1831
1861
  };
1832
1862
 
1833
1863
  // src/importFromHtml/SimulationQuestionNodeHandler.ts
1834
- import { HTMLElement as HTMLElement19 } from "node-html-parser";
1864
+ import { HTMLElement as HTMLElement20 } from "node-html-parser";
1835
1865
  var TAG_X_SIMULATION = "x-simulation";
1836
1866
  var TAG_X_SYSTEM_MESSAGE2 = "x-ai-system-message";
1837
1867
  var TAG_X_STEP2_INSTRUCTIONS = "x-step2-instructions";
1838
1868
  var SimulationQuestionNodeHandler2 = class extends NodeHandler2 {
1839
1869
  processNode(node) {
1840
- if (!(node instanceof HTMLElement19) || node.tagName !== TAG_X_SIMULATION.toUpperCase()) {
1870
+ if (!(node instanceof HTMLElement20) || node.tagName !== TAG_X_SIMULATION.toUpperCase()) {
1841
1871
  return null;
1842
1872
  }
1843
1873
  const jsonNode = {
@@ -1864,11 +1894,11 @@ var SimulationQuestionNodeHandler2 = class extends NodeHandler2 {
1864
1894
  };
1865
1895
 
1866
1896
  // src/importFromHtml/SpanNodeHandler.ts
1867
- import { HTMLElement as HTMLElement20, parse } from "node-html-parser";
1897
+ import { HTMLElement as HTMLElement21, parse } from "node-html-parser";
1868
1898
  var TextNode = parse.TextNode;
1869
1899
  var SpanNodeHandler = class extends NodeHandler2 {
1870
1900
  processNode(node) {
1871
- if (!(node instanceof HTMLElement20) || node.tagName !== "SPAN")
1901
+ if (!(node instanceof HTMLElement21) || node.tagName !== "SPAN")
1872
1902
  return null;
1873
1903
  const styleAttr = node.getAttribute("style") || "";
1874
1904
  if (node.childNodes.length === 1 && node.childNodes[0] instanceof TextNode) {
@@ -1928,7 +1958,7 @@ var SpanNodeHandler = class extends NodeHandler2 {
1928
1958
  };
1929
1959
 
1930
1960
  // src/importFromHtml/TableCellNodeHandler.ts
1931
- import { HTMLElement as HTMLElement21 } from "node-html-parser";
1961
+ import { HTMLElement as HTMLElement22 } from "node-html-parser";
1932
1962
 
1933
1963
  // src/utils/styleUtils.ts
1934
1964
  var extractStyleValue = (styleAttr, property, isNumeric = false, unit = "") => {
@@ -1977,7 +2007,7 @@ function createEmptyTableCellNode(isHeader = false) {
1977
2007
 
1978
2008
  // src/importFromHtml/TableCellNodeHandler.ts
1979
2009
  var isHtmlTableCellElement = (node) => {
1980
- return node instanceof HTMLElement21 && (node.tagName === "TD" || node.tagName === "TH");
2010
+ return node instanceof HTMLElement22 && (node.tagName === "TD" || node.tagName === "TH");
1981
2011
  };
1982
2012
  var TableCellNodeHandler2 = class extends NodeHandler2 {
1983
2013
  processNode(node) {
@@ -2019,10 +2049,10 @@ var TableCellNodeHandler2 = class extends NodeHandler2 {
2019
2049
  };
2020
2050
 
2021
2051
  // src/importFromHtml/TableNodeHandler.ts
2022
- import { HTMLElement as HTMLElement22 } from "node-html-parser";
2052
+ import { HTMLElement as HTMLElement23 } from "node-html-parser";
2023
2053
  var REFERENCE_TABLE_WIDTH = 720;
2024
2054
  var MINIMUM_REFERENCE_TABLE_WIDTH = 500;
2025
- var isHtmlTableElement = (node) => node instanceof HTMLElement22 && node.tagName === "TABLE";
2055
+ var isHtmlTableElement = (node) => node instanceof HTMLElement23 && node.tagName === "TABLE";
2026
2056
  var TableNodeHandler2 = class extends NodeHandler2 {
2027
2057
  processNode(node) {
2028
2058
  if (!isHtmlTableElement(node)) return null;
@@ -2177,9 +2207,9 @@ var TableNodeHandler2 = class extends NodeHandler2 {
2177
2207
  };
2178
2208
 
2179
2209
  // src/importFromHtml/TableRowNodeHandler.ts
2180
- import { HTMLElement as HTMLElement23 } from "node-html-parser";
2210
+ import { HTMLElement as HTMLElement24 } from "node-html-parser";
2181
2211
  var isHtmlTableRowElement = (node) => {
2182
- return node instanceof HTMLElement23 && node.tagName === "TR";
2212
+ return node instanceof HTMLElement24 && node.tagName === "TR";
2183
2213
  };
2184
2214
  var TableRowNodeHandler2 = class extends NodeHandler2 {
2185
2215
  processNode(node) {
@@ -2226,10 +2256,10 @@ var TextNodeHandler2 = class extends NodeHandler2 {
2226
2256
  };
2227
2257
 
2228
2258
  // src/importFromHtml/VariableNodeHandler.ts
2229
- import { HTMLElement as HTMLElement24 } from "node-html-parser";
2259
+ import { HTMLElement as HTMLElement25 } from "node-html-parser";
2230
2260
  var VariableNodeHandler2 = class extends NodeHandler2 {
2231
2261
  processNode(node) {
2232
- if (!(node instanceof HTMLElement24) || !node.tagName) return null;
2262
+ if (!(node instanceof HTMLElement25) || !node.tagName) return null;
2233
2263
  if (node.tagName !== "x-param".toUpperCase()) return null;
2234
2264
  return {
2235
2265
  variableName: node.getAttribute("data-x-name") || "undefined",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@examind/block-sdk",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
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.22"
24
+ "@examind/block-types": "^0.1.24"
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.22"
39
+ "@examind/block-types": "0.1.24"
40
40
  },
41
41
  "dependencies": {
42
42
  "lodash-es": "4.17.21"