marko 0.3.0 → 0.4.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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +12 -0
  3. data/.rubocop.yml +45 -0
  4. data/CHANGELOG.md +10 -4
  5. data/Dockerfile +11 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +17 -31
  8. data/Rakefile +2 -11
  9. data/exe/marko +4 -22
  10. data/lib/basic.rb +27 -0
  11. data/lib/marko/chain.rb +44 -0
  12. data/lib/marko/cli.rb +119 -129
  13. data/lib/marko/config.rb +30 -20
  14. data/lib/marko/errors.rb +38 -0
  15. data/lib/marko/model/markup.rb +33 -0
  16. data/lib/marko/model/topic.rb +126 -0
  17. data/lib/marko/model/tree_node.rb +34 -0
  18. data/lib/marko/model.rb +10 -0
  19. data/lib/marko/parser/metadata.rb +28 -0
  20. data/lib/marko/parser/source.rb +52 -0
  21. data/lib/marko/parser/topic.rb +33 -0
  22. data/lib/marko/parser.rb +8 -19
  23. data/lib/marko/renderers/artifact.rb +29 -0
  24. data/lib/marko/renderers/content.rb +37 -0
  25. data/lib/marko/renderers/link.rb +19 -0
  26. data/lib/marko/renderers/metadata.rb +34 -0
  27. data/lib/marko/renderers/nested_list.rb +21 -0
  28. data/lib/marko/renderers/nested_tree.rb +22 -0
  29. data/lib/marko/renderers/renderer.rb +17 -0
  30. data/lib/marko/renderers/title.rb +16 -0
  31. data/lib/marko/renderers/topic.rb +24 -0
  32. data/lib/marko/renderers/url.rb +16 -0
  33. data/lib/marko/renderers.rb +17 -0
  34. data/lib/marko/scanner.rb +39 -0
  35. data/lib/marko/tasks/assemble.rb +52 -0
  36. data/lib/marko/tasks/compile.rb +19 -0
  37. data/lib/marko/tasks/load.rb +13 -0
  38. data/lib/marko/tasks/parse.rb +27 -0
  39. data/lib/marko/tasks/scan.rb +18 -0
  40. data/lib/marko/tasks/validate.rb +32 -0
  41. data/lib/marko/tasks.rb +13 -0
  42. data/lib/marko/validators/lost_index.rb +21 -0
  43. data/lib/marko/validators/lost_links.rb +25 -0
  44. data/lib/marko/validators/lost_parent.rb +21 -0
  45. data/lib/marko/validators/non_unique_id.rb +23 -0
  46. data/lib/marko/validators.rb +11 -0
  47. data/lib/marko/version.rb +1 -3
  48. data/lib/marko.rb +11 -43
  49. metadata +47 -85
  50. data/Gemfile +0 -10
  51. data/Gemfile.lock +0 -23
  52. data/STORY.md +0 -44
  53. data/_layouts/footer.md +0 -4
  54. data/_layouts/header.md +0 -3
  55. data/_layouts/layout.html +0 -73
  56. data/_layouts/robots.txt.erb +0 -4
  57. data/_layouts/sitemap.xml.erb +0 -20
  58. data/_layouts/styles.css +0 -92
  59. data/docs/changelog.html +0 -74
  60. data/docs/css/styles.css +0 -92
  61. data/docs/index.html +0 -297
  62. data/docs/readme.html +0 -297
  63. data/docs/robots.txt +0 -4
  64. data/docs/sitemap.xml +0 -30
  65. data/docs/story.html +0 -132
  66. data/lib/assets/demo/README.md +0 -13
  67. data/lib/assets/demo/src/fr/assemble.md +0 -27
  68. data/lib/assets/demo/src/fr/compile.md +0 -25
  69. data/lib/assets/demo/src/fr/markup.md +0 -111
  70. data/lib/assets/demo/src/fr/storage.md +0 -16
  71. data/lib/assets/demo/src/fr/treenode.md +0 -34
  72. data/lib/assets/demo/src/index.md +0 -34
  73. data/lib/assets/demo/src/intro.md +0 -98
  74. data/lib/assets/demo/src/ui/cli.md +0 -26
  75. data/lib/assets/demo/src/ui/gem.md +0 -14
  76. data/lib/assets/demo/src/ur/uc.create.project.md +0 -8
  77. data/lib/assets/demo/src/ur/uc.general.flow.md +0 -14
  78. data/lib/assets/init/README.md +0 -61
  79. data/lib/assets/init/Rakefile +0 -100
  80. data/lib/assets/init/tt/custom.md.tt +0 -19
  81. data/lib/assets/init/tt/default.md.tt +0 -4
  82. data/lib/assets/samples/0_index.md +0 -14
  83. data/lib/assets/samples/1_intro.md +0 -55
  84. data/lib/assets/samples/2_stakh.md +0 -21
  85. data/lib/assets/samples/3_actors.md +0 -10
  86. data/lib/assets/samples/4_cases.md +0 -53
  87. data/lib/assets/samples/5_entities.md +0 -18
  88. data/lib/assets/samples/6_concerns.md +0 -60
  89. data/lib/assets/samples/SRS-IEEE-830-1998.md +0 -293
  90. data/lib/assets/samples/SRS-RUP.md +0 -283
  91. data/lib/assets/samples/business-case.md +0 -116
  92. data/lib/assets/samples/ears.md +0 -112
  93. data/lib/assets/samples/gen_punch_domain.rb +0 -183
  94. data/lib/assets/samples/requirements.md +0 -105
  95. data/lib/assets/samples/stakeholders.png +0 -0
  96. data/lib/assets/samples/vision.md +0 -191
  97. data/lib/marko/artifact.rb +0 -5
  98. data/lib/marko/assembler.rb +0 -83
  99. data/lib/marko/compiler.rb +0 -16
  100. data/lib/marko/gadgets/pluggable.rb +0 -55
  101. data/lib/marko/gadgets/sentry.rb +0 -66
  102. data/lib/marko/gadgets/service.rb +0 -52
  103. data/lib/marko/gadgets.rb +0 -3
  104. data/lib/marko/loader.rb +0 -38
  105. data/lib/marko/markup/compiler.rb +0 -30
  106. data/lib/marko/markup/decorator.rb +0 -80
  107. data/lib/marko/markup/macro.rb +0 -176
  108. data/lib/marko/markup/parser.rb +0 -122
  109. data/lib/marko/markup/storage.rb +0 -118
  110. data/lib/marko/markup/validator.rb +0 -101
  111. data/lib/marko/markup.rb +0 -24
  112. data/lib/marko/services/assemble.rb +0 -16
  113. data/lib/marko/services/compile.rb +0 -30
  114. data/lib/marko/services.rb +0 -2
  115. data/lib/marko/storage.rb +0 -36
  116. data/lib/marko/tree_node.rb +0 -129
  117. data/lib/marko/validator.rb +0 -19
  118. data/marko.gemspec +0 -44
  119. data/sancho.yml +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c3511e83282f71094f00c81bd8d926df0b0b9ecd7fa90fe978111e4b2d51afb
