styleToCssString.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. 'use strict';
  2. /**
  3. * CSS properties which accept numbers but are not in units of "px".
  4. */
  5. var isUnitlessNumber = {
  6. boxFlex: true,
  7. boxFlexGroup: true,
  8. columnCount: true,
  9. flex: true,
  10. flexGrow: true,
  11. flexPositive: true,
  12. flexShrink: true,
  13. flexNegative: true,
  14. fontWeight: true,
  15. lineClamp: true,
  16. lineHeight: true,
  17. opacity: true,
  18. order: true,
  19. orphans: true,
  20. widows: true,
  21. zIndex: true,
  22. zoom: true,
  23. // SVG-related properties
  24. fillOpacity: true,
  25. strokeDashoffset: true,
  26. strokeOpacity: true,
  27. strokeWidth: true
  28. };
  29. /**
  30. * @param {string} prefix vendor-specific prefix, eg: Webkit
  31. * @param {string} key style name, eg: transitionDuration
  32. * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
  33. * WebkitTransitionDuration
  34. */
  35. function prefixKey(prefix, key) {
  36. return prefix + key.charAt(0).toUpperCase() + key.substring(1);
  37. }
  38. /**
  39. * Support style names that may come passed in prefixed by adding permutations
  40. * of vendor prefixes.
  41. */
  42. var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
  43. // Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
  44. // infinite loop, because it iterates over the newly added props too.
  45. Object.keys(isUnitlessNumber).forEach(function(prop) {
  46. prefixes.forEach(function(prefix) {
  47. isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
  48. });
  49. });
  50. var msPattern = /^ms-/;
  51. var _uppercasePattern = /([A-Z])/g;
  52. /**
  53. * Hyphenates a camelcased string, for example:
  54. *
  55. * > hyphenate('backgroundColor')
  56. * < "background-color"
  57. *
  58. * For CSS style names, use `hyphenateStyleName` instead which works properly
  59. * with all vendor prefixes, including `ms`.
  60. *
  61. * @param {string} string
  62. * @return {string}
  63. */
  64. function hyphenate(string) {
  65. return string.replace(_uppercasePattern, '-$1').toLowerCase();
  66. }
  67. /**
  68. * Hyphenates a camelcased CSS property name, for example:
  69. *
  70. * > hyphenateStyleName('backgroundColor')
  71. * < "background-color"
  72. * > hyphenateStyleName('MozTransition')
  73. * < "-moz-transition"
  74. * > hyphenateStyleName('msTransition')
  75. * < "-ms-transition"
  76. *
  77. * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
  78. * is converted to `-ms-`.
  79. *
  80. * @param {string} string
  81. * @return {string}
  82. */
  83. function hyphenateStyleName(string) {
  84. return hyphenate(string).replace(msPattern, '-ms-');
  85. }
  86. var isArray = Array.isArray;
  87. var keys = Object.keys;
  88. var counter = 1;
  89. // Follows syntax at https://developer.mozilla.org/en-US/docs/Web/CSS/content,
  90. // including multiple space separated values.
  91. var unquotedContentValueRegex = /^(normal|none|(\b(url\([^)]*\)|chapter_counter|attr\([^)]*\)|(no-)?(open|close)-quote|inherit)((\b\s*)|$|\s+))+)$/;
  92. function buildRule(key, value) {
  93. if (!isUnitlessNumber[key] && typeof value === 'number') {
  94. value = '' + value + 'px';
  95. } else if (key === 'content' && !unquotedContentValueRegex.test(value)) {
  96. value = "'" + value.replace(/'/g, "\\'") + "'";
  97. }
  98. return hyphenateStyleName(key) + ': ' + value + '; ';
  99. }
  100. function styleToCssString(rules) {
  101. var result = ''
  102. if (typeof rules === 'string') {
  103. rules = rules.trim()
  104. return rules.slice(-1) === ";" ? `${rules} ` : `${rules}; `
  105. }
  106. if (!rules || keys(rules).length === 0) {
  107. return result;
  108. }
  109. var styleKeys = keys(rules);
  110. for (var j = 0, l = styleKeys.length; j < l; j++) {
  111. var styleKey = styleKeys[j];
  112. var value = rules[styleKey];
  113. if (isArray(value)) {
  114. for (var i = 0, len = value.length; i < len; i++) {
  115. result += buildRule(styleKey, value[i]);
  116. }
  117. } else {
  118. result += buildRule(styleKey, value);
  119. }
  120. }
  121. return result;
  122. }
  123. export default styleToCssString