createNodesFromMarkup.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. 'use strict';
  2. /**
  3. * Copyright (c) 2013-present, Facebook, Inc.
  4. *
  5. * This source code is licensed under the MIT license found in the
  6. * LICENSE file in the root directory of this source tree.
  7. *
  8. * @typechecks
  9. */
  10. /*eslint-disable fb-www/unsafe-html*/
  11. var ExecutionEnvironment = require('./ExecutionEnvironment');
  12. var createArrayFromMixed = require('./createArrayFromMixed');
  13. var getMarkupWrap = require('./getMarkupWrap');
  14. var invariant = require('./invariant');
  15. /**
  16. * Dummy container used to render all markup.
  17. */
  18. var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;
  19. /**
  20. * Pattern used by `getNodeName`.
  21. */
  22. var nodeNamePattern = /^\s*<(\w+)/;
  23. /**
  24. * Extracts the `nodeName` of the first element in a string of markup.
  25. *
  26. * @param {string} markup String of markup.
  27. * @return {?string} Node name of the supplied markup.
  28. */
  29. function getNodeName(markup) {
  30. var nodeNameMatch = markup.match(nodeNamePattern);
  31. return nodeNameMatch && nodeNameMatch[1].toLowerCase();
  32. }
  33. /**
  34. * Creates an array containing the nodes rendered from the supplied markup. The
  35. * optionally supplied `handleScript` function will be invoked once for each
  36. * <script> element that is rendered. If no `handleScript` function is supplied,
  37. * an exception is thrown if any <script> elements are rendered.
  38. *
  39. * @param {string} markup A string of valid HTML markup.
  40. * @param {?function} handleScript Invoked once for each rendered <script>.
  41. * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes.
  42. */
  43. function createNodesFromMarkup(markup, handleScript) {
  44. var node = dummyNode;
  45. !!!dummyNode ? process.env.NODE_ENV !== 'production' ? invariant(false, 'createNodesFromMarkup dummy not initialized') : invariant(false) : void 0;
  46. var nodeName = getNodeName(markup);
  47. var wrap = nodeName && getMarkupWrap(nodeName);
  48. if (wrap) {
  49. node.innerHTML = wrap[1] + markup + wrap[2];
  50. var wrapDepth = wrap[0];
  51. while (wrapDepth--) {
  52. node = node.lastChild;
  53. }
  54. } else {
  55. node.innerHTML = markup;
  56. }
  57. var scripts = node.getElementsByTagName('script');
  58. if (scripts.length) {
  59. !handleScript ? process.env.NODE_ENV !== 'production' ? invariant(false, 'createNodesFromMarkup(...): Unexpected <script> element rendered.') : invariant(false) : void 0;
  60. createArrayFromMixed(scripts).forEach(handleScript);
  61. }
  62. var nodes = Array.from(node.childNodes);
  63. while (node.lastChild) {
  64. node.removeChild(node.lastChild);
  65. }
  66. return nodes;
  67. }
  68. module.exports = createNodesFromMarkup;