4
- data.tar.gz: 34810477d8a4449873eda8799ccd57f47726d35884c721d46e0c606119ca91c9
3
+ metadata.gz: 5831f616f2b1b2ae35890d79e685dd75efbe0553ebce040b04ce501656667cba
4
+ data.tar.gz: f6aaa2fdb7814193c221791b77331510374fc85a265e48138a4501be00f0ab26
5
5
  SHA512:
6
- metadata.gz: 3f0c0838b0c0f7328d927664e56caf58f787175bd0aa9883700b6a12377c1483e979138f021f8d3588bc287131292e889d6af0cecebfd29780a83588cb2e8291
7
- data.tar.gz: d7441f513814ad56d4c91cbd09ace4cdd56e5cbaef5598f15f15dbb66b2770eb54fab2fd1580920df1375ee0f1f6ec0427b4df52fb871f432a4fb50a591fc85e
6
+ metadata.gz: b23fe86805352e1b60fec19a059ac39dd4015096d1127f5dfcea157b36a6e3a922f85b66740ab23ef4718ea7d2bec71fbb0e04df4fd396867d887c8c82827233
7
+ data.tar.gz: f761d82d937f881cf92d2d21830a082f786d82c4b87a329d0ddfcc5564b3521ed823190ff702844cd71261dd223dcbd4c7ee4ef6ebf08c86a188322a9ffe8615
data/.dockerignore ADDED
@@ -0,0 +1,12 @@
1
+ # Ignore all
2
+ *
3
+
4
+ # Allow sources
5
+ !/bin/
6
+ !/app/
7
+ !/lib/
8
+ !Gemfile
9
+ !Gemfile.lock
10
+
11
+ # Ignore backups
12
+ **/*~
data/.rubocop.yml ADDED
@@ -0,0 +1,45 @@
1
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
2
+ # configuration file. It makes it possible to enable/disable
3
+ # certain cops (checks) and to alter their behavior if they accept
4
+ # any parameters. The file can be placed either in your home
5
+ # directory or in some project directory.
6
+ #
7
+ # RuboCop will start looking for the configuration file in the directory
8
+ # where the inspected file is and continue its way up to the root directory.
9
+ #
10
+ # See https://docs.rubocop.org/rubocop/configuration
11
+ AllCops:
12
+ TargetRubyVersion: 3.4.X
13
+ DisableByDefault: true
14
+ Exclude:
15
+ - 'test/**/*'
16
+
17
+ Style:
18
+ Enabled: true
19
+
20
+ Style/LambdaCall:
21
+ Enabled: false
22
+
23
+ Style/KeywordParametersOrder:
24
+ Enabled: false
25
+
26
+ Style/SignalException:
27
+ Enabled: false
28
+
29
+ Style/CharacterLiteral:
30
+ Enabled: false
31
+
32
+ Style/StringLiterals:
33
+ Enabled: false
34
+
35
+ Style/ModuleFunction:
36
+ Enabled: false
37
+
38
+ Style/StringConcatenation:
39
+ Enabled: false
40
+
41
+ Metrics:
42
+ Enabled: false
43
+
44
+ Layout:
45
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,13 +1,19 @@
1
1
  ---
