marko 0.1.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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +12 -0
  3. data/.rubocop.yml +45 -0
  4. data/CHANGELOG.md +54 -1
  5. data/Dockerfile +11 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +24 -35
  8. data/Rakefile +2 -6
  9. data/exe/marko +4 -20
  10. data/lib/basic.rb +27 -0
  11. data/lib/marko/chain.rb +44 -0
  12. data/lib/marko/cli.rb +119 -121
  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 -35
  49. metadata +47 -54
  50. data/Gemfile +0 -10
  51. data/Gemfile.lock +0 -22
  52. data/lib/assets/demo/README.md +0 -13
  53. data/lib/assets/demo/src/fr/assemble.md +0 -27
  54. data/lib/assets/demo/src/fr/compile.md +0 -25
  55. data/lib/assets/demo/src/fr/markup.md +0 -111
  56. data/lib/assets/demo/src/fr/storage.md +0 -16
  57. data/lib/assets/demo/src/fr/treenode.md +0 -34
  58. data/lib/assets/demo/src/index.md +0 -34
  59. data/lib/assets/demo/src/intro.md +0 -98
  60. data/lib/assets/demo/src/ui/cli.md +0 -26
  61. data/lib/assets/demo/src/ui/gem.md +0 -14
  62. data/lib/assets/demo/src/ur/uc.create.project.md +0 -8
  63. data/lib/assets/demo/src/ur/uc.general.flow.md +0 -14
  64. data/lib/assets/init/README.md +0 -61
  65. data/lib/assets/init/Rakefile +0 -100
  66. data/lib/assets/init/tt/artifact.md.tt +0 -3
  67. data/lib/marko/artifact.rb +0 -3
  68. data/lib/marko/assembler.rb +0 -82
  69. data/lib/marko/compiler.rb +0 -16
  70. data/lib/marko/gadgets/pluggable.rb +0 -55
  71. data/lib/marko/gadgets/sentry.rb +0 -66
  72. data/lib/marko/gadgets/service.rb +0 -52
  73. data/lib/marko/gadgets.rb +0 -3
  74. data/lib/marko/loader.rb +0 -38
  75. data/lib/marko/markup/compiler.rb +0 -36
  76. data/lib/marko/markup/decorator.rb +0 -65
  77. data/lib/marko/markup/macro.rb +0 -176
  78. data/lib/marko/markup/parser.rb +0 -122
  79. data/lib/marko/markup/storage.rb +0 -100
  80. data/lib/marko/markup/validator.rb +0 -101
  81. data/lib/marko/markup.rb +0 -24
  82. data/lib/marko/services/assemble.rb +0 -16
  83. data/lib/marko/services/compile.rb +0 -30
  84. data/lib/marko/services.rb +0 -2
  85. data/lib/marko/storage.rb +0 -36
  86. data/lib/marko/tree_node.rb +0 -128
  87. data/lib/marko/validator.rb +0 -19
  88. data/marko.gemspec +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f907c502f514d2cd27122f2c2d6acf4e96c066515075c7b8df69b39c3022ee85
4
- data.tar.gz: 075f639071daab8f53d56fec821196514f8c614c58b43b1cbc2306fc616f9f24
3
+ metadata.gz: 5831f616f2b1b2ae35890d79e685dd75efbe0553ebce040b04ce501656667cba
4
+ data.tar.gz: f6aaa2fdb7814193c221791b77331510374fc85a265e48138a4501be00f0ab26
5
5
  SHA512:
