From 687969fb1429439ca7ff9fd038f0df82493f5890 Mon Sep 17 00:00:00 2001 From: Slava Oliyanchuk Date: Wed, 1 Feb 2017 23:25:34 +0300 Subject: [PATCH] Use bem-xjst in Node.js without bundling via browserify (#407 and #408 fixed) --- index.js | 14 +++----- lib/bemxjst/index.js | 33 ++++++++++-------- lib/compiler.js | 79 ++++++++++++++++--------------------------- package.json | 2 +- runtime-lint/index.js | 3 ++ 5 files changed, 55 insertions(+), 76 deletions(-) diff --git a/index.js b/index.js index 55e5eeaa..68fa735d 100644 --- a/index.js +++ b/index.js @@ -1,18 +1,12 @@ -var fs = require('fs'); -var Compiler = require('./lib/compiler').Compiler; +var Compiler = require('./lib/compiler'); var _cache = {}; function getEngine(engineName) { - if (_cache[engineName]) return _cache[engineName]; + var engine = _cache[engineName]; - var runtime = require('./lib/' + engineName); - var pathToBundle = require.resolve('./lib/' + engineName + '/bundle'); - var sourceBundle = fs.readFileSync(pathToBundle, 'utf8'); - - runtime.source = sourceBundle; + return engine || (engine = new Compiler(engineName)); +}; - return _cache[engineName] = new Compiler(runtime); -} module.exports = { get bemtree() { return getEngine('bemtree'); }, diff --git a/lib/bemxjst/index.js b/lib/bemxjst/index.js index b68f0970..0015418a 100644 --- a/lib/bemxjst/index.js +++ b/lib/bemxjst/index.js @@ -115,17 +115,15 @@ BEMXJST.prototype.compile = function compile(code) { this.oninit = out.oninit; }; -BEMXJST.prototype.recompileInput = function recompileInput(code) { - var args = BEMXJST.prototype.locals; - var out = code.toString(); - - // Strip the function - out = out.replace(/^function[^{]+{|}$/g, ''); +BEMXJST.prototype.getTemplate = function(code, options) { + this.compile(code, options); - // And recompile it with right arguments - out = new Function(args.join(', '), out); + return this.exportApply(); +}; - return out; +BEMXJST.prototype.recompileInput = function recompileInput(code) { + return new Function(BEMXJST.prototype.locals.join(', '), + utils.fnToString(code)); }; BEMXJST.prototype.groupEntities = function groupEntities(tree) { @@ -513,23 +511,28 @@ BEMXJST.prototype.applyMode = function applyMode(mode, changes) { BEMXJST.prototype.exportApply = function exportApply(exports) { var self = this; - exports.apply = function apply(context) { + var ret = exports || {}; + + ret.apply = function apply(context) { return self.run(context); }; // Add templates at run time - exports.compile = function compile(templates) { - return self.compile(templates); + ret.compile = function compile(templates) { + self.compile(templates); + return ret; }; var sharedContext = {}; - exports.BEMContext = this.contextConstructor; - sharedContext.BEMContext = exports.BEMContext; + ret.BEMContext = this.contextConstructor; + sharedContext.BEMContext = ret.BEMContext; for (var i = 0; i < this.oninit.length; i++) { var oninit = this.oninit[i]; - oninit(exports, sharedContext); + oninit(ret, sharedContext); } + + return ret; }; diff --git a/lib/compiler.js b/lib/compiler.js index 58fdab06..a2426e07 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -1,33 +1,41 @@ -var vm = require('vm'); -var BEMXJSTError = require('./bemxjst/error').BEMXJSTError; var fnToString = require('./bemxjst/utils').fnToString; +var engines = { + bemhtml: require('./bemhtml'), + bemtree: require('./bemtree') +}; -function Compiler(runtime) { - this.runtime = runtime; +function Compiler(engineName) { + this.engineName = engineName; } -exports.Compiler = Compiler; +function getCode(code, isRuntimeLint) { + return isRuntimeLint ? + (fnToString(code) + ';' + fnToString(require('../runtime-lint'))) + : fnToString(code); +} -Compiler.prototype.generate = function generate(code, options) { +Compiler.prototype.compile = function compile(code, options) { if (!options) options = {}; + var api = new engines[this.engineName](options); + return api.getTemplate(getCode(code, options.runtimeLint), options); +}; +Compiler.prototype.generate = function generate(code, options) { + if (!options) options = {}; code = fnToString(code); - var exportName = options.exportName || 'BEMHTML'; - var engine = options.engine || 'BEMHTML'; - - var locals = this.runtime.prototype.locals; - - if (options.runtimeLint) - code = code + ';' + require('fs') - .readFileSync('./runtime-lint/index.js', 'utf8'); + var exportName = this.engineName.toUpperCase(); var source = [ '/// -------------------------------------', '/// --------- BEM-XJST Runtime Start ----', '/// -------------------------------------', 'var ' + exportName + ' = function(module, exports) {', - this.runtime.source + ';', + require('fs').readFileSync( + require.resolve('./' + this.engineName + '/bundle'), + 'utf8' + ), + ';', ' return module.exports ||', ' exports.' + exportName + ';', '}({}, {});', @@ -35,12 +43,14 @@ Compiler.prototype.generate = function generate(code, options) { '/// --------- BEM-XJST Runtime End ------', '/// -------------------------------------', '', - 'var api = new ' + engine + '(' + JSON.stringify(options) + ');', + 'var api = new ' + exportName + '(' + JSON.stringify(options) + ');', '/// -------------------------------------', '/// ------ BEM-XJST User-code Start -----', '/// -------------------------------------', - 'api.compile(function(' + locals.join(', ') + ') {', - code + ';', + 'api.compile(function(', + require('./bemxjst').prototype.locals.join(', '), + ') {', + getCode(code, options.runtimeLint) + ';', '});', 'api.exportApply(exports);', '/// -------------------------------------', @@ -51,35 +61,4 @@ Compiler.prototype.generate = function generate(code, options) { return source; }; -var _compile = function _compile(fn, exports) { - try { - fn(exports, console); - } catch (e) { - if (e instanceof BEMXJSTError) - throw new BEMXJSTError(e.message); - else - throw e; - } - - return exports; -}; - -Compiler.prototype.compile = function compile(code, options) { - if (!options) options = {}; - - var out = this.generate(code, options); - - out = '(function(exports, console) {' + out + '})'; - var exports = {}; - - var fn = options.context === 'this' ? - vm.runInThisContext(out) : - vm.runInNewContext(out, { - console: console, - Error: Error, - BEMXJSTError: BEMXJSTError }); - - _compile(fn, exports); - - return exports; -}; +module.exports = Compiler; diff --git a/package.json b/package.json index c9c25aa6..8b6fa91e 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "test": "npm run make && npm run test:lint && npm run test:coverage && npm run size", "test:lint": "jscs `ls lib/*.js lib/**/*.js test/*.js | grep -v bundle` && jshint `ls lib/*.js lib/**/*.js test/*.js | grep -v bundle`", "test:mocha": "mocha --reporter=spec test/*-test.js", - "test:coverage": "./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha -- -u bdd -R spec test/*-test.js", + "test:coverage": "./node_modules/.bin/istanbul cover -x '**/runtime-lint/**' ./node_modules/mocha/bin/_mocha -- -u bdd -R spec test/*-test.js", "size": "npm run size:bemhtml && npm run size:bemtree", "size:bemhtml": "ls -ola ./lib/bemhtml/bundle.js | awk '{print \"BEMHTML Bundle Size:\", $4\" B\"}'", "size:bemtree": "ls -ola ./lib/bemtree/bundle.js | awk '{print \"BEMTREE Bundle Size:\", $4\" B\"}'" diff --git a/runtime-lint/index.js b/runtime-lint/index.js index ad97f6b2..e0bb3859 100644 --- a/runtime-lint/index.js +++ b/runtime-lint/index.js @@ -1,3 +1,4 @@ +module.exports = function(match, block, elem, mod, elemMod, oninit, xjstOptions, wrap, replace, extend, mode, def, content, appendContent, prependContent, attrs, addAttrs, js, addJs, mix, addMix, mods, addMods, addElemMods, elemMods, tag, cls, bem, local, applyCtx, applyNext, apply) { var collectMixes = function collectMixes(item, res, context) { res = res || []; if (!item) @@ -320,3 +321,5 @@ block('*')( return applyNext(); }) ); + +};