{"id":17954871,"url":"https://github.com/dennisreimann/gulp-mvb","last_synced_at":"2025-03-25T01:30:56.511Z","repository":{"id":3050516,"uuid":"48298902","full_name":"dennisreimann/gulp-mvb","owner":"dennisreimann","description":"gulp-mvb is a gulp plugin for creating a minimum viable blog.","archived":false,"fork":false,"pushed_at":"2024-06-16T09:55:27.000Z","size":2172,"stargazers_count":9,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-29T11:00:50.854Z","etag":null,"topics":["blog","blog-engine","blogging","frontmatter","gulp","gulp-plugin","markdown","static-site-generator"],"latest_commit_sha":null,"homepage":"https://dennisreimann.de/articles/gulp-mvb.html","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/dennisreimann.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},"funding":{"custom":["⚡️ Lightning Address: donate@d11n.net"]}},"created_at":"2015-12-19T22:12:11.000Z","updated_at":"2024-04-24T08:38:23.000Z","dependencies_parsed_at":"2024-11-29T19:34:56.361Z","dependency_job_id":"0cb5e03c-2099-4a26-9e4a-47e67e44727b","html_url":"https://github.com/dennisreimann/gulp-mvb","commit_stats":{"total_commits":68,"total_committers":1,"mean_commits":68.0,"dds":0.0,"last_synced_commit":"bb7427c8c22ff8a1b82520e8a51fafa523030c7e"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dennisreimann%2Fgulp-mvb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dennisreimann%2Fgulp-mvb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dennisreimann%2Fgulp-mvb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dennisreimann%2Fgulp-mvb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dennisreimann","download_url":"https://codeload.github.com/dennisreimann/gulp-mvb/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245381418,"owners_count":20606036,"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","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":["blog","blog-engine","blogging","frontmatter","gulp","gulp-plugin","markdown","static-site-generator"],"created_at":"2024-10-29T10:20:34.497Z","updated_at":"2025-03-25T01:30:55.849Z","avatar_url":"https://github.com/dennisreimann.png","language":"JavaScript","funding_links":["⚡️ Lightning Address: donate@d11n.net"],"categories":[],"sub_categories":[],"readme":"# gulp-mvb\n\ngulp-mvb is a [gulp](https://github.com/wearefractal/gulp) plugin for creating a _minimum viable blog_.\n\n[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)\n[![Build Status](https://travis-ci.org/dennisreimann/gulp-mvb.svg?branch=master)](https://travis-ci.org/dennisreimann/gulp-mvb)\n[![Known Vulnerabilities](https://snyk.io/test/github/dennisreimann/gulp-mvb/badge.svg)](https://snyk.io/test/github/dennisreimann/gulp-mvb)\n[![npm](https://img.shields.io/npm/v/gulp-mvb.svg)](https://www.npmjs.com/package/gulp-mvb)\n[![npm](https://img.shields.io/npm/dw/gulp-mvb.svg)](https://www.npmjs.com/package/gulp-mvb)\n\n## Dead simple blogging\n\nIt is made up of these parts which are connected to [DoTheSimplestThingThatCouldPossiblyWork](http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html)(TM):\n\n- **Markdown** for writing the articles\n- **YAML Front Matter** for the article meta information\n- **Jade** for the templates.\n  This is optional and the library is supposed to work with other template languages as well, as long as they support [gulp-data](https://www.npmjs.com/package/gulp-data).\n  I've only tested it with Jade, yet.\n- **Gulp** to wire it together\n\nIn fact, this is the [Octopress](http://octopress.org/) way of writing articles, which I really like.\nAs I needed another foundation for building [my site and blog](https://github.com/dennisreimann/website/), I decided to use this approach and create a gulp-plugin for it.\n\n## Conventions and assumptions\n\nTo keep it dead simple, here are the rules.\nArticles...\n\n- are written in Markdown\n- have this filename pattern: `YYYY-MM-DD-ARTICLE_NAME.md` (the `YYYY-MM-DD-` part is optional)\n- meta data is defined via YAML Front Matter\n\n## Usage\n\nInstall with:\n\n```bash\nnpm install gulp-mvb --save-dev\n```\n\nor\n\n```bash\nyarn add --dev gulp-mvb\n```\n\n### Example\n\nFor a full featured example of all the things described below see [my websites code](https://github.com/dennisreimann/website/).\n\n### Gulpfile\n\nHere is the TL;DR for how to use gulp-mvb in your gulpfile:\n\n```javascript\nimport mvb from 'gulp-mvb';\nimport jade from 'gulp-jade';\nimport rename from 'gulp-rename';\nimport highlightjs from 'highlight.js';\n\nconst paths = {\n  articles: ['src/articles/**/*.md'],\n  feedTemplate: 'src/templates/atom.jade',\n  articleTemplate: 'src/templates/article.jade',\n  articlesBasepath: 'articles'\n};\n\nconst mvbConf = {\n  // glob that locates the article markdown files\n  glob: paths.articles,\n  // the template for an article page\n  template: paths.articleTemplate,\n  // optionally define custom markdown-it plugins\n  plugins: [\n    'markdown-it-mark',\n    ['markdown-it-anchor', { permalink: false }]\n  ],\n  // callback function for generating an article permalink.\n  // see docs below for info on the article properties.\n  permalink(article) {\n    return `/${paths.articlesBasepath}/${article.id}.html`;\n  },\n  // callback function to further modify an article after it has been loaded.\n  loaded(article) {\n    article.calculatedData = doSomething();\n  },\n  highlight(code, lang) {\n    const languages = (lang != null) ? [lang] : undefined;\n    return highlightjs.highlightAuto(code, languages).value;\n  },\n  // callback function for generating custom article groups.\n  // access the return value via the groupedArticles property, so that you can\n  // either return an array if you only have one group or return an object with\n  // named groups in case you want to use multiple groups (by date, by tag, ...)\n  grouping(articles) {\n    const byYear = {};\n    articles.forEach((article) =\u003e {\n      let year = article.date.toISOString().replace(/-.*/, \"\");\n      byYear[year] || (byYear[year] = []);\n      return byYear[year].push(article);\n    });\n    return { byYear };\n  }\n}\n\ngulp.task('articles', () =\u003e\n  gulp.src(paths.articles)\n    .pipe(mvb(mvbConf))\n    .pipe(jade())\n    .pipe(gulp.dest(paths.articlesBasepath))\n);\n\ngulp.task('feed', () =\u003e\n  gulp.src(paths.feedTemplate)\n    .pipe(mvb(mvbConf))\n    .pipe(jade(pretty: true))\n    .pipe(rename('atom.xml'))\n    .pipe(gulp.dest())\n);\n```\n\nSee all of this in a broader context in [my websites gulpfile](https://github.com/dennisreimann/website/blob/master/gulpfile.babel.js).\n\n### The `article` object\n\nThe article object has the following properties, which can be used in the template and permalink function:\n\n- `id`: In case this is not set via front matter, it will be inferred from the articles file name (second part after date)\n- `date`: In case this is not set via front matter, it will be inferred from the articles file name (optional `YYYY-MM-DD-` part)\n- `permalink`: Gets generated via the permalink function\n- `content`: The rendered content (HTML)\n- `fileName`: You might want to use this in the permalink callback function\n- `previousArticle`: The previous/earlier article\n- `nextArticle`: The next/later article\n- `description`: If you use the Wordpress style `\u003c!-- more --\u003e` marker in your content, the description will be set with the text up to the marker. The marker will get replaced with `\u003cdiv id=\"more\"\u003e\u003c/div\u003e` so you can link to it by appending the `#more` hash to the permalink.\n\nIn addition to these properties, you will also have access to the ones you defined in the article's frontmatter.\nTo append further data, you can use the `loaded` callback function.\n\n### An article/blogpost\n\nThis is what a simple article with some frontmatter could look like:\n\n```markdown\n---\ntitle: Hello World\nsubtitle: Additional title\ndate: 2015-12-06\n---\n\nHere goes the markdown content that will be rendered as HTML...\n```\n\n### Templates\n\nYour `articleTemplate` might be something like:\n\n```jade\nextends layout\n\nblock main\n  article\n    header\n      h1= mvb.article.title\n      - if mvb.article.subtitle\n        h2= mvb.article.subtitle\n    != mvb.article.content\n    footer\n      | Posted on\n      time= mvb.article.date\n```\n\nAs you can see the article data will be available in your template via the namespaced variable `mvb.article`.\nThis is to avoid collision of mvbs variables with other potential custom variables.\n\nYou can also use the `mvb.articles` list to generate an overview for all your articles or your `feedTemplate` (in this case atom):\n\n```jade\ndoctype xml\nfeed(xmlns=\"http://www.w3.org/2005/Atom\" xml:base=\"https://example.org\")\n  id https://example.org/atom.xml\n  title Example Atom Feed\n  updated= mvb.articles[0].date.toISOString()\n  link(href=\"/\")\n  link(rel=\"self\" href=\"/atom.xml\")\n  for article in mvb.articles\n    entry\n      id= article.id\n      title= article.title\n      link(href=article.permalink)\n      updated= article.date.toISOString()\n      content(type=\"html\")= article.content\n```\n\nJade can be used to compile XML as shown above too, but it will always give the resulting file the .html extension.\nSo you will need to rename the feed with [gulp-rename](https://www.npmjs.com/package/gulp-rename).\n\nYou can also use the `mvb.articles` list to embed a list of your blogposts in your sites pages:\n\n```jade\nul\n  for article in mvb.articles\n    li\n      a(href=article.permalink)= article.title\n```\n\nIn case you defined a `grouping` callback in your config, you can access the grouped articles via the `mvb.groupedArticles` property.\n\nTo have access to the mvb variables you will need to use `.pipe(mvb(mvbConf))` in your gulp stream before rendering the templates.\n\n## License\n\n[MIT License](http://en.wikipedia.org/wiki/MIT_License)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdennisreimann%2Fgulp-mvb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdennisreimann%2Fgulp-mvb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdennisreimann%2Fgulp-mvb/lists"}