6
- metadata.gz: fcdf1096aec13270c9a87ed229feda55c81e95de4073b7de264cb8b42dcd66ca2031f643bba63b40c9db2da2e83e945b817866589e4ecb3e2abebb04e2592ad3
7
- data.tar.gz: df5ea3a5f9cdc378aee2bbe8292b3dc3d0e033da11a676a8fcaa5b5c294f614b0e23609ac6a633c79e1725ee9af462be1849a780ff4d1b45f1158ed417601f4e
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,4 +1,57 @@
1
- ## [Unreleased]
1
+ ---
2
+ title: Marko Changelog
3
+ keywords:
4
+ - ruby
5
+ - markup-compiler
6
+ ...
7
+
8
+ ## [Unreleased] 2025-Sep-04
9
+
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
17
+
18
+ ## [0.3.0] - 2023-11-22
19
+
20
+ - changed `Markup::Compiler` for using collection instead of decorated object
21
+ - changed `Markup::Decorator` for providing `#text` than combines header, props, and body
22
+ - changed `default` and `custom` templates
23
+ - fixed `rake marko:toc` for using `abort` instead of `return` for empty query
24
+ - removed unused `id` from `marko.yml`
25
+
26
+ ## [0.2.4] - 2023-11-21
27
+
28
+ - changed compiler for using `trim_mode: '%<>'` for ERB
29
+ - changed decorator
30
+ - removed `?\n` in `#header`, `#body`
31
+ - changed `#meta` for returning original meta without system keys
32
+ - added `#props` for creating `meta` table
33
+ - added `alias :topic :header`
34
+ - changed `tt/artifact.md.tt` for removing extra empty lines
35
+ - added `tt/custom.md.tt` as an example of handling custom meta keys
36
+ - added test for `tt/*.md.tt`
37
+
38
+ ## [0.2.3] - 2023-11-06
39
+
40
+ - upgraded for Ruby 3.2
41
+ - fixed `assets/init/Rakefile` for lost file extension
42
+ - removed extra word from README
43
+
44
+ ## [0.2.2] - 2023-04-14
45
+
46
+ - changed artifact filename into `bin/artifact.md`; fixed `README.md`
47
+ - removed Psych object string from `marko.yml`
48
+ - changed `TreeNode#belongs_to?`
49
+
50
+ ## [0.2.0] - 2023-02-11
51
+
52
+ - added `$ marko samples` that copies samples into `.marko/samples`
53
+ - fixed "Marko v0.1.3" error gem version
54
+ - changed `$ marko demo`, now it copies demo into `.marko/demo`
2
55
 
3
56
  ## [0.1.0] - 2023-01-02
4
57
 
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
@@ -1,8 +1,13 @@
1
- # Marko
1
+ ---
2
+ title: Marko Readme
3
+ keywords:
4
+ - ruby
5
+ - markup-compiler
6
+ ...
2
7
 
3
- 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.
4
9
 
5
- 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.
6
11
 
7
12
  Having assembled the artifact, it can be analyzed, enriched by extra data, etc.; it can serve as a source for deriving subdued artifacts.
8
13
 
@@ -20,27 +25,25 @@ Install the gem by executing:
20
25
 
21
26
  Marko provides just basic command-line interface for creating new projects and assembling artifacts - run `$ marko` to see the details.
22
27
 
23
- 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.
24
29
 
25
- 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.
26
31
 
27
32
  ### Structure
28
33
 
29
- `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:
30
35
 
31
- - [bin/](bin/) - output folder for `build`
32
- - [bin/assets/](bin/assets/) - assets folder
33
- - [src/](src/) - markup sources
34
- - [tt/](tt/) - templates for `build`
35
- - [marko.yml](marko.yml) - project configuration
36
- - [Rakefile](Rakefile) - Rake automation file
37
- - [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`
38
41
 
39
42
  ### Markup
40
43
 
41
- 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.
42
45
 
43
- 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.
44
47
 
45
48
  Let's see it by example and assume one has a few separate sources `content.md`, `uc.signup.md`, and `uc.signin.md`.
46
49
  `content.md`
@@ -90,7 +93,7 @@ body markup
90
93
  # Functional requirements
91
94
  ```
92
95
 
93
- 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`.
94
97
 
95
98
  ### Metadata
96
99
 
@@ -110,30 +113,16 @@ The TreeNode.body can include macros. The most helpful one is `[[reference.id]]`
110
113
 
111
114
  - `@@tree` substituted by the tree of references to all descendants of the current node, might be used for the table of contents;
112
115
  - `@@list` substituted by the list of references to node items;
113
- - `@@todo` will will skip text with the macro till the end of the line
116
+ - `@@todo` will skip text with the macro till the end of the line
114
117
  - `@@skip` will skip the text after the macro
115
118
 
116
- ### Templates
119
+ ### marko.yml configuraton
117
120
 
118
- 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 enumerates TreeNodes and renders the node output.
121
+ The `marko.yml` configuration file provide a few configuration parametera like artifact name, title, author and order_index.
119
122
 
120
- ```
121
- <%= @node.header %>
122
- <%= @node.meta %>
123
- <%= @node.body %>
124
- ```
125
-
126
- The `marko.yml` configuration file sets the building process's default template and other default values.
127
-
128
- ```yml
129
- --- !ruby/struct:Marko::Artifact
130
- id: ed863484-243f-4d46-8012-4b148f8c2910
131
- title: Marko Artifact
132
- template: tt/artifact.md.tt
133
- filename: tt/marko-artifact.md
134
- ```
123
+ You can change it any time and it will affect the next assemble/ compile run
135
124
 
