npm

Need private packages and team management tools?Check out npm Orgs. »

headman

0.2.0 • Public • Published

headman

Build Status codecov

headman renders and validates all your components and its variations. For maximum convenience, you can define json test data which can be reused from other components. This allows you to work independently from a backend. headman uses consolidate.js internally, hence it automatically supports a lot of rendering engines.

Benefits

  • Make sure all possible variations of your components behave as expected
  • Get your components immediately validated for html and accessibility violations
  • Improve the code of your components by developing them encapsulated
  • No need for a backend that provides data
  • Show stakeholders the state of your development early
  • No overhead in your project (except for the config file)

Overview

Demo

headman.mgrossklaus.de (Code: https://github.com/mgrsskls/headman-demo)

Data concept

Variation inheritance

You can define variations for each of your components. These variations inherit data from the components base definition (if defined), which can then easily be overwritten or extended.

Data inclusion

If you have a component that includes another component, you can easily include the data (or one of its variations) of the latter into the data of including component. That way, it is enough to define data for a specific component once.

Installation

npm install headman or yarn install headman. You can also install it globally via npm install -g headman or yarn global add headman.

Usage

Starting headman

Create a headman.json in your project folder with the following options:

option required/optional type default Note
projectName required String -
srcFolder required String / Setting this value to a folder with nothing else but components is optimal, while using your root folder decreases performance.
srcFolderIgnores optional Array [".git", "node_modules"] Values will be merged with the default value.
cssFiles optional String or Array or Object [] Can either be a string, an array of strings or an object with your NODE_ENVs as key and String or Array as value, e.g.: { development: ["dev/css/index.css"], productions: ["dist/index.css"] }
jsFiles optional String or Array or Object [] See cssFiles.
es6Modules optional Boolean false Adds type="module" to the script tags of your included js files (useful when using unbundled javascript that uses es6 imports)
validations optional Object { html: true, accessibility: true }
reload optional Boolean true Defines if your component automatically reloads after saving.

Start headman with NODE_ENV=(development|production) node node_modules/headman (or NODE_ENV=(development|production) headman if installed globally). This will serve headman at http://localhost:5000. You can change the port with NODE_ENV=(development|production) PORT=1234 node node_modules/headman.

Organizing your components

headman assumes that you have a dedicated folder for each of your components, including a template, css and js file, all named like the folder.

Example

├── src
│   ├── components
│   │   ├── button
│   │   │   ├── button.css
│   │   │   ├── button.hbs
│   │   │   ├── button.js
│   │   │   └── button.json
│   │   └── teaser
│   │       ├── teaser.css
│   │       ├── teaser.hbs
│   │       ├── teaser.js
│   │       └── teaser.json
│   └── templates
│       └── homepage
│           ├── header
│           │   ├── header.css
│           │   ├── header.hbs
│           │   ├── header.js
│           │   └── header.json
│           ├── footer
│           │   ├── header.css
│           │   ├── header.hbs
│           │   ├── header.js
│           │   └── header.json
│           ├── homepage.css
│           ├── homepage.hbs
│           ├── homepage.js
│           └── homepage.json
└── ...

You can call the folders whatever you want and you can nest them as deep as you want.

Note: Files, that are not named the same as the folder they live in, will be ignored.

Creating test data

Create a json file in your component folder with a structure like this:

/* e.g. components/button/button.json */
{
  "data": {
    "label": "Click me",
    "type": "submit"
  }
}
 
/* e.g. components/teaser/teaser.json */
{
  "data": {
    "title": "Teaser 1 title"
  },
  "variations": [
    {
      "name": "Teaser 2",
      "data": {
        "title": "Teaser 2 title"
      }
    }
  ]
}
 
/* e.g. templates/homepage/homepage.json */
{
  "data": {
    "content": "<p>Here goes my content html</p>",
    "teaser": {
      "dataFile": "components/teaser/teaser.json"
    },
    "header": {
      "title": "The page title"
    }
  },
  "variations": [
    {
      "name": "With CTA",
      "data": {
        "cta": {
          "dataFile": "components/button/button.json"
        }
      }
    },
    {
      "name": "With different title",
      "data": {
        "title": "Another page title"
      }
    },
    {
      "name": "With teaser variation",
      "data": {
        "teaser": {
          "dataFile": "components/teaser/teaser.json",
          "variation": "Teaser 2"
        }
      }
    },
    {
      "name": "With overwritte teaser variation",
      "data": {
        "teaser": {
          "dataFile": "components/teaser/teaser.json",
          "variation": "Teaser 2",
          "title": "Overwritten title"
        }
      }
    }
  ]
}

The simplest way is to only have a data key in which you have some key/value pairs.

Additionally, you can create variations. Each entry needs a name key and its own data key in which you overwrite or add variables for your variation. All variables, that are not overwritten, will be inherited by the base data key.

NOTE: The base data key is optional, that means you can also create variations only.

Instead of defining data manually, you can also use data from included components:

The example above uses a dataFile key in templates/homepage/homepage.json in multiple places. headman then uses the data from the given files. If you have variations defined in these files, you can tell headman to use any of them like this:

{
  "teaser": {
    "dataFile": "components/teaser/teaser.json",
    "variation": "Teaser 2"
  }
}

This would use the variation with the name Teaser 2 from components/teaser/teaser.json. If you omit the variation key, it uses the base data of the component.

Note: You can also overwrite values of the imported data (see last variation in the homepage.json example above).

The teaser.json example above would be resolved like this:

/* e.g. template.json */
{
  "data": {
    "content": "<p>Here goes my content html</p>",
    "teaser":  {
      "title": "Teaser 1 title"
    },
    "header": {
      "title": "The page title"
    }
  },
  "variations": [
    {
      "name": "With CTA",
      "data": {
        "cta": {
          "label": "Click me",
          "type": "submit"
        }
      }
    },
    {
      "name": "With different title",
      "data": {
        "title": "Another page title"
      }
    },
    {
      "name": "With teaser variation",
      "data": {
        "teaser":  {
          "title": "Teaser 2 title"
        }
      }
    },
    {
      "name": "With teaser variation",
      "data": {
        "teaser":  {
          "title": "Overwritten title"
        }
      }
    }
  ]
}

headman's concept of inheriting data works best with rendering engines which allow you to pass data objects into an include. Please check the section Rendering engines for limitations with certain rendering engines.

Note: There is no way to create a named variation of a variation.

Global data

You can define global data by creating a data.json in your srcFolder. This data will be merged into your components data. The components data has higher priority, hence overwrites keys with the same name.

Rendering engines

As headman uses consolidate.js, most of its rendering engines should work out of the box.

The following rendering engines have been tested and appear to work without problems:

Due to the nature of their APIs, there might be some constraints.

The following engines do not allow passing data into includes, but the data is globally available:

Because of that, headman's concept of data inclusion does not work. Nevertheless, you can still define all variables manually in your data files. These variables will then be available in your included components.

If you use pug, you could also use a mixin and would then be able to use data inclusion. However, headman is not able to render mixins independently, so you could only render them in the context of the including file.

The following engines do not allow passing data into includes and the data is not globally available:

If you use nunjucks, you could set a variable in your component (e.g. {% set myVar = myData.myVar %} which creates a global variable. This would be available in the included component. Alternatively, you could use a macro, but headman is not able to render these independently, so you could only render them in the context of the including file.

Engines that do not support includes at all:

headman does not work with the following rendering engines:

Validations

By default, components are tested for accessibility and html violations. The accessibility validation uses a local axe-core installation, while the html validation uses an external service from https://validator.w3.org/nu/.

https://validator.w3.org/nu/ has a rate limit of max. 10 requests per minute. If you are updating your components often, you might want to deactivate the html validation, otherwise your IP will be blocked.

Note: Just because the accessibility validation does not result in any errors, it does not mean that your component is accessible.

Good to know

  • Your component is automatically reloaded as soon as you change it.
  • headman does not actually use the css and js files from your component folders. That is because headman cannot know which other components are included in your component, hence does not know which other files to load additionally. If you rely on a build task for your asset files (that might be slower than _headman_), you can turn off the automatic reloading of your component (reload in the options).
  • The start page of headman renders all your components, but without variations. Opening a component either renders an overview of all of its variations or the component directly if it does not have any variations.
  • Folders, that do not include a file with the same name and the given file extension (defined in headman.json), are shown in the menu, but disabled.
  • You can open a standalone view of your component in a new tab by clicking on the small icon on the top right corner.

Things to come (maybe)

  • Manually triggering html/accessibility validation if it is disabled
  • Creating a production build (static html files)
  • CSS validation
  • Global data that is available in every component
  • Support for YAML data files
  • Referencing a template file in the data to be able to render dynamic content (useful for rich text elements e.g.)

install

npm i headman

Downloadsweekly downloads

9

version

0.2.0

license

MIT

homepage

github.com

repository

Gitgithub

last publish

collaborators

  • avatar
Report a vulnerability