-
Notifications
You must be signed in to change notification settings - Fork 24
Expand method in import-notation #288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
751d187
28099be
8b94a32
550bbbf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,7 @@ | ||
| const hashSet = require('hash-set'); | ||
| const helpers = require('./lib/helpers'); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add to package.json |
||
|
|
||
| const tmpl = { | ||
| b : b => `b:${b}`, | ||
| e : e => e ? ` e:${e}` : '', | ||
| m : m => Object.keys(m).map(name => `${tmpl.mn(name)}${tmpl.mv(m[name])}`).join(''), | ||
| mn : m => ` m:${m}`, | ||
| mv : v => v.length ? `=${v.join('|')}` : '', | ||
| t : t => t ? ` t:${t}` : '' | ||
| }; | ||
|
|
||
| const btmpl = Object.assign({}, tmpl, { | ||
| m : m => m ? `${tmpl.mn(m['name'])}${tmpl.mv([m['val']])}` : '' | ||
| }); | ||
|
|
||
| const BemCellSet = hashSet(cell => | ||
| ['block', 'elem', 'mod', 'tech'] | ||
| .map(k => btmpl[k[0]](cell[k])) | ||
| .join('') | ||
| ); | ||
| const BemCellSet = hashSet(helpers.stringifyCell); | ||
|
|
||
| /** | ||
| * Parse import statement and extract bem entities | ||
|
|
@@ -37,43 +21,43 @@ const BemCellSet = hashSet(cell => | |
| * @returns {BemCell[]} | ||
| */ | ||
| function parse(importString, ctx) { | ||
| const main = {}; | ||
| ctx || (ctx = {}); | ||
| const cell = {}; | ||
|
|
||
| ctx && (importString = helpers.expand(importString, ctx)); | ||
|
|
||
| return Array.from(importString.split(' ').reduce((acc, importToken) => { | ||
| const split = importToken.split(':'), | ||
| type = split[0], | ||
| tail = split[1]; | ||
|
|
||
| if(type === 'b') { | ||
| main.block = tail; | ||
| acc.add(main); | ||
| } else if(type === 'e') { | ||
| main.elem = tail; | ||
| if(!main.block && ctx.elem !== tail) { | ||
| main.block = ctx.block; | ||
| acc.add(main); | ||
| } | ||
| } else if(type === 'm' || type === 't') { | ||
| if(!main.block) { | ||
| main.block = ctx.block; | ||
| main.elem || ctx.elem && (main.elem = ctx.elem); | ||
| } | ||
| switch(type) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why switch here?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not? |
||
| case 'b': | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тоже не любишь делать доп отступ для case? ;-)
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Vasiliy не любит =)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually, it's O2 team code style. |
||
| cell.block = tail; | ||
| acc.add(cell); | ||
| break; | ||
|
|
||
| if(type === 'm') { | ||
| const splitMod = tail.split('='), | ||
| modName = splitMod[0], | ||
| modVals = splitMod[1]; | ||
| case 'e': | ||
| cell.elem = tail; | ||
| break; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is strange
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you add more details?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, sorry. we mutating |
||
|
|
||
| acc.add(Object.assign({}, main, { mod : { name : modName } })); | ||
| case 'm': { | ||
| const splitMod = tail.split('='), | ||
| modName = splitMod[0], | ||
| modVals = splitMod[1]; | ||
|
|
||
| acc.add(Object.assign({}, cell, { mod : { name : modName } })); | ||
|
|
||
| modVals && modVals.split('|').forEach(modVal => { | ||
| acc.add(Object.assign({}, cell, { mod : { name : modName, val : modVal } })); | ||
| }); | ||
| break; | ||
| } | ||
|
|
||
| modVals && modVals.split('|').forEach(modVal => { | ||
| acc.add(Object.assign({}, main, { mod : { name : modName, val : modVal } })); | ||
| }); | ||
| } else { | ||
| acc.size || acc.add(main); | ||
| acc.forEach(e => (e.tech = tail)); | ||
| } | ||
| case 't': | ||
| acc.forEach(e => { | ||
| e.tech = tail; | ||
| }); | ||
| break; | ||
| } | ||
| return acc; | ||
| }, new BemCellSet())); | ||
|
|
@@ -93,20 +77,21 @@ function parse(importString, ctx) { | |
| */ | ||
| function stringify(cells) { | ||
| const merged = [].concat(cells).reduce((acc, cell) => { | ||
| cell.block && (acc.b = cell.block); | ||
| cell.elem && (acc.e = cell.elem); | ||
| cell.mod && (acc.m[cell.mod.name] || (acc.m[cell.mod.name] = [])) | ||
| cell.block && (acc.block = cell.block); | ||
| cell.elem && (acc.elem = cell.elem); | ||
| cell.mod && (acc.mod[cell.mod.name] || (acc.mod[cell.mod.name] = [])) | ||
| && cell.mod.val && typeof cell.mod.val !== 'boolean' | ||
| && !~acc.m[cell.mod.name].indexOf(cell.mod.val) | ||
| && acc.m[cell.mod.name].push(cell.mod.val); | ||
| cell.tech && (acc.t = cell.tech); | ||
| && !~acc.mod[cell.mod.name].indexOf(cell.mod.val) | ||
| && acc.mod[cell.mod.name].push(cell.mod.val); | ||
| cell.tech && (acc.tech = cell.tech); | ||
| return acc; | ||
| }, { m : {} }); | ||
| }, { mod : {} }); | ||
|
|
||
| return ['b', 'e', 'm', 't'].map(k => tmpl[k](merged[k])).join(''); | ||
| return helpers.stringifyMergedCells(merged); | ||
| } | ||
|
|
||
| module.exports = { | ||
| parse, | ||
| stringify | ||
| stringify, | ||
| expand : helpers.expand | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| /** | ||
| * Helpers to test import-notation first part | ||
| */ | ||
| const tests = { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure about this object. Prob it's enough to make 2 simple functions
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did it a group of functions like
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nvm, not a blocker. |
||
| /** | ||
| * Returns true if notation starts with block-part | ||
| * | ||
| * Example: | ||
| * ```js | ||
| * b('b:button e:icon') // true | ||
| * b('e:icon') // false | ||
| * ``` | ||
| * | ||
| * @param {String} n - notation | ||
| * | ||
| * @returns {Boolean} | ||
| */ | ||
| b : n => /^b:/.test(n), | ||
|
|
||
| /** | ||
| * Returns true if notation starts with element-part | ||
| * | ||
| * Example: | ||
| * ```js | ||
| * b('b:button e:icon') // false | ||
| * b('e:icon') // true | ||
| * ``` | ||
| * | ||
| * @param {String} n - notation | ||
| * | ||
| * @returns {Boolean} | ||
| */ | ||
| e : n => /^e:/.test(n) | ||
| }; | ||
|
|
||
| /** | ||
| * @type {ImportNotationTemplates} | ||
| */ | ||
| const templates = { | ||
| /** | ||
| * Returns block-part of notation | ||
| * | ||
| * Example: | ||
| * ```js | ||
| * b('button') // 'b:button' | ||
| * ``` | ||
| * | ||
| * @param {String} b - name of block | ||
| * | ||
| * @returns {String} | ||
| */ | ||
| b : b => `b:${b}`, | ||
|
|
||
| /** | ||
| * Returns element-part of notation | ||
| * | ||
| * Example: | ||
| * ```js | ||
| * e('icon') // ' e:icon' | ||
| * ``` | ||
| * | ||
| * @param {String} e - name of element | ||
| * | ||
| * @returns {String} | ||
| */ | ||
| e : e => e ? ` e:${e}` : '', | ||
|
|
||
| /** | ||
| * Returns modifiers-part of notation | ||
| * | ||
| * Example: | ||
| * ```js | ||
| * m({ color: ['red', 'yellow'], theme: ['default'] }) | ||
| * // ' m:color=red|yellow m:theme=default' | ||
| * ``` | ||
| * | ||
| * @param {Object<String[]>} m - modifiers with values in arrays | ||
| * | ||
| * @returns {String} | ||
| */ | ||
| m : m => Object.keys(m).map(name => `${templates._mn(name)}${templates._mv(m[name])}`).join(''), | ||
|
|
||
| /** | ||
| * Returns modifier-name-part of notation | ||
| * | ||
| * Example: | ||
| * ```js | ||
| * _mn('color') // ' m:color' | ||
| * ``` | ||
| * | ||
| * @param {String} mn - name of modifier | ||
| * | ||
| * @returns {String} | ||
| */ | ||
| _mn : mn => ` m:${mn}`, | ||
|
|
||
| /** | ||
| * Returns modifier-values-part of notation | ||
| * | ||
| * Example: | ||
| * ```js | ||
| * _mv(['red', 'yellow']) // '=red|yellow' | ||
| * ``` | ||
| * | ||
| * @param {String[]} mv - modifier values in array | ||
| * | ||
| * @returns {String} | ||
| */ | ||
| _mv : mv => mv.length ? `=${mv.join('|')}` : '', | ||
|
|
||
| /** | ||
| * Returns technology-part of notation | ||
| * | ||
| * Example: | ||
| * ```js | ||
| * t('js') // ' t:js' | ||
| * ``` | ||
| * | ||
| * @param {String[]} t - name of technology | ||
| * | ||
| * @returns {String} | ||
| */ | ||
| t : t => t ? ` t:${t}` : '' | ||
| }; | ||
|
|
||
| /** | ||
| * Helpers for BemCell | ||
| * | ||
| * @type {ImportNotationTemplates} | ||
| */ | ||
| const cellTemplates = Object.assign({}, templates, { | ||
| /** | ||
| * Returns modifiers-part of notation | ||
| * | ||
| * Example: | ||
| * ```js | ||
| * m({ name: 'theme', val: 'default' }) // ' m:theme=default' | ||
| * ``` | ||
| * | ||
| * @param {{ name: String, val: String }} m - modifier with single value | ||
| * | ||
| * @returns {String} | ||
| */ | ||
| m : m => m ? `${templates._mn(m['name'])}${templates._mv([m['val']])}` : '' | ||
| }); | ||
|
|
||
| /** | ||
| * Returns import-notation stringify for set of templates | ||
| * | ||
| * @param {ImportNotationTemplates} ts - set of templates to build parts of import-notation | ||
| * | ||
| * @returns {String} | ||
| */ | ||
| const stringifyBuilder = ts => x => ['block', 'elem', 'mod', 'tech'].map(k => ts[k[0]](x[k])).join(''); | ||
|
|
||
| /** | ||
| * Returns import-notation expanded by context entity | ||
| * | ||
| * @param {String} n - notation | ||
| * @param {BemEntity} ctx - context entity | ||
| * | ||
| * @returns {String} | ||
| */ | ||
| const expand = (n, ctx) => { | ||
| if(tests.b(n)) { | ||
| return n; | ||
| } | ||
|
|
||
| return templates.b(ctx.block) + (tests.e(n) ? '' : templates.e(ctx.elem)) + ' ' + n; | ||
| }; | ||
|
|
||
| module.exports = { | ||
| expand, | ||
| stringifyMergedCells : stringifyBuilder(templates), | ||
| stringifyCell : stringifyBuilder(cellTemplates) | ||
| }; | ||
|
|
||
| /** | ||
| * Helpers to build parts of import-notation. All parts concatenated by '' gives import-notation string | ||
| * | ||
| * @typedef {Object} ImportNotationTemplates | ||
| * | ||
| * @property {Function} b - returns block-part of notation | ||
| * @property {Function} e - returns element-part of notation | ||
| * @property {Function} m - returns modifiers-part of notation | ||
| * @property {Function} t - returns technology-part of notation | ||
| */ | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
expand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I didn't understand the difference from parse method.
Actually, I understood but it was not so obvious
add examples of the distinction between them, please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure we need 2 methods? ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure!
expandgives us string and it is fast/lightweightThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure
expandis the most viable name for this functionality?I'd suggest:
fullfillfillupsate