{"id":16739312,"url":"https://github.com/olehdutchenko/gulp-ejs-monster","last_synced_at":"2026-05-05T22:01:18.068Z","repository":{"id":20455032,"uuid":"89958812","full_name":"OlehDutchenko/gulp-ejs-monster","owner":"OlehDutchenko","description":"Gulp plugin for ejs with steroids.","archived":false,"fork":false,"pushed_at":"2026-02-23T10:51:08.000Z","size":1084,"stargazers_count":11,"open_issues_count":4,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-23T19:19:15.584Z","etag":null,"topics":["ejs","gulp","gulp-plugin","template-engine"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OlehDutchenko.png","metadata":{"files":{"readme":"README-RU.md","changelog":"CHANGELOG-RU.md","contributing":"CONTRIBUTING-RU.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT-RU.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-05-01T20:09:50.000Z","updated_at":"2026-02-23T10:49:06.000Z","dependencies_parsed_at":"2024-03-01T21:45:31.814Z","dependency_job_id":null,"html_url":"https://github.com/OlehDutchenko/gulp-ejs-monster","commit_stats":{"total_commits":144,"total_committers":5,"mean_commits":28.8,"dds":0.25,"last_synced_commit":"b9678cb0d05a44e18c622047a3cfd67f18642076"},"previous_names":["dutchenkoOleg/gulp-ejs-monster","dutchenkooleg/gulp-ejs-monster"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/OlehDutchenko/gulp-ejs-monster","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OlehDutchenko%2Fgulp-ejs-monster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OlehDutchenko%2Fgulp-ejs-monster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OlehDutchenko%2Fgulp-ejs-monster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OlehDutchenko%2Fgulp-ejs-monster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OlehDutchenko","download_url":"https://codeload.github.com/OlehDutchenko/gulp-ejs-monster/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OlehDutchenko%2Fgulp-ejs-monster/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32669433,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ejs","gulp","gulp-plugin","template-engine"],"created_at":"2024-10-13T00:50:09.430Z","updated_at":"2026-05-05T22:01:18.053Z","avatar_url":"https://github.com/OlehDutchenko.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gulp-ejs-monster\n\n![npm](https://img.shields.io/badge/node-6.3.1-yellow.svg)\n![es2015](https://img.shields.io/badge/ECMAScript-2015_(ES6)-blue.svg)\n![license](https://img.shields.io/badge/License-MIT-orange.svg)\n[![Build Status](https://travis-ci.org/dutchenkoOleg/gulp-ejs-monster.svg?branch=master)](https://travis-ci.org/dutchenkoOleg/gulp-ejs-monster)\n\n\n:us: [English](./README.md)\n|\n:ru: Русский язык\n\n\u003e _Gulp плагин для [ejs](http://ejs.co/) со стероидами. Проект вдохновлен [ejs-locals](https://github.com/RandomEtc/ejs-locals)_\n\n[![js happiness style](https://cdn.rawgit.com/JedWatson/happiness/master/badge.svg)](https://github.com/JedWatson/happiness)\n\n---\n\n## Содержание\n\n1. [Благодарность](#Благодарность)\n1. [Для чего был создан этот плагин?](#Для-чего-был-создан-этот-плагин)\n1. [Пример использования плагина](#Пример-использования-плагина)\n1. [gulpEjsMonster()](#gulpejsmonster)\n\t- [Свойства плагина](#Свойства-плагина)\n\t- [Методы плагина](#Методы-плагина)\n\t- [Параметры плагина](#Параметры-плагина)\n\t- [Отчеты о ошибках рендера](#Отчеты-о-ошибках-рендера)\n1. [locals API](#locals-api)\n\t- [Свойства](#Свойства)\n\t- [Методы](#Методы)\n1. [Информация о проекте](#Информация-о-проекте)\n\n---\n\n## Благодарность\n\nПрежде всего, хотим выразит свою благодарность людям которые привели нас к использованию шаблонизатора [`ejs`](https://www.npmjs.com/package/ejs) и созданию на его основе `gulp-ejs-monster`:\n\n- [Matthew Eernisse (mde)](https://github.com/mde) - за создание и поддержку [`ejs`](https://github.com/mde/ejs)(http://ejs.co), а также сообщество `ejs`, которое ему в этом помогает\n- [Tom Carden (RandomEtc)](https://github.com/RandomEtc) - за создание проекта [`ejs-locals`](https://github.com/RandomEtc/ejs-locals), с которого мы взяли идею реализации `gulp-ejs-monster`\n- [Ryan Zimmerman (RyanZim)](https://github.com/RyanZim) - [`EJS-Lint`](https://github.com/RyanZim/EJS-Lint)\n- [Ariya Hidayat (ariya)](https://github.com/ariya) -   [`jquery/esprima`](https://github.com/jquery/esprima)\n- [Corey Hart (codenothing)](https://github.com/codenothing) -   [`jsonlint`](https://github.com/codenothing/jsonlint)\n\n## Для чего был создан этот плагин?\n\n[`ejs`](https://www.npmjs.com/package/ejs)(http://ejs.co) - это универсальный шаблонизатор, который позволяет создавать любую разметку, любой сложности. Чем лучше Ваше познания JavaScript - тем больше перед Вами открывается возможностей с `ejs`.\n\nУже существует много других плагинов для `ejs`. Но мы также решили создать свой, как надстройку к шаблонизатору + прокачав его небольшим набором \"стероидов\" ))).\n\nТакже, основной упор плагина `gulp-ejs-monster` - был сделан на оптимизацию и скорость рендера.\n\nПо умолчанию `ejs` использует JavaScript конструкцию [`with (expression)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with) для добавления области видимости - это дает свои преимущества для работы с шаблонизатором, но имеет свою цену - скорость поиска переменных увеличивается - что сказывается на скорости рендера страниц. Это особенно заметно на больших проектах.\n\nПоэтому `gulp-ejs-monster` принудительно отключает родные параметры `ejs` для того чтобы работать в строгом режиме. Что дает значительный прирост к скорости рендера.\n\nСписок константных значений от `gulp-ejs-monster` для `ejs`:\n\n```json\n{\n    \"strict\": true,\n    \"_with\": false,\n    \"debug\": false,\n    \"rmWhitespace\": false,\n    \"client\": false\n}\n```\n\nТакой подход, также имеет свою цену - теперь для работы Вам доступен только один глобальный объект, без всяких \"проксируемых\" свойств (которые раньше имитировала конструкция `with`). \n\n\n\u003e Если этот подход к работе с `ejs` шаблонизатором Вас не устраивает, Вы можете не читать дальше и не создавать запросов, так как менять его мы не намерены )))\n\n## Пример использования плагина\n\n### Установка\n\n```bash\nnpm i --save-dev gulp-ejs-monster\n# or yarn cli\nyarn add --dev gulp-ejs-monster\n```\n\n### Gulp задача\n\n```js\nconst gulp = require('gulp');\nconst gulpEjsMonster = require('gulp-ejs-monster');\n\ngulp.task('ejs', function() {\n    return gulp.src('./src/ejs/*.ejs')\n        .pipe(gulpEjsMonster({/* plugin options */}))\n        .pipe(gulp.dest('./dist/'));\n});\n```\n\n### EJS разметка\n\nПример структуры проекта\n\n```js\nejs/\n    layouts/\n        base.ejs\n    widgets/\n        news-list.ejs\n    includes/\n        critical.css\n    requires/\n        news-list.json\n    index.ejs\n    news.ejs    \n```\n\n#### Лейауты\n\n###### layouts/base.ejs\n\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n    \u003chead\u003e\n        \u003cmeta charset=\"UTF-8\"\u003e\n        \u003ctitle\u003e\u003c%- locals.blocks.title %\u003e\u003c/title\u003e\n        \u003cstyle\u003e\u003c%- locals.include('includes/critical.css') %\u003e\u003c/style\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003c%- locals.blocks.header %\u003e\n        \u003c%- locals.body %\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n#### Страницы рендера\n\n###### index.ejs\n\n```html\n\u003c% locals.setLayout('layouts/base.ejs') -%\u003e\n\u003c% locals.block('title', 'Index view') -%\u003e\n\n\u003ch1\u003eIndex view\u003c/h1\u003e\n\u003cp\u003eLorem ipsum dolor sit amet, consectetur adipisicing elit.\u003c/p\u003e\n\u003chr\u003e\n```\n\n###### news.ejs\n\n```html\n\u003c% locals.setLayout('layouts/base.ejs') -%\u003e\n\u003c% locals.block('title', 'Last News') -%\u003e\n\u003c% let newsList = locals.require('requires/news-list.json') -%\u003e\n\n\u003ch1\u003eLast News\u003c/h1\u003e\n\u003c%- locals.widget('widgets/news-list.ejs', {list: newsList}) %\u003e\n\u003chr\u003e\n```\n\n#### Исполняемые файлы\n\n###### requires/news-list.json\n\n```json\n[\n    {\n        \"title\": \"News title 1\",\n        \"description\": \"Lorem ipsum dolor sit ....\",\n        \"href\": \"news-page.html\"\n    }, {\n        \"title\": \"News title 2\",\n        \"description\": \"Lorem ipsum dolor sit ....\",\n        \"href\": \"news-page.html\"\n    }, {\n        \"title\": \"News title 3\",\n        \"description\": \"Lorem ipsum dolor sit ....\",\n        \"href\": \"news-page.html\"\n    }\n]\n```\n\n#### Текстовые файлы\n\n###### includes/critical.css\n\n```css\nhtml{font-family:sans-serif}\nbody{margin:0}\nh1{color:red}\n```\n\n#### Виджеты\n\n###### widgets/news-list.ejs\n\n```html\n\u003c%\n    let {\n        list = []\n    } = locals.entry;\n    \n    if (!list.length) {\n        return  'No news yet :((';\n    }\n-%\u003e\n\u003cul class=\"news-list\"\u003e\n    \u003c% list.forEach(item =\u003e { -%\u003e\n        \u003cli class=\"news-list__item\"\u003e\n            \u003cdiv class=\"news-item\"\u003e\n                \u003cdiv class=\"news-item__title\"\u003e\u003c%- item.title %\u003e\u003c/div\u003e\n                \u003cdiv class=\"news-item__description\"\u003e\n                    \u003cp\u003e\u003c%- item.description %\u003e\u003c/p\u003e\n                    \u003cp\u003e\u003ca href=\"\u003c%- item.href %\u003e\"\u003eRead more\u003c/a\u003e\u003c/p\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/li\u003e\n    \u003c% }); -%\u003e\n\u003c/ul\u003e\n```\n\n---\n\n## gulpEjsMonster\n\n### Свойства плагина\n\n#### `gulpEjsMonster.pluginName`\n\nИмя плагина.\n\n### Методы плагина\n\n#### `gulpEjsMonster.preventCrash()`\n\nМетод который при ошибке вызовет событие `end` чтобы предотвратить _\"падение\"_ текущего процесса `gulp` задачи. \n\n###### Пример использования\n\n```js\nconst gulp = require('gulp');\nconst gulpEjsMonster = require('gulp-ejs-monster');\n\ngulp.task('ejs', function() {\n    return gulp.src('./src/ejs/*.ejs')\n        .pipe(gulpEjsMonster({/* plugin options */}).on('error', gulpEjsMonster.preventCrash))\n        .pipe(gulp.dest('./dist/'));\n});\n```\n\n### Параметры плагина\n\nНебольшой совет - чтобы ускорить переработку и подготовку параметров плагина - используйте созданый объект с сохранением в переменную, которую потом Вы сможете указвать при вызове.  \nВ таком случае, за счет сохранения ссылок на внешний объект, параметры не будут пере-подготавливаться. А также появляется возможность сохранения полученных данных (в объекте `locals`) от предыдущей страницы рендера к последующим.\n\n###### Пример использования\n\n```js\nconst gulp = require('gulp');\nconst gulpEjsMonster = require('gulp-ejs-monster');\n\nconst options = {/* plugin options */}; // save as variable\n\ngulp.task('ejs', function() {\n    return gulp.src('./src/ejs/*.ejs')\n        .pipe(gulpEjsMonster(options).on('error', gulpEjsMonster.preventCrash))\n        .pipe(gulp.dest('./dist/'));\n});\n```\n\nДалее Вы можете ознакомится со списком всех доступных параметров.\n\n#### `layouts` \n\n_тип данных_ `string`\n|\n_по умолчанию_ `process.cwd()`\n\nОтносительный путь от текущей рабочей директории к директории с лейаутами.\n\n#### `widgets` \n\n_тип данных_ `string`\n|\n_по умолчанию_ `process.cwd()`\n\nОтносительный путь от текущей рабочей директории к директории с виджетами.\n\n#### `requires` \n\n_тип данных_ `string`\n|\n_по умолчанию_ `process.cwd()`\n\nОтносительный путь от текущей рабочей директории к директории с js/json файлами, которые Вы сможете подключать как исполняемые файлы, используя експорт CommonJS Модулей.\n\n#### `includes` \n\n_тип данных_ `string`\n|\n_по умолчанию_ `process.cwd()`\n\nОтносительный путь от текущей рабочей директории к директории c любыми текстовыми файлами, с которых Вы сможете подключать тектовый контент как есть.\n\n#### `extname` \n\n_тип данных_ `string`\n|\n_по умолчанию_ `'.html'`\n\nРасширение итоговых файлов рендера.  \nРазрешается не указывать . (точку) в начале значения, пример `'php' =\u003e '.php'`\n\n#### `delimiter` \n\n_тип данных_ `string` \n|\n_по умолчанию_ `'%'`\n|\n_допустимые значения_ `['%', '\u0026', '$', '?']`\n\nСимвол для использования с угловыми скобками для открытия / закрытия.  \nЕсли указаннное свойство не соответствует допустимому - будет утановлено значение по умолчанию! \n\n#### `localsName`\n\n_тип данных_ `string` \n|\n_по умолчанию_ `'locals'`\n\nИмя, которое будет использоваться для объекта, хранящего локальные переменные. Вы можете заменить это значение на свое и в дальнейшем использовать его внутри шаблонизатора.   \nСоответствено значение должно иметь корректное имя JavaScript переменной!\n\n#### `locals`\n\n_тип данных_ `Object` \n|\n_по умолчанию_ `{}`\n\nПередача собственных значений в объект, хранящий локальные переменные, которые будут доступны Вам внутри шаблоназотора в объекте `locals` (или под тем именем которое Вы могли указать в свойстве `localsName`)\n\nВажно знать, что плагин уже имеет определенный набор свойств и методов, которые будут добавлены к этому объекту. Поэтому чтобы не было конфликтов и перезаписей - ознакомтесь с [locals API](#locals-api).\n\n#### `compileDebug`\n\n_тип данных_ `boolean` \n|\n_по умолчанию_ `false`\n\nПри отключении - инструменты отладки не компилируются, что позволяет немного ускорить процесс рендера.  \nУказанное значение будет приведено к булевому.\n\nВажно знать, что при ошибке - плагин не сможет дать пояснения о произошедшем сбое, если значение равно `false`. Поэтому, в случае ошибки - плагин сделает рендер текущей страницы заново c включенным параметром, для того что бы выяснить что пошло не так и вывести максимальный отчет о найденных ошибках. \n\nЕсли вы используете вотч задачи для рендера - после исправления ошибки параметр снова будет иметь прежнее значение.\n\n\u003e В очень специфических ситуациях ре-рендер может не корректно выявить ошибки, из-за  \n\u003e повторного прохода, при котором, к примеру уже могут быть переопределены какие-то значение и тд.  \n\u003e Если это происходит - запустите сразу задачу с включенным параметром `compileDebug` \n\n#### `showHistory`\n\n_тип данных_ `boolean` \n|\n_по умолчанию_ `false`\n\nВыводит историю рендера после завершения работы с каждой страницей.\n\n#### `showHistoryOnCrash`\n\n_тип данных_ `boolean` \n|\n_по умолчанию_ `false`\n\nВыводит историю рендера при ошибках.\n\n#### `escape`\n\n_тип данных_ `function` \n|\n_по умолчанию_ `undefined`\n\n###### Параметры\n\nName | Type | Description\n--- | --- | ---\n`markup` | `string` | Разметка внутри конструкции\n\nСобственная функция экранирования, используемая с конструкцией `\u003c%=`, которая должна возвращать строку.\n\n#### `afterRender`\n\n_тип данных_ `function` \n|\n_по умолчанию_ `undefined`\n\nМетод который будет вызван после рендера страницы с ее лейаутами.\n\n###### Параметры\n\nName | Type | Description\n--- | --- | ---\n`markup` | `string` | Итоговая разметка страницы\n`file` | `Object` | Текущий файл рендера\n`sources` | `Array.\u003cstring\u003e` | Пути всех подключенных файлов в процессе рендера текущего файла, включая путь к текущей странице (первый в списке)\n\n\nИспользуя метод `afterRender` Вы можете изменить разметку, к примеру отформатировать при помощи [`js-beautify`](https://github.com/beautify-web/js-beautify) и вернуть новый результат использая `return` или использовать метод для установки вотчей на зависимости для каждой страницы отдельно.\n\n###### Пример форматирования разметки\n\n```js\nconst gulp = require('gulp');\nconst gulpEjsMonster = require('gulp-ejs-monster');\nconst jsBeautify = require('js-beautify').html;\n\nconst options = {\n    afterRender (markup) {\n        return jsBeautify.html(markup, /* jsBeautify options */);\n    }\n};\n\ngulp.task('ejs', function() {\n    return gulp.src('./src/ejs/*.ejs')\n        .pipe(gulpEjsMonster(options).on('error', gulpEjsMonster.preventCrash))\n        .pipe(gulp.dest('./dist/'));\n});\n```\n\n###### Пример установки вотчей на зависимые файлы\n\n```js\nconst gulp = require('gulp');\nconst gulpEjsMonster = require('gulp-ejs-monster');\nconst gulpWatchAndTouch = require('gulp-watch-and-touch');\n\nconst ejsFileWatcher = gulpWatchAndTouch(gulp);\nconst watchTask = true;\n\nconst options = {\n    afterRender (markup, file, sources) {\n        if (watchTask) {\n            let filePath = sources.shift(); // remove path of current view\n            let newImports = ejsFileWatcher(filePath, filePath, sources);\n            if (newImports) {\n                console.log(`${file.stem} has new imports`);\n            }\n        }\n    }\n};\n\ngulp.task('ejs', function() {\n    return gulp.src('./src/ejs/*.ejs')\n        .pipe(gulpEjsMonster(options).on('error', gulpEjsMonster.preventCrash))\n        .pipe(gulp.dest('./dist/'));\n});\n\ngulp.task('ejs-watch', function() {\n    gulp.watch('./src/ejs/*.ejs', gulp.series('ejs')); // gulp#4.x\n});\n\n```\n\n### Отчеты о ошибках рендера\n\nМы также сделали упор на вывод максимальных отчетов о ошибках которые могут возникнуть при рендере страниц, чтобы Вы могли понять что пошло не так\n\nПри сбое Вы будете получать группу отчетов:\n\n#### render history\n\n\nИстория рендера текущей страницы, при помощи которой вы сможете отследить последовательность действий плагина\n\n\u003e _**Внимание!** Начиная с версии 3.1.0_  \n\u003e История выводится только при включенном параметре [showHistoryOnCrash](#showHistoryOnCrash)\n\n```bash\nRender history:\nStart\nrender view - C:\\Wezom\\NodeModules\\gulp-ejs-monster\\examples\\src\\index.ejs\n    \u003e set layout - C:\\Wezom\\NodeModules\\gulp-ejs-monster\\examples\\src\\_layouts\\base.ejs\n    \u003e render widget - C:\\Wezom\\NodeModules\\gulp-ejs-monster\\examples\\src\\_widgets\\demo.ejs\n      caching new file content\n      √ file changed\n      ! render file content\n    \u003e render widget - C:\\Wezom\\NodeModules\\gulp-ejs-monster\\examples\\src\\_widgets\\demo.ejs\n      getting file content from cache\n      ! file not changed\n      ! render file content\n    \u003e require node module \"lodash\"\n      caching new file content\n    \u003e require file - C:\\Wezom\\NodeModules\\gulp-ejs-monster\\examples\\src\\_requires\\data.js\n      √ file changed\n      caching new file content\n    \u003e require file - C:\\Wezom\\NodeModules\\gulp-ejs-monster\\examples\\src\\_requires\\component.js\n        → CRASH...\n```\n\n#### ejs report\n\nРодной `ejs` отчет о найденной ошибке\n\n\u003e Наявность следующих отчетов будет зависеть от самой ошибки и файла в котором она произошла\n\n#### fs report\n\nЕсли файл, к которому вы обратились, не был найден.\n\n#### ejs-lint report\n\nЕсли ошибка в `*.ejs` файле - будет проведен линтинг плагином [`EJS-Lint`](https://github.com/RyanZim/EJS-Lint), для выявления возможных ошибок\n\n#### esprima report\n\nЕсли ошибка в `*.js` файле - будет проведен анализ плагином [`esprima`](https://github.com/jquery/esprima), для выявления возможных ошибок\n\n#### json-lint report\n\nЕсли ошибка в `*.json` файле - будет проведен линтинг плагином [`json-lint`](https://github.com/codenothing/jsonlint), для выявления возможных ошибок\n\n\n---\n\n## locals API\n\n`locals` - это единный глобальный объект хранящий в себе локальные значения, который будет доступен для работы шаблонизатора.\n\n### Свойства\n\n#### locals.body\n\n_тип данных_ `string` \n\nКонтент текущей страницы, для вставки внутри лейаутов.  \nСоответственно свойство доступно только внутри лейаутов! \n\n###### Пример использования\n\n```html\n\u003c!-- view index.ejs --\u003e\n\u003c% locals.setLayout('base.ejs') %\u003e\n\n\u003ch1\u003eIndex view\u003c/h1\u003e\n\u003cp\u003eLorem ipsum dolor sit amet, consectetur adipisicing elit.\u003c/p\u003e\n```\n\n```html\n\u003c!-- layout base.ejs --\u003e\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n    \u003chead\u003e\n        \u003cmeta charset=\"UTF-8\"\u003e\n        \u003ctitle\u003eDocument\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003c%- locals.body %\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n\n```\n\n#### locals.blocks\n\n_тип данных_ `Object` \n\nСписок собранных блоков, которые создаются при помощи метода [`locals.block()`](#localsblock-blockname-markup--mtd---block)\n\n###### Пример использования\n\n```html\n\u003c!-- view index.ejs --\u003e\n\u003c% locals.setLayout('base.ejs') %\u003e\n\u003c% locals.block('title', 'Index view') %\u003e\n\u003c% locals.block('header', '\u003ch1\u003eIndex view header\u003c/h1\u003e') %\u003e\n```\n\n```html\n\u003c!-- view news.ejs --\u003e\n\u003c% locals.setLayout('base.ejs') %\u003e\n\u003c% locals.block('title', 'Last News') %\u003e\n\u003c% locals.block('header', '\u003ch1\u003eNews view header\u003c/h1\u003e') %\u003e\n```\n\n```html\n\u003c!-- layout base.ejs --\u003e\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n    \u003chead\u003e\n        \u003cmeta charset=\"UTF-8\"\u003e\n        \u003ctitle\u003e\u003c%- locals.blocks.title %\u003e\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003c%- locals.blocks.header %\u003e\n        \u003c%- locals.body %\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n\n```\n\n#### locals.entry\n\n_тип данных_ `Object` \n\nВходящие параметры для текущего виджета.  \nСоответственно свойство доступно только внутри виджетов!\n \n###### Пример использования\n\n```html\n\u003c!-- view index.ejs --\u003e\n\u003c%- locals.widget('test.ejs') %\u003e\n\u003c%- locals.widget('test.ejs', {title: 'Custom title'}) %\u003e\n```\n\n```html\n\u003c!-- widget test.ejs --\u003e\n\u003c% let title = locals.entry.title || 'Default title'; %\u003e\n\u003ch1\u003e\u003c%- title) %\u003e\u003c/h1\u003e\n```\n\n###### Пример с используванием деструктуризации es6\n\n```html\n\u003c!-- widget test.ejs --\u003e\n\u003c% let {title = 'Default title'} = locals.entry; %\u003e\n\u003ch1\u003e\u003c%- title) %\u003e\u003c/h1\u003e\n```\n\n\n#### locals.viewName\n\n_тип данных_ `string` \n\nИмя текущей страницы рендера (без расширения).  \nНезависимо от текущего виджета, инклуда лейаута и тд.\n\n\n#### locals.viewPath\n\n_тип данных_ `string` \n\nАбсолютный путь к текущей странице рендера в Вашей файловой системе.\nНезависимо от текущего виджета, инклуда лейаута и тд.\n\n\n#### locals.fileChanged\n\n_тип данных_ `boolean` \n\nФлаг, изменился ли файл после последнего обращения к нему.   \nСвойство доступно внутри виджетов. На основных страницах рендера и их лейаутах, свойство также доступно, но для них оно всегда будет равно `true`.\n\n### Методы\n\n#### locals.setLayout (filePath)\n\nУстанавливает путь к лейауту для текущей страницы.\n\n###### Параметры\n\nName | Type | Description\n--- | --- | ---\n`filePath` | `string` | Путь к файлу (с расширением) относительно директории указанной в параметре [layouts](#layouts)\n\n#### locals.widget (filePath _[, relativeFolderPath] [, entry] [, cacheRenderResult]_) → `string`\n\nПодключение виджета разметки.\n\n###### Параметры\n\nName | Type | Attributes | Default | Description\n--- | --- | --- | --- | ---\n`filePath` | `string` |  |  | Путь к файлу (с расширением) относительно директории указанной в параметре [widgets](#widgets)\n`relativeFolderPath` | `string` | \u0026lt;optional\u003e |  | Относительный путь от которого следует подключать указанный файл, игнорируя параметр [widgets](#widgets), Если параметр не равен строке, то он воспринимается как `entry`\n`entry` | `Object` | \u0026lt;optional\u003e | `{}` | Входящие данные, которые передаются внутрь виджета, Если параметр `relativeFolderPath` не равен строке и третий параметр равен логическому значению, то он воспринимается как `cacheRenderResult`\n`cacheRenderResult` | `boolean` | \u0026lt;optional\u003e | `false` | Кешировать результат рендера разметки.\n\n###### Возвращает\n\n- _тип_: `string`\n- _описание_: рендер ejs разметки\n\nВнутри виджета Вы можете принять входящие параметры из [`locals.entry`](#localsentry). \n\n_Кеширование результата рендера_ позволит запоминать полученную строку в виде уже ***готовой статической разметки*** и вставлять ее при последующих вызовах на странице без прохода компиляции. Чтобы это выполнить при последующих применениях виджета нужно также указавать `cacheRenderResult`. Иначе рендер будет выполнен снова для текущего вызова.\n\nПри изменении файла самого виджета (смены даты модификации) - кэш будет сброшен.\n\nЭтот подход также можно использовать для нескольких страниц в общей задаче рендера.  \nК примеру - первая страница, `index.ejs`, рендерить блок кода, a `news.ejs`, которая идет после, уже возьмет закэшированный результат.\n\n###### Пример использования\n\n```html\n\u003c!-- cache at first render --\u003e\n\u003c%- locals.widget('big-rendering-markup.ejs', {/*data*/}, true) %\u003e\n\n\u003c!-- get cached render result from first render --\u003e\n\u003c%- locals.widget('big-rendering-markup.ejs', {/*data*/}, true) %\u003e\n\n\u003c!-- new render result --\u003e\n\u003c%- locals.widget('big-rendering-markup.ejs', {/*data*/}) %\u003e\n\n\u003c!-- get cached render result from first render --\u003e\n\u003c%- locals.widget('big-rendering-markup.ejs', {/*data*/}, true) %\u003e\n```\n\n#### locals.requireNodeModule (moduleName) → `*`\n\nПодключение модулей из установленных `node_modules`\n\n###### Параметры\n\nName | Type | Description\n--- | --- | ---\n`moduleName` | `string` | Имя модуля\n\n###### Возвращает\n\n- _тип_: `*`\n- _описание_: подключеный модуль\n\n###### Пример использования\n\n```js\n\u003c%\n    let lodash = locals.requireNodeModule('lodash');\n    lodash.cloneDeep(options);\n    lodash.isPlainObject(data);\n%\u003e\n```\n\n#### locals.require (filePath _[, relativeFolderPath]_) → `*`\n\nПодключение собственных исполняемых js/json файлов с поддержкой CommonJS для экспорта.\n\n###### Параметры\n\nName | Type | Attributes | Default | Description\n--- | --- | --- | --- | ---\n`filePath` | `string` |  |  | Путь к файлу (с расширением) относительно директории указанной в параметре [requires](#requires)\n`relativeFolderPath` | `string` | \u0026lt;optional\u003e |  | Относительный путь от которого следует подключать указанный файл, игнорируя параметр [requires](#requires)\n\n###### Возвращает\n\n- _тип_: `*`\n- _описание_: подключеный файл\n\nВнутри таких файлов объект `locals` не доступен. Вы можете передать его внутрь файла, к примеру, если вы экспортируете некий метод:\n\nВариант 1. Привязать контекст для метода\n\n```js\n\u003c%\n    let component = locals.require('component.js').bind(locals);\n    component('Hello');\n%\u003e\n```\n\n```js\n// component.js\n\nfunction component (message) {\n\tconsole.log(this);\n\tconsole.log(message);\n\t\n\t// require another components and files\n\tlet anotherComponent = this.require('another-component.js').bind(this);\n\tlet data = this.require('config.json');\n\t\n\t// ...\n}\n\nmodule.exports = component;\n```\n\nВариант 2. Использовать _каррирование (карринг)_\n\n```js\n\u003c%\n    let component = locals.require('component.js')(locals);\n    component('Hello');\n%\u003e\n```\n\n```js\n// component.js\n\n// Function wrapper\nfunction componentWrapper (locals) {\n\t// component\n\tfunction component (message) {\n\t\tconsole.log(locals);\n\t\tconsole.log(message);\n\t\t\n\t\t// require another components and files\n\t\tlet anotherComponent = locals.require('another-component.js')(locals);\n\t\tlet data = this.require('config.json');\n\t\t\n\t\t// ...\n\t}\n\t\n\treturn component;\n}\n\nmodule.exports = componentWrapper;\n```\n\n#### locals.include (filePath _[, relativeFolderPath]_) → `Object`\n\nВключает текстовый контент файла в Вашу разметку как есть.\n\n###### Параметры\n\nName | Type | Attributes | Default | Description\n--- | --- | --- | --- | ---\n`filePath` | `string` |  |  | Путь к файлу (с расширением) относительно директории указанной в параметре [includes](#includes)\n`relativeFolderPath` | `string` | \u0026lt;optional\u003e |  | Относительный путь от которого следует подключать указанный файл, игнорируя параметр [includes](#includes)\n\n###### Возвращает\n\n- _тип_: `Object`\n- _описание_: Объект имеет набор свойств\n\t- `changed` - флаг, изменен ли файл\n\t- `mtime` - Дата последней модификации файла\n\t- `content` - Строка с контентом файла\n\t- `toString()` - собственный метод приведения в строку, который возвращает `this.content`, таким образом если выполнить метод в контексте вставки в разметку - результатом будет сразу контент файла.\n\n###### Пример использования\n\n```html\n\u003c!-- include css file --\u003e\n\u003cstyle\u003e\u003c%- locals.include('critical.css') %\u003e\u003c/style\u003e\n```\n\n###### Пример создания компонента с конвертацией md в html\n\n```js\n// requires/components/md2html.js\n\nfunction createMd2HtmlComponent (locals) {\n    const marked = locals.requireNodeModule('marked');\n    const lodash = locals.requireNodeModule('lodash');\n    const defaultOptions = {\n        render: false,\n        gfm: true,\n        tables: true,\n        breaks: true,\n        pedantic: false,\n        sanitize: false,\n        smartLists: true,\n        smartypants: true\n    };\n\n    /**\n     * Convert md 2 html\n     * @param {string} filePath\n     * @param {Object} [options={}]\n     * @returns {string} converted html markup\n     */\n    function md2html (filePath, options = {}) {\n        let mdFile = locals.include(filePath);\n        if (mdFile.changed) {\n            let markedOptions = lodash.merge({}, defaultOptions, options);\n            // rewrite cached file content until it not changed\n            mdFile.content =  marked(mdFile.content, markedOptions);\n        }\n        return mdFile;\n    }\n    \n    return md2html;\n}\n\nmodule.exports = createMd2HtmlComponent;\n```\n\n```js\n// requires/extend-locals.js\n\nfunction extendLocals (locals) {\n    if (!locals.hasOwnProperty('com')) {\n        locals.com = {};\n    }\n  \n    locals.com.md2html = locals.com.md2html || locals.require('components/md2html.js')(locals);\n\n    // set other components inside render\n    // ...\n}\n\nmodule.exports = extendLocals;\n```\n\n```markdown\n# icludes/about-us.md\n\n[Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)\n\n# H1\n## H2\n### H3\n#### H4\n##### H5\n###### H6\n\nAlternatively, for H1 and H2, an underline-ish style:\n\nAlt-H1\n======\n\nAlt-H2\n------\n\n```\n\n```html\n\u003c!-- view index.ejs --\u003e\n\u003c% locals.setLayout('base.ejs'); -%\u003e\n\u003c% locals.require('extend-locals.js')(locals); -%\u003e\n\u003cdiv class=\"container\"\u003e\n    \u003carticle class=\"wysiwyg\"\u003e\n        \u003c%- locals.com.md2html('about-us.md') %\u003e\n    \u003c/article\u003e\n\u003c/div\u003e\n```\n\n#### locals.block (blockName, markup _[, mtd]_)  → `Block`\n\nУказание блока разметки, который будет доступен в [списке блоков](#localsblocks).\n\n###### Параметры\n\nName | Type | Attributes | Default | Description\n--- | --- | --- | --- | ---\n`blockName` | `string` |  |  | Имя блока, по которому можно будет обратится в [списке блоков](#localsblocks)\n`markup` | `string` |  |  | Значение блока\n`mtd` | `string` | \u0026lt;optional\u003e | `'replace'` | Метод указания значения для блока.\n\n###### Возвращает\n\n- _тип_: `string`\n- _описание_: значение блока\n\nПри указании значения для блока - формируется массив, которые при выводе склеивается в строку.  \nМетоды указания значения для блока:\n\n- `'replace'` - заменить предыдущее значение, если оно было. Если нет то просто назначит новое значение.\n- `'append'` - добавить в конец массива новое значение.\n- `'prepend'` - добавить в начало массива новое значение.\n\n###### Пример использования методов добавления\n\n```js\n\u003c% locals.block(headers, '\u003ch2\u003eIpsum\u003c/h2\u003e') %\u003e\n...\n\u003c% locals.block(headers, '\u003ch3\u003eDolor\u003c/h3\u003e', 'append') %\u003e\n...\n\u003c% locals.block(headers, '\u003ch1\u003eLorem\u003c/h1\u003e', 'prepend') %\u003e\n\n...\n\n\u003c%- locals.blocks.header %\u003e // =\u003e ['\u003ch1\u003eLorem\u003c/h1\u003e', '\u003ch2\u003eIpsum\u003c/h2\u003e', '\u003ch3\u003eDolor\u003c/h3\u003e'].join('\\n');\n```\n\n---\n\n## Информация о проекте\n\n* [История изменений](./CHANGELOG-RU.md)\n* [Руководство по содействию проекту](./CONTRIBUTING-RU.md)\n* [Кодекс поведения](./CODE_OF_CONDUCT-RU.md)\n* [Лицензия MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folehdutchenko%2Fgulp-ejs-monster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Folehdutchenko%2Fgulp-ejs-monster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folehdutchenko%2Fgulp-ejs-monster/lists"}