UNPKG

babelute

Version:

Internal Domain Specific (Multi)Modeling javascript framework

244 lines (196 loc) 8.56 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); // removed in production /** * Babelute core * * @author Gilles Coomans * @licence MIT * @copyright 2016-2017 Gilles Coomans */ var _lexem = require('./lexem'); var _lexem2 = _interopRequireDefault(_lexem); var _extends = require('./utils/extends'); var _extends2 = _interopRequireDefault(_extends); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Babelute subclass(es) instances : for holding array of lexems (i.e. a sentence) written through the DSL's API. * * Will be the base class for all DSLs handlers. * * Babelute API and lexems Naming Conventions : * * - any "meta-language" method (aka any method that handle the sentence it self - appending new lexem, changing current lexicon, sentences translations, ...) * must start with and underscore : e.g. _append, _lexicon, _if, _each, _eachLexem, _translate... * - any "pragmatics output related" method should start with a '$' and should be named with followed format : e.g. .$myLexiconToMyOutputType(...) * - any DSL lexems (so any other "api"'s method) should start with a simple alphabetic char : e.g. .myLexem(), .description(), .title(), ... * * @public */ var Babelute = function () { /** * construct a babelute instance * @param {?Array} lexems array of lexems for init. (only for internal use) */ function Babelute() { var lexems = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; _classCallCheck(this, Babelute); /** * the array where lexems are stored * @type {Array} */ this._lexems = lexems || []; /** * useful marker for fast instanceof replacement (frame/multiple-js-runtime friendly) * @type {Boolean} */ this.__babelute__ = true; } /** * The absolute Babelute atom method : add a lexem to babelute's array * @public * @param {String} lexiconName the current lexicon name * @param {String} name the lexem's name * @param {Array|arguments} args the lexem's arguments (either an array or maybe directly the arguments object from when lexem is called) * @return {Babelute} the current Babelute instance */ _createClass(Babelute, [{ key: '_append', value: function _append(lexiconName, name, args) { this._lexems.push(new _lexem2.default(lexiconName, name, args)); return this; } /** * conditional sentences concatenation. * * Apply modification at sentence writing time (aka the babelute does not contains the _if lexems. _if has immediatly been applied). * * @public * @param {*} condition any value that will be casted to Boolean (!!) * @param {Babelute} babelute which sentence to insert if !!condition === true * @param {?Babelute} elseBabelute which sentence to insert if !!condition === false * @return {Babelute} the current Babelute instance */ }, { key: '_if', value: function _if(condition, babelute) { var elseBabelute = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; if (condition) this._lexems = this._lexems.concat(babelute._lexems);else if (elseBabelute) this._lexems = this._lexems.concat(elseBabelute._lexems); return this; } /** * For each item from array : execute function and concatenate returned babelute sentence to current one. * Provided function must return a babelute. * * Apply modification at sentence writing time (aka the babelute does not contains the _each lexems. _each has immediatly been applied). * * @public * @param {Array} array the array to iterate on * @param {Function} func the function to handle each item. it must return a babelute. * @return {Babelute} the current Babelute instance */ }, { key: '_each', value: function _each(array, func) { var _this = this; if (array) array.forEach(function (item, index) { var b = func(item, index); _this._lexems.push.apply(_this._lexems, b._lexems); }); return this; } /** * Use a babelute (another sentence) at this point in the current sentence * @public * @param {string|Babelute} babelute Either a string formatted as 'mylexicon:myMethod' (which gives the lexem's method to call), or a Babelute instance (which will be inserted in current sentence) * @param {?...args} args the optional arguments to use when calling lexem (only if first argument is a string) * @return {Babelute} the current Babelute instance * @throws {Error} If lexicon not found (when first arg is string) * @throws {Error} If method not found in lexicon (when first arg is string) */ /* istanbul ignore next */ }, { key: '_use', value: function _use(babelute) {} // eslint-disable-line no-unused-vars // will be implemented in lexicon /** * Change current lexicon for next lexems * @public * @param {string} lexiconName the lexicon to use * @return {Babelute} a new Babelute from lexicon (i.e. with lexicon's API) * @throws {Error} If lexicon not found with lexiconName */ /* istanbul ignore next */ }, { key: '_lexicon', value: function _lexicon(lexiconName) {} // eslint-disable-line no-unused-vars // will be implemented in lexicon /** * transform a sentence through a function. This function must return a new sentence. * @param {Function} handler a function that receive the current sentence as argument and that return a new sentence. * @return {Babelute} the new sentence */ }, { key: '_transform', value: function _transform(handler) { return handler(this); } /** * translate each lexems * @param {[type]} handler [description] * @return {[type]} [description] */ }, { key: '_translateLexems', value: function _translateLexems(handler) { return this._transform(function (sentence) { var b = new Babelute(); sentence._lexems.forEach(function (lexem) { return b._use(handler(lexem)); }); return b; }); } /** * translate current sentence's lexems through a Lexicon or a map of Lexicon. * * @param {Lexicon|Object} lexicon the Lexicon (or a map of Lexicon) to get translation from * @param {Boolean} firstLevel true if should produce FirstLevel translation (i.e. targetLexicon.FirstLevel). False otherwise. * @return {Babelute} a new Babelute instance with translated lexems. */ /* istanbul ignore next */ }, { key: '_translateLexemsThrough', value: function _translateLexemsThrough(lexicon) { var firstLevel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; } // eslint-disable-line no-unused-vars // will be implemented in Lexicon // static extends(BaseClass, ...apis) { // assert(BaseClass === Babelute || (BaseClass.prototype instanceof Babelute), 'Babelute.extends accepts only a Babelute Class (or subclass) as first argument'); // const B = function(...args) { // BaseClass.apply(this, args); // }; // B.prototype = Object.create(BaseClass.prototype); // B.prototype.constructor = B; // apis.forEach((api) => { // for (var i in api) B.prototype[i] = api[i]; // }); // // Object.assign seems to bug when used on prototype (not investigate enough : so use plain old for-in syntax) // // investigation gives : babel make prototype not enumerable // return B; // } }]); return Babelute; }(); /** * Create Babelute subclass * @param {Babelute} BaseClass the class to be extended * @param {?Object} api an object containing methods to add to prototype * @return {Babelute} The subclass * @throws {AssertionError} (only in dev mode) If BaseClass is not a Babelute Subclass (or Babelute) */ exports.default = Babelute; Babelute.extends = _extends2.default;