objectifier.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. let camelcase = require('camelcase-css')
  2. let UNITLESS = {
  3. boxFlex: true,
  4. boxFlexGroup: true,
  5. columnCount: true,
  6. flex: true,
  7. flexGrow: true,
  8. flexPositive: true,
  9. flexShrink: true,
  10. flexNegative: true,
  11. fontWeight: true,
  12. lineClamp: true,
  13. lineHeight: true,
  14. opacity: true,
  15. order: true,
  16. orphans: true,
  17. tabSize: true,
  18. widows: true,
  19. zIndex: true,
  20. zoom: true,
  21. fillOpacity: true,
  22. strokeDashoffset: true,
  23. strokeOpacity: true,
  24. strokeWidth: true
  25. }
  26. function atRule(node) {
  27. if (typeof node.nodes === 'undefined') {
  28. return true
  29. } else {
  30. return process(node)
  31. }
  32. }
  33. function process(node, options = {}) {
  34. let name
  35. let result = {}
  36. let { stringifyImportant } = options;
  37. node.each(child => {
  38. if (child.type === 'atrule') {
  39. name = '@' + child.name
  40. if (child.params) name += ' ' + child.params
  41. if (typeof result[name] === 'undefined') {
  42. result[name] = atRule(child)
  43. } else if (Array.isArray(result[name])) {
  44. result[name].push(atRule(child))
  45. } else {
  46. result[name] = [result[name], atRule(child)]
  47. }
  48. } else if (child.type === 'rule') {
  49. let body = process(child)
  50. if (result[child.selector]) {
  51. for (let i in body) {
  52. let object = result[child.selector];
  53. if (stringifyImportant && object[i] && object[i].endsWith('!important')) {
  54. if (body[i].endsWith('!important')) {
  55. object[i] = body[i]
  56. }
  57. } else {
  58. object[i] = body[i]
  59. }
  60. }
  61. } else {
  62. result[child.selector] = body
  63. }
  64. } else if (child.type === 'decl') {
  65. if (child.prop[0] === '-' && child.prop[1] === '-') {
  66. name = child.prop
  67. } else if (child.parent && child.parent.selector === ':export') {
  68. name = child.prop
  69. } else {
  70. name = camelcase(child.prop)
  71. }
  72. let value = child.value
  73. if (!isNaN(child.value) && UNITLESS[name]) {
  74. value = parseFloat(child.value)
  75. }
  76. if (child.important) value += ' !important'
  77. if (typeof result[name] === 'undefined') {
  78. result[name] = value
  79. } else if (Array.isArray(result[name])) {
  80. result[name].push(value)
  81. } else {
  82. result[name] = [result[name], value]
  83. }
  84. }
  85. })
  86. return result
  87. }
  88. module.exports = process