Skip to content
This repository was archived by the owner on Aug 1, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion lib/schemes/flat.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
var bemNaming = require('bem-naming');
var path = require('path'),
bemNaming = require('bem-naming');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bem/naming


module.exports = {
path: function(entity, tech, options) {
options || (options = {});
var naming = bemNaming(options.naming);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I think this is not optimal to create the same thing many times per build.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but each level may have its own naming settings

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass in naming object instead of creating it on each call

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


return naming.stringify(entity) + '.' + tech;
},
parse: function(str, options) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jsdoc

if (path.basename(str) !== str) {
return;
}

options || (options = {});
var naming = bemNaming(options.naming),
splittedPath = str.split('.');

return {
Copy link

@qfox qfox Oct 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use here BemUnnamedObject? To reduce hidden classes quantity

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WAT?

Copy link

@qfox qfox Oct 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object like {entity: {block, elem, mod}, tech: ?String} has no name atm so it's BemUnnamedObject.
You are free to call it somehow, but not BemEntityTech and not Tenorok.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand profit of such naming so such simple things. Can't we refactor it later when we end up with some name and found real cases for it?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we refactor it later when we

Yes, we can.

end up with some name

We decided to call it BemCell or BemCytus for now

and found real cases for it?

https://github.com/bem-sdk/bem-decl/blob/master/lib/normalize.js#L13
https://github.com/bem-sdk/bem-graph/blob/master/lib/vertex.js#L7
etc.

entity: naming.parse(splittedPath[0]),
tech: splittedPath.slice(1).join('.')
};
}
};
44 changes: 43 additions & 1 deletion lib/schemes/nested.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,48 @@ module.exports = {
entity.modName ? modFolder : '');

