-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add parse, convert, stringify, load and improvements
- Loading branch information
Showing
17 changed files
with
315 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
'use strict'; | ||
|
||
const assert = require('assert'); | ||
|
||
const isNotSupported = () => { | ||
throw new Error( | ||
'This format isn\'t supported yet, file an issue: https://github.com/bem-sdk/bem-decl/issues/new' | ||
); | ||
}; | ||
|
||
const converters = { | ||
enb: require('./convert/enb'), | ||
v2: isNotSupported, | ||
v1: isNotSupported, | ||
harmony: isNotSupported | ||
}; | ||
|
||
/** | ||
* Convert normalized declaration to target format | ||
* | ||
* @param {Array|Object} decl normalized declaration | ||
* @param {Object} opts Addtional options | ||
* @param {String} opts.version format version | ||
* @return {Array} Array with converted declaration | ||
*/ | ||
module.exports = function (decl, opts) { | ||
opts || (opts = {}); | ||
|
||
const version = opts.version; | ||
|
||
assert(version, 'You must declare target version'); | ||
|
||
if (!converters[version]) { | ||
throw new Error('Unknown format'); | ||
} | ||
|
||
return converters[version](decl); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
'use strict'; | ||
|
||
/** | ||
* Convert normalized declaration to enb format | ||
* | ||
* @param {Array|Object} decl Source declaration | ||
* @return {Array} | ||
*/ | ||
module.exports = function (decl) { | ||
Array.isArray(decl) || (decl = [decl]); | ||
|
||
return decl.map(item => { | ||
const entity = item.entity; | ||
let tmp = {}; | ||
|
||
tmp.block = entity.block; | ||
entity.elem && (tmp.elem = entity.elem); | ||
entity.modName && (tmp.mod = entity.modName); | ||
entity.modVal && (tmp.val = entity.modVal); | ||
|
||
return tmp; | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
'use strict'; | ||
|
||
const assert = require('assert'); | ||
|
||
/** | ||
* Detects decl version | ||
* | ||
* @param {Object} obj Declaration object | ||
* @return {String} | ||
*/ | ||
module.exports = function (obj) { | ||
assert(typeof obj === 'object', 'Argument must be an object'); | ||
|
||
if (typeof obj.blocks === 'object') { | ||
return 'v1'; | ||
} else if (typeof obj.deps === 'object') { | ||
return 'enb'; | ||
} else if (typeof obj.decl === 'object' || Array.isArray(obj)) { | ||
return 'v2'; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
'use strict'; | ||
|
||
const fs = require('mz/fs'); | ||
|
||
const parse = require('./parse'); | ||
|
||
/** | ||
* Read file and call parse on its content | ||
* | ||
* @param {String} filePath path to file | ||
* @return {Promise} | ||
*/ | ||
module.exports = filePath => fs.readFile(filePath, 'utf-8').then(parse); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,45 @@ | ||
'use strict'; | ||
|
||
const assert = require('assert'); | ||
|
||
const nodeEval = require('node-eval'); | ||
|
||
const detect = require('./detect'); | ||
const normalize = require('./normalize'); | ||
const normalize2 = require('./normalize2'); | ||
const normalizeHarmony = require('./normalize-harmony'); | ||
|
||
const normalizers = { | ||
'1.0': normalize, | ||
next: normalizeHarmony | ||
v1: normalize, | ||
v2: normalize2, | ||
harmony: normalizeHarmony | ||
}; | ||
|
||
/** | ||
* Parses BEMDECL file data | ||
* | ||
* @param {{version: string, decl: BEMEntityPart[]}|{blocks: BEMEntityPart[]}} bemdecl [description] | ||
* @returns {[type]} [description] | ||
* @param {String|Object} bemdecl - string of bemdecl or object | ||
* @returns {Array<BemEntity>} Array of normalized entities | ||
*/ | ||
module.exports = function parse(bemdecl) { | ||
const hasOwn = Object.prototype.hasOwnProperty.bind(Object(bemdecl)); | ||
|
||
let version, decl; | ||
|
||
// Legacy 1.0 format | ||
if (hasOwn('blocks')) { | ||
version = '1.0'; | ||
decl = bemdecl.blocks; | ||
} else if (hasOwn('version') && hasOwn('decl')) { | ||
version = bemdecl.version; | ||
decl = bemdecl.decl; | ||
assert(typeof bemdecl === 'object' || typeof bemdecl === 'string', 'Bemdecl must be String or Object'); | ||
|
||
const declaration = (typeof bemdecl === 'string') ? nodeEval(bemdecl) : bemdecl; | ||
const hasOwn = Object.prototype.hasOwnProperty.bind(Object(declaration)); | ||
const version = declaration.version || detect(declaration); | ||
|
||
switch (version) { | ||
case 'v1': | ||
assert(hasOwn('blocks'), 'Invalid declaration format'); | ||
return normalizers.v1(declaration.blocks); | ||
case 'v2': | ||
case 'enb': | ||
assert(hasOwn('decl') || hasOwn('deps'), 'Invalid format of declaration.'); | ||
return normalizers.v2(declaration.decl || declaration.deps); | ||
case 'harmony': | ||
assert(hasOwn('decl'), 'Invalid format of declaration.'); | ||
return normalizers.harmony(declaration.decl); | ||
default: | ||
throw new Error('Unknown BEMDECL format.'); | ||
} | ||
|
||
const normalizer = normalizers[version]; | ||
|
||
if (!decl || !normalizer) { | ||
throw new Error('Unknown BEMDECL format.'); | ||
} | ||
|
||
return normalizer(decl); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
'use strict'; | ||
|
||
const assert = require('assert'); | ||
|
||
const convert = require('./convert'); | ||
|
||
/** | ||
* Create string representation of declaration | ||
* | ||
* @param {Array|Object} decl source declaration | ||
* @param {Object} opts additional options | ||
* @param {String} opts.version format version | ||
* @return {String} string representation | ||
*/ | ||
module.exports = function (decl, opts) { | ||
opts || (opts = {}); | ||
assert(opts.version, 'You must declare target version'); | ||
|
||
const version = opts.version; | ||
|
||
Array.isArray(decl) || (decl = [decl]); | ||
|
||
const formatedDecl = convert(decl, { version }); | ||
const jsonStr = JSON.stringify(formatedDecl, null, 4); | ||
|
||
let exportsStr = ''; | ||
|
||
if (version === 'v1') { | ||
exportsStr = 'exports.blocks'; | ||
} else if (version === 'enb') { | ||
exportsStr = 'exports.deps'; | ||
} else { | ||
exportsStr = 'module.exports'; | ||
} | ||
|
||
return `${exportsStr} = ${jsonStr};\n`; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
'use strict'; | ||
|
||
const test = require('ava'); | ||
|
||
const convert = require('../../lib/convert'); | ||
|
||
test('should throw exception if no version given', t => { | ||
t.throws(() => convert({ entity: { block: 'block' }, tech: null }), 'You must declare target version'); | ||
}); | ||
|
||
test('should convert to enb format', t => { | ||
t.deepEqual(convert({ entity: { block: 'block' }, tech: null }, { version: 'enb' }), [{ block: 'block' }]); | ||
}); | ||
|
||
test('should convert with elem', t => { | ||
t.deepEqual( | ||
convert([ | ||
{ entity: { block: 'block' }, tech: null }, | ||
{ entity: { block: 'block', elem: 'elem' }, tech: null } | ||
], { version: 'enb' }), | ||
[ | ||
{ block: 'block' }, | ||
{ block: 'block', elem: 'elem' } | ||
] | ||
); | ||
}); | ||
|
||
test('should convert with mod', t => { | ||
t.deepEqual( | ||
convert([ | ||
{ entity: { block: 'block', modName: 'mod', modVal: 'val' }, tech: null } | ||
], { version: 'enb' }), | ||
[{ block: 'block', mod: 'mod', val: 'val' }] | ||
) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
'use strict'; | ||
|
||
const test = require('ava'); | ||
|
||
const parse = require('../../lib/parse'); | ||
|
||
test('should throw error while parsing empty deps property if version not given', t => { | ||
t.deepEqual(parse('({ deps: [] })'), []); | ||
}); | ||
|
||
test('should parse blocks property with single entity', t => { | ||
t.deepEqual(parse('({ version: \'enb\', deps: [{ block: \'doesnt-matter\', elems: [\'elem\'] }] })'), | ||
[{ entity: { block: 'doesnt-matter' }, tech: null }, | ||
{ entity: { block: 'doesnt-matter', elem: 'elem' }, tech: null }]); | ||
}); | ||
|
||
test('should parse empty legacy blocks property of object', t => { | ||
t.deepEqual(parse({ version: 'enb', deps: [] }), []); | ||
}); | ||
|
||
test('should parse blocks property with single entity of object', t => { | ||
t.deepEqual(parse({ version: 'enb', deps: [{ block: 'doesnt-matter', elems: ['elem'] }] }), | ||
[{ entity: { block: 'doesnt-matter' }, tech: null }, | ||
{ entity: { block: 'doesnt-matter', elem: 'elem' }, tech: null }]); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
'use strict'; | ||
|
||
const test = require('ava'); | ||
const parse = require('../..').parse; | ||
|
||
test('should parse empty legacy blocks property', t => { | ||
t.deepEqual(parse('({ version: \'harmony\', decl: [] })'), []); | ||
}); | ||
|
||
test('should parse blocks property with single entity', t => { | ||
t.deepEqual(parse('({ version: \'harmony\', decl: [{ block: \'doesnt-matter\', elems: [\'elem\'] }] })'), | ||
[{ entity: { block: 'doesnt-matter' }, tech: null }, | ||
{ entity: { block: 'doesnt-matter', elem: 'elem' }, tech: null }]); | ||
}); | ||
|
||
test('should parse empty legacy blocks property of object', t => { | ||
t.deepEqual(parse({ version: 'harmony', decl: [] }), []); | ||
}); | ||
|
||
test('should parse blocks property with single entity of object', t => { | ||
t.deepEqual(parse({ version: 'harmony', decl: [{ block: 'doesnt-matter', elems: ['elem'] }] }), | ||
[{ entity: { block: 'doesnt-matter' }, tech: null }, | ||
{ entity: { block: 'doesnt-matter', elem: 'elem' }, tech: null }]); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.