marklow v1.3.5
marklow
marklow is a library and npx
script for defining custom markdown-like syntax and compiling your custom markdown into JSON to be rendered however you please in your application.
Installation
npm i marklow
Why?
Geez, I gotta have a reason for everything? Jokes aside, consider the following scenario:
- You have some writing in the form of
.txt
or.md
files that you'd like to turn into a blog. - Sounds like a job for Jekyll (or equivalent).
- But, in addition to the basic markdown stuff, you'd also like to add a bit of extra functionality to your writing. For example, suppose you'd like some words to have a "definition" feature, where you can click on it and a pop-up will appear in the corner with the definition.
- Realizing that you'll need a custom framework, you switch to writing your content directly in your
jsx
/tsx
files.
Inlining content in your JSX files is terrible in every way; not only will duplicate JSX be unavoidable, but your writing will also be practically unreadable, resulting in the worst of both worlds. With marklow, you can instead define custom syntax for your specific use-case e.g. %term%((definition))
and then write markdown as usual. Then, your markdown files get compiled into JSON which your application can read and display exactly in the way you want.
Usage
Example
After installing marklow
, we need to define a configuration file called marklow.json
at the package level. An example with all options set is shown below:
// marklow.json
{
"defaultsConfig": {
// If this value is true, all others are ignored. True by default.
"useAllDefaults": false,
// See the table below for a description of each default pattern.
"useDefaultHeaders": false,
"useDefaultBold": false,
"useDefaultItalic": false,
"useDefaultCode": false,
"useDefaultLink": false,
"useDefaultImage": false,
"useDefaultBreaks": false,
"useDefaultCodeBlock": false,
"useDefaultQuotation": false
},
// The directory containing your input files.
"inputDir": "./posts",
// The output JSON directory.
"outputDir": "./src/posts",
// Custom syntax.
"matchers": [
{
// A regex pattern. Note that escaped regex characters need to be double escaped.
// Named groups (besides "body") will be used as attributes of the "color" element.
// "body" is a special group name used for text meant to be displayed inline.
"pattern": ";;(?<body>.+?);;\\((?<colorName>.+?)\\)",
// The "tag name" for this element
"tag": "color",
},
{
"pattern": "%(?<body>.+?)%\\(\\((?<definition>.+?)\\)\\)",
"tag": "def",
// An optional list of named groups in the regex pattern to treat as children rather than attributes.
// These are essentially like additional "body"s.
"subgroups": ["definition"]
}
],
// Which file extensions in the input directory to compile / watch for changes.
"ext": ["md", "txt"]
}
Then, you just need to run npx marklow
and marklow will compile your md
or txt
files into JSON using the patterns you defined, watching for changes and re-compiling as needed. Say we have the following markdown file:
This page is about ;;red ants;;(red).
Red ants are %terrestrial%((This means they live on ;;land;;(green))) critters.
Marklow will convert this markdown to the following JSON (some fields removed for brevity):
{
"type": "marklow",
"children": [
{
"text": "This page is about "
},
{
"attributes": { "colorName": "red" },
"type": "color",
"children": [
{
"children": [{ "text": "red ants" }]
}
]
},
{
"text": ".\n\nRed ants are "
},
{
"type": "def",
"children": [
{
"children": [
{
"text": "terrestrial"
}
]
},
{
"type": "definition",
"children": [
{
"text": "This means they live on "
},
{
"attributes": { "colorName": "green" },
"type": "color",
"children": [
{
"children": [
{
"id": "3dea1cd2-19ac-43a8-868b-fca59a20c7fb",
"text": "land"
}
]
}
]
}
]
}
]
},
{ "text": " critters.\n" }
]
}
The JSON implements the MarklowNode
interface, which can be imported in your application via:
import { MarklowNode } from "marklow";
Default matchers
Below is a list of currently supported default matchers.
name | tag | supported? | syntax | attributes | subgroups |
---|---|---|---|---|---|
bold | b | yes | **example** | - | - |
italic | i | yes | _example_ | - | - |
code | code | yes | `example` | - | - |
headers | h1 , h2 , etc. | yes | # title , ## title , etc. | - | - |
code block | codeblock | yes | ``` multiline ``` | - | - | ||
quote | quot | yes | """ multiline """ | - | - |
link | a | yes | [example](link) | href | - |
image | img | yes |  | src , alt | - |
paragraph break | pb | yes | \n\n | - | - |
line break | br | yes | \n | - | - |
lists | ul & li | unordered | - example | - | - |
tables | - | no | - | - | - |
Rendering example
For an example of how marklow can be rendered in an application, check out my blog (live link to be added) and the React rendering logic on GitHub.
CLI usage
tsx marklow [-c | --config] [-i | --initial]
config
(string): If not using the defaultmarklow.json
, where to look for the configuration file.initial
(boolean): If set, compiles immediately upon execution instead of first waiting for changes (default:true
).
Bugs & feature requests
This library is new and was initially developed just so that I could add definitions and footnotes to my blog without moving away from markdown. If you have a bug or feature request, please feel free to leave an Issue on GitHub.