html-react-parser 5.2.15 → 5.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -614,9 +614,9 @@ npm run benchmark
614
614
  Output of benchmark run on MacBook Pro 2024:
615
615
 
616
616
  ```
617
- html-to-react - Single x 1,230,874 ops/sec ±0.21% (97 runs sampled)
618
- html-to-react - Multiple x 502,028 ops/sec ±0.89% (94 runs sampled)
619
- html-to-react - Complex x 54,401 ops/sec ±0.76% (93 runs sampled)
617
+ html-to-react - Single x 1,270,990 ops/sec ±0.21% (100 runs sampled)
618
+ html-to-react - Multiple x 522,472 ops/sec ±0.64% (94 runs sampled)
619
+ html-to-react - Complex x 54,028 ops/sec ±0.82% (98 runs sampled)
620
620
  ```
621
621
 
622
622
  Run [Size Limit](https://github.com/ai/size-limit):
@@ -810,7 +810,7 @@
810
810
  }, {});
811
811
  exports$1.CARRIAGE_RETURN = '\r';
812
812
  exports$1.CARRIAGE_RETURN_REGEX = new RegExp(exports$1.CARRIAGE_RETURN, 'g');
813
- exports$1.CARRIAGE_RETURN_PLACEHOLDER = "__HTML_DOM_PARSER_CARRIAGE_RETURN_PLACEHOLDER_".concat(Date.now(), "__");
813
+ exports$1.CARRIAGE_RETURN_PLACEHOLDER = "__HTML_DOM_PARSER_CARRIAGE_RETURN_PLACEHOLDER_".concat(Date.now().toString(), "__");
814
814
  exports$1.CARRIAGE_RETURN_PLACEHOLDER_REGEX = new RegExp(exports$1.CARRIAGE_RETURN_PLACEHOLDER, 'g');
815
815
 
816
816
  } (constants));
@@ -824,6 +824,7 @@
824
824
  hasRequiredUtilities$2 = 1;
825
825
  Object.defineProperty(utilities$2, "__esModule", { value: true });
826
826
  utilities$2.formatAttributes = formatAttributes;
827
+ utilities$2.hasOpenTag = hasOpenTag;
827
828
  utilities$2.escapeSpecialCharacters = escapeSpecialCharacters;
828
829
  utilities$2.revertEscapedCharacters = revertEscapedCharacters;
829
830
  utilities$2.formatDOM = formatDOM;
@@ -870,6 +871,28 @@
870
871
  }
871
872
  return tagName;
872
873
  }
874
+ /**
875
+ * Checks if an HTML string contains an opening tag (case-insensitive).
876
+ *
877
+ * @param html - HTML string.
878
+ * @param tagName - Tag name to search for (e.g., 'head' or 'body').
879
+ * @returns - Whether the tag is found.
880
+ */
881
+ function hasOpenTag(html, tagName) {
882
+ var openTag = '<' + tagName;
883
+ var index = html.toLowerCase().indexOf(openTag);
884
+ if (index === -1) {
885
+ return false;
886
+ }
887
+ var char = html[index + openTag.length];
888
+ // the character after the tag name must be '>' or whitespace (for attributes)
889
+ return (char === '>' ||
890
+ char === ' ' ||
891
+ char === '\t' ||
892
+ char === '\n' ||
893
+ char === '\r' ||
894
+ char === '/');
895
+ }
873
896
  /**
874
897
  * Escapes special characters before parsing.
875
898
  *
@@ -897,6 +920,7 @@
897
920
  * @returns - Nodes.
898
921
  */
899
922
  function formatDOM(nodes, parent, directive) {
923
+ var _a, _b, _c, _d;
900
924
  if (parent === void 0) { parent = null; }
901
925
  var domNodes = [];
902
926
  var current;
@@ -918,16 +942,17 @@
918
942
  break;
919
943
  }
920
944
  case 3:
921
- current = new domhandler_1.Text(revertEscapedCharacters(node.nodeValue));
945
+ current = new domhandler_1.Text(revertEscapedCharacters((_a = node.nodeValue) !== null && _a !== void 0 ? _a : ''));
922
946
  break;
923
947
  case 8:
924
- current = new domhandler_1.Comment(node.nodeValue);
948
+ current = new domhandler_1.Comment((_b = node.nodeValue) !== null && _b !== void 0 ? _b : '');
925
949
  break;
926
950
  default:
927
951
  continue;
928
952
  }
929
953
  // set previous node next