136
- ### Automation
125
+ ### Automation (UNDER CONSTRUCTION)
137
126
 
138
127
  Following quick example will assemble tree, remove TreeNode with id == 'hint', and compile the tree. You can also see Rakefile for other examples.
139
128
 
data/Rakefile CHANGED
@@ -1,12 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- require "rake/testtask"
4
+ require "minitest/test_task"
5
5
 
6
- Rake::TestTask.new(:test) do |t|
7
- t.libs << "test"
8
- t.libs << "lib"
9
- t.test_files = FileList["test/**/test_*.rb"]
10
- end
6
+ Minitest::TestTask.create
11
7
 
12
8
  task default: :test
data/exe/marko CHANGED
@@ -1,20 +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 /(d|demo)/
15
- CLI.punch_demo
16
- when /(c|compile)/
17
- CLI.compile
18
- else
19
- CLI.banner
20
- 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,121 +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 cloned!\n#{log}"
29
- kwargs = options(:demo, args)
30
- editor = kwargs.fetch(:editor, '')
31
- Dir.chdir(log) { `#{editor} .` } unless editor.empty?
32
- end
33
-
34
- def compile(args = ARGV)
35
- unless storage.marko_home?
36
- puts "Marko directory required!"
37
- return
38
- end
39
- kwargs = options(:compile, args)
40
- verbose = kwargs.delete(:verbose) { false }
41
- pulsefn = method(verbose ? :pulse_verbose : :pulse_concise)
42
- result = Compile.(**kwargs, &pulsefn)
43
- puts "compiled #{result}\nSuccess!"
44
- rescue Marko::Assembler::Failure => e
45
- puts "Assembler failed with #{e.errors.size} #{e.message}"
46
- puts "Failure"
47
- end
48
-
49
- def banner
50
- puts "#{BANNER}\nUsage:"
51
- PARSER.each{|_, cmd| puts "\n #{cmd}"}
52
- end
53
-
54
- protected
55
-
56
- def storage
57
- StoragePlug.plugged
58
- end
59
-
60
- def pulse_verbose(events, payload)
61
- case events
62
- when :stage
63
- puts "#{payload}.."
64
- when :source
65
- print " #{payload}.."
66
- when :errors
67
- unless payload.empty?
68
- puts "#{payload.size} errors #{payload.join}"
69
- else
70
- puts "OK"
71
- end
72
- end
73
- end
74
-
75
- def pulse_concise(events, payload)
76
- case events
77
- when :stage
78
- puts "#{payload}.."
79
- end
80
- end
81
-
82
- def options(cmd, args = ARGV)
83
- {}.tap{|opt| PARSER[cmd].parse(args, into: opt)}
84
- end
85
-
86
- # \ ^__^
87
- # \ (oo)\_______
88
- # (__)\ )\/\
89
- # ||----w |
90
- # || ||
91
- BANNER = <<~EOF.freeze
92
- ~ Marko v0.1.3 ~ Markup Compiler
93
- ~ https://github.io/nvoynov/marko
94
- EOF
95
-
96
- PARSER = {
97
- new: OptionParser.new {|cmd|
98
- ban = "marko new|n DIRECTORY [OPTIONS]".ljust(35, ?\s)
99
- cmd.banner = ban + "Create a new Marko project"
100
- cmd.on('-e EDITOR', '--editor EDITOR',
101
- 'Open the project in EDITOR', String)
102
- },
103
- demo: OptionParser.new {|cmd|
104
- ban = "marko demo|d [OPTIONS]".ljust(35, ?\s)
105
- cmd.banner = ban + "Clone Marko Demo project"
106
- cmd.on('-e EDITOR', '--editor EDITOR',
107
- 'Open the project in EDITOR', String)
108
- },
109
- compile: OptionParser.new {|cmd|
110
- ban = "marko compile|c [OPTIONS]".ljust(35, ?\s)
111
- cmd.banner = ban + "Compile Marko artifact"
112
- cmd.on('-t TEMPLATE', '--template TEMPLATE',
113
- 'Template to render', String)
114
- cmd.on('-o FILENAME', '--filename FILENAME',
115
- 'Render to filename', String)
116
- cmd.on('-v', '--verbose', 'Run verbosely')
117
- }
118
- }.freeze
119
-
120
- end
121
- 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