petit-felix 0.1.4 → 0.1.6
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/lib/felix/config.rb +34 -24
- data/lib/felix/error.rb +4 -2
- data/lib/felix/generator.rb +6 -3
- data/lib/felix/metadata.rb +33 -4
- data/lib/felix/task_manager.rb +17 -7
- data/lib/petit-felix.rb +3 -1
- data/lib/task/basic_pdf_classic_task.rb +182 -0
- data/lib/task/default_task.rb +54 -9
- data/lib/task/pdf_single_task.rb +74 -0
- data/lib/task/template_pdf_task.rb +51 -0
- data/lib/version.rb +3 -1
- data/lib/worker/{basic_pdf_writer.rb → basic_pdf_writer_classic.rb} +38 -66
- data/lib/worker/pdf_writer/bounding_box.rb +135 -0
- data/lib/worker/pdf_writer/column_box.rb +38 -0
- data/lib/worker/pdf_writer.rb +98 -0
- data/lib/worker/template_pdf_writer.rb +300 -0
- data/lib/worker/templater/error.rb +90 -0
- data/lib/worker/templater/font.rb +59 -0
- data/lib/worker/templater/methods.rb +1072 -0
- data/lib/worker/templater/validation.rb +213 -0
- data/templates/zine-single.json +774 -0
- metadata +29 -3
- data/lib/task/basic_pdf_task.rb +0 -133
@@ -0,0 +1,300 @@
|
|
1
|
+
require "prawn"
|
2
|
+
require 'fileutils'
|
3
|
+
require "prawndown-ext"
|
4
|
+
require "felix/metadata"
|
5
|
+
require "felix/error"
|
6
|
+
require "worker/pdf_writer"
|
7
|
+
require "worker/templater/methods"
|
8
|
+
require "worker/templater/error"
|
9
|
+
require "worker/templater/validation"
|
10
|
+
require "worker/templater/font"
|
11
|
+
require "eqn"
|
12
|
+
|
13
|
+
## Prawn PDF writer that inputs template files
|
14
|
+
|
15
|
+
module PetitFelix
|
16
|
+
module Worker
|
17
|
+
|
18
|
+
class TemplatePDFWriter < PetitFelix::Worker::DefaultPDFWriter
|
19
|
+
|
20
|
+
# Highest a stack is allowed to be
|
21
|
+
MAX_STACK = 1024
|
22
|
+
|
23
|
+
## Functions
|
24
|
+
|
25
|
+
def init_values options, pdf
|
26
|
+
|
27
|
+
@variables = {}
|
28
|
+
|
29
|
+
@options = Marshal.load(Marshal.dump(options))
|
30
|
+
|
31
|
+
# Options to use for method calls and stuff
|
32
|
+
# Updated every time a template is loaded
|
33
|
+
@metaoptions = {}
|
34
|
+
@pdf = pdf
|
35
|
+
|
36
|
+
# stack referencing current running commands
|
37
|
+
@command_stack = []
|
38
|
+
|
39
|
+
# stack referencing current program counter
|
40
|
+
@counter_stack = []
|
41
|
+
|
42
|
+
# stack referencing current running template
|
43
|
+
# currently unused, will use when stitching
|
44
|
+
# external templates together.
|
45
|
+
@template_stack = []
|
46
|
+
|
47
|
+
# Templates
|
48
|
+
@template = {}
|
49
|
+
|
50
|
+
# prints errors
|
51
|
+
@error_printer = PetitFelix::Error.new
|
52
|
+
|
53
|
+
# For variables of errors
|
54
|
+
@error_param = {}
|
55
|
+
|
56
|
+
set_variables
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_variables
|
60
|
+
|
61
|
+
@metaoptions.keys.each do |key|
|
62
|
+
|
63
|
+
@variables[key] = @metaoptions[key]
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
if @variables.key? :markdown_metadata
|
68
|
+
|
69
|
+
@variables[:markdown_metadata].keys.each do |meta|
|
70
|
+
|
71
|
+
@variables[meta] = @variables[:markdown_metadata][meta]
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
## add additional functional stuff
|
78
|
+
@variables["cursor"] = @pdf.cursor
|
79
|
+
@variables["bounds_height"] = @pdf.bounds.height
|
80
|
+
@variables["bounds_width"] = @pdf.bounds.width
|
81
|
+
@variables["pages"] = @pdf.page_count
|
82
|
+
|
83
|
+
# the currently loaded markdown file
|
84
|
+
@variables["loaded_markdown"] = {}
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
def replace_variables args
|
89
|
+
|
90
|
+
args.keys.each do |arg|
|
91
|
+
|
92
|
+
if args[arg].instance_of? String
|
93
|
+
|
94
|
+
args[arg] = replace_variable args[arg]
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
args
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def replace_variable string
|
104
|
+
|
105
|
+
@variables.keys.each do |key|
|
106
|
+
string = string.gsub("${#{key}}", @variables[key].to_s)
|
107
|
+
end
|
108
|
+
|
109
|
+
string
|
110
|
+
end
|
111
|
+
|
112
|
+
## Parsing template stuff
|
113
|
+
|
114
|
+
# Reads template from JSON
|
115
|
+
# Format: Array of objects where
|
116
|
+
# each object has command and set of args
|
117
|
+
def read_template
|
118
|
+
|
119
|
+
if @options.key? "template"
|
120
|
+
|
121
|
+
if File.file? @options["template"]
|
122
|
+
|
123
|
+
obj = JSON.parse(File.read(@options["template"]), symbolize_names: true)
|
124
|
+
|
125
|
+
default_options = obj[:default_variables].transform_keys!(&:to_s)
|
126
|
+
|
127
|
+
if default_options.nil?
|
128
|
+
default_options = {}
|
129
|
+
end
|
130
|
+
|
131
|
+
@fonts = {}
|
132
|
+
|
133
|
+
@metaoptions = default_options.merge @options
|
134
|
+
|
135
|
+
set_variables
|
136
|
+
|
137
|
+
if obj.key? :fonts
|
138
|
+
|
139
|
+
@fonts = obj[:fonts]
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
add_fonts
|
144
|
+
|
145
|
+
@template = {
|
146
|
+
"main" => obj[:definition]
|
147
|
+
}
|
148
|
+
|
149
|
+
# Runs the main function as entry point of the template
|
150
|
+
@template_stack.push "main"
|
151
|
+
result = execute_function "main", "main", self
|
152
|
+
|
153
|
+
if result[0] != 0
|
154
|
+
|
155
|
+
print_error result[0], result[1]
|
156
|
+
end
|
157
|
+
|
158
|
+
else
|
159
|
+
|
160
|
+
@error_param["arg"] = @options["template"].to_s
|
161
|
+
print_error 15, -1
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
else
|
166
|
+
|
167
|
+
print_error 16, -1
|
168
|
+
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def execute_function template_id, function_id, obj
|
173
|
+
|
174
|
+
definition = nil
|
175
|
+
|
176
|
+
if !@template.key? template_id
|
177
|
+
|
178
|
+
@error_param["arg"] = template_id.to_s
|
179
|
+
# Fails because template ID not found.
|
180
|
+
return [5, -1]
|
181
|
+
|
182
|
+
else
|
183
|
+
|
184
|
+
if !@template[template_id].key? function_id.to_sym
|
185
|
+
|
186
|
+
@error_param["arg"] = function_id.to_s
|
187
|
+
# Fails because template function ID not found.
|
188
|
+
return [6, -1]
|
189
|
+
|
190
|
+
else
|
191
|
+
|
192
|
+
definition = Marshal.load(Marshal.dump(@template[template_id][function_id.to_sym]))
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
if definition.instance_of? Array
|
199
|
+
|
200
|
+
counter = 0
|
201
|
+
|
202
|
+
@counter_stack.push counter
|
203
|
+
|
204
|
+
for index in counter ... definition.size
|
205
|
+
|
206
|
+
# executes the command
|
207
|
+
line = definition[counter]
|
208
|
+
|
209
|
+
set_variables
|
210
|
+
|
211
|
+
command = ""
|
212
|
+
|
213
|
+
if line.key? :cmd
|
214
|
+
|
215
|
+
command = line[:cmd].to_sym
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
if line.key? :command
|
220
|
+
|
221
|
+
command = line[:command].to_sym
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
args = {
|
226
|
+
"LINE_NUMBER" => counter
|
227
|
+
}
|
228
|
+
|
229
|
+
if line.key? :args
|
230
|
+
|
231
|
+
args = line[:args]
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
begin
|
236
|
+
|
237
|
+
args = replace_variables(args)
|
238
|
+
|
239
|
+
rescue => error
|
240
|
+
|
241
|
+
print "\n"
|
242
|
+
print error
|
243
|
+
print "\n"
|
244
|
+
print "Error rendering variables!\n"
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
if !command.empty?
|
249
|
+
|
250
|
+
if COMMAND.keys.include? command
|
251
|
+
|
252
|
+
@command_stack.push definition
|
253
|
+
|
254
|
+
if @command_stack.count > 1024
|
255
|
+
# Failed because of stack overflow
|
256
|
+
return [4, counter]
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
comm = COMMAND[command].call obj, args
|
261
|
+
|
262
|
+
@counter_stack[-1] = counter
|
263
|
+
counter += 1
|
264
|
+
|
265
|
+
# something about command execution failed
|
266
|
+
if comm != 0
|
267
|
+
|
268
|
+
return [comm, counter]
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
@command_stack.pop
|
273
|
+
else
|
274
|
+
# failed because command not found
|
275
|
+
return [3, counter]
|
276
|
+
|
277
|
+
end
|
278
|
+
|
279
|
+
else
|
280
|
+
# failed because no command defined
|
281
|
+
return [2, -1]
|
282
|
+
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
@counter_stack.pop()
|
287
|
+
|
288
|
+
# Returns 0 if successful
|
289
|
+
return [0, counter]
|
290
|
+
|
291
|
+
end
|
292
|
+
|
293
|
+
# Failed because malformed command list
|
294
|
+
return [1, -1]
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
## Error handling stuff for TemplatePDFWriter
|
2
|
+
|
3
|
+
module PetitFelix
|
4
|
+
module Worker
|
5
|
+
|
6
|
+
class TemplatePDFWriter < PetitFelix::Worker::DefaultPDFWriter
|
7
|
+
|
8
|
+
# error count: 16
|
9
|
+
|
10
|
+
ERROR_CODES = [
|
11
|
+
"OK",
|
12
|
+
"Malformed command list.",
|
13
|
+
"No command defined. Use \"com\" or \"command\" to define commands.",
|
14
|
+
"Command not found.",
|
15
|
+
"Stack overflow.",
|
16
|
+
"Template ID \"{{arg}}\" not found.",
|
17
|
+
"Template method \"{{arg}}\" not found.",
|
18
|
+
"\"{{arg}}\" argument not defined.",
|
19
|
+
"Expression \"{{arg}}\" does not result in boolean result.",
|
20
|
+
"Expression \"{{arg}}\" cannot be evaluated.",
|
21
|
+
"File \"{{arg}}\" not found.",
|
22
|
+
"Not a valid position.",
|
23
|
+
"\"at\" (Array) argument not defined.",
|
24
|
+
"\"{{arg}}\" is not an array.",
|
25
|
+
"Image \"{{arg}}\" not found.",
|
26
|
+
"Template file \"{{arg}}\" not found.",
|
27
|
+
"\"template\" option not defined. No template file can be loaded."
|
28
|
+
]
|
29
|
+
|
30
|
+
## Error display
|
31
|
+
|
32
|
+
def error_replace_string error
|
33
|
+
|
34
|
+
@error_param.keys.each do |key|
|
35
|
+
|
36
|
+
error = error.gsub "{{#{key}}}", @error_param[key]
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
error
|
41
|
+
end
|
42
|
+
|
43
|
+
def print_error error_code, line
|
44
|
+
|
45
|
+
if error_code > -1 && error_code < ERROR_CODES.count
|
46
|
+
|
47
|
+
@error_printer.print_err "Error reading template. #{error_replace_string( ERROR_CODES[error_code])}"
|
48
|
+
|
49
|
+
else
|
50
|
+
|
51
|
+
@error_printer.print_err "Error reading template. General template processing error occured."
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
print "Error code: #{error_code}"
|
56
|
+
|
57
|
+
print "\n\n"
|
58
|
+
print "Processing markdown file: #{@metaoptions["filename"]}"
|
59
|
+
print "\n\n"
|
60
|
+
|
61
|
+
stack_rv = @command_stack.reverse
|
62
|
+
|
63
|
+
if line >= 0 && !stack_rv.empty?
|
64
|
+
|
65
|
+
print "\n\nCurrent line:\n"
|
66
|
+
print stack_rv[0][line]
|
67
|
+
|
68
|
+
print "\n\nCurrent Stack:"
|
69
|
+
test_arr = *(0..[19,@command_stack.count-1].min)
|
70
|
+
test_arr.each do | i |
|
71
|
+
|
72
|
+
command_obj = stack_rv[i]
|
73
|
+
|
74
|
+
line_edit = command_obj[0..@counter_stack[i]+1]
|
75
|
+
|
76
|
+
print "\n"
|
77
|
+
print "Line: #{line_edit.count}: "
|
78
|
+
print line_edit[-1]
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
print "\n"
|
84
|
+
|
85
|
+
return error_code
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
## font handling stuff for TemplatePDFWriter
|
2
|
+
|
3
|
+
module PetitFelix
|
4
|
+
module Worker
|
5
|
+
|
6
|
+
class TemplatePDFWriter < PetitFelix::Worker::DefaultPDFWriter
|
7
|
+
|
8
|
+
# Adds a font to the pdf document
|
9
|
+
def add_font font, font_name
|
10
|
+
|
11
|
+
if font.key?(:normal)
|
12
|
+
|
13
|
+
if font.key?(:italic)
|
14
|
+
|
15
|
+
font[:italic] = font[:normal]
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
if font.key?(:bold)
|
20
|
+
|
21
|
+
font[:bold] = font[:normal]
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
if font.key?(:bold_italic)
|
26
|
+
|
27
|
+
font[:bold_italic] = font[:normal]
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
font.keys.each do |key|
|
32
|
+
|
33
|
+
font[key] = replace_variable font[key]
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
font_families.update(font_name => font)
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_fonts
|
44
|
+
|
45
|
+
font_families.clear
|
46
|
+
|
47
|
+
fonts = Marshal.load(Marshal.dump(@fonts))
|
48
|
+
|
49
|
+
fonts.keys.each do |font|
|
50
|
+
|
51
|
+
add_font fonts[font], font.to_s
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|