marko 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/Gemfile.lock +3 -2
  4. data/README.md +16 -13
  5. data/Rakefile +5 -0
  6. data/STORY.md +44 -0
  7. data/_layouts/footer.md +4 -0
  8. data/_layouts/header.md +3 -0
  9. data/_layouts/layout.html +73 -0
  10. data/_layouts/robots.txt.erb +4 -0
  11. data/_layouts/sitemap.xml.erb +20 -0
  12. data/_layouts/styles.css +92 -0
  13. data/docs/changelog.html +74 -0
  14. data/docs/css/styles.css +92 -0
  15. data/docs/index.html +297 -0
  16. data/docs/readme.html +297 -0
  17. data/docs/robots.txt +4 -0
  18. data/docs/sitemap.xml +30 -0
  19. data/docs/story.html +132 -0
  20. data/exe/marko +4 -2
  21. data/lib/assets/demo/README.md +2 -2
  22. data/lib/assets/demo/src/ur/uc.general.flow.md +1 -1
  23. data/lib/assets/init/README.md +1 -1
  24. data/lib/assets/init/Rakefile +2 -2
  25. data/lib/assets/init/tt/custom.md.tt +19 -0
  26. data/lib/assets/init/tt/default.md.tt +4 -0
  27. data/lib/assets/samples/0_index.md +14 -0
  28. data/lib/assets/samples/1_intro.md +55 -0
  29. data/lib/assets/samples/2_stakh.md +21 -0
  30. data/lib/assets/samples/3_actors.md +10 -0
  31. data/lib/assets/samples/4_cases.md +53 -0
  32. data/lib/assets/samples/5_entities.md +18 -0
  33. data/lib/assets/samples/6_concerns.md +60 -0
  34. data/lib/assets/samples/SRS-IEEE-830-1998.md +293 -0
  35. data/lib/assets/samples/SRS-RUP.md +283 -0
  36. data/lib/assets/samples/business-case.md +116 -0
  37. data/lib/assets/samples/ears.md +112 -0
  38. data/lib/assets/samples/gen_punch_domain.rb +183 -0
  39. data/lib/assets/samples/requirements.md +105 -0
  40. data/lib/assets/samples/stakeholders.png +0 -0
  41. data/lib/assets/samples/vision.md +191 -0
  42. data/lib/marko/artifact.rb +3 -1
  43. data/lib/marko/assembler.rb +1 -0
  44. data/lib/marko/cli.rb +10 -2
  45. data/lib/marko/markup/compiler.rb +3 -9
  46. data/lib/marko/markup/decorator.rb +45 -30
  47. data/lib/marko/markup/storage.rb +37 -19
  48. data/lib/marko/tree_node.rb +3 -2
  49. data/lib/marko/version.rb +1 -1
  50. data/lib/marko.rb +8 -0
  51. data/sancho.yml +6 -0
  52. metadata +35 -4
  53. data/lib/assets/init/tt/artifact.md.tt +0 -3