2
2
  title: Marko Changelog
3
3
  keywords:
4
- - ruby
5
- - markup-compiler
4
+ - ruby
5
+ - markup-compiler
6
6
  ...
7
7
 
8
- ## [Unreleased]
8
+ ## [Unreleased] 2025-Sep-04
9
9
 
10
- - [ ] add order_index to Artifact?
10
+ Marko redesigned and simplified
11
+
12
+ - new model, renderers, and tasks design
13
+ - added the abiltiy to change root artifact order_index
14
+ - removed Sancho dependency
15
+ - lost @@todo macro
16
+ - lost demo, but might be returned
11
17
 
12
18
  ## [0.3.0] - 2023-11-22
13
19
 
data/Dockerfile ADDED
@@ -0,0 +1,11 @@
1
+ FROM ruby:3.4.4 as build
2
+ WORKDIR /app
3
+ COPY Gemfile .
4
+ # COPY Gemfile.lock .
5
+ ENV BUNDLER_WITHOUT development test
6
+ RUN gem update --system && bundle install
7
+ ADD . .
8
+
9
+ FROM ruby:3.4.4
10
+ COPY --from=build /app /app
11
+ CMD ["/bin/app", "help"]
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 nvoynov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -5,9 +5,9 @@ keywords:
5
5
  - markup-compiler
6
6
  ...
7
7
 
8
- Marko is a markup compiler that builds a tree from separated sources and compiles it into a single deliverable artifact.
8
+ Marko is a markup compiler that builds a tree from separated Markdown sources and compiles it into a single artifact.
9
9
 
10
- Marko supplies a "docs-as-code" approach for compiling bulky software artifacts by providing source storage, original plain text markup, compiler templates, Ruby- and a command-line interface for assembling and compiling.
10
+ 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.
11
11
 
12
12
  Having assembled the artifact, it can be analyzed, enriched by extra data, etc.; it can serve as a source for deriving subdued artifacts.
13
13
 
@@ -25,27 +25,25 @@ Install the gem by executing:
25
25
 
26
26
  Marko provides just basic command-line interface for creating new projects and assembling artifacts - run `$ marko` to see the details.
27
27
 
28
- In addition to the standard CLI, Marko supplies you with Rakefile, that also serves as custom automation example. You can run `rake -T` to see available commands.
28
+ In addition to the standard CLI, one can automate some work with Rakefile.
29
29
 
