{"id":25478457,"url":"https://github.com/fatihtatoglu/enginaer","last_synced_at":"2025-07-28T17:07:33.667Z","repository":{"id":42430324,"uuid":"458904545","full_name":"fatihtatoglu/enginaer","owner":"fatihtatoglu","description":"A simple static web site engine with javascript.","archived":false,"fork":false,"pushed_at":"2025-06-03T05:23:14.000Z","size":743,"stargazers_count":1,"open_issues_count":9,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-19T22:28:50.626Z","etag":null,"topics":["enginaer","html","javascript","markdown","mustashe","website-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/fatihtatoglu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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}},"created_at":"2022-02-13T19:06:13.000Z","updated_at":"2022-03-19T13:09:56.000Z","dependencies_parsed_at":"2024-05-13T23:53:31.007Z","dependency_job_id":null,"html_url":"https://github.com/fatihtatoglu/enginaer","commit_stats":{"total_commits":98,"total_committers":3,"mean_commits":"32.666666666666664","dds":0.08163265306122447,"last_synced_commit":"a220a0059676b174ddf8d57aaac4cd2946cd054e"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fatihtatoglu/enginaer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatihtatoglu%2Fenginaer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatihtatoglu%2Fenginaer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatihtatoglu%2Fenginaer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatihtatoglu%2Fenginaer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fatihtatoglu","download_url":"https://codeload.github.com/fatihtatoglu/enginaer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fatihtatoglu%2Fenginaer/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267552097,"owners_count":24106000,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["enginaer","html","javascript","markdown","mustashe","website-engine"],"created_at":"2025-02-18T14:33:07.369Z","updated_at":"2025-07-28T17:07:33.643Z","avatar_url":"https://github.com/fatihtatoglu.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Enginær\n\nEnginær is a simple **static** website engine.\n\n## Motivation\n\nWhile developing, my motivation has been to easily publish a new post or a new page, like sending a new commit message to a git repository.\n\nI like writing blogs, but I cannot have enough time. I know writing markdown is so easy and also the markdown document has a human-readable structure. Moreover, markdown documents also support many components that using in HTML documents is not easy such as tables, images, and lists.\n\n![Publish Test Project](https://github.com/fatihtatoglu/enginaer/actions/workflows/test.yml/badge.svg\n) [![HitCount](https://hits.dwyl.com/fatihtatoglu/enginaer.svg?style=flat-square\u0026show=unique)](http://hits.dwyl.com/fatihtatoglu/enginaer) ![GitHub top language](https://img.shields.io/github/languages/top/fatihtatoglu/enginaer) ![GitHub](https://img.shields.io/github/license/fatihtatoglu/enginaer) ![npm](https://img.shields.io/npm/v/enginaer) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=fatihtatoglu_enginaer\u0026metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=fatihtatoglu_enginaer) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=fatihtatoglu_enginaer\u0026metric=bugs)](https://sonarcloud.io/summary/new_code?id=fatihtatoglu_enginaer) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=fatihtatoglu_enginaer\u0026metric=code_smells)](https://sonarcloud.io/summary/new_code?id=fatihtatoglu_enginaer)\n\n## Challenges\n\nCreating a blog engine there are some challenges. The first one is to create an automation for converting markdown documents into HTML documents. For this operation, I am using the **`marked`** library. The second challenge is creating a simple and extendable template system. The **`mustache`** library is the simple and logic-less template engine that is suitable for this challenge.\n\nApart from all of the other challenges, executing operations in parallel or serial order I need to develop an automated pipeline system. **`gulp`** is a flexible and repetitive system. I selected **`gulp`** and the main part of the project stands a gulp plugin.\n\n![gulp](docs/gulp.png \"gulp\") ![markdown](docs/markdown.png \"markdown\") ![markedjs](docs/markedjs.png \"markedjs\") ![mustache](docs/mustache.png \"mustache\") ![NodeJs](docs/nodejs.png \"NodeJs\") ![Github Actions](docs/actions.png \"Github Actions\") ![SonarCloud](docs/sonarcloud.png \"SonarCloud\") ![Glob](docs/glob.png \"Glob\")\n\n## Usage\n\nThe usage of the tool is very easy if you have selected your blog template or blog layout and its style.\n\n### Install\n\n```bash\nnpm install --save-dev enginaer\n```\n\n### Import References\n\nFirst of all import all required references.\n\n```js\nconst { series, parallel, src, dest } = require(\"gulp\");\nconst clean = require(\"gulp-clean\");\nconst enginær = require(\"enginaer\");\n```\n\n### Configuration\n\nThe configuration is very basic and user friendly.\n\n```js\nconst config = {\n    \"base\": __dirname,\n    \"page\": {\n        \"path\": \"./page/**/*.md\",\n        \"visitor\": \"./page/**/*Visitor.js\",\n        \"marked\": {\n            breaks: true,\n            smartLists: true,\n            headerIds: false\n        }\n    },\n    \"template\": {\n        \"path\": \"./template/*.mustache\",\n        \"helpers\": \"./template/templateHelpers.js\"\n    },\n    \"site-title-prefix\": \"Enginær - \",\n    \"site-name\": \"Enginær Demo\",\n    \"base-url\": \"https://blog.tatoglu.net/enginaer/\"\n};\n```\n\n#### Configuration Description\n\n| Attribute | | Description | Type |\n| :--- | :---: | :--- | :-- |\n| **base** | | The base path of the resources. Usually you can set *__dirname*. | string |\n| **page** | | The page object | object |\n| | ***path*** | The page folders paths. | glob |\n| | ***visitor*** | The page visitors paths.  | glob |\n| | ***marked*** | The marked configuration. Reference: [markedJS Options](https://marked.js.org/using_advanced#options) | object |\n| **template** | | The template object. | object |\n| | ***path*** | The templates paths. | glob |\n| | ***helpers*** | The render helper functions paths. | glob |\n| **site-title-prefix** | | The website title prefix. | string |\n| **site-name** | | The name of the website. | string |\n| **base-url** | | The website base url. | string |\n\nFor more details about [glob](https://gulpjs.com/docs/en/getting-started/explaining-globs/) data type.\n\n### Execution Steps\n\nAfter defining the configuration, there are there main steps.\n\n#### Initialization\n\n```js\nvar enginær = new Enginaer(config);\n```\n\nIn this step, the engine is initialized. While initilization, if the engine is faced any invalid or missing configuration, will throw an exception.\n\n#### Loading Resources\n\n```js\nenginær.load();\n```\n\nThis step is required for loading mandatory resources validation and processing in the engine. While loading resources engine could throw any exceptions, if the resource is not valid.\n\nThe loading steps work in the following order.\n\n1. Templates\n2. Template Helpers\n3. Page Visitors\n4. Pages\n\n#### Generation\n\n```js\nenginær.generate();\n```\n\nAt the end, the engine is ready to generate web site pages.\n\n### Sample Gulpfile\n\nFor putting all execution step together the sample gulp file is below.\n\n```js\nconst outputPath = \"../dist/\";\n\n// Gulp Step 1 - Clean old files.\nfunction cleanAll() {\n    return src(outputPath, { allowEmpty: true })\n        .pipe(clean({ force: true }));\n}\n\n// Gulp Step 2 - Copy all required assets.\nfunction copyAssets() {\n    return src([\"./assets/css/*.css\",\n        \"./assets/js/*.js\",\n        \"./assets/img/*.png\",\n        \"./assets/img/*.jpg\"], { base: \"./assets/\" })\n        .pipe(dest(outputPath));\n}\n\n// Gulp Step 3 - Enginær\nfunction generate() {\n\n    // Initialize enginær engine.\n    var enginær = new Enginaer(config);\n\n    // load required resources (templates, template helpers, pages, and page visitors.)\n    enginær.load();\n\n    // Generate web site pages.\n    return enginær.generate()\n        .pipe(dest(outputPath));\n}\n\nexports.default = series(\n    cleanAll,\n    parallel(copyAssets, generate)\n);\n```\n\n## Customization\n\nThe `enginær.generate` method return file stream. If you want to customize the output, you should add new pipe steps.\n\nThe other customization options are `Page Visitors` and `Template Helpers`.\n\n### Page Visitors\n\nThis customization step provides adding new key-value pair in the page metadata. The page visitors are applied for all pages after loading and for each page object.\n\nThe page visitor must be extend from `BasePageVisitor` class.\n\n```js\nclass BasePageVisitor {\n    name: string;\n    visit(page:Page):Error | undefined;\n}\n```\n\n#### Template Helpers\n\nThis customization step provides helpers for rendering mustache templates. There is one restriction that must be returns an object such as the below example.\n\n```js\nmodule.exports = {\n    \"helper-name\": function () {\n        return \"sample-code\";\n    }\n};\n```\n\n## Execute\n\nAfter creating `gulpfile.js` the system is ready to execute. For executing follow the below steps.\n\n```bash\n# Step 1. Install NPM Packages\nnpm install\n\n# Step 2. Install Gulp CLI\nnpm install --global gulp-cli\n\n# Step 3. Execute Enginær\ngulp\n```\n\nThat's all. For demo you can visit [Enginær Demo](https://blog.tatoglu.net/enginaer/) site.\n\n## Support\n\nFor supporting me, you can add an issue for bug cases or new feature requests.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffatihtatoglu%2Fenginaer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffatihtatoglu%2Fenginaer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffatihtatoglu%2Fenginaer/lists"}