data/docs/index.html ADDED
@@ -0,0 +1,297 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="generator" content="pandoc" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
7
+ <meta name="keywords" content="ruby, markup-compiler" />
8
+ <title>Marko Readme</title>
9
+ <style>
10
+ code{white-space: pre-wrap;}
11
+ span.smallcaps{font-variant: small-caps;}
12
+ div.columns{display: flex; gap: min(4vw, 1.5em);}
13
+ div.column{flex: auto; overflow-x: auto;}
14
+ div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
15
+ ul.task-list{list-style: none;}
16
+ ul.task-list li input[type="checkbox"] {
17
+ width: 0.8em;
18
+ margin: 0 0.8em 0.2em -1.6em;
19
+ vertical-align: middle;
20
+ }
21
+ .display.math{display: block; text-align: center; margin: 0.5rem auto;}
22
+ /* CSS for syntax highlighting */
23
+ pre > code.sourceCode { white-space: pre; position: relative; }
24
+ pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
25
+ pre > code.sourceCode > span:empty { height: 1.2em; }
26
+ .sourceCode { overflow: visible; }
27
+ code.sourceCode > span { color: inherit; text-decoration: inherit; }
28
+ div.sourceCode { margin: 1em 0; }
29
+ pre.sourceCode { margin: 0; }
30
+ @media screen {
31
+ div.sourceCode { overflow: auto; }
32
+ }
33
+ @media print {
34
+ pre > code.sourceCode { white-space: pre-wrap; }
35
+ pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
36
+ }
37
+ pre.numberSource code
38
+ { counter-reset: source-line 0; }
39
+ pre.numberSource code > span
40
+ { position: relative; left: -4em; counter-increment: source-line; }
41
+ pre.numberSource code > span > a:first-child::before
42
+ { content: counter(source-line);
43
+ position: relative; left: -1em; text-align: right; vertical-align: baseline;
44
+ border: none; display: inline-block;
45
+ -webkit-touch-callout: none; -webkit-user-select: none;
46
+ -khtml-user-select: none; -moz-user-select: none;
47
+ -ms-user-select: none; user-select: none;
48
+ padding: 0 4px; width: 4em;
49
+ color: #aaaaaa;
50
+ }
51
+ pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
52
+ div.sourceCode
53
+ { }
54
+ @media screen {
55
+ pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
56
+ }
57
+ code span.al { color: #ff0000; font-weight: bold; } /* Alert */
58
+ code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
59
+ code span.at { color: #7d9029; } /* Attribute */
60
+ code span.bn { color: #40a070; } /* BaseN */
61
+ code span.bu { color: #008000; } /* BuiltIn */
62
+ code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
63
+ code span.ch { color: #4070a0; } /* Char */
64
+ code span.cn { color: #880000; } /* Constant */
65
+ code span.co { color: #60a0b0; font-style: italic; } /* Comment */
66
+ code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
67
+ code span.do { color: #ba2121; font-style: italic; } /* Documentation */
68
+ code span.dt { color: #902000; } /* DataType */
69
+ code span.dv { color: #40a070; } /* DecVal */
70
+ code span.er { color: #ff0000; font-weight: bold; } /* Error */
71
+ code span.ex { } /* Extension */
72
+ code span.fl { color: #40a070; } /* Float */
73
+ code span.fu { color: #06287e; } /* Function */
74
+ code span.im { color: #008000; font-weight: bold; } /* Import */
75
+ code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
76
+ code span.kw { color: #007020; font-weight: bold; } /* Keyword */
77
+ code span.op { color: #666666; } /* Operator */
78
+ code span.ot { color: #007020; } /* Other */
79
+ code span.pp { color: #bc7a00; } /* Preprocessor */
80
+ code span.sc { color: #4070a0; } /* SpecialChar */
81
+ code span.ss { color: #bb6688; } /* SpecialString */
82
+ code span.st { color: #4070a0; } /* String */
83
+ code span.va { color: #19177c; } /* Variable */
84
+ code span.vs { color: #4070a0; } /* VerbatimString */
85
+ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
86
+ </style>
87
+ <link rel="stylesheet" href="css/styles.css" />
88
+ <!--[if lt IE 9]>
89
+ <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
90
+ <![endif]-->
91
+ </head>
92
+ <body>
93
+ <p class="navbar">
94
+ <span class="smallcaps">= <strong>“Marko” Markup Compiler</strong> = <a
95
+ href="readme.html">Readme</a> ~ <a href="changelog.html">Changelog</a> ~
96
+ <a href="story.html">Story</a> ~ <a
97
+ href="https://github.com/nvoynov/sancho">Github</a></span>
98
+ </p>
99
+ <header id="title-block-header">
100
+ <h1 class="title">Marko Readme</h1>
101
+ </header>
102
+ <nav id="TOC" role="doc-toc">
103
+ <ul>
104
+ <li><a href="#installation" id="toc-installation">Installation</a></li>
105
+ <li><a href="#usage" id="toc-usage">Usage</a>
106
+ <ul>
107
+ <li><a href="#interface" id="toc-interface">Interface</a></li>
108
+ <li><a href="#structure" id="toc-structure">Structure</a></li>
109
+ <li><a href="#markup" id="toc-markup">Markup</a></li>
110
+ <li><a href="#metadata" id="toc-metadata">Metadata</a></li>
111
+ <li><a href="#tree-ids" id="toc-tree-ids">Tree, IDs</a></li>
112
+ <li><a href="#macros" id="toc-macros">Macros</a></li>
113
+ <li><a href="#templates" id="toc-templates">Templates</a></li>
114
+ <li><a href="#automation" id="toc-automation">Automation</a></li>
115
+ </ul></li>
116
+ <li><a href="#development" id="toc-development">Development</a></li>
117
+ <li><a href="#contributing" id="toc-contributing">Contributing</a></li>
118
+ </ul>
119
+ </nav>
120
+ <p>Marko is a markup compiler that builds a tree from separated sources
121
+ and compiles it into a single deliverable artifact.</p>
122
+ <p>Marko supplies a “docs-as-code” approach for compiling bulky software
123
+ artifacts by providing source storage, original plain text markup,
124
+ compiler templates, Ruby- and a command-line interface for assembling
125
+ and compiling.</p>
126
+ <p>Having assembled the artifact, it can be analyzed, enriched by extra
127
+ data, etc.; it can serve as a source for deriving subdued artifacts.</p>
128
+ <p>I’ve applied the approach for dozens of artifacts for the last six
129
+ years, mainly writing requirements in Markdown, analyzing quality,
130
+ deriving estimation sheets, exporting deliverables with Pandoc, and
131
+ automating some parts of my everyday work.</p>
132
+ <h2 id="installation">Installation</h2>
133
+ <p>Install the gem by executing:</p>
134
+ <pre><code>$ gem install marko</code></pre>
135
+ <h2 id="usage">Usage</h2>
136
+ <h3 id="interface">Interface</h3>
137
+ <p>Marko provides just basic command-line interface for creating new
138
+ projects and assembling artifacts - run <code>$ marko</code> to see the
139
+ details.</p>
140
+ <p>In addition to the standard CLI, Marko supplies you with Rakefile,
141
+ that also serves as custom automation example. You can run
142
+ <code>rake -T</code> to see available commands.</p>
143
+ <p>To help you with task automation, Marko provides
144
+ <code>Marko.assemble</code> for assembling and
145
+ <code>Marko.compile</code> for compiling artifacts (you could already
146
+ spot it inside Rakefile.) See <a href="#automation">Automation</a>
147
+ section for examples.</p>
148
+ <h3 id="structure">Structure</h3>
149
+ <p><code>marko new PROJECT</code> command will create a new marko
150
+ project inside the <code>PROJECT</code> directory with following
151
+ structure:</p>
152
+ <ul>
153
+ <li><a href="bin/">bin/</a> - output folder for <code>build</code></li>
154
+ <li><a href="bin/assets/">bin/assets/</a> - assets folder</li>
155
+ <li><a href="src/">src/</a> - markup sources</li>
156
+ <li><a href="tt/">tt/</a> - templates for <code>build</code></li>
157
+ <li><a href="marko.yml">marko.yml</a> - project configuration</li>
158
+ <li><a href="Rakefile">Rakefile</a> - Rake automation file</li>
159
+ <li><a href="README.md">README.md</a> - this file</li>
160
+ </ul>
161
+ <h3 id="markup">Markup</h3>
162
+ <p>The basic and the only Marko entity is <a
163
+ href="#github-link">TreeNode</a> with <code>id</code>,
164
+ <code>meta</code>, <code>body</code>, and <code>items</code>
165
+ properties.</p>
166
+ <p>And the primary activity is just writing source files consisting of
167
+ the TreeNode, where the source actually just a regular Markdown with an
168
+ optional metadata excerpt. All lines from <code>#</code> until the next
169
+ <code>#</code> are considered TreeNode.</p>
170
+ <p>Let’s see it by example and assume one has a few separate sources
171
+ <code>content.md</code>, <code>uc.signup.md</code>, and
172
+ <code>uc.signin.md</code>. <code>content.md</code></p>
173
+ <div class="sourceCode" id="cb2"><pre
174
+ class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu"># Overview</span></span>
175
+ <span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="fu"># User Requirements</span></span>
176
+ <span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="fu">## Use Cases</span></span>
177
+ <span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>{{id: uc, order_index: .signup .signin}}</span>
178
+ <span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="fu"># Functional requirements</span></span></code></pre></div>
179
+ <p><code>uc.signup.md</code></p>
180
+ <div class="sourceCode" id="cb3"><pre
181
+ class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu"># Sign-Up</span></span>
182
+ <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>{{id: .signup, parent: uc}}</span>
183
+ <span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
184
+ <span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>body markup</span></code></pre></div>
185
+ <p><code>uc.signin.md</code></p>
186
+ <div class="sourceCode" id="cb4"><pre
187
+ class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu"># Sign-In</span></span>
188
+ <span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>{{id: .signin, parent: uc}}</span>
189
+ <span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
190
+ <span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>body markup</span></code></pre></div>
191
+ <p>These sources will be assembled in a single hierarchy as follows</p>
192
+ <div class="sourceCode" id="cb5"><pre
193
+ class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu"># Overview</span></span>
194
+ <span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="fu"># User Requirements</span></span>
195
+ <span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="fu">## Use Cases</span></span>
196
+ <span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>{{id: uc, order_index: .signup .signin}}</span>
197
+ <span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="fu">### Sign-Up</span></span>
198
+ <span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>{{id: .signup, parent: uc}}</span>
199
+ <span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a></span>
200
+ <span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>body markup</span>
201
+ <span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="fu">### Sign-In</span></span>
202
+ <span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>{{id: .signin, parent: uc}}</span>
203
+ <span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a></span>
204
+ <span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>body markup</span>
205
+ <span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a></span>
206
+ <span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a><span class="fu"># Functional requirements</span></span></code></pre></div>
207
+ <p>So all the assemblage magic is just linking TreeNode by using
208
+ <code>id</code>, <code>parent</code>, and <code>order_index</code>
209
+ attributes; where <code>id</code> and <code>parent</code> are just nodes
210
+ identifiers, and <code>order_index</code> is just an array of
211
+ identifiers that point out the order of getting <code>items</code>.</p>
212
+ <h3 id="metadata">Metadata</h3>
213
+ <p>It was shown above how to provide hierarchy attributes by metadata
214
+ excerpt <code>{{}}</code>. But you can also use the excerpt to provide
215
+ your own attributes, like <code>source: John Doe</code>,
216
+ <code>affects: some.other.thing</code>, etc.</p>
217
+ <h3 id="tree-ids">Tree, IDs</h3>
218
+ <p>When you deal with trees in separated sources, to reference nodes you
219
+ need identifiers. So when you write <code>id</code>, <code>parent</code>
220
+ and <code>order_index</code> metadata - you actually deal with TreeNode
221
+ Id, and it must be unique.</p>
222
+ <p>When one works on a simple parent -&gt; child relationship,
223
+ identifiers can be shortened by starting from <code>.</code>. In the
224
+ example above <code>{{order_index: .signup .signin}}</code>, the parent
225
+ will find its children by <code>/.signup$/</code> and
226
+ <code>/.signin$/</code>; and besides, during the assembling phase those
227
+ relative identifiers will be turned to full - <code>uc.signup</code> and
228
+ <code>uc.signin</code>.</p>
229
+ <p>Marko will generate a unique Id for each TreeNode when Id was not
230
+ provided by the author.</p>
231
+ <h3 id="macros">Macros</h3>
232
+ <p>The TreeNode.body can include macros. The most helpful one is
233
+ <code>[[reference.id]]</code> that will be substituted by well-formed
234
+ markdown link <code>[&lt;node.title&gt;](#&lt;node.url&gt;)</code>.
235
+ There are also <code>@@tree</code>, <code>@@list</code>,
236
+ <code>@@todo</code>, and <code>@@skip</code> standard macros; and this
237
+ list could be extended or shortened through building templates.</p>
238
+ <ul>
239
+ <li><code>@@tree</code> substituted by the tree of references to all
240
+ descendants of the current node, might be used for the table of
241
+ contents;</li>
242
+ <li><code>@@list</code> substituted by the list of references to node
243
+ items;</li>
244
+ <li><code>@@todo</code> will will skip text with the macro till the end
245
+ of the line</li>
246
+ <li><code>@@skip</code> will skip the text after the macro</li>
247
+ </ul>
248
+ <h3 id="templates">Templates</h3>
249
+ <p>Marko uses templates placed under the <code>tt</code> folder to
250
+ compile sources into artifacts. You can use and customize the default
251
+ one or design your own for particular purposes. It’s just pure ERB,
252
+ where Marko enumerates TreeNodes and renders the node output.</p>
253
+ <pre><code>&lt;%= @node.header %&gt;
254
+ &lt;%= @node.meta %&gt;
255
+ &lt;%= @node.body %&gt;</code></pre>
256
+ <p>The <code>marko.yml</code> configuration file sets the building
257
+ process’s default template and other default values.</p>
258
+ <div class="sourceCode" id="cb7"><pre
259
+ class="sourceCode yml"><code class="sourceCode yaml"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="pp">--- !ruby/struct:Marko::Artifact</span></span>
260
+ <span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="fu">id</span><span class="kw">:</span><span class="at"> ed863484-243f-4d46-8012-4b148f8c2910</span></span>
261
+ <span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="fu">title</span><span class="kw">:</span><span class="at"> Marko Artifact</span></span>
262
+ <span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="fu">template</span><span class="kw">:</span><span class="at"> tt/artifact.md.tt</span></span>
263
+ <span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="fu">filename</span><span class="kw">:</span><span class="at"> tt/marko-artifact.md</span></span></code></pre></div>
264
+ <h3 id="automation">Automation</h3>
265
+ <p>Following quick example will assemble tree, remove TreeNode with id
266
+ == ‘hint’, and compile the tree. You can also see Rakefile for other
267
+ examples.</p>
268
+ <div class="sourceCode" id="cb8"><pre
269
+ class="sourceCode ruby"><code class="sourceCode ruby"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">require</span> <span class="vs">&#39;marko&#39;</span></span>
270
+ <span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
271
+ <span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="cf">def</span> do_remove_hint</span>
272
+ <span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> tree <span class="kw">=</span> <span class="dt">Marko</span><span class="at">.assemble</span></span>
273
+ <span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a> hint <span class="kw">=</span> tree<span class="at">.find_node</span>(<span class="vs">&#39;hint&#39;</span>)</span>
274
+ <span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a> hint<span class="at">.orphan!</span></span>
275
+ <span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">Marko</span><span class="at">.compile</span>(<span class="wa">tree: </span>tree) </span>
276
+ <span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="cf">end</span></span></code></pre></div>
277
+ <h2 id="development">Development</h2>
278
+ <p>After checking out the repo, run <code>bin/setup</code> to install
279
+ dependencies. Then, run <code>rake test</code> to run the tests. You can
280
+ also run <code>bin/console</code> for an interactive prompt that will
281
+ allow you to experiment.</p>
282
+ <p>To install this gem onto your local machine, run
283
+ <code>bundle exec rake install</code>. To release a new version, update
284
+ the version number in <code>version.rb</code>, and then run
285
+ <code>bundle exec rake release</code>, which will create a git tag for
286
+ the version, push git commits and the created tag, and push the
287
+ <code>.gem</code> file to <a
288
+ href="https://rubygems.org">rubygems.org</a>.</p>
289
+ <h2 id="contributing">Contributing</h2>
290
+ <p>Bug reports and pull requests are welcome on GitHub at
291
+ https://github.com/[USERNAME]/marko.</p>
292
+ <div id="footer">
293
+ <hr />
294
+ <p>© 2022-2023 <a href="http://nvoynov.github.io/">nvoynov</a></p>
295
+ </div>
296
+ </body>
297
+ </html>
data/docs/readme.html ADDED
@@ -0,0 +1,297 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="generator" content="pandoc" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
7
+ <meta name="keywords" content="ruby, markup-compiler" />
8
+ <title>Marko Readme</title>
9
+ <style>
10
+ code{white-space: pre-wrap;}
11
+ span.smallcaps{font-variant: small-caps;}
12
+ div.columns{display: flex; gap: min(4vw, 1.5em);}
13
+ div.column{flex: auto; overflow-x: auto;}
14
+ div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
15
+ ul.task-list{list-style: none;}
16
+ ul.task-list li input[type="checkbox"] {
17
+ width: 0.8em;
18
+ margin: 0 0.8em 0.2em -1.6em;
19
+ vertical-align: middle;
20
+ }
21
+ .display.math{display: block; text-align: center; margin: 0.5rem auto;}
22
+ /* CSS for syntax highlighting */
23
+ pre > code.sourceCode { white-space: pre; position: relative; }
24
+ pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
25
+ pre > code.sourceCode > span:empty { height: 1.2em; }
26
+ .sourceCode { overflow: visible; }
27
+ code.sourceCode > span { color: inherit; text-decoration: inherit; }
28
+ div.sourceCode { margin: 1em 0; }
29
+ pre.sourceCode { margin: 0; }
30
+ @media screen {
31
+ div.sourceCode { overflow: auto; }
32
+ }
33
+ @media print {
34
+ pre > code.sourceCode { white-space: pre-wrap; }
35
+ pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
36
+ }
37
+ pre.numberSource code
38
+ { counter-reset: source-line 0; }
39
+ pre.numberSource code > span
40
+ { position: relative; left: -4em; counter-increment: source-line; }
41
+ pre.numberSource code > span > a:first-child::before
42
+ { content: counter(source-line);
43
+ position: relative; left: -1em; text-align: right; vertical-align: baseline;
44
+ border: none; display: inline-block;
45
+ -webkit-touch-callout: none; -webkit-user-select: none;
46
+ -khtml-user-select: none; -moz-user-select: none;
47
+ -ms-user-select: none; user-select: none;
48
+ padding: 0 4px; width: 4em;
49
+ color: #aaaaaa;
50
+ }
51
+ pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
52
+ div.sourceCode
53
+ { }
54
+ @media screen {
55
+ pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
56
+ }
57
+ code span.al { color: #ff0000; font-weight: bold; } /* Alert */
58
+ code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
59
+ code span.at { color: #7d9029; } /* Attribute */
60
+ code span.bn { color: #40a070; } /* BaseN */
61
+ code span.bu { color: #008000; } /* BuiltIn */
62
+ code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
63
+ code span.ch { color: #4070a0; } /* Char */
64
+ code span.cn { color: #880000; } /* Constant */
65
+ code span.co { color: #60a0b0; font-style: italic; } /* Comment */
66
+ code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
67
+ code span.do { color: #ba2121; font-style: italic; } /* Documentation */
68
+ code span.dt { color: #902000; } /* DataType */
69
+ code span.dv { color: #40a070; } /* DecVal */
70
+ code span.er { color: #ff0000; font-weight: bold; } /* Error */
71
+ code span.ex { } /* Extension */
72
+ code span.fl { color: #40a070; } /* Float */
73
+ code span.fu { color: #06287e; } /* Function */
74
+ code span.im { color: #008000; font-weight: bold; } /* Import */
75
+ code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
76
+ code span.kw { color: #007020; font-weight: bold; } /* Keyword */
77
+ code span.op { color: #666666; } /* Operator */
78
+ code span.ot { color: #007020; } /* Other */
79
+ code span.pp { color: #bc7a00; } /* Preprocessor */
80
+ code span.sc { color: #4070a0; } /* SpecialChar */
81
+ code span.ss { color: #bb6688; } /* SpecialString */
82
+ code span.st { color: #4070a0; } /* String */
83
+ code span.va { color: #19177c; } /* Variable */
84
+ code span.vs { color: #4070a0; } /* VerbatimString */
85
+ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
86
+ </style>
87
+ <link rel="stylesheet" href="css/styles.css" />
88
+ <!--[if lt IE 9]>
89
+ <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
90
+ <![endif]-->
91
+ </head>
92
+ <body>
93
+ <p class="navbar">
94
+ <span class="smallcaps">= <strong>“Marko” Markup Compiler</strong> = <a
95
+ href="readme.html">Readme</a> ~ <a href="changelog.html">Changelog</a> ~
96
+ <a href="story.html">Story</a> ~ <a
97
+ href="https://github.com/nvoynov/sancho">Github</a></span>
98
+ </p>
99
+ <header id="title-block-header">
100
+ <h1 class="title">Marko Readme</h1>
101
+ </header>
102
+ <nav id="TOC" role="doc-toc">
103
+ <ul>
104
+ <li><a href="#installation" id="toc-installation">Installation</a></li>
105
+ <li><a href="#usage" id="toc-usage">Usage</a>
106
+ <ul>
107
+ <li><a href="#interface" id="toc-interface">Interface</a></li>
108
+ <li><a href="#structure" id="toc-structure">Structure</a></li>
109
+ <li><a href="#markup" id="toc-markup">Markup</a></li>
110
+ <li><a href="#metadata" id="toc-metadata">Metadata</a></li>
111
+ <li><a href="#tree-ids" id="toc-tree-ids">Tree, IDs</a></li>
112
+ <li><a href="#macros" id="toc-macros">Macros</a></li>
113
+ <li><a href="#templates" id="toc-templates">Templates</a></li>
114
+ <li><a href="#automation" id="toc-automation">Automation</a></li>
115
+ </ul></li>
116
+ <li><a href="#development" id="toc-development">Development</a></li>
117
+ <li><a href="#contributing" id="toc-contributing">Contributing</a></li>
118
+ </ul>
119
+ </nav>
120
+ <p>Marko is a markup compiler that builds a tree from separated sources
121
+ and compiles it into a single deliverable artifact.</p>
122
+ <p>Marko supplies a “docs-as-code” approach for compiling bulky software
123
+ artifacts by providing source storage, original plain text markup,
124
+ compiler templates, Ruby- and a command-line interface for assembling
125
+ and compiling.</p>
126
+ <p>Having assembled the artifact, it can be analyzed, enriched by extra
127
+ data, etc.; it can serve as a source for deriving subdued artifacts.</p>
128
+ <p>I’ve applied the approach for dozens of artifacts for the last six
129
+ years, mainly writing requirements in Markdown, analyzing quality,
130
+ deriving estimation sheets, exporting deliverables with Pandoc, and
131
+ automating some parts of my everyday work.</p>
132
+ <h2 id="installation">Installation</h2>
133
+ <p>Install the gem by executing:</p>
134
+ <pre><code>$ gem install marko</code></pre>
135
+ <h2 id="usage">Usage</h2>
136
+ <h3 id="interface">Interface</h3>
137
+ <p>Marko provides just basic command-line interface for creating new
138
+ projects and assembling artifacts - run <code>$ marko</code> to see the
139
+ details.</p>
140
+ <p>In addition to the standard CLI, Marko supplies you with Rakefile,
141
+ that also serves as custom automation example. You can run
142
+ <code>rake -T</code> to see available commands.</p>
143
+ <p>To help you with task automation, Marko provides
144
+ <code>Marko.assemble</code> for assembling and
145
+ <code>Marko.compile</code> for compiling artifacts (you could already
146
+ spot it inside Rakefile.) See <a href="#automation">Automation</a>
147
+ section for examples.</p>
148
+ <h3 id="structure">Structure</h3>
149
+ <p><code>marko new PROJECT</code> command will create a new marko
150
+ project inside the <code>PROJECT</code> directory with following
151
+ structure:</p>
152
+ <ul>
153
+ <li><a href="bin/">bin/</a> - output folder for <code>build</code></li>
154
+ <li><a href="bin/assets/">bin/assets/</a> - assets folder</li>
155
+ <li><a href="src/">src/</a> - markup sources</li>
156
+ <li><a href="tt/">tt/</a> - templates for <code>build</code></li>
157
+ <li><a href="marko.yml">marko.yml</a> - project configuration</li>
158
+ <li><a href="Rakefile">Rakefile</a> - Rake automation file</li>
159
+ <li><a href="README.md">README.md</a> - this file</li>
160
+ </ul>
161
+ <h3 id="markup">Markup</h3>
162
+ <p>The basic and the only Marko entity is <a
163
+ href="#github-link">TreeNode</a> with <code>id</code>,
164
+ <code>meta</code>, <code>body</code>, and <code>items</code>
165
+ properties.</p>
166
+ <p>And the primary activity is just writing source files consisting of
167
+ the TreeNode, where the source actually just a regular Markdown with an
168
+ optional metadata excerpt. All lines from <code>#</code> until the next
169
+ <code>#</code> are considered TreeNode.</p>
170
+ <p>Let’s see it by example and assume one has a few separate sources
171
+ <code>content.md</code>, <code>uc.signup.md</code>, and
172
+ <code>uc.signin.md</code>. <code>content.md</code></p>
173
+ <div class="sourceCode" id="cb2"><pre
174
+ class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu"># Overview</span></span>
175
+ <span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="fu"># User Requirements</span></span>
176
+ <span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="fu">## Use Cases</span></span>
177
+ <span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>{{id: uc, order_index: .signup .signin}}</span>
178
+ <span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="fu"># Functional requirements</span></span></code></pre></div>
179
+ <p><code>uc.signup.md</code></p>
180
+ <div class="sourceCode" id="cb3"><pre
181
+ class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu"># Sign-Up</span></span>
182
+ <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>{{id: .signup, parent: uc}}</span>
183
+ <span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
184
+ <span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>body markup</span></code></pre></div>
185
+ <p><code>uc.signin.md</code></p>
186
+ <div class="sourceCode" id="cb4"><pre
187
+ class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu"># Sign-In</span></span>
188
+ <span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>{{id: .signin, parent: uc}}</span>
189
+ <span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
190
+ <span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>body markup</span></code></pre></div>
191
+ <p>These sources will be assembled in a single hierarchy as follows</p>
192
+ <div class="sourceCode" id="cb5"><pre
193
+ class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu"># Overview</span></span>
194
+ <span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="fu"># User Requirements</span></span>
195
+ <span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="fu">## Use Cases</span></span>
196
+ <span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>{{id: uc, order_index: .signup .signin}}</span>
197
+ <span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="fu">### Sign-Up</span></span>
198
+ <span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>{{id: .signup, parent: uc}}</span>
199
+ <span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a></span>
200
+ <span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>body markup</span>
201
+ <span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="fu">### Sign-In</span></span>
202
+ <span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>{{id: .signin, parent: uc}}</span>
203
+ <span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a></span>
204
+ <span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>body markup</span>
205
+ <span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a></span>
206
+ <span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a><span class="fu"># Functional requirements</span></span></code></pre></div>
207
+ <p>So all the assemblage magic is just linking TreeNode by using
208
+ <code>id</code>, <code>parent</code>, and <code>order_index</code>
209
+ attributes; where <code>id</code> and <code>parent</code> are just nodes
210
+ identifiers, and <code>order_index</code> is just an array of
211
+ identifiers that point out the order of getting <code>items</code>.</p>
212
+ <h3 id="metadata">Metadata</h3>
213
+ <p>It was shown above how to provide hierarchy attributes by metadata
214
+ excerpt <code>{{}}</code>. But you can also use the excerpt to provide
215
+ your own attributes, like <code>source: John Doe</code>,
216
+ <code>affects: some.other.thing</code>, etc.</p>
217
+ <h3 id="tree-ids">Tree, IDs</h3>
218
+ <p>When you deal with trees in separated sources, to reference nodes you
219
+ need identifiers. So when you write <code>id</code>, <code>parent</code>
220
+ and <code>order_index</code> metadata - you actually deal with TreeNode
221
+ Id, and it must be unique.</p>
222
+ <p>When one works on a simple parent -&gt; child relationship,
223
+ identifiers can be shortened by starting from <code>.</code>. In the
224
+ example above <code>{{order_index: .signup .signin}}</code>, the parent
225
+ will find its children by <code>/.signup$/</code> and
226
+ <code>/.signin$/</code>; and besides, during the assembling phase those
227
+ relative identifiers will be turned to full - <code>uc.signup</code> and
228
+ <code>uc.signin</code>.</p>
229
+ <p>Marko will generate a unique Id for each TreeNode when Id was not
230
+ provided by the author.</p>
231
+ <h3 id="macros">Macros</h3>
232
+ <p>The TreeNode.body can include macros. The most helpful one is
233
+ <code>[[reference.id]]</code> that will be substituted by well-formed
234
+ markdown link <code>[&lt;node.title&gt;](#&lt;node.url&gt;)</code>.
235
+ There are also <code>@@tree</code>, <code>@@list</code>,
236
+ <code>@@todo</code>, and <code>@@skip</code> standard macros; and this
237
+ list could be extended or shortened through building templates.</p>
238
+ <ul>
239
+ <li><code>@@tree</code> substituted by the tree of references to all
240
+ descendants of the current node, might be used for the table of
241
+ contents;</li>
242
+ <li><code>@@list</code> substituted by the list of references to node
243
+ items;</li>
244
+ <li><code>@@todo</code> will will skip text with the macro till the end
245
+ of the line</li>
246
+ <li><code>@@skip</code> will skip the text after the macro</li>
247
+ </ul>
248
+ <h3 id="templates">Templates</h3>
249
+ <p>Marko uses templates placed under the <code>tt</code> folder to
250
+ compile sources into artifacts. You can use and customize the default
251
+ one or design your own for particular purposes. It’s just pure ERB,
252
+ where Marko enumerates TreeNodes and renders the node output.</p>
253
+ <pre><code>&lt;%= @node.header %&gt;
254
+ &lt;%= @node.meta %&gt;
255
+ &lt;%= @node.body %&gt;</code></pre>
256
+ <p>The <code>marko.yml</code> configuration file sets the building
257
+ process’s default template and other default values.</p>
258
+ <div class="sourceCode" id="cb7"><pre
259
+ class="sourceCode yml"><code class="sourceCode yaml"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="pp">--- !ruby/struct:Marko::Artifact</span></span>
260
+ <span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="fu">id</span><span class="kw">:</span><span class="at"> ed863484-243f-4d46-8012-4b148f8c2910</span></span>
261
+ <span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="fu">title</span><span class="kw">:</span><span class="at"> Marko Artifact</span></span>
262
+ <span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="fu">template</span><span class="kw">:</span><span class="at"> tt/artifact.md.tt</span></span>
263
+ <span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="fu">filename</span><span class="kw">:</span><span class="at"> tt/marko-artifact.md</span></span></code></pre></div>
264
+ <h3 id="automation">Automation</h3>
265
+ <p>Following quick example will assemble tree, remove TreeNode with id
266
+ == ‘hint’, and compile the tree. You can also see Rakefile for other
267
+ examples.</p>
268
+ <div class="sourceCode" id="cb8"><pre
269
+ class="sourceCode ruby"><code class="sourceCode ruby"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">require</span> <span class="vs">&#39;marko&#39;</span></span>
270
+ <span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
271
+ <span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="cf">def</span> do_remove_hint</span>
272
+ <span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> tree <span class="kw">=</span> <span class="dt">Marko</span><span class="at">.assemble</span></span>
273
+ <span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a> hint <span class="kw">=</span> tree<span class="at">.find_node</span>(<span class="vs">&#39;hint&#39;</span>)</span>
274
+ <span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a> hint<span class="at">.orphan!</span></span>
275
+ <span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">Marko</span><span class="at">.compile</span>(<span class="wa">tree: </span>tree) </span>
276
+ <span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="cf">end</span></span></code></pre></div>
277
+ <h2 id="development">Development</h2>
278
+ <p>After checking out the repo, run <code>bin/setup</code> to install
279
+ dependencies. Then, run <code>rake test</code> to run the tests. You can
280
+ also run <code>bin/console</code> for an interactive prompt that will
281
+ allow you to experiment.</p>
282
+ <p>To install this gem onto your local machine, run
283
+ <code>bundle exec rake install</code>. To release a new version, update
284
+ the version number in <code>version.rb</code>, and then run
285
+ <code>bundle exec rake release</code>, which will create a git tag for
286
+ the version, push git commits and the created tag, and push the
287
+ <code>.gem</code> file to <a
288
+ href="https://rubygems.org">rubygems.org</a>.</p>
289
+ <h2 id="contributing">Contributing</h2>
290
+ <p>Bug reports and pull requests are welcome on GitHub at
291
+ https://github.com/[USERNAME]/marko.</p>
292
+ <div id="footer">
293
+ <hr />
294
+ <p>© 2022-2023 <a href="http://nvoynov.github.io/">nvoynov</a></p>
295
+ </div>
296
+ </body>
297
+ </html>
data/docs/robots.txt ADDED
@@ -0,0 +1,4 @@
1
+ User-agent: *
2
+ Allow: /
3
+
4
+ Sitemap: https://nvoynov.github.io/marko/sitemap.xml