getMarkupWrap.js 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. */
  9. /*eslint-disable fb-www/unsafe-html */
  10. var ExecutionEnvironment = require('./ExecutionEnvironment');
  11. var invariant = require('./invariant');
  12. /**
  13. * Dummy container used to detect which wraps are necessary.
  14. */
  15. var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;
  16. /**
  17. * Some browsers cannot use `innerHTML` to render certain elements standalone,
  18. * so we wrap them, render the wrapped nodes, then extract the desired node.
  19. *
  20. * In IE8, certain elements cannot render alone, so wrap all elements ('*').
  21. */
  22. var shouldWrap = {};
  23. var selectWrap = [1, '<select multiple="true">', '</select>'];
  24. var tableWrap = [1, '<table>', '</table>'];
  25. var trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
  26. var svgWrap = [1, '<svg xmlns="http://www.w3.org/2000/svg">', '</svg>'];
  27. var markupWrap = {
  28. '*': [1, '?<div>', '</div>'],
  29. 'area': [1, '<map>', '</map>'],
  30. 'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
  31. 'legend': [1, '<fieldset>', '</fieldset>'],
  32. 'param': [1, '<object>', '</object>'],
  33. 'tr': [2, '<table><tbody>', '</tbody></table>'],
  34. 'optgroup': selectWrap,
  35. 'option': selectWrap,
  36. 'caption': tableWrap,
  37. 'colgroup': tableWrap,
  38. 'tbody': tableWrap,
  39. 'tfoot': tableWrap,
  40. 'thead': tableWrap,
  41. 'td': trWrap,
  42. 'th': trWrap
  43. };
  44. // Initialize the SVG elements since we know they'll always need to be wrapped
  45. // consistently. If they are created inside a <div> they will be initialized in
  46. // the wrong namespace (and will not display).
  47. var svgElements = ['circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'text', 'tspan'];
  48. svgElements.forEach(function (nodeName) {
  49. markupWrap[nodeName] = svgWrap;
  50. shouldWrap[nodeName] = true;
  51. });
  52. /**
  53. * Gets the markup wrap configuration for the supplied `nodeName`.
  54. *
  55. * NOTE: This lazily detects which wraps are necessary for the current browser.
  56. *
  57. * @param {string} nodeName Lowercase `nodeName`.
  58. * @return {?array} Markup wrap configuration, if applicable.
  59. */
  60. function getMarkupWrap(nodeName) {
  61. !!!dummyNode ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Markup wrapping node not initialized') : invariant(false) : void 0;
  62. if (!markupWrap.hasOwnProperty(nodeName)) {
  63. nodeName = '*';
  64. }
  65. if (!shouldWrap.hasOwnProperty(nodeName)) {
  66. if (nodeName === '*') {
  67. dummyNode.innerHTML = '<link />';
  68. } else {
  69. dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>';
  70. }
  71. shouldWrap[nodeName] = !dummyNode.firstChild;
  72. }
  73. return shouldWrap[nodeName] ? markupWrap[nodeName] : null;
  74. }
  75. module.exports = getMarkupWrap;