npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mad-mark

v2.2.4

Published

Static site generator based on Markdown and [bem-xjst](https://github.com/bem/bem-xjst). Motivation is easy modular component based way to build static sites from simple markdown files. Like Max but Mark ;)

Downloads

4

Readme

Mad Mark

Static site generator based on Markdown and bem-xjst. Motivation is easy modular component based way to build static sites from simple markdown files. Like Max but Mark ;)

To match this needs Mad Mark uses:

Watch examples here.

Installation

npm i --save-dev mad-mark

Usage

Mad Mark can work standalone and in existing project like cli-tool for static content generation. Documentation for any project will be the best example. Mad Mark can help to build local and online documentation in easy way. Also you can write blog, articles and anything from your mind ;)

Init

You should choose cwd directory for your content in Markdown, output directory for generated content and languages for i18n. Mad Mark support i18n as well. First language will be used as default.

mark init

After that Mad Mark generate base project structure:

├── config.js
├── content
│   ├── articles
│   │   └── index.en.md
│   └── index.en.md
├── i18n.js
├── package.json
└── themes
    └── <project-name>

Build

You can build all content in two ways. Firstly, it's simple command:

mark build

After that you can open generated content as html files open dist/index.html. You can see generated folder structure below:

├── dist
│   ├── articles
│   │   └── index.html
│   ├── css
│   │   └── styles.min.css
│   ├── .nojekyll
│   ├── index.html
│   └── js
│       └── scripts.min.js

Second way to build your site is the dev-server which based on browser-sync.

mark serve

Point your browser to http://localhost:3000. Now you can edit your content, templates and configs with live-reloading ;)

Content

To generate static pages put markdown files into content/* with lang suffixes (e.g. index.en.md). You may use yaml header to set title and tags like this:

---
title: Post title
tags:
  - tag1
  - tag2
  - tag3
---

# Markdown content

Every markdown page will be wrapped in layout which is based on bemhtml templates for bem-xjst engine.

Layouts

When you put your pages into content/**/* each of them get layout name based on folder name where they stay. For example file in content/artiсles/index.en.md has articles layout. If file stay in the root of content folder so it has root layout ;) What does it mean for you? It's an unlimited number of possibilities for content customization. For example put template below to static/themes/<theme-name>/page/_layout/page_layout_articles.bemhtml.js:

block('page').mod('layout', 'articles')(
  content()(function() {
    return [
      {
        elem: 'header',
        content: {
          block: 'header',
          content: [
          	{
              tag: 'h1',
              content: 'Article layout'
            },
            {
	          tag: 'h2',
              content: `It's name: ${this._name}`
            }
          ]
        }
      },
      {
        elem: 'content',
        content: this.ctx.content
      },
      {
        elem: 'footer',
        content: {
          block: 'footer',
          content: 'Copyright by Superhero!'
        }
      },
      this.ctx.scripts
    ];
  })
);

Themes

You can collect your components for layouts in static/themes/<theme-name>. One default theme with your project name was created for you by mark init command. Theme folders follows filesystem organization for BEM projects. Component is the subfolder of theme for entity with *.bemhtml.js, *.css and *.js implementation. For example you can write component for header. Put template below to static/themes/<theme-name>/header/header.bemhtml.js:

block('header')(
  content()(function() {
    return [
      {
        tag: 'h1',
    	  content: 'Article layout'
      },
      {
        tag: 'h2',
        content: `It's name: ${this._name}`
      }
    ];
  })
);

Rewrite layout for articles to use header component:

block('page').mod('layout', 'articles')(
  content()(function() {
    return [
      {
        elem: 'header',
        content: {
          block: 'header'
        }
      },
      {
        elem: 'content',
        content: this.ctx.content
      },
      {
        elem: 'footer',
        content: {
          block: 'footer',
          content: 'Copyright by Superhero!'
        }
      },
      this.ctx.scripts
    ];
  })
);

Describe dependency in static/themes/<theme-name>/page/page.deps.js:

({
  shouldDeps: { block: 'header' }
});

Run mark serve to watch result at the same time.

You can use many themes in one project. Make sure your themes is defined in config. All of them is active in the same time and used as redefinition levels.

Config

config.js is the simple commonJs module:

module.exports = {
  debug: false, // false by default
  langs: ['en', 'ru'],
  themes: ['<theme-name>', ...], // all sub folders names from `themes` folder
  output: './dist',
  server: { // will be passed as options for Browser Sync
    tunnel: true, // https://www.browsersync.io/docs/options
    open: false
  }
};

Config data is exposed to your templates as this._config helper.

Template helpers

Meta

Components or layouts may require extra information about your markdown, project, other files, languages, paginations and etc. Mad Mark know this problem ;)

You can get information below in body of your templates by call this._*, ex this._name, this._config:

{
  _tags, // Array - parsed tags for all pages from meta in yml
  _pagination, // Object - data for pagination
  _paginatable, // Boolean - need pagination
  _config, // Object - project config
  _data, // Object - compiled data by current lang
  _multilang, // undefined || Array - contains `{ lang: String, url: String, current: Boolean, default: Boolean }` objects if there is more then 1 lang in config
  _name, // String - page name
  _meta, // Object - parsed meta from yml in Markdown file
  _layout, // String - layout name
  _i18n, // Object - i18n translations
  _lang, // String - page lang
  _mods // Object - layout modificators
}

i18n meta

i18n.js is the simple commonJs module:

module.exports = {
  en: {
    title: 'Title in english',
    subtitle: 'Subtitile in en'
  },
  ru: {
    title: 'Title in russian',
    subtitle: 'Subtitile in ru'
  },
  ...
};

You can use this information in your templates in this manner:

// static/themes/<project-name>/header/header.bemhtml.js
block('header')(
  content()(function() {
    const i18n = this._i18n[this._lang];
    return [
      {
        tag: 'h1',
    	  content: i18n.title
      },
      {
        tag: 'h2',
        content: i18n.subtitle
      }
    ];
  })
);

Markdown transform

By default Mad Mark transform Markdown to posthtml-tree and apply plugins for semantic and bemjson content. You can use custom posthtml-plugins by config:

module.exports = {
  ...
  posthtmlPlugins: [].concat(
    require('mad-mark').posthtmlPlugins,
    require('custom-posthtml-plugin')
  )
};

Browse PostHTML plugins directory to find them all ;)

CSS transform

You can write CSS for PostCSS and use any plugins for it by config:

module.exports = {
  ...
  postcssPlugins: [
    require('postcss-import'),
    require('bem-grid').postcss(),
    require('postcss-nested'),
    require('postcss-font-magician'),
    require('postcss-browser-reporter'),
    require('postcss-reporter')
  ]
};

Browse PostCSS plugins directory to find them all ;)

Vendors

You can connect any external styles and scripts for any layout or for all of them. For example you can connect Bootstrap in your templates:

block('page').mod('layout', 'any')(
  def()(function () {
    this.ctx.vendors.css = [
      {
        elem: 'css',
        url: 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css'
      }
    ];

    this.ctx.vendors.js = [
      {
        elem: 'js',
        url: '//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'
      },
      {
        elem: 'js',
        url: '//cdnjs.cloudflare.com/ajax/libs/tether/1.3.1/js/tether.min.js'
      },
      {
        elem: 'js',
        url: '//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/js/bootstrap.min.js'
      }
    ];

    return applyNext();
  })
);

All styles will be added to head of your pages and all of scripts will be added to the end of body tag of your pages.

License MIT