Skip to content

Commit

Permalink
Merge pull request #13 from bem-sdk/yeti-or.elem-in-ctx
Browse files Browse the repository at this point in the history
Add context to elems and transform style to obj
  • Loading branch information
Yeti-or committed Apr 19, 2017
2 parents 345fbca + 1b04d89 commit a46a6ef
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 23 deletions.
16 changes: 15 additions & 1 deletion lib/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,26 @@ function propToStr (key, val) {

function objToStr(obj) {
const keys = Object.keys(obj);
if (!keys.length) { return ''; }
if (!keys.length) { return '{}'; }
return `{ ${keys.map(k => propToStr(k, obj[k])).join(', ')} }`;
}

function styleToObj(style) {
if (typeof style === 'string') {
return style.split(';').reduce((acc, st) => {
if (st.length) {
var prop = st.split(':');
acc[prop[0]] = prop[1];
}
return acc;
}, {});
}
return style;
}

module.exports = {
objToStr,
arrToStr,
styleToObj,
valToStr
};
37 changes: 23 additions & 14 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var pascalCase = require('pascal-case');

var reactMappings = require('./reactMappings');
var valToStr = require('./helpers').valToStr;
var styleToObj = require('./helpers').styleToObj;

var plugins = require('./plugins');

Expand All @@ -17,12 +18,12 @@ function JSXNode(tag, props, children) {
}

var propsToStr = props => Object.keys(props).reduce((acc, k) => {
if (typeof props[k] === 'string') {
return acc + ` ${k}=${valToStr(props[k])}`
} else {
return acc + ` ${k}={${valToStr(props[k])}}`
}
}, '');
if (typeof props[k] === 'string') {
return acc + ` ${k}=${valToStr(props[k])}`
} else {
return acc + ` ${k}={${valToStr(props[k])}}`
}
}, '');
var tagToClass = tag => reactMappings[tag] ? tag : pascalCase(tag);

