You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
2.2 KiB

2 years ago
  1. let postcss = require('postcss')
  2. let IMPORTANT = /\s*!important\s*$/i
  3. let UNITLESS = {
  4. 'box-flex': true,
  5. 'box-flex-group': true,
  6. 'column-count': true,
  7. 'flex': true,
  8. 'flex-grow': true,
  9. 'flex-positive': true,
  10. 'flex-shrink': true,
  11. 'flex-negative': true,
  12. 'font-weight': true,
  13. 'line-clamp': true,
  14. 'line-height': true,
  15. 'opacity': true,
  16. 'order': true,
  17. 'orphans': true,
  18. 'tab-size': true,
  19. 'widows': true,
  20. 'z-index': true,
  21. 'zoom': true,
  22. 'fill-opacity': true,
  23. 'stroke-dashoffset': true,
  24. 'stroke-opacity': true,
  25. 'stroke-width': true
  26. }
  27. function dashify(str) {
  28. return str
  29. .replace(/([A-Z])/g, '-$1')
  30. .replace(/^ms-/, '-ms-')
  31. .toLowerCase()
  32. }
  33. function decl(parent, name, value) {
  34. if (value === false || value === null) return
  35. if (!name.startsWith('--')) {
  36. name = dashify(name)
  37. }
  38. if (typeof value === 'number') {
  39. if (value === 0 || UNITLESS[name]) {
  40. value = value.toString()
  41. } else {
  42. value += 'px'
  43. }
  44. }
  45. if (name === 'css-float') name = 'float'
  46. if (IMPORTANT.test(value)) {
  47. value = value.replace(IMPORTANT, '')
  48. parent.push(postcss.decl({ prop: name, value, important: true }))
  49. } else {
  50. parent.push(postcss.decl({ prop: name, value }))
  51. }
  52. }
  53. function atRule(parent, parts, value) {
  54. let node = postcss.atRule({ name: parts[1], params: parts[3] || '' })
  55. if (typeof value === 'object') {
  56. node.nodes = []
  57. parse(value, node)
  58. }
  59. parent.push(node)
  60. }
  61. function parse(obj, parent) {
  62. let name, value, node
  63. for (name in obj) {
  64. value = obj[name]
  65. if (value === null || typeof value === 'undefined') {
  66. continue
  67. } else if (name[0] === '@') {
  68. let parts = name.match(/@(\S+)(\s+([\W\w]*)\s*)?/)
  69. if (Array.isArray(value)) {
  70. for (let i of value) {
  71. atRule(parent, parts, i)
  72. }
  73. } else {
  74. atRule(parent, parts, value)
  75. }
  76. } else if (Array.isArray(value)) {
  77. for (let i of value) {
  78. decl(parent, name, i)
  79. }
  80. } else if (typeof value === 'object') {
  81. node = postcss.rule({ selector: name })
  82. parse(value, node)
  83. parent.push(node)
  84. } else {
  85. decl(parent, name, value)
  86. }
  87. }
  88. }
  89. module.exports = function (obj) {
  90. let root = postcss.root()
  91. parse(obj, root)
  92. return root
  93. }