dynamicCSS.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.clearContainerCache = clearContainerCache;
  7. exports.injectCSS = injectCSS;
  8. exports.removeCSS = removeCSS;
  9. exports.updateCSS = updateCSS;
  10. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  11. var _canUseDom = _interopRequireDefault(require("./canUseDom"));
  12. var _contains = _interopRequireDefault(require("./contains"));
  13. var APPEND_ORDER = 'data-rc-order';
  14. var APPEND_PRIORITY = 'data-rc-priority';
  15. var MARK_KEY = "rc-util-key";
  16. var containerCache = new Map();
  17. function getMark() {
  18. var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
  19. mark = _ref.mark;
  20. if (mark) {
  21. return mark.startsWith('data-') ? mark : "data-".concat(mark);
  22. }
  23. return MARK_KEY;
  24. }
  25. function getContainer(option) {
  26. if (option.attachTo) {
  27. return option.attachTo;
  28. }
  29. var head = document.querySelector('head');
  30. return head || document.body;
  31. }
  32. function getOrder(prepend) {
  33. if (prepend === 'queue') {
  34. return 'prependQueue';
  35. }
  36. return prepend ? 'prepend' : 'append';
  37. }
  38. /**
  39. * Find style which inject by rc-util
  40. */
  41. function findStyles(container) {
  42. return Array.from((containerCache.get(container) || container).children).filter(function (node) {
  43. return node.tagName === 'STYLE';
  44. });
  45. }
  46. function injectCSS(css) {
  47. var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  48. if (!(0, _canUseDom.default)()) {
  49. return null;
  50. }
  51. var csp = option.csp,
  52. prepend = option.prepend,
  53. _option$priority = option.priority,
  54. priority = _option$priority === void 0 ? 0 : _option$priority;
  55. var mergedOrder = getOrder(prepend);
  56. var isPrependQueue = mergedOrder === 'prependQueue';
  57. var styleNode = document.createElement('style');
  58. styleNode.setAttribute(APPEND_ORDER, mergedOrder);
  59. if (isPrependQueue && priority) {
  60. styleNode.setAttribute(APPEND_PRIORITY, "".concat(priority));
  61. }
  62. if (csp !== null && csp !== void 0 && csp.nonce) {
  63. styleNode.nonce = csp === null || csp === void 0 ? void 0 : csp.nonce;
  64. }
  65. styleNode.innerHTML = css;
  66. var container = getContainer(option);
  67. var firstChild = container.firstChild;
  68. if (prepend) {
  69. // If is queue `prepend`, it will prepend first style and then append rest style
  70. if (isPrependQueue) {
  71. var existStyle = (option.styles || findStyles(container)).filter(function (node) {
  72. // Ignore style which not injected by rc-util with prepend
  73. if (!['prepend', 'prependQueue'].includes(node.getAttribute(APPEND_ORDER))) {
  74. return false;
  75. }
  76. // Ignore style which priority less then new style
  77. var nodePriority = Number(node.getAttribute(APPEND_PRIORITY) || 0);
  78. return priority >= nodePriority;
  79. });
  80. if (existStyle.length) {
  81. container.insertBefore(styleNode, existStyle[existStyle.length - 1].nextSibling);
  82. return styleNode;
  83. }
  84. }
  85. // Use `insertBefore` as `prepend`
  86. container.insertBefore(styleNode, firstChild);
  87. } else {
  88. container.appendChild(styleNode);
  89. }
  90. return styleNode;
  91. }
  92. function findExistNode(key) {
  93. var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  94. var container = getContainer(option);
  95. return (option.styles || findStyles(container)).find(function (node) {
  96. return node.getAttribute(getMark(option)) === key;
  97. });
  98. }
  99. function removeCSS(key) {
  100. var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  101. var existNode = findExistNode(key, option);
  102. if (existNode) {
  103. var container = getContainer(option);
  104. container.removeChild(existNode);
  105. }
  106. }
  107. /**
  108. * qiankun will inject `appendChild` to insert into other
  109. */
  110. function syncRealContainer(container, option) {
  111. var cachedRealContainer = containerCache.get(container);
  112. // Find real container when not cached or cached container removed
  113. if (!cachedRealContainer || !(0, _contains.default)(document, cachedRealContainer)) {
  114. var placeholderStyle = injectCSS('', option);
  115. var parentNode = placeholderStyle.parentNode;
  116. containerCache.set(container, parentNode);
  117. container.removeChild(placeholderStyle);
  118. }
  119. }
  120. /**
  121. * manually clear container cache to avoid global cache in unit testes
  122. */
  123. function clearContainerCache() {
  124. containerCache.clear();
  125. }
  126. function updateCSS(css, key) {
  127. var originOption = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  128. var container = getContainer(originOption);
  129. var styles = findStyles(container);
  130. var option = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originOption), {}, {
  131. styles: styles
  132. });
  133. // Sync real parent
  134. syncRealContainer(container, option);
  135. var existNode = findExistNode(key, option);
  136. if (existNode) {
  137. var _option$csp, _option$csp2;
  138. if ((_option$csp = option.csp) !== null && _option$csp !== void 0 && _option$csp.nonce && existNode.nonce !== ((_option$csp2 = option.csp) === null || _option$csp2 === void 0 ? void 0 : _option$csp2.nonce)) {
  139. var _option$csp3;
  140. existNode.nonce = (_option$csp3 = option.csp) === null || _option$csp3 === void 0 ? void 0 : _option$csp3.nonce;
  141. }
  142. if (existNode.innerHTML !== css) {
  143. existNode.innerHTML = css;
  144. }
  145. return existNode;
  146. }
  147. var newNode = injectCSS(css, option);
  148. newNode.setAttribute(getMark(option), key);
  149. return newNode;
  150. }