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
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../validator"
4
-
5
- module Marko
6
- module Markup
7
- class Validator < Marko::Validator
8
-
9
- def initialize
10
- @inspectors = []
11
- @inspectors << TheSameId.new
12
- @inspectors << LostParent.new
13
- @inspectors << LostIndex.new
14
- @inspectors << LostLink.new
15
- end
16
-
17
- # see Marko::Validator#call
18
- def call(tree)
19
- [].tap{|errors|
20
- @inspectors.each{|spectr| errors.concat(spectr.(tree)) }
21
- }
22
- end
23
-
24
- end
25
-
26
- class Inspector
27
- def call(tree)
28
- select(tree).then{ report(_1) }
29
- end
30
-
31
- def select(tree)
32
- fail "the abstract method must be overriden"
33
- end
34
-
35
- def report(errs)
36
- fail "the abstract method must be overriden"
37
- end
38
-
39
- end
40
-
41
- class TheSameId < Inspector
42
- def select(tree)
43
- fn = proc{|n, memo| memo[n.id] ||= []; memo[n.id] << n}
44
- tree
45
- .each_with_object({}, &fn)
46
- .select{|_, v| v.size > 1}
47
- end
48
-
49
- def report(errs)
50
- # the same id [ref] found twice
51
- # src/source2.md:22 >> ## header
52
- # src/source3.md:11 >> ## header
53
- errs.map{|id, nodes|
54
- sources = nodes.map{|n| " #{n[:origin]}\n"}.join
55
- "the same id [#{id}] found in\n#{sources}"
56
- }
57
- end
58
- end
59
-
60
- class LostParent < Inspector
61
- def select(tree)
62
- tree.select{|n| n[:parent] && n.parent_id != n[:parent]}
63
- end
64
-
65
- def report(errs)
66
- # lost parent [ref] src/source2.md:22 >> ## header
67
- errs.map{|n| "lost parent [#{n[:parent]}] found in #{n[:origin]}\n"}
68
- end
69
- end
70
-
71
- class LostIndex < Inspector
72
- def select(tree)
73
- lost = proc{|n| n.order_index.reject{|i| n.find_item(i)}}
74
- tree
75
- .select{|n| n.order_index.any? && lost.(n).any?}
76
- .map{|n| [n[:origin], lost.(n)]} # @todo second time calculation
77
- end
78
-
79
- def report(errs)
80
- # lost index [a, b] src/source2.md:22 >> ## header
81
- errs.map{|orig, lost| "lost index [#{lost.join(', ')}] in #{orig}\n" }
82
- end
83
- end
84
-
85
- class LostLink < Inspector
86
- def select(tree)
87
- lost = proc{|n| n.links.reject{|i| n.find_node(i)}}
88
- tree
89
- .select{|n| lost.(n).any? }
90
- .map{|n| [n[:origin], lost.(n)]} # @todo second time #lost calculation
91
- end
92
-
93
- # @todo report link line number in the origin
94
- def report(errs)
95
- # lost links [ref] src/source2.md:22 >> ## header
96
- errs.map{|orig, lost| "lost link [#{lost.join(', ')}] in #{orig}\n"}
97
- end
98
- end
99
-
100
- end
101
- end
data/lib/marko/markup.rb DELETED
@@ -1,24 +0,0 @@
1
- require_relative "markup/parser"
2
- require_relative "markup/storage"
3
- require_relative "markup/validator"
4
- require_relative "markup/macro"
5
- require_relative "markup/decorator"
6
- require_relative "markup/compiler"
7
- require_relative "config"
8
-
9
-
10
- module Marko
11
-
12
- ParserPlug.plug Markup::Parser
13
- StoragePlug.plug Markup::Storage
14
- CompilerPlug.plug Markup::Compiler
15
- ValidatorPlug.plug Markup::Validator
16
-
17
- # ParserPlug = Markup::Parser.plug
18
- # StoragePlug = Markup::Storage.plug
19
- # @todo let Decorator know
20
- MacroProcPlug = Markup::MacroProcessor.plug
21
- # ValidatorPlug = Markup::Validator.plug
22
- # CompilerPlug = Markup::Compiler.plug
23
-
24
- end
@@ -1,16 +0,0 @@
1
- require_relative "../gadgets"
2
- require_relative "../assembler"
3
-
4
- module Marko
5
- module Services
6
-
7
- # Assemblage service
8
- # @todo assemble projects bu url
9
- class Assemble < Service
10
- def call
11
- Assembler.(&@block)
12
- end
13
- end
14
-
15
- end
16
- end
@@ -1,30 +0,0 @@
1
- require_relative "../gadgets"
2
- require_relative "../assembler"
3
-
4
- module Marko
5
- module Services
6
-
7
- # Compitation service
8
- class Compile < Service
9
- def initialize(tree: nil, template: '', filename: '', &block)
10
- @tree = MustbeTreeNode.(tree) if tree
11
- @template = MustbeString.(template)
12
- @filename = MustbeString.(filename)
13
- @block = block
14
-
15
- art = Marko.artifact
16
- @template = art.template if @template.empty?
17
- @filename = art.filename if @filename.empty?
18
- end
19
-
20
- def call
21
- storage = StoragePlug.plugged
22
- compiler = CompilerPlug.plugged
23
- erb = storage.content(@template)
24
- @tree = Assembler.(&@block) unless @tree
25
- compiler.(@tree, erb, @filename, &@block) # => filename
26
- end
27
- end
28
-
29
- end
30
- end
@@ -1,2 +0,0 @@
1
- require_relative "services/assemble"
2
- require_relative "services/compile"
data/lib/marko/storage.rb DELETED
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "gadgets"
4
- require_relative "artifact"
5
-
6
- module Marko
7
-
8
- # The base class that represents sources repository
9
- class Storage
10
- extend Pluggable
11
-
12
- # create a new repository
13
- # @param repository [String] the name for the repository
14
- def punch(repository)
15
- fail "the abstract method must be overriden"
16
- end
17
-
18
- # @retrun [Array<String>] array of sources inside the repository
19
- def sources
20
- fail "the abstract method must be overriden"
21
- end
22
-
23
- # @param source [Striing] source to retrieve content
24
- # @return [String] content of :source
25
- def content(source)
26
- fail "the abstract method must be overriden"
27
- end
28
-
29
- # @return [Artifact] artifact settings
30
- def artifact
31
- fail "the abstract method must be overriden"
32
- end
33
-
34
- end
35
-
36
- end
@@ -1,128 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "forwardable"
4
- require_relative "gadgets"
5
-
6
- module Marko
7
-
8
- MustbeString = Sentry.new(:key, "must be String"
9
- ) {|v| v.is_a? String}
10
-
11
- MustbeTreeNode = Sentry.new(:key, "must be TreeNode"
12
- ) {|v| v.is_a? TreeNode}
13
-
14
- class TreeNode
15
- extend Forwardable
16
- include Enumerable
17
-
18
- attr_reader :parent
19
- attr_reader :title
20
- attr_reader :meta
21
- attr_reader :body
22
-
23
- def_delegators :@meta, :[], :[]=
24
- def_delegator :@items, :last
25
- def_delegator :@items, :delete, :delete_item
26
- def_delegator :@meta, :delete, :delete_meta
27
- def_delegator :@parent, :id, :parent_id
28
-
29
- def initialize(title = '', body = '', **meta)
30
- @parent, @items = nil, []
31
- @title = MustbeString.(title, :title)
32
- @body = MustbeString.(body, :body)
33
- @meta = meta
34
- @meta[:id] = '' unless @meta[:id]
35
- end
36
-
37
- def <<(node)
38
- MustbeTreeNode.(node)
39
- node.parent = self
40
- @items << node
41
- node
42
- end
43
-
44
- # see Enumerable#each
45
- def each(&block)
46
- return to_enum(__callee__) unless block_given?
47
- yield(self)
48
- items.each{|n| n.each(&block) }
49
- end
50
-
51
- # @return [Array<String>]
52
- def order_index
53
- @meta
54
- .fetch(:order_index, '')
55
- .strip
56
- .split(/\s{1,}/)
57
- end
58
-
59
- def id
60
- val = @meta.fetch(:id, '')
61
- return val unless @parent
62
- val.start_with?('.') ? @parent.id + val : val
63
- end
64
-
65
- def find_item(ref)
66
- @items.find{|n| n.id == ref || n.id.end_with?(ref)}
67
- end
68
-
69
- def find_node(ref)
70
- return find_item(ref) if ref.start_with?(?.)
71
- root.find{|n| n.id == ref}
72
- end
73
-
74
- # @return [Array<Node>] ordered list of child nodes
75
- def items
76
- return @items unless order_index.any?
77
- [].tap do |ary|
78
- src = Array.new(@items)
79
- order_index.each do |i|
80
- node = find_item(i)
81
- ary << src.delete(node) if node
82
- end
83
- ary.concat(src)
84
- end
85
- end
86
-
87
- def belongs_to?(ref)
88
- owner = root.find{|n| n.id == ref}
89
- self == owner&.find{|n| n == self}
90
- end
91
-
92
- # @return [Node] the root node in the node hierarchy
93
- def root
94
- n = self
95
- n = n.parent while n.parent
96
- n
97
- end
98
-
99
- def root?
100
- self == root
101
- end
102
-
103
- # @return [Integer] the node level in the node hierarchy
104
- def nesting_level
105
- @parent.nil? ? 0 : @parent.nesting_level + 1
106
- end
107
-
108
- # @return [Array<String>] macro links in the node #body IT IS RATHER MACRO FOR WRITER SO TI SHOULD BE PROCESSED APPROPRIATELY
109
- def links
110
- return [] if @body.empty?
111
- @body.scan(/\[\[([\w\.]*)\]\]/).flatten.uniq
112
- end
113
-
114
- def orphan!
115
- return unless @parent
116
- @parent.delete_item(self)
117
- @parent = nil
118
- end
119
-
120
- protected
121
-
122
- def parent=(node)
123
- @parent = MustbeTreeNode.(node)
124
- end
125
-
126
- end
127
-
128
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "tree_node"
4
-
5
- module Marko
6
-
7
- # The strategy of tree validation
8
- class Validator
9
- extend Pluggable
10
-
11
- # @param tree [TreeNode]
12
- # @param block [&block] proc {|event, payload|}
13
- # @return [Array<String>] errors array
14
- def call(tree, &block)
15
- fail "the abstract method must be overriden"
16
- end
17
- end
18
-
19
- end
data/marko.gemspec DELETED
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/marko/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "marko"
7
- spec.version = Marko::VERSION
8
- spec.authors = ["Nikolay Voynov"]
9
- spec.email = ["nvoynov@gmail.com"]
10
-
11
- spec.summary = "Marko is a markup compiler that builds a tree from separated markup sources and compiles it into a deliverable artifact."
12
-
13
- spec.description = <<~EOF
14
- Marko supplies a "docs-as-code" approach for compiling bulky software artifacts by providing source storage, original plain text markup, compiler templates, command-line and Gem interfaces.
15
-
16
- Having the assembled artifact, it can be analyzed, enriched by extra data, served as a source for deriving subdued artifacts, etc.
17
- EOF
18
-
19
- spec.homepage = "https://github.com/nvoynov/marko"
20
- spec.required_ruby_version = ">= 2.6.0"
21
-
22
- spec.metadata["allowed_push_host"] = "https://rubygems.org"
23
-
24
- spec.metadata["homepage_uri"] = spec.homepage
25
- spec.metadata["source_code_uri"] = spec.homepage
26
- spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md"
27
-
28
- # Specify which files should be added to the gem when it is released.
29
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
- spec.files = Dir.chdir(__dir__) do
31
- `git ls-files -z`.split("\x0").reject do |f|
32
- (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
33
- end
34
- end
35
- spec.bindir = "exe"
36
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
37
- spec.require_paths = ["lib"]
38
-
39
- # Uncomment to register a new dependency of your gem
40
- # spec.add_dependency "example-gem", "~> 1.0"
41
-
42
- # For more information and examples about making a new gem, check out our
43
- # guide at: https://bundler.io/guides/creating_gem.html
44
- end