return path.join(folder,
naming.stringify(entity) + '.' + tech);
naming.stringify(entity) + (tech ? '.' + tech : ''));
},
parse: function(str, options) {
options || (options = {});
var naming = bemNaming(options.naming),
splittedPath = str.split(path.sep).filter(Boolean),
file = splittedPath.pop(),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basename = path.basename(str);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need mutated splittedPath bellow

splittedFile = file.split('.'),
entity = naming.parse(splittedFile[0]),
tech = splittedFile.slice(1).join('.');

// support for paths without filename, e.g. 'b1/__e1/'
if (!entity) {
entity = naming.parse(splittedPath.join('') + splittedFile[0]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what exactly confuses you?

Copy link

@qfox qfox Oct 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we should parse directories as entities? Any real life case for that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cd level1/b1/__e1
bem create _m1_v1.css # b1__e1_m1_v1.css

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about

cd level1/b1/b2/b3
bem create _m1_v1.css # b1b2b3_m1_v1.css

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch 👍

}

if (splittedPath.length && entity.block !== splittedPath[0]) {
return;
}

// check if path is valid
for (var i = 1; i < splittedPath.length; i++) {
var chunk = splittedPath[i];

// __e1 or _m1
if (i === 1 &&
(chunk.indexOf(naming.elemDelim) !== 0 &&
chunk.indexOf(naming.modDelim) !== 0)
) { return; }

// __e1/_m1
if (i === 2 &&
(splittedPath[i - 1].indexOf(naming.elemDelim) !== 0 ||
chunk.indexOf(naming.modDelim) !== 0)
) { return; }

if (i > 2) { return; }
}

return {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

result should be bem-cell

entity: entity,
tech: tech
};
Copy link
Contributor

@a-x- a-x- Feb 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my implementation:

function parseBemPath(filePath) {
    const filePath_ = path.normalize(filePath);

    const cell = _parseComplexBemPath(filePath_); // With directories-technologies
    // null is a signal 'incorrect cell found'
    return cell || cell !== null && _parseSimpleBemPath(filePath_) || null;
}
function _parseComplexBemPath(filePath) {
    const chunks = filePath.split(path.sep);
    const block = chunks[1];
    const secondChunk = splitAtFirst(chunks[2], '.'); // E.g. ['suggest2', 'priv.js']

    if(!secondChunk[1]) { // Directory-technology, e.g. button2. < examples >/
        return; // skip, go to next processor
    }
    const cell = BemCell(secondChunk);
    return cell && !compareEntities(cell.entity, {block: block}).length ? cell : null;
}
function _parseSimpleBemPath(filePath) {
    const name = path.basename(filePath);
    const cellFromName = BemCell(splitAtFirst(name, '.'));

    if(!cellFromName) {
        return null;
    }
    const entityFromDir = parseDirAsBemCell(path.dirname(filePath));
    const diff = compareEntities(cellFromName.entity, entityFromDir);
    return !diff.length || _.isEqual(diff, ['modVal']) ? cellFromName : null;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compareEntities
parseDirAsBemCell
splitAtFirst
это какие то твои хелперы?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@a-x- а pr прислать ты не хочешь ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it's mine

yep, i can, but i afraid it useless and what would be changed if i do?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can see all of helpers in the internal pr: lego/islands-ci-helpers/pull/233

}
};
163 changes: 150 additions & 13 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
var expect = require('chai').expect,
scheme = require('..');

describe('default', function() {

it('should return path + tech', function() {
expect('a/a.js')
.eql(scheme().path({ block: 'a' }, 'js'));
});
describe('path', function() {
describe('default', function() {
it('should return path + tech', function() {
expect(scheme().path({ block: 'a' }, 'js'))
.eql('a/a.js');
});

it('should return nested scheme by default', function() {
expect(scheme().path({ block: 'a', elem: 'e1' }, 'js'))
.eql('a/__e1/a__e1.js');
});
it('should return nested scheme by default', function() {
expect(scheme().path({ block: 'a', elem: 'e1' }, 'js'))
.eql('a/__e1/a__e1.js');
});

it('should return error', function() {
var s = scheme;
expect(s.bind(s, 'scheme-not-found')).to.throw(/Scheme not found/);
it('should return error', function() {
var s = scheme;
expect(s.bind(s, 'scheme-not-found')).to.throw(/Scheme not found/);
});
});

it('should support optional naming style', function() {
Expand Down Expand Up @@ -131,3 +132,139 @@ describe('default', function() {
});
});
});

describe('parse', function() {
describe('default', function() {

});

describe('nested', function() {
it('should parse block', function() {
var expected = { entity: { block: 'b1' }, tech: '' };

expect(scheme().parse('b1')).eql(expected);
expect(scheme().parse('b1/')).eql(expected);
});

it('should parse elem', function() {
var expected = { entity: { block: 'b1', elem: 'e1' }, tech: '' };

expect(scheme().parse('b1__e1')).eql(expected);
expect(scheme().parse('b1/__e1')).eql(expected);
expect(scheme().parse('b1/__e1/')).eql(expected);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that it is a block_elem, but not block ?

expect(scheme().parse('b1/__e1/b1__e1')).eql(expected);
});

it('should parse block with boolean modifier', function() {
var expected = { entity: { block: 'b1', modName: 'm1', modVal: true }, tech: '' };

expect(scheme().parse('b1_m1')).eql(expected);
expect(scheme().parse('b1/_m1')).eql(expected);
expect(scheme().parse('b1/_m1/')).eql(expected);
expect(scheme().parse('b1/_m1/b1_m1')).eql(expected);
});

it('should parse block with key-value modifier', function() {
var expected = { entity: { block: 'b1', modName: 'm1', modVal: 'v1' }, tech: '' };

expect(scheme().parse('b1_m1_v1')).eql(expected);
expect(scheme().parse('b1/_m1/b1_m1_v1')).eql(expected);
});

it('should parse elem with boolean modifier', function() {
var expected = { entity: { block: 'b1', elem: 'e1', modName: 'm1', modVal: true }, tech: '' };

expect(scheme().parse('b1__e1_m1')).eql(expected);
expect(scheme().parse('b1/__e1/_m1')).eql(expected);
expect(scheme().parse('b1/__e1/_m1/')).eql(expected);
expect(scheme().parse('b1/__e1/_m1/b1__e1_m1')).eql(expected);
});

it('should parse elem with key-value modifier', function() {
var expected = { entity: { block: 'b1', elem: 'e1', modName: 'm1', modVal: 'v1' }, tech: '' };

expect(scheme().parse('b1__e1_m1_v1')).eql(expected);
expect(scheme().parse('b1/__e1/_m1/b1__e1_m1_v1')).eql(expected);
});

it('should parse tech', function() {
var expectedBlock = { entity: { block: 'b1' }, tech: 'spec.js' },
expectedBlockMod = { entity: { block: 'b1', modName: 'm1', modVal: true }, tech: 'spec.js' },
expectedElem = { entity: { block: 'b1', elem: 'e1' }, tech: 'spec.js' },
expectedElemMod = { entity: { block: 'b1', elem: 'e1', modName: 'm1', modVal: 'v1' }, tech: 'spec.js' };

expect(scheme().parse('b1.spec.js')).eql(expectedBlock);
expect(scheme().parse('b1/b1.spec.js')).eql(expectedBlock);

expect(scheme().parse('b1_m1.spec.js')).eql(expectedBlockMod);
expect(scheme().parse('b1/_m1/b1_m1.spec.js')).eql(expectedBlockMod);

expect(scheme().parse('b1__e1.spec.js')).eql(expectedElem);
expect(scheme().parse('b1/__e1/b1__e1.spec.js')).eql(expectedElem);

expect(scheme().parse('b1__e1_m1_v1.spec.js')).eql(expectedElemMod);
expect(scheme().parse('b1/__e1/_m1/b1__e1_m1_v1.spec.js')).eql(expectedElemMod);
});

it('should not parse wrong paths', function() {
expect(scheme().parse('b1/b2')).eql(undefined);
expect(scheme().parse('b1/b2/b3')).eql(undefined);
expect(scheme().parse('b1/b2/b1')).eql(undefined);
expect(scheme().parse('b1/b2/b1__e1')).eql(undefined);
expect(scheme().parse('b1/b2/b1__e1.t1')).eql(undefined);
expect(scheme().parse('b1/_m1/__e1/b1__e1_m1.t1')).eql(undefined);
expect(scheme().parse('blah/b1/_m1/__e1/b1__e1_m1.t1')).eql(undefined);
expect(scheme().parse('blah/b1/_m1/__e1/b1__e1_m1/b1__e1_m1.t1')).eql(undefined);
});
});

describe('flat', function() {
it('should parse block', function() {
var expected = { entity: { block: 'b1' }, tech: '' };

expect(scheme('flat').parse('b1')).eql(expected);
});

it('should parse elem', function() {
var expected = { entity: { block: 'b1', elem: 'e1' }, tech: '' };

expect(scheme('flat').parse('b1__e1')).eql(expected);
});

it('should parse block with boolean modifier', function() {
var expected = { entity: { block: 'b1', modName: 'm1', modVal: true }, tech: '' };

expect(scheme('flat').parse('b1_m1')).eql(expected);
});

it('should parse block with key-value modifier', function() {
var expected = { entity: { block: 'b1', modName: 'm1', modVal: 'v1' }, tech: '' };

expect(scheme('flat').parse('b1_m1_v1')).eql(expected);
});

it('should parse elem with boolean modifier', function() {
var expected = { entity: { block: 'b1', elem: 'e1', modName: 'm1', modVal: true }, tech: '' };

expect(scheme('flat').parse('b1__e1_m1')).eql(expected);
});

it('should parse elem with key-value modifier', function() {
var expected = { entity: { block: 'b1', elem: 'e1', modName: 'm1', modVal: 'v1' }, tech: '' };

expect(scheme('flat').parse('b1__e1_m1_v1')).eql(expected);
});

it('should parse tech', function() {
var expectedBlock = { entity: { block: 'b1' }, tech: 'spec.js' },
expectedBlockMod = { entity: { block: 'b1', modName: 'm1', modVal: true }, tech: 'spec.js' },
expectedElem = { entity: { block: 'b1', elem: 'e1' }, tech: 'spec.js' },
expectedElemMod = { entity: { block: 'b1', elem: 'e1', modName: 'm1', modVal: 'v1' }, tech: 'spec.js' };

expect(scheme('flat').parse('b1.spec.js')).eql(expectedBlock);
expect(scheme('flat').parse('b1_m1.spec.js')).eql(expectedBlockMod);
expect(scheme('flat').parse('b1__e1.spec.js')).eql(expectedElem);
expect(scheme('flat').parse('b1__e1_m1_v1.spec.js')).eql(expectedElemMod);
});
});
});