object-stringifier.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. 'use strict';
  2. const camelCase = require('./camel-case');
  3. const Stringifier = require('postcss/lib/stringifier');
  4. class ObjectStringifier extends Stringifier {
  5. object(node) {
  6. this.builder('{', node, 'start');
  7. let after;
  8. if (node.nodes && node.nodes.length) {
  9. this.body(node);
  10. after = this.raw(node, 'after');
  11. } else {
  12. after = this.raw(node, 'after', 'emptyBody');
  13. }
  14. if (after) this.builder(after);
  15. this.builder('}', node, 'end');
  16. }
  17. literal(node, semicolon) {
  18. this.builder(node.text + (semicolon ? ',' : ''), node);
  19. }
  20. decl(node, semicolon) {
  21. let prop = this.rawValue(node, 'prop');
  22. if (prop === 'float') {
  23. prop = 'cssFloat';
  24. }
  25. let string = prop;
  26. const isObjectShorthand = node.raws.node && node.raws.node.shorthand;
  27. if (!isObjectShorthand) {
  28. const between = this.raw(node, 'between', 'colon');
  29. const value = this.rawValue(node, 'value');
  30. string += between + value;
  31. }
  32. if (semicolon) string += ',';
  33. this.builder(string, node);
  34. }
  35. rule(node, semicolon) {
  36. this.block(node, this.rawValue(node, 'selector'), semicolon);
  37. }
  38. atrule(node, semicolon) {
  39. const name = this.rawValue(node, 'name');
  40. const params = this.rawValue(node, 'params');
  41. if (node.nodes) {
  42. let string;
  43. if (params) {
  44. const afterName = this.raw(node, 'afterName');
  45. string = name + afterName + params;
  46. } else {
  47. string = name;
  48. }
  49. this.block(node, string, semicolon);
  50. } else {
  51. const between = this.raw(node, 'between', 'colon');
  52. let string = name + between + params;
  53. if (semicolon) string += ',';
  54. this.builder(string, node);
  55. }
  56. }
  57. block(node, start, semicolon) {
  58. super.block(node, start);
  59. if (semicolon) {
  60. this.builder(',', node);
  61. }
  62. }
  63. comment(node) {
  64. const left = this.raw(node, 'left', 'commentLeft');
  65. const right = this.raw(node, 'right', 'commentRight');
  66. if (node.raws.inline) {
  67. const text = node.raws.text || node.text;
  68. this.builder('//' + left + text + right, node);
  69. } else {
  70. this.builder('/*' + left + node.text + right + '*/', node);
  71. }
  72. }
  73. raw(node, own, detect) {
  74. let value = super.raw(node, own, detect);
  75. if (
  76. (own === 'between' || (own === 'afterName' && node.type === 'atrule' && !node.nodes)) &&
  77. !/:/.test(value)
  78. ) {
  79. value = ':' + value;
  80. } else if (own === 'before' && /^(decl|rule)$/.test(node.type)) {
  81. value = value.replace(/\S+$/, '');
  82. }
  83. return value;
  84. }
  85. rawValue(node, prop) {
  86. const raw = node.raws[prop];
  87. if (raw) {
  88. const descriptor = Object.getOwnPropertyDescriptor(raw, 'raw');
  89. if (descriptor && descriptor.get) {
  90. return raw.prefix + raw.raw + raw.suffix;
  91. }
  92. }
  93. let value = super.rawValue(node, prop);
  94. if (value === null || value === undefined) {
  95. return value;
  96. }
  97. if (/^(prop|selector)$/i.test(prop)) {
  98. value = camelCase(value);
  99. if (node.raws.before && /(\S+)$/.test(node.raws.before)) {
  100. value = RegExp.$1 + value;
  101. } else if (value && !/\W/.test(value)) {
  102. return value;
  103. }
  104. } else if (node.type === 'atrule') {
  105. if (prop === 'name') {
  106. value = '@' + value;
  107. } else if (node.nodes) {
  108. return;
  109. }
  110. if (node.nodes) {
  111. value += this.raw(node, 'afterName');
  112. value += super.rawValue(node, 'params');
  113. }
  114. }
  115. value = JSON.stringify(value);
  116. return value;
  117. }
  118. }
  119. module.exports = ObjectStringifier;