bem / bem-xjst Goto Github PK
View Code? Open in Web Editor NEWbem-xjst (eXtensible JavaScript Templates): declarative template engine for the browser and server
Home Page: https://bem.github.io/bem-xjst
License: Other
bem-xjst (eXtensible JavaScript Templates): declarative template engine for the browser and server
Home Page: https://bem.github.io/bem-xjst
License: Other
n/t
We need some syntax sugar for cases like that:
block('b1').def().match(function() { return !this._wrapped })(function() {
apply(
'',
{ 'ctx._wrapped': true },
{ ctx: { block: 'wrap', content: this.ctx } }
)
})
With applyCtx
sugar for assignments it can be written like that:
block('b1').def().match(function() { return !this._wrapped })(function() {
applyCtx(
{ block: 'wrap', content: this.ctx },
{ 'ctx._wrapped': true }
)
})
but we still need something for guard !this._wrapped
.
As some kind of theoretical thought about current BEMHTML's JS-syntax
Why not to use ES6's arrow functions in our templates? We could pass BEMContext
's instance as a first parameter of templates body (bem
parameter in the example below) instead of using this
keyword.
For example our bem-components' button
template could look like this
block('button')(
def()((bem) => {
var mods = bem.mods;
applyNext({ _button : bem.ctx });
}),
tag()((bem) => bem.ctx.tag || 'button'),
js()(true),
mix()({ elem : 'control' }),
attrs()(
// Common attributes
(bem) => {
var ctx = bem.ctx,
attrs = { role : 'button' };
ctx.tabIndex && (attrs.tabindex = ctx.tabIndex);
return attrs;
},
// Attributes for button variant
match((bem) => !bem.mods.type)((bem) => {
var ctx = bem.ctx, attrs = {};
ctx.tag || (attrs.type = ctx.type || 'button');
ctx.name && (attrs.name = ctx.name);
ctx.val && (attrs.value = ctx.val);
bem.mods.disabled && (attrs.disabled = 'disabled');
return bem.extend(applyNext(), attrs);
})
),
content()(
(bem) => {
var ctx = bem.ctx, content = [bem.ctx.icon];
ctx.text && content.push({ elem : 'text', content : ctx.text });
return content;
},
match((bem) => typeof bem.ctx.content !== 'undefined')((bem) => bem.ctx.content)
)
)
The idea about some fix for problem with dev runtime and autoinsertion of elem subpredicate. We can add .elemMatch
for using instead of .match
in cases when we need custom predicate about elem. So this will allow as for determine difference between custom predicates about elems and other in dev runtime.
Check that base template is the same in bem-core and bem-xjst.
Provide possibility to pass own naming scheme, e.g. with bem-naming
// cc @veged
Context already has block
property, and it should have others too.
n/t
\cc @veged
We need to have an opportunity to invoke exports.apply
inside templates which will be part of BEHTML APIs.
Something like BEMHTML.apply()
in example:
block('blah')(
content()(function() {
return BEMHTML.apply({ some : 'data' });
})
}
See bem/bem-components#149 (comment) for more examples
n/t
I think, instead of
'(function(g) {\n' +
' var __bem_xjst = function(exports' + modulesProvidedDeps + ') {\n' +
' ' + code + ';\n' +
' return exports;\n' +
' }\n' +
' var defineAsGlobal = true;\n' +
' if(typeof exports === "object") {\n' +
' exports["' + exportName + '"] = __bem_xjst({}' + modulesProvidedDeps + ');\n' +
' defineAsGlobal = false;\n' +
' }\n' +
' if(typeof modules === "object") {\n' +
' modules.define("' + exportName + '"' + modulesDeps + ',\n' +
' function(provide' + modulesProvidedDeps + ') {\n' +
' provide(__bem_xjst({}' + modulesProvidedDeps + ')) });\n' +
' defineAsGlobal = false;\n' +
' }\n' +
' defineAsGlobal && (g["' + exportName + '"] = __bem_xjst({}' + modulesProvidedDeps + '));\n' +
'})(this);'
we should use
'(function(g) {\n' +
' var __bem_xjst = function(exports' + modulesProvidedDeps + ') {\n' +
' ' + code + ';\n' +
' return exports;\n' +
' }\n' +
' var defineAsGlobal = true;\n' +
' if(typeof modules === "object") {\n' +
' modules.define("' + exportName + '"' + modulesDeps + ',\n' +
' function(provide' + modulesProvidedDeps + ') {\n' +
' provide(__bem_xjst({}' + modulesProvidedDeps + ')) });\n' +
' defineAsGlobal = false;\n' +
' }\n' +
' else if(typeof exports === "object") {\n' +
' exports["' + exportName + '"] = __bem_xjst({}' + modulesProvidedDeps + ');\n' +
' defineAsGlobal = false;\n' +
' }\n' +
' defineAsGlobal && (g["' + exportName + '"] = __bem_xjst({}' + modulesProvidedDeps + '));\n' +
'})(this);'
because now we force users of bemhtml/bemtree to use global variables in node.js context.
Please refer bem-site/bem-forum-content-ru#37 for more info.
Find out the numbers for different number of templates:
Right now it is taken from the return values, but should be probably in this._str
for compatibility reasons.
cc @veged: how necessary is this?
In 2.x
branch for BEMJSON
{ block: 'b1', elem: 'e1' }
and template
block('b1').elem('e1').mix()([{
{ block: 'b2' },
{ block: 'b3' }
}]);
the result is
<div class="b1__e1 b2__e1 b3__e1"></div>
Expected
<div class="b1__e1 b2 b3"></div>
We can introduce short-cut for cases like:
block('b1').def()(function() { applyCtx(...) })
block('b1').replace()(function() { return ... })
Moreover, we can make short-cut for another common case:
block('b1').def()(function() {
applyCtx(this.extend(this.ctx, ...))
})
block('b1').extend()(function() { return ... })
Now in production mode it's possible not to wrap templates body into js function. But it fails in dev mode. It'd be great to make it consistent so compilation in production mode should fail as well.
// cc @veged
Use it as a key to entity hashmap?
Using bem-xjst @ 0.6.0
The same template (bellow) compiles fine in dev mode, but fails when compiling with optimize: true
.
Template:
oninit(function() {
function JsdtmdContext(ctx) {
this._ctx = ctx;
this._start = false;
}
var oldApply = exports.apply;
exports.apply = function(ctx) {
var ctx_ = new JsdtmdContext(ctx);
return oldApply(ctx_);
};
});
match()(function() {
return 'Boom!';
});
match(this._start === false)(function() {
this._start = true;
return apply(this._ctx);
});
Generator:
require('bem-xjst').generate(body, { optimize : fasle }); // compiles fine
require('bem-xjst').generate(body, { optimize : true }); // fails
The full stacktrace:
AssertionError: "MemberExpression" == "ObjectExpression"
at Body.<anonymous> (/Users/varankinv/src/jsdtmd/node_modules/bem-xjst/node_modules/xjst/lib/xjst/compiler/entities/body.js:253:12)
at Array.forEach (native)
at Body.rollOutLocal (/Users/varankinv/src/jsdtmd/node_modules/bem-xjst/node_modules/xjst/lib/xjst/compiler/entities/body.js:250:11)
at Body.rollOutApply (/Users/varankinv/src/jsdtmd/node_modules/bem-xjst/node_modules/xjst/lib/xjst/compiler/entities/body.js:181:17)
at Body.rollOutSpecific (/Users/varankinv/src/jsdtmd/node_modules/bem-xjst/node_modules/xjst/lib/xjst/compiler/entities/body.js:146:19)
at Controller.__execute (/Users/varankinv/src/jsdtmd/node_modules/bem-xjst/node_modules/xjst/node_modules/estraverse/estraverse.js:313:31)
at Controller.replace (/Users/varankinv/src/jsdtmd/node_modules/bem-xjst/node_modules/xjst/node_modules/estraverse/estraverse.js:488:27)
at Object.replace (/Users/varankinv/src/jsdtmd/node_modules/bem-xjst/node_modules/xjst/node_modules/estraverse/estraverse.js:556:27)
at Body.rollOut (/Users/varankinv/src/jsdtmd/node_modules/bem-xjst/node_modules/xjst/lib/xjst/compiler/entities/body.js:117:16)
at Template.rollOut (/Users/varankinv/src/jsdtmd/node_modules/bem-xjst/node_modules/xjst/lib/xjst/compiler/entities/template.js:55:8)
n/t
cc @veged
block('b1').def()(function() {
function a() {
return x;
}
var x = 1;
return a();
})
После компиляции:
function __$b1(__$ctx, __$ref) {
function a__$0() {
return x;
}
var x__$1 = 1;
return a__$0();
}
Если в шаблоне var x поднять выше function a(), то все ок.
It seems that there's no use of ometa
anymore so it can be safely removed from package.json?
n/t
Does not seem to work in production mode of bem-xjst 1.0.0.
cc @veged
Test template:
block('b-bla')(
def()(function() {
applyCtx({ block: 'b-bla', elem: 'e' })
})
)
Test data:
{ "block": "b-bla" }
Test expect result:
<div class="b-bla__e"></div>
n/t
As a shortcut for match(this.ctx.mods[args[0]])
Atm:
block('a').mod('m')(
...
)
Throws
AssertionError: mod() predicates must have two arguments
Please provide a reference documentation on how to write templates, what is the difference between bem-xjst and xjst and so on.
apply('mode')
Now replace()
expects only function as an argument but it'd be useful to support strings, arrays, objects, etc as it is possible with applyCtx()
.
And the same for extend()
.
see #32 for some of the templates that could be used.
In 2.x branch
Here https://github.com/bem/bem-xjst/blob/2.x/lib/bemhtml.js#L8 it waits for bundle
, which is absent at https://github.com/bem/bem-xjst/tree/2.x/lib/bemhtml/runtime.
And as there's 3838318, it was done on purpose.
n/t
По мотивам bem/bem-core#330 (comment) перенести код про оборачивание результатов компиляции в bem-xjst
.
n/t
n/t
Branch 2.x
block('b1').replace()(function () {
return { block: 'b2' };
});
works fine (result is a string <div class="b2"></div>
) but
block('b1')(replace()(function () {
return { block: 'b2' };
}));
doesn't apply templates on new context (result is an object { block: 'b2' }
).
I have a bemhtml file with following content:
block('')
When I build my project in the production mode I get an error:
AssertionError: "Identifier" == "CallExpression"
at dive (/home/jifeon/projects/bnsf-adwiki/libs/bem-core/node_modules/bem-xjst/lib/bemhtml/compiler.js:317:12)
at Compiler.flatten (/home/jifeon/projects/bnsf-adwiki/libs/bem-core/node_modules/bem-xjst/lib/bemhtml/compiler.js:355:10)
at Compiler.pretranslate (/home/jifeon/projects/bnsf-adwiki/libs/bem-core/node_modules/bem-xjst/lib/bemhtml/compiler.js:91:22)
at Compiler.translate (/home/jifeon/projects/bnsf-adwiki/libs/bem-core/node_modules/bem-xjst/lib/bemhtml/compiler.js:105:14)
at Compiler.generate (/home/jifeon/projects/bnsf-adwiki/libs/bem-core/node_modules/bem-xjst/lib/bemhtml/compiler.js:692:14)
at Object.generate (/home/jifeon/projects/bnsf-adwiki/libs/bem-core/node_modules/bem-xjst/lib/bemhtml/api.js:16:40)
at exports.techMixin.getCompiledResult (/home/jifeon/projects/bnsf-adwiki/libs/bem-core/.bem/techs/bemhtml.js:46:24)
at _fulfilled (/home/jifeon/projects/bnsf-adwiki/node_modules/bem/node_modules/q/q.js:798:54)
at self.promiseDispatch.done (/home/jifeon/projects/bnsf-adwiki/node_modules/bem/node_modules/q/q.js:827:30)
at Promise.promise.promiseDispatch (/home/jifeon/projects/bnsf-adwiki/node_modules/bem/node_modules/q/q.js:760:13)
It's really impossible to guess what the file I should fix for successful build. Could you provide more verbose output with the bemhtml file name?
(Should also work with reimplemented and intersecting templates, i.e. with the same block).
include
lint
mode? With assertions for popular mistakes: bemhint/bemhint#56
.tag().def().content()
.def()(function() { /* forgot to return */ applyCtx({ ... }) })
block('b1')(tag()('a'))
should be block('b1').tag()('a')
n/t
while (i__$104 < l__$103) (function __$lb__$107() {
var __$r__$108;
var __$l0__$109 = __$ctx.ctx;
__$ctx.ctx = v__$102[i__$104++];
__$r__$108 = applyc(__$ctx, __$ref);
__$ctx.ctx = __$l0__$109;
return __$r__$108;
})();
Immediately invoked functions inside while
don't get inlined.
In 2.x
branch require('./desktop.bundles/index/index.bemhtml.js');
results in
ReferenceError: BEMHTML is not defined
at __bem_xjst (/Users/tadatuta/Sites/rimarcom-base-xjst2/desktop.bundles/index/index.bemhtml.js:1339:15)
at /Users/tadatuta/Sites/rimarcom-base-xjst2/desktop.bundles/index/index.bemhtml.js:1355:26
at Object.<anonymous> (/Users/tadatuta/Sites/rimarcom-base-xjst2/desktop.bundles/index/index.bemhtml.js:1365:3)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at repl:1:1
but vm.runInContext()
works.
@indutny Please provide jsdoc for api methods
n/t
{
"block": "b1",
"content": {
"elem": "e1",
Content: { tag: 'span', content: { elem: 'e2' } }
}
}
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.