marko 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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