mdmerge
Version:
Make a complete Markdown document from other files with a dedicated include instruction
238 lines (152 loc) • 11.4 kB
Markdown
# mdmerge
I developed `mdmerge` for my own usage.
I was tired to update my main `README.md` file
when it contains some codes (all or part of) from an existing file.
When the source file change, your `README.md` must be manually updated.
So I create my own **Node.js** application to update my `README.md`
which using other files thanks to a custom instruction which is
invisible in the rendered document (also in PDF document).
Currently, the application is not fully finished but the main feature are finished.
## Getting Start
### The Command Line Interface
The simpliest command line to merge your **Markdown** is ``mdmerge <FILE>.md``.
By default, the command line creates a new file nammed ``<FILE>.merged.md``.
I choose to do this to prevent breaks on the source file.
The command line have two **implicits** options :
* The first one will stands for the **input file** to merge.
* The second one will stands for the **output file** to put the result.
Examples with **implicits** options :
1. ``mdmerge <INPUT_FILE>.md <OUTPUT_FILE>.md`` : The merged document from
``<INPUT_FILE>.md`` will be place in the output file `<OUTPUT_FILE>.md`
2. ``mdmerge <INPUT_FILE>.md <INPUT_FILE>.md`` : Done like this, you will overwrite
your source file with the result.
The second case ``2.`` can be simply with the following command :
``mdmerge <FILE>.md -w``
### Implicit Options
This application allows **implicits** options.
**Implicits** options are the values which not begins with a hyphen char (`-`).
They are determined with their position behind the **command** (`mdmerge`).
On the following example ``mdmerge -c README.md README.final.md``,
the first **implicit** option is ``README.md`` and the second is `README.final.md`.
**Implicits** options priority is lesser than **Explicits** ones.
#### Implicit Option ``1``
The first **implicit** option stands for the file to merge. It's is equal
to the option ``-i``, `--in`.
#### Implicit Option ``2``
The second **implicit** option stands for the output file. It's is equal
to the option ``-o``, `--out`.
### Command Line Options
Please find below the detail of each options for
the command ``mdmerge``.
**Be warned** : **Explicit** options have the priority on the **implicit** ones.
**Be warned** : The **long options** have the **priority** on the **short ones**.
For instance, if you use at the same time options ``-i=file_1`` and
``--in=file_2``, this is the file `file_2` which will be processed.
#### Option ``-i``, `--in` : Input file
The option ``-i`` (`--in`) allows you to specified
the input file to merged.
* It requires a value.
* The input must be a **file** which exists.
* It equal to the implicit options `1`.
#### Option ``-o``, `--out` : Output file
The option ``-o`` (`--out`) allows you to specified
the target file in which the result will be placed.
* It requires a value.
* The output must be a **file**. If the file not exists, it will be created.
* It equal to the implicit options `2`.
This option will have no effect if option ``-w`` (`--write`) is used.
#### Option ``-w``, `--write` : Overwrite
The option ``-w`` (`--write`) allows you to directly
**overwrite** the input file with the result.
* It does not requires a value.
#### Option ``-c``, `--clear` : Clear
The option ``-c`` (`--clear`) allows you to remove
merged content between tags.
* It does not requires a value.
### The Instruction
The detailed instruction hereafter must be placed at the begin of the line
in a comment block in your Markdown file : ``[](<instruction>)``
Once parsed by `mdmerge`, a closing instruction has been inserted.
That will allows the application to update the included parts.
Please find below, the generic form of the instruction `<instruction>` :
The element separator is the colon char (`:`)
* `<instruction>` = `@import><pathToFile>[..:<inclusionInstruction>][:[<codeBlockLanguage>]]`
* `<pathToFile>` : This is the relative path to the file used for this inclusion.
* `:<inclusionInstruction>` : You can insert none to many of the inclusion instruction separated by `:`.
* `<inclusionInstruction` = `<line>[,<startOffset>][,<endOffset>]`
* `<line>` : You can specified the line to toggle the inclusion.
* `<startOffset>` : You can specified from which char you want to begin the inclusion on the line.
* `<endOffset>` : You can specified when you stop the inclusion on the line
* `:<codeBlockLanguage>` : You can ask to `mdmerge` to insert your content in a Markdown code block
in a specified language. You can omit `<codeBlockLanguage>` to let your favorite render to identify
automatically the language (Example with **Highligh.js**)
The `<inclusionInstruction>` toggle the inclusion.
The generic rule is the **odds** elements will start the inclusion whereas the **evens** will
stop the inclusion. When the total number of `<inclusionInstruction>` is **odd**, the last
inclusion process will inclusion until the **EOF** is met.
Please find an example of instruction :
````markdown
[](@import>bin/mdmerge.js:53:79:js)
````
The instruction can be read as
"Please, include here the JavaScript code from file `mdmerge.js`,
from line `53` to line `79` in a code block `js`".
The result is the following
[](#import>bin/mdmerge.js:53:79:js)
````js
/**
* Afficher un message dans le stream.
*
* @param message Message à afficher
* @param level Niveau de message. 0=OK,1=KO,2=WARN
*/
function log(message, level = 0, args = []){
// 0 = Success
// 1 = Error
// 2 = Warn
let levels = [
{color: "Green", name: "SUCCESS", return: 0},
{color: "Red", name: "ERROR", return: 1},
{color: "Yellow", name: "WARNING", return: 0},
];
console.log(
"[ " +
colors.fg[levels[level].color] +
levels[level].name +
colors.Reset +
" ] : " +
message
);
return levels[level].return;
}
````
[](#import<bin/mdmerge.js:53:79:js)
## Usage Cases
Please find below an exhaustiv list of usage cases and their development status
| Instruction | Explanation | Dev. Status |
|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|:-----------:|
| @import>test/incl.md | Include the whole content of file `incl.md` in folder `test` | DONE |
| @import>test/incl.md: | Include the whole content of file `incl.md` in folder `test` in a code block | DONE |
| @import>test/incl.md:js | Include the whole content of file `incl.md` in folder `test` in a code block JavaScript `js` | DONE |
| @import>test/incl.md:53 | Include the content of file `incl.md` from line `53` to the end of file `EOF` | DONE |
| @import>test/incl.md:53: | Include the content of file `incl.md` from line `53` to the end of file `EOF` in a code block | DONE |
| @import>test/incl.md:53:js | Include the content of file `incl.md` from line `53` to the end of file `EOF` in a code block JavaScript `js` | DONE |
| @import>test/incl.md::79 | Include the content of file `incl.md` from the beginning to the line `79` | DONE |
| @import>test/incl.md::79: | Include the content of file `incl.md` from the beginning to the line `79` in a code block | DONE |
| @import>test/incl.md::79:js | Include the content of file `incl.md` from the beginning to the line `79` in a code block JavaScript `js` | DONE |
| @import>test/incl.md:53:79 | Include the content of file `incl.md` from line `53` to the line `79` | DONE |
| @import>test/incl.md:53:79: | Include the content of file `incl.md` from line `53` to the line `79` in a code block | DONE |
| @import>test/incl.md:53:79:js | Include the content of file `incl.md` from line `53` to the line `79` in a code block JavaScript `js` | DONE |
| @import>test/incl.md:53,1 | Include the content of file `incl.md` from line `53`, starting at position `1` to the end of file `EOF` | DONE |
| @import>test/incl.md:53,1: | Include the content of file `incl.md` from line `53`, starting at position `1` to the end of file `EOF` in a code block | DONE |
| @import>test/incl.md:53,1:js | Include the content of file `incl.md` from line `53`, starting at position `1` to the end of file `EOF` in a code block Javascript `js` | DONE |
| @import>test/incl.md:53,,1 | Include the line number `53` from the file `incl.md`, starting at position `0` to position `1` | DONE |
| @import>test/incl.md:53,,1: | Include the line number `53` from the file `incl.md`, starting at position `0` to position `1` in a code block | DONE |
| @import>test/incl.md:53,,1:js | Include the line number `53` from the file `incl.md`, starting at position `0` to position `1` in a code block Javascript `js` | DONE |
| @import>test/incl.md:53,2,4 | Include the line number `53` from the file `incl.md`, starting at position `02` to position `4` | DONE |
| @import>test/incl.md:53,2,4: | Include the line number `53` from the file `incl.md`, starting at position `02` to position `4` in a code block | DONE |
| @import>test/incl.md:53,2,4:js | Include the line number `53` from the file `incl.md`, starting at position `02` to position `4` in a code block Javascript `js` | DONE |
| @import>test/incl.md:53:79:526 | Include the content of file `incl.md` from line `53` to the line `79`, and from line `526` to the end of line `EOF` | DONE |
| @import>test/incl.md:53:79:526: | Include the content of file `incl.md` from line `53` to the line `79`, and from line `526` to the end of line `EOF` in a code block | DONE |
| @import>test/incl.md:53:79:526:js | Include the content of file `incl.md` from line `53` to the line `79`, and from line `526` to the end of line `EOF` in a code block JavaScript `js` | DONE |
**Their is some cases not listed here which are functional and some other ideas which are not implemented yet**