From 6954668eda5698f9cc155bb1364234ce59ed7b33 Mon Sep 17 00:00:00 2001 From: drugan Date: Wed, 17 May 2017 11:54:13 +0300 Subject: [PATCH 1/2] Add detect() method for the tab-size.js --- src/options/tab-size.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/options/tab-size.js b/src/options/tab-size.js index d9a4b753..ad05882f 100644 --- a/src/options/tab-size.js +++ b/src/options/tab-size.js @@ -22,5 +22,38 @@ module.exports = { ast.traverseByType('space', function(space) { space.content = space.content.replace(/\t/, value); }); + }, + + /** + * Detects the value of this option in ast. + * @param {Node} ast + * @return {Array?} List of detected values + */ + detect(ast) { + var detected = []; + + ast.traverseByType('block', block => { + var spaces = 0; + var tabs = 0; + + block.forEach(blockContent => { + if (blockContent.is('space')) { + spaces = blockContent.content.replace(/\n/g, ''); + tabs = spaces.match(/\t/g); + // It is very rare case when tabs are used in a file instead of + // whitespaces and it requires a lot of efforts to find the tab size + // in a particular environment, ... so we imply that tab size = 2. + tabs = tabs ? tabs.length * 2 : 0; + spaces = spaces.match(/( )/g); + spaces = spaces ? spaces.length + tabs : tabs; + + } else if (spaces && blockContent.is('declaration')) { + detected.push(spaces); + spaces = 0; + } + }); + }); + + return detected; } }; From 4dbb02e3ebd79ae8ce2d1f1eea861b2d61e21167 Mon Sep 17 00:00:00 2001 From: drugan Date: Fri, 2 Jun 2017 18:55:39 +0300 Subject: [PATCH 2/2] Improved logic for tab-size.js detect() and fixed a bug when running integral/detect/test.js --- src/options/tab-size.js | 57 ++++++++++++++++++---------- test/options/integral/detect/test.js | 2 + 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/options/tab-size.js b/src/options/tab-size.js index ad05882f..c372f337 100644 --- a/src/options/tab-size.js +++ b/src/options/tab-size.js @@ -32,26 +32,43 @@ module.exports = { detect(ast) { var detected = []; - ast.traverseByType('block', block => { - var spaces = 0; - var tabs = 0; - - block.forEach(blockContent => { - if (blockContent.is('space')) { - spaces = blockContent.content.replace(/\n/g, ''); - tabs = spaces.match(/\t/g); - // It is very rare case when tabs are used in a file instead of - // whitespaces and it requires a lot of efforts to find the tab size - // in a particular environment, ... so we imply that tab size = 2. - tabs = tabs ? tabs.length * 2 : 0; - spaces = spaces.match(/( )/g); - spaces = spaces ? spaces.length + tabs : tabs; - - } else if (spaces && blockContent.is('declaration')) { - detected.push(spaces); - spaces = 0; - } - }); + ast.forEach(node => { + if (node.is('ruleset') || node.is('atrule')) { + var spaces = 0; + var tabs = 0; + var tabsize; + + node.forEach(block => { + if (block && block.is('block')) { + block.forEach(blockContent => { + // The indent before the very first property declaration in the + // block usually has a length of one tab or the number of + // whitespaces set for a tab. Because there might be nested + // blocks having incremented indent, we continue to the next root + // block in the each ruleset where tabsize is not detected yet. + if (tabsize !== 'detected') { + if (blockContent.is('space')) { + spaces = blockContent.content.replace(/\n/g, ''); + tabs = spaces.match(/\t/g); + spaces = spaces.match(/( )/g); + if (tabs) { + // It is a very rare case when tabs are used in a file + // instead of whitespaces and it requires a lot of efforts + // to find the tab size in a particular environment. So we + // imply that tab size = 2. + tabsize = 2; + } else if (spaces) { + tabsize = spaces.length; + } + } else if (tabsize && blockContent.is('declaration')) { + detected.push(tabsize); + tabsize = 'detected'; + } + } + }); + } + }); + } }); return detected; diff --git a/test/options/integral/detect/test.js b/test/options/integral/detect/test.js index e4f40a28..cb6132a4 100644 --- a/test/options/integral/detect/test.js +++ b/test/options/integral/detect/test.js @@ -9,6 +9,8 @@ describe('Option `integral`, detect', function() { let expected = JSON.parse(JSON.stringify(test.Comb.getConfig('csscomb'))); delete expected['sort-order']; delete expected.exclude; + // The default csscomb.json has no tab-size option. + expected['tab-size'] = 4; test.shouldDetect(undefined, input, expected); }); });