930
- var prev = domNodes[index - 1] || null;
954
+ var prev = (_c = domNodes[index - 1]) !== null && _c !== void 0 ? _c : null;
955
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
931
956
  if (prev) {
932
957
  prev.next = current;
933
958
  }
@@ -939,7 +964,7 @@
939
964
  }
940
965
  if (directive) {
941
966
  current = new domhandler_1.ProcessingInstruction(directive.substring(0, directive.indexOf(' ')).toLowerCase(), directive);
942
- current.next = domNodes[0] || null;
967
+ current.next = (_d = domNodes[0]) !== null && _d !== void 0 ? _d : null;
943
968
  current.parent = parent;
944
969
  domNodes.unshift(current);
945
970
  if (domNodes[1]) {
@@ -965,20 +990,17 @@
965
990
  var HEAD = 'head';
966
991
  var BODY = 'body';
967
992
  var FIRST_TAG_REGEX = /<([a-zA-Z]+[0-9]?)/; // e.g., <h1>
968
- // match-all-characters in case of newlines (DOTALL)
969
- var HEAD_TAG_REGEX = /<head[^]*>/i;
970
- var BODY_TAG_REGEX = /<body[^]*>/i;
971
993
  // falls back to `parseFromString` if `createHTMLDocument` cannot be used
972
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
994
+ /* eslint-disable @typescript-eslint/no-unused-vars */
995
+ /* istanbul ignore start */
973
996
  var parseFromDocument = function (html, tagName) {
974
- /* istanbul ignore next */
975
997
  throw new Error('This browser does not support `document.implementation.createHTMLDocument`');
976
998
  };
977
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
978
999
  var parseFromString = function (html, tagName) {
979
- /* istanbul ignore next */
980
1000
  throw new Error('This browser does not support `DOMParser.prototype.parseFromString`');
981
1001
  };
1002
+ /* istanbul ignore stop */
1003
+ /* eslint-enable @typescript-eslint/no-unused-vars */
982
1004
  var DOMParser = typeof window === 'object' && window.DOMParser;
983
1005
  /**
984
1006
  * DOMParser (performance: slow).
@@ -996,10 +1018,11 @@
996
1018
  * @returns - Document.
997
1019
  */
998
1020
  parseFromString = function (html, tagName) {
1021
+ /* istanbul ignore start */
999
1022
  if (tagName) {
1000
- /* istanbul ignore next */
1001
1023
  html = "<".concat(tagName, ">").concat(html, "</").concat(tagName, ">");
1002
1024
  }
1025
+ /* istanbul ignore stop */
1003
1026
  return domParser_1.parseFromString(html, mimeType_1);
1004
1027
  };
1005
1028
  parseFromDocument = parseFromString;
@@ -1009,6 +1032,7 @@
1009
1032
  *
1010
1033
  * @see https://developer.mozilla.org/docs/Web/API/DOMImplementation/createHTMLDocument
1011
1034
  */
1035
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1012
1036
  if (typeof document === 'object' && document.implementation) {
1013
1037
  var htmlDocument_1 = document.implementation.createHTMLDocument();
1014
1038
  /**
@@ -1019,6 +1043,7 @@
1019
1043
  * @returns - Document
1020
1044
  */
1021
1045
  parseFromDocument = function (html, tagName) {
1046
+ /* istanbul ignore start */
1022
1047
  if (tagName) {
1023
1048
  var element = htmlDocument_1.documentElement.querySelector(tagName);
1024
1049
  if (element) {
@@ -1026,6 +1051,7 @@
1026
1051
  }
1027
1052
  return htmlDocument_1;
1028
1053
  }
1054
+ /* istanbul ignore stop */
1029
1055
  htmlDocument_1.documentElement.innerHTML = html;
1030
1056
  return htmlDocument_1;
1031
1057
  };
@@ -1037,6 +1063,7 @@
1037
1063
  */
1038
1064
  var template = typeof document === 'object' && document.createElement('template');
1039
1065
  var parseFromTemplate;
1066
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1040
1067
  if (template && template.content) {
1041
1068
  /**
1042
1069
  * Uses a template element (content fragment) to parse HTML.
@@ -1049,6 +1076,9 @@
1049
1076
  return template.content.childNodes;
1050
1077
  };
1051
1078
  }
1079
+ var createNodeList = /* istanbul ignore next */ function () {
1080
+ return document.createDocumentFragment().childNodes;
1081
+ };
1052
1082
  /**
1053
1083
  * Parses HTML string to DOM nodes.
1054
1084
  *
@@ -1056,23 +1086,25 @@
1056
1086
  * @returns - DOM nodes.
1057
1087
  */
1058
1088
  function domparser$1(html) {
1059
- var _a, _b;
1089
+ var _a, _b, _c, _d, _e, _f;
1060
1090
  // Escape special characters before parsing
1061
1091
  html = (0, utilities_1.escapeSpecialCharacters)(html);
1062
- var match = html.match(FIRST_TAG_REGEX);
1063
- var firstTagName = match && match[1] ? match[1].toLowerCase() : '';
1092
+ var match = FIRST_TAG_REGEX.exec(html);
1093
+ var firstTagName = (_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.toLowerCase();
1064
1094
  switch (firstTagName) {
1065
1095
  case HTML: {
1066
1096
  var doc = parseFromString(html);
1067
1097
  // the created document may come with filler head/body elements,
1068
1098
  // so make sure to remove them if they don't actually exist
1069
- if (!HEAD_TAG_REGEX.test(html)) {
1099
+ if (!(0, utilities_1.hasOpenTag)(html, HEAD)) {
1070
1100
  var element = doc.querySelector(HEAD);
1071
- (_a = element === null || element === void 0 ? void 0 : element.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(element);
1101
+ /* istanbul ignore next */
1102
+ (_b = element === null || element === void 0 ? void 0 : element.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(element);
1072
1103
  }
1073
- if (!BODY_TAG_REGEX.test(html)) {
1104
+ if (!(0, utilities_1.hasOpenTag)(html, BODY)) {
1074
1105
  var element = doc.querySelector(BODY);
1075
- (_b = element === null || element === void 0 ? void 0 : element.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(element);
1106
+ /* istanbul ignore next */
1107
+ (_c = element === null || element === void 0 ? void 0 : element.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(element);
1076
1108
  }
1077
1109
  return doc.querySelectorAll(HTML);
1078
1110
  }
@@ -1080,18 +1112,22 @@
1080
1112
  case BODY: {
1081
1113
  var elements = parseFromDocument(html).querySelectorAll(firstTagName);
1082
1114
  // if there's a sibling element, then return both elements
1083
- if (BODY_TAG_REGEX.test(html) && HEAD_TAG_REGEX.test(html)) {
1084
- return elements[0].parentNode.childNodes;
1115
+ if ((0, utilities_1.hasOpenTag)(html, BODY) && (0, utilities_1.hasOpenTag)(html, HEAD)) {
1116
+ /* istanbul ignore next */
1117
+ return (_e = (_d = elements[0].parentNode) === null || _d === void 0 ? void 0 : _d.childNodes) !== null && _e !== void 0 ? _e : createNodeList();
1085
1118
  }
1086
1119
  return elements;
1087
1120
  }
1088
1121
  // low-level tag or text
1089
1122
  default: {
1123
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1090
1124
  if (parseFromTemplate) {
1091
1125
  return parseFromTemplate(html);
1092
1126
  }
1127
+ /* istanbul ignore start */
1093
1128
  var element = parseFromDocument(html, BODY).querySelector(BODY);
1094
- return element.childNodes;
1129
+ return (_f = element === null || element === void 0 ? void 0 : element.childNodes) !== null && _f !== void 0 ? _f : createNodeList();
1130
+ /* istanbul ignore stop */
1095
1131
  }
1096
1132
  }
1097
1133
  }
@@ -1126,7 +1162,7 @@
1126
1162
  return [];
1127
1163
  }
1128
1164
  // match directive
1129
- var match = html.match(DIRECTIVE_REGEX);
1165
+ var match = DIRECTIVE_REGEX.exec(html);
1130
1166
  var directive = match ? match[1] : undefined;
1131
1167
  return (0, utilities_1.formatDOM)((0, domparser_1.default)(html), null, directive);
1132
1168
  }
@@ -2688,7 +2724,7 @@
2688
2724
  * @param arg - The argument to be returned.
2689
2725
  * @returns - The input argument `arg`.
2690
2726
  */
2691
- var returnFirstArg = function (arg) { return arg; }; // eslint-disable-line @typescript-eslint/no-explicit-any
2727
+ var returnFirstArg = function (arg) { return arg; };
2692
2728
  exports$1.returnFirstArg = returnFirstArg;
2693
2729
 
2694
2730
  } (utilities$1));
@@ -2742,7 +2778,7 @@
2742
2778
  propName = getPropName('default' + attributeNameLowerCased);
2743
2779
  }
2744
2780
  props[propName] = attributeValue;
2745
- switch (propertyInfo && propertyInfo.type) {
2781
+ switch (propertyInfo === null || propertyInfo === void 0 ? void 0 : propertyInfo.type) {
2746
2782
  case react_property_1.BOOLEAN:
2747
2783
  props[propName] = true;
2748
2784
  break;
@@ -2783,6 +2819,7 @@
2783
2819
  function requireDomToReact () {
2784
2820
  if (hasRequiredDomToReact) return domToReact;
2785
2821
  hasRequiredDomToReact = 1;
2822
+ /* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
2786
2823
  var __importDefault = (domToReact && domToReact.__importDefault) || function (mod) {
2787
2824
  return (mod && mod.__esModule) ? mod : { "default": mod };
2788
2825
  };
@@ -2804,23 +2841,24 @@
2804
2841
  * @returns - String or JSX element(s).
2805
2842
  */
2806
2843
  function domToReact$1(nodes, options) {
2844
+ var _a, _b, _c, _d, _e;
2807
2845
  if (options === void 0) { options = {}; }
2808
2846
  var reactElements = [];
2809
2847
  var hasReplace = typeof options.replace === 'function';
2810
- var transform = options.transform || utilities_1.returnFirstArg;
2811
- var _a = options.library || React, cloneElement = _a.cloneElement, createElement = _a.createElement, isValidElement = _a.isValidElement;
2848
+ var transform = (_a = options.transform) !== null && _a !== void 0 ? _a : utilities_1.returnFirstArg;
2849
+ var _f = (_b = options.library) !== null && _b !== void 0 ? _b : React, cloneElement = _f.cloneElement, createElement = _f.createElement, isValidElement = _f.isValidElement;
2812
2850
  var nodesLength = nodes.length;
2813
2851
  for (var index = 0; index < nodesLength; index++) {
2814
2852
  var node = nodes[index];
2815
2853
  // replace with custom React element (if present)
2816
2854
  if (hasReplace) {
2817
- var replaceElement = options.replace(node, index);
2855
+ var replaceElement = (_c = options.replace) === null || _c === void 0 ? void 0 : _c.call(options, node, index);
2818
2856
  if (isValidElement(replaceElement)) {
2819
2857
  // set "key" prop for sibling elements
2820
2858
  // https://react.dev/learn/rendering-lists#rules-of-keys
2821
2859
  if (nodesLength > 1) {
2822
2860
  replaceElement = cloneElement(replaceElement, {
2823
- key: replaceElement.key || index,
2861
+ key: (_d = replaceElement.key) !== null && _d !== void 0 ? _d : index,
2824
2862
  });
2825
2863
  }
2826
2864
  reactElements.push(transform(replaceElement, node, index));
@@ -2851,6 +2889,7 @@
2851
2889
  if (skipAttributesToProps(element)) {
2852
2890
  (0, utilities_1.setStyleProp)(element.attribs.style, element.attribs);
2853
2891
  props = element.attribs;
2892
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2854
2893
  }
2855
2894
  else if (element.attribs) {
2856
2895
  props = (0, attributes_to_props_1.default)(element.attribs, element.name);
@@ -2872,8 +2911,9 @@
2872
2911
  // https://react.dev/reference/react-dom/components/textarea#caveats
2873
2912
  if (node.name === 'textarea' && node.children[0]) {
2874
2913
  props.defaultValue = node.children[0].data;
2914
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
2875
2915
  }
2876
- else if (node.children && node.children.length) {
2916
+ else if ((_e = node.children) === null || _e === void 0 ? void 0 : _e.length) {
2877
2917
  // continue recursion of creating React elements (if applicable)
2878
2918
  children = domToReact$1(node.children, options);
2879
2919
  }
@@ -2939,13 +2979,14 @@
2939
2979
  * @returns - React element(s), empty array, or string.
2940
2980
  */
2941
2981
  function HTMLReactParser(html, options) {
2982
+ var _a;
2942
2983
  if (typeof html !== 'string') {
2943
2984
  throw new TypeError('First argument must be a string');
2944
2985
  }
2945
2986
  if (!html) {
2946
2987
  return [];
2947
2988
  }
2948
- return (0, dom_to_react_1.default)((0, html_dom_parser_1.default)(html, (options === null || options === void 0 ? void 0 : options.htmlparser2) || domParserOptions), options);
2989
+ return (0, dom_to_react_1.default)((0, html_dom_parser_1.default)(html, (_a = options === null || options === void 0 ? void 0 : options.htmlparser2) !== null && _a !== void 0 ? _a : domParserOptions), options);
2949
2990
  }
2950
2991
 
2951
2992
  } (lib$3));