clerq 0.1.0 → 0.3.3
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.
- checksums.yaml +4 -4
- data/.gitignore +4 -3
- data/CHANGELOG.md +49 -0
- data/Gemfile.lock +9 -9
- data/README.md +260 -133
- data/Rakefile +1 -0
- data/clerq.gemspec +6 -6
- data/clerq.thor +28 -0
- data/docs/README.md +408 -0
- data/lib/assets/knb/SRS-IEEE-830-1998.md +293 -0
- data/lib/assets/knb/SRS-RUP.md +283 -0
- data/lib/assets/knb/business-case.md +135 -0
- data/lib/assets/knb/ears-with-examples.md +101 -0
- data/lib/assets/knb/problem-statement.md +8 -0
- data/lib/assets/knb/product-statement.md +8 -0
- data/lib/assets/knb/requirement-attributes.md +26 -0
- data/lib/assets/knb/requirement-classification.md +27 -0
- data/lib/assets/knb/requirement-life-cycle.md +47 -0
- data/lib/assets/knb/requirement-quality.md +13 -0
- data/lib/assets/knb/use-case.md +39 -0
- data/lib/assets/knb/vision-document.md +191 -0
- data/lib/assets/lib/clerq_doc.thor +119 -0
- data/lib/assets/lib/colonize_repo.rb +82 -0
- data/lib/assets/lib/spec/colonize_repo_spec.rb +85 -0
- data/lib/assets/new/clerq.thor.tt +32 -5
- data/lib/assets/new/content.md.tt +3 -40
- data/lib/assets/tt/default.md.erb +23 -42
- data/lib/assets/tt/pandoc.md.erb +11 -8
- data/lib/clerq.rb +57 -12
- data/lib/clerq/cli.rb +77 -60
- data/lib/clerq/entities.rb +0 -1
- data/lib/clerq/entities/node.rb +135 -115
- data/lib/clerq/properties.rb +1 -3
- data/lib/clerq/repositories.rb +2 -4
- data/lib/clerq/repositories/file_repository.rb +59 -0
- data/lib/clerq/repositories/node_repository.rb +72 -30
- data/lib/clerq/repositories/text_repository.rb +47 -0
- data/lib/clerq/services.rb +8 -0
- data/lib/clerq/services/check_assembly.rb +108 -0
- data/lib/clerq/{interactors → services}/create_node.rb +12 -11
- data/lib/clerq/services/load_assembly.rb +54 -0
- data/lib/clerq/services/query_node.rb +72 -0
- data/lib/clerq/services/query_template.rb +26 -0
- data/lib/clerq/services/read_node.rb +101 -0
- data/lib/clerq/services/render_erb.rb +29 -0
- data/lib/clerq/services/render_node.rb +37 -0
- data/lib/clerq/services/service.rb +19 -0
- data/lib/clerq/settings.rb +2 -2
- data/lib/clerq/version.rb +1 -1
- metadata +49 -37
- data/TODO.md +0 -3
- data/lib/assets/tt/gitlab.md.erb +0 -93
- data/lib/assets/tt/raw.md.erb +0 -23
- data/lib/clerq/entities/template.rb +0 -19
- data/lib/clerq/gateways.rb +0 -3
- data/lib/clerq/gateways/gateway.rb +0 -17
- data/lib/clerq/gateways/in_files.rb +0 -36
- data/lib/clerq/gateways/in_memory.rb +0 -35
- data/lib/clerq/interactors.rb +0 -5
- data/lib/clerq/interactors/check_nodes.rb +0 -81
- data/lib/clerq/interactors/compile_nodes.rb +0 -31
- data/lib/clerq/interactors/interactor.rb +0 -28
- data/lib/clerq/interactors/join_nodes.rb +0 -59
- data/lib/clerq/interactors/query_nodes.rb +0 -62
- data/lib/clerq/repositories/in_memory.rb +0 -45
- data/lib/clerq/repositories/node_reader.rb +0 -107
- data/lib/clerq/repositories/repository.rb +0 -11
- data/lib/clerq/repositories/template_repository.rb +0 -53
- data/lib/clerq/templater.rb +0 -32
data/TODO.md
DELETED
data/lib/assets/tt/gitlab.md.erb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
<%
|
2
|
-
require 'delegate'
|
3
|
-
# Template for generate documents by Pandoc
|
4
|
-
class MarkupNode < SimpleDelegator
|
5
|
-
def title
|
6
|
-
[].tap do |ary|
|
7
|
-
ary << '#' * (nesting_level + 1)
|
8
|
-
ary << '[' + id + ']' unless __getobj__.meta[:skip_meta]
|
9
|
-
ary << super
|
10
|
-
end.join(' ')
|
11
|
-
end
|
12
|
-
|
13
|
-
def meta
|
14
|
-
return '' if nesting_level == 0
|
15
|
-
return '' if super[:skip_meta]
|
16
|
-
|
17
|
-
hsh = {}.merge(super)
|
18
|
-
hsh.delete(:order_index)
|
19
|
-
hsh.delete(:file_name)
|
20
|
-
hsh.delete(:parent)
|
21
|
-
return '' if hsh.empty?
|
22
|
-
|
23
|
-
[].tap{|ary|
|
24
|
-
ary << "Attribute | Value"
|
25
|
-
ary << "--------- | -----"
|
26
|
-
hsh.each{|k,v| ary << "#{k} | #{v}"}
|
27
|
-
}.join("\n")
|
28
|
-
end
|
29
|
-
|
30
|
-
def body
|
31
|
-
# links replacement
|
32
|
-
txt = String.new(super)
|
33
|
-
links.each{|l| txt.gsub! "[[#{l}]]", link(l)}
|
34
|
-
# macro substitution
|
35
|
-
macro.each{|m| txt.gsub! m.regex, m.substitution}
|
36
|
-
txt
|
37
|
-
end
|
38
|
-
|
39
|
-
def link(ref)
|
40
|
-
node = root.find{|n| n.id == ref}
|
41
|
-
return "[#{ref}](#unknown)" unless node
|
42
|
-
"[#{node.title}](##{url(node.title)})"
|
43
|
-
end
|
44
|
-
|
45
|
-
def url(id)
|
46
|
-
id.downcase
|
47
|
-
.gsub(/[^A-Za-z0-9]{1,}/, '-')
|
48
|
-
.gsub(/^-/, '')
|
49
|
-
.gsub(/-$/, '')
|
50
|
-
end
|
51
|
-
|
52
|
-
class Macro
|
53
|
-
attr_reader :regex
|
54
|
-
def initialize(regex, &substitution)
|
55
|
-
@regex, @substitution = regex, substitution
|
56
|
-
end
|
57
|
-
|
58
|
-
def substitution
|
59
|
-
@substitution.call()
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def macro
|
64
|
-
[].tap do |ary|
|
65
|
-
ary << Macro.new(/{{@@skip[\s\S]*?}}/, &Proc.new{ '' })
|
66
|
-
ary << Macro.new("{{@@list}}", &Proc.new{list})
|
67
|
-
ary << Macro.new("{{@@tree}}", &Proc.new{tree})
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def tree
|
72
|
-
this_level = nesting_level + 1
|
73
|
-
to_a.drop(1).inject([]) do |ary, n|
|
74
|
-
lead_spaces = ' ' * (n.nesting_level - this_level)
|
75
|
-
ary << "#{lead_spaces}* [#{n.title}](##{url(n.id)})"
|
76
|
-
end.join("\n")
|
77
|
-
end
|
78
|
-
|
79
|
-
def list
|
80
|
-
items.inject([]) do |ary, n|
|
81
|
-
ary << "* [#{n.title}](##{url(n.id)})"
|
82
|
-
end.join("\n")
|
83
|
-
end
|
84
|
-
end
|
85
|
-
-%>
|
86
|
-
% <%= @object.title %>
|
87
|
-
% generated by Clerq on <%= Time.now.strftime('%B %e, %Y at %H:%M') %>
|
88
|
-
|
89
|
-
<% for @node in @object.to_a.drop(1) -%>
|
90
|
-
<% n = MarkupNode.new(@node) -%>
|
91
|
-
<%= [n.title, n.meta, n.body].select{|t| !t.empty?}.join("\n\n") %>
|
92
|
-
|
93
|
-
<% end %>
|
data/lib/assets/tt/raw.md.erb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
<%
|
2
|
-
# template for saving created nodes
|
3
|
-
require 'delegate'
|
4
|
-
class MarkupNode < SimpleDelegator
|
5
|
-
def title
|
6
|
-
'#' * (nesting_level + 1) + ' [' + id + '] ' + super
|
7
|
-
end
|
8
|
-
|
9
|
-
def meta
|
10
|
-
return '' if super.empty?
|
11
|
-
[].tap{|ary|
|
12
|
-
ary << '{{'
|
13
|
-
hsh.each{|k,v| ary << "#{k}: #{v}"}
|
14
|
-
ary << '}}'
|
15
|
-
}.join("\n")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
-%>
|
19
|
-
<% for @node in @object.to_a.drop(1) -%>
|
20
|
-
<% n = MarkupNode.new(@node) -%>
|
21
|
-
<%= [n.title, n.meta, n.body].select{|t| !t.empty?}.join("\n\n") %>
|
22
|
-
|
23
|
-
<% end %>
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
module Clerq
|
4
|
-
module Entities
|
5
|
-
|
6
|
-
class Template
|
7
|
-
attr_reader :id
|
8
|
-
attr_reader :body
|
9
|
-
|
10
|
-
def initialize(id:, body: '')
|
11
|
-
raise ArgumentError, "Invalid argument :id" if !(id.is_a?(String) && !id.empty?)
|
12
|
-
raise ArgumentError, "Invalid argument :body" unless body.is_a? String
|
13
|
-
@id = id
|
14
|
-
@body = body
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
data/lib/clerq/gateways.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require "forwardable"
|
4
|
-
require_relative '../repositories'
|
5
|
-
require_relative 'gateway'
|
6
|
-
|
7
|
-
module Clerq
|
8
|
-
module Gateways
|
9
|
-
|
10
|
-
class InFiles < Gateway
|
11
|
-
extend Forwardable
|
12
|
-
|
13
|
-
attr_reader :node_repo, :tplt_repo
|
14
|
-
|
15
|
-
def_delegator :@node_repo, :items, :nodes
|
16
|
-
def_delegator :@tplt_repo, :items, :templates
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
settings = Clerq.settings
|
20
|
-
@node_repo = Clerq::Repositories::NodeRepository.new(settings.src)
|
21
|
-
@tplt_repo = Clerq::Repositories::TemplateRepository.new(settings.tt)
|
22
|
-
@repositories = {}
|
23
|
-
@repositories[Clerq::Entities::Node] = @node_repo
|
24
|
-
@repositories[Clerq::Entities::Template] = @tplt_repo
|
25
|
-
end
|
26
|
-
|
27
|
-
def save(obj)
|
28
|
-
repo = @repositories[obj.class]
|
29
|
-
raise ArgumentError, "Repository for #{obj.class} not found" unless repo
|
30
|
-
repo.save(obj)
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require "forwardable"
|
4
|
-
require_relative "gateway"
|
5
|
-
require_relative "../repositories/in_memory"
|
6
|
-
|
7
|
-
module Clerq
|
8
|
-
module Gateways
|
9
|
-
|
10
|
-
class InMemory < Gateway
|
11
|
-
extend Forwardable
|
12
|
-
|
13
|
-
attr_reader :node_repo, :template_repo
|
14
|
-
|
15
|
-
def_delegator :@node_repo, :items, :nodes
|
16
|
-
def_delegator :@template_repo, :items, :templates
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
@node_repo = Clerq::Repositories::InMemory.new
|
20
|
-
@template_repo = Clerq::Repositories::InMemory.new
|
21
|
-
@repositories = {}
|
22
|
-
@repositories[Clerq::Entities::Node] = @node_repo
|
23
|
-
@repositories[Clerq::Entities::Template] = @template_repo
|
24
|
-
end
|
25
|
-
|
26
|
-
def save(obj)
|
27
|
-
repo = @repositories[obj.class]
|
28
|
-
raise ArgumentError, "Repository for #{obj.class} not found" unless repo
|
29
|
-
repo.save(obj)
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
data/lib/clerq/interactors.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require_relative "interactor"
|
4
|
-
require_relative "join_nodes"
|
5
|
-
|
6
|
-
module Clerq
|
7
|
-
module Interactors
|
8
|
-
|
9
|
-
# TODO: maybe it needs QueryNodes instead of JoinNodes?
|
10
|
-
# TODO: add check for empty node content - @items.empty && @body.empty?
|
11
|
-
class CheckNodes < Interactor
|
12
|
-
|
13
|
-
def call
|
14
|
-
# TODO: query parameter for each interactor
|
15
|
-
@node = JoinNodes.()
|
16
|
-
{}.tap do |errors|
|
17
|
-
nonuniq = nonuniq_ids
|
18
|
-
errors.merge!(nonuniq_ids: nonuniq) unless nonuniq.empty?
|
19
|
-
parents = unknown_parents
|
20
|
-
errors.merge!(unknown_parents: parents) unless parents.empty?
|
21
|
-
references = unknown_references
|
22
|
-
errors.merge!(unknown_references: references) unless references.empty?
|
23
|
-
order = unknown_order_index
|
24
|
-
errors.merge!(unknown_order_index: order) unless order.empty?
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
protected
|
29
|
-
|
30
|
-
# @return [Hash<node id, Array<file_name>>] node ids and array of file_names
|
31
|
-
def nonuniq_ids
|
32
|
-
@node.each_with_object({}){|node, hsh|
|
33
|
-
hsh[node.id] ||= []
|
34
|
-
# TODO that way CheckNodes depends on files!?
|
35
|
-
hsh[node.id] << node[:file_name]
|
36
|
-
}.select{|k, v| v.size > 1}
|
37
|
-
.each{|k, v| v.uniq!}
|
38
|
-
end
|
39
|
-
|
40
|
-
# @return [Hash<parent, Array<node id>>] unknown meta[:parent] and
|
41
|
-
# array of nodes those have this meta attribute
|
42
|
-
def unknown_parents
|
43
|
-
@node # .drop(1)?
|
44
|
-
.select{|node| node[:parent] && node.parent.id != node[:parent]}
|
45
|
-
.each_with_object({}){|node, hsh|
|
46
|
-
hsh[node[:parent]] ||= []
|
47
|
-
hsh[node[:parent]] << node.id
|
48
|
-
}
|
49
|
-
end
|
50
|
-
|
51
|
-
# @return [Hash<node_id, Array<node_id>>] node ids that noe found
|
52
|
-
# in hierarchy and array of node ids those have links to corresponding
|
53
|
-
# unknown node
|
54
|
-
def unknown_references
|
55
|
-
index = @node.map(&:id).drop(1)
|
56
|
-
@node.each_with_object({}) do |node, hsh|
|
57
|
-
node.links
|
58
|
-
.reject {|lnk| index.include?(lnk)}
|
59
|
-
.each do |lnk|
|
60
|
-
hsh[lnk] ||= []
|
61
|
-
hsh[lnk] << node.id
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# @return [Hash<node_id, Array<node_id>>] node ids and array of
|
67
|
-
# unknown links in :order_index
|
68
|
-
def unknown_order_index
|
69
|
-
@node
|
70
|
-
.select{|node| node[:order_index]}
|
71
|
-
.each_with_object({}){|node, hsh|
|
72
|
-
order = node[:order_index].split(/ /)
|
73
|
-
wrong = order.select{|o| node.item(o).nil?}
|
74
|
-
hsh[node.id] = wrong unless wrong.empty?
|
75
|
-
}
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require_relative "interactor"
|
4
|
-
require_relative "join_nodes"
|
5
|
-
require_relative "query_nodes"
|
6
|
-
|
7
|
-
module Clerq
|
8
|
-
module Interactors
|
9
|
-
|
10
|
-
class CompileNodes < Interactor
|
11
|
-
|
12
|
-
# @return [String] document body
|
13
|
-
def call
|
14
|
-
tt = gateway.templates(@template)
|
15
|
-
raise Failure, "Template '#{@template}' not found" unless tt
|
16
|
-
node = @query.empty? ? JoinNodes.() : QueryNodes.(query: @query)
|
17
|
-
Clerq::Templater.(tt.body, node)
|
18
|
-
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
def initialize(template:, query: '')
|
23
|
-
raise ArgumentError, "Invalid argument :query" unless query.is_a? String
|
24
|
-
raise ArgumentError, "Invalid argument :template" if !(template.is_a?(String) && !template.empty?)
|
25
|
-
@query = query
|
26
|
-
@template = template
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
module Clerq
|
4
|
-
module Interactors
|
5
|
-
|
6
|
-
class Interactor
|
7
|
-
Failure = Class.new(StandardError)
|
8
|
-
|
9
|
-
def self.inherited(klass)
|
10
|
-
klass.const_set(:Failure, Class.new(klass::Failure))
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.call(*args)
|
14
|
-
new(*args).call
|
15
|
-
end
|
16
|
-
|
17
|
-
# Should be implemented in subclasses
|
18
|
-
def call; end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
def gateway
|
23
|
-
Clerq.gateway
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require_relative "interactor"
|
4
|
-
|
5
|
-
module Clerq
|
6
|
-
module Interactors
|
7
|
-
|
8
|
-
# Combine all nodes in one root node (document)
|
9
|
-
class JoinNodes < Interactor
|
10
|
-
|
11
|
-
# @return [Node]
|
12
|
-
def call
|
13
|
-
@node = join(gateway.nodes)
|
14
|
-
subordinate!
|
15
|
-
equip_ident!
|
16
|
-
@node
|
17
|
-
end
|
18
|
-
|
19
|
-
protected
|
20
|
-
|
21
|
-
def join(nodes)
|
22
|
-
return nodes.first if nodes.size == 1
|
23
|
-
node = Clerq::Entities::Node.new(id: 'join', title: Clerq.settings.title)
|
24
|
-
node.tap{|node| nodes.each{|n| node << n}}
|
25
|
-
end
|
26
|
-
|
27
|
-
def subordinate!
|
28
|
-
@node.items
|
29
|
-
.select{|n| n[:parent] && n[:parent] != n.parent.id}
|
30
|
-
.each{|n|
|
31
|
-
parent = @node.node(n[:parent])
|
32
|
-
next unless parent
|
33
|
-
parent << n
|
34
|
-
@node.items.delete(n)
|
35
|
-
n.meta.delete(:parent)
|
36
|
-
}
|
37
|
-
# if @node.id == 'join' && @node.items.size == 1
|
38
|
-
# @node = @node.items.first
|
39
|
-
# @node.orphan!
|
40
|
-
# end
|
41
|
-
end
|
42
|
-
|
43
|
-
# equips nodes with autogenerated id
|
44
|
-
# @param [Node] node
|
45
|
-
def equip_ident!
|
46
|
-
counter = {}
|
47
|
-
@node.select{|n| n.id.empty?}.each do |n|
|
48
|
-
next if n == @node
|
49
|
-
index = counter[n.parent] || 1
|
50
|
-
counter[n.parent] = index + 1
|
51
|
-
id = index.to_s.rjust(2, '0')
|
52
|
-
id = '.' + id unless n.parent == @node
|
53
|
-
n.id = id
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|