UNPKG

snakeskin

Version:

Компилятор блочных шаблонов c поддержкой наследования.

447 lines (369 loc) 12.1 kB
Snakeskin.DirObj = DirObj; /** * Объект управления директивами * * @constructor * @param {string} src - исходный текст шаблона * * @param {!Object} params - дополнительные параметры * @param {?function(!Error)=} [params.onError] - функция обратного вызова для обработки ошибок при трансляции * * @param {boolean} params.throws - если true, то в случае ошибки и отсутствия обработчика ошибок - * будет сгенерирована ошибка * * @param {string} params.exports - тип экспорта шаблонов * @param {boolean} params.inlineIterators - если true, то итераторы forEach и forIn * будут развёрнуты в циклы * * @param {boolean} params.autoReplace - если false, то Snakeskin не делает дополнительных преобразований * последовательностей * * @param {Object=} [params.macros] - таблица символов для преобразования последовательностей * @param {?string=} [params.renderAs] - тип рендеринга шаблонов, доступные варианты: * * 1) placeholder - все шаблоны рендерятся как placeholder-ы; * 2) interface - все шаблоны рендерятся как interface-ы; * 3) template - все шаблоны рендерятся как template-ы. * * @param {string|boolean} [params.doctype] - тип генерируемого документа HTML: * 1) html; * 2) xml. * * @param {boolean} params.localization - если false, то блоки ` ... ` не заменяются на вызов i18n * @param {string} params.i18nFn - название функции для i18n * @param {Object=} [params.language] - таблица фраз для локализации (найденные фразы будут заменены по ключу) * * @param {string} params.lineSeparator - символ перевода строки * @param {boolean} params.tolerateWhitespace - если true, то пробельные символы * вставляются "как есть" * * @param {boolean} params.replaceUndef - если false, то на вывод значений через директиву output * не будет накладываться фильтр undef * * @param {boolean} params.escapeOutput - если false, то на вывод значений через директиву output * не будет накладываться фильтр html * * @param {string} params.bemFilter - название используемого фильтра для БЭМ * @param {string} params.renderMode - режим рендеринга шаблонов, доступные варианты: * * 1) stringConcat - рендеринг шаблона в строку с простой конкатенацией через оператор сложения; * 2) stringBuffer - рендеринг шаблона в строку с конкатенацией через Snakeskin.StringBuffer; * 3) dom - рендеринг шаблона в набор команд из DOM API. * * @param {Array=} [params.lines] - массив строк шаблона (листинг) * @param {DirObj=} [params.parent] - ссылка на родительский объект * * @param {?boolean=} [params.needPrfx] - если true, то директивы декларируются как #{ ... } * @param {RegExp=} [params.ignore] - регулярное выражение, которое задаёт пробельные символы для игнорирования * * @param {Array=} [params.scope] - область видимости (контекст) директив * @param {Object=} [params.vars] - объект локальных переменных * @param {Array=} [params.consts] - массив деклараций констант * * @param {Object=} [params.proto] - объект корневого прототипа * @param {Object=} [params.info] - дополнительная информация о запуске * (используется для сообщений об ошибках) */ function DirObj(src, params) { for (let key in this) { if (this[key] && this[key].init) { this[key] = this[key].init(); } } /** @type {DirObj} */ this.parent = params.parent; /** @type {boolean} */ this.throws = params.throws; /** @type {?function(!Error)} */ this.onError = params.onError || null; /** @type {!Array} */ this.scope = params.scope || []; /** @type {Object} */ this.proto = params.proto; /** @type {Object} */ this.info = params.info; /** @type {boolean} */ this.needPrfx = params.needPrfx || false; /** @type {!Array} */ this.lines = params.lines || ['']; /** @type {string} */ this.lineSeparator = params.lineSeparator; /** * @expose * @type {string} */ this.renderMode = params.renderMode; /** * @expose * @type {boolean} */ this.tolerateWhitespace = params.tolerateWhitespace; /** * @expose * @type {boolean} */ this.inlineIterators = params.inlineIterators; /** * @expose * @type {(string|boolean)} */ this.doctype = params.doctype; /** * @expose * @type {boolean} */ this.replaceUndef = params.replaceUndef; /** * @expose * @type {boolean} */ this.escapeOutput = params.escapeOutput; /** * @expose * @type {(?string|undefined)} */ this.renderAs = params.renderAs; /** * @expose * @type {string} */ this.exports = params.exports; /** * @expose * @type {boolean} */ this.autoReplace = params.autoReplace !== false; /** * @expose * @type {(Object|undefined)} */ this.macros = params.macros; /** * @expose * @type {string} */ this.bemFilter = params.bemFilter; /** * @expose * @type {boolean} */ this.localization = params.localization; /** * @expose * @type {string} */ this.i18nFn = params.i18nFn; /** * @expose * @type {(Object|undefined)} */ this.language = params.language; /** * @expose * @type {(RegExp|undefined)} */ this.ignore = params.ignore; /** * Стек изменяемых параметров * (те параметры, которые можно изменить директивой) * @type {!Array} */ this.params = [ { '@root': true, renderMode: this.renderMode, inlineIterators: this.inlineIterators, doctype: this.doctype, escapeOutput: this.escapeOutput, renderAs: this.renderAs, replaceUndef: this.replaceUndef, autoReplace: this.autoReplace, macros: this.macros, localization: this.localization, i18nFn: this.i18nFn, bemFilter: this.bemFilter, language: this.language, ignore: this.ignore, tolerateWhitespace: this.tolerateWhitespace } ]; if (params.consts) { /** @type {(Array|undefined)} */ this.consts = params.consts; } /** * Если true, то трансляция сбрасывается * @type {boolean} */ this.brk = false; /** * Название активной директивы * @type {?string} */ this.name = null; /** * Таблица директив, которые могут идти после исходной * @type {Object} */ this.after = null; /** * Если false, то шаблон не вставляется в результирующую JS строку * @type {boolean} */ this.canWrite = true; // Флаги работы с пробельными символами // >>> /** @type {boolean} */ this.space = false; /** @type {boolean} */ this.skipSpace = false; /** @type {boolean} */ this.prevSpace = false; /** @type {boolean} */ this.chainSpace = false; /** @type {number} */ this.strongSpace = 0; /** @type {boolean} */ this.sysSpace = false; /** @type {number} */ this.freezeLine = 0; /** @type {boolean} */ this.attr = false; /** @type {boolean} */ this.attrEscape = false; // <<< /** * Номер активной итерации * @type {number} */ this.i = -1; /** * Дерево блоков (прототипы, блоки, константы) * @type {Object} */ this.blockStructure = null; /** * Таблица блоков (прототипы, блоки, константы) * @type {Object} */ this.blockTable = null; /** * Кеш внешних блоков и прототипов * @type {!Object} */ this.preDefs = {}; /** * Название активного внешнего прототипа или блока * @type {?string} */ this.outerLink = null; /** * Структура шаблонов * @type {!Object} */ this.structure = { name: 'root', /** @type {?{name: string, parent: Object, params: !Object, stack: !Array, vars: Object, children: Array, sys: boolean, strong: boolean}} */ parent: null, params: {}, stack: [], vars: params.vars || {}, children: [], sys: false, strong: false }; /** * Если true, то директива не имеет закрывающей части * @type {?boolean} */ this.inline = null; /** * Если true, то директива считается текстовой * @type {boolean} */ this.text = false; /** * Содержимое скобок (Escaper) * @type {!Array} */ this.quotContent = []; /** * Содержимое директив (для replaceTplVars) * @type {!Array} */ this.dirContent = []; /** * Содержимое блоков cdata * @type {!Array} */ this.cDataContent = []; /** * Таблица подключённых файлов * @type {!Object} */ this.files = {}; /** * Объект модуля * @type {{exports, require, id, key, root, filename, parent, children, loaded}} */ this.module = { exports: {}, require: IS_NODE ? require : null, id: 0, key: [], root: null, filename: this.info['file'], parent: IS_NODE ? module : null, children: [], loaded: true }; /** * Исходный текст шаблона * @type {string} */ this.source = this.replaceCData(String(src)); /** * Результирующий JS код * @type {string} */ this.res = ''; if (!this.proto) { this.res += /* cbws */` This code is generated automatically, don\'t alter it. */ (function () { var __IS_NODE__ = false, __HAS_EXPORTS__ = typeof exports !== 'undefined', __EXPORTS__ = __HAS_EXPORTS__ ? exports : this; try { __IS_NODE__ = 'object' === typeof process && Object.prototype.toString.call(process) === '[object process]'; } catch (ignore) { } var Snakeskin = (__IS_NODE__ ? global : this).Snakeskin; function __INIT__(obj) { Snakeskin = Snakeskin || (obj instanceof Object ? obj : void 0); if (__HAS_EXPORTS__) { delete __EXPORTS__.init; } if (__IS_NODE__) { Snakeskin = Snakeskin || require(obj); } __EXEC__.call(__EXPORTS__); return __EXPORTS__; } if (__HAS_EXPORTS__) { __EXPORTS__.init = __INIT__; } function __EXEC__() { var __ROOT__ = this, self = this; var __APPEND__ = Snakeskin.appendChild, __FILTERS__ = Snakeskin.Filters, __VARS__ = Snakeskin.Vars, __LOCAL__ = Snakeskin.LocalVars; ${this.multiDeclVar('$_')} `; } }