markdown2docx 0.1.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/bin/md2docx +9 -0
- data/lib/markdown2docx.rb +416 -0
- data/samples/release.docx +0 -0
- data/samples/release.yaml +34 -0
- metadata +130 -0
data/bin/md2docx
ADDED
@@ -0,0 +1,416 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'zip' # 'zip/zip' # rubyzip gem
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'yaml'
|
5
|
+
require 'dimensions'
|
6
|
+
require 'kramdown'
|
7
|
+
|
8
|
+
YAML::ENGINE.yamler = 'syck'
|
9
|
+
|
10
|
+
class Markdown2Docx
|
11
|
+
def self.open(path, &block)
|
12
|
+
self.new(path, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(path, &block)
|
16
|
+
@replace = {}
|
17
|
+
@media = {}
|
18
|
+
if block_given?
|
19
|
+
@zip = Zip::File.open(path)
|
20
|
+
yield(self)
|
21
|
+
@zip.close
|
22
|
+
else
|
23
|
+
@zip = Zip::File.open(path)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_node(run, search)
|
28
|
+
node_to_find = (run.xpath(".//#{search}")).first
|
29
|
+
if node_to_find.nil?
|
30
|
+
node_to_find = Nokogiri::XML::Node.new search, @doc
|
31
|
+
run.add_child node_to_find
|
32
|
+
end
|
33
|
+
node_to_find
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_emus_dimensions(image_file)
|
37
|
+
dimensions = Dimensions.dimensions(image_file)
|
38
|
+
px_width = dimensions[0]
|
39
|
+
px_height = dimensions[1]
|
40
|
+
dpi = 96.0
|
41
|
+
emus_per_inch = 914400.0
|
42
|
+
emus_per_cm = 360000.0
|
43
|
+
max_width_cm = 15.0
|
44
|
+
emus_width = px_width / dpi * emus_per_inch
|
45
|
+
emus_height = px_height / dpi * emus_per_inch
|
46
|
+
max_width = max_width_cm * emus_per_cm
|
47
|
+
if (emus_width > max_width)
|
48
|
+
ratio = emus_height / emus_width
|
49
|
+
emus_width = max_width
|
50
|
+
emus_height = emus_width * ratio
|
51
|
+
end
|
52
|
+
|
53
|
+
return emus_width.round, emus_height.round
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_image_node(image_file, description)
|
57
|
+
image_name = File.basename image_file
|
58
|
+
docx_image_path = File.join 'media', image_name
|
59
|
+
@media[File.join 'word',docx_image_path] = File.binread image_file
|
60
|
+
rel_id = add_rels_link(docx_image_path, :image)
|
61
|
+
check_for_jpeg_content_type
|
62
|
+
drawing = Nokogiri::XML::Node.new 'w:drawing', @doc
|
63
|
+
inline = Nokogiri::XML::Node.new 'wp:inline', @doc
|
64
|
+
drawing.add_child inline
|
65
|
+
inline['distT'] = '0'
|
66
|
+
inline['distB'] = '0'
|
67
|
+
inline['distL'] = '0'
|
68
|
+
inline['distR'] = '0'
|
69
|
+
|
70
|
+
extent = Nokogiri::XML::Node.new 'wp:extent', @doc
|
71
|
+
inline.add_child extent
|
72
|
+
emu_dimensions = get_emus_dimensions image_file
|
73
|
+
extent['cx'] = emu_dimensions[0]
|
74
|
+
extent['cy'] = emu_dimensions[1]
|
75
|
+
|
76
|
+
effect_extent = Nokogiri::XML::Node.new 'wp:effectExtent', @doc
|
77
|
+
inline.add_child effect_extent
|
78
|
+
effect_extent['l'] = 0 # '19050'
|
79
|
+
effect_extent['t'] = 0
|
80
|
+
effect_extent['r'] = 0 #2099'
|
81
|
+
effect_extent['b'] = 0
|
82
|
+
|
83
|
+
docPr = Nokogiri::XML::Node.new 'wp:docPr', @doc
|
84
|
+
inline.add_child docPr
|
85
|
+
docPr['id'] = '1'
|
86
|
+
docPr['name'] = image_name
|
87
|
+
docPr['descr'] = description
|
88
|
+
|
89
|
+
non_visual_graphic_props = Nokogiri::XML::Node.new 'wp:cNvGraphicFramePr', @doc
|
90
|
+
inline.add_child non_visual_graphic_props
|
91
|
+
frame_locks = Nokogiri::XML::Node.new 'a:graphicFrameLocks', @doc
|
92
|
+
frame_locks.add_namespace_definition 'a', 'http://schemas.openxmlformats.org/drawingml/2006/main'
|
93
|
+
frame_locks['noChangeAspect'] = '1'
|
94
|
+
non_visual_graphic_props.add_child frame_locks
|
95
|
+
|
96
|
+
graphic = Nokogiri::XML::Node.new 'a:graphic', @doc
|
97
|
+
inline.add_child graphic
|
98
|
+
graphic.add_namespace_definition 'a', 'http://schemas.openxmlformats.org/drawingml/2006/main'
|
99
|
+
|
100
|
+
graphic_data = Nokogiri::XML::Node.new 'a:graphicData', @doc
|
101
|
+
graphic.add_child graphic_data
|
102
|
+
graphic_data['uri'] = 'http://schemas.openxmlformats.org/drawingml/2006/picture'
|
103
|
+
|
104
|
+
pic = Nokogiri::XML::Node.new 'pic:pic', @doc
|
105
|
+
pic.add_namespace_definition 'pic', 'http://schemas.openxmlformats.org/drawingml/2006/picture'
|
106
|
+
graphic_data.add_child pic
|
107
|
+
|
108
|
+
nv_picture_properties = Nokogiri::XML::Node.new 'pic:nvPicPr', @doc
|
109
|
+
pic.add_child nv_picture_properties
|
110
|
+
nv_drawing_properties = Nokogiri::XML::Node.new 'pic:cNvPr', @doc
|
111
|
+
nv_drawing_properties['id'] = '0'
|
112
|
+
nv_drawing_properties['name'] = image_name
|
113
|
+
nv_drawing_properties['descr'] = description
|
114
|
+
nv_picture_properties.add_child nv_drawing_properties
|
115
|
+
|
116
|
+
nv_picture_drawing_properties = Nokogiri::XML::Node.new 'pic:cNvPicPr', @doc
|
117
|
+
nv_picture_properties.add_child nv_picture_drawing_properties
|
118
|
+
pic_locks = Nokogiri::XML::Node.new 'a:picLocks', @doc
|
119
|
+
pic_locks['noChangeAspect'] = '1'
|
120
|
+
nv_picture_drawing_properties.add_child pic_locks
|
121
|
+
|
122
|
+
blip_fill = Nokogiri::XML::Node.new 'pic:blipFill', @doc
|
123
|
+
pic.add_child blip_fill
|
124
|
+
|
125
|
+
blip = Nokogiri::XML::Node.new 'a:blip', @doc
|
126
|
+
blip_fill.add_child blip
|
127
|
+
blip['r:embed'] = "rId#{rel_id}"
|
128
|
+
blip['cstate'] = 'print'
|
129
|
+
|
130
|
+
src_rect = Nokogiri::XML::Node.new 'a:srcRect', @doc
|
131
|
+
blip_fill.add_child src_rect
|
132
|
+
|
133
|
+
stretch = Nokogiri::XML::Node.new 'a:stretch', @doc
|
134
|
+
fill_rect = Nokogiri::XML::Node.new 'a:fillRect', @doc
|
135
|
+
stretch.add_child fill_rect
|
136
|
+
blip_fill.add_child stretch
|
137
|
+
|
138
|
+
shape_properties = Nokogiri::XML::Node.new 'pic:spPr', @doc
|
139
|
+
shape_properties['bwMode'] = 'auto'
|
140
|
+
transform = Nokogiri::XML::Node.new 'a:xfrm', @doc
|
141
|
+
offset = Nokogiri::XML::Node.new 'a:off', @doc
|
142
|
+
offset['x'] = '0'
|
143
|
+
offset['y'] = '0'
|
144
|
+
transform.add_child offset
|
145
|
+
extents = Nokogiri::XML::Node.new 'a:ext', @doc
|
146
|
+
|
147
|
+
extents['cx'] = (emu_dimensions[0] * 1.0000762).round
|
148
|
+
extents['cy'] = (emu_dimensions[1] * 1.0000762).round
|
149
|
+
transform.add_child extents
|
150
|
+
shape_properties.add_child transform
|
151
|
+
|
152
|
+
preset_geometry = Nokogiri::XML::Node.new 'a:prstGeom', @doc
|
153
|
+
preset_geometry['prst'] = 'rect'
|
154
|
+
adjust_value_list = Nokogiri::XML::Node.new 'a:avLst', @doc
|
155
|
+
preset_geometry.add_child adjust_value_list
|
156
|
+
shape_properties.add_child preset_geometry
|
157
|
+
|
158
|
+
no_fill = Nokogiri::XML::Node.new 'a:noFill', @doc
|
159
|
+
shape_properties.add_child no_fill
|
160
|
+
|
161
|
+
line = Nokogiri::XML::Node.new 'a:ln', @doc
|
162
|
+
line['w'] = 0 # '9525'
|
163
|
+
line.add_child no_fill.dup
|
164
|
+
miter = Nokogiri::XML::Node.new 'a:miter', @doc
|
165
|
+
miter['lim'] = '800000'
|
166
|
+
line.add_child miter
|
167
|
+
line.add_child Nokogiri::XML::Node.new 'a:headEnd', @doc
|
168
|
+
line.add_child Nokogiri::XML::Node.new 'a:tailEnd', @doc
|
169
|
+
shape_properties.add_child line
|
170
|
+
|
171
|
+
pic.add_child shape_properties
|
172
|
+
|
173
|
+
drawing
|
174
|
+
end
|
175
|
+
|
176
|
+
def process_runs(source_node, cur_run)
|
177
|
+
old_run = cur_run
|
178
|
+
|
179
|
+
source_node.children.each do |run|
|
180
|
+
next_run = cur_run.dup
|
181
|
+
if cur_run.parent.nil?
|
182
|
+
old_run.add_next_sibling(cur_run)
|
183
|
+
end
|
184
|
+
if run.name == 'strong'
|
185
|
+
bold = Nokogiri::XML::Node.new 'w:b', @doc
|
186
|
+
get_node(cur_run, 'w:rPr').add_child bold
|
187
|
+
elsif run.name == 'br'
|
188
|
+
br = Nokogiri::XML::Node.new 'w:br', @doc
|
189
|
+
get_node(cur_run, 'w:rPr').add_child br
|
190
|
+
elsif run.name == 'a'
|
191
|
+
rel_id = add_rels_link(run['href'], :hyperlink)
|
192
|
+
r_id = "rId#{rel_id}"
|
193
|
+
hyperlink = Nokogiri::XML::Node.new 'w:hyperlink', @doc
|
194
|
+
hyperlink['r:id'] = r_id
|
195
|
+
hyperlink['w:history'] = "1"
|
196
|
+
cur_run.add_next_sibling(hyperlink)
|
197
|
+
hyperlink.add_child(cur_run)
|
198
|
+
style = Nokogiri::XML::Node.new 'w:rStyle', @doc
|
199
|
+
style['w:val'] = 'Hyperlink'
|
200
|
+
get_node(cur_run, 'w:rPr').add_child style
|
201
|
+
elsif run.name == 'img'
|
202
|
+
image_node = create_image_node run['src'], run['alt']
|
203
|
+
run_properties = get_node(cur_run, 'w:rPr')
|
204
|
+
run_properties.add_child Nokogiri::XML::Node.new('w:noProof', @doc)
|
205
|
+
#(cur_run.parent/'.//w:ind').remove
|
206
|
+
lang = Nokogiri::XML::Node.new 'w:lang', @doc
|
207
|
+
lang['w:val'] = 'en-GB'
|
208
|
+
lang['w:eastAsia'] = 'en-GB'
|
209
|
+
run_properties.add_child lang
|
210
|
+
cur_run.add_child image_node
|
211
|
+
end
|
212
|
+
if run.name != 'img'
|
213
|
+
if run.text[0] == ' '
|
214
|
+
new_text = Nokogiri::XML::Node.new "w:t", @doc
|
215
|
+
cur_run.add_child new_text
|
216
|
+
new_text['xml:space'] = "preserve"
|
217
|
+
new_text.content = ' '
|
218
|
+
old_run = cur_run
|
219
|
+
cur_run = next_run
|
220
|
+
next_run = cur_run.dup
|
221
|
+
old_run.add_next_sibling(cur_run)
|
222
|
+
end
|
223
|
+
|
224
|
+
new_text = Nokogiri::XML::Node.new "w:t", @doc
|
225
|
+
cur_run.add_child new_text
|
226
|
+
new_text.content = run.text
|
227
|
+
|
228
|
+
if run.text[run.text.length-1] == ' '
|
229
|
+
cur_run.add_next_sibling(next_run)
|
230
|
+
cur_run = next_run
|
231
|
+
next_run = cur_run.dup
|
232
|
+
new_text = Nokogiri::XML::Node.new "w:t", @doc
|
233
|
+
cur_run.add_child new_text
|
234
|
+
new_text['xml:space'] = "preserve"
|
235
|
+
new_text.content = ' '
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
if run.name == 'a'
|
240
|
+
old_run = hyperlink
|
241
|
+
else
|
242
|
+
old_run = cur_run
|
243
|
+
end
|
244
|
+
cur_run = next_run
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def add_paragraph(text_elements, cur_node)
|
249
|
+
first_run = (cur_node.xpath('.//w:r')).first
|
250
|
+
|
251
|
+
process_runs text_elements, first_run
|
252
|
+
end
|
253
|
+
|
254
|
+
def add_bullet(text_elements, cur_node)
|
255
|
+
bullet_node = (cur_node.xpath('.//w:pPr')).first
|
256
|
+
(bullet_node/'.//w:ind').remove
|
257
|
+
numpr = Nokogiri::XML::Node.new "w:numPr", @doc
|
258
|
+
ilvl = Nokogiri::XML::Node.new "w:ilvl", @doc
|
259
|
+
ilvl['w:val'] = '0'
|
260
|
+
numpr.add_child ilvl
|
261
|
+
numId = Nokogiri::XML::Node.new 'w:numId', @doc
|
262
|
+
numId['w:val'] = '22'
|
263
|
+
numpr.add_child numId
|
264
|
+
bullet_node.add_child numpr
|
265
|
+
|
266
|
+
first_run = (cur_node.xpath('.//w:r')).first
|
267
|
+
process_runs text_elements, first_run
|
268
|
+
end
|
269
|
+
|
270
|
+
def process_elements(elements, cur_node)
|
271
|
+
old_node = cur_node
|
272
|
+
elements.each do |element|
|
273
|
+
dup_p = cur_node.dup
|
274
|
+
if cur_node.parent.nil?
|
275
|
+
old_node.add_next_sibling(cur_node)
|
276
|
+
end
|
277
|
+
if element.name == 'p'
|
278
|
+
add_paragraph element, cur_node
|
279
|
+
elsif element.name == 'h3'
|
280
|
+
properties = get_node(cur_node, 'w:pPr')
|
281
|
+
style = get_node(properties, 'w:pStyle')
|
282
|
+
style['w:val'] = 'Heading3'
|
283
|
+
add_paragraph element, cur_node
|
284
|
+
elsif element.name == 'li'
|
285
|
+
add_bullet element, cur_node
|
286
|
+
elsif element.name == 'ul'
|
287
|
+
cur_node = process_elements element.elements, cur_node
|
288
|
+
end
|
289
|
+
|
290
|
+
old_node = cur_node
|
291
|
+
cur_node = dup_p
|
292
|
+
end
|
293
|
+
old_node
|
294
|
+
end
|
295
|
+
|
296
|
+
def merge_yaml(yaml_file)
|
297
|
+
records = YAML::parse_file yaml_file
|
298
|
+
merge(records)
|
299
|
+
end
|
300
|
+
|
301
|
+
def merge(rec)
|
302
|
+
xml = @zip.read("word/document.xml")
|
303
|
+
@doc = Nokogiri::XML(xml) {|x| x.noent}
|
304
|
+
doc_values = (@doc/"//w:p") #.select { |element| element.text =~ /^\$(.*)\$$/ }
|
305
|
+
doc_values.each do |element|
|
306
|
+
#puts element.text
|
307
|
+
if element.text =~ /^\$(.*)\$$/
|
308
|
+
value = (rec.select $1)[0]
|
309
|
+
if value.nil?
|
310
|
+
value = ''
|
311
|
+
else
|
312
|
+
value = value.value
|
313
|
+
end
|
314
|
+
|
315
|
+
# Ensure there is only one w:t node
|
316
|
+
(element/'.//w:t').remove
|
317
|
+
|
318
|
+
value_html = Kramdown::Document.new(value).to_html
|
319
|
+
|
320
|
+
html_doc = Nokogiri::HTML(value_html)
|
321
|
+
if html_doc.elements.count > 0
|
322
|
+
markdown_elements = html_doc.elements[0].elements[0].elements
|
323
|
+
process_elements(markdown_elements, element)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
@replace["word/document.xml"] = @doc.serialize :save_with => 0
|
328
|
+
end
|
329
|
+
|
330
|
+
def check_for_jpeg_content_type()
|
331
|
+
xml_file = '[Content_Types].xml'
|
332
|
+
xml = @replace[xml_file] || @zip.read(xml_file)
|
333
|
+
types = Nokogiri::XML(xml) {|x| x.noent}
|
334
|
+
|
335
|
+
default_types = types.elements[0]/"Default"
|
336
|
+
|
337
|
+
if default_types.select { |element| element['Extension'] == 'jpeg'}.count == 0
|
338
|
+
jpeg_type = Nokogiri::XML::Node.new 'Default', types
|
339
|
+
jpeg_type['Extension'] = 'jpeg'
|
340
|
+
jpeg_type['ContentType'] = 'image/jeg'
|
341
|
+
#default_types.last.add_next_sibling jpeg_type
|
342
|
+
types.children[0].add_child jpeg_type
|
343
|
+
@replace[xml_file] = types.serialize :save_with => 0
|
344
|
+
end
|
345
|
+
|
346
|
+
|
347
|
+
end
|
348
|
+
|
349
|
+
def add_rels_link(url, type)
|
350
|
+
xml = @replace["word/_rels/document.xml.rels"] || @zip.read("word/_rels/document.xml.rels")
|
351
|
+
rels = Nokogiri::XML(xml) {|x| x.noent}
|
352
|
+
|
353
|
+
cur_id = 1
|
354
|
+
have_unused_id = false
|
355
|
+
until have_unused_id
|
356
|
+
id = "rId#{cur_id}"
|
357
|
+
have_unused_id = true
|
358
|
+
rels.elements[0].elements.each do |element|
|
359
|
+
if element['Id'] == id
|
360
|
+
cur_id += 1
|
361
|
+
id = "rId#{cur_id}"
|
362
|
+
have_unused_id = false
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
relationship = Nokogiri::XML::Node.new "Relationship", rels
|
368
|
+
relationship['Id'] = id
|
369
|
+
if type == :hyperlink
|
370
|
+
relationship['Type'] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
|
371
|
+
relationship['TargetMode'] = 'External'
|
372
|
+
elsif type == :image
|
373
|
+
relationship['Type'] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
|
374
|
+
end
|
375
|
+
relationship['Target'] = url
|
376
|
+
|
377
|
+
rels.elements[0].add_child relationship
|
378
|
+
|
379
|
+
@replace["word/_rels/document.xml.rels"] = rels.serialize :save_with => 0
|
380
|
+
|
381
|
+
cur_id
|
382
|
+
end
|
383
|
+
|
384
|
+
def save(path)
|
385
|
+
Zip::File.open(path, Zip::File::CREATE) do |out|
|
386
|
+
@zip.each do |entry|
|
387
|
+
out.get_output_stream(entry.name) do |o|
|
388
|
+
if @replace[entry.name]
|
389
|
+
o.write(@replace[entry.name])
|
390
|
+
else
|
391
|
+
o.write(@zip.read(entry.name))
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
@media.keys.each do |key|
|
396
|
+
out.get_output_stream(key) { |o| o.write @media[key] }
|
397
|
+
end
|
398
|
+
end
|
399
|
+
@zip.close
|
400
|
+
|
401
|
+
# this is to ensure the zip can actually be opened by word. RubyZip doesn't quite do it
|
402
|
+
# from the build server
|
403
|
+
require 'rbconfig'
|
404
|
+
is_windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
405
|
+
if is_windows
|
406
|
+
if Dir.exist?('releasePack')
|
407
|
+
FileUtils.rmtree 'releasePack'
|
408
|
+
end
|
409
|
+
`"C:\\program files\\7-zip\\7z.exe" x -oreleasePack release.docx`
|
410
|
+
`cd releasePack && "C:\\program files\\7-zip\\7z.exe" a release.docx *`
|
411
|
+
FileUtils.move File.join('releasePack', 'release.docx'), 'release.docx'
|
412
|
+
FileUtils.rmtree 'releasePack'
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
Binary file
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Release pack
|
2
|
+
|
3
|
+
# Title page
|
4
|
+
|
5
|
+
author: Dave Arkell
|
6
|
+
project: Markdown to docx
|
7
|
+
system_area: Ruby
|
8
|
+
|
9
|
+
version_history:
|
10
|
+
- author: Dave Arkell
|
11
|
+
description: Initial version
|
12
|
+
version: 1
|
13
|
+
date: 26/09/2013
|
14
|
+
- author: Daoud Clarke
|
15
|
+
description: Remove company content
|
16
|
+
date: 22/10/2013
|
17
|
+
|
18
|
+
# Overview
|
19
|
+
|
20
|
+
release_overview: |+
|
21
|
+
This is a test paragraph.
|
22
|
+
|
23
|
+
\\
|
24
|
+
This is another paragraph.
|
25
|
+
* **Something bold** - nice
|
26
|
+
* **Something else** - also good
|
27
|
+
|
28
|
+
\\
|
29
|
+
Here is a link to [DuckDuckGo](https://duckduckgo.com)
|
30
|
+
|
31
|
+
Here is a wombat:
|
32
|
+
\\
|
33
|
+

|
34
|
+
|
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: markdown2docx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dave Arkell
|
9
|
+
- Daoud Clarke
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-10-07 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: dimensions
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: rubyzip
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 1.0.0
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.0.0
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: nokogiri
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: dimensions
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: kramdown
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
type: :runtime
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
description: Combines markdown in a yaml file with a docx template
|
96
|
+
email: daoud.clarke@gmail.com
|
97
|
+
executables:
|
98
|
+
- md2docx
|
99
|
+
extensions: []
|
100
|
+
extra_rdoc_files: []
|
101
|
+
files:
|
102
|
+
- lib/markdown2docx.rb
|
103
|
+
- bin/md2docx
|
104
|
+
- samples/release.yaml
|
105
|
+
- samples/release.docx
|
106
|
+
homepage:
|
107
|
+
licenses: []
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ! '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project:
|
126
|
+
rubygems_version: 1.8.23
|
127
|
+
signing_key:
|
128
|
+
specification_version: 3
|
129
|
+
summary: markdown2docx
|
130
|
+
test_files: []
|