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
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'clerq'
|
2
|
+
require 'thor'
|
3
|
+
require 'tmpdir'
|
4
|
+
require_relative 'lib/colonize_repo'
|
5
|
+
include Clerq::Repositories
|
6
|
+
include Clerq::Entities
|
7
|
+
include Clerq::Services
|
8
|
+
|
9
|
+
# This thor file sample was created with purpose to show some examples
|
10
|
+
# of using Pandoc for clerq reposiory publishing and even import souce
|
11
|
+
# documents into a clerq repository ... `thor clerq:doc:grab`, `thor clerq:doc:publish`
|
12
|
+
class ClerqDoc < Thor
|
13
|
+
include Thor::Actions
|
14
|
+
namespace 'clerq:doc'.to_sym
|
15
|
+
|
16
|
+
no_commands {
|
17
|
+
def eqid!(node)
|
18
|
+
counter = {}
|
19
|
+
node.to_a.drop(1).each do |n|
|
20
|
+
index = counter[n.parent] || 1
|
21
|
+
counter[n.parent] = index + 1
|
22
|
+
id = index.to_s.rjust(2, '0')
|
23
|
+
id = '.' + id unless n.parent == node
|
24
|
+
n.id = id
|
25
|
+
end
|
26
|
+
end
|
27
|
+
}
|
28
|
+
|
29
|
+
# Why does one need to grab the document?
|
30
|
+
# it started in MS Word but the author decieded to pкoceed in Clerq
|
31
|
+
# it is the source for the clerq project, SRS based on Vision?
|
32
|
+
# something else?
|
33
|
+
# TODO provide -q/--query QUERY_STRING parameter
|
34
|
+
# TODO how about importing images?
|
35
|
+
desc 'grab FILENAME', 'Grab document and populate the clerq repository'
|
36
|
+
def grab(filename)
|
37
|
+
mdown = File.join(Dir.tmpdir, 'clerq.grab.md')
|
38
|
+
optns = [].tap{|o|
|
39
|
+
o << '--wrap=none'
|
40
|
+
o << '--atx-headers'
|
41
|
+
o << "#{filename}"
|
42
|
+
o << "-o #{mdown}"
|
43
|
+
}.join(' ')
|
44
|
+
|
45
|
+
`pandoc #{optns}`
|
46
|
+
|
47
|
+
on_error_callback = lambda {|err| puts err}
|
48
|
+
puts "Reading '#{mdown}'..."
|
49
|
+
|
50
|
+
# TODO handle query parameter
|
51
|
+
arry = ReadNode.(mdown, on_error_callback)
|
52
|
+
node = Node.new(id: '00', title: File.basename(mdown, '.md'))
|
53
|
+
arry.each{|n| node << n}
|
54
|
+
eqid!(node)
|
55
|
+
|
56
|
+
puts "Colonizing this repository..."
|
57
|
+
dir_counter = 0
|
58
|
+
src_counter = 0
|
59
|
+
on_create_dir = lambda {|dir| puts "Created '#{dir}' directory"; dir_counter += 1 }
|
60
|
+
on_create_src = lambda {|src| puts "Created '#{src}' file"; src_counter += 1 }
|
61
|
+
|
62
|
+
Dir.chdir(Clerq.src) { ColonizeRepo.(node, on_create_dir, on_create_src) }
|
63
|
+
|
64
|
+
msg = [].tap do |memo|
|
65
|
+
memo << "#{dir_counter} #{dir_counter == 1 ? 'directory' : 'directories'}" if dir_counter > 0
|
66
|
+
memo << "#{src_counter} #{src_counter == 1 ? 'file' : 'files'}" if src_counter > 0
|
67
|
+
end.join(' and ')
|
68
|
+
|
69
|
+
say "#{node.to_a.size} nodes from '#{filename}' imported to the repositroy. #{msg} created in the repository."
|
70
|
+
end
|
71
|
+
|
72
|
+
desc 'publish', 'Publishing final deliverables'
|
73
|
+
def publish
|
74
|
+
invoke :docx
|
75
|
+
invoke :html
|
76
|
+
end
|
77
|
+
|
78
|
+
desc 'html', 'Publish final deliverable in Html'
|
79
|
+
def html
|
80
|
+
source = File.join(Clerq.bin, Clerq.document + ".md")
|
81
|
+
target = File.join(Clerq.bin, Clerq.document + ".html")
|
82
|
+
optns = [].tap{|o|
|
83
|
+
o << '-s --toc --toc-depth 3'
|
84
|
+
o << "--resource-path #{Clerq.bin}"
|
85
|
+
o << "\"#{source}\""
|
86
|
+
o << "-o \"#{target}\""
|
87
|
+
}.join(" ")
|
88
|
+
|
89
|
+
`clerq build -t pandoc.md.erb`
|
90
|
+
`pandoc #{optns}`
|
91
|
+
say "\"#{target}\" created!"
|
92
|
+
end
|
93
|
+
|
94
|
+
desc 'docx', 'Publish final deliverable in Docx'
|
95
|
+
def docx
|
96
|
+
source = File.join(Clerq.bin, Clerq.document + ".md")
|
97
|
+
target = File.join(Clerq.bin, Clerq.document + ".docx")
|
98
|
+
sample = File.join(Clerq.bin, 'custom-reference.docx')
|
99
|
+
|
100
|
+
unless File.exist?(sample)
|
101
|
+
# produce a custom reference.docx
|
102
|
+
`pandoc -o #{sample} --print-default-data-file reference.docx`
|
103
|
+
end
|
104
|
+
|
105
|
+
optns = [].tap{|o|
|
106
|
+
o << '-s --toc --toc-depth 3'
|
107
|
+
o << '--from markdown+table_captions+implicit_figures'
|
108
|
+
o << "--reference-doc #{sample}"
|
109
|
+
o << "--resource-path #{Clerq.bin}"
|
110
|
+
o << "\"#{source}\""
|
111
|
+
o << "-o \"#{target}\""
|
112
|
+
}.join(" ")
|
113
|
+
|
114
|
+
`clerq build -t pandoc.md.erb`
|
115
|
+
`pandoc #{optns}`
|
116
|
+
say "\"#{target}\" created!"
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'clerq'
|
2
|
+
require 'erb'
|
3
|
+
include Clerq::Entities
|
4
|
+
include Clerq::Services
|
5
|
+
|
6
|
+
# Creates clerq repository sources in current work directory
|
7
|
+
# Warning! Change work dierectory before calling for the serice
|
8
|
+
# Usage
|
9
|
+
# node = Clerq.node_repository.assembly
|
10
|
+
# Dir.chdir(Clerq.src) { ColonizeRepo.(node) }
|
11
|
+
class ColonizeRepo < Service
|
12
|
+
private_class_method :new
|
13
|
+
|
14
|
+
def call
|
15
|
+
write(@node)
|
16
|
+
end
|
17
|
+
|
18
|
+
# TODO callback? and calback for ReadNode.()?
|
19
|
+
def write(node)
|
20
|
+
dir = folder(node)
|
21
|
+
src = source(node)
|
22
|
+
txt = text(node)
|
23
|
+
unless dir.empty? || Dir.exist?(dir)
|
24
|
+
Dir.mkdir(dir)
|
25
|
+
@on_create_dir.call(dir) if @on_create_dir
|
26
|
+
end
|
27
|
+
File.write(src, txt)
|
28
|
+
@on_create_file.call(src) if @on_create_file
|
29
|
+
node.items.reject{|n| n.items.empty?}.each{|n| write(n)}
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param node [Node] the node for colonization
|
33
|
+
# @param on_create_file [Block(arg)] on create new file callback
|
34
|
+
# @param on_create_dir [Block(arg)] on create new directory callback
|
35
|
+
def initialize(node, on_create_dir = nil, on_create_file = nil)
|
36
|
+
@node = node
|
37
|
+
@on_create_dir = on_create_dir
|
38
|
+
@on_create_file = on_create_file
|
39
|
+
end
|
40
|
+
|
41
|
+
def source(node)
|
42
|
+
fld = folder(node)
|
43
|
+
src = filename(node)
|
44
|
+
fld.empty? ? src : File.join(fld, src)
|
45
|
+
end
|
46
|
+
|
47
|
+
def folder(node)
|
48
|
+
dir = ''
|
49
|
+
n = node
|
50
|
+
while n != @node.root && n.parent != @node.root
|
51
|
+
dir = File.join("#{n.parent.id} #{n.parent.title}", dir)
|
52
|
+
n = n.parent
|
53
|
+
end
|
54
|
+
dir
|
55
|
+
end
|
56
|
+
|
57
|
+
def filename(node)
|
58
|
+
"#{node.id} #{node.title}.md"
|
59
|
+
end
|
60
|
+
|
61
|
+
# TODO replace to services
|
62
|
+
def text(node)
|
63
|
+
RenderErb.(erb: TEMPLATE, object: node)
|
64
|
+
end
|
65
|
+
|
66
|
+
TEMPLATE = <<~EOF
|
67
|
+
# <%= @object.title %>
|
68
|
+
{{id: <%= @object.id %><%= ", parent: " + @object.parent.id if @object.parent %>, order_index: <%= @object.items.map(&:id).join(' ') %>}}
|
69
|
+
|
70
|
+
<%= @object.body %>
|
71
|
+
|
72
|
+
<% for n in @object.items -%>
|
73
|
+
<% next unless n.items.empty? -%>
|
74
|
+
## <%= n.title %>
|
75
|
+
{{id: <%= n.id %>}}
|
76
|
+
|
77
|
+
<%= n.body %>
|
78
|
+
|
79
|
+
<% end %>
|
80
|
+
EOF
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'clerq'
|
2
|
+
require 'erb'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require_relative 'colonize_repo'
|
5
|
+
include Clerq::Entities
|
6
|
+
include Clerq::Services
|
7
|
+
|
8
|
+
describe ColonizeRepo do
|
9
|
+
class FakeWriter < ColonizeRepo
|
10
|
+
public_class_method :new
|
11
|
+
attr_reader :node
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:node) {
|
15
|
+
Node.new(id: '0', title: 'Import').tap{|n|
|
16
|
+
n << Node.new(id: '01', title: 'User')
|
17
|
+
n << Node.new(id: '02', title: 'Func')
|
18
|
+
n.item('01') << Node.new(id: '01.01', title: 'Story 1')
|
19
|
+
n.item('01') << Node.new(id: '01.02', title: 'Story 2')
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
let(:writer) { FakeWriter.new(node) }
|
24
|
+
|
25
|
+
describe '#folder' do
|
26
|
+
it 'must return parent.id + parent.name' do
|
27
|
+
spec = writer.node.map{|n| writer.folder(n)}
|
28
|
+
_(spec).must_equal([
|
29
|
+
'', '', '01 User/', '01 User/', ''
|
30
|
+
])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#filename' do
|
35
|
+
it 'must return node.id + node.title' do
|
36
|
+
spec = writer.node.map{|n| writer.filename(n)}
|
37
|
+
_(spec).must_equal([
|
38
|
+
'0 Import.md', '01 User.md', '01.01 Story 1.md',
|
39
|
+
'01.02 Story 2.md', '02 Func.md'
|
40
|
+
])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#source' do
|
45
|
+
# title and first level shall be paced in root folder
|
46
|
+
it 'must return node.id + node.title' do
|
47
|
+
spec = writer.node.map{|n| writer.source(n)}
|
48
|
+
_(spec).must_equal([
|
49
|
+
'0 Import.md',
|
50
|
+
'01 User.md',
|
51
|
+
'01 User/01.01 Story 1.md',
|
52
|
+
'01 User/01.02 Story 2.md',
|
53
|
+
'02 Func.md'
|
54
|
+
])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#write(node)' do
|
59
|
+
let(:node) {
|
60
|
+
Node.new(id: '0', title: 'Import').tap{|n|
|
61
|
+
n << Node.new(id: '01', title: 'User')
|
62
|
+
n << Node.new(id: '02', title: 'Func')
|
63
|
+
n.item('01') << Node.new(id: '01.01', title: 'Story 1')
|
64
|
+
n.item('01') << Node.new(id: '01.02', title: 'Story 2')
|
65
|
+
n.node('01.01') << Node.new(id: '01.01.01', title: 'Story 1.1')
|
66
|
+
n.node('01.01') << Node.new(id: '01.01.02', title: 'Story 1.2')
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
it 'must build repo' do
|
71
|
+
files = ['0 Import.md', '01 User.md', '01 User/01.01 Story 1.md']
|
72
|
+
Dir.mktmpdir(['clerq']) do |dir|
|
73
|
+
Dir.chdir(dir) do
|
74
|
+
ColonizeRepo.(node)
|
75
|
+
files.each{|fn| _(File.exist?(fn)).must_equal true }
|
76
|
+
_(File.read('0 Import.md')).wont_match "parent:"
|
77
|
+
_(File.read('01 User.md')).must_match "parent: 0"
|
78
|
+
_(File.read('01 User/01.01 Story 1.md')).must_match "parent: 01"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -1,15 +1,42 @@
|
|
1
|
-
# TODO how about to include commands automatically from 'lib' folder
|
2
|
-
|
3
|
-
require 'thor'
|
4
1
|
require 'clerq'
|
2
|
+
require 'thor'
|
5
3
|
|
6
|
-
class <%=config[:
|
4
|
+
class <%=config[:klass]%> < Thor
|
7
5
|
include Thor::Actions
|
8
6
|
|
9
7
|
desc "stat", "Print statistic"
|
10
8
|
def stat
|
11
|
-
nodes = Clerq
|
9
|
+
nodes = Clerq.assemble
|
12
10
|
say "#{nodes.to_a.drop(1).size} nodes total"
|
13
11
|
end
|
14
12
|
|
13
|
+
desc "mm", "Create meeting minutes"
|
14
|
+
def mm
|
15
|
+
minutes = "meeting minutes #{Time.new.strftime('%Y-%m-%d')}.md"
|
16
|
+
content = "% #{minutes.capitalize}\n\n" + MINUTES_TEMPLATE
|
17
|
+
Dir.mkdir('mm') unless Dir.exist?('mm')
|
18
|
+
File.write("mm/#{minutes}", content)
|
19
|
+
say "'mm/#{minutes}' created!"
|
20
|
+
end
|
21
|
+
|
22
|
+
MINUTES_TEMPLATE = <<~EOF
|
23
|
+
# Attendants
|
24
|
+
|
25
|
+
1.
|
26
|
+
2.
|
27
|
+
3.
|
28
|
+
|
29
|
+
# Questions
|
30
|
+
|
31
|
+
1.
|
32
|
+
2.
|
33
|
+
3.
|
34
|
+
|
35
|
+
# Resolutions
|
36
|
+
|
37
|
+
1.
|
38
|
+
2.
|
39
|
+
3.
|
40
|
+
EOF
|
41
|
+
|
15
42
|
end
|
@@ -1,41 +1,4 @@
|
|
1
|
-
#
|
2
|
-
{{
|
1
|
+
# <%=config[:project]%>
|
2
|
+
{{id: 0}}
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
This file was created automatically from the premise that you could want to have the high-level structure of the project (document) in a single place.
|
7
|
-
|
8
|
-
For the usual descriptive parts (nodes) that do not need unique identifiers - use `skip_meta: true` attribute. To output child parts in appropriate order - use the `order_index: nx ny nz` attribute.
|
9
|
-
|
10
|
-
Pay attention that this content placed under `skip` macro that means this content won't be included in the output document.}}
|
11
|
-
|
12
|
-
## Purpose
|
13
|
-
{{skip_meta: true}}
|
14
|
-
|
15
|
-
The purpose of this document is to provide a detailed product description of the <%= config[:project] %>. The document describes the product from user and software requirements perspectives.
|
16
|
-
|
17
|
-
All parties who are responsible for the definition and implementation of the project should read and understand this document.
|
18
|
-
|
19
|
-
## Scope
|
20
|
-
{{skip_meta: true}}
|
21
|
-
|
22
|
-
## Definitions, acronyms, and abbreviations
|
23
|
-
{{skip_meta: true}}
|
24
|
-
|
25
|
-
## References
|
26
|
-
{{skip_meta: true}}
|
27
|
-
|
28
|
-
## Overview
|
29
|
-
{{skip_meta: true}}
|
30
|
-
|
31
|
-
# Users and Stakeholders
|
32
|
-
{{skip_meta: true}}
|
33
|
-
|
34
|
-
# User requirements
|
35
|
-
{{skip_meta: true}}
|
36
|
-
|
37
|
-
# Functional requirements
|
38
|
-
{{skip_meta: true}}
|
39
|
-
|
40
|
-
# Nonfunctional requirements
|
41
|
-
{{skip_meta: true}}
|
4
|
+
This file was created automatically by the `clerq new` command as the root node of your project. To familiarize yourself with how to start writing with the Clerq - please read the [Writing](https://github.com/nvoynov/clerq/blob/master/README.md#writing) section and then just delete the content of the paragraph.
|
@@ -1,64 +1,45 @@
|
|
1
1
|
<%
|
2
|
-
|
2
|
+
|
3
3
|
require 'delegate'
|
4
|
+
|
4
5
|
class MarkupNode < SimpleDelegator
|
5
6
|
def title
|
6
|
-
|
7
|
+
s = super
|
8
|
+
s = ".#{id.split(/\./).last}" if s.empty?
|
9
|
+
'#' * nesting_level + ' ' + s
|
7
10
|
end
|
8
11
|
|
9
12
|
def meta
|
10
13
|
return '' if nesting_level == 0
|
11
|
-
|
12
|
-
|
13
|
-
hsh = {id: id}.merge(super)
|
14
|
-
hsh.delete(:order_index)
|
14
|
+
hsh = {}.merge(super)
|
15
15
|
hsh.delete(:parent)
|
16
|
-
hsh.delete(:
|
17
|
-
|
18
|
-
|
19
|
-
ary << "--------- | -----"
|
20
|
-
hsh.each{|k,v| ary << "#{k} | #{v}"}
|
21
|
-
}.join("\n")
|
22
|
-
end
|
23
|
-
|
24
|
-
def body
|
25
|
-
return '' if super.empty?
|
26
|
-
# replace links
|
27
|
-
txt = String.new(super)
|
28
|
-
links.each{|l| txt.gsub!("[[#{l}]]", link(l))}
|
29
|
-
txt
|
30
|
-
end
|
31
|
-
|
32
|
-
def link(id)
|
33
|
-
r = find_node(id)
|
34
|
-
return "[#{id}](#unknown)" unless r
|
35
|
-
"[#{r.title}](##{url(r.id)})"
|
36
|
-
end
|
16
|
+
hsh.delete(:order_index)
|
17
|
+
hsh.delete(:filename)
|
18
|
+
return '' if hsh.empty?
|
37
19
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
def find_node(id)
|
43
|
-
return find{|n| n.id.end_with? id[1..-1]} if id.start_with? '.'
|
44
|
-
return root.find{|n| n.id.end_with? id[1..-1]} if id.start_with? '*'
|
45
|
-
root.find{|n| n.id.eql? id}
|
20
|
+
hsh.map{|k, v| "#{k}: #{v}"}
|
21
|
+
.unshift("{{")
|
22
|
+
.push("}}")
|
23
|
+
.join("\n")
|
46
24
|
end
|
47
25
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
.
|
52
|
-
.
|
26
|
+
def markup
|
27
|
+
[].tap do |o|
|
28
|
+
o << title
|
29
|
+
o << meta unless meta.empty?
|
30
|
+
unless body.empty?
|
31
|
+
o << "\n#{body}"
|
32
|
+
end
|
33
|
+
end.join("\n")
|
53
34
|
end
|
54
|
-
|
55
35
|
end
|
56
36
|
-%>
|
57
37
|
% <%= @object.title %>
|
58
38
|
% generated by Clerq on <%= Time.now.strftime('%B %e, %Y at %H:%M') %>
|
39
|
+
% default template
|
59
40
|
|
60
41
|
<% for @node in @object.to_a.drop(1) -%>
|
61
42
|
<% n = MarkupNode.new(@node) -%>
|
62
|
-
<%=
|
43
|
+
<%= n.markup %>
|
63
44
|
|
64
45
|
<% end %>
|