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

@namgoe/gcmstatic

v0.0.2

Published

Statically generated GCMS lookalike

Downloads

1

Readme

gcmstatic

A GCMS lookalike based on the Metalsmith static site generator.

Quick start

  1. Fork this project by clicking the Fork button on the project's GitLab page.

  2. Clone your fork, and add this project as a remote (makes it easier to track updates):

    $ git clone https://gitlab.gwdg.de/<USER>/gcmstatic.git
    $ git remote add upstream https://gitlab.gwdg.de/nam/gcmstatic.git
  3. Install Node.js version at least 7.10, either via the linked website, or via your distribution's package manager. You can also install it locally into your home directory using NVM.

    Note: While Node.js does run on Windows, gcmstatic has not been tested there yet. In particular, differences in the path separator (/ and \) may lead to problems when processing the source directory hierarchy.

  4. Run npm install from the project's root directory to fetch all dependencies.

  5. Add some content to the src directory:

    • src/index.de.md

      ---
      title: Willkommen
      ---
      
      Sehr informativer Inhalt hier.
    • src/index.en.md

      ---
      title: Welcome
      ---
      
      Very informative content here.

    Note: As a general rule, you should likely not modify any files outside the src directory. If we make changes the lib, merging the updates can otherwise become arbitrarily complex over time. On the other hand, we will try and take care not to break existing site setups in src. If you need functionality that is not available via means described below, please tell us.

  6. From the project's root directory, run

    ./generate

    The generated website will be written to the build directory. gcmstatic is a static site generator; it will generate a set of static HTML files which can be directly opened in a browser or pushed to the document root of a web server.

    For development, you can also run

    ./generate --serve

    This will start a local web server on http://localhost:8080. It will also monitor files for changes, rebuild the website if needed, and tell the browser to reload.

    Note: The HTML generated by generate --serve contains additional javascript for the livereload functionality. Make sure to always run generate without --serve once before pushing to a web server to get rid of the script. It may also be useful to completely remove the build directory before the final generate, just to be sure.

    Another note: You will still not be able to view the generated website without a network connection, as some resources (jQuery, Bootstrap, ...) are fetched from external servers. We will (probably) add an option for completely offline webpages later.

Directory structure

The structure of src is mostly mirrored in build. Markdown files (.md) will be processed to .html, dotfiles removed, and some other file types will be processed and removed as well (see below for details).

The biggest difference is that all language-specific files will be moved to separate directory hierarchies. Given these an src directory like

index.de.md
index.en.md
foobar.de.md
subpage/
  index.de.md
  index.en.md
img/
  logo.png

the build directory will contain

de/
  index.html
  foobar.html
  subpage/
    index.html
en/
  index.html
  subpage/
    index.html
img/
  logo.png
static/
index.html

The static subdirectory contains stylesheets and scripts mosyly copied from GCMS. The top-level index.html is (almost) identical to de/index.html and serves as the default landing page.

Navigation sidebar

All pages by default have a navigation sidebar on the right hand side consisting of up to three boxes containing

  • links to all pages in the same directory,
  • links to the index.html files of all subdirectories, and
  • optional supplementary links that can be configured in metadata (see below).

The subdirectories of the current language's top-level directory (i.e. the subpage directories in the example above) are listed in the page header instead of the sidebar.

Links

In-site links in Markdown or HTML should usually be written relative to the current directory so as not to break when moving files to the language-specific subdirectories. If you use absolute links, make sure to take the target's final location into account.

As a final processing step, after the directory structures are fixed, all absolute links are automatically rewritten to relative links. This makes it possible to serve the generated site from a subdirectory of the web server or your local drive.

Metadata

Files can be preceded by a front matter, which is a block of YAML data delimited by lines containing only ---. YAML is a simple language for structured data, consisting essentially of lists, key-value-maps and some elementary data types like strings and numbers. To quickly learn about the basics, Learn YAML in Y minutes is a good resource.

The front matter can contain arbitrary data. Some keys have special meaning, but all keys defined here will are available when processing the input files via the template engine (see Templates below).

defaults.yaml

In addition to specifying metadata in the front matter, the source will be searched for files named defaults.yaml. These should contain YAML maps, the keys of which are taken as shell-style glob patterns, and the values are again maps which are applied to all files matching the pattern relative to the subdirectory the defaults.yaml is located in, e.g.

"*.md":
  key1: val1

"**/*.txt":
  key2: val2

will set key1 to val1 in all .md files, and key2 to val2 in all .txt files in all subdirectories (**/ matches arbitrarily many subdirectories).

