index.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. "use strict";
  2. var __assign = (this && this.__assign) || function () {
  3. __assign = Object.assign || function(t) {
  4. for (var s, i = 1, n = arguments.length; i < n; i++) {
  5. s = arguments[i];
  6. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
  7. t[p] = s[p];
  8. }
  9. return t;
  10. };
  11. return __assign.apply(this, arguments);
  12. };
  13. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  14. if (k2 === undefined) k2 = k;
  15. var desc = Object.getOwnPropertyDescriptor(m, k);
  16. if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
  17. desc = { enumerable: true, get: function() { return m[k]; } };
  18. }
  19. Object.defineProperty(o, k2, desc);
  20. }) : (function(o, m, k, k2) {
  21. if (k2 === undefined) k2 = k;
  22. o[k2] = m[k];
  23. }));
  24. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  25. Object.defineProperty(o, "default", { enumerable: true, value: v });
  26. }) : function(o, v) {
  27. o["default"] = v;
  28. });
  29. var __importStar = (this && this.__importStar) || function (mod) {
  30. if (mod && mod.__esModule) return mod;
  31. var result = {};
  32. if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  33. __setModuleDefault(result, mod);
  34. return result;
  35. };
  36. Object.defineProperty(exports, "__esModule", { value: true });
  37. exports.render = void 0;
  38. /*
  39. * Module dependencies
  40. */
  41. var ElementType = __importStar(require("domelementtype"));
  42. var entities_1 = require("entities");
  43. /**
  44. * Mixed-case SVG and MathML tags & attributes
  45. * recognized by the HTML parser.
  46. *
  47. * @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign
  48. */
  49. var foreignNames_js_1 = require("./foreignNames.js");
  50. var unencodedElements = new Set([
  51. "style",
  52. "script",
  53. "xmp",
  54. "iframe",
  55. "noembed",
  56. "noframes",
  57. "plaintext",
  58. "noscript",
  59. ]);
  60. function replaceQuotes(value) {
  61. return value.replace(/"/g, "&quot;");
  62. }
  63. /**
  64. * Format attributes
  65. */
  66. function formatAttributes(attributes, opts) {
  67. var _a;
  68. if (!attributes)
  69. return;
  70. var encode = ((_a = opts.encodeEntities) !== null && _a !== void 0 ? _a : opts.decodeEntities) === false
  71. ? replaceQuotes
  72. : opts.xmlMode || opts.encodeEntities !== "utf8"
  73. ? entities_1.encodeXML
  74. : entities_1.escapeAttribute;
  75. return Object.keys(attributes)
  76. .map(function (key) {
  77. var _a, _b;
  78. var value = (_a = attributes[key]) !== null && _a !== void 0 ? _a : "";
  79. if (opts.xmlMode === "foreign") {
  80. /* Fix up mixed-case attribute names */
  81. key = (_b = foreignNames_js_1.attributeNames.get(key)) !== null && _b !== void 0 ? _b : key;
  82. }
  83. if (!opts.emptyAttrs && !opts.xmlMode && value === "") {
  84. return key;
  85. }
  86. return "".concat(key, "=\"").concat(encode(value), "\"");
  87. })
  88. .join(" ");
  89. }
  90. /**
  91. * Self-enclosing tags
  92. */
  93. var singleTag = new Set([
  94. "area",
  95. "base",
  96. "basefont",
  97. "br",
  98. "col",
  99. "command",
  100. "embed",
  101. "frame",
  102. "hr",
  103. "img",
  104. "input",
  105. "isindex",
  106. "keygen",
  107. "link",
  108. "meta",
  109. "param",
  110. "source",
  111. "track",
  112. "wbr",
  113. ]);
  114. /**
  115. * Renders a DOM node or an array of DOM nodes to a string.
  116. *
  117. * Can be thought of as the equivalent of the `outerHTML` of the passed node(s).
  118. *
  119. * @param node Node to be rendered.
  120. * @param options Changes serialization behavior
  121. */
  122. function render(node, options) {
  123. if (options === void 0) { options = {}; }
  124. var nodes = "length" in node ? node : [node];
  125. var output = "";
  126. for (var i = 0; i < nodes.length; i++) {
  127. output += renderNode(nodes[i], options);
  128. }
  129. return output;
  130. }
  131. exports.render = render;
  132. exports.default = render;
  133. function renderNode(node, options) {
  134. switch (node.type) {
  135. case ElementType.Root:
  136. return render(node.children, options);
  137. // @ts-expect-error We don't use `Doctype` yet
  138. case ElementType.Doctype:
  139. case ElementType.Directive:
  140. return renderDirective(node);
  141. case ElementType.Comment:
  142. return renderComment(node);
  143. case ElementType.CDATA:
  144. return renderCdata(node);
  145. case ElementType.Script:
  146. case ElementType.Style:
  147. case ElementType.Tag:
  148. return renderTag(node, options);
  149. case ElementType.Text:
  150. return renderText(node, options);
  151. }
  152. }
  153. var foreignModeIntegrationPoints = new Set([
  154. "mi",
  155. "mo",
  156. "mn",
  157. "ms",
  158. "mtext",
  159. "annotation-xml",
  160. "foreignObject",
  161. "desc",
  162. "title",
  163. ]);
  164. var foreignElements = new Set(["svg", "math"]);
  165. function renderTag(elem, opts) {
  166. var _a;
  167. // Handle SVG / MathML in HTML
  168. if (opts.xmlMode === "foreign") {
  169. /* Fix up mixed-case element names */
  170. elem.name = (_a = foreignNames_js_1.elementNames.get(elem.name)) !== null && _a !== void 0 ? _a : elem.name;
  171. /* Exit foreign mode at integration points */
  172. if (elem.parent &&
  173. foreignModeIntegrationPoints.has(elem.parent.name)) {
  174. opts = __assign(__assign({}, opts), { xmlMode: false });
  175. }
  176. }
  177. if (!opts.xmlMode && foreignElements.has(elem.name)) {
  178. opts = __assign(__assign({}, opts), { xmlMode: "foreign" });
  179. }
  180. var tag = "<".concat(elem.name);
  181. var attribs = formatAttributes(elem.attribs, opts);
  182. if (attribs) {
  183. tag += " ".concat(attribs);
  184. }
  185. if (elem.children.length === 0 &&
  186. (opts.xmlMode
  187. ? // In XML mode or foreign mode, and user hasn't explicitly turned off self-closing tags
  188. opts.selfClosingTags !== false
  189. : // User explicitly asked for self-closing tags, even in HTML mode
  190. opts.selfClosingTags && singleTag.has(elem.name))) {
  191. if (!opts.xmlMode)
  192. tag += " ";
  193. tag += "/>";
  194. }
  195. else {
  196. tag += ">";
  197. if (elem.children.length > 0) {
  198. tag += render(elem.children, opts);
  199. }
  200. if (opts.xmlMode || !singleTag.has(elem.name)) {
  201. tag += "</".concat(elem.name, ">");
  202. }
  203. }
  204. return tag;
  205. }
  206. function renderDirective(elem) {
  207. return "<".concat(elem.data, ">");
  208. }
  209. function renderText(elem, opts) {
  210. var _a;
  211. var data = elem.data || "";
  212. // If entities weren't decoded, no need to encode them back
  213. if (((_a = opts.encodeEntities) !== null && _a !== void 0 ? _a : opts.decodeEntities) !== false &&
  214. !(!opts.xmlMode &&
  215. elem.parent &&
  216. unencodedElements.has(elem.parent.name))) {
  217. data =
  218. opts.xmlMode || opts.encodeEntities !== "utf8"
  219. ? (0, entities_1.encodeXML)(data)
  220. : (0, entities_1.escapeText)(data);
  221. }
  222. return data;
  223. }
  224. function renderCdata(elem) {
  225. return "<![CDATA[".concat(elem.children[0].data, "]]>");
  226. }
  227. function renderComment(elem) {
  228. return "<!--".concat(elem.data, "-->");
  229. }