JSXNode.prototype.toString = function() {
Expand All @@ -43,14 +44,16 @@ JSXNode.prototype.toString = function() {
};

function Transformer(options) {
this.plugins = plugins.defaultPlugins;
this.plugins = [];
this.use(plugins.defaultPlugins);
this.bemNaming = bn(options.naming || 'react');
}

Transformer.prototype.process = function(bemjson) {
var nodes = [{
json: bemjson,
id: 0,
blockName: '',
tree: []
}];
var root = nodes[0];
Expand All @@ -61,11 +64,12 @@ Transformer.prototype.process = function(bemjson) {

if (Array.isArray(json)) {
for (i = 0; i < json.length; i++) {
nodes.push({ json: json[i], id: i, tree: node.tree });
nodes.push({ json: json[i], id: i, tree: node.tree, blockName: node.blockName});
}
} else {
var res = undefined;
var jsx = new JSXNode();
var blockName = json.block || node.blockName;

if (typeof json === 'string') {
jsx.isText = true;
Expand All @@ -74,17 +78,18 @@ Transformer.prototype.process = function(bemjson) {

if (json.tag) {
jsx.tag = json.tag;
} else if (json.block) {
jsx.bemEntity = new BemEntity({block: json.block, elem: json.elem});
} else if (json.block || json.elem) {
jsx.bemEntity = new BemEntity({ block: blockName, elem: json.elem });
jsx.tag = this.bemNaming.stringify(jsx.bemEntity);
}

for (i = 0; i < this.plugins.length; i++) {
var plugin = this.plugins[i];
res = plugin(jsx, json);
res = plugin(jsx, Object.assign({ block: blockName }, json));
if (res !== undefined) {
json = res;
node.json = json;
node.blockName = blockName;
nodes.push(node);
break;
}
Expand All @@ -94,11 +99,13 @@ Transformer.prototype.process = function(bemjson) {
var content = json.content;
if (content) {
if (Array.isArray(content)) {
// flatten
json.content = content = content.concat.apply([], content);
for (i = 0; i < content.length; i++) {
nodes.push({ json: content[i], id: i, tree: jsx.children });
nodes.push({ json: content[i], id: i, tree: jsx.children, blockName: blockName });
}
} else {
nodes.push({ json: content, id: 'children', tree: jsx});
nodes.push({ json: content, id: 'children', tree: jsx, blockName: blockName });
}
} else {
jsx.children = undefined;
Expand All @@ -119,7 +126,7 @@ Transformer.prototype.process = function(bemjson) {
};

Transformer.prototype.use = function() {
[].push.apply(this.plugins, arguments)
this.plugins = [].concat.apply(this.plugins, arguments)
return this;
};

Expand All @@ -134,5 +141,7 @@ Transformer.prototype.Transformer = Transformer;
module.exports = function(opts) {
return new Transformer(opts || {});
};

module.exports.tagToClass = tagToClass;
module.exports.plugins = plugins;
module.exports.styleToObj = styleToObj;
12 changes: 12 additions & 0 deletions lib/plugins.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
var styleToObj = require('./helpers').styleToObj;

module.exports.defaultPlugins = [
function copyMods(jsx, bemjson) {
Expand All @@ -8,9 +9,19 @@ module.exports.defaultPlugins = [

Object.keys(bemjson).forEach(k => {
if(~blackList.indexOf(k)) { return; }
if(k === 'attrs') {
bemjson[k]['style'] && (jsx.props['style'] = bemjson[k]['style']);
}

jsx.props[k] = bemjson[k];
});
},
function stylePropToObj(jsx) {
if (jsx.props['style']) {
jsx.props['style'] = styleToObj(jsx.props['style'])
jsx.props['attrs'] &&
(jsx.props['attrs']['style'] = jsx.props['style']);
}
}
];

Expand All @@ -24,3 +35,4 @@ module.exports.whiteList = function(options) {
}
}
};

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
"homepage": "https://github.com/bem-sdk/bemjson-to-jsx#readme",
"dependencies": {
"@bem/entity-name": "^1.4.0",
"@bem/entity-name": "github:bem-sdk/bem-entity-name",
"@bem/naming": "^2.0.0-6",
"pascal-case": "^2.0.1"
}
Expand Down
20 changes: 17 additions & 3 deletions test/helpers.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
const expect = require('chai').expect;

const objToStr = require('../lib/helpers').objToStr;
const helpers = require('../lib/helpers');
const objToStr = helpers.objToStr;
const styleToObj = helpers.styleToObj;


describe('helpers: objToStr', () => {
it('should stringify object', () => {
expect(objToStr({ hello: 'world' })).to.equal('{ \'hello\': \'world\' }');
});

it('should return empty string for empty obj', () => {
expect(objToStr({})).to.equal('');
it('should return empty obj for empty obj', () => {
expect(objToStr({})).to.equal('{}');
});

it('should process many keys', () => {
Expand Down Expand Up @@ -58,3 +60,15 @@ describe('helpers: objToStr', () => {
});
});
});

describe('helpers: styleToObj', () => {
it('should transform style string to style obj', () => {
var obj = styleToObj('width:200px;height:100px;');
expect(obj).to.eql({ width: '200px', height: '100px' });
});

it('should not transform style obj to smth else', () => {
var obj = styleToObj({ width: '200px', height: '100px' });
expect(obj).to.eql({ width: '200px', height: '100px' });
});
});
6 changes: 6 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ describe('transform', () => {
).to.equal(`<span>\n<Button2 text='hello'/>\n<Button2 text='world'/>\n</span>`);
});

it('should transform elem in context of block', () => {
expect(
transform({ block: 'button2', content: { elem: 'text', content: 'Hello' } }).JSX
).to.equal(`<Button2>\n<Button2Text>\nHello\n</Button2Text>\n</Button2>`);
});

it('should treat mods as props', () => {
expect(
transform({ block: 'button2', mods: {theme: 'normal', size: 's'} }).JSX
Expand Down
24 changes: 20 additions & 4 deletions test/plugins.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
const expect = require('chai').expect;

var T = require('../lib');
var transformer = T();

var BemEntity = require('@bem/entity-name');
// var transform = transformer.process.bind(transformer);

describe('pluginis', () => {

describe('whiteList', () => {
it('without opts', () => {
var res = transformer
var res = T()
.use(T.plugins.whiteList())
.process({ block: 'button2' });

Expand All @@ -20,7 +18,7 @@ describe('pluginis', () => {
});

it('whiteList', () => {
var res = transformer
var res = T()
.use(T.plugins.whiteList({ entities: [{ block: 'button2' }].map(BemEntity.create) }))
.process({ block: 'button2', content: [{ block: 'menu' }, { block: 'selec' }] });

Expand All @@ -30,4 +28,22 @@ describe('pluginis', () => {
});
});

describe('stylePropToObj', () => {
it('styleProp to obj', () => {
var res = T().process({ block: 'button2', style: 'width:200px' });

expect(res.JSX).to.equal(
`<Button2 style={{ 'width': '200px' }}/>`
);
});

it('attrs style to obj', () => {
var res = T().process({ block: 'button2', attrs: { style: 'width:200px' } });

expect(res.JSX).to.equal(
`<Button2 style={{ 'width': '200px' }} attrs={{ 'style': { 'width': '200px' } }}/>`
);
});
});

});

0 comments on commit a46a6ef

Please sign in to comment.