If both a key is specified both in the front matter and a defaults.yaml, the former takes precedence. On conflicts between multiple defaults.yaml files, the one further down the directory hierarchy wins.

Special properties

The following file properties have special meaning. Some of them can be set to control how the file contents will be processed, others are automatically generated to be used by templates if needed.

  • layout

    The content generated from each file can optionally be wrapped in a layout. Currently, the only available layout is default, which is enabled for all Markdown and HTML files. If unset, the generated content will be used as-is.

    The default layout uses some additional properties.

    • title

      Sets the page title.

    • navtitle

      An alternative title to be used in the navigation sidebar. If unset, title will be used.

    • sidebar

      Whether to show the sidebar at all. Defaults to true.

    • links

      A list of supplementary list of links to be displayed in the sidebar. This should be a YAML list of strings. These strings will be inserted into the sidebar verbatim, so they should be valid HTML.

    • stylesheets

      A YAML list of additional CSS stylesheets to be loaded in the generated page header.

    • mathjax

      Add a <script> header to fetch MathJax from external servers. In combination with the already-installed MathJax Markdown plugin, this allows you to write LaTeX math in .md files (or .html files, if you really want to).

      The MathJax scripts are somewhat heavy, so they should only be activated on pages that actually need this.

    • livereload

      Add a script supporting automatic page reloading when using generate --serve. Defaults to true, and only has an effect if the --serve option is actually given. There should be little reason to set this to false.

  • template

    Setting this to false causes the template engine (see below) to ignore this file. Defaults to true for Markdown and HTML, false otherwise.

  • partial

    Declares the file to be a partial template (see below). The value should be the intended partial name, or true, in which case the name is derived from the filename up to the first dot. The file itself will not appear in the generated output. All other properties of the file are ignored. Defaults to false.

  • bibname

    Declares the file to be a BibTeX collection. The value is processed just as the partial parameter above. See below for more details on the BibTeX plugin.

    The plugin will remove the file from the generated output. If you want to also make a BibTeX file available for download, you will have to include it a second time.

  • data

    Used by the data loader plugin. Can be set to the (relative) path of a supplementary YAML or JSON file, a list of such paths, or a map with such paths as values. The files will be loaded and inserted in place of the respective paths.

    This does have some conceptual overlap with the defaults.yaml mechanism. Its main usecase is to have an external script generate some additional data which can be processed by the template.

  • contents, stats

    Auto-generated, mostly for internal use; these properties should not be assigned otherwise.

Multiple languages

There are some additional properties that govern the multiple language support. Their behaviour is slightly more complex. For the most part, using files ending in .de.md and .en.md (or ...html) should just work.

  • lang

    This is the language of the file and determines where in the directory hierarchy the genreated file ends up. It defaults to en for all .en.md and .en.html files, and to de for all other .md and .html files (its probably a good idea to use .de.md nevertheless). All other files do not have lang set by default and will not be moved to the language-specific directories.

    lang can also be set to a list of languages. In this case, multiple copies of the file will be generated, one for each entry. When processing the individual templates, lang will be set to the respective language.

    Finally, lang can be map from languages to addtional language-specific metadata. Processing will be performed as for the list case above, but with the respective language-specific metadata available. Example:

    ---
    lang:
      de:
        title: Deutscher Seitentitel
      en:
        title: English page title
    ---
    
    ...
  • basename

    The file name of the generated file in the language-specific directory. Defaults to the file name itself with .${lang}. removed if lang is set, and to the plain file name otherwise. Files are regarded as different versions of the same page if they have the same path (inside the language-specific directory) and basename, and corresponding links below the header will be generated.

  • langinfo

    Auto-generated property that contains supplementary language information from the site's meta.yaml (see below).

  • lang_versions

    Auto-generated map from languages to versions of the same page in a different language. This is mainly used to generate the "other language" links below the page header and probably not really useful otherwise.

Standard settings

The default properties, except for the ones auto-generated during processing, are set from lib/defaults.yaml. Here are its contents (at the time of writing this README):

'**/*.de.{md,htm,html}':
  lang: de

'**/*.en.{md,htm,html}':
  lang: en

---

'**':
  livereload: true
  sidebar: true

'**/*.{md,htm,html}':
  layout: default
  template: true
  lang: de

The --- ensures that the lower part is applied after the upper part, so the upper part takes precedence. Otherwise, the order of applying the lang properties would be undefined.

meta.yaml

Finally, some configuration options are site-wide rather than page-specific. The defaults of these are set in lib/meta.yaml, which can be overridden in src/meta.yaml. Here they are:

