Skip to content
This repository
Browse code

Update README.md and README.ru.md

  • Loading branch information...
commit 2ca9f04b5550380724e6b885b643b5493365bc6f 1 parent 3f6a77a
Sergey Belov arikon authored
1,252 README.md
Source Rendered
... ... @@ -1,1240 +1,22 @@
1   -# BEM Tools [![Build Status](https://secure.travis-ci.org/bem/bem-tools.png?branch=nodejs)](http://travis-ci.org/bem/bem-tools)
2   -Toolkit to work with files based on [BEM methodology](http://bem.github.com/bem-method/pages/beginning/beginning.en.html).
  1 +# BEM Tools
  2 +[![Build Status](https://secure.travis-ci.org/bem/bem-tools.png?branch=master)](http://travis-ci.org/bem/bem-tools)
3 3
4   -## Installation
5   -You need [NodeJS 0.6+](http://nodejs.org/) or later and [npm 1.x](http://npmjs.org/).
6   -After this it suffices `npm -g install bem`.
  4 +BEM tools is a toolkit to work with files based on [BEM methodology](http://bem.info/method/).
7 5
8   - * Install [nodejs](http://nodejs.org)
  6 +It allows you:
9 7
10   - https://github.com/joyent/node/wiki/Installation
  8 +* creating entities;
  9 +* building final runtime;
  10 +* working with build declarations: merge, subtract and intersect them;
  11 +* building the whole project using bem make command;
  12 +* launching development server on the projects source tree using bem server command.
11 13
12   - * Install [npm](http://npmjs.org)
  14 +See also:
13 15
14   - curl http://npmjs.org/install.sh | sudo sh
15   -
16   - * After installation configure `NODE_PATH`:
17   -
18   - echo 'export NODE_PATH="'$(npm root -g)'"'>> ~/.bashrc && . ~/.bashrc
19   -
20   - or
21   -
22   - echo 'export NODE_PATH="'$(npm root -g)'"'>> ~/.zshrc && . ~/.zshrc
23   -
24   - * Install [bem-tools](https://github.com/bem/bem-tools)
25   -
26   - sudo npm -g install bem
27   -
28   - * Use this command [bem-tools](https://github.com/bem/bem-tools) to install the development version
29   -
30   - sudo npm -g install bem@unstable
31   -
32   -### bem-bl
33   -
34   -If you are going to use `bem` with
35   -[bem-bl](https://github.com/bem/bem-bl) block library, you should also install
36   -[XJST](https://github.com/veged/xjst) and [OmetaJS](https://github.com/veged/ometa-js).
37   -
38   - sudo npm -g install xjst ometajs
39   -
40   -## Usage
41   -Get the list of commands with `bem --help`.
42   -To read about commands and subcommands use `bem COMMAND --help` or `bem COMMAND SUBCOMMAND --help`.
43   -
44   -### Shell completion
45   -
46   -#### bash
47   -
48   -To make completions for bem-tools available in your bash, run following
49   -command (ensure that you have bash-completion installed, first). Run this
50   -
51   - bem completion > /path/to/etc/bash_completion.d/bem
52   -
53   -and restart bash.
54   -
55   -If you aren't using `bash-completion`, you can add `bem completion` to your `.bashrc` and reload:
56   -
57   - bem completion >> ~/.bashrc
58   - source ~/.bashrc
59   -
60   -#### zsh
61   -
62   -If you use `zsh`, you can add `bem completion` to your `.zshrc` and reload:
63   -
64   - bem completion >> ~/.zshrc
65   - source ~/.zshrc
66   -
67   -### Commands
68   -#### bem create
69   -
70   -You can create following entities using `bem create`:
71   -
72   - * levels of defenition
73   - * blocks
74   - * elements
75   - * modifiers
76   -
77   -##### Level of defenition
78   -
79   -Level of defenition is a directory that holds blocks and an utility directiry `.bem`.
80   -
81   -A `.bem` directory holds configuration of a current level:
82   -
83   - * naming convention
84   - * links to the technologies
85   -
86   -An example of technologies' links (this is `blocks-desktop` level of
87   -`bem-bl` block library):
88   -
89   - https://github.com/bem/bem-bl/blob/master/blocks-common/.bem/level.js
90   -
91   -###### Create new level of defenition named `blocks` under current directory:
92   -
93   - bem create level blocks
94   -
95   -###### Create a level for pages
96   -
97   -In `bem-tools` terms pages are blocks as well and a directory which holds pages is a level of
98   -defenition itself. To create such a directory run this:
99   -
100   - bem create level pages
101   -
102   -###### Create a level based on an existing one
103   -
104   -`bem create level` allows to use an existing level as a prototype for a level it creates.
105   -
106   - bem create level --level bem-bl/blocks-desktop blocks
107   -
108   -##### Block
109   -
110   -Block is a bunch of files in different technologies that hold block's implementation.
111   -
112   -###### Create a new block
113   -
114   - bem create block b-my-block
115   -
116   -By default, a block has several techs: (`bemhtml`, `css`, `js`).
117   -
118   -###### Create a new block using concrete tech
119   -
120   -Flags -t (-T) are to create files of technologies you need:
121   -
122   - bem create block -t deps.js b-my-block
123   - // Creates a block implementation in deps.js technology, ecxept of default techs.
124   -
125   - bem create block -T css b-my-block
126   - // Creates only CSS technology for a block
127   -
128   - bem create block -T bem-bl/blocks-desktop/i-bem/bem/techs/bemhtml.js b-my-block
129   - // -T flag is useful when you need to add a new tech to the block existed
130   -
131   -The value of this flag may be either tech's name (e.g `css`) or a path to tech module.
132   -
133   -Tech names may be listed in `.bem/level.js` file of a level.
134   -E.g., https://github.com/bem/bem-bl/blob/master/blocks-common/.bem/level.js
135   -
136   -You can find the examples of tech modules in the repo:
137   -
138   - https://github.com/bem/bem-tools/tree/master/lib/techs
139   -
140   -###### Create element
141   -
142   -Create element named `elem` for block `b-my-block`
143   -
144   - bem create elem -b b-my-block elem
145   -
146   -###### Create modifier of block or element
147   -
148   -Create modifier named `mod` for block `b-my-block`
149   -
150   - bem create mod -b b-my-block mod
151   -
152   -Create modifier named `mod` having value `val` for block `b-my-block`
153   -
154   - bem create mod -b b-my-block mod -v val
155   -
156   -Create modifier named `mod` for element `elem` of block `b-my-block`
157   -
158   - bem create mod -b b-my-block -e elem mod
159   -
160   -Create modifier named `mod` having value `val` for element `elem` of block `b-my-block`
161   -
162   - bem create mod -b b-my-block -e elem mod -v val
163   -
164   -###### Create any BEM entity using `bem create` command only
165   -
166   -You can create any BEM entities or bunches of them using `bem create` command.
167   -
168   -Create blocks named `b-block1` and `b-block2`
169   -
170   - bem create -b b-block1 -b b-block2
171   -
172   -Create elements named `elem1` and `elem2` for block `b-block`
173   -
174   - bem create -b b-block -e elem1 -e elem2
175   -
176   -Create modifier names `mod` of block `b-block`
177   -
178   - bem create -b b-block -m mod
179   -
180   -Create modifier named `mod` of block `b-block` having values `val1` and `val2`
181   -
182   - bem create -b b-block -m mod -v val1 -v val2
183   -
184   -Create modifier named `mod` for element `elem` of block `b-block`
185   -
186   - bem create -b b-block -e elem -m mod
187   -
188   -Create modifier named `mod` having values `val1` and `val2` for element `elem` of block `b-block`
189   -
190   - bem create -b b-block -e elem -m mod -v val1 -v val2
191   -
192   -#### bem build
193   -
194   -`bem build` command builds page files in different techs, according to a page declaration.
195   -
196   -##### Create bemdecl.js file from page's bemjson
197   -
198   - bem build \
199   - -l bem-bl/blocks-common -l bem-bl/blocks-desktop \
200   - -l blocks -l pages/index/blocks \
201   - -d pages/index/index.bemjson.js -t bemdecl.js \
202   - -o pages/index -n index
203   -
204   -You can use either tech's name or a path to its module as a value of -t flag. This
205   -module says how to build a final file from a declaration.
206   -
207   -E.g., this is a module for `deps.js`: https://github.com/bem/bem-tools/blob/master/lib/techs/deps.js.js
208   -
209   -##### Create deps.js file from bemdecl.js
210   -
211   - bem build \
212   - -l bem-bl/blocks-common -l bem-bl/blocks-desktop \
213   - -l blocks -l pages/index/blocks \
214   - -d pages/index/index.bemdecl.js -t deps.js \
215   - -o pages/index -n index
216   -
217   -###### Create js and css files for a page from deps.js
218   -
219   - bem build \
220   - -l bem-bl/blocks-common -l bem-bl/blocks-desktop \
221   - -l blocks -l pages/index/blocks \
222   - -d pages/index/index.deps.js -t css \
223   - -o pages/index -n index
224   -
225   - bem build \
226   - -l bem-bl/blocks-common -l bem-bl/blocks-desktop \
227   - -l blocks -l pages/index/blocks \
228   - -d pages/index/index.deps.js -t js \
229   - -o pages/index -n index
230   -
231   -###### Create bemhtml.js template for a page from deps.js
232   -
233   - bem build \
234   - -l bem-bl/blocks-common -l bem-bl/blocks-desktop \
235   - -l blocks -l pages/index/blocks \
236   - -d pages/index/index.bemhtml.js \
237   - -t bem-bl/blocks-desktop/i-bem/bem/techs/bemhtml.js \
238   - -o pages/index -n index
239   -
240   -There is an example how pages are built using `bem build` in our test project that uses
241   -`bem-bl` block library: https://github.com/toivonen/bem-bl-test/blob/master/GNUmakefile
242   -
243   -#### bem decl
244   -
245   -`bem decl` is to work with declaration files. Thus,
246   -
247   - * to merge two or more decls into one
248   - * «subtract» decls
249   -
250   -All subcommands of `bem decl` can take either bemdecl.js or deps.js as input declaration formats.
251   -as input declaration (via `-d` flag).
252   -
253   -Ouput data (`-o` flag) is always in `deps.js` format.
254   -
255   -##### bem decl merge
256   -
257   -`bem decl merge` is to merge two or more decls into one. It is useful if you need, for example, to build
258   -one file for several pages.
259   -
260   -###### Create a decl for all the pages
261   -
262   - bem decl merge \
263   - -d pages/index/index.deps.js \
264   - -d pages/about/about.deps.js \
265   - -d pages/search/search.deps.js \
266   - -o pages/common/common.deps.js
267   -
268   -##### bem decl subtract
269   -
270   -`bem decl subtract` is to «subtract» all next decls from the first one.
271   -You may use it to create a bundle that you request by application.
272   -
273   -###### Create a decl for a "heavy" block requested by application
274   -
275   - bem decl subtract \
276   - -d bundles/heavy-block/heavy-block.deps.js \
277   - -d pages/common/common.deps.js \
278   - -o bundles/heavy-block/heavy-block.bundle.js
279   -
280   -##### bem make
281   -`make` command implements the build process of the BEM projects. You don't have to write your own scripts or makefiles (for GNU make or other build system) to build your BEM project.
282   -
283   -During the build `bem make`
284   -
285   - * fetches the block libraries
286   - * builds the levels content
287   - * builds the bundles
288   - * generates the templates (`bemhtml`)
289   - * generates `html` from `bemjson.js`
290   - * generates the static content files (`js`, `css`)
291   - * expands the `@import` derectives in `css` files (`borschik`)
292   - * expands the `borschik:link:include` directives in `js` files (`borschik`)
293   - * optimizes `css` files using `csso`
294   - * optimizes `js` files using `uglifyjs`
295   -
296   -##### bem server
297   -
298   -`bem server` command runs a development server. It makes the project files being accessible via the http protocol.
299   -This includes the files which are generated during the build process. So the server can be useful when you develop the
300   -static pages using the bem method. You just edit the files, refresh the browser and get updated page. All the files
301   -which are affected by your changes will be rebuilt automatically.
302   -In the case your project has no static pages you can configure your backend server and production environment to retrieve
303   -the stylesheets and scripts from the bem server. bem server accepts connections via normal TCP socket and via UNIX domain socket.
304   -
305   -By default the current directory is considered as the project root. You can change it using the --project (-r) option.
306   -
307   -Default TCP port is 8080. You can change it using the --port (-p) option.
308   -
309   -When requested URL is mapped to a directory, the server will check if there is an index.html file or it's possible to build it.
310   -In the case one of these is true the content of the file will be returned to browser. The directory content listing will be returned
311   -otherwise.
312   -
313   -#### Build configuration
314   -
315   -There is a default build behavior programmed in the build system. The configuration files allow to adjust it a little or change it completely.
316   -To make `bem make` work you should have `.bem/level.js` file within your levels. It should contain the `getTechs()` function,
317   -which returns object with the tech definitions used on the level.
318   -And it should have function `getConfig()`:
319   -
320   -```js
321   -var extend = require('bem/lib/util').extend;
322   -
323   -exports.getTechs = function() {
324   - return {
325   - 'bemjson.js': '',
326   - 'js': 'js-i',
327   - 'bemhtml': '../../bem-bl/blocks-common/i-bem/bem/techs/bemhtml.js',
328   - 'priv.js': '../../.bem/techs/priv.js',
329   - 'html': '../../bem-bl/blocks-common/i-bem/bem/techs/html'
330   - };
331   -};
332   -
333   -exports.getConfig = function() {
334   -
335   - return extend({}, this.__base() || {}, {
336   -
337   - bundleBuildLevels: this.resolvePaths([
338   - '../../bem-bl/blocks-common',
339   - '../../bem-bl/blocks-desktop',
340   - '../../blocks'
341   - ])
342   -
343   - });
344   -
345   -};
346   -```
347   -
348   -`getTechs()` returns an object with used techs. Object properties (for example `'bemjson.js'`, `'js'`, `'bemhtml'`) define the
349   -tech names, object values specify the paths to the appropriate tech files (`''`, `'js-i'`, `'../../bem-bl/blocks-common/i-bem/bem/techs/bemhtml.js'`).
350   -A path can be relative or absolute, it can be empty, or it can specify just a file name. When the latter case is used the
351   -tech will be considered being standard (bundled with bem-tools) and the file will be looked up in the `[bem]/lib/techs` folder.
352   -
353   -`getConfig()` function returns an object with the `bundleBuildLevels` property, containing the array of the used block levels.
354   -
355   -Another (optional) configuration file is `.bem/make.js` located in the project root. Core of the build system is a graph
356   -of nodes, each of which executes own part of the whole build process. `make.js` allows you to adjust nodes behavior and change build graph.
357   -There are several standard node types:
358   - * `Node` - base node, implements basic functionality. All other nodes are inherited from this one
359   - * `LibraryNode` - retrieves external libraries
360   - * `LevelNode` - inspects the contents of a level and constructs graph branch accordingly to build the level
361   - * `BundlesLevelNode` - inherits from `LevelNode` and builds the bundles levels
362   - * `BundleNode` - constructs graph branch for a bundle
363   - * `MergedBundleNode` - builds merged bundle (aka common bundle)
364   - * `BorschikNode` - processes files with the `borschik` utility, `csso` and `uglifyjs`
365   - * `Arch` - builds initial graph, which by default consists of `LibraryNode`, `BundlesLevelNode` and `LevelNode` nodes
366   -
367   -To alter build system behavior for your project you need to alter behavior of the nodes. This can be achieved by adding `MAKE.decl()` calls in the `.bem/make` file. `MAKE.decl()` is a helper
368   -function which accepts two arguments. First one is the node name which we want to change, second - an object with overriding methods.
369   -
370   -```js
371   -MAKE.decl('BundleNode', {
372   -
373   -});
374   -```
375   -
376   -Node classes have some fundamental methods, which take care about the build process:
377   - * `isValid()` - validates the node - indicates is there a need to rebuild it or not. If node artifacts were built during
378   - previous build and dependency nodes were not rebuilt after that, the node is considered being valid. In other words
379   - if you changed a file after first build then only the nodes which depend on this file will be rebuilt during the
380   - consequent build.
381   - * `make()` - implements the build logic for the node.
382   - * `run()` - node entry point. In the default implementation it executes isValid method and in case it returns false the make method will be executed next.
383   - * `clean()` - removes the build artifacts for the node.
384   -
385   -##### Sample configuration files for some typical tasks
386   -
387   -###### Build of static html, css, js, bemhtml templates on the level `pages`. Bemjson file is used as a source file. Also using blocks level `blocks`, and also `blocks-common` and `blocks-desktop` from bem-bl.
388   -
389   -`pages/.bem/level.js`
390   -```js
391   -var extend = require('bem/lib/util').extend;
392   -
393   -exports.getTechs = function() {
394   -
395   - return {
396   - 'bemjson.js': '',
397   - 'bemdecl.js': 'bemdecl.js',
398   - 'deps.js': 'deps.js',
399   - 'js': 'js-i',
400   - 'css': 'css',
401   - 'bemhtml': '../../bem-bl/blocks-common/i-bem/bem/techs/bemhtml.js',
402   - 'html': '../../bem-bl/blocks-common/i-bem/bem/techs/html.js'
403   - };
404   -
405   -};
406   -
407   -exports.getConfig = function() {
408   -
409   - return extend({}, this.__base() || {}, {
410   -
411   - bundleBuildLevels: this.resolvePaths([
412   - '../../bem-bl/blocks-common',
413   - '../../bem-bl/blocks-desktop',
414   - '../../blocks'
415   - ])
416   -
417   - });
418   -
419   -};
420   -```
421   -
422   -`.bem/make.js`
423   -```js
424   -MAKE.decl('Arch', {
425   -
426   - getLibraries: function() {
427   -
428   - return {
429   - 'bem-bl': {
430   - type: 'git',
431   - url: 'git://github.com/bem/bem-bl.git'
432   - }
433   - };
434   -
435   - }
436   -
437   -});
438   -
439   -MAKE.decl('BundleNode', {
440   -
441   - getTechs: function() {
442   -
443   - return [
444   - 'bemjson.js',
445   - 'bemdecl.js',
446   - 'deps.js',
447   - 'bemhtml',
448   - 'css',
449   - 'js',
450   - 'html'
451   - ];
452   - }
453   -
454   -});
455   -```
456   -
457   -
458   -###### Build of css, js, bemhtml tamples on the level `pages`. `bemdecl` declaration file is used as a source file. Also using blocks level `blocks`, and also `blocks-common` and `blocks-desktop` from bem-bl.
459   -
460   -`pages/.bem/level.js`
461   -```js
462   -var extend = require('bem/lib/util').extend;
463   -
464   -exports.getTechs = function() {
465   -
466   - return {
467   - 'bemdecl.js': 'bemdecl.js',
468   - 'deps.js': 'deps.js',
469   - 'js': 'js-i',
470   - 'css': 'css',
471   - 'bemhtml': '../../bem-bl/blocks-common/i-bem/bem/techs/bemhtml.js'
472   - };
473   -
474   -};
475   -
476   -exports.getConfig = function() {
477   -
478   - return extend({}, this.__base() || {}, {
479   -
480   - bundleBuildLevels: this.resolvePaths([
481   - '../../bem-bl/blocks-common',
482   - '../../bem-bl/blocks-desktop',
483   - '../../blocks'
484   - ])
485   -
486   - });
487   -
488   -};
489   -```
490   -
491   -`.bem/make.js`
492   -```js
493   -MAKE.decl('Arch', {
494   -
495   - getLibraries: function() {
496   -
497   - return {
498   - 'bem-bl': {
499   - type: 'git',
500   - url: 'git://github.com/bem/bem-bl.git'
501   - }
502   - };
503   -
504   - }
505   -
506   -});
507   -
508   -MAKE.decl('BundleNode', {
509   -
510   - getTechs: function() {
511   -
512   - return [
513   - 'bemdecl.js',
514   - 'deps.js',
515   - 'bemhtml',
516   - 'css',
517   - 'js'
518   - ];
519   - }
520   -
521   -});
522   -```
523   -
524   -###### The block libraries
525   -
526   -The block libraries are not used by default. To use a library add the following code to `.bem/make.js`:
527   -
528   -```js
529   -MAKE.decl('Arch', {
530   - getLibraries: function() {
531   -
532   - return {
533   - 'bem-bl': {
534   - type: 'git',
535   - url: 'git://github.com/bem/bem-bl.git'
536   - }
537   - };
538   - }
539   -});
540   -```
541   -
542   -
543   -Where:
544   - * `'Arch'` - node class name which we want to override. Arch builds initial build graph.
545   - * `getLibraries` - a method of the Arch class, which returns the associative array of the used block libraries.
546   - * `'bem-bl'` — the name of the library and the folder where it will be copied to.
547   - * `type` - the type of the library source. We use git in the example, so the library will be checked out of a git repository.
548   - Possible values are: `'git'`, `'svn'`, `'symlink'`. `svn` works the same as `git`, but with svn repositories. `symlink` -
549   - creates a symbolic link in the project folder to the library folder. The library path is specified by the `relative` property.
550   - * `url` - URL to the svn/git repository
551   -
552   -Also you can use shorter code:
553   -
554   -```js
555   -MAKE.decl('Arch', {
556   - libraries: {
557   - 'bem-bl': {
558   - type: 'git',
559   - url: 'git://github.com/bem/bem-bl.git'
560   - }
561   - }
562   -});
563   -```
564   -
565   -###### Block levels
566   -
567   -The folders in the project root matching the `blocks*` mask are considered being the blocks level. You can change this using the following code:
568   -
569   -```js
570   -MAKE.decl('Arch', {
571   - blocksLevelsRegexp: /regular expression/,
572   -});
573   -```
574   -
575   -The regular expression will be used to match the folders in the project root. A folder which does match will be used as the blocks level.
576   -
577   -If you need some logic for the levels selection you can achieve that by overriding the `createBlocksLevelsNodes()` method:
578   -
579   -```js
580   -MAKE.decl('Arch', {
581   - createBlocksLevelsNodes: function(parent, children) {
582   - // Create the LevelNode instance
583   - var node1 = new LevelNode(...);
584   - // Add it into the graph
585   - this.arch.setNode(node1, parent, children);
586   -
587   - var node2 = new LevelNode(...);
588   - this.arch.setNode(node2, parent, children);
589   -
590   - // return an array with the Ids of the created nodes
591   - return [node1.getId(), node2.getId()];
592   - }
593   -});
594   -```
595   -
596   -###### The bundles and the pages
597   -
598   -The folders in the project root matching the `pages*` abd `bundles*` masks are considered being bundle level. You can change this using the following code:
599   -
600   -```js
601   -MAKE.decl('Arch', {
602   - bundlesLevelsRegexp: /regular expression/,
603   -});
604   -```
605   -
606   -And for more precise control:
607   -
608   -```js
609   -MAKE.decl('Arch', {
610   -
611   - getBundlesLevels: function() {
612   - return [
613   - 'pages-desktop',
614   - 'pages-touch',
615   - 'bundles/common'
616   - ];
617   - }
618   -
619   -});
620   -```
621   -
622   -
623   -For every bundle the following target files are built by default:
624   -
625   - * `.bemhtml.js`
626   - * `.html`
627   - * `.css`
628   - * `.ie.css`
629   - * `.js`
630   - * `_*.css`
631   - * `_*.ie.css`
632   - * `_*.js`
633   -
634   -and the intermediate:
635   -
636   - * `.bemdecl.js`
637   - * `.deps.js`
638   - * `.deps.js.deps.js`
639   - * `.bemhtml.js.meta.js`
640   - * `.js.meta.js`
641   - * `.css.meta.js`
642   - * `.ie.css.meta.js`
643   -
644   -`.bemjson.js` file is considered as a source file. If it does not exist, `.bemdecl.js` is used then. If `.bemdecl.js`
645   - does not exist too, `.deps.js` will be used. For the cases when `.bemjson.js` does not exist static html will not be built.
646   -
647   -To change the list of the file techs to use, add the following code into `.bem/make.js`:
648   -
649   -```js
650   -MAKE.decl('BundleNode', {
651   -
652   - getTechs: function() {
653   - return [
654   - 'bemdecl.js',
655   - 'deps.js',
656   - 'bemhtml',
657   - 'css',
658   - 'js',
659   - 'priv.js'
660   - ];
661   - }
662   -});
663   -```
664   -
665   -**IMPORTANT:** Techs in the list should be in the order of dependency on each other. Tech B, which depends on A, should go **bellow** A. The source file tech should also be in the list, for example `bemjson.js`.
666   -
667   -###### The merged bundles
668   -The merged bundle — a bundle which includes the declarations of all bundles on the level. So for example css in a merged bundle will contain the styles from all of the bundles.
669   -
670   -The following code will enable the build of the merged bundles for all levels:
671   -
672   -```js
673   -MAKE.decl('BundlesLevelNode', {
674   - buildMergedBundle: function() {
675   - return true;
676   - }
677   -});
678   -```
679   -
680   -If you need a merged bundle for the selected levels only (for `pages-desktop` level in the example):
681   -
682   -```js
683   -var PATH = require('path');
684   -
685   -MAKE.decl('BundlesLevelNode', {
686   - buildMergedBundle: function() {
687   - if (this.getLevelPath() === 'pages-desktop') return true;
688   -
689   - return false;
690   - }
691   -});
692   -```
693   -
694   -The `getLevelPath()` method returns the relative path for the level. We can use it to decide should we enable some special logic for current level or not.
695   -
696   -To change the merged bundle name use the code:
697   -```js
698   -MAKE.decl('BundlesLevelNode', {
699   -
700   - mergedBundleName: function() {
701   - return 'mymergedbundle';
702   - }
703   -
704   -});
705   -```
706   -
707   -##### Production and Development builds
708   -By changing the `YENV` environment variable value, you can switch between the production and development builds.
709   -In production mode static files are processed with the `borschik` utility. It expands the include directives and puts the
710   -result content in the file with the `_` prefix. For example, `index.css` has the directives to include `blocks/block1.css`
711   -and `blocks/block2.css`. `_index.css` will be created with the content of both `block1.css` and `block2.css`. Also the
712   -`css` files are optimized with the `csso` utility, the `js` files are optimized with `uglifyjs`. In development mode
713   -`borschik` is used only, no optimizations take the place.
714   -
715   -The default mode is development. To use the production mode set `YENV` to `production`.
716   -
717   -Environment variables can be set in `.bem/make.js`, for example
718   -
719   -```js
720   -process.env.YENV = 'production';
721   -```
722   -
723   -### Configuration files
724   -#### Level (.bem/level.js)
725   -
726   -A level should have `.bem/level.js` configuration file which contains the meta information about the level:
727   -
728   -- the mapping rules between the BEM entities and the file system
729   -- the thech modules defined on the level
730   -- the meta information for the build system
731   -
732   -When the `bem create level` command is used to create a level the empty `.bem/level.js` file will be also created.
733   -Which means that this level is «standard» one. The logic for standard level is defined in the `Level` class within
734   -[lib/level.js](https://github.com/bem/bem-tools/blob/master/lib/level.js).
735   -
736   -As the `.bem/level.js` file is a CommonJS module it's easy to override the level's behavior. `bem-tools` creates a new
737   -class inherited from the standard `Level` class using export of this module as a class extention (under the hood the
738   -[inherit](https://github.com/dfilatov/node-inherit) module is used).
739   -
740   -In the example bellow the `getTechs()` method is overriden.
741   -
742   -```js
743   -exports.getTechs = function() {
744   -
745   - return {
746   - 'bemjson.js': ''
747   - 'css': 'path/to/my/css-tech-module.js'
748   - }
749   -
750   -};
751   -```
752   -
753   -##### The levels inheritance
754   -
755   -To avoid the copy and paste of the same code among several levels you can put the common parts into the independant
756   -modules and inherit them. This way you can build up the levels hierarchy.
757   -
758   -To specify the base level you should export it in the `baseLevelPath` property. For example
759   -
760   -```js
761   -exports.baseLevelPath = require.resolve('path/to/base/level.js');
762   -```
763   -
764   -It's also possible to create the inherited levels using the command
765   -
766   - bem create level <your-level-name> --level path/to/base/level.js
767   -
768   -##### The mapping rules between BEM entities and the file system
769   -
770   -By default the following mapping scheme is used (this example is about the `css` tech):
771   -
772   -```
773   -level/
774   - block/
775   - __elem/
776   - _mod/
777   - block__elem_mod_val.css
778   - block__elem.css
779   - _mod/
780   - block_mod_val.css
781   - block.css
782   -```
783   -
784   -If you want to use a custom scheme override the appropriate `match*()` and `get*()` methods in the `.bem/level.js` file.
785   -
786   -##### Tech modules defined on the level
787   -
788   -To define a list of the tech modules used on the level export the `getTechs()` function. It should return an object
789   -the keys of which contain the tech names and the values contain on of the following:
790   -
791   -- the absolute tech path;
792   -- a short tech name — a tech module with such name bundled with `bem-tools` will be used;
793   -- an empty string — the default tech implementation will be used.
794   -
795   -By deault there is no any techs defined explicitly on a level. In the case some techs are used within such a level
796   -by a short name (for example `css`, `js`, etc) then the appropriate tech modules bundled with `bem-tools` are loaded.
797   -If such do exist of course. The full list of such techs can be found there [lib/techs](https://github.com/bem/bem-tools/tree/master/lib/techs).
798   -
799   -If you try to use a tech which was not defined explicitly and which is not bundled with `bem-tools` - the default tech
800   -will be used (see [lib/tech.js](https://github.com/bem/bem-tools/blob/master/lib/tech.js)).
801   -
802   -The techs defined on the level are used:
803   -
804   -- by the `bem create` command
805   -- by the `bem build` command
806   -- by the file system introspection (see the `getLevelByIntrospection()` of the `Level` class)
807   -- during the project build with the `bem make` and `bem build` commands
808   -
809   -It's recommended to define explicitly the used techs.
810   -
811   -##### The build system meta information
812   -
813   -To let the build system know which levels should be used to build one bundle or another set the `bundleBuildLevels`
814   -property within an object returned by the `getConfig()` function to an array of these levels.
815   -
816   -```js
817   -exports.getConfig = function() {
818   -
819   - return extend({}, this.__base() || {}, {
820   -
821   - bundleBuildLevels: this.resolvePaths([
822   - // your levels here
823   - ])
824   -
825   - });
826   -
827   -};
828   -```
829   -
830   -### Tech modules
831   -
832   -#### API
833   -
834   -Look for the documentation in the source code [lib/tech.js](https://github.com/bem/bem-tools/blob/master/lib/tech.js).
835   -
836   -#### Creating tech module
837   -
838   -There are many ways to write a tech module.
839   -
840   -Whatever manner you choose you can refer to the tech object from methods using `this`.
841   -Any base method is available using `this.__base(...)` call. Tech class can be referenced
842   -using `this.__class`. Thanks to [inherit](https://github.com/dfilatov/node-inherit) module
843   -that helps us to organize inheritance here.
844   -
845   -##### Trivial way
846   -
847   -You only need to declare regular CommonJS module and export some of its
848   -functions to redefine them. By default your tech will derive from base `Tech` class
849   -defined in module [lib/tech.js](https://github.com/bem/bem-tools/blob/master/lib/tech.js).
850   -
851   -```js
852   -exports.getCreateResult = function(...) {
853   - // your code goes here
854   -};
855   -```
856   -
857   -You can also group all methods in `techMixin` object. This is a recommended way.
858   -
859   -```js
860   -exports.techMixin = {
861   -
862   - getCreateResult: function(...) {
863   - // your code goes here
864   - }
865   -
866   -};
867   -```
868   -
869   -##### Simple way
870   -
871   -Besides function, you can also export `baseTechPath` variable to define an
872   -absolute path to a tech module you are extending. Or you can
873   -
874   -```js
875   -var BEM = require('bem');
876   -
877   -exports.baseTechPath = BEM.require.resolve('./techs/css');
878   -```
879   -
880   -You can also derive from tech module by its name using `baseTechName` variable.
881   -Base class will be chosen in the context of level where tech module will be used.
882   -
883   -```js
884   -exports.baseTechName = 'css';
885   -```
886   -
887   -In this example new tech will derive from `css` tech declared on level in file
888   -`.bem/level.js`.
889   -
890   -##### Hardcore way
891   -
892   -If you need a total control, you can create a module that exports
893   -the whole `Tech` class.
894   -
895   -```js
896   -var INHERIT = require('inherit'),
897   - BaseTech = require('bem/lib/tech').Tech;
898   -
899   -exports.Tech = INHERIT(BaseTech, {
900   -
901   - create: function(prefix, vars, force) {
902   - // do some creation work
903   - },
904   -
905   - build: function(prefixes, outputDir, outputName) {
906   - // organize own build process
907   - }
908   -
909   -});
910   -```
911   -
912   -If you need to base your tech on an existing one written in a simple way use
913   -`getTechClass()` function to get its class. We recommend to use `getTechClass()`
914   -function all the time to not depend on tech implementation.
915   -
916   -```js
917   -var INHERIT = require('inherit'),
918   - BEM = require('bem'),
919   - BaseTech = BEM.getTechClass(require.resolve('path/to/tech/module'));
920   -
921   -exports.Tech = INHERIT(BaseTech, {
922   -
923   - // your overrides go here
924   -
925   -});
926   -```
927   -
928   -##### Examples of tech modules
929   -
930   - * [bem-tools/lib/techs/](https://github.com/bem/bem-tools/tree/nodejs/lib/techs)
931   - * [bem-bl/blocks-common/i-bem/bem/techs/](https://github.com/bem/bem-bl/tree/master/blocks-common/i-bem/bem/techs)
932   -
933   -### API usage
934   -
935   -Starting from 0.2.0 version it is possible to use `bem-tools` from API.
936   -
937   -`bem` module exports the object of a command that has an `api` property.
938   -It is to use in this way:
939   -
940   -```js
941   -var Q = require('q'),
942   - BEM = require('bem').api,
943   -
944   - techs = ['css', 'js'],
945   - blocks = ['b-block1', 'b-block2'];
946   -
947   -Q.when(BEM.create.block({ forceTech: techs }, { names: blocks }), function() {
948   - console.log('Create blocks: %s', blocks.join(', '));
949   -});
950   -```
951   -
952   -The example above shows that you can use all the commands (including subcommands).
953   -
954   -A command accepts two args:
955   -
956   - * **Object** `opts` command options
957   - * **Object** `args` command arguments
958   -
959   -It returns an object of `Q.promise` type.
960   -
961   -#### BEM.create
962   -
963   -Commands to create BEM entities.
964   -
965   -##### BEM.create.level()
966   -
967   -Creates a level of defenition.
968   -
969   -###### Options
970   -
971   - * **String** `outputDir` a directory of output (current directory by default)
972   - * **String** `level` a «prototype» of the level
973   - * **Boolean** `force` key to force level's creating if it already exists
974   -
975   -###### Arguments
976   -
977   - * **Array** `names` Namef of levels you are creating
978   -
979   -###### Example
980   -
981   -```js
982   -var PATH = require('path'),
983   - Q = require('q'),
984   - BEM = require('bem').api,
985   -
986   - outputDir = PATH.join(__dirname, 'levels'),
987   - levels = ['blocks-common', 'blocks-desktop'];
988   -
989   -Q.when(BEM.create.level({ outputDir: outputDir }, { names: levels }), function() {
990   - console.log('Create levels %s at %s', levels.join(', '), outputDir);
991   -});
992   -```
993   -
994   -##### BEM.create()
995   -
996   -Creates BEM entities: blocks, elems, modifiers and their values.
997   -
998   -###### Options
999   -
1000   - * **String** `level` Level directory (current directory by default)
1001   - * **Array** `block` Block name (required)
1002   - * **Array** `elem` Element name
1003   - * **Array** `mod` Modifier name
1004   - * **Array** `val` Modifier value
1005   - * **Array** `addTech` Add the techs listed
1006   - * **Array** `forceTech` Use only the techs listed
1007   - * **Array** `noTech` Exclude the techs listed
1008   - * **Boolean** `force` Force creating BEM entities files (rewrite)
1009   -
1010   -###### Example
1011   -
1012   -```js
1013   -var Q = require('q'),
1014   - BEM = require('bem').api,
1015   -
1016   - forceTechs = ['css'],
1017   - block = 'b-header',
1018   - elem = 'logo',
1019   - mods = ['lang'],
1020   - vals = ['ru', 'en'];
1021   -
1022   -Q.when(BEM.create({ forceTechs: forceTechs, block: block, mod: mods, val: vals }), function() {
1023   - console.log('Create mod %s of block %s with vals %s', mods.join(', '), block, vals.join(', '));
1024   -});
1025   -
1026   -Q.when(BEM.create({ forceTechs: forceTechs, block: block, elem: elem, mod: mods, val: vals }), function() {
1027   - console.log('Create mod %s of elem %s of block %s with vals %s', mods.join(', '), elem, block, vals.join(', '));
1028   -});
1029   -```
1030   -
1031   -##### BEM.create.block()
1032   -
1033   -Creates a block.
1034   -
1035   -###### Options
1036   -
1037   - * **String** `level` A directory of block's level. (Current directory by default)
1038   - * **Array** `addTech` Add the techs listed
1039   - * **Array** `forceTech` Use these techs only
1040   - * **Array** `noTech` Exclude these techs
1041   - * **Boolean** `force` Force files creating
1042   -
1043   -###### Arguments
1044   -
1045   - * **Array** `names` List of block names
1046   -
1047   -###### Example
1048   -
1049   -```js
1050   -var Q = require('q'),
1051   - BEM = require('bem').api,
1052   -
1053   - addTechs = ['bemhtml'],
1054   - blocks = ['b-header'];
1055   -
1056   -Q.when(BEM.create.block({ addTech: addTechs }, { names: blocks }), function() {
1057   - console.log('Create blocks: %s', blocks.join(', '));
1058   -});
1059   -```
1060   -
1061   -##### BEM.create.elem()
1062   -
1063   -Creating an element.
1064   -
1065   -###### Options
1066   -
1067   - * **String** `level` A directory of level. (Current directory by default)
1068   - * **String** `blockName` A name of element's block (required)
1069   - * **Array** `addTech` Add the techs listed
1070   - * **Array** `forceTech` Use only the techs listed
1071   - * **Array** `noTech` Exclude the techs listed
1072   - * **Boolean** `force` Force creating element's files (to rewrite them)
1073   -
1074   -###### Arguments
1075   -
1076   - * **Array** `names` List of element names
1077   -
1078   -###### Example
1079   -
1080   -```js
1081   -var Q = require('q'),
1082   - BEM = require('bem').api,
1083   -
1084   - addTechs = ['bemhtml', 'title.txt'],
1085   - block = 'b-header',
1086   - elems = ['logo'];
1087   -
1088   -Q.when(BEM.create.elem({ addTech: addTechs, blockName: block }, { names: elems }), function() {
1089   - console.log('Create elems %s of block %s', elems.join(', '), block);
1090   -});
1091   -```
1092   -
1093   -##### BEM.create.mod()
1094   -
1095   -Creating a modifier for a block or an element.
1096   -
1097   -###### Options
1098   -
1099   - * **String** `level` Level directory (current directory by default)
1100   - * **String** `blockName` Block name of this modifier (required)
1101   - * **String** `elemName` Element name
1102   - * **Array** `modVal` Modifier value
1103   - * **Array** `addTech` Add the techs listed
1104   - * **Array** `forceTech` Use only the techs listed
1105   - * **Array** `noTech` Exclude the techs listed
1106   - * **Boolean** `force` Force creating modifier files (rewrite)
1107   -
1108   -###### Arguments
1109   -
1110   - * **Array** `names` List of modifier
1111   -
1112   -###### Example
1113   -
1114   -```js
1115   -var Q = require('q'),
1116   - BEM = require('bem').api,
1117   -
1118   - forceTechs = ['css'],
1119   - block = 'b-header',
1120   - elem = 'logo',
1121   - mods = ['lang'],
1122   - vals = ['ru', 'en'];
1123   -
1124   -Q.when(BEM.create.mod({ forceTechs: forceTechs, blockName: block, modVal: vals }, { names: mods }), function() {
1125   - console.log('Create mod %s of block %s with vals %s', mods.join(', '), block, vals.join(', '));
1126   -});
1127   -
1128   -Q.when(BEM.create.mod({ forceTechs: forceTechs, blockName: block, elemName: elem, modVal: vals }, { names: mods }), function() {
1129   - console.log('Create mod %s of elem %s of block %s with vals %s', mods.join(', '), elem, block, vals.join(', '));
1130   -});
1131   -```
1132   -
1133   -#### BEM.build()
1134   -
1135   -Build files from blocks.
1136   -
1137   -###### Options
1138   -
1139   - * **String** `outputDir` An output directory (current directory by default)
1140   - * **String** `outputName` A filename (its prefix) for output
1141   - * **Level** `outputLevel` Output level for BEM entity to create
1142   - * **String** `block` Block name
1143   - * **String** `elem` Element name
1144   - * **String** `mod` Modifier name
1145   - * **String** `val` Modifier name
1146   - * **String** `declaration` A filename of input declaration (required)
1147   - * **Array** `level` List of levels to use
1148   - * **Array** `tech` List of techs to build
1149   -
1150   -You should use one of the following to specify output prefix:
1151   -
1152   - * `outputName` to specify full path-prefix
1153   - * `outputDir` plus `outputName` to specify directory path and file prefix (they will be joined for you)
1154   - * `outputLevel` plus properties describing BEM entity: `block`, `elem`, `mod` and `val` (path-prefix will
1155   - be constructed for you using level file mapping scheme)
1156   -
1157   -###### Example
1158   -
1159   -```js
1160   -var Q = require('q'),
1161   - B = require('bem'),
1162   - BEM = B.api,
1163   -
1164   - decl = 'page.deps.js',
1165   - outputDir = 'build',
1166   - outputName = 'page',
1167   - levels = ['blocks-common', 'blocks-desktop'],
1168   - techs = ['css', 'js'];
1169   -
1170   -// use outputDir and outputName options
1171   -Q.when(
1172   - BEM.build({
1173   - outputDir: outputDir,
1174   - outputName: outputName,
1175   - declaration: decl,
1176   - level: levels,
1177   - tech: techs
1178   - }),
1179   - function() {
1180   - console.log('Finished build of techs %s for levels %s. Result in %s/%s.* files.',
1181   - techs.join(', '), levels.join(', '), outputDir, outputName);
1182   - }
1183   -);
1184   -
1185   -// use outputLevel option
1186   -var level = B.createLevel('path/to/level'),
1187   - block = 'page';
1188   -Q.when(
1189   - BEM.build({
1190   - outputLevel: level,
1191   - block: block
1192   - }),
1193   - function() {
1194   - console.log('Finished build of techs %s for levels %s. Result in %s.* files.',
1195   - techs.join(', '), levels.join(', '), level.getRelByObj({ block: block }));
1196   - }
1197   -);
1198   -```
1199   -
1200   -#### BEM.decl
1201   -
1202   -Commands to work with declarations.
1203   -
1204   -##### BEM.decl.merge()
1205   -
1206   -Merging two or more declarations into one.
1207   -
1208   -###### Options
1209   -
1210   - * **String** `output` A file for output result. By default output is in STDOUT
1211   - * **Array** `declaration` List of filenames for declarations (required)
1212   -
1213   -##### BEM.decl.subtract()
1214   -
1215   -Subtracting the next declarations from the first one.
1216   -
1217   -###### Options
1218   -
1219   - * **String** `output` A file for output result. By default output is in STDOUT
1220   - * **Array** `declaration` List of filenames for declarations (required)
1221   -
1222   -## Contribute to development
1223   -
1224   -### Executing autotests
1225   -
1226   -To verify that your changes do not break existing functionality we recommend to run autotests and check that all of them pass. You can do that by executing the following command in the root of the project:
1227   -
1228   - mocha
1229   -
1230   -### Running autotests with test coverage report
1231   -
1232   -You can check the level of the code coverage by tests using the command:
1233   -
1234   - make test-cover
1235   -
1236   -Then open coverage.html file in a browser. Code lines which have not been executed during the tests run will be marked red.
1237   -
1238   -<!-- Yandex.Metrika counter -->
1239   -<img src="//mc.yandex.ru/watch/12831025" style="position:absolute; left:-9999px;" alt="" />
1240   -<!-- /Yandex.Metrika counter -->
  16 +* [Installation](http://bem.info/tools/bem/installation/)
  17 +* [Commands](http://bem.info/tools/bem/commands/)
  18 +* [Levels](http://bem.info/tools/bem/levels/)
  19 +* [Build customization](http://bem.info/tools/bem/customization/)
  20 +* [Tech modules](http://bem.info/tools/bem/tech-modules/)
  21 +* [API](http://bem.info/tools/bem/api/)
  22 +* [How to contribute](http://bem.info/tools/bem/contribute/)
1,291 README.ru.md
Source Rendered
... ... @@ -1,1271 +1,20 @@
1   -# БЭМ-инструменты
2   -Работа с файлами, написанными по [БЭМ-методу](http://bem.github.com/bem-method/pages/beginning/beginning.en.html).
3   -
4   -## Установка
5   -Вам потребуется [NodeJS 0.6+](http://nodejs.org/) или выше и [npm 1.x](http://npmjs.org/).
6   -После этого достаточно `npm -g install bem`.
7   -
8   - * Установить [nodejs](http://nodejs.org)
9   -
10   - https://github.com/joyent/node/wiki/Installation
11   -
12   - * Установить [npm](http://npmjs.org)
13   -
14   - curl http://npmjs.org/install.sh | sudo sh
15   -
16   - * После установки сконфигурируйте `NODE_PATH`:
17   -
18   - echo 'export NODE_PATH="'$(npm root -g)'"'>> ~/.bashrc && . ~/.bashrc
19   -