bem-sdk-archive / bem-deps Goto Github PK
View Code? Open in Web Editor NEW🎯 Manage BEM dependencies. DEPRECATED →
Home Page: https://github.com/bem/bem-sdk/tree/master/packages/deps
License: Other
🎯 Manage BEM dependencies. DEPRECATED →
Home Page: https://github.com/bem/bem-sdk/tree/master/packages/deps
License: Other
Need to add following infrastructure items in order to start working with tests:
chai
, lodash
.must
index.js
as lib entry point)fake.test.js
file.test
folder to spec
resolve
to spec
folder.{
"shouldDeps": [
{
"block": "block",
"mods": [
"mod-1",
"mod-2"
]
},
{
"block": "block",
"elem": "elem",
"mods": [
"mod-1",
"mod-2"
]
}
]
}
Преобразуется в
[
{
"block": "block"
},
{
"block": "block",
"mod": "0",
"val": true
},
{
"block": "block",
"mod": "1",
"val": true
},
{
"block": "block",
"elem": "elem"
},
{
"block": "block",
"elem": "elem",
"mod": "0",
"val": true
},
{
"block": "block",
"elem": "elem",
"mod": "1",
"val": true
},
{
"block": "block",
"mod": "0",
"val": "mod-1"
},
{
"block": "block",
"mod": "1",
"val": "mod-2"
},
{
"block": "block",
"elem": "elem",
"mod": "0",
"val": "mod-1"
},
{
"block": "block",
"elem": "elem",
"mod": "1",
"val": "mod-2"
}
]
https://github.com/bem-sdk/bem-deps/blob/master/lib/formats/deps.js/reader.js#L24
Can be fixed with swapping lines and adding entity.block ||
to entity.elem || (…)
like that:
dep[depsType].forEach(function (entity) {
entity.block || entity.elem || (entity.elem = file.entity.elem);
entity.block || (entity.block = file.entity.block);
});
Otherwise it adds unwished elem to dependent blocks:
({
block: 'header',
elem: 'logo',
shouldDeps: [{
block: 'logo' // It will require now logo__logo
}]
});
These methods should be implemented in bem-deps
:
https://github.com/gulp-bem/gulp-bem-src/blob/specs/deps.js
It will be cool if you make decomposition of epic issues to some little issues.
For example, I want to contribute to the project but I have not much time for the epic tasks. And if there will be little tasks that easy to understand, I will do some of them.
Section describes special cases when tech dependencies may be ignored.
Move to folder unordered from unordered_dependencies
Remove redundant describe('resolve') from resolve common deps spec
Rename to common from entity-entity
Describes entity - entity
relationship for for dependencies which ordering is not specified.
Need to include following items into this spec:
decl
deps
deps
paramopts
paramTestcase: https://github.com/Yeti-or/bem-deps-bug
bem-deps uses bem-walk inside gather function https://github.com/bem-sdk/bem-deps/blob/master/lib/gather.js
But now there is no way to provide levelsMap to bem-walk.
const walker = walk(config.levels, { defaults: config.options });
This line should look like
const walker = walk(config.levels, { levels: config.options.levels, defaults: config.options });
TypeError: Cannot read property 'block' of undefined
https://github.com/bem-sdk/bem-deps/blob/master/lib/formats/deps.js/parser.js#L33
Error message: mismatchig-tech-deps.spec.js: line 274, col 29, Unexpected use of '~'.
Section describes recommended ordering for dependencies which ordering was not specified.
/Users/grape/Sources/Yandex/islands/node_modules/@bem/deps/lib/formats/deps.js/reader.js:20
dep[depsType] = normalize(dep[depsType]);
^
TypeError: Cannot read property 'mustDeps' of undefined
at /Users/grape/Sources/Yandex/islands/node_modules/@bem/deps/lib/formats/deps.js/reader.js:20:46
at Array.forEach (native)
at /Users/grape/Sources/Yandex/islands/node_modules/@bem/deps/lib/formats/deps.js/reader.js:19:50
at Array.map (native)
at /Users/grape/Sources/Yandex/islands/node_modules/@bem/deps/lib/formats/deps.js/reader.js:18:29
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:380:3)
🙅
Describes entity <- tech
, tech <- entity
and tech <- tech
relationships for unordered dependencies
There are cases when we have a block which have a few optional modifiers. These modifiers can be included to bundle at the same time or separately. And in the case when they are included together the order becomes important.
I'm propose feature like include: false
, but more understandable for community.
Consider the example.
Block filter
is just a button in the common case.
block('filter').content()({ block: 'button' });
It have optional ability to show tooltip on mouseover. Code for this feature locate in the modifier _hoverable_yes
. Template of this modifier adds to content the tooltip.
block('filter').mod('hoverable', 'yes').content()(function() {
return [
applyNext(),
{ block: 'tooltip' }
];
});
Also block have other optional ability to turn into dropdown. Code for this feature locate in the modifier _changable_yes
. Template of this modifier replace content of the main template to dropdown.
block('filter').mod('changable', 'yes').content()({ block: 'dropdown' });
Now, on case when block has both these modifiers order becomes important. We can declare it in the filter_hoverable_yes.deps.js
.
({
shouldDeps: [
{ block: 'tooltip' }
],
optionalMustDeps: [
{ mods: { changable: 'yes' } }
]
});
Guys what do you think about it?
Section overviews direct (A <- B <- A)
, indirect (A <- B <- C <- A)
and intermediate (A <- B <- C <- B)
cases for ordered - ordered
dependency cycles
Describes entity - entity relations between dependencies with specified ordering
Write specs for resolve
method: #2.
Input processing
Resolving unordered dependencies
unordered
entities dependencies — #10unordered
tech dependencies — #12unordered
dependencies recommended ordering — #13Resolving ordered dependencies
ordered
entity dependencies — #14ordered
tech dependencies — #15ordered
dependencies recommended ordering — #16Resolving dependency cycles
unordered - unordered
dependency cycles — #17unordered - ordered
dependency cycles — #18ordered - ordered
dependency cycles — #19Other
Need to fix this if it's not expected.
The resolve
method to supplement the declaration missing entities.
Important: It takes into account the order dependencies of BEM-entities.
resolve(decl, deps) -> decl
Object[] decl
— list of BEM-entities. Each item is object. See, bem-naming.
Object[] deps
— list of dependencies between BEM-entities.
Example:
var deps = require('bem-deps'),
decl = [
{ block: 'A' },
{ block: 'B' }
],
myDeps = [
{
entity: { block: 'A' },
dependOn: [
{
entity: { block: 'B' },
order: 'dependenceBeforeDependants'
},
{
entity: { block: 'C' }
}
]
}
];
var res = deps.resolve(decl, myDeps);
console.log(res);
/*
{
entities: [{ block: 'B' }, { block: 'A' }, { block: 'C' }],
dependOn: []
}
*/
Common
dependencies - dependencies where one entity depends on another entity, without taking in account specific techsResolve common dependencies
- resolve dependencies without specifying any techUnordered
dependencies - dependencies which ordering is not specified explicitly. (i.e. order
param is not set)Ordered
dependencies - dependencies which ordering specified explicitly (i.e. order
param is being set)Each item of deps list is Object
.
Object entity
— BEM-entity that is dependent on other
Object[] dependOn
— list of BEM-entities of which depends on entity
Example:
{
entity: { block: 'A' },
dependOn: [
{ entity: { block: 'B' } },
{ entity: { block: 'C' } }
]
}
This means that the block A
depends on blocks B
and C
.
Constraints can be not only between the BEM-entities but also between technologies.
resolve(decl, deps, { tech: 'css' })
Example:
Tech -> Block
{
entity: { block: 'A' },
tech: 'css',
dependOn: [
{ entity: { block: 'B' } }
]
}
This means that the css
tech of block A
depends on all techs of block B
.
Example:
Tech -> Tech
{
entity: { block: 'A' },
tech: 'js',
dependOn: [
{
entity: { block: 'B' },
tech: 'js'
}
]
}
This means that the js
tech of block A
depends on js
tech of block B
.
For cases when the technology is dependent on other technology in result will be add dependOn
field. Each item of dependOn
is object with tech
and entities
filed.
Example:
var myDeps = {
entity: { block: 'A' },
tech: 'js',
dependOn: [
{
entity: [{ block: 'B' }],
tech: 'bemhtml'
}
]
};
var res = resolve(decl, deps, { tech: 'js' });
console.log(res);
/*
{
entities: [{ block: 'A' }],
dependOn: [
{
tech: bemhtml,
entities: [{ block: 'B' }]
}
]
}
*/
Depending provides information about the order:
dependenceBeforeDependants
— BEM-entity may require that the other BEM-entity will be before it.false
— BEM-entity may expect that the other BEM-entity will be before or after it.Example:
{
entity: { block: 'A' },
tech: 'js',
dependOn: [
{
entity: { block: 'B' },
order: 'dependenceBeforeDependants'
}
]
}
This means that the block A
depends on of block B
and require that B
will be before A
.
Rule 1: Try to keep the order of declaration.
Example:
Declaration: A, B, C
Dependency graph: B <- E (with order: dependenceBeforeDependants
)
Expected result: A, E, B, C
Rule 2: Try to keep the natural order for BEM-entities with same block scope (block and its mods, elems and their mods):
We should report for broken format in deps.js files instead of crashing.
See also bem-site/bem-forum-content-ru#1294
Describes entity <- tech
, tech <- entity
и tech <- tech
relationships for dependencies with specified ordering
описывает приоритет упорядочивания зависимостей
Describes priority between ordering rules (recommended ordering for unordered
deps, BEM natural ordering, ordered
dependencies)
Atm it's possible to pass just one reader/parser to the function.
Would be great to pass a Map with functions that will be executed depends on file.tech
.
This section describes how natural ordering is being applied to unordered
dependencies.
n({block: 'bb', elem: ['a','b']})
[ { block: 'bb' },
{ elem: 'a', block: 'bb' },
{ elem: 'b', block: 'bb' } ]
Describes recommended ordering for dependencies with specified ordering.
Section describes how tech deps will be ordered when dependenceBeforeDependants
ordering is being used.
This package should support other formats and not have the default format.
read
methodparse
methodresolve
methodSection overviews direct (A <- B <- A)
, indirect (A <- B <- C <- A)
and intermediate (A <- B <- C <- B)
cases for unordered - ordered
dependency cycles
Section overviews direct (A <- B <- A)
, indirect (A <- B <- C <- A)
and intermediate (A <- B <- C <- B)
cases for unordered - unordered
dependency cycles.
normalize([{ ?tech, ?mustDeps, ?shouldDeps }]): tenorok[] — normalize internals
fulfill({ ?elem, mod, val }, { block, ?elem }): tenorok — reader internals
And also the current functionality for streams, and for https://nda.ya.ru/3RfcVx
Since node 4.0 have generators support we should try to stop using babel.
See also #55
Fails:
{block: 'i-bem', elem: ['dom'], mods: {init: 'auto'}},
Works:
{block: 'i-bem', elem: 'dom', mods: {init: 'auto'}},
There are cases when several entities depend on other entity.
The dependency should be added only when both entities are in declaration.
Example:
var bemDeps = require('@bem/deps');
var relations = {
entity: { block: 'A' },
onlyWith: [
{ entity: { block: 'B' } }
],
dependOn: [
{ entity: { block: 'C' } }
]
};
bemDeps.resolve([{ block: 'A' }, { block: 'B' }], relations);
// [
// { block: 'A' },
// { block: 'B' },
// { block: 'C' }
// ]
bemDeps.resolve([{ block: 'A' }], relations);
// [
// { block: 'A' }
// ]
Real examples:
{ block: 'checkbox', modName: 'theme', modVal: 'islands'
with { block: 'checkbox', modName: 'type', modVal: 'button' }
depend on { block: 'button', modName: 'theme', modVal: 'islands' }
.
islands
theme of button
should be added only if checkbox
has type_button
modifier with islands
theme.
Code in bem-components
— https://github.com/bem/bem-components/blob/5406834d2f35911574ec49f974c0788c800d7835/design/common.blocks/checkbox/_theme/checkbox_theme_islands.deps.js
{ block: 'dropdown', modName: 'theme', modVal: 'islands'
with { block: 'dropdown', modName: 'switcher', modVal: 'link' }
depend on { block: 'link', modName: 'theme', modVal: 'islands' }
.
islands
theme of link
should be added only if dropdown
has switcher_link
modifier with islands
theme.
Code in bem-components
— https://github.com/bem/bem-components/blob/5406834d2f35911574ec49f974c0788c800d7835/design/common.blocks/dropdown/_theme/dropdown_theme_islands.deps.js
Quotes:
Taken from bem-archive/bem-tools#463.
Это позволяет указывать зависимости между сущностями, но без подключения самих сущностей. Например, блок
B
не зависит от кода блокаA
напрямую, но если вдруг какой-то другой блок будет явно зависеть отA
, то его код (код блокаA
) должен подключаться раньше подключения кодаB
. Для этого в B пишется такая зависимость (с ключомinclude: false
), которая влияет только на порядок, без явного подключения самой сущности.
представьте, что есть блок
input
и у него есть 1) разные темыinput_theme_{dark,light}
и 2) опциональный элементinput__label
в стилях для темы написано переопределение базовых стилей для лейбла, поэтому
input_theme_{dark,light}
должен идти послеinput__label
-- т.е. нуженmustDeps
:input_theme_{dark,light}
mustDeps
input__label
, но если так написать сейчас, то всегда с темой будет подцеплятьсяinput__label
(т.к. у нас понятия "это должно идти перед этим" и "это должно попадать в финальную сборку вместе с этим" не разделены)чтобы можно было указать зависимость по порядку следования в сборке, но при этом не требовать обязательного подключения опционального элемента мы сделали
include: false
--input_theme_{dark,light}
mustDeps
input__label
include: false
-- в этом случае мы запомним факт про зависимость, но не будем подключатьinput__label
до тех пор, пока кто-то его не попросит безinclude: false
Add specs describing lib structure (i.e. input.js
)
I think we should abandon internal format.
API with internal format
const resolve = require('bem-deps').resolve;
const decl = [{ block: 'A' }];
const deps = [
{
entity: { block: 'A' },
dependOn: [
{
entity: { block: 'B' }
}
]
},
{
entity: { block: 'B' },
dependOn: [
{
entity: { block: 'C' },
order: 'dependenceBeforeDependants'
}
]
},
{
entity: { block: 'C' },
tech: 'js',
dependOn: [
{
entity: { block: 'D' },
tech: 'bemhtml'
}
]
}
];
const resolved = resolve(decl, deps);
Graph API
const DependencyGraph = require('bem-deps').DependencyGraph;
const graph = new DependencyGraph();
graph
.node({ block: 'A' })
.addDependency({ block: 'B' });
graph
.node({ block: 'B' })
.addDependency({ block: 'C' }, { ordered: true });
graph
.node({ block: 'C' }, { tech: 'js' })
.addDependency({ block: 'D' }, { tech: 'bemhtml' });
graph.dependenciesOf({ block: 'A' }, { tech: 'js' });
Methods:
graph.node(entity[, { tech: string }])
— gets or adds BEM entity part to graph.
Returns GraphNode
instance.
If tech
is not specified, adds entity part with common (*) tech.
graph.addDependency(dependence[, { tech: string, ordered: boolean }])
— add dependency from node entity part to dependence entity part.
If tech
is not specified, adds dependency to dependence with common (*) tech.
If ordered: true
, adds note that dependence will be added before dependants (old order: dependenceBeforeDependants
).
graph.dependenciesOf(entity[, { tech: string })
— resolve dependencies for specified tech.
Returns { entities: iterator, dependOn: object }
.
If tech
is not specified, dependencies will be resolve for common tech.
graph.entityParts({ tech: string })
— returns all entity parts in graph for specified tech.
Returns iterator with entity parts.
If tech
is not specified, returns entity parts with common tech.
graph.sortedEntityParts({ tech: string })
— like graph.sortedEntityParts()
, but sorted by dependency rules (like graph.dependenciesOf
).
Equivalently graph.dependenciesOf(graph.entityParts())
.
entityParts
and sortedEntityParts
.A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.