From 7f36cfacab765dc0b2d1fc053c4d7151f355004f Mon Sep 17 00:00:00 2001 From: Sergey Belozyorcev Date: Tue, 12 Jul 2016 21:53:00 +0300 Subject: [PATCH] Merge from 'pobems v0.3.1' --- lib/index.js | 66 +++++++++++++++++++++++++++++++++-------------- test/lib/index.js | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 20 deletions(-) diff --git a/lib/index.js b/lib/index.js index 6f17e3a..4f8c0cb 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,32 +3,32 @@ import postcss from 'postcss'; const modDelim = process.env.REBEM_MOD_DELIM || '_'; const elemDelim = process.env.REBEM_ELEM_DELIM || '__'; -function buildSelector (block) { +function buildSelector (ctx, mod) { let selector = '.'; - if (block.blockName) { - selector += block.blockName; + if (ctx.blockName) { + selector += ctx.blockName; } - if (block.elemName) { - selector += elemDelim + block.elemName; + if (ctx.elemName) { + selector += elemDelim + ctx.elemName; } - if (block.modName) { - selector += modDelim + block.modName; + if (mod) { + selector += modDelim + mod; } return selector; } -export default postcss.plugin('rebem-css', () => (css) => { +export default postcss.plugin('pobems', () => (css) => { css.walkRules((rule) => { rule.selector = rule.selector .replace(/(:block\(.+)/g, (match, rawSelector) => { // ":block(b):mod(m v) div :block(b2)" -> [":block(b):mod(m v)", "div", "block(b2)"] - const groups = rawSelector.split(/\s+(?!\w+\))/gi); + const groups = rawSelector.split(/\s+(?![\w\s->'",]+\))/gi); - const re = /:(block|elem|mod)\(([\w-\s]+)\)(\s+)?/g; - const blockDecl = { blockName: false, elemName: false, modName: false }; + const re = /(:+)([\w-]+)(\((['",\w->\s]+)\))?/g; + const ctx = { blockName: false, elemName: false }; // Convert all groups to CSS selectors // :block(b):mod(m v) -> .b_m_v @@ -43,25 +43,51 @@ export default postcss.plugin('rebem-css', () => (css) => { let selector = ''; let mathes = null; + let requiredBuild = false; while ((mathes = re.exec(group)) !== null) { + const _spliter = 1; + const _tag = 2; + const _rawValue = 3; + const _value = 4; + const spliter = mathes[_spliter]; + const tag = mathes[_tag]; + const rawValue = mathes[_rawValue]; + const value = mathes[_value] ? + mathes[_value].replace(/([\(\)'"])/g, '').trim() : false; + + + if (tag === 'block') { + requiredBuild = true; + ctx.blockName = value; + continue; + } - if (mathes[1] === 'block') { - blockDecl.blockName = mathes[2]; + if (tag === 'elem') { + requiredBuild = true; + ctx.elemName = value; + continue; } - if (mathes[1] === 'elem') { - blockDecl.elemName = mathes[2]; + if (tag === 'mod') { + requiredBuild = false; + const mod = value.replace(/(\s?->\s?|,\s?|\s+?)/g, modDelim); + + selector += buildSelector(ctx, mod); + continue; } - if (mathes[1] === 'mod') { - blockDecl.modName = mathes[2].replace(' ', modDelim); - selector += buildSelector(blockDecl); + // For pseudo-classes + selector += requiredBuild ? buildSelector(ctx) : ''; + selector += spliter + tag; + if (rawValue) { + selector += rawValue; } + requiredBuild = false; } - if (!blockDecl.modName) { - selector += buildSelector(blockDecl); + if (requiredBuild) { + selector += buildSelector(ctx); } result.push(selector); diff --git a/test/lib/index.js b/test/lib/index.js index 986e38f..cae7917 100644 --- a/test/lib/index.js +++ b/test/lib/index.js @@ -27,6 +27,27 @@ describe('plugin', () => { ); }); + it('block name with double quotes', () => { + test( + ':block("block1") :block("block2")', + '.block1 .block2' + ); + }); + + it('block name with single quotes', () => { + test( + ':block(\'block1\') :block(\'block2\')', + '.block1 .block2' + ); + }); + + it('with pseudo classes', () => { + test( + ':root :block(block1):mod(m v):hover::before :block(block1):nth-of-type(2)', + ':root .block1_m_v:hover::before .block1:nth-of-type(2)' + ); + }); + it('with other tags', () => { test( ':block(block1) div :block(bl2) img', @@ -81,6 +102,13 @@ describe('plugin', () => { ); }); + it('multiple blocks mods with delimeter "-" in value', () => { + test( + ':block(block):mod(mod val-1) :block(block):elem(icon)', + '.block_mod_val-1 .block__icon' + ); + }); + it('block mod', () => { test( ':block(block):mod(mod val)', @@ -88,12 +116,33 @@ describe('plugin', () => { ); }); + it('block mod with double quotes', () => { + test( + ':block("block1"):mod("mod", "val")', + '.block1_mod_val' + ); + }); + + it('block mod with single quotes', () => { + test( + ':block(\'block1\'):mod(\'mod\',\'val\')', + '.block1_mod_val' + ); + }); + it('multiple blocks mods', () => { test( ':block(block1):mod(mod1 val1) :block(block2):mod(mod2 val2)', '.block1_mod1_val1 .block2_mod2_val2' ); }); + + it('mod val with delimeter "->"', () => { + test( + ':block(block1):mod(mod1 -> val1) :block(block2):mod("mod2" -> "val2")', + '.block1_mod1_val1 .block2_mod2_val2' + ); + }); }); describe('elem', () => {