useStyleRegister.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _typeof3 = require("@babel/runtime/helpers/typeof");
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.STYLE_PREFIX = void 0;
  8. exports.default = useStyleRegister;
  9. exports.extract = void 0;
  10. exports.normalizeStyle = normalizeStyle;
  11. exports.parseStyle = void 0;
  12. exports.uniqueHash = uniqueHash;
  13. var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
  14. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  15. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  16. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  17. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  18. var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
  19. var _hash = _interopRequireDefault(require("@emotion/hash"));
  20. var _dynamicCSS = require("rc-util/lib/Dom/dynamicCSS");
  21. var React = _interopRequireWildcard(require("react"));
  22. var _unitless = _interopRequireDefault(require("@emotion/unitless"));
  23. var _stylis = require("stylis");
  24. var _linters = require("../linters");
  25. var _StyleContext = _interopRequireWildcard(require("../StyleContext"));
  26. var _util = require("../util");
  27. var _cacheMapUtil = require("../util/cacheMapUtil");
  28. var _useGlobalCache3 = _interopRequireDefault(require("./useGlobalCache"));
  29. function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
  30. function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof3(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
  31. // @ts-ignore
  32. var SKIP_CHECK = '_skip_check_';
  33. var MULTI_VALUE = '_multi_value_';
  34. // ============================================================================
  35. // == Parser ==
  36. // ============================================================================
  37. // Preprocessor style content to browser support one
  38. function normalizeStyle(styleStr) {
  39. var serialized = (0, _stylis.serialize)((0, _stylis.compile)(styleStr), _stylis.stringify);
  40. return serialized.replace(/\{%%%\:[^;];}/g, ';');
  41. }
  42. function isCompoundCSSProperty(value) {
  43. return (0, _typeof2.default)(value) === 'object' && value && (SKIP_CHECK in value || MULTI_VALUE in value);
  44. }
  45. // 注入 hash 值
  46. function injectSelectorHash(key, hashId, hashPriority) {
  47. if (!hashId) {
  48. return key;
  49. }
  50. var hashClassName = ".".concat(hashId);
  51. var hashSelector = hashPriority === 'low' ? ":where(".concat(hashClassName, ")") : hashClassName;
  52. // 注入 hashId
  53. var keys = key.split(',').map(function (k) {
  54. var _firstPath$match;
  55. var fullPath = k.trim().split(/\s+/);
  56. // 如果 Selector 第一个是 HTML Element,那我们就插到它的后面。反之,就插到最前面。
  57. var firstPath = fullPath[0] || '';
  58. var htmlElement = ((_firstPath$match = firstPath.match(/^\w+/)) === null || _firstPath$match === void 0 ? void 0 : _firstPath$match[0]) || '';
  59. firstPath = "".concat(htmlElement).concat(hashSelector).concat(firstPath.slice(htmlElement.length));
  60. return [firstPath].concat((0, _toConsumableArray2.default)(fullPath.slice(1))).join(' ');
  61. });
  62. return keys.join(',');
  63. }
  64. // Parse CSSObject to style content
  65. var parseStyle = exports.parseStyle = function parseStyle(interpolation) {
  66. var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  67. var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
  68. root: true,
  69. parentSelectors: []
  70. },
  71. root = _ref.root,
  72. injectHash = _ref.injectHash,
  73. parentSelectors = _ref.parentSelectors;
  74. var hashId = config.hashId,
  75. layer = config.layer,
  76. path = config.path,
  77. hashPriority = config.hashPriority,
  78. _config$transformers = config.transformers,
  79. transformers = _config$transformers === void 0 ? [] : _config$transformers,
  80. _config$linters = config.linters,
  81. linters = _config$linters === void 0 ? [] : _config$linters;
  82. var styleStr = '';
  83. var effectStyle = {};
  84. function parseKeyframes(keyframes) {
  85. var animationName = keyframes.getName(hashId);
  86. if (!effectStyle[animationName]) {
  87. var _parseStyle = parseStyle(keyframes.style, config, {
  88. root: false,
  89. parentSelectors: parentSelectors
  90. }),
  91. _parseStyle2 = (0, _slicedToArray2.default)(_parseStyle, 1),
  92. _parsedStr = _parseStyle2[0];
  93. effectStyle[animationName] = "@keyframes ".concat(keyframes.getName(hashId)).concat(_parsedStr);
  94. }
  95. }
  96. function flattenList(list) {
  97. var fullList = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  98. list.forEach(function (item) {
  99. if (Array.isArray(item)) {
  100. flattenList(item, fullList);
  101. } else if (item) {
  102. fullList.push(item);
  103. }
  104. });
  105. return fullList;
  106. }
  107. var flattenStyleList = flattenList(Array.isArray(interpolation) ? interpolation : [interpolation]);
  108. flattenStyleList.forEach(function (originStyle) {
  109. // Only root level can use raw string
  110. var style = typeof originStyle === 'string' && !root ? {} : originStyle;
  111. if (typeof style === 'string') {
  112. styleStr += "".concat(style, "\n");
  113. } else if (style._keyframe) {
  114. // Keyframe
  115. parseKeyframes(style);
  116. } else {
  117. var mergedStyle = transformers.reduce(function (prev, trans) {
  118. var _trans$visit;
  119. return (trans === null || trans === void 0 || (_trans$visit = trans.visit) === null || _trans$visit === void 0 ? void 0 : _trans$visit.call(trans, prev)) || prev;
  120. }, style);
  121. // Normal CSSObject
  122. Object.keys(mergedStyle).forEach(function (key) {
  123. var value = mergedStyle[key];
  124. if ((0, _typeof2.default)(value) === 'object' && value && (key !== 'animationName' || !value._keyframe) && !isCompoundCSSProperty(value)) {
  125. var subInjectHash = false;
  126. // 当成嵌套对象来处理
  127. var mergedKey = key.trim();
  128. // Whether treat child as root. In most case it is false.
  129. var nextRoot = false;
  130. // 拆分多个选择器
  131. if ((root || injectHash) && hashId) {
  132. if (mergedKey.startsWith('@')) {
  133. // 略过媒体查询,交给子节点继续插入 hashId
  134. subInjectHash = true;
  135. } else if (mergedKey === '&') {
  136. // 抹掉 root selector 上的单个 &
  137. mergedKey = injectSelectorHash('', hashId, hashPriority);
  138. } else {
  139. // 注入 hashId
  140. mergedKey = injectSelectorHash(key, hashId, hashPriority);
  141. }
  142. } else if (root && !hashId && (mergedKey === '&' || mergedKey === '')) {
  143. // In case of `{ '&': { a: { color: 'red' } } }` or `{ '': { a: { color: 'red' } } }` without hashId,
  144. // we will get `&{a:{color:red;}}` or `{a:{color:red;}}` string for stylis to compile.
  145. // But it does not conform to stylis syntax,
  146. // and finally we will get `{color:red;}` as css, which is wrong.
  147. // So we need to remove key in root, and treat child `{ a: { color: 'red' } }` as root.
  148. mergedKey = '';
  149. nextRoot = true;
  150. }
  151. var _parseStyle3 = parseStyle(value, config, {
  152. root: nextRoot,
  153. injectHash: subInjectHash,
  154. parentSelectors: [].concat((0, _toConsumableArray2.default)(parentSelectors), [mergedKey])
  155. }),
  156. _parseStyle4 = (0, _slicedToArray2.default)(_parseStyle3, 2),
  157. _parsedStr2 = _parseStyle4[0],
  158. childEffectStyle = _parseStyle4[1];
  159. effectStyle = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, effectStyle), childEffectStyle);
  160. styleStr += "".concat(mergedKey).concat(_parsedStr2);
  161. } else {
  162. var _value;
  163. function appendStyle(cssKey, cssValue) {
  164. if (process.env.NODE_ENV !== 'production' && ((0, _typeof2.default)(value) !== 'object' || !(value !== null && value !== void 0 && value[SKIP_CHECK]))) {
  165. [_linters.contentQuotesLinter, _linters.hashedAnimationLinter].concat((0, _toConsumableArray2.default)(linters)).forEach(function (linter) {
  166. return linter(cssKey, cssValue, {
  167. path: path,
  168. hashId: hashId,
  169. parentSelectors: parentSelectors
  170. });
  171. });
  172. }
  173. // 如果是样式则直接插入
  174. var styleName = cssKey.replace(/[A-Z]/g, function (match) {
  175. return "-".concat(match.toLowerCase());
  176. });
  177. // Auto suffix with px
  178. var formatValue = cssValue;
  179. if (!_unitless.default[cssKey] && typeof formatValue === 'number' && formatValue !== 0) {
  180. formatValue = "".concat(formatValue, "px");
  181. }
  182. // handle animationName & Keyframe value
  183. if (cssKey === 'animationName' && cssValue !== null && cssValue !== void 0 && cssValue._keyframe) {
  184. parseKeyframes(cssValue);
  185. formatValue = cssValue.getName(hashId);
  186. }
  187. styleStr += "".concat(styleName, ":").concat(formatValue, ";");
  188. }
  189. var actualValue = (_value = value === null || value === void 0 ? void 0 : value.value) !== null && _value !== void 0 ? _value : value;
  190. if ((0, _typeof2.default)(value) === 'object' && value !== null && value !== void 0 && value[MULTI_VALUE] && Array.isArray(actualValue)) {
  191. actualValue.forEach(function (item) {
  192. appendStyle(key, item);
  193. });
  194. } else {
  195. appendStyle(key, actualValue);
  196. }
  197. }
  198. });
  199. }
  200. });
  201. if (!root) {
  202. styleStr = "{".concat(styleStr, "}");
  203. } else if (layer) {
  204. // fixme: https://github.com/thysultan/stylis/pull/339
  205. if (styleStr) {
  206. styleStr = "@layer ".concat(layer.name, " {").concat(styleStr, "}");
  207. }
  208. if (layer.dependencies) {
  209. effectStyle["@layer ".concat(layer.name)] = layer.dependencies.map(function (deps) {
  210. return "@layer ".concat(deps, ", ").concat(layer.name, ";");
  211. }).join('\n');
  212. }
  213. }
  214. return [styleStr, effectStyle];
  215. };
  216. // ============================================================================
  217. // == Register ==
  218. // ============================================================================
  219. function uniqueHash(path, styleStr) {
  220. return (0, _hash.default)("".concat(path.join('%')).concat(styleStr));
  221. }
  222. function Empty() {
  223. return null;
  224. }
  225. var STYLE_PREFIX = exports.STYLE_PREFIX = 'style';
  226. /**
  227. * Register a style to the global style sheet.
  228. */
  229. function useStyleRegister(info, styleFn) {
  230. var token = info.token,
  231. path = info.path,
  232. hashId = info.hashId,
  233. layer = info.layer,
  234. nonce = info.nonce,
  235. clientOnly = info.clientOnly,
  236. _info$order = info.order,
  237. order = _info$order === void 0 ? 0 : _info$order;
  238. var _React$useContext = React.useContext(_StyleContext.default),
  239. autoClear = _React$useContext.autoClear,
  240. mock = _React$useContext.mock,
  241. defaultCache = _React$useContext.defaultCache,
  242. hashPriority = _React$useContext.hashPriority,
  243. container = _React$useContext.container,
  244. ssrInline = _React$useContext.ssrInline,
  245. transformers = _React$useContext.transformers,
  246. linters = _React$useContext.linters,
  247. cache = _React$useContext.cache,
  248. enableLayer = _React$useContext.layer;
  249. var tokenKey = token._tokenKey;
  250. var fullPath = [tokenKey];
  251. if (enableLayer) {
  252. fullPath.push('layer');
  253. }
  254. fullPath.push.apply(fullPath, (0, _toConsumableArray2.default)(path));
  255. // Check if need insert style
  256. var isMergedClientSide = _util.isClientSide;
  257. if (process.env.NODE_ENV !== 'production' && mock !== undefined) {
  258. isMergedClientSide = mock === 'client';
  259. }
  260. var _useGlobalCache = (0, _useGlobalCache3.default)(STYLE_PREFIX, fullPath,
  261. // Create cache if needed
  262. function () {
  263. var cachePath = fullPath.join('|');
  264. // Get style from SSR inline style directly
  265. if ((0, _cacheMapUtil.existPath)(cachePath)) {
  266. var _getStyleAndHash = (0, _cacheMapUtil.getStyleAndHash)(cachePath),
  267. _getStyleAndHash2 = (0, _slicedToArray2.default)(_getStyleAndHash, 2),
  268. inlineCacheStyleStr = _getStyleAndHash2[0],
  269. styleHash = _getStyleAndHash2[1];
  270. if (inlineCacheStyleStr) {
  271. return [inlineCacheStyleStr, tokenKey, styleHash, {}, clientOnly, order];
  272. }
  273. }
  274. // Generate style
  275. var styleObj = styleFn();
  276. var _parseStyle5 = parseStyle(styleObj, {
  277. hashId: hashId,
  278. hashPriority: hashPriority,
  279. layer: enableLayer ? layer : undefined,
  280. path: path.join('-'),
  281. transformers: transformers,
  282. linters: linters
  283. }),
  284. _parseStyle6 = (0, _slicedToArray2.default)(_parseStyle5, 2),
  285. parsedStyle = _parseStyle6[0],
  286. effectStyle = _parseStyle6[1];
  287. var styleStr = normalizeStyle(parsedStyle);
  288. var styleId = uniqueHash(fullPath, styleStr);
  289. return [styleStr, tokenKey, styleId, effectStyle, clientOnly, order];
  290. },
  291. // Remove cache if no need
  292. function (_ref2, fromHMR) {
  293. var _ref3 = (0, _slicedToArray2.default)(_ref2, 3),
  294. styleId = _ref3[2];
  295. if ((fromHMR || autoClear) && _util.isClientSide) {
  296. (0, _dynamicCSS.removeCSS)(styleId, {
  297. mark: _StyleContext.ATTR_MARK,
  298. attachTo: container
  299. });
  300. }
  301. },
  302. // Effect: Inject style here
  303. function (_ref4) {
  304. var _ref5 = (0, _slicedToArray2.default)(_ref4, 4),
  305. styleStr = _ref5[0],
  306. _ = _ref5[1],
  307. styleId = _ref5[2],
  308. effectStyle = _ref5[3];
  309. if (isMergedClientSide && styleStr !== _cacheMapUtil.CSS_FILE_STYLE) {
  310. var mergedCSSConfig = {
  311. mark: _StyleContext.ATTR_MARK,
  312. prepend: enableLayer ? false : 'queue',
  313. attachTo: container,
  314. priority: order
  315. };
  316. var nonceStr = typeof nonce === 'function' ? nonce() : nonce;
  317. if (nonceStr) {
  318. mergedCSSConfig.csp = {
  319. nonce: nonceStr
  320. };
  321. }
  322. // ================= Split Effect Style =================
  323. // We will split effectStyle here since @layer should be at the top level
  324. var effectLayerKeys = [];
  325. var effectRestKeys = [];
  326. Object.keys(effectStyle).forEach(function (key) {
  327. if (key.startsWith('@layer')) {
  328. effectLayerKeys.push(key);
  329. } else {
  330. effectRestKeys.push(key);
  331. }
  332. });
  333. // ================= Inject Layer Style =================
  334. // Inject layer style
  335. effectLayerKeys.forEach(function (effectKey) {
  336. (0, _dynamicCSS.updateCSS)(normalizeStyle(effectStyle[effectKey]), "_layer-".concat(effectKey), (0, _objectSpread2.default)((0, _objectSpread2.default)({}, mergedCSSConfig), {}, {
  337. prepend: true
  338. }));
  339. });
  340. // ==================== Inject Style ====================
  341. // Inject style
  342. var style = (0, _dynamicCSS.updateCSS)(styleStr, styleId, mergedCSSConfig);
  343. style[_StyleContext.CSS_IN_JS_INSTANCE] = cache.instanceId;
  344. // Used for `useCacheToken` to remove on batch when token removed
  345. style.setAttribute(_StyleContext.ATTR_TOKEN, tokenKey);
  346. // Debug usage. Dev only
  347. if (process.env.NODE_ENV !== 'production') {
  348. style.setAttribute(_StyleContext.ATTR_CACHE_PATH, fullPath.join('|'));
  349. }
  350. // ================ Inject Effect Style =================
  351. // Inject client side effect style
  352. effectRestKeys.forEach(function (effectKey) {
  353. (0, _dynamicCSS.updateCSS)(normalizeStyle(effectStyle[effectKey]), "_effect-".concat(effectKey), mergedCSSConfig);
  354. });
  355. }
  356. }),
  357. _useGlobalCache2 = (0, _slicedToArray2.default)(_useGlobalCache, 3),
  358. cachedStyleStr = _useGlobalCache2[0],
  359. cachedTokenKey = _useGlobalCache2[1],
  360. cachedStyleId = _useGlobalCache2[2];
  361. return function (node) {
  362. var styleNode;
  363. if (!ssrInline || isMergedClientSide || !defaultCache) {
  364. styleNode = /*#__PURE__*/React.createElement(Empty, null);
  365. } else {
  366. styleNode = /*#__PURE__*/React.createElement("style", (0, _extends2.default)({}, (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _StyleContext.ATTR_TOKEN, cachedTokenKey), _StyleContext.ATTR_MARK, cachedStyleId), {
  367. dangerouslySetInnerHTML: {
  368. __html: cachedStyleStr
  369. }
  370. }));
  371. }
  372. return /*#__PURE__*/React.createElement(React.Fragment, null, styleNode, node);
  373. };
  374. }
  375. var extract = exports.extract = function extract(cache, effectStyles, options) {
  376. var _cache = (0, _slicedToArray2.default)(cache, 6),
  377. styleStr = _cache[0],
  378. tokenKey = _cache[1],
  379. styleId = _cache[2],
  380. effectStyle = _cache[3],
  381. clientOnly = _cache[4],
  382. order = _cache[5];
  383. var _ref7 = options || {},
  384. plain = _ref7.plain;
  385. // Skip client only style
  386. if (clientOnly) {
  387. return null;
  388. }
  389. var keyStyleText = styleStr;
  390. // ====================== Share ======================
  391. // Used for rc-util
  392. var sharedAttrs = {
  393. 'data-rc-order': 'prependQueue',
  394. 'data-rc-priority': "".concat(order)
  395. };
  396. // ====================== Style ======================
  397. keyStyleText = (0, _util.toStyleStr)(styleStr, tokenKey, styleId, sharedAttrs, plain);
  398. // =============== Create effect style ===============
  399. if (effectStyle) {
  400. Object.keys(effectStyle).forEach(function (effectKey) {
  401. // Effect style can be reused
  402. if (!effectStyles[effectKey]) {
  403. effectStyles[effectKey] = true;
  404. var effectStyleStr = normalizeStyle(effectStyle[effectKey]);
  405. var effectStyleHTML = (0, _util.toStyleStr)(effectStyleStr, tokenKey, "_effect-".concat(effectKey), sharedAttrs, plain);
  406. if (effectKey.startsWith('@layer')) {
  407. keyStyleText = effectStyleHTML + keyStyleText;
  408. } else {
  409. keyStyleText += effectStyleHTML;
  410. }
  411. }
  412. });
  413. }
  414. return [order, styleId, keyStyleText];
  415. };