@per1234/generator-kb-document
v1.0.0
Published
Yeoman generator for creating documents in a Markdown file-based knowledge base.
Downloads
197
Readme
@per1234/generator-kb-document
This is a Yeoman generator that creates new documents and supplemental files in a Markdown file-based knowledge base.
The generator can be configured to prompt the user for arbitrary information, which can be referenced in the document template in order to populate the created document with basic content.
Although it is configurable enough to make it a general purpose tool for developing knowledge bases on any subject matter, the generator is opinionated on the structure of the knowledge base.
Project website: https://github.com/per1234/generator-kb-document
Table of contents
- Installation
- Configuration
- Generator Usage
- Example
- Knowledge Base Structure
- Contributing
Installation
Install the npm packages for Yeoman and the generator as development dependencies of your project:
npm install --save-dev yo @per1234/generator-kb-document
Configuration
Generator Configuration File
Yeoman generators are configured by a JSON file named .yo-rc.json
.
Create a file named .yo-rc.json
in the root of your knowledge base project and open it in any text editor.
This generator is configured via the keys under the @per1234/generator-kb-document
object in the .yo-rc.json
file:
{
"@per1234/generator-kb-document": {
<generator configuration>
}
}
For a better understanding of the configuration file format and functionality, see the Example section.
kbPath
The path of the knowledge base folder.
promptsConfigurationPath
The path of the prompts configuration file.
sortFrontMatter
Default value: true
Boolean value to configure whether the items in the generated front matter document should be sorted in lexicographical order.
documentPrimaryTemplatePath
The path of the template for the knowledge base document primary file.
documentSupplementTemplatePath
The path of the templatefor knowledge base document supplemental files.
universalFrontMatter
Default value: {}
Object defining data that should be added to the front matter of every document the generator creates.
For example, if you set the universalFrontMatter
like so:
"universalFrontMatter": {
"foo": "bar"
}
The front matter document available for use in your template via the kbDocumentFrontMatter
variable will contain this content:
---
foo: bar
<...>
This is static data. An example usage would be configuring tools that consume Markdown files and recognize special front matter keys.
You can also use the prompts configuration file to configure prompts so that front matter data will be set according to the answers provided during the document creation process.
For information on front matter, see the Informational Structure section.
Generator Configuration JSON Schema
A JSON schema for validation of the generator configuration is provided here.
Prompts Configuration File
The prompts configuration file defines the additional prompts that will be presented when the generator is run. The prompt names can be referenced in the document file template, which will cause the generator user's answer to the prompt to be filled in the generated knowledge base document. This allows the basic content of the knowledge base document to be efficiently populated in a standardized format at the time of document creation.
The prompts configuration file is written in the JavaScript programming language programming language.
The code must export an array of prompt configuration objects as the default export:
const prompts = [
<prompt configuration objects>
];
export default prompts;
The generator displays the prompts to the user in the order of the elements in the array.
The prompt configuration object contains the following properties:
inquirer
The inquirer
property is an Inquirer Question
object. The format of the Question
object is documented here:
https://github.com/SBoudrias/Inquirer.js/tree/main/packages/inquirer#question
The style of the prompt is configured by the Question.type
property. The prompt types are explained here:
https://github.com/SBoudrias/Inquirer.js/tree/main/packages/prompts#prompts
{
inquirer: {
<Inquirer Question object>
},
<...>
},
operations
Default value: ["new", "supplement"]
The operations
property is an array of strings which specify on which operations the generator should present the prompt to the user.
The user
{
inquirer: {
<Inquirer Question object>
},
operations: [
"new",
"supplement",
],
<...>
}
new
The prompt should be presented when the user selected "Create new document" from the built-in "Which operation would you like to perform?" prompt.
supplement
The prompt should be presented when the user selected "Add a supplement file to an existing document" from the built-in "Which operation would you like to perform?" prompt.
usages
Default value: ["content"]
The usages
property is an array of strings which specify how the generator should make the prompt answer available for use in the document file template:
{
inquirer: {
<Inquirer Question object>
},
usages: [
"content",
"front matter",
],
<...>
}
content
The answer can be referenced by the value from the inquirer
object's name
property anywhere in the document file template.
front matter
The answer will be included in the generated front matter document, which can be referenced as kbDocumentFrontMatter
in the document file template. The answers to all prompts with usages
property that contains "front matter"
will be merged into the front matter document.
For information on front matter, see the Informational Structure section.
❗ If you include "front matter"
in the usages
property, you must also set the frontMatterPath
property.
frontMatterPath
The frontMatterPath
property is a string that specifies the data path in the front matter document under which the answer should be added.
The JSON pointer notation is used:
https://datatracker.ietf.org/doc/html/rfc6901
ⓘ The frontMatterPath
property is only relevant when the usages
property contains "front matter"
.
Object as Path
With the following prompt configuration object:
{
frontMatterPath: "/tags",
inquirer: {
type: "rawlist",
name: "someTag",
message: "Some tag:",
choices: [
{
name: "Foo",
value: "foo",
},
{
name: "Bar",
value: "bar",
},
],
},
usages: ["front matter"],
}
And the following document file template:
<%- kbDocumentFrontMatter %>
If the user answers "Foo" to the "Some tag:" prompt, the value of the tags
key in the root object (AKA "mapping in YAML language terminology) will be set to the answer value foo
. The front matter in the generated document will contain:
---
tags: foo
---
Array as Path
In the example above, the prompt is being used to assign a categorical tag to the document. In this case we actually want to append the answer value as an element in an array rather than setting the value of the key to a single string.
In this case we must instead set the property to "/tags/-"
:
frontMatterPath: "/tags/-"
If the user answers "Foo" to the "Some tag:" prompt, the front matter in the generated document will contain:
---
tags:
- foo
---
Answer Arrays
A prompt might produce answer values in either of two data formats:
- Single answer
- Answer array
In the case of an answer array, if we used /tags/-
as in the above example (which is appropriate for prompt types that produce a single answer value), we would end up appending the array as an element in the tags
array, giving an unintended front matter data structure like this:
---
tags:
- - foo
- bar
---
The intended data structure will be obtained by instead specifying the target key:
frontMatterPath: "/tags"
Which will result in the front matter in the generated document having a structure like this:
---
tags:
- foo
- bar
---
Just as with the single answer prompts, the answers from prompts that produce an array of answers will be merged into any existing data that was added to the front matter by previous prompts.
For a better understanding of the prompts configuration file format and functionality, see the Example section.
processors
Default value: []
The processors
property is an array of processor configuration objects which specify optional processing operations that should be performed on the answer to the prompt before making making the value available for use in the document file template:
{
inquirer: {
<Inquirer Question object>
},
usages: [
"content"
],
processors: [
{
<processor configuration object>
},
],
<...>
}
The processing operations will be applied in sequence, following the order from the processors
array.
processor: "csv"
It may be necessary for a single prompt to accept multiple answer values. When the set of possible answer values is fixed, the checkbox
prompt type can be used to handle this nicely. Unfortunately Inquirer doesn't provide any equivalent prompt type for accepting multiple free text answer values. In this case, the best solution will be to use the input
prompt type and pass the set of values in a string that has a delimiter-separated format (commonly referred to as CSV).
This processor handles the parsing of a delimiter-separated answer value, converting it to an answer array.
delimiter
Default value: ","
This processor converts the string answer value to an array by splitting it on delimiters. The delimiter can be configured via the processor configuration object's delimiter
property:
{
processor: "csv",
delimiter: ",",
}
processor: "join"
The join
processor transforms an answer array into a single string by concatenating all the elements.
separator
Default value: "\n"
The string to insert between the elements can be configured via the processor configuration object's separator
property.
{
processor: "join",
separator: "\n",
}
processor: "kb-link"
The kb-link
processor transforms an answer value into a link to the document of that name in the knowledge base.
{
processor: "kb-link",
}
When the input is an answer array, each of the elements in the array is transformed into a link.
processor: "sort"
The sort
processor sorts an answer array in lexicographical order.
{
processor: "sort",
}
processor: "template"
The template
processor transforms an answer value according to the provided template.
The template is written in the EJS template language:
https://ejs.co/
The answer value is available for referencing in the template as answer
.
{
processor: "template",
template: "The answer value is <%- answer %>",
}
When the input is an answer array, the processor transforms each of the elements in the array.
Prompts Configuration JSON Schema
A JSON schema for validation of the prompts configuration is provided here.
Document File Template
This file is the template for the knowledge base document files that will be created by the generator.
It is written in the EJS template language:
https://ejs.co/
❗ The EJS <%- reference %>
tag format should be used in the template rather than the <%= reference %>
format. The latter is intended for use in generating HTML code and is not appropriate for our use of generating Markdown.
For a better understanding of the document file template format and functionality, see the Example section.
Built-in Prompts
In addition to the custom prompts the user defines in their prompts configuration file, the generator always displays a series of prompts for information that is used by the generator.
The answers to these "built-in" prompts are available for use in the template just the same as the user-defined prompts.
Operation
The answer to the "Which operation would you like to perform?" prompt is available for use in the template via the kbDocumentOperation
variable:
<%- kbDocumentOperation %>
- If the user chose the "Create new document" option, the value will be
new
. - If the user chose the "Add a supplement file to an existing document" option, the value will be
supplement
.
Document Title
The answer to the "Knowledge base document title" prompt is available for use in the template via the kbDocumentTitle
variable:
<%- kbDocumentTitle %>
It is recommended to use this as the document's H1 heading:
# <%- kbDocumentTitle %>
Supplement Title
If the user selects the "Add a supplement file to an existing document" option from the "Which operation would you like to perform?" prompt, they will also be presented with a "Supplement title" prompt. The answer to this prompt is available for use in the template via the kbDocumentSupplementTitle
variable:
<%- kbDocumentSupplementTitle %>
It is recommended to use this as the document supplement file's H1 heading:
# <%- kbDocumentSupplementTitle %>
Prompts from Prompts Configuration File
"content"
Prompts
If a prompt defined in the prompts configuration file has "content"
in its usages
property, you can use the answer by referencing the value of the name
property of the prompt configuration inquirer
object in the template:
<%- <prompt name> %>
Front Matter
Front matter data can come from two sources:
- The
universalFrontMatter
key in the generator configuration file. - Prompts defined in the prompts configuration file that have
"front matter"
in theirusages
property.
This data is used to populate a single generated front matter document. That front matter document is available for use in the template via the kbDocumentFrontMatter
variable:
<%- kbDocumentFrontMatter %>
For information on front matter, see the Informational Structure section.
Answer Arrays
The checkbox
Inquirer prompt type allows the user to select multiple answers from the prompt. For this reason, it produces an array of answer values rather than a single value as is done by other prompt types.
Arrays of answer values are also produced by the csv
processor.
There are special considerations for handling this distinct answer data type:
ⓘ Inquirer doesn't provide a prompt type for obtaining multiple free text answers. If you need this capability in your project, the generator can be configured to extract multiple values from a single answer in delimiter-separated format. See the information here for details.
Generator Usage
Create New Document
This procedure is used to add a new document to the knowledge base.
- Run the following command from a terminal in a path under the knowledge base project:
npx yo @per1234/kb-document
- The "Which operation would you like to perform?" prompt will be displayed in the terminal. Select the "Create new document" option and press the Enter key.
- The "Knowledge base document title" prompt will be displayed in the terminal. Type the title you want to use for the new knowledge base document and press the Enter key.
- If you defined additional prompts in the prompts configuration file, they will be presented in turn. Answer these prompts.
- At the end of the process you will see an "A new document has been created at ..." message printed in the terminal. Open the file at the path shown in the message. You will see the file has been populated according to the document file template and your answers to the prompts.
- Manually fill in the document content.
Add a Document Supplement File
This procedure is used to add a supplement file to an existing knowledge base document. Knowledge base document supplements are used to split lengthy document content into multiple files (as opposed to having it all in the document primary file).
- Run the following command from a terminal in a path under the knowledge base project:
npx yo @per1234/kb-document
- The "Which operation would you like to perform?" prompt will be displayed in the terminal. Select the "Add a supplement file to an existing document" option and press the Enter key.
- The "Knowledge base document title" prompt will be displayed in the terminal. Type the title of the existing knowledge base document to which you want to add a supplement file and press the Enter key.
- If you defined additional prompts in the prompts configuration file, they will be presented in turn. Answer these prompts.
- At the end of the process you will see an "A knowledge base document supplement file has been created at ..." message printed in the terminal. Open the file at the path shown in the message. You will see the file has been populated according to the document file template and your answers to the prompts.
- Manually fill in the document content.
Answer via Command Line Flag
As an alternative to providing answers via the human-friendly prompts interface, the generator supports providing answers via command line flags passed to the generator invocation:
npx yo @per1234/kb-document --<prompt name>=<answer>
ⓘ You can provide multiple answers to a single prompt (for prompt types that produce an answer array) by passing the flag multiple times:
npx yo @per1234/kb-document --foo="Pippo" --foo="Pluto"
Providing answers via command line flags can be useful for automated use cases for which the generator's interactive prompt interface is not appropriate.
The built-in prompts have the following names:
- Which operation would you like to perform?:
kbDocumentOperation
- Knowledge base document title:
kbDocumentTitle
- Supplement title:
kbDocumentSupplementTitle
As for additional user-configured prompts, the prompt name is defined by the name
property of the Inquirer Question
object.
Example
It might be helpful to take a look at a full example of a configuration and usage of the generator.
Let's say you have a knowledge base project with this file structure:
<project folder>/
├── .yo-rc.json
├── generator-kb-document/
│ ├── prompts.js
│ └── template.ejs
├── my-kb/
│ │
│ ...
...
.yo-rc.json
:
{
"@per1234/generator-kb-document": {
"kbPath": "my-kb",
"promptsConfigurationPath": "generator-kb-document/prompts.js",
"templatePath": "generator-kb-document/template.ejs"
}
}
prompts.js
:
const prompts = [
{
frontMatterPath: "/tags/-",
inquirer: {
type: "rawlist",
name: "topic",
message: "Topic:",
choices: [
{
name: "Cooking",
value: "cooking",
},
{
name: "Games",
value: "games",
},
],
},
usages: ["front matter"],
},
{
inquirer: {
type: "input",
name: "homePageUrl",
message: "Home page URL:",
},
usages: ["content"],
},
];
export default prompts;
template.ejs
:
<%- kbDocumentFrontMatter %>
# <%- kbDocumentTitle %>
Home Page: <%- homePageUrl %>
The following generator run:
$ npx yo @per1234/kb-document
? Knowledge base document title: My Document
? Topic: Games
? Home page URL: https://example.com
A new knowledge base document has been created at C:\my-kb-project\my-kb\my-document\doc.md
will result in the following file structure:
<project folder>/
├── .yo-rc.json
├── generator-kb-document/
│ ├── prompts.js
│ └── template.ejs
├── my-kb/
│ ├── my-document/
│ │ └── doc.md
│ │
│ ...
...
And the generated <project folder>/my-kb/my-document/doc.md
having the following content:
---
tags:
- games
---
# My Document
Home Page: https://example.com
Knowledge Base Structure
File Structure
The knowledge base is composed of a collection of files, which have the following structure:
<knowledge base folder>/
├── <document title slug>/
│ ├── doc.md
│ ├── <supplement title slug>.md
│ ...
...
- <knowledge base folder>/: This folder is the container for all the knowledge base content files.
- <document title slug>/: This folder is the container for all the document content files. The folder name is a normalized version of the document title.
- doc.md: The knowledge base document primary file, written in the Markdown markup language.
- <supplement title slug>.md: A knowledge base document supplement file, the name of which is a normalized version of the supplement title. Document supplements are used to split lengthy document content into multiple files.
Informational Structure
Although not part of the official Markdown specifications, it is common for Markdown tooling to recognize metadata defined in a YAML document at the start of a MarkDown file. The term for this is "front matter".
The metadata defined in front matter can be used for various purposes, including
- Assigning categorical tags to a document.
- The standardized way to do this is a sequence (i.e., array) under the
tags
key.
- The standardized way to do this is a sequence (i.e., array) under the
- Configuration of tools that consume Markdown files and recognize special front matter keys.
- Some tools (e.g., Material for MkDocs, Obsidian) use the data from the
tags
key.
- Some tools (e.g., Material for MkDocs, Obsidian) use the data from the
The file structure produced by the generator is flat at the document scope, with all documents stored under the root of the knowledge base folder rather than attempting to support the definition of an informational structure via folder hierarchies.
The information structure of the knowledge base should instead be defined by tags. It is through these tags that the user navigates and searches the knowledge base.
The generator can be configured to populate the front matter of the new document according to the user's answers to prompts. See the documentation for the prompts configuration file and document file template for details.
Contributing
Acknowledgments
Thanks to the open source community who contribute to this project and the software and resources it uses!
See the Acknowledgments page for details.