langs:
  de:
    name: Deutsch
    sitename: Institut für Numerische und Angewandte Mathematik
  en:
    name: English
    sitename: Institute for Numerical and Applied Mathematics

indexlang: de

All of these are available in templates as well, but get overriden by site-specific settings. The applicable branch of the the langs property is availabe as langinfo in templates. indexlang determines the language of the top-level index.html.

If you want to support a third language, adding it is only a matter of extending langs and various glob patterns in defaults.yaml. de and en are not hard-coded otherwise.

Finally, some plugins may be configured in meta.yaml. Currently, this only applies to BibTeX.

Markdown

gcmstatic used the markdown-it Markdown parser, which is CommonMark compliant and extensible by plugins. If you never used Markdown, the plain text of this README or markdown-it's homepage should give you an idea.

markdown-it is extensible via plugins, of which we are currently using the following ones.

MathJax

This was already mentioned for the mathjax file property above. It allows you to use a subset LaTeX math via MathJax.

Decorate

This allows you to add HTML classes, id's and attributes to Markdown elements, which can be useful in combination with custom CSS (see the stylesheets property above) or Bootstrap (see below).

Note that you can also include most HTML constructs directly in Markdown, in case this plugin does not suffice.

BibTeX

gcmstatic includes a BibTeX plugin, which adds some template helpers (see the Templates section below) to include bibliography listings in a customizable format on a page, and to cite references inline. Configuration is done via the bibtex key in meta.yaml. Collections (i.e. bibtex source files) can either be configured there, or via the bibname file property desctibed above.

Bootstrap

GCMS' responsive page layout is based on the Bootstrap framework, and gcmstatic inherits this dependency. For documentation, refer to the linked page.

Presence of the framework should be mostly transparent, as it is handled in the default layout, but you may use it for your own purposes, for example to create a responsive multi-column layout. The layout wraps the page content in a .container-fluid, so all you need to do is to add a row and two columns:

---
title: Column example
---

<div class="row">
<div class="col-sm-6">

## First column

</div>
<div class="col-sm-6">

## Second column

</div>
</div>

Note: The default layout adds the page title as an <h1>, so in-page headings should mostly be <h2> (i.e. ## in Markdown) or higher.

Templates

gcmstatic uses the Handlebars template engine on all files having a template property. The basics are rather simple. Variable expansion happens between {{ and }}, so {{title}} expands to the page title set in the front matter. Conditionals are written like

{{#if someproperty}}It's set.{{else}}It's unset.{{/if}}
{{#unless someproperty}}It's set.{{else}}It's unset.{{/unless}}

where in both cases the {{else}} branch is optional. Iteration over lists and maps can be done by

{{#each somelist}}{{somefield}}{{/each}}

which expands to the the somefield properties of all list elements in turn.

For debugging, there is a log helper:

{{log something}}

outputs the value of something to the console on expansion.

For full documentation, refer to the website linked above.

Partials

A partial is a "non-evaluated" template that can be included in other templates and is expanded in the context of the containing template (by default). Partials in gcmstatic are registered using the partial property (see above for details), and are included by

{{> somepartial}}

Parials can also receive other contexts, additional variables or entire template blocks as parameters, which allows for some pretty flexible trickery.

Helpers

Handlebars by itself is very minimal and delegates most tasks to helpers, which can be arbitrary Javascript functions. Registering helpers is (somewhat intentionally) not possible without modifying the lib directory. If you need some helper functions, please tell us.

Currently, our custom helpers only include elementary logic operations:

  • or

    Takes an arbitraty number of arguments and evaluates to first non-"false" one, otherwise to undefined (which expands to nothing in templates). "false" has a somewhat broad definition; it's the same one Handlebars' own if helper uses.

    {{or false someproperty}}

    expands to whatever someproperty would expand to. or can also be used in conditionals:

    {{if (or a b)}} ... {{/if}}

    and as a block helper, i.e.

    {{#or a b}} ... {{/or}}

    In the latter case, it evaluates the block in the context of the first non-"false" argument.

  • and

    Evaluates to the last argument if all arguments are non-"false", and undefined otherwise. The rest of the behaviour is the same as for or.

  • eq and eqw

    These correspond to Javascripts' === and ==, respectively. If unsure about the difference, eq is the one you want.

    {{if (eq key1 key2)}} ... {{/if}}

    does the obvious thing.

  • not

    Does what you think it does.

Updating

TODO

If you do change files outside src, it would be great if you would tell us about it or even create a merge request, so that your changes are made available to others, and so we can make sure not to break them on updates.

Bugs

Found a bug? Need some additional functionality, template helpers, markdown plugins or custom javascript? Tell us or create an issue on GitLab.