暫無描述

index.js 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import { html } from 'parse5';
  2. import { Element, Document, ProcessingInstruction, Comment, Text, isDirective, isText, isComment, isTag, } from 'domhandler';
  3. function createTextNode(value) {
  4. return new Text(value);
  5. }
  6. function enquoteDoctypeId(id) {
  7. const quote = id.includes('"') ? "'" : '"';
  8. return quote + id + quote;
  9. }
  10. /** @internal */
  11. export function serializeDoctypeContent(name, publicId, systemId) {
  12. let str = '!DOCTYPE ';
  13. if (name) {
  14. str += name;
  15. }
  16. if (publicId) {
  17. str += ` PUBLIC ${enquoteDoctypeId(publicId)}`;
  18. }
  19. else if (systemId) {
  20. str += ' SYSTEM';
  21. }
  22. if (systemId) {
  23. str += ` ${enquoteDoctypeId(systemId)}`;
  24. }
  25. return str;
  26. }
  27. export const adapter = {
  28. // Re-exports from domhandler
  29. isCommentNode: isComment,
  30. isElementNode: isTag,
  31. isTextNode: isText,
  32. //Node construction
  33. createDocument() {
  34. const node = new Document([]);
  35. node['x-mode'] = html.DOCUMENT_MODE.NO_QUIRKS;
  36. return node;
  37. },
  38. createDocumentFragment() {
  39. return new Document([]);
  40. },
  41. createElement(tagName, namespaceURI, attrs) {
  42. const attribs = Object.create(null);
  43. const attribsNamespace = Object.create(null);
  44. const attribsPrefix = Object.create(null);
  45. for (let i = 0; i < attrs.length; i++) {
  46. const attrName = attrs[i].name;
  47. attribs[attrName] = attrs[i].value;
  48. attribsNamespace[attrName] = attrs[i].namespace;
  49. attribsPrefix[attrName] = attrs[i].prefix;
  50. }
  51. const node = new Element(tagName, attribs, []);
  52. node.namespace = namespaceURI;
  53. node['x-attribsNamespace'] = attribsNamespace;
  54. node['x-attribsPrefix'] = attribsPrefix;
  55. return node;
  56. },
  57. createCommentNode(data) {
  58. return new Comment(data);
  59. },
  60. //Tree mutation
  61. appendChild(parentNode, newNode) {
  62. const prev = parentNode.children[parentNode.children.length - 1];
  63. if (prev) {
  64. prev.next = newNode;
  65. newNode.prev = prev;
  66. }
  67. parentNode.children.push(newNode);
  68. newNode.parent = parentNode;
  69. },
  70. insertBefore(parentNode, newNode, referenceNode) {
  71. const insertionIdx = parentNode.children.indexOf(referenceNode);
  72. const { prev } = referenceNode;
  73. if (prev) {
  74. prev.next = newNode;
  75. newNode.prev = prev;
  76. }
  77. referenceNode.prev = newNode;
  78. newNode.next = referenceNode;
  79. parentNode.children.splice(insertionIdx, 0, newNode);
  80. newNode.parent = parentNode;
  81. },
  82. setTemplateContent(templateElement, contentElement) {
  83. adapter.appendChild(templateElement, contentElement);
  84. },
  85. getTemplateContent(templateElement) {
  86. return templateElement.children[0];
  87. },
  88. setDocumentType(document, name, publicId, systemId) {
  89. const data = serializeDoctypeContent(name, publicId, systemId);
  90. let doctypeNode = document.children.find((node) => isDirective(node) && node.name === '!doctype');
  91. if (doctypeNode) {
  92. doctypeNode.data = data !== null && data !== void 0 ? data : null;
  93. }
  94. else {
  95. doctypeNode = new ProcessingInstruction('!doctype', data);
  96. adapter.appendChild(document, doctypeNode);
  97. }
  98. doctypeNode['x-name'] = name !== null && name !== void 0 ? name : undefined;
  99. doctypeNode['x-publicId'] = publicId !== null && publicId !== void 0 ? publicId : undefined;
  100. doctypeNode['x-systemId'] = systemId !== null && systemId !== void 0 ? systemId : undefined;
  101. },
  102. setDocumentMode(document, mode) {
  103. document['x-mode'] = mode;
  104. },
  105. getDocumentMode(document) {
  106. return document['x-mode'];
  107. },
  108. detachNode(node) {
  109. if (node.parent) {
  110. const idx = node.parent.children.indexOf(node);
  111. const { prev, next } = node;
  112. node.prev = null;
  113. node.next = null;
  114. if (prev) {
  115. prev.next = next;
  116. }
  117. if (next) {
  118. next.prev = prev;
  119. }
  120. node.parent.children.splice(idx, 1);
  121. node.parent = null;
  122. }
  123. },
  124. insertText(parentNode, text) {
  125. const lastChild = parentNode.children[parentNode.children.length - 1];
  126. if (lastChild && isText(lastChild)) {
  127. lastChild.data += text;
  128. }
  129. else {
  130. adapter.appendChild(parentNode, createTextNode(text));
  131. }
  132. },
  133. insertTextBefore(parentNode, text, referenceNode) {
  134. const prevNode = parentNode.children[parentNode.children.indexOf(referenceNode) - 1];
  135. if (prevNode && isText(prevNode)) {
  136. prevNode.data += text;
  137. }
  138. else {
  139. adapter.insertBefore(parentNode, createTextNode(text), referenceNode);
  140. }
  141. },
  142. adoptAttributes(recipient, attrs) {
  143. for (let i = 0; i < attrs.length; i++) {
  144. const attrName = attrs[i].name;
  145. if (typeof recipient.attribs[attrName] === 'undefined') {
  146. recipient.attribs[attrName] = attrs[i].value;
  147. recipient['x-attribsNamespace'][attrName] = attrs[i].namespace;
  148. recipient['x-attribsPrefix'][attrName] = attrs[i].prefix;
  149. }
  150. }
  151. },
  152. //Tree traversing
  153. getFirstChild(node) {
  154. return node.children[0];
  155. },
  156. getChildNodes(node) {
  157. return node.children;
  158. },
  159. getParentNode(node) {
  160. return node.parent;
  161. },
  162. getAttrList(element) {
  163. return element.attributes;
  164. },
  165. //Node data
  166. getTagName(element) {
  167. return element.name;
  168. },
  169. getNamespaceURI(element) {
  170. return element.namespace;
  171. },
  172. getTextNodeContent(textNode) {
  173. return textNode.data;
  174. },
  175. getCommentNodeContent(commentNode) {
  176. return commentNode.data;
  177. },
  178. getDocumentTypeNodeName(doctypeNode) {
  179. var _a;
  180. return (_a = doctypeNode['x-name']) !== null && _a !== void 0 ? _a : '';
  181. },
  182. getDocumentTypeNodePublicId(doctypeNode) {
  183. var _a;
  184. return (_a = doctypeNode['x-publicId']) !== null && _a !== void 0 ? _a : '';
  185. },
  186. getDocumentTypeNodeSystemId(doctypeNode) {
  187. var _a;
  188. return (_a = doctypeNode['x-systemId']) !== null && _a !== void 0 ? _a : '';
  189. },
  190. //Node types
  191. isDocumentTypeNode(node) {
  192. return isDirective(node) && node.name === '!doctype';
  193. },
  194. // Source code location
  195. setNodeSourceCodeLocation(node, location) {
  196. if (location) {
  197. node.startIndex = location.startOffset;
  198. node.endIndex = location.endOffset;
  199. }
  200. node.sourceCodeLocation = location;
  201. },
  202. getNodeSourceCodeLocation(node) {
  203. return node.sourceCodeLocation;
  204. },
  205. updateNodeSourceCodeLocation(node, endLocation) {
  206. if (endLocation.endOffset != null)
  207. node.endIndex = endLocation.endOffset;
  208. node.sourceCodeLocation = {
  209. ...node.sourceCodeLocation,
  210. ...endLocation,
  211. };
  212. },
  213. };
  214. //# sourceMappingURL=index.js.map