https://github.com/webqit/oohtml-cli
A small Command Line utility that automates certain aspects of hand-authored OOHTML-based documents.
https://github.com/webqit/oohtml-cli
bundler html-bundling html-modules oohtml
Last synced: 3 months ago
JSON representation
A small Command Line utility that automates certain aspects of hand-authored OOHTML-based documents.
- Host: GitHub
- URL: https://github.com/webqit/oohtml-cli
- Owner: webqit
- License: mit
- Created: 2022-06-17T04:44:32.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2024-08-02T06:56:52.000Z (over 1 year ago)
- Last Synced: 2024-11-18T11:03:59.908Z (about 1 year ago)
- Topics: bundler, html-bundling, html-modules, oohtml
- Language: JavaScript
- Homepage:
- Size: 5.29 MB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# OOHTML Command Line Interface
OOHTML Command Line is a small utility that automates certain aspects of your hand-authored OOHTML-based documents. You are able to go about coding in absolute free-form with a view to having everything automatically come to shape in one command.
> **Note**
>
This is documentation for `OOHTML-CLI@1.x` - for working with [`OOHTML@2.x`](https://github.com/webqit/oohtml/tree/next). (Looking for [`OOHTML-CLI@0.x`](https://github.com/webqit/oohtml-cli/tree/v0.3.4)?)
## Commands
+ [`oohtml bundle`](#command-oohtml-bundle)
+ [`oohtml config`](#command-oohtml-config)
## Installation
With [npm available on your terminal](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm), run the following command to install OOHTML CLI.
> System Requirements: Node.js 14.0 or later.
```js
npm i -g @webqit/oohtml-cli
```
> The `-g` flag above makes this installation global such that you can directly call `oohtml` from any directory. If you omit it, you may need to prefix each command in this documentation with `npx`; e.g. `npx oohtml bundle`.
## Command: `oohtml bundle`
The **`oohtml bundle`** command is used to automatically bundle static HTML files from the filesystem into *[HTML Module](http://github.com/webqit/oohtml#html-modules)* elements.
### Overview
Here, you are able to place your `.html` files in a directory, or a hierarchy of directories, and have them automatically come together into an HTML `` element, or an equivalent hierarchy of HTML `` elements - in the case of the latter.
Here's a sample layout of HTML files for an application.
```html
public
├── about
│ └── main.html About Page
├── home
│ └── main.html Home Page
└── index.html
```
The goal is to translate the above layout into the following *module* structure...
```html
Home Page
About Page
```
...such that each `` element can be imported into the `index.html` document using the `` element:
```html
FluffyPets
Home Page
About Page
```
The **`oohtml bundle`** command acheives just that! It scans the current directory for those files and, this time, writes them to a new file named `bundle.html`. The bundle contains just the following content:
```html
Home Page
About Page
```
And the `index.html` document is able to link to the bundle as an external resource.
```html
FluffyPets
```
> You can find a working example of [a typical module structure](https://github.com/webqit/oohtml#put-together) right at OOHTML's documentation.
That said, much of this can be customized using *flags* and other options.
### Flags
#### `--recursive`
This flag gets the bundler to restart a new bundling process for nested directories that have their own `index.html` file. The default behaviour is to see them as *subroots* and ignore them.
```html
public
├── about
│ └── main.html About Page
├── home
│ └── main.html Home Page
├── subroot
│ ├── home
│ │ └── main.html Home Page
│ └── index.html
└── index.html
```
With the `--recursiv` flag, the bundler will now recursively bundle the `subroot` directory above. The *subroot* recieves its own `bundle.html` for its contents, and will be omitted from its parent bundle. This gives us the following final structure:
```html
public
├── about
│ └── main.html About Page
├── home
│ └── main.html Home Page
├── subroot
│ ├── home
│ │ └── main.html Home Page
│ ├── bundle.html ...
│ └── index.html
├── bundle.html ... ...
└── index.html
```
#### `--auto-embed=[value]`
This flag gets the bundler to automatically find the `index.html` document at its entry directory and embed the appropriate `` element on it.
> Replace `[value]` with and actual module name; e.g. `pages`.
### Other Options
This utility lets us keep additional configurations to a JSON file, to have a better command-line experience! It expects to locate this file at `./.webqit/oohtml-cli/bundler.json`, relative to its entry directory.
> The `./.webqit/oohtml-cli/bundler.json` file may be edited by hand or from a command line walkthrough using [`oohtml config bundler`](#command-oohtml-config).
```shell
public
├── .webqit/oohtml-cli/bundler.json
```
```json
{
"entry_dir": "./",
"output_dir": "./",
"filename": "./bundle.html",
"plugins": [],
"module_inherits": "",
"module_extends": "",
"remote_module_loading": "eager",
"remote_module_ssr": true,
"public_base_url": "/",
"max_data_url_size": 1024,
"ignore_folders_by_prefix": ["."],
"create_outline_file": false,
"module_def_attr": "def",
"fragment_def_attr": "def"
}
```
For advanced layout scenerios, a nested directory may have its own `.webqit/oohtml-cli/bundler.json` config, and the bundler will honour those configurations down that subtree.
```html
public
├── .webqit/oohtml-cli/bundler.json
├── about
│ ├── deep
│ │ ├── .webqit/oohtml-cli/bundler.json
│ │ └── main.html Deep Page
│ └── main.html About Page
```
#### `[entry_dir]`
This specifies the entry point into the filesystem. The default value is `./`, relative to its host directory. (An absolute path may also be used.)
This is good for pointing the bundler to the actual *`views` (or equivalent)* folder when working from the actual project root.
```html
my-app
├── .webqit/oohtml-cli/bundler.json
├── views
│ └── about
│ └── main.html About Page
```
#### `[output_dir]`
This specifies the output directory for the generated `bundle.html` file. The default value is `./`, relative to its host directory. (An absolute path may also be used.)
This is good for pointing the bundler to the actual *`public` (or equivalent)* folder when working from the actual project root.
```html
my-app
├── .webqit/oohtml-cli/bundler.json
├── views
│ └── about
│ └── main.html About Page
└── public
└── index.html
```
> Typical layouts have the `./public` (or equivalent) directory for both `[entry_dir]` and `[output_dir]`.
#### `[filename]`
This specifies the file name of the output bundle. The default value is `./bundle.html`, which is resolved relative to [`[output_dir]`](#output_dir).
Where the given `.webqit/oohtml-cli/bundler.json` config is for a nested directory, having a non-empty `filename` means that the sub directory is bundled to its own `./bundle.html` file and only *linked* to the parent bundle as an external resource.
```html
public
├── .webqit/oohtml-cli/bundler.json
├── about
│ ├── deep
│ │ ├── .webqit/oohtml-cli/bundler.json
│ │ └── main.html Deep Page
│ └── main.html About Page
```
```html
About Page
```
> To add the OOHTML `loading="lazy"` attribute to linked modules, see [`[remote_module_loading]`](#remote_module_loading) below.
#### `[plugins]`
This specifies an optional list of plugins for the bundling operation. (See [Bundler Plugins](#bundler-plugins).) The default value is an empty array `[]`.
This is good for extending the capabilities of the bundler to custom-load or transform certain file formats that are not natively provided for.
> On the command line, skip this question where not apply. Or follow the prompt to interactively specify plugins, optionally along with their arguments or flags. Entries are asked recursively.
Each entry has the following structure:
+ **`[name]`** - The path to a function, or the name of an installed npm package, that is designed as an [OOHTML CLI Plugin](#bundler-plugins). (The bundler imports plugins using the ES6 `import()` syntax.)
To refer to the bundler's [built-in plugins](#built-ins), like the markdown-to-HTML loader ([`md-loader`](#md-loader)), simply add the prefix `default:` to the plugin's bare name. E.g. `default:md-loader`.
+ **`[args]`** - Optional list of parameters (arguments/flags) for a plugin - each in name/value pair.
> On the command line, skip this question where not apply. Or follow the prompt to interactively specify parameters. Entries are asked recursively.
Each entry has the following structure:
+ **`[name]`** - The name of the parameter as required by a plugin. E.g. `flavor` - in the default [`md-loader`](#md-loader).
+ **`[value]`** - The value of the parameter. E.g. `github` - for the `flavor` parameter above.
#### Advanced Options
#### `[public_base_url]`
This specifies the public path that maps to [`[output_dir]`](#output_dir) on the filesystem. The default value is `/`. The *`src` (or equivalent)* attribute of any automatically-embedded `` element, plus every asset bundled, will be prefixed with this path.
#### `[max_data_url_size]`
This specifies at what file size an image, or other assets, should be bundled with inline *[data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs)*. (See [Bundling Assets](#bundling-assets) below.) The default value is `1024`, in bytes. Assets smaller than this size will be bundled with inline *data URL*.
This is good for having small image files embed their own content instead of having them create additional HTTP requests on the page.
#### `[module_inherits]`
This specifies a space-separated list of *sibling* module IDs that this module inherits, which when set, creates an `inherits` attribute on the module.
```html
```
*See [how the `inherits` attribute is treated](https://github.com/webqit/oohtml#inheriting-modules) in OOHTML.*
#### `[module_extends]`
This specifies a *sibling* module ID that this module extends, which when set, creates an `extends` attribute on the module.
```html
```
*See [how the `extends` attribute is treated](https://github.com/webqit/oohtml#extending-modules) in OOHTML.*
#### `[remote_module_loading]`
This controls the loading mode for remote-loading modules - ``, which when set to `lazy` adds the `loading="lazy"` attribute. The default value is `eager`.
```html
```
> The OOHTML `loading="lazy"` attribute tells a remote-loading module to only load its contents on-demand - on the first attempt to access its contents. (See [how lazy-loading works](https://github.com/webqit/oohtml-ssr#lazy-loading) in OOGTML.)
#### `[remote_module_ssr]`
This controls the "SSR" (Server-Side Rendering) flag for remote-loading modules - ``, which when set, adds the `ssr` boolean attribute. The default value is `false`.
```html
```
> The `ssr` attribute enables resource loading for a given element during Server-Side Rendering. (See [how subresources are treated](https://github.com/webqit/oohtml-ssr#subresource-loading) during Server-Side Rendering.)
#### `[ignore_folders_by_prefix]`
This specifies a comma-separated list of prefixes for certain types of folders to ignore. Folders with a name that begins with any of the listed prefixes are ingnored. The default value is an array of one prefix: `.`.
This is good for excluding certain system folders or *dot directories* like `.git`. *Dot directories* are automatically excluded by the default value.
```shell
my-app
├── .git
├── public
```
#### `[create_outline_file]`
This specifies whether or not to generate a JSON outline of the bundle. The generated file is named after [`[filename]`](#filename); e.g. `./bundle.html.json`. The default value is `false`.
```shell
public
├── bundle.html
├── bundle.html.json
```
This is good for programmatically traversing the bundle structure. Simply `JSON.parse()` the contents of `./bundle.html.json`.
#### OOHTML-Related Options
#### `[module_def_attr]`
This controls the "Module Def" attribute name `def` for the template element and should generally only be changed to align with custom settings in the [OOHTML meta tag](https://github.com/webqit/oohtml#the-polyfill) of the page where the bundle will be used.
#### `[fragment_def_attr]`
This controls the "Fragment Def" attribute name `def` for the template's fragments and should generally only be changed to align with custom settings in the [OOHTML meta tag](https://github.com/webqit/oohtml#the-polyfill) of the page where the bundle will be used.
### Bundling Assets
While HTML files are bundled by reading the file's contents into the bundle, assets, like images, are handled differently. These files are copied from their location in [`[entry_dir]`](#entry_dir) into [`[output_dir]`](#output_dir) when these happen to be two different locations on the filesystem. Copying them to [`[output_dir]`](#output_dir) makes them accessible to HTTP requests. An appropriate HTML element that points to an asset's *public* location is automatically generated as a *module export* in the bundle. This is illustrated below.
We have an image file at `my-app/views/about`, and we have set [`[entry_dir]`](#entry_dir) to `./views` and [`[output_dir]`](#output_dir) to `./public`.
```html
my-app
└── views
├── about
│ ├── image1.png
│ └── main.html About Page
└── home
└── main.html Home Page
```
On running the **`oohtml bundle`** command, our final directory structure will be...
```html
my-app
├── public
│ └── about
│ └── image1.png
└── views
├── about
│ ├── image1.png
│ └── main.html About Page
└── home
└── main.html Home Page
```
...and an `
` element pointing to the *public* location of `image1.png` is added as a *module export* to the bundle.
```html
Home Page
About Page
```
But where the file size of that image is smaller than `1024` - [`[max_data_url_size]`](#max_data_url_size), its contents is *inlined* as [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), and no copying takes place on the filesystem.
```html
Home Page
About Page
```
This way, the browser won't have to load it via a HTTP request. (Cutting down on the number of assets to load should greatly speed up the site's load time.)
### Bundler Plugins
OOHTML CLI plugins are packages that extend the capabilities of the OOHTML Bundler. OOHTML CLI comes with certain plugins built-in, and it also makes it possible to provide custom plugins.
#### Overview
Plugins are functions that are called with each file during the bundling process. Multiple plugins are taken in cascade order where a plugin is responsible for calling the next. This makes for an awesome processing pipeline for each file being bundled.
> This, however, requires thoughtfulness in the order in which these plugins are specified.
By default, the main OOHTML CLI bundler only handles `.html` files, and images, audio and video files. Then it features built-in plugins that extend the list.
#### Built-Ins
##### `md-loader`
The `md-loader` plugin is used to load `.md` (markdown) files into HTML exports, just the way regular HTML files are. It takes an initial step of converting the markdown content into HTML using the [Showdown](https://github.com/showdownjs/showdown) library, then goes ahead to add it to the bundle as a *module export*. Markdown links are automatically resolved to better work as HTML links. And a few other transformations are supported through arguments/flags. (Learn more about specifying arguments/flags for a plugin [here](#plugins).)
###### Arguments/Flags
All parameters are optional.
+ **`outline_generation`** - Set this to a *non-empty* value to generate a JSON outline of the page's content. The generated outline will show up in the meta data for the file in the bundle's overall [JSON outline](#create_outline_file).
+ **`code_highlighting`** - Set this to a *non-empty* value to transform code blocks into stylable markup using the [Showdown-Highlight](https://github.com/Bloggify/showdown-highlight) utility. The transformed code blocks are highlighted in the UI on adding any of the [Highlight.js](https://highlightjs.org/) CSS to the page.
+ **`flavor`** - This equates to any of [Showdown's three flavours](https://github.com/showdownjs/showdown#flavors): `original`, `vanilla`, `github`.
###### Other
+ **Markdown Metadata** - By default, `md-loader` automatically parses any found markdown metadata (defined at the top of the document between ««« and »»» or between --- and ---) into JSON. This metadata object is added as a node to the bundle's overall [JSON outline](#create_outline_file). Below is an example metadata:
```md
---
description: Page description.
---
# Page Title
```
+ **Markdown Tables** - The markdown table syntax is supported by default. Below is an example table:
```md
| h1 | h2 | h3 |
|:------|:-------:|--------:|
| 100 | [a][1] | ![b][2] |
| *foo* | **bar** | ~~baz~~ |
```
###### Usage
The `md-loader` plugin is used by specifying `default:md-loader` in the [`[plugins]`](#plugins) config option.
#### Custom Plugins
Custom Plugins are basic JavaScript modules that *export* a `type` variable (`export const type;`), and a function named `handle` (`export function handle() {}`). The `type` variable is the plugin type, and this should be either `input` or `output`.
###### Input Plugins
*Input* plugins are plugins that are called to load a resource and return its contents.
```js
export const type = 'input';
export function handle( event, args, recieved, next ) {
if ( received || !event.resource.endsWith( '.css' ) ) {
// Or let the flow continue
return next( received );
}
console.log( event.resource ); // File name
console.log( args );
return {
type: 'text/css'
contents: '...',
};
}
```
**Parameters**
+ **`event.resource: String`** - The filename of the resource being processed.
+ **`event.params: Object`** - The [`options` object](#other-options) that the Bundler was initialized with.
+ **`event.indentation: Number`** - A number which represents how deep in the source directory the given resource is. This number is `0` at the root of the source directory.
+ **`args: Object`** - The [`args` object](#plugins) defined specifically for the plugin.
+ **`received: Object`** - The output forwarded (that is, `next()`ed) from the previous plugin in the pipeline, if any.
+ **`next: Function`** - A function that forwards control to the next plugin in the pipeline, if any, and if none, to the default internal *loader*. The `next()` accpets only one parameter, which is received by the next plugin on its `received` parameter.
**Return Schema**
+ **`type: String`** - The MIME type of the resource.
+ **`contents: String`** - The contents of the resource.
###### Output Plugins
*Output* plugins are plugins that are called to transform a loaded resource into its final HTML representation.
```js
export const type = 'output';
export function handle( event, args, recieved, next ) {
if ( received || event.resource.type !== 'text/css' ) {
// Or let the flow continue
return next( received );
}
console.log( event.resource.type ); // text/css
console.log( event.resource.contents ); // ...
console.log( args );
return {
html: '...'
json: {},
};
}
```
**Parameters**
+ **`event.resource: Object`** - The object that represents a loaded resource - as returned by a *loader*.
+ **`event.params: Object`** - The [`options` object](#other-options) that the Bundler was initialized with.
+ **`event.indentation: Number`** - A number which represents how deep in the source directory the given resource is. This number is `0` at the root of the source directory.
+ **`args: Object`** - The [`args` object](#plugins) defined specifically for the plugin.
+ **`received: Object`** - The output forwarded (that is, `next()`ed) from the previous plugin in the pipeline, if any.
+ **`next: Function`** - A function that forwards control to the next plugin in the pipeline, if any, and if none, to the default internal *loader*. The `next()` accpets only one parameter, which is received by the next plugin on its `received` parameter.
**Return Schema**
+ **`html: String`** - The HTML representation of the resource.
+ **`json: Object`** - An optional object that contains metadata about the resource. (This metadata object is added as a node to the overall [JSON outline](#create_outline_file) generated by the bundler.)
###### Usage
Custom plugins are used by specifying their filename in the [`[plugins]`](#plugins) config option. Plugins installed as an npm package are used by specifying their package name.
## Getting Involved
All forms of contributions and PR are welcome! To report bugs or request features, please submit an [issue](https://github.com/webqit/oohtml-cli/issues). For general discussions, ideation or community help, please join our github [Discussions](https://github.com/webqit/oohtml-cli/discussions).
## License
MIT.