wortsammler 0.0.2 → 0.0.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.
- data/.gitignore +1 -0
- data/README.md +44 -1
- data/README.pdf +0 -0
- data/Rakefile +1 -1
- data/changelog.rb.txt +9 -0
- data/lib/wortsammler/class.Traceable.md.rb +7 -7
- data/lib/wortsammler/class.proolib.rb +103 -46
- data/lib/wortsammler/exe.wortsammler.rb +9 -318
- data/lib/wortsammler/version.rb +1 -1
- data/lib/wortsammler.rb +375 -2
- data/resources/default.latex +20 -21
- data/spec/wortsammler_spec.rb +18 -1
- data/testresults/wortsammler_testresults.html +89 -87
- data/testresults/wortsammler_testresults.log +4 -3
- data/wortsammler-gem.sublime-project +8 -0
- data/wortsammler.gemspec +1 -1
- metadata +6 -4
data/lib/wortsammler.rb
CHANGED
@@ -1,5 +1,378 @@
|
|
1
1
|
require "wortsammler/version"
|
2
|
+
require 'pry' if false
|
2
3
|
|
4
|
+
|
5
|
+
##
|
6
|
+
# This represents the high level API of Wortsammler
|
7
|
+
|
3
8
|
module Wortsammler
|
4
|
-
|
5
|
-
|
9
|
+
|
10
|
+
|
11
|
+
#
|
12
|
+
# execute Wortsammler after parsing the command line
|
13
|
+
#
|
14
|
+
# @param options [Hash] The parsed commandline arguments.
|
15
|
+
#
|
16
|
+
# The key of each entry is the argument name as a symbol
|
17
|
+
#
|
18
|
+
# The value of each entry is the value of the argument
|
19
|
+
#
|
20
|
+
# No default handling is performed, since defaulting of arguments has been done
|
21
|
+
# on the commandline processor.
|
22
|
+
#
|
23
|
+
# @return [Nil] No Return
|
24
|
+
def self.execute(options)
|
25
|
+
##
|
26
|
+
#
|
27
|
+
# print version info
|
28
|
+
#
|
29
|
+
if options[:version] then
|
30
|
+
puts "Wortsammler #{Wortsammler::VERSION}"
|
31
|
+
|
32
|
+
pandoc=`pandocx -v`.split("\n")[0] rescue pandoc="error running pandoc"
|
33
|
+
xetex=`xelatex -v`.split("\n")[0] rescue pandoc="error running xelatex"
|
34
|
+
|
35
|
+
puts "found #{pandoc}"
|
36
|
+
puts "found #{xetex}"
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# initialize a project
|
42
|
+
#
|
43
|
+
if project_folder=options[:init] then
|
44
|
+
if File.exists?(project_folder)
|
45
|
+
$log.error "directory already exists: '#{project_folder}'"
|
46
|
+
exit(false)
|
47
|
+
end
|
48
|
+
Wortsammler::init_folders(project_folder)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
##
|
53
|
+
#
|
54
|
+
# load the manifest
|
55
|
+
#
|
56
|
+
config=nil
|
57
|
+
if config_file=options[:manifest] then
|
58
|
+
config = ProoConfig.new(config_file)
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# process input path
|
63
|
+
#
|
64
|
+
#
|
65
|
+
input_files=nil
|
66
|
+
if inputpath = options[:inputpath]
|
67
|
+
unless File.exists? inputpath then
|
68
|
+
$log.error "path does not exist path '#{inputpath}'"
|
69
|
+
exit(false)
|
70
|
+
end
|
71
|
+
if File.file?(inputpath) #(RS_Mdc)
|
72
|
+
input_files=[inputpath]
|
73
|
+
elsif File.exists?(inputpath)
|
74
|
+
input_files=Dir["#{inputpath}/**/*.md", "#{inputpath}/**/*.markdown"]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
#
|
80
|
+
# beautify markdown files
|
81
|
+
#
|
82
|
+
#
|
83
|
+
|
84
|
+
if options[:beautify]
|
85
|
+
|
86
|
+
|
87
|
+
# process path
|
88
|
+
|
89
|
+
if input_files then
|
90
|
+
Wortsammler.beautify(input_files)
|
91
|
+
end
|
92
|
+
|
93
|
+
# process manifest
|
94
|
+
|
95
|
+
if config then
|
96
|
+
Wortsammler.beautify(config.input)
|
97
|
+
end
|
98
|
+
|
99
|
+
unless input_files or config
|
100
|
+
$log.error "no input specified. Please use -m or -i to specify input"
|
101
|
+
exit false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# process collect in markdown files
|
107
|
+
#
|
108
|
+
|
109
|
+
if options[:collect]
|
110
|
+
|
111
|
+
# collect by path
|
112
|
+
|
113
|
+
if input_files then
|
114
|
+
$log.warn "collect from path not yet implemented"
|
115
|
+
end
|
116
|
+
|
117
|
+
# collect by manifest
|
118
|
+
|
119
|
+
if config then
|
120
|
+
Wortsammler.collect_traces(config)
|
121
|
+
end
|
122
|
+
|
123
|
+
unless input_files or config
|
124
|
+
$log.error "no input specified. Please use -m or -i to specify input"
|
125
|
+
exit false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
##
|
132
|
+
# process files
|
133
|
+
#
|
134
|
+
if options[:process]
|
135
|
+
|
136
|
+
if input_files then
|
137
|
+
|
138
|
+
if options[:outputformats] then
|
139
|
+
outputformats = options[:outputformats].split(":")
|
140
|
+
end
|
141
|
+
|
142
|
+
if options[:outputfolder] then
|
143
|
+
outputfolder = options[:outputfolder]
|
144
|
+
else
|
145
|
+
$log.error "no output folder specified"
|
146
|
+
exit false
|
147
|
+
end
|
148
|
+
|
149
|
+
unless File.exists?(outputfolder) then
|
150
|
+
$log.info "creating folder '#{outputfolder}'"
|
151
|
+
FileUtils.mkdir_p(outputfolder)
|
152
|
+
end
|
153
|
+
|
154
|
+
input_files.each{|f| Wortsammler.render_single_document(f, outputfolder, outputformats)}
|
155
|
+
end
|
156
|
+
|
157
|
+
# collect by manifest
|
158
|
+
|
159
|
+
if config then
|
160
|
+
Wortsammler.process(config)
|
161
|
+
end
|
162
|
+
|
163
|
+
unless input_files or config
|
164
|
+
$log.error "no input specified. Please use -m or -i to specify input"
|
165
|
+
exit false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
nil
|
170
|
+
end #execute
|
171
|
+
|
172
|
+
|
173
|
+
#
|
174
|
+
# beautify a list of Documents
|
175
|
+
# @param paths [Array of String] Array of filenames which shall be cleaned.
|
176
|
+
#
|
177
|
+
# @return [Nil] no return
|
178
|
+
def self.beautify(paths)
|
179
|
+
|
180
|
+
cleaner = PandocBeautifier.new($log)
|
181
|
+
|
182
|
+
paths.each{|f| cleaner.beautify(f)}
|
183
|
+
nil
|
184
|
+
end
|
185
|
+
|
186
|
+
#
|
187
|
+
# process the documents according to the maanifest
|
188
|
+
#
|
189
|
+
# @param config [ProoConfig] A configuration object representing the manifest.
|
190
|
+
#
|
191
|
+
# @return [Nil] no return
|
192
|
+
def self.process(config)
|
193
|
+
cleaner = PandocBeautifier.new($log)
|
194
|
+
|
195
|
+
cleaner.generateDocument(config.input,
|
196
|
+
config.outdir,
|
197
|
+
config.outname,
|
198
|
+
config.format,
|
199
|
+
config.vars,
|
200
|
+
config.editions,
|
201
|
+
config.snippets,
|
202
|
+
config.frontmatter,
|
203
|
+
config)
|
204
|
+
|
205
|
+
nil
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
#
|
211
|
+
# render a single document
|
212
|
+
# @param filename [String] The filename of the document file which shall be rendered
|
213
|
+
# @param outputfolder [String] The path to the outputfolder where the output files shall be placed.
|
214
|
+
#
|
215
|
+
#
|
216
|
+
# @param outputformats [Array of String] The list of formats which shall be produced
|
217
|
+
#
|
218
|
+
# @return [Nil] no return
|
219
|
+
def self.render_single_document(filename, outputfolder, outputformats)
|
220
|
+
cleaner = PandocBeautifier.new($log)
|
221
|
+
cleaner.render_single_document(filename, outputfolder, outputformats)
|
222
|
+
nil
|
223
|
+
end
|
224
|
+
|
225
|
+
#
|
226
|
+
# initialize a project directory. It creates a bunch of
|
227
|
+
# folders, a root document, a manifest and an intial rakefile
|
228
|
+
#
|
229
|
+
# @param root [String] [The path to the root folder of the sample project]
|
230
|
+
#
|
231
|
+
# @return [Nil] No return
|
232
|
+
def self.init_folders(root)
|
233
|
+
|
234
|
+
folders=["ZSUPP_Manifests",
|
235
|
+
"ZGEN_Documents",
|
236
|
+
"ZSUPP_Tools",
|
237
|
+
"ZSUPP_Styles",
|
238
|
+
"ZGEN_RequirementsTracing",
|
239
|
+
"001_Main"
|
240
|
+
]
|
241
|
+
|
242
|
+
folders.each{|folder|
|
243
|
+
FileUtils.mkdir_p("#{root}/#{folder}")
|
244
|
+
}
|
245
|
+
|
246
|
+
resourcedir=File.dirname(__FILE__)+"/../resources"
|
247
|
+
Dir["#{resourcedir}/*.yaml"].each{|f|
|
248
|
+
FileUtils.cp(f, "#{root}/ZSUPP_Manifests")
|
249
|
+
}
|
250
|
+
FileUtils.cp("#{resourcedir}/main.md", "#{root}/001_Main")
|
251
|
+
FileUtils.cp("#{resourcedir}/rakefile.rb", "#{root}/ZSUPP_Tools")
|
252
|
+
FileUtils.cp("#{resourcedir}/default.latex", "#{root}/ZSUPP_Styles")
|
253
|
+
FileUtils.cp("#{resourcedir}/logo.jpg", "#{root}/ZSUPP_Styles")
|
254
|
+
|
255
|
+
nil
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
#
|
260
|
+
# collect the Traceables in a document specified by a manifest
|
261
|
+
# @param config [ProolibConfig] the manifest model
|
262
|
+
#
|
263
|
+
# @return [Nil] no return
|
264
|
+
def self.collect_traces(config)
|
265
|
+
|
266
|
+
files = config.input # get the input files
|
267
|
+
rootdir = config.rootdir # get the root directory
|
268
|
+
|
269
|
+
downstream_tracefile = config.downstream_tracefile # String to save downstram filenames
|
270
|
+
reqtracefile_base = config.reqtracefile_base # string to determine the requirements tracing results
|
271
|
+
upstream_tracefiles = config.upstream_tracefiles # String to read upstream tracefiles
|
272
|
+
|
273
|
+
traceable_set = TraceableSet.new
|
274
|
+
|
275
|
+
# collect all traceables in input
|
276
|
+
files.each{|f|
|
277
|
+
x=TraceableSet.processTracesInMdFile(f)
|
278
|
+
traceable_set.merge(x)
|
279
|
+
}
|
280
|
+
|
281
|
+
# collect all upstream traceables
|
282
|
+
#
|
283
|
+
upstream_traceable_set=TraceableSet.new
|
284
|
+
unless upstream_tracefiles.nil?
|
285
|
+
upstream_tracefiles.each{|f|
|
286
|
+
x=TraceableSet.processTracesInMdFile(f)
|
287
|
+
upstream_traceable_set.merge(x)
|
288
|
+
}
|
289
|
+
end
|
290
|
+
|
291
|
+
# check undefined traces
|
292
|
+
all_traceable_set=TraceableSet.new
|
293
|
+
all_traceable_set.merge(traceable_set)
|
294
|
+
all_traceable_set.merge(upstream_traceable_set)
|
295
|
+
undefineds=all_traceable_set.undefined_ids
|
296
|
+
$log.warn "undefined traces: #{undefineds.join(' ')}" unless undefineds.empty?
|
297
|
+
|
298
|
+
|
299
|
+
# check duplicates
|
300
|
+
duplicates=all_traceable_set.duplicate_traces
|
301
|
+
if duplicates.count > 0
|
302
|
+
$logger.warn "duplicated trace ids found:"
|
303
|
+
duplicates.each{|d| d.each{|t| $log.warn "#{t.id} in #{t.info}"}}
|
304
|
+
end
|
305
|
+
|
306
|
+
# write traceables to the intermediate Tracing file
|
307
|
+
outname="#{rootdir}/#{reqtracefile_base}.md"
|
308
|
+
|
309
|
+
# poke ths sort order for the traceables
|
310
|
+
all_traceable_set.sort_order=config.traceSortOrder if config.traceSortOrder
|
311
|
+
traceable_set.sort_order=config.traceSortOrder if config.traceSortOrder
|
312
|
+
# generate synopsis of traceableruby 1.8.7 garbage at end of file
|
313
|
+
|
314
|
+
|
315
|
+
tracelist=""
|
316
|
+
File.open(outname, "w"){|fx|
|
317
|
+
fx.puts ""
|
318
|
+
fx.puts "\\clearpage"
|
319
|
+
fx.puts ""
|
320
|
+
fx.puts "# Requirements Tracing"
|
321
|
+
fx.puts ""
|
322
|
+
tracelist=all_traceable_set.reqtraceSynopsis(:SPECIFICATION_ITEM)
|
323
|
+
fx.puts tracelist
|
324
|
+
}
|
325
|
+
|
326
|
+
# output the graphxml
|
327
|
+
# write traceables to the intermediate Tracing file
|
328
|
+
outname="#{rootdir}/#{reqtracefile_base}.graphml"
|
329
|
+
File.open(outname, "w") {|fx| fx.puts all_traceable_set.to_graphml}
|
330
|
+
|
331
|
+
outname="#{rootdir}/#{reqtracefile_base}Compare.txt"
|
332
|
+
File.open(outname, "w") {|fx| fx.puts traceable_set.to_compareEntries}
|
333
|
+
|
334
|
+
# write the downstream_trace file - to be included in downstream - speciifcations
|
335
|
+
outname="#{rootdir}/#{downstream_tracefile}"
|
336
|
+
File.open(outname, "w") {|fx|
|
337
|
+
fx.puts ""
|
338
|
+
fx.puts "\\clearpage"
|
339
|
+
fx.puts ""
|
340
|
+
fx.puts "# Upstream Requirements"
|
341
|
+
fx.puts ""
|
342
|
+
fx.puts traceable_set.to_downstream_tracefile(:SPECIFICATION_ITEM)
|
343
|
+
} unless downstream_tracefile.nil?
|
344
|
+
|
345
|
+
|
346
|
+
# now add the upstream traces to input
|
347
|
+
files.concat( upstream_tracefiles) unless upstream_tracefiles.nil?
|
348
|
+
|
349
|
+
nil
|
350
|
+
end
|
351
|
+
|
352
|
+
private
|
353
|
+
#
|
354
|
+
# This method can verify wortsammler options delivered by option parser
|
355
|
+
# @param options [Hash] Option hash delivered by option parser
|
356
|
+
#
|
357
|
+
# @return [Boolean] true if successful. otherwise exits the program
|
358
|
+
def self.verify_options(options)
|
359
|
+
if options[:inputpath] or options[:manifest] then
|
360
|
+
unless options[:process] or options[:beautify] or options[:collect] then
|
361
|
+
$log.error "no procesing option (p, b, c) specified"
|
362
|
+
exit false
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
if options[:inputpath] and options[:process] then
|
367
|
+
unless options[:outputfolder] then
|
368
|
+
$log.error "no output folder specified for input path"
|
369
|
+
exit false
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
true
|
374
|
+
end #verify_options
|
375
|
+
|
376
|
+
|
377
|
+
|
378
|
+
end # module
|
data/resources/default.latex
CHANGED
@@ -1,24 +1,23 @@
|
|
1
1
|
\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$lang$,$endif$]{$documentclass$}
|
2
|
-
%
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
%
|
21
|
-
% }%
|
2
|
+
{\catcode`\@=11\relax%
|
3
|
+
\gdef\itemize{%
|
4
|
+
\ifnum \@itemdepth >\thr@@\@toodeep\else
|
5
|
+
\advance\@itemdepth\@ne
|
6
|
+
\edef\@itemitem{labelitem\romannumeral\the\@itemdepth}%
|
7
|
+
\expandafter
|
8
|
+
\list
|
9
|
+
\csname\@itemitem\endcsname
|
10
|
+
{\def\makelabel##1{\hss\llap{##1}}%
|
11
|
+
\addtolength{\leftmargin}{-10pt}% 29.37pt
|
12
|
+
\addtolength{\rightmargin}{0.0pt}% 0.0pt
|
13
|
+
\addtolength{\labelsep}{0pt}% 23.50pt
|
14
|
+
\addtolength{\itemsep}{-3.0pt}% 5.0pt
|
15
|
+
\addtolength{\parsep}{0pt}% 5.0pt
|
16
|
+
\addtolength{\topsep}{-5pt}% 10.0pt
|
17
|
+
\addtolength{\partopsep}{0pt}% 3.0pt
|
18
|
+
}%
|
19
|
+
\fi}
|
20
|
+
}%
|
22
21
|
%end list environment by Reinhard Jahraus
|
23
22
|
\usepackage[T1]{fontenc}
|
24
23
|
\usepackage{lmodern}
|
@@ -175,7 +174,7 @@ $endif$
|
|
175
174
|
\chead{\begin{center}\textbf{$title$}\end{center}}
|
176
175
|
%\lhead{\includegraphics{logo.jpg}}
|
177
176
|
\rhead{\leftmark}
|
178
|
-
\lfoot{
|
177
|
+
\lfoot{"generated by Wortsammler"}
|
179
178
|
\rfoot{\today}
|
180
179
|
\renewcommand{\footrulewidth}{0.4pt}
|
181
180
|
%
|
data/spec/wortsammler_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'tmpdir'
|
3
|
+
require 'pry'
|
3
4
|
|
4
5
|
wortsammlerbin = "'#{File.expand_path("bin")}'"
|
5
6
|
wortsammler = "'#{File.expand_path(File.join("bin", "wortsammler"))}'"
|
@@ -42,6 +43,7 @@ end
|
|
42
43
|
|
43
44
|
describe "Wortsammler beautifier features" do
|
44
45
|
|
46
|
+
|
45
47
|
it "beautifies all markdown files in a folder" do
|
46
48
|
tempdir=Dir.mktmpdir
|
47
49
|
mdtext="#this is headline\n\n lorem ipsum\n\nbla fasel"
|
@@ -115,7 +117,22 @@ describe "Wortsammler conversion" do
|
|
115
117
|
]
|
116
118
|
end
|
117
119
|
|
118
|
-
it "converts
|
120
|
+
it "converts a single file to default output format" do
|
121
|
+
tempdir=Dir.mktmpdir
|
122
|
+
mdfile="#{tempdir}/single.md"
|
123
|
+
mdtext="#this is headline\n\n lorem ipsum\n\nbla fasel"
|
124
|
+
File.open(mdfile, "w"){|f| f.puts mdtext}
|
125
|
+
system "#{wortsammler} -pi #{mdfile} -o #{tempdir}"
|
126
|
+
$?.success?.should==true
|
127
|
+
|
128
|
+
|
129
|
+
Dir["#{tempdir}/*"].map{|f|File.basename(f)}.should== ["single.md",
|
130
|
+
"single.pdf"
|
131
|
+
]
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
it "converts all files within a folder to output format" do
|
119
136
|
tempdir=Dir.mktmpdir
|
120
137
|
system "#{wortsammler} -pi . -o #{tempdir} -f latex:pdf:html:docx"
|
121
138
|
$?.success?.should==true
|