title: Marko Readme keywords:
- ruby
- markup-compiler ...
Marko is a markup compiler that builds a tree from separated Markdown sources and compiles it into a single artifact.
Marko supplies a "docs-as-code" approach for assembling bulky software artifacts by providing sources storage, original plain text markup, and command-line interface for assembling and compiling.
Having assembled the artifact, it can be analyzed, enriched by extra data, etc.; it can serve as a source for deriving subdued artifacts.
I've applied the approach for dozens of artifacts for the last six years, mainly writing requirements in Markdown, analyzing quality, deriving estimation sheets, exporting deliverables with Pandoc, and automating some parts of my everyday work.
Installation
Install the gem by executing:
$ gem install marko
Usage
Interface
Marko provides just basic command-line interface for creating new projects and assembling artifacts - run $ marko to see the details.
In addition to the standard CLI, one can automate some work with Rakefile.
To help you with task automation, Marko provides Marko.assemble for assembling and Marko.compile for compiling artifacts. See some examples in the Automation section.
Structure
marko punch PROJECT command will create a new Marko project inside the PROJECT directory with following structure:
bin- output artifact foldersrc- markup sourcesmarko.yml- configuration fileREADME.mdCHANGELOG.md
Markup
The basic and the only Marko entity is Topic with id, title, content, and metadata properties.
The the primary activity is just writing source files consisting of the Topic, where the source actually just a regular Markdown with an optional metadata excerpt. All lines from # until the next # are considered TreeNode.
Let's see it by example and assume one has a few separate sources content.md, uc.signup.md, and uc.signin.md.
content.md
# Overview
# User Requirements
## Use Cases
{{id: uc, order_index: .signup .signin}}
# Functional requirements
uc.signup.md
# Sign-Up
{{id: .signup, parent: uc}}
body markup
uc.signin.md
# Sign-In
{{id: .signin, parent: uc}}
body markup
These sources will be assembled in a single hierarchy as follows
# Overview
# User Requirements
## Use Cases
{{id: uc, order_index: .signup .signin}}
### Sign-Up
{{id: .signup, parent: uc}}
body markup
### Sign-In
{{id: .signin, parent: uc}}
body markup
# Functional requirements
So all the assemblage magic is just linking Topics by using id, parent, and order_index attributes; where id and parent are just nodes identifiers, and order_index is just an array of identifiers that point out the order of getting items.
Metadata
It was shown above how to provide hierarchy attributes by metadata excerpt {{}}. But you can also use the excerpt to provide your own attributes, like source: John Doe, affects: some.other.thing, etc.
Tree, IDs
When you deal with trees in separated sources, to reference nodes you need identifiers. So when you write id, parent and order_index metadata - you actually deal with TreeNode Id, and it must be unique.
When one works on a simple parent -> child relationship, identifiers can be shortened by starting from .. In the example above {{order_index: .signup .signin}}, the parent will find its children by /.signup$/ and /.signin$/; and besides, during the assembling phase those relative identifiers will be turned to full - uc.signup and uc.signin.
Marko will generate a unique Id for each TreeNode when Id was not provided by the author.
Macros
The TreeNode.body can include macros. The most helpful one is [[reference.id]] that will be substituted by well-formed markdown link [<node.title>](#<node.url>). There are also @@tree, @@list, @@todo, and @@skip standard macros; and this list could be extended or shortened through building templates.
@@treesubstituted by the tree of references to all descendants of the current node, might be used for the table of contents;@@listsubstituted by the list of references to node items;@@todowill skip text with the macro till the end of the line@@skipwill skip the text after the macro
marko.yml configuraton
The marko.yml configuration file provide a few configuration parametera like artifact name, title, author and order_index.
You can change it any time and it will affect the next assemble/ compile run
Automation (UNDER CONSTRUCTION)
Following quick example will assemble tree, remove TreeNode with id == 'hint', and compile the tree. You can also see Rakefile for other examples.
require 'marko'
def do_remove_hint
tree = Marko.assemble
hint = tree.find_node('hint')
hint.orphan!
Marko.compile(tree: tree)
end
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/marko.