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