@cake-hub/core
v1.0.0-alpha.16
Published
The core rendering engine for cake documentation pages.
Downloads
19
Readme
CAKE showroom core
The package @cake-hub/core
helps you to export markdown documentation to usable HTML documentation. You can then make them available to other users, upload them to your website or use them in other ways. The package provides several configuration options, additional interfaces for custom markdown syntax and an extensive plugin interface.
Configuration
To keep the showroom core flexible, you can make some settings. To adjust the current configuration, you can use the function setOptions
.
const core = require ("@cake-hub/core");
core.setOptions ({
<your settings>
});
By default, the following configuration is set:
{
mode: "production",
projectsDirectory: null,
outputDirectory: null,
pathPrefix: null,
projects: {
configurationFileName: "cake-project.yml",
defaultConfigurationFilePath: path.resolve(__dirname, "./templates/cake-project.yml"),
filterFiles: null, // (filePath, projectConfiguration) => {},
},
logging: {
logToConsole: true,
logToFile: false,
logFilePath: path.resolve(__dirname, "./logs.log"),
},
markdown: {
useHighlightJs: true,
},
}
mode
– describes the actual environment mode (is used by the project commands)projectsDirectory
(required) – the directory where your project's are locatedoutputDirectory
– the directory where the build documentation will be stored at (required, if you do not only use the server middleware)pathPrefix
– can be a string or a method (async ({ projectConfiguration, fileStructure }) => "string"
) returning a string to define a path prepended to every file's locationprojects
– define some basic settings for the projectsconfigurationFileName
– The file name of the configuration file that should be useddefaultConfigurationFilePath
– The path to the default project configuration file. The individual project configuration will be merged with this one.filterFiles
– An optional method to filter special files, that should be ignored by the build process (async (filePath, projectConfiguration) => { return true|false; }
)
logging
– define some basic settings for the logging of project commandslogToConsole
– should the project commands log to the stdout console?logToFile
– should the project commands log to a dedicated log-file?logFilePath
– the location of the log-file, if previous options was set totrue
markdown
– define some basic settings for the markdown behavioruseHighlightJs
– a flag, if the code examples in markdown files should be rendered with highlight.js syntax
To overwrite these settings, you can use the previously named method. You can overwrite all of the default values or only the part that you want to change:
const core = require ("@cake-hub/core");
core.setOptions ({
mode: "development",
pathPrefix: async ({ projectConfiguration, fileStructure }) => {
return projectConfiguration.get("brand") + "/" + projectConfiguration.get("name");
},
logging: {
logToFile: true,
},
});
If you need to access the current configuration of the core, you can simply use the method getOptions
:
const core = require ("@cake-hub/core");
console.log ("current options", core.getOptions ());
Projects (configuration of projects, cake-project.yml)
The various projects whose documentation is to be rendered must all be located in the root directory of the projectsDirectory
. The file cake-project.yml
must be located in the respective project folder in the first hierarchy (unless otherwise configured).
The default configuration of such a file can be found at ./templates/cake-project.yml:
name: default
documentationDirectory: ./
commands: []
fileTypes: []
hiddenPrefixes: []
name
– the name/label of this projectdocumentationDirectory
– the relative path to the folder containing the documentationcommands
– an array of commands that should be run previously to the build of the documentation (eg.commands: [{ mode: "production", name: "build", run: "sleep 2 && ls -ali" }]
)mode
– the mode when the command should be executed (see Configuration)name
– the name of the command to be identifiedcommand
– the bash command that should be executed
fileTypes
– an array with all the extensions that should be made avaliable. if empty all files will be published (eg.fileTypes: [".md", ".jpg", ".html"]
)hiddenPrefixes
– an array containing all file/path prefixes that should be ignored (eg.hiddenPrefixes: ["_", "."]
)
The cake-project.yml
file can be extended with custom additional values. You can later use this values inside your own plugins and markdown components.
Additionally to the fileTypes
and hiddenPrefixes
options you can exclude files inside your documentation folder from beeing published. This can be done with the .cakeignore
file which should be located in the root folder of the project documentation. This file has a similar functionality as the .gitignore
file and works with globs.
**/Ignore.*
dist
**/*.js
Commands
This library provides three different methods:
async initialize ()
– To initialize everything and run initial commands of the projects. When you change any options or plugins after this command being run, you have to re-run it.async build ()
– This command build's the complete documentations and stores it at the configured location.async server ()
– This method is not really a command, but a server-middleware which can be used together with the most common server frameworks.
Initialize
This command must be run before the other two commands can be used. It will prepare everything and initialize the required components. This method runs asynchronously and you should therefore wait until it's execution is finished, before calling any of the other commands.
const { initialize } = require ("@cake-hub/core");
(async () => {
await initialize ();
})();
Build
To build a ready to use documentation you have to run the build ()
command. This command will go through all of your projects and render all markdown files to HTML files.
const { initialize, build } = require ("@cake-hub/core");
(async () => {
await initialize ();
await build ();
})();
Server
If you want to render your documentation on the fly, there is no need to build the entire projects, store them at your hard-drive and serve them to your users. You can just use the server ()
middleware together with your favourite server framework:
const { initialize, server } = require ("@cake-hub/core");
const express = require('express');
(async () => {
await initialize ();
const app = express();
const port = 3000;
app.use("/documentation", await server());
app.all('*', (req, res) => {
res.send('Error: 404!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
});
})();
Custom markdown components
Our core supports the common markdown syntax without extensions. To add custom syntax or components to the functionality, the core provides its own interface via the so-called markdown components. With this you can extend our showroom core as well as our CAKE-CMS with your own components.
To register your own components you can use the registerMarkdownComponent
method as described below:
const { registerMarkdownComponent } = require ("@cake-hub/core");
registerMarkdownComponent (<your component>);
To create your own component you should extend the MarkdownComponentInterface
and overwrite the provided methods with your custom implementation.
The MarkdownComponentInterface
already contains an example, which should help you starting.
const { registerMarkdownComponent, interfaces: { MarkdownComponentInterface } } = require ("@cake-hub/core");
class CustomMarkdownComponent extends MarkdownComponentInterface {
// ### Just basic information about this component ###
id() {
return "example";
}
label() {
return "My first example";
}
fields() {
return [{
name: 'source',
label: 'Link / Href',
widget: 'string',
},
{
name: 'alt',
label: 'Alt text',
widget: 'string'
}];
}
// ### REGEX / matching options to detect this component ###
start(src) {
return src.match(/^:/)?.index;
}
pattern() {
return /^(?::([^:\n]+):([^:\n]*)(?:\n|$))+/;
}
immutableProperties () {
return []; // properties defined in match that will not be rendered, if inline tokens are available
}
match(match, { tokens, lexer, options: { configuration, plugins, markdownComponents, templates }, projectConfigurations, templateEngine, fileStructure, filePath }) {
return {
dt: match[1] ? match[1].trim() : null,
dd: match[2] ? match[2].trim() : null
}
}
level() {
return "inline"; // Is this a block-level or inline-level tokenizer?
// A block-level extension will be handled before any of the block-level tokenizer methods listed above,
// and generally consists of 'container-type' text (paragraphs, tables, blockquotes, etc.).
// - space(string src)
// - code(string src)
// - fences(string src)
// - heading(string src)
// - hr(string src)
// - blockquote(string src)
// - list(string src)
// - html(string src)
// - def(string src)
// - table(string src)
// - lheading(string src)
// - paragraph(string src)
// - text(string src)
// An inline-level extension will be handled inside each block-level token,
// before any of the inline-level tokenizer methods listed above.
// These generally consist of 'style-type' text (italics, bold, etc.).
// - escape(string src)
// - tag(string src)
// - link(string src)
// - reflink(string src, object links)
// - emStrong(string src, string maskedSrc, string prevChar)
// - codespan(string src)
// - br(string src)
// - del(string src)
// - autolink(string src, function mangle)
// - url(string src, function mangle)
// - inlineText(string src, function smartypants)
}
// ### Generate preview / HTML ###
htmlRenderer(data, { getAsset, fields, token, parser, options: { configuration, plugins, markdownComponents, templates }, projectConfigurations, templateEngine, fileStructure, filePath }) {
return `<dt>${data.dt}</dt><dd>${data.dd}</dd>`;
}
// ### Generate source / markdown ###
markdownRenderer (data) {
return `: ${data.dt} : ${data.dd}\n`;
}
// ### Additional marked options ###
childTokens() {
return null;
}
}
registerMarkdownComponent (new CustomMarkdownComponent ());
Custom plugins
Our core builds your documentation without complex configuration or custom development. But to enable custom functionality, we provide a very simple plugin interface which will help you customizating.
To register your own plugins you can use the registerMarkdownComponent
method as described below:
const { registerPlugin } = require ("@cake-hub/core");
registerPlugin (<your plugin>);
To create your own plugin you should extend the PluginInterface
and overwrite the provided methods with your custom implementation.
The PluginInterface
already contains the available methods, which should help you starting.
const { registerPlugin, interfaces: { PluginInterface } } = require ("@cake-hub/core");
class CustomPlugin extends PluginInterface {
async afterInitialization({
configuration,
plugins,
markdownComponents,
templates,
projectConfigurations,
fileStructure,
fileLists,
}) {
return undefined;
}
// Runs just before each markdown file get's rendered to HTML
async beforeMarkdownRendering(markdownContent, {
projectConfiguration,
filePath,
fileStructure,
frontmatter,
destinationPath,
}) {
return markdownContent;
}
// Runs just after each markdown file got rendered to HTML
async afterMarkdownRendering(htmlContent, {
projectConfiguration,
filePath,
fileStructure,
frontmatter,
destinationPath,
}) {
return htmlContent;
}
// Runs just after the templates has been rendered
async afterTemplateRendering(htmlContent, {
projectConfiguration,
filePath,
fileStructure,
frontmatter,
destinationPath,
}) {
return htmlContent;
}
// Runs just before all other files expect markdown-files get copied / streamed
async beforeFileCopy({
projectConfiguration,
filePath,
fileStructure,
}) {
return true; // <boolean> or <string> | <Buffer> | <TypedArray> | <DataView> | <Object> | <AsyncIterable> | <Iterable> | <Stream>
}
// Runs just after the build has been finished (will not execute when using the `server ()` middleware)
async afterBuild({
projectConfigurations,
fileStructure,
}) {
return undefined;
// Will not be run with server middleware
}
}
registerPlugin (new CustomPlugin ());
Custom templates
Our core builds your documentation without complex configuration or custom development. But to provide you customization for the UI and how the documentation should look like in the end, we provide you a tempalte interface that you can use.
To register your own templates you can use the registerTemplate
method as described below:
const { registerTemplate } = require ("@cake-hub/core");
registerTemplate (<your template>);
To create your own template you should extend the TemplateInterface
and overwrite the provided methods with your custom implementation.
The TemplateInterface
already contains the available methods, which should help you getting started.
const { registerTemplate, interfaces: { TemplateInterface } } = require ("@cake-hub/core");
class CustomTemplate extends TemplateInterface {
static get Options() {
return {
isStackable: true, // option to define, it there could be multiple templates stacked into each other, if precondition matches in multiple templates
};
}
static async template(slot, { projectConfiguration, filePath, relativePath, frontmatter, markdownContent, fileStructure, configuration }) {
return `
<html>
<head>
<title>CAKE</title>
</head>
<body>
<main>
${slot}
</main>
</body>
</html>
`;
}
static async precondition({ projectConfiguration, filePath, relativePath, frontmatter, markdownContent, fileStructure }) {
// Extend this logic, to have conditional templates
return true;
}
}
registerTemplate (CustomTemplate);
You can register mutliple templates which can also be used in combination. The option isStackable
indicates, if this template is able to stack with other templates. This means, if the option is set to true
, this tempalte can be rendered inside other templates, or other templates can be rendered inside this template. Otherwise, if the option is set to false
, no other template will ever be rendered inside this template.
The TemplateEngine
will check for each markdown file if the precondition
runs successfully (returning true
) and if so, it will render the template arround the converted markdown content. If isStackable=false
, the TemplateEngine
will stop at the first match and return the HTML content. If isStackable=true
the TemplateEngine
will continue checking the other precondition
s and render the template arround the markdown content and all previous templates, until one template has set option isStackable=false
or all templates has been checked.
The TemplateEngine
will start with the last template that has been registered and finish with the first one being registered (which always is the default TemplateInterface
of the core).
Interfaces
In addition to the interfaces already mentioned, the core provides further interfaces that can be used freely. These are only listed and briefly described below. To understand the exact structure, please have a look at the source files.
FileStructureInterface
– This interface holds a list of files, that can be exported to structures mapping the file-system hierarchy.FrontmatterInterface
– This interface renders or parses frontmatters of markdown files and provides an api to read or change the values.MarkdownComponentInterface
– This interface is used to extend the default markdown render behavior.PluginInterface
– This interface is used to extend the default documentation building behavior.TemplateInterface
– This interface is used to extend or change the default UI of the build documentation.
const {
interfaces: {
FileStructureInterface,
FrontmatterInterface,
MarkdownComponentInterface,
PluginInterface,
TemplateInterface,
},
} = require ("@cake-hub/core");
Modules
In addition, the core exports some helpful modules that are also used internally and provide functionality for a specific topic.
CommandManager
– This module helps you running bash commands on your local machine and manage the logs during execution.ConfigurationParser
– This module helps you providing configurations with default options that can be overwritten or read.FileManager
– This module helps working with the file-system. Reading, Writing, Parsing files or check if it is a directory or if it even exist.LoggingModule
– This module helps log to the console or even into a log-file.MarkdownInterpreter
– This module helps parsing markdown files and convert them into useful HTML.Queue
– This module helps you queueing asynchronous commands into a queue and executing them in parallel.TemplateEngine
– This module helps managing different templates, traverse them and combining them depending on theprecondition
.
const {
modules: {
CommandManager,
ConfigurationParser,
FileManager,
LoggingModule,
MarkdownInterpreter,
Queue,
TemplateEngine,
},
} = require ("@cake-hub/core");
Hint: Custom pages and content
Custom content pages that are not in markdown-format should be created just before the documentation get's build so that the files will be made available through the build process. Another option would be to create these pages afterwards and make them available at the right place afterwards.
Contact / Feature requests
You have any questions, feature requests or need furhter help? Feel free to get in touch with us!