block-indent.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. module.exports = (function() {
  2. var syntax;
  3. var value;
  4. function processNode(node, level) {
  5. level = level || 0;
  6. // XXX: Hack for braces
  7. if (node.is('braces') || node.is('id')) return;
  8. for (var i = 0; i < node.length; i++) {
  9. var n = node.get(i);
  10. if (!n) continue;
  11. if (syntax === 'sass' && n.is('block')) {
  12. processSassBlock(n, level, value);
  13. }
  14. // Continue only with space nodes inside {...}:
  15. if (syntax !== 'sass' && level !== 0 && n.is('space')) {
  16. processSpaceNode(n, level, value);
  17. }
  18. if (n.is('block') || n.is('atrulers')) level++;
  19. processNode(n, level);
  20. }
  21. }
  22. function processSassBlock(node, level, value) {
  23. var spaces;
  24. var whitespaceNode;
  25. var i;
  26. for (i = node.length; i--;) {
  27. whitespaceNode = node.get(i);
  28. if (!whitespaceNode.is('space')) continue;
  29. if (whitespaceNode.content === '\n') continue;
  30. spaces = whitespaceNode.content.replace(/[ \t]/gm, '');
  31. spaces += new Array(level + 2).join(value);
  32. whitespaceNode.content = spaces;
  33. }
  34. }
  35. function processSpaceNode(node, level, value) {
  36. var spaces;
  37. // Remove all whitespaces and tabs, leave only new lines:
  38. spaces = node.content.replace(/[ \t]/gm, '');
  39. if (!spaces) return;
  40. spaces += new Array(level + 1).join(value);
  41. node.content = spaces;
  42. }
  43. return {
  44. name: 'block-indent',
  45. runBefore: 'sort-order',
  46. syntax: ['css', 'less', 'sass', 'scss'],
  47. accepts: {
  48. number: true,
  49. string: /^[ \t]*$/
  50. },
  51. /**
  52. * Processes tree node.
  53. *
  54. * @param {node} node
  55. */
  56. process: function process(node) {
  57. var spaces;
  58. var whitespaceNode;
  59. var i;
  60. if (!node.is('stylesheet')) return;
  61. syntax = this.getSyntax();
  62. value = this.getValue('block-indent');
  63. for (i = node.length; i--;) {
  64. whitespaceNode = node.get(i);
  65. if (!whitespaceNode.is('space')) continue;
  66. spaces = whitespaceNode.content.replace(/\n[ \t]+/gm, '\n');
  67. if (spaces === '') {
  68. node.remove(i);
  69. } else {
  70. whitespaceNode.content = spaces;
  71. }
  72. }
  73. processNode(node);
  74. },
  75. /**
  76. * Detects the value of an option at the tree node.
  77. *
  78. * @param {node} node
  79. */
  80. detect: function(node) {
  81. var result = [];
  82. // Continue only with non-empty {...} blocks:
  83. if (!node.is('atrulers') && !node.is('block') || !node.length)
  84. return;
  85. for (var i = node.length; i--;) {
  86. var whitespaceNode = node.get(i);
  87. if (!whitespaceNode.is('space')) continue;
  88. var spaces = whitespaceNode.content;
  89. var lastIndex = spaces.lastIndexOf('\n');
  90. // Do not continue if there is no line break:
  91. if (lastIndex < 0) continue;
  92. // Number of spaces from beginning of line:
  93. var spacesLength = spaces.slice(lastIndex + 1).length + 1;
  94. result.push(new Array(spacesLength).join(' '));
  95. }
  96. return result;
  97. }
  98. };
  99. })();