├── .gitignore
├── index.jade
├── index.pug
├── package.json
├── LICENSE
├── test
├── start.js
├── page.fix.html
├── page.pug
├── page.jade.html
└── page.pug.html
├── core.pug
├── core.jade
└── readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | Thumbs.db
4 | Desktop.ini
5 | .DS_Store*
6 | ehthumbs.db
7 | .npmignore
--------------------------------------------------------------------------------
/index.jade:
--------------------------------------------------------------------------------
1 |
2 |
3 | //- Include core
4 |
5 | include core
6 |
7 |
8 | //- Element mixin
9 |
10 | mixin e( name, data, tag )
11 |
12 | +b( name, data, tag )(isElement=true)&attributes(attributes): block
13 |
14 |
15 | //- Block mixin
16 |
17 | mixin b( name, data, tag )
18 |
19 | - var myBlock = new BEMPUG.Block( name, data, tag, attributes );
20 |
21 | - BEMPUG.addData( myBlock );
22 |
23 | if myBlock.selfClosing
24 |
25 | #{myBlock.tag}(class=myBlock.classes)/&attributes(myBlock.attributes)
26 |
27 | else
28 |
29 | #{myBlock.tag}(class=myBlock.classes)&attributes(myBlock.attributes): block
30 |
31 | - BEMPUG.removeData( myBlock );
32 |
33 |
--------------------------------------------------------------------------------
/index.pug:
--------------------------------------------------------------------------------
1 |
2 |
3 | //- Include core
4 |
5 | include core
6 |
7 |
8 | //- Element mixin
9 |
10 | mixin e( name, data, tag )
11 |
12 | +b( name, data, tag )(isElement=true)&attributes(attributes): block
13 |
14 |
15 | //- Block mixin
16 |
17 | mixin b( name, data, tag )
18 |
19 | - var myBlock = new BEMPUG.Block( name, data, tag, attributes );
20 |
21 | - BEMPUG.addData( myBlock );
22 |
23 | if myBlock.selfClosing
24 |
25 | #{myBlock.tag}(class=myBlock.classes)&attributes(myBlock.attributes)/
26 |
27 | else
28 |
29 | #{myBlock.tag}(class=myBlock.classes)&attributes(myBlock.attributes): block
30 |
31 | - BEMPUG.removeData( myBlock );
32 |
33 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bempug",
3 | "version": "1.1.1",
4 | "description": "Simple mixins to help you writing code on BEM methodology in pug or jade projects.",
5 | "keywords": [
6 | "pug",
7 | "jade",
8 | "bem",
9 | "mixins"
10 | ],
11 | "main": "index.pug",
12 | "scripts": {
13 | "test": "echo \"Error: no test specified\" && exit 1"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "git+https://github.com/werty1001/bempug.git"
18 | },
19 | "author": "Oleg Krylov",
20 | "license": "MIT",
21 | "bugs": {
22 | "url": "https://github.com/werty1001/bempug/issues"
23 | },
24 | "homepage": "https://github.com/werty1001/bempug#readme"
25 | }
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Oleg
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/test/start.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | (function() {
5 |
6 | let file = __dirname + '/page.pug';
7 |
8 | let options = {
9 | pretty: '\t',
10 | doctype: 'html'
11 | };
12 |
13 | try {
14 |
15 | var pug = require( 'pug' );
16 |
17 | } catch( err ) {
18 |
19 | console.log( 'For Pug test you must install module [ npm i pug --save-dev ]' );
20 |
21 | }
22 |
23 | try {
24 |
25 | var jade = require( 'jade' );
26 |
27 | } catch( err ) {
28 |
29 | console.log( 'For Jade test you must install module [ npm i jade --save-dev ]' );
30 |
31 | }
32 |
33 | if ( pug ) {
34 |
35 | let PugCompiled = pug.renderFile( file, options );
36 |
37 | let selfClosing = ['img','input','hr','br','wbr','source','area','col','colgroup','meta','link'];
38 |
39 | let fixCompiled = PugCompiled.replace( /\/>/gi, '>' ).replace( /(<[A-Z][A-Z0-9]*\b[^>]*>)([^<>]*)(<\/[A-Z][A-Z0-9]*>)/gi, function(str, start, content, end) {
40 |
41 | let tag = start.replace( /<|>/gi, '' ).split( ' ' )[0];
42 |
43 | return start + ( ( selfClosing.indexOf( tag ) === -1 ) ? content.trim() : content ) + end;
44 | });
45 |
46 | require( 'fs' ).writeFileSync( __dirname + '/page.pug.html', PugCompiled + '', 'utf8' );
47 | require( 'fs' ).writeFileSync( __dirname + '/page.fix.html', fixCompiled + '', 'utf8' );
48 |
49 | }
50 |
51 | if ( jade ) {
52 |
53 | let JadeCompiled = jade.renderFile( file, options );
54 |
55 | require( 'fs' ).writeFileSync( __dirname + '/page.jade.html', JadeCompiled + '', 'utf8' );
56 |
57 | }
58 |
59 | })();
60 |
--------------------------------------------------------------------------------
/core.pug:
--------------------------------------------------------------------------------
1 | -
2 | const BEMPUG = {
3 |
4 | // bempug by Oleg Krylov [olegkrylov.pro]
5 |
6 | version: '1.1.1',
7 |
8 | tree: [],
9 |
10 | blocks: [],
11 |
12 | tagByName: {},
13 |
14 | beforeParse: {},
15 |
16 | afterParse: {},
17 |
18 | tagByAttr: { href: 'a', alt: 'img', for: 'label' },
19 |
20 | selfClosingTags: ['img','input','hr','br','wbr','source','area','col','colgroup'],
21 |
22 | forSpanTags: ['abbr','a','b','bdo','cite','dfn','em','i','kbd','q','s','span','sub','sup','samp','small','strong','u','var','mark','p','h1','h2','h3','h4','h5','h6','time','bdi','button','li','label'],
23 |
24 | isExternal: function( str ) {
25 | return /^(?:https?\:)?\/\//i.test( str );
26 | },
27 |
28 | isObject: function( obj ) {
29 | return ( typeof obj === 'object' && obj !== null && ! Array.isArray( obj ) ) ? true : false;
30 | },
31 |
32 | isString: function( str ) {
33 | return ( str && typeof str === 'string' && !!str.trim() ) ? true : false;
34 | },
35 |
36 | getCurrentBlock: function() {
37 | return this.blocks[ this.blocks.length - 1 ] || '';
38 | },
39 |
40 | getCurrentParent: function() {
41 | return this.tree[ this.tree.length - 1 ] || {};
42 | },
43 |
44 | addData: function( block ) {
45 | if ( block.type === 'block' ) this.blocks[ this.blocks.length ] = block.name;
46 | this.tree[ this.tree.length ] = block;
47 | },
48 |
49 | removeData: function( block ) {
50 | if ( block.type === 'block' ) this.blocks.pop();
51 | this.tree.pop();
52 | },
53 |
54 | blockProto: {
55 |
56 | setName: function( name, parent ) {
57 |
58 | var blockName = BEMPUG.isString( name ) ? name.trim() : false,
59 | parentName = BEMPUG.isString( parent ) ? parent.trim() : ( BEMPUG.getCurrentBlock() + '' );
60 |
61 | if ( this.type === 'element' )
62 | blockName = parentName + this.sep.element + ( blockName || 'element' );
63 |
64 | this.name = ( blockName || 'block' );
65 | this.classes.push( this.name );
66 |
67 | return this;
68 | },
69 |
70 | identifyTag: function( tag, name, attr ) {
71 |
72 | if ( BEMPUG.isString( tag ) ) return this.setTag( tag );
73 |
74 | if ( name && BEMPUG.isString( BEMPUG.tagByName[ name ] ) ) {
75 |
76 | return this.setTag( BEMPUG.tagByName[ name ] );
77 | }
78 |
79 | if ( attr.href || attr.alt || attr.for ) {
80 |
81 | var attribute = attr.href ? 'href' : ( attr.alt ? 'alt' : 'for' );
82 |
83 | return this.setTag( BEMPUG.tagByAttr[ attribute ] );
84 | }
85 |
86 | if ( this.parent.tag && this.parent.tag !== 'div' ) {
87 |
88 | if ( this.parent.tag === 'select' ) return this.setTag( 'option' );
89 |
90 | if ( this.parent.tag === 'dl' ) return this.setTag( 'dd' );
91 |
92 | if ( ['ul','ol'].indexOf( this.parent.tag ) !== -1 ) return this.setTag( 'li' );
93 |
94 | if ( BEMPUG.forSpanTags.indexOf( this.parent.tag ) !== -1 ) return this.setTag( 'span' );
95 | }
96 |
97 | return this.setTag( 'div' );
98 |
99 | },
100 |
101 | setTag: function( tag ) {
102 |
103 | if ( tag ) this.tag = tag.trim().toLowerCase();
104 |
105 | this.selfClosing = ( BEMPUG.selfClosingTags.indexOf( this.tag ) !== -1 );
106 |
107 | return this;
108 |
109 | },
110 |
111 | setSeparators: function( sep ) {
112 |
113 | var separator = BEMPUG.isString( sep ) ? sep.split( '|' ) : [],
114 | modifier = separator[0] || ( this.parent.sep ? this.parent.sep.modifier : BEMPUG.modifier ),
115 | element = separator[1] || ( this.parent.sep ? this.parent.sep.element : BEMPUG.element );
116 |
117 | this.sep.modifier = BEMPUG.isString( modifier ) ? modifier.trim() : '--';
118 | this.sep.element = BEMPUG.isString( element ) ? element.trim() : '__';
119 |
120 | return this;
121 | },
122 |
123 | addModifier: function( mod, name ) {
124 |
125 | if ( ! BEMPUG.isString( mod ) ) return this;
126 |
127 | mod.split( '.' ).forEach( function( val ) {
128 |
129 | var blockName = BEMPUG.isString( name ) ? name.trim() : this.name,
130 | modifier = BEMPUG.isString( val ) ? val.trim() : false;
131 |
132 | if ( ! modifier || ! blockName ) return;
133 |
134 | this.classes.push( blockName + this.sep.modifier + modifier );
135 |
136 | }, this);
137 |
138 | return this;
139 |
140 | },
141 |
142 | addMix: function( data, isElementMix ) {
143 |
144 | if ( ! data ) return this;
145 |
146 | var array = Array.isArray( data ) ? data : [ data ];
147 |
148 | array.forEach( function( val ) {
149 |
150 | var name, mix = ( val === true || val === 1 ) ? ( BEMPUG.getCurrentBlock() + '' ) : val;
151 |
152 | if ( ! BEMPUG.isString( mix ) ) return;
153 |
154 | name = mix.split( '|' )[0];
155 | name = name.replace( '&', ( BEMPUG.getCurrentBlock() + '' ) );
156 |
157 | if ( ! BEMPUG.isString( name ) ) return;
158 |
159 | name = name.trim();
160 |
161 | if ( isElementMix ) {
162 |
163 | var elementOf = name.split( ':' )[0];
164 | var elementName = name.split( ':' )[1];
165 |
166 | if ( ! elementName )
167 | elementName = this.type === 'element' ? this.name.split( this.sep.element )[1] : this.name;
168 |
169 | if ( ! ( BEMPUG.isString( elementOf ) && BEMPUG.isString( elementName ) ) ) return;
170 |
171 | name = elementOf.trim() + this.sep.element + elementName.trim();
172 | }
173 |
174 | this.classes.push( name );
175 | this.addModifier( mix.split( '|' )[1], name );
176 |
177 | }, this);
178 |
179 | return this;
180 |
181 | }
182 |
183 | },
184 |
185 | Block: function( name, data, tag, attr ) {
186 |
187 | this.__proto__ = BEMPUG.blockProto;
188 |
189 | this.name = name;
190 |
191 | this.data = BEMPUG.isObject( data ) ? data : {m: data};
192 |
193 | this.attributes = attr;
194 |
195 | this.isElement = !!this.attributes.isElement;
196 |
197 | this.parent = BEMPUG.getCurrentParent();
198 |
199 | if ( this.isElement ) delete this.attributes.isElement;
200 |
201 | if ( typeof this.data.t === 'undefined' ) this.data.t = tag;
202 |
203 | if ( typeof BEMPUG.beforeParse[ name ] === 'function' ) BEMPUG.beforeParse[ name ]( this );
204 |
205 | this.type = this.isElement ? 'element' : 'block' + ( ( this.data.p === false || this.data.p === 0 ) ? 'Off' : '' );
206 |
207 | this.sep = {};
208 |
209 | this.classes = [];
210 |
211 | this.identifyTag( this.data.t, this.name, this.attributes );
212 |
213 | this.setSeparators( this.data.s );
214 |
215 | this.setName( this.name, this.data.p );
216 |
217 | this.addModifier( this.data.m );
218 |
219 | this.addMix( this.data.b ).addMix( this.data.e, true );
220 |
221 | delete this.data;
222 |
223 | if ( typeof BEMPUG.afterParse[ name ] === 'function' ) BEMPUG.afterParse[ name ]( this );
224 |
225 | }
226 |
227 | };
--------------------------------------------------------------------------------
/core.jade:
--------------------------------------------------------------------------------
1 | -
2 | const BEMPUG = {
3 |
4 | // bempug by Oleg Krylov [olegkrylov.pro]
5 |
6 | version: '1.1.1',
7 |
8 | tree: [],
9 |
10 | blocks: [],
11 |
12 | tagByName: {},
13 |
14 | beforeParse: {},
15 |
16 | afterParse: {},
17 |
18 | tagByAttr: { href: 'a', alt: 'img', for: 'label' },
19 |
20 | selfClosingTags: ['img','input','hr','br','wbr','source','area','col','colgroup'],
21 |
22 | forSpanTags: ['abbr','a','b','bdo','cite','dfn','em','i','kbd','q','s','span','sub','sup','samp','small','strong','u','var','mark','p','h1','h2','h3','h4','h5','h6','time','bdi','button','li','label'],
23 |
24 | isExternal: function( str ) {
25 | return /^(?:https?\:)?\/\//i.test( str );
26 | },
27 |
28 | isObject: function( obj ) {
29 | return ( typeof obj === 'object' && obj !== null && ! Array.isArray( obj ) ) ? true : false;
30 | },
31 |
32 | isString: function( str ) {
33 | return ( str && typeof str === 'string' && !!str.trim() ) ? true : false;
34 | },
35 |
36 | getCurrentBlock: function() {
37 | return this.blocks[ this.blocks.length - 1 ] || '';
38 | },
39 |
40 | getCurrentParent: function() {
41 | return this.tree[ this.tree.length - 1 ] || {};
42 | },
43 |
44 | addData: function( block ) {
45 | if ( block.type === 'block' ) this.blocks[ this.blocks.length ] = block.name;
46 | this.tree[ this.tree.length ] = block;
47 | },
48 |
49 | removeData: function( block ) {
50 | if ( block.type === 'block' ) this.blocks.pop();
51 | this.tree.pop();
52 | },
53 |
54 | blockProto: {
55 |
56 | setName: function( name, parent ) {
57 |
58 | var blockName = BEMPUG.isString( name ) ? name.trim() : false,
59 | parentName = BEMPUG.isString( parent ) ? parent.trim() : ( BEMPUG.getCurrentBlock() + '' );
60 |
61 | if ( this.type === 'element' )
62 | blockName = parentName + this.sep.element + ( blockName || 'element' );
63 |
64 | this.name = ( blockName || 'block' );
65 | this.classes.push( this.name );
66 |
67 | return this;
68 | },
69 |
70 | identifyTag: function( tag, name, attr ) {
71 |
72 | if ( BEMPUG.isString( tag ) ) return this.setTag( tag );
73 |
74 | if ( name && BEMPUG.isString( BEMPUG.tagByName[ name ] ) ) {
75 |
76 | return this.setTag( BEMPUG.tagByName[ name ] );
77 | }
78 |
79 | if ( attr.href || attr.alt || attr.for ) {
80 |
81 | var attribute = attr.href ? 'href' : ( attr.alt ? 'alt' : 'for' );
82 |
83 | return this.setTag( BEMPUG.tagByAttr[ attribute ] );
84 | }
85 |
86 | if ( this.parent.tag && this.parent.tag !== 'div' ) {
87 |
88 | if ( this.parent.tag === 'select' ) return this.setTag( 'option' );
89 |
90 | if ( this.parent.tag === 'dl' ) return this.setTag( 'dd' );
91 |
92 | if ( ['ul','ol'].indexOf( this.parent.tag ) !== -1 ) return this.setTag( 'li' );
93 |
94 | if ( BEMPUG.forSpanTags.indexOf( this.parent.tag ) !== -1 ) return this.setTag( 'span' );
95 | }
96 |
97 | return this.setTag( 'div' );
98 |
99 | },
100 |
101 | setTag: function( tag ) {
102 |
103 | if ( tag ) this.tag = tag.trim().toLowerCase();
104 |
105 | this.selfClosing = ( BEMPUG.selfClosingTags.indexOf( this.tag ) !== -1 );
106 |
107 | return this;
108 |
109 | },
110 |
111 | setSeparators: function( sep ) {
112 |
113 | var separator = BEMPUG.isString( sep ) ? sep.split( '|' ) : [],
114 | modifier = separator[0] || ( this.parent.sep ? this.parent.sep.modifier : BEMPUG.modifier ),
115 | element = separator[1] || ( this.parent.sep ? this.parent.sep.element : BEMPUG.element );
116 |
117 | this.sep.modifier = BEMPUG.isString( modifier ) ? modifier.trim() : '--';
118 | this.sep.element = BEMPUG.isString( element ) ? element.trim() : '__';
119 |
120 | return this;
121 | },
122 |
123 | addModifier: function( mod, name ) {
124 |
125 | if ( ! BEMPUG.isString( mod ) ) return this;
126 |
127 | mod.split( '.' ).forEach( function( val ) {
128 |
129 | var blockName = BEMPUG.isString( name ) ? name.trim() : this.name,
130 | modifier = BEMPUG.isString( val ) ? val.trim() : false;
131 |
132 | if ( ! modifier || ! blockName ) return;
133 |
134 | this.classes.push( blockName + this.sep.modifier + modifier );
135 |
136 | }, this);
137 |
138 | return this;
139 |
140 | },
141 |
142 | addMix: function( data, isElementMix ) {
143 |
144 | if ( ! data ) return this;
145 |
146 | var array = Array.isArray( data ) ? data : [ data ];
147 |
148 | array.forEach( function( val ) {
149 |
150 | var name, mix = ( val === true || val === 1 ) ? ( BEMPUG.getCurrentBlock() + '' ) : val;
151 |
152 | if ( ! BEMPUG.isString( mix ) ) return;
153 |
154 | name = mix.split( '|' )[0];
155 | name = name.replace( '&', ( BEMPUG.getCurrentBlock() + '' ) );
156 |
157 | if ( ! BEMPUG.isString( name ) ) return;
158 |
159 | name = name.trim();
160 |
161 | if ( isElementMix ) {
162 |
163 | var elementOf = name.split( ':' )[0];
164 | var elementName = name.split( ':' )[1];
165 |
166 | if ( ! elementName )
167 | elementName = this.type === 'element' ? this.name.split( this.sep.element )[1] : this.name;
168 |
169 | if ( ! ( BEMPUG.isString( elementOf ) && BEMPUG.isString( elementName ) ) ) return;
170 |
171 | name = elementOf.trim() + this.sep.element + elementName.trim();
172 | }
173 |
174 | this.classes.push( name );
175 | this.addModifier( mix.split( '|' )[1], name );
176 |
177 | }, this);
178 |
179 | return this;
180 |
181 | }
182 |
183 | },
184 |
185 | Block: function( name, data, tag, attr ) {
186 |
187 | this.__proto__ = BEMPUG.blockProto;
188 |
189 | this.name = name;
190 |
191 | this.data = BEMPUG.isObject( data ) ? data : {m: data};
192 |
193 | this.attributes = attr;
194 |
195 | this.isElement = !!this.attributes.isElement;
196 |
197 | this.parent = BEMPUG.getCurrentParent();
198 |
199 | if ( this.isElement ) delete this.attributes.isElement;
200 |
201 | if ( typeof this.data.t === 'undefined' ) this.data.t = tag;
202 |
203 | if ( typeof BEMPUG.beforeParse[ name ] === 'function' ) BEMPUG.beforeParse[ name ]( this );
204 |
205 | this.type = this.isElement ? 'element' : 'block' + ( ( this.data.p === false || this.data.p === 0 ) ? 'Off' : '' );
206 |
207 | this.sep = {};
208 |
209 | this.classes = [];
210 |
211 | this.identifyTag( this.data.t, this.name, this.attributes );
212 |
213 | this.setSeparators( this.data.s );
214 |
215 | this.setName( this.name, this.data.p );
216 |
217 | this.addModifier( this.data.m );
218 |
219 | this.addMix( this.data.b ).addMix( this.data.e, true );
220 |
221 | delete this.data;
222 |
223 | if ( typeof BEMPUG.afterParse[ name ] === 'function' ) BEMPUG.afterParse[ name ]( this );
224 |
225 | }
226 |
227 | };
--------------------------------------------------------------------------------
/test/page.fix.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test page
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
26 |
27 |
32 |
33 |
34 |
35 |
38 |
39 |
40 |
41 |
44 |
45 |
46 |
47 |
50 |
51 |
52 |
53 |
56 |
57 |
58 |
59 | Success
60 |
61 |
62 |
63 |
64 | Title
65 |
66 |
67 |
68 | Title
69 |
70 |
71 |
72 |
73 |
74 | My item 1
75 | My item 2
76 | My item 3
77 |
78 |
79 |
80 | My text
81 |
82 |
83 |
84 |
85 |
89 |
90 |
93 |
94 |
95 |
96 | Title
97 |
98 |
99 |
100 | Title
101 |
102 |
103 |
104 | Title
105 |
106 |
107 |
108 |
111 |
112 |
115 |
116 |
117 |
118 |
119 |
Title
120 |
Text
121 |
122 |
123 |
124 |
125 | Title
126 |
127 |
128 |
129 |
132 |
133 |
134 |
135 |
138 |
139 |
140 |
141 | Content
142 |
143 |
144 |
145 | Content
146 |
147 |
148 |
149 | Content
150 |
151 |
152 |
153 |
156 |
157 |
158 |
159 |
160 |
Item of nav
161 |
162 |
Item of myblock
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | My item 1
177 | My item 2
178 |
179 | My mark
180 |
181 |
182 | My item 4
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
207 |
208 |
211 |
212 |
213 |
Without anything
214 |
215 |
216 |
219 |
220 |
223 |
224 |
227 |
228 |
231 |
232 |
235 |
236 |
239 |
240 |
243 |
244 |
247 |
248 |
251 |
252 |
255 |
256 |
259 |
260 |
263 |
264 |
267 |
268 |
271 |
272 |
275 |
276 |
279 |
280 |
283 |
284 |
287 |
288 |
289 |
290 |
--------------------------------------------------------------------------------
/test/page.pug:
--------------------------------------------------------------------------------
1 |
2 | - var n = '\n';
3 |
4 | include ../index
5 |
6 | -
7 | BEMPUG.modifier = '--';
8 | BEMPUG.element = '__';
9 |
10 | BEMPUG.tagByName = {list: 'ul', form: 'form', fields: 'fieldset'};
11 |
12 | BEMPUG.beforeParse[ 'input' ] = function( block ) {
13 |
14 | if ( typeof block.data.m === 'undefined' ) block.data.m = 'default';
15 | block.tag = 'input';
16 |
17 | };
18 |
19 | BEMPUG.afterParse[ 'page' ] = function( block ) {
20 |
21 | block.setTag( 'body' );
22 | block.addModifier( 'test' );
23 | block.attributes.itemscope = true;
24 | block.attributes.itemtype = 'http://schema.org/WebPage';
25 |
26 | };
27 |
28 | doctype
29 | +b('html', 'no-js', 'html')(lang='en')
30 | head
31 | meta(charset='utf-8')
32 | meta(http-equiv='X-UA-Compatible' content='IE=edge')
33 | meta(name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no')
34 |
35 | = n
36 |
37 | title Test page
38 | meta(name='description' content='This HTML code compiled from Pug.')
39 |
40 |
41 | +b('page')
42 |
43 |
44 |
45 | = n + n
46 | // Simple example
47 |
48 | +b('block')
49 | +e('element') Text
50 |
51 |
52 | = n + n
53 | // You can disable parent mode and element will ignore this block
54 |
55 | +b('header')
56 | +b('grid', {p: false})
57 | +e('logo') Logo
58 |
59 | = n
60 |
61 | +b('header')
62 | +b('grid', {p:0})
63 | +e('logo') Logo
64 |
65 |
66 | = n + n
67 | // Element depends on parent block
68 |
69 | +b('content')
70 | +e('layout') Content
71 |
72 |
73 | = n + n
74 | // You can set element directly
75 |
76 | +b('content')
77 | +e('layout', {p: 'page'}) Content
78 |
79 |
80 | = n + n
81 | // Block and element have modifier
82 |
83 | +b('alert', 'success')
84 | +e('text', 'bolder') Success
85 |
86 |
87 | = n + n
88 | // Block and element have more than one modifier
89 |
90 | +b('alert', 'success.active')
91 | +e('text', 'bolder.italic') Success
92 |
93 |
94 | = n + n
95 | // Also, you can set modifiers in data argument
96 |
97 | +b('alert', {m: 'success.active'}) Success
98 |
99 |
100 | = n + n
101 | // Default tag is div, but you can set it directly
102 |
103 | +b('news', {}, 'article')
104 | +e('title', {}, 'h1') Title
105 |
106 | = n
107 |
108 | +b('news', {t: 'article'})
109 | +e('title', {t: 'h1'}) Title
110 |
111 |
112 | = n + n
113 | // Sometimes mixin can be smart and tag depends on parent or attributes
114 |
115 | +b('list', {t: 'ul'})
116 | +e('item') My item 1
117 | +e('item') My item 2
118 | +e('item') My item 3
119 |
120 | = n
121 |
122 | +b('link')(href='https://www.npmjs.com/package/bempug')
123 | +b('text') My text
124 |
125 |
126 | = n + n
127 | // Also, you can use tagByName global option for set default tag by name
128 |
129 | +b('list')
130 | +e('item') Item
131 | +e('item') Item
132 |
133 | = n
134 |
135 | +b('form')
136 | +e('fields') Fields
137 |
138 |
139 | = n + n
140 | // Block is mixed with element
141 |
142 | +b('title', {e: 'article'}) Title
143 |
144 |
145 | = n + n
146 | // You can set name of element in mix with colon
147 |
148 | +b('title', {e: 'article:my-name'}) Title
149 |
150 |
151 | = n + n
152 | // Block is mixed with two elements
153 |
154 | +b('title', {e: ['article', 'content']}) Title
155 |
156 |
157 | = n + n
158 | // Block is mixed with element of parent block
159 |
160 | +b('news')
161 | +b('title', {e: true}) Title
162 |
163 | = n
164 |
165 | +b('news')
166 | +b('title', {e:1}) Title
167 |
168 |
169 | = n + n
170 | // Also, you can use ampersand & sign as parent block reference
171 |
172 | +b('news')
173 | +b('title', {e: '&'}) Title
174 | +b('text', {e: '&:description'}) Text
175 |
176 |
177 | = n + n
178 | // Block is mixed with element which has modifiers
179 |
180 | +b('title', {e: 'news|bolder.size-m'}) Title
181 |
182 |
183 | = n + n
184 | // Element is mixed with another element
185 |
186 | +b( 'footer' )
187 | +e( 'bottom', {e: 'page'} )
188 |
189 |
190 | = n + n
191 | // Element is mixed with block
192 |
193 | +b( 'footer' )
194 | +e( 'bottom', {b: 'grid'} )
195 |
196 |
197 | = n + n
198 | // Block is mixed with another block
199 |
200 | +b('article', {b: 'news'}) Content
201 |
202 |
203 | = n + n
204 | // Block is mixed with another block which has modifiers
205 |
206 | +b('article', {b: 'news|first'}) Content
207 |
208 |
209 | = n + n
210 | // Block is mixed with two blocks which have modifiers
211 |
212 | +b('article', {b: ['news|first','fixed|active']}) Content
213 |
214 |
215 | = n + n
216 | // Also, you can set separators in data argument 'modifier|element' and ignore global settings
217 |
218 | +b('news', {e: 'content', m: 'first', s: '---|___' })
219 | +b('text', {e: true, m: 'bolder'}) Text
220 |
221 |
222 | = n + n
223 | // You can get current block name
224 |
225 | +b('nav')
226 | +e('item')= 'Item of ' + BEMPUG.getCurrentBlock()
227 |
228 | +b('myblock')
229 | +e('item')= 'Item of ' + BEMPUG.getCurrentBlock()
230 |
231 |
232 |
233 |
234 | = n + n
235 | // Self closing tags
236 |
237 | +b('image','','img')
238 | +b('field',{t: 'input'})
239 |
240 |
241 | = n + n
242 | // Default tag depends on parent tag for any descendant
243 |
244 | +b('description')
245 | +e('list',{}, 'ul')
246 | +e('item') My item 1
247 | +e('item') My item 2
248 | +e('item')
249 | +e('mark') My mark
250 | +e('item')
251 | +b('text') My item 4
252 |
253 |
254 |
255 |
256 | = n + n
257 | // Before parse callback
258 |
259 | +b('input', {m: 'search'})
260 | +b('input')
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 | = n + n + n + n + n + n + n + n
270 | //
271 | // Crash test
272 | //
273 |
274 | = n + n
275 |
276 | +b(' block ',' mod ',' div ')
277 | +e(' el ',' mod ',' div ') With space
278 |
279 | = n
280 |
281 | +b(0,{m: ' big . small ', e: [' page | ', ' content : test | active '], b: ' text | bold . small ' },0)
282 | +e(0,{m: ' big . small . bold ', p: ' content '},0)
283 |
284 | = n
285 |
286 | +b
287 | +e Without anything
288 |
289 | = n
290 |
291 | +b([],[],[])
292 | +e([],[],[]) []
293 |
294 | = n
295 |
296 | +b({},{},{})
297 | +e({},{},{}) {}
298 |
299 | = n
300 |
301 | +b('','','')
302 | +e('','','') ('')
303 |
304 | = n
305 |
306 | +b(' ',' ',' ')
307 | +e(' ',' ',' ') (' ')
308 |
309 | = n
310 |
311 | +b(null,null,null)
312 | +e(null,null,null) null
313 |
314 | = n
315 |
316 | +b(false,false,false)
317 | +e(false,false,false) false
318 |
319 | = n
320 |
321 | +b(true,true,true)
322 | +e(true,true,true) true
323 |
324 | = n
325 |
326 | +b(1,1,1)
327 | +e(1,1,1) 1
328 |
329 | = n
330 |
331 | +b(0,0,0)
332 | +e(0,0,0) 0
333 |
334 | = n
335 |
336 | +b([],{m: [], p: [], e: [], b: [], s: [], t: [] },[])
337 | +e([],{m: [], p: [], e: [], b: [], s: [], t: [] },[]) {[]}
338 |
339 | = n
340 |
341 | +b({},{m: {}, p: {}, e: {}, b: {}, s: {}, t: {} },{})
342 | +e({},{m: {}, p: {}, e: {}, b: {}, s: {}, t: {} },{}) {{}}
343 |
344 | = n
345 |
346 | +b(0,{m: 0, p: 0, e: 0, b: 0, s: 0, t: 0 },0)
347 | +e(0,{m: 0, p: 0, e: 0, b: 0, s: 0, t: 0 },0) {0}
348 |
349 | = n
350 |
351 | +b(1,{m: 1, p: 1, e: 1, b: 1, s: 1, t: 1 },1)
352 | +e(1,{m: 1, p: 1, e: 1, b: 1, s: 1, t: 1 },1) {1}
353 |
354 | = n
355 |
356 | +b(null,{m: null, p: null, e: null, b: null, s: null, t: null },null)
357 | +e(null,{m: null, p: null, e: null, b: null, s: null, t: null },null) {null}
358 |
359 | = n
360 |
361 | +b(false,{m: false, p: false, e: false, b: false, s: false },false)
362 | +e(false,{m: false, p: false, e: false, b: false, s: false },false) {false}
363 |
364 | = n
365 |
366 | +b(true,{m: true, p: true, e: true, b: true, s: true },true)
367 | +e(true,{m: true, p: true, e: true, b: true, s: true },true) {true}
368 |
369 |
370 | = n
371 |
372 | +b('',{m: '', p: '', e: '', b: '', s: '' },'')
373 | +e('',{m: '', p: '', e: '', b: '', s: '' },'') {''}
374 |
375 |
376 | = n
377 |
378 | +b(' ',{m: ' ', p: ' ', e: ' ', b: ' ', s: ' ' },' ')
379 | +e(' ',{m: ' ', p: ' ', e: ' ', b: ' ', s: ' ' },' ') {' '}
380 |
381 |
382 |
383 | = n + n
384 |
385 |
--------------------------------------------------------------------------------
/test/page.jade.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test page
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
28 |
29 |
35 |
36 |
37 |
38 |
42 |
43 |
44 |
45 |
49 |
50 |
51 |
52 |
56 |
57 |
58 |
59 |
63 |
64 |
65 |
66 | Success
67 |
68 |
69 |
70 |
71 |
72 | Title
73 |
74 |
75 |
76 |
77 | Title
78 |
79 |
80 |
81 |
82 |
83 |
84 | My item 1
85 |
86 | My item 2
87 |
88 | My item 3
89 |
90 |
91 |
92 |
93 | My text
94 |
95 |
96 |
97 |
98 |
99 |
100 | Item
101 |
102 | Item
103 |
104 |
105 |
106 |
110 |
111 |
112 |
113 | Title
114 |
115 |
116 |
117 |
118 | Title
119 |
120 |
121 |
122 |
123 | Title
124 |
125 |
126 |
127 |
128 |
132 |
133 |
137 |
138 |
139 |
140 |
141 |
Title
142 |
143 |
Text
144 |
145 |
146 |
147 |
148 |
149 | Title
150 |
151 |
152 |
153 |
154 |
158 |
159 |
160 |
161 |
165 |
166 |
167 |
168 | Content
169 |
170 |
171 |
172 |
173 | Content
174 |
175 |
176 |
177 |
178 | Content
179 |
180 |
181 |
182 |
183 |
187 |
188 |
189 |
190 |
191 |
Item of nav
192 |
193 |
Item of myblock
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | My item 1
209 |
210 | My item 2
211 |
212 |
213 | My mark
214 |
215 |
216 |
217 | My item 4
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
With space
244 |
245 |
246 |
247 |
251 |
252 |
253 |
Without anything
254 |
255 |
256 |
257 |
261 |
262 |
266 |
267 |
271 |
272 |
276 |
277 |
281 |
282 |
286 |
287 |
291 |
292 |
296 |
297 |
301 |
302 |
306 |
307 |
311 |
312 |
316 |
317 |
321 |
322 |
326 |
327 |
328 |
{false}
329 |
330 |
331 |
332 |
336 |
337 |
341 |
342 |
346 |
347 |
348 |
349 |
--------------------------------------------------------------------------------
/test/page.pug.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Test page
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
28 |
29 |
35 |
36 |
37 |
38 |
42 |
43 |
44 |
45 |
49 |
50 |
51 |
52 |
56 |
57 |
58 |
59 |
63 |
64 |
65 |
66 | Success
67 |
68 |
69 |
70 |
71 |
72 | Title
73 |
74 |
75 |
76 |
77 | Title
78 |
79 |
80 |
81 |
82 |
83 |
84 | My item 1
85 |
86 | My item 2
87 |
88 | My item 3
89 |
90 |
91 |
92 |
93 | My text
94 |
95 |
96 |
97 |
98 |
99 |
100 | Item
101 |
102 | Item
103 |
104 |
105 |
106 |
110 |
111 |
112 |
113 | Title
114 |
115 |
116 |
117 |
118 | Title
119 |
120 |
121 |
122 |
123 | Title
124 |
125 |
126 |
127 |
128 |
132 |
133 |
137 |
138 |
139 |
140 |
141 |
Title
142 |
143 |
Text
144 |
145 |
146 |
147 |
148 |
149 | Title
150 |
151 |
152 |
153 |
154 |
158 |
159 |
160 |
161 |
165 |
166 |
167 |
168 | Content
169 |
170 |
171 |
172 |
173 | Content
174 |
175 |
176 |
177 |
178 | Content
179 |
180 |
181 |
182 |
183 |
187 |
188 |
189 |
190 |
191 |
Item of nav
192 |
193 |
Item of myblock
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | My item 1
209 |
210 | My item 2
211 |
212 |
213 | My mark
214 |
215 |
216 |
217 | My item 4
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
With space
244 |
245 |
246 |
247 |
251 |
252 |
253 |
Without anything
254 |
255 |
256 |
257 |
261 |
262 |
266 |
267 |
271 |
272 |
276 |
277 |
281 |
282 |
286 |
287 |
291 |
292 |
296 |
297 |
301 |
302 |
306 |
307 |
311 |
312 |
316 |
317 |
321 |
322 |
326 |
327 |
328 |
{false}
329 |
330 |
331 |
332 |
336 |
337 |
341 |
342 |
346 |
347 |
348 |
349 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # BemPug
2 |
3 | [](https://raw.githubusercontent.com/werty1001/bempug/master/LICENSE) [](https://www.npmjs.com/package/bempug) [](https://www.npmjs.com/package/bempug)
4 |
5 | Simple mixins to help you writing code on [BEM](https://en.bem.info/) methodology in [pug](https://pugjs.org/) or jade projects.
6 |
7 | ---
8 |
9 | > You like BEM? Try [BemGo](https://github.com/werty1001/bemgo) — starter kit for developing BEM apps using Gulp and Webpack.
10 |
11 | ---
12 |
13 | ### Anchors
14 | [Install](#install) | [Mixins](#mixins) | [Examples](#examples) | [Helpers](#helpers) | [Changelog](#changelog)
15 |
16 | ---
17 |
18 | ### Install
19 |
20 | Install from npm:
21 | ```sh
22 | npm i bempug -D
23 | ```
24 | Then include `index` file to your pug or jade project:
25 | ```Jade
26 | include ../../node_modules/bempug/index
27 | ```
28 |
29 | ---
30 |
31 | ### Mixins
32 |
33 | Block mixin:
34 |
35 | ```Pug
36 | +b( name, data, tag )
37 | ```
38 |
39 | - **name** `String`
40 | - **data** `String or Object`
41 | - **data.m** `String` — block modifier
42 | - **data.p** `Boolean` — disable parent mode
43 | - **data.e** `Array or String` — mix block with element
44 | - **data.b** `Array or String` — mix block with another block
45 | - **data.t** `String` — block tag
46 | - **data.s** `String` — block separators
47 | - **tag** `String`
48 |
49 | > If data argument is String it will be a modifier.
50 |
51 |
52 |
53 | Element mixin:
54 |
55 | ```Pug
56 | +e( name, data, tag )
57 | ```
58 |
59 | - **name** `String`
60 | - **data** `String or Object`
61 | - **data.m** `String` — element modifier
62 | - **data.p** `String` — parent block
63 | - **data.e** `Array or String` — mix element with another element
64 | - **data.b** `Array or String` — mix element with block
65 | - **data.t** `String` — element tag
66 | - **data.s** `String` — element separators
67 | - **tag** `String`
68 |
69 | > If data argument is String it will be a modifier.
70 |
71 | ---
72 |
73 | ### Examples
74 | [Block](#block) | [Element](#element) | [Modifier](#modifier) | [Tag](#tag) | [Mix](#mix) | [Separators](#separators)
75 |
76 | ---
77 |
78 | ### Block
79 | Simple example:
80 | ```Pug
81 | +b( 'block' )
82 | +e( 'element' ) Text
83 | ```
84 | ```HTML
85 |
88 | ```
89 |
90 | You can to disable parent mode and element will ignore this block:
91 | ```Pug
92 | +b( 'header' )
93 | +b( 'grid', {p: false} ) // or short {p:0}
94 | +e( 'logo' ) Logo
95 | ```
96 | ```HTML
97 |
102 | ```
103 |
104 | ---
105 |
106 | ### Element
107 |
108 | Element depends on parent block:
109 | ```Pug
110 | +b( 'content' )
111 | +e( 'layout' ) Content
112 | ```
113 | ```HTML
114 |
117 | ```
118 | You can set parent block for element directly:
119 | ```Pug
120 | +b( 'content' )
121 | +e( 'layout', {p: 'page'} ) Content
122 | ```
123 | ```HTML
124 |
127 | ```
128 |
129 | ---
130 |
131 | ### Modifier
132 |
133 | Block and element have modifier:
134 | ```Pug
135 | +b( 'alert', 'success' )
136 | +e( 'text', 'bolder' ) Success
137 | ```
138 | ```HTML
139 |
142 | ```
143 |
144 | Block and element have more than one modifier:
145 | ```Pug
146 | +b( 'alert', 'success.active' )
147 | +e( 'text', 'bolder.italic' ) Success
148 | ```
149 | ```HTML
150 |
153 | ```
154 |
155 | Also, you can set modifiers in `Object`:
156 | ```Pug
157 | +b( 'alert', {m: 'success.active'} ) Success
158 | ```
159 | ```HTML
160 | Success
161 | ```
162 |
163 | ---
164 |
165 | ### Tag
166 |
167 | Default tag is **div**, but you can set it directly:
168 | ```Pug
169 | +b( 'news', {}, 'article' )
170 | +e( 'title', {}, 'h1' ) Title
171 |
172 | // Or in data Object
173 |
174 | +b( 'news', {t: 'article'} )
175 | +e( 'title', {t: 'h1'} ) Title
176 | ```
177 | ```HTML
178 |
179 | Title
180 |
181 | ```
182 |
183 | Sometimes mixin can be smart and tag depends on parent or attributes:
184 | ```Pug
185 | +b( 'list', {t: 'ul'} )
186 | +e( 'item' ) My item 1
187 | +e( 'item' ) My item 2
188 | +e( 'item' ) My item 3
189 |
190 | +b( 'link' )(href='https://www.npmjs.com/package/bempug')
191 | +b( 'text' ) My text
192 | ```
193 | ```HTML
194 |
195 | My item 1
196 | My item 2
197 | My item 3
198 |
199 |
200 |
201 | My text
202 |
203 | ```
204 |
205 | Also, you can use `tagByName` global option for set default tag by name:
206 |
207 | ```Pug
208 | - BEMPUG.tagByName = {list: 'ul', form: 'form', fields: 'fieldset'};
209 |
210 | +b( 'list' )
211 | +e( 'item' ) Item
212 | +e( 'item' ) Item
213 |
214 | +b( 'form' )
215 | +e( 'fields' ) Fields
216 | ```
217 | ```HTML
218 |
219 | Item
220 | Item
221 |
222 |
223 |
226 | ```
227 |
228 | ---
229 |
230 | ### Mix
231 |
232 | Block is mixed with element:
233 | ```Jade
234 | +b( 'title', {e: 'article'} ) Title
235 | ```
236 | ```HTML
237 | Title
238 | ```
239 |
240 | You can set name of element in mix with colon:
241 | ```Pug
242 | +b( 'title', {e: 'article:my-name'} ) Title
243 | ```
244 | ```HTML
245 | Title
246 | ```
247 |
248 | Block is mixed with two elements:
249 | ```Pug
250 | +b( 'title', {e: ['article', 'content']} ) Title
251 | ```
252 | ```HTML
253 | Title
254 | ```
255 |
256 | Also, you can use ampersand `&` sign as parent block reference:
257 | ```Pug
258 | +b( 'news' )
259 | +b( 'title', {e: '&'} ) Title
260 | +b( 'text', {e: '&:description'} ) Text
261 | ```
262 | ```HTML
263 |
264 |
Title
265 |
Text
266 |
267 | ```
268 |
269 | Block is mixed with element which has modifiers:
270 | ```Pug
271 | +b( 'title', {e: 'news|bolder.size-m'} ) Title
272 | ```
273 | ```HTML
274 | Title
275 | ```
276 |
277 | Element is mixed with another element:
278 | ```Pug
279 | +b( 'footer' )
280 | +e( 'bottom', {e: 'page'} )
281 | ```
282 | ```HTML
283 |
286 | ```
287 |
288 | Element is mixed with block:
289 | ```Pug
290 | +b( 'footer' )
291 | +e( 'bottom', {b: 'grid'} )
292 | ```
293 | ```HTML
294 |
297 | ```
298 |
299 | Block is mixed with another block:
300 | ```Pug
301 | +b( 'article', {b: 'news'} ) Content
302 | ```
303 | ```HTML
304 | Content
305 | ```
306 |
307 | Block is mixed with another block which has modifiers:
308 | ```Pug
309 | +b( 'article', {b: 'news|first'} ) Content
310 | ```
311 | ```HTML
312 | Content
313 | ```
314 |
315 | Block is mixed with two blocks which have modifiers:
316 | ```Pug
317 | +b( 'article', {b: ['news|first','fixed|active']} ) Content
318 | ```
319 | ```HTML
320 | Content
321 | ```
322 |
323 | ---
324 |
325 | ### Separators
326 | You can change global separators:
327 | ```Pug
328 | - BEMPUG.modifier = '_';
329 | - BEMPUG.element = '__';
330 |
331 | +b( 'alert', 'success.active' )
332 | +e( 'text', 'bolder.italic' ) Success
333 | ```
334 | ```HTML
335 |
338 | ```
339 |
340 | Also, you can set separators for each block and ignore global settings `'modifier|element'`:
341 | ```Pug
342 | +b( 'news', {e: 'content', m: 'first', s: '---|___' } )
343 | +b( 'text', {e: true, m: 'bolder'} ) Text
344 | ```
345 | ```HTML
346 |
349 | ```
350 |
351 | ---
352 |
353 | ### Helpers
354 | [Get current block](#get-current-block) | [Get current parent](#get-current-parent) | [Callbacks](#callbacks)
355 |
356 | ---
357 |
358 | ### Get current block
359 | You can get current block name:
360 | ```Pug
361 | +b( 'nav' )
362 | +e( 'item' )
363 | - console.log( BEMPUG.getCurrentBlock() ); // 'nav'
364 | +b( 'img' )
365 | - console.log( BEMPUG.getCurrentBlock() ); // 'img'
366 | ```
367 |
368 | ---
369 |
370 | ### Get current parent
371 | You can get current parent `Object`:
372 | ```Pug
373 | +b( 'html', 'no-js', 'html' )(lang='en')
374 | - console.log( BEMPUG.getCurrentParent() );
375 | ```
376 | ```JS
377 | { type: 'block',
378 | name: 'html',
379 | tag: 'html',
380 | attributes: { lang: 'en' },
381 | sep: { modifier: '--', element: '__' },
382 | classes: [ 'html', 'html--no-js' ],
383 | parent: {},
384 | selfClosing: false }
385 | ```
386 |
387 | ---
388 |
389 | ### Callbacks
390 | You can set `beforeParse` callback:
391 | ```Pug
392 | - BEMPUG.beforeParse[ 'input' ] = function( block ) {
393 |
394 | if ( typeof block.data.m === 'undefined' ) block.data.m = 'default';
395 | }
396 |
397 | +b( 'input', {m: 'search'} ) // Have modifier 'search'
398 |
399 | +b( 'input' ) // No modifier, but we set modifier 'default' by callback
400 | ```
401 | ```HTML
402 |
403 |
404 | ```
405 |
406 | You can set `afterParse` callback:
407 | ```Pug
408 | - BEMPUG.afterParse[ 'page' ] = function( block ) {
409 |
410 | block.setTag( 'body' );
411 | block.addModifier( 'test' );
412 | block.attributes.itemscope = true;
413 | block.attributes.itemtype = 'http://schema.org/WebPage';
414 | }
415 |
416 | +b( 'page' ) My page
417 | ```
418 | ```HTML
419 | My page
420 | ```
421 |
422 | ---
423 |
424 | ### Changelog
425 |
426 | #### 1.1.1
427 | * **Fixed**: disable parent mode not work in cb
428 | * **Fixed**: name of element in mix with another element
429 |
430 | #### 1.1.0
431 | * **Add**: ampersand sign for mix
432 | * **Add**: mix element with blocks and another elements
433 |
434 | #### 1.0.2
435 | * **Add**: some global helpers
436 | * **Add**: before / after parse callback
437 | * **Fixed**: block and element separators work for any descendant
438 | * **Fixed**: default tag depends on parent tag for any descendant
439 |
440 | #### 1.0.1
441 | * **Add**: disable parent mode for blocks
442 |
443 | #### 1.0.0
444 | * **Release version**
445 |
446 | ---
447 |
448 | ### Thanks
449 |
450 | Many thanks to Roman Komarov for the [original idea](https://github.com/kizu/bemto).
451 |
452 |
--------------------------------------------------------------------------------