30
- To help you with task automation, Marko provides `Marko.assemble` for assembling and `Marko.compile` for compiling artifacts (you could already spot it inside Rakefile.) See [Automation](#automation) section for examples.
30
+ To help you with task automation, Marko provides `Marko.assemble` for assembling and `Marko.compile` for compiling artifacts. See some examples in the [Automation](#automation) section.
31
31
 
32
32
  ### Structure
33
33
 
34
- `marko new PROJECT` command will create a new Marko project inside the `PROJECT` directory with following structure:
34
+ `marko punch PROJECT` command will create a new Marko project inside the `PROJECT` directory with following structure:
35
35
 
36
- - [bin/](bin/) - output folder for `build`
37
- - [bin/assets/](bin/assets/) - assets folder
38
- - [src/](src/) - markup sources
39
- - [tt/](tt/) - compiler templates
40
- - [marko.yml](marko.yml) - project configuration
41
- - [Rakefile](Rakefile) - Rake automation file
42
- - [README.md](README.md) - this file
36
+ - `bin` - output artifact folder
37
+ - `src` - markup sources
38
+ - `marko.yml` - configuration file
39
+ - `README.md`
40
+ - `CHANGELOG.md`
43
41
 
44
42
  ### Markup
45
43
 
46
- The basic and the only Marko entity is [TreeNode](#github-link) with `id`, `meta`, `body`, and `items` properties.
44
+ The basic and the only Marko entity is [Topic](lib/marko/model/topic.rb) with `id`, `title`, `content`, and `metadata` properties.
47
45
 
48
- And the primary activity is just writing source files consisting of the TreeNode, where the source actually just a regular Markdown with an optional metadata excerpt. All lines from `#` until the next `#` are considered TreeNode.
46
+ 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.
49
47
 
50
48
  Let's see it by example and assume one has a few separate sources `content.md`, `uc.signup.md`, and `uc.signin.md`.
51
49
  `content.md`
@@ -95,7 +93,7 @@ body markup
95
93
  # Functional requirements
96
94
  ```
97
95
 
98
- So all the assemblage magic is just linking TreeNode 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`.
96
+ 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`.
99
97
 
100
98
  ### Metadata
101
99
 
@@ -118,25 +116,13 @@ The TreeNode.body can include macros. The most helpful one is `[[reference.id]]`
118
116
  - `@@todo` will skip text with the macro till the end of the line
119
117
  - `@@skip` will skip the text after the macro
120
118
 
121
- ### Templates
119
+ ### marko.yml configuraton
122
120
 
123
- Marko uses templates placed under the `tt` folder to compile sources into artifacts. You can use and customize the default one or design your own for particular purposes. It's just pure ERB, where Marko renders collection of decorated TreeNodes.
121
+ The `marko.yml` configuration file provide a few configuration parametera like artifact name, title, author and order_index.
124
122
 
125
- ```
126
- % @model.each do |node|
127
- <%= node.text %>
128
- % end
129
- ```
130
-
131
- The `marko.yml` configuration file sets the building process's default template and other default values.
132
-
133
- ```yml
134
- title: Artifact
135
- template: tt/default.md.tt
136
- filename: bin/artifact.md
137
- ```
123
+ You can change it any time and it will affect the next assemble/ compile run
138
124
 
139
- ### Automation
125
+ ### Automation (UNDER CONSTRUCTION)
140
126
 
141
127
  Following quick example will assemble tree, remove TreeNode with id == 'hint', and compile the tree. You can also see Rakefile for other examples.
142
128
 
data/Rakefile CHANGED
@@ -1,17 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # require "rake"
4
- # require "sancho"
5
- # tasks, folders = Sancho.tasks
6
- # Rake.application.rake_require tasks, folders
7
-
8
3
  require "bundler/gem_tasks"
9
- require "rake/testtask"
4
+ require "minitest/test_task"
10
5
 
11
- Rake::TestTask.new(:test) do |t|
12
- t.libs << "test"
13
- t.libs << "lib"
14
- t.test_files = FileList["test/**/test_*.rb"]
15
- end
6
+ Minitest::TestTask.create
16
7
 
17
8
  task default: :test
data/exe/marko CHANGED
@@ -1,22 +1,4 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "marko"
5
- include Marko
6
-
7
- command = ARGV.shift
8
- case command
9
- when nil
10
- CLI.banner
11
- when /(n|new)/
12
- dir = ARGV.shift
13
- CLI.punch(dir)
14
- when /(c|compile)/
15
- CLI.compile
16
- when /(d|demo)/
17
- CLI.punch_demo
18
- when /(samples)/
19
- CLI.punch_samples
20
- else
21
- CLI.banner
22
- end
1
+ #!/usr/bin/env ruby
2
+ require 'marko'
3
+
4
+ Marko::CLI::parse(ARGV)
data/lib/basic.rb ADDED
@@ -0,0 +1,27 @@
1
+
2
+ # open String and provide some helpful methods
3
+ class String
4
+ # @return [String] with remove non-word characters
5
+ # and adding ?n prfix when it starts from number
6
+ def sanitize
7
+ gsub(/[^\w\s]/, '')
8
+ .gsub(/\s{1,}/, ' ')
9
+ .then{ it.start_with?(/\d/) ? "n#{it}" : it }
10
+ end
11
+
12
+ def underscore
13
+ gsub(/\s{1,}/, ?_)
14
+ end
15
+
16
+ # @return [String] "snake_case" from "CamelCase"
17
+ def snakecase
18
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
19
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
20
+ .downcase
21
+ end
22
+
23
+ # @return [String] "CamelCase" fron "snake_case"
24
+ def camelcase
25
+ split(/_/).map(&:capitalize).join
26
+ end
27
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'config'
2
+ require_relative 'tasks'
3
+
4
+ module Marko
5
+
6
+ # Chain feature
7
+ module Chain
8
+
9
+ # @param chain [Array<Marko::Tasks>]
10
+ # @param payload [Object]
11
+ def self.call(chain, payload)
12
+ achain = chain.dup
13
+ while step = achain.shift
14
+ print " #{step.class}.. "
15
+ payload = step.call(payload)
16
+ puts "OK"
17
+ end
18
+ payload
19
+ end
20
+ end
21
+
22
+ def self.assemble(pattern)
23
+ chain = [
24
+ Tasks::Load.new,
25
+ Tasks::Scan.new,
26
+ Tasks::Parse.new,
27
+ Tasks::Assemble.new(Marko.read_config(Marko::CONFIG)),
28
+ Tasks::Validate.new
29
+ ]
30
+ Chain.call(chain, pattern)
31
+ end
32
+
33
+ def self.compile(pattern)
34
+ chain = [
35
+ Tasks::Load.new,
36
+ Tasks::Scan.new,
37
+ Tasks::Parse.new,
38
+ Tasks::Assemble.new(Marko.read_config(Marko::CONFIG)),
39
+ Tasks::Validate.new,
40
+ Tasks::Compile.new
41
+ ]
42
+ Chain.call(chain, pattern)
43
+ end
44
+ end
data/lib/marko/cli.rb CHANGED
@@ -1,129 +1,119 @@
1
- # frozen_string_literal: true
2
-
3
- require "optparse"
4
- require_relative "services"
5
- include Marko::Services
6
-
7
- module Marko
8
- module CLI
9
- extend self
10
-
11
- def punch(dir, args = ARGV)
12
- if Dir.exist?(dir)
13
- puts "Directory '#{dir}' already exist!"
14
- return
15
- end
16
- storage.punch(dir)
17
- puts "Marko directory created!"
18
- log = Dir.chdir(dir) { Dir.glob('**/*') }
19
- puts log.map{ " created #{dir}/#{_1}" }.join(?\n)
20
- kwargs = options(:new, args)
21
- editor = kwargs.fetch(:editor, '')
22
- Dir.chdir(dir) { `#{editor} .` } unless editor.empty?
23
- end
24
-
25
- def punch_demo(args = ARGV)
26
- # pp options(:demo, args)
27
- log = storage.punch_demo
28
- puts "Marko Demo copied!"
29
- puts log.map{" #{_1}"}.join(?\n)
30
-
31
- kwargs = options(:demo, args)
32
- editor = kwargs.fetch(:editor, '')
33
- Dir.chdir(log) { `#{editor} .` } unless editor.empty?
34
- end
35
-
36
- def punch_samples(args = ARGV)
37
- log = storage.punch_samples
38
- puts "Marko Samples copied!"
39
- puts log.map{" #{_1}"}.join(?\n)
40
- end
41
-
42
- def compile(args = ARGV)
43
- unless storage.marko_home?
44
- puts "Marko directory required!"
45
- return
46
- end
47
- kwargs = options(:compile, args)
48
- verbose = kwargs.delete(:verbose) { false }
49
- pulsefn = method(verbose ? :pulse_verbose : :pulse_concise)
50
- result = Compile.(**kwargs, &pulsefn)
51
- puts "compiled #{result}\nSuccess!"
52
- rescue Marko::Assembler::Failure => e
53
- puts "Assembler failed with #{e.errors.size} #{e.message}"
54
- puts "Failure"
55
- end
56
-
57
- def banner
58
- puts "#{BANNER}\nUsage:"
59
- PARSER.each{|_, cmd| puts "\n #{cmd}"}
60
- end
61
-
62
- protected
63
-
64
- def storage
65
- StoragePlug.plugged
66
- end
67
-
68
- def pulse_verbose(events, payload)
69
- case events
70
- when :stage
71
- puts "#{payload}.."
72
- when :source
73
- print " #{payload}.."
74
- when :errors
75
- unless payload.empty?
76
- puts "#{payload.size} errors #{payload.join}"
77
- else
78
- puts "OK"
79
- end
80
- end
81
- end
82
-
83
- def pulse_concise(events, payload)
84
- case events
85
- when :stage
86
- puts "#{payload}.."
87
- end
88
- end
89
-
90
- def options(cmd, args = ARGV)
91
- {}.tap{|opt| PARSER[cmd].parse(args, into: opt)}
92
- end
93
-
94
- # \ ^__^
95
- # \ (oo)\_______
96
- # (__)\ )\/\
97
- # ||----w |
98
- # || ||
99
- BANNER = <<~EOF.freeze
100
- ~ Marko v#{Marko::VERSION} ~ Markup Compiler
101
- ~ https://github.io/nvoynov/marko
102
- EOF
103
-
104
- PARSER = {
105
- new: OptionParser.new {|cmd|
106
- ban = "marko new|n DIRECTORY [OPTIONS]".ljust(35, ?\s)
107
- cmd.banner = ban + "Create a new Marko project"
108
- cmd.on('-e EDITOR', '--editor EDITOR',
109
- 'Open the project in EDITOR', String)
110
- },
111
- demo: OptionParser.new {|cmd|
112
- ban = "marko demo|d [OPTIONS]".ljust(35, ?\s)
113
- cmd.banner = ban + "Clone Marko Demo project"
114
- cmd.on('-e EDITOR', '--editor EDITOR',
115
- 'Open the project in EDITOR', String)
116
- },
117
- compile: OptionParser.new {|cmd|
118
- ban = "marko compile|c [OPTIONS]".ljust(35, ?\s)
119
- cmd.banner = ban + "Compile Marko artifact"
120
- cmd.on('-t TEMPLATE', '--template TEMPLATE',
121
- 'Template to render', String)
122
- cmd.on('-o FILENAME', '--filename FILENAME',
123
- 'Render to filename', String)
124
- cmd.on('-v', '--verbose', 'Run verbosely')
125
- }
126
- }.freeze
127
-
128
- end
129
- end
1
+ require_relative '../basic'
2
+ require_relative 'config'
3
+ require_relative 'chain'
4
+
5
+ module Marko
6
+
7
+ # Commanmd line interface
8
+ module CLI
9
+ extend self
10
+
11
+ def parse(args)
12
+ command = args.shift
13
+ case command&.to_sym
14
+ when :punch
15
+ punch(args.shift)
16
+ when :assemble, :a
17
+ assemble
18
+ when :compile, :c
19
+ compile
20
+ when :help
21
+ puts "Marko didn't get you", BANNER
22
+ else
23
+ puts "Marko didn't get you", BANNER
24
+ end
25
+ end
26
+
27
+ protected
28
+
29
+ def assemble
30
+ exit_unless_marko('assemble')
31
+
32
+ rescue_marko_errors do
33
+ puts "Marko artifact assemblage:"
34
+ Marko.assemble(File.join('src', '**/*.md'))
35
+ puts "Marko artifact assembled!"
36
+ end
37
+ end
38
+
39
+ def compile
40
+ exit_unless_marko('compile')
41
+
42
+ rescue_marko_errors do
43
+ puts "Marko artifact compilation:"
44
+ compiled = Marko.compile(File.join('src', '**/*.md'))
45
+
46
+ config = Marko.read_config(Marko::CONFIG)
47
+ artifact = config.artifact
48
+ filename = File.join('bin', artifact)
49
+ File.write(filename, compiled)
50
+ puts "Marko artifact compiled!",
51
+ "Find it in #{filename}"
52
+ end
53
+ end
54
+
55
+ def rescue_marko_errors
56
+ yield
57
+ rescue Marko::StageError => e
58
+ puts "Marko failed", e.message,
59
+ e.errors.map{ " #{it.message}" }
60
+ end
61
+
62
+ def exit_unless_marko(command)
63
+ return if File.exist?(Marko::CONFIG)
64
+ puts "Marko '#{command}' requires Marko #{Marko::CONFIG}"
65
+ exit
66
+ end
67
+
68
+ def punch(dir)
69
+ unless dir
70
+ puts "required DIRECTORY"
71
+ exit
72
+ end
73
+
74
+ dir = dir.sanitize.underscore.downcase
75
+ Dir.mkdir(dir)
76
+ Dir.chdir(dir) do
77
+ Dir.mkdir 'bin'
78
+ Dir.mkdir 'src'
79
+ config = Config.new(
80
+ title: dir,
81
+ author: 'one')
82
+ Marko.write_config(Marko::CONFIG, config)
83
+ File.write('README.md', '% README')
84
+ File.write('CHANGELOG.md', CHANGELOG)
85
+ end
86
+
87
+ pattern = File.join(dir, '*')
88
+ punched = Dir[pattern]
89
+ .map{ " #{it}" }
90
+ .join(?\n)
91
+
92
+ puts "Marko punched", punched
93
+ end
94
+
95
+ CHANGELOG = <<~STR
96
+ % CHANGELOG
97
+
98
+ ## Unreleased
99
+
100
+ ## [v0.1.0] #{Time.now.strftime('%Y-%b-%d')}
101
+
102
+ Marko punched
103
+ STR
104
+
105
+ BANNER = <<~STR
106
+ Marko Markdown generator v#{VERSION}
107
+
108
+ Usage:
109
+ # create a new Marko directory
110
+ marko punch DIRECTORY
111
+
112
+ # assemble Marko tree
113
+ marko assemble|a
114
+
115
+ # compile Marko artifact
116
+ marko compile|c
117
+ STR
118
+ end
119
+ end
data/lib/marko/config.rb CHANGED
@@ -1,20 +1,30 @@
1
-
2
- require_relative "parser"
3
- require_relative "storage"
4
- require_relative "compiler"
5
- require_relative "validator"
6
-
7
- module Marko
8
-
9
- # default abstract starters that must be replugged later
10
- ParserPlug = Parser.plug
11
- StoragePlug = Storage.plug
12
- CompilerPlug = Compiler.plug
13
- ValidatorPlug = Validator.plug
14
-
15
- def self.artifact
16
- storage = StoragePlug.plugged
17
- storage.artifact
18
- end
19
-
20
- end
1
+ require 'psych'
2
+
3
+ module Marko
4
+
5
+ VERSION = '0.4.0'
6
+
7
+ CONFIG = 'marko.yml'
8
+
9
+ Config = Data.define(:artifact, :title, :author, :order_index) do
10
+ def initialize(artifact: 'artifact.md', title: 'title',
11
+ author: 'author', order_index: '')
12
+ super
13
+ end
14
+ end
15
+
16
+ def self.read_config(filename)
17
+ dump = File.read(filename)
18
+ Psych.load(dump)
19
+ .transform_keys(&:to_sym)
20
+ .then{ Config.new(**it) }
21
+ end
22
+
23
+ def self.write_config(filename, config = Config.new)
24
+ data = config.to_h.transform_keys(&:to_s)
25
+
26
+ dump = Psych.dump(data)
27
+ File.write(filename, dump)
28
+ end
29
+
30
+ end