sablon 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1c8b7cc35ce1718d11e3ebc44d2b50e5a03b1575
4
- data.tar.gz: 003512773f3372b9ed1243a4a7fd88ac301dafcb
3
+ metadata.gz: 8a4d14328ddbea68fddbbc747b5a8e4fe89b7e1b
4
+ data.tar.gz: 45c9af0a71ce34c1c2211474bf75f0f60fd611fb
5
5
  SHA512:
6
- metadata.gz: ad54b7f87dc83a60b77fb3559d756d1798197f264618195e11796c0cd0cd71bea955991b5f7d01aa2ad668c4afbed0f2c9eaf16c0b28a3d693b0bb2c4cbe891a
7
- data.tar.gz: 4c45533f60f2cf77b7d17be0ad77a3180fc17c3c6257178963229d1374bc8eef0d31024a110e8a9b11b4b768e451a4d04f674d0113b696a6d102cc4f8b16cdd6
6
+ metadata.gz: d5d4a12a4ec9c75a08fb18a729775072ee96cd029cbd064a8295832be6c9a70409e27c80dfd0ea92354a10d2c4715946e03d414a52d1514bd8300ef56c6c00cf
7
+ data.tar.gz: 9525095be7b154d71e307ec3bdebb6a026c6b514b03323b09151a58ec2376c22f8c66921ac70525c1f87f0005e999670c6b2c12097f0b736fe642db6284627f4
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sablon (0.0.10)
4
+ sablon (0.0.11)
5
5
  nokogiri (>= 1.6.0)
6
+ redcarpet (>= 3.2)
6
7
  rubyzip (>= 1.1)
7
8
 
8
9
  GEM
@@ -13,6 +14,7 @@ GEM
13
14
  nokogiri (1.6.6.2)
14
15
  mini_portile (~> 0.6.0)
15
16
  rake (10.4.2)
17
+ redcarpet (3.2.2)
16
18
  rubyzip (1.1.7)
17
19
  xml-simple (1.1.5)
18
20
 
data/README.md CHANGED
@@ -32,8 +32,8 @@ template.render_to_file File.expand_path("~/Desktop/output.docx"), context
32
32
 
33
33
  ### Writing Templates
34
34
 
35
- Sablon templates are normal word documents (`.docx`) sprinkled with MergeFields
36
- to perform operations. The following section will use the notation `«=title»` to
35
+ Sablon templates are normal Word documents (`.docx`) sprinkled with MailMerge fields
36
+ to perform operations. The following section uses the notation `«=title»` to
37
37
  refer to [Word MailMerge](http://en.wikipedia.org/wiki/Mail_merge) fields.
38
38
 
39
39
  #### Content Insertion
@@ -70,34 +70,76 @@ format ahead of processing time (in the template) you can insert
70
70
  [WordProcessingML](http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats)
71
71
  directly.
72
72
 
73
- The template can use a simple insertion operation like so:
73
+ It's enough to use a simply insertion operation in the template:
74
74
 
75
75
  ```
76
76
  «=long_description»
77
77
  ```
78
78
 
79
- The thing that changes is the context passed when processing the template:
79
+ To insert WordProcessingML prepare the context accordingly:
80
80
 
81
81
  ```ruby
82
- word_processing_ml = <<-XML
82
+ word_processing_ml = <<-XML.gsub("\n", "")
83
83
  <w:p>
84
- <w:r w:rsidRPr="00B97C39">
85
- <w:rPr>
86
- <w:b />
87
- </w:rPr>
88
- <w:t>this is bold text</w:t>
89
- </w:r>
84
+ <w:r w:rsidRPr="00B97C39">
85
+ <w:rPr>
86
+ <w:b />
87
+ </w:rPr>
88
+ <w:t>this is bold text</w:t>
89
+ </w:r>
90
90
  </w:p>
91
91
  XML
92
+
92
93
  context = {
93
94
  long_description: Sablon.content(:word_ml, word_processing_ml)
94
95
  }
95
96
  template.render_to_file File.expand_path("~/Desktop/output.docx"), context
96
97
  ```
97
98
 
98
- **IMPORTANT:** This feature is very much *experimental*. Currently, this only
99
- works if the insertion is the only thing inside the template paragraph. Other
100
- content is discarded!
99
+ IMPORTANT: This feature is very much *experimental*. Currently, the insertion
100
+ will replace the containing paragraph. This means that other content in the same
101
+ paragraph is discarded.
102
+
103
+ ##### Markdown
104
+
105
+ Similar to WordProcessingML it's possible to use markdown while processing the
106
+ tempalte. You don't need to modify your templates, a simple insertion operation
107
+ is sufficient:
108
+
109
+ ```
110
+ «=article.body»
111
+ ```
112
+
113
+ To use Markdown insertion prepare the context like so:
114
+
115
+ ```ruby
116
+ markdown_body = <<-MD
117
+ This text can contain *additional formatting*
118
+ according to the **Markdown** specification.
119
+ MD
120
+ context = {
121
+ article: { body: Sablon.content(:markdown, markdown_body) }
122
+ }
123
+ template.render_to_file File.expand_path("~/Desktop/output.docx"), context
124
+ ```
125
+
126
+ Markdown insertion has built-in support for:
127
+
128
+ * [Headers](http://spec.commonmark.org/0.17/#atx-header)
129
+ * [Paragraphs](http://spec.commonmark.org/0.17/#paragraphs)
130
+ * [Emphasis and strong emphasis](http://spec.commonmark.org/0.17/#emphasis-and-strong-emphasis)
131
+ * [Hard line breaks](http://spec.commonmark.org/0.17/#hard-line-breaks)
132
+ * [Lists](http://spec.commonmark.org/0.17/#lists)
133
+
134
+ For headings and lists to function properly it is necessary that the template
135
+ defines specific styles. Headings use styles called `Heading1`, `Heading2`,
136
+ etc. according to the header level. Ordered lists will use the style
137
+ `ListNumber` and unordered lists use `ListBullet`. Nested lists are not
138
+ supported.
139
+
140
+ IMPORTANT: This feature is very much *experimental*. Currently, the insertion
141
+ will replace the containing paragraph. This means that other content in the same
142
+ paragraph is discarded.
101
143
 
102
144
  #### Conditionals
103
145
 
@@ -136,7 +178,7 @@ Loops repeat parts of the document.
136
178
  Loops can be used to repeat table rows or list enumerations. The fields need to
137
179
  be placed in within table cells or enumeration items enclosing the rows or items
138
180
  to repeat. Have a look at the
139
- [example template](test/fixtures/sablon_sample.docx) for more details.
181
+ [example template](test/fixtures/cv_template.docx) for more details.
140
182
 
141
183
 
142
184
  #### Nesting
@@ -160,25 +202,48 @@ Have a look at [this test](test/executable_test.rb) for examples.
160
202
 
161
203
  ### Examples
162
204
 
163
- There is a [sample template](test/fixtures/sablon_template.docx) in the
205
+ #### Using a Ruby script
206
+
207
+ There is a [sample template](test/fixtures/cv_template.docx) in the
164
208
  repository, which illustrates the functionality of sablon:
165
209
 
166
210
  <p align="center">
167
211
  <img
168
- src="https://raw.githubusercontent.com/senny/sablon/master/misc/template.png"
212
+ src="https://raw.githubusercontent.com/senny/sablon/master/misc/cv_template.png"
169
213
  alt="Sablon Template"/>
170
214
  </p>
171
215
 
172
216
  Processing this template with some sample data yields the following
173
- [output document](test/fixtures/sablon_sample.docx).
217
+ [output document](test/fixtures/cv_sample.docx).
174
218
  For more details, check out this [test case](test/sablon_test.rb).
175
219
 
176
220
  <p align="center">
177
221
  <img
178
- src="https://raw.githubusercontent.com/senny/sablon/master/misc/output.png"
222
+ src="https://raw.githubusercontent.com/senny/sablon/master/misc/cv_sample.png"
179
223
  alt="Sablon Output"/>
180
224
  </p>
181
225
 
226
+ #### Using the sablon executable
227
+
228
+ The [executable test](test/executable_test.rb) showcases the `sablon`
229
+ executable.
230
+
231
+ The [template](test/fixtures/recipe_template.docx)
232
+
233
+ <p align="center">
234
+ <img
235
+ src="https://raw.githubusercontent.com/senny/sablon/master/misc/recipe_template.png"
236
+ alt="Sablon Output"/>
237
+ </p>
238
+
239
+ is rendered using a [json context](test/fixtures/recipe_context.json) to provide
240
+ the data. Following is the resulting [output](test/fixtures/recipe_sample.docx):
241
+
242
+ <p align="center">
243
+ <img
244
+ src="https://raw.githubusercontent.com/senny/sablon/master/misc/recipe_sample.png"
245
+ alt="Sablon Output"/>
246
+ </p>
182
247
 
183
248
  ## Contributing
184
249
 
data/lib/sablon.rb CHANGED
@@ -9,6 +9,8 @@ require "sablon/content"
9
9
 
10
10
  require 'zip'
11
11
  require 'nokogiri'
12
+ require 'redcarpet'
13
+ require "sablon/redcarpet/render/word_ml"
12
14
 
13
15
  module Sablon
14
16
  class TemplateError < ArgumentError; end
@@ -77,7 +77,24 @@ module Sablon
77
77
  end
78
78
  end
79
79
 
80
+ class Markdown < Struct.new(:word_ml)
81
+ include Sablon::Content
82
+ def self.id; :markdown end
83
+ def self.wraps?(value) false end
84
+
85
+ def initialize(markdown)
86
+ redcarpet = ::Redcarpet::Markdown.new(Sablon::Redcarpet::Render::WordML)
87
+ word_ml = Sablon.content(:word_ml, redcarpet.render(markdown))
88
+ super word_ml
89
+ end
90
+
91
+ def append_to(*args)
92
+ word_ml.append_to(*args)
93
+ end
94
+ end
95
+
80
96
  register Sablon::Content::String
81
97
  register Sablon::Content::WordML
98
+ register Sablon::Content::Markdown
82
99
  end
83
100
  end
@@ -0,0 +1,57 @@
1
+ module Sablon
2
+ module Redcarpet
3
+ module Render
4
+ class WordML < ::Redcarpet::Render::Base
5
+ def linebreak
6
+ "</w:p><w:p>"
7
+ end
8
+
9
+ def header(title, level)
10
+ style = "Heading#{level}"
11
+
12
+ "<w:p><w:pPr><w:pStyle w:val=\"#{style}\"/></w:pPr>#{title}</w:p>"
13
+ end
14
+
15
+ def paragraph(text)
16
+ "<w:p>#{text}</w:p>"
17
+ end
18
+
19
+ def normal_text(text)
20
+ @raw_text = text
21
+ return '' if text.nil? || text == '' || text == "\n"
22
+ "<w:r><w:t xml:space=\"preserve\">#{text}</w:t></w:r>"
23
+ end
24
+
25
+ def emphasis(text)
26
+ "<w:r><w:rPr><w:i /></w:rPr><w:t xml:space=\"preserve\">#{@raw_text}</w:t></w:r>"
27
+ end
28
+
29
+ def double_emphasis(text)
30
+ "<w:r><w:rPr><w:b /></w:rPr><w:t xml:space=\"preserve\">#{@raw_text}</w:t></w:r>"
31
+ end
32
+
33
+ def list(content, list_type)
34
+ content
35
+ end
36
+
37
+ LIST_PATTERN = <<-XML.gsub("\n", "")
38
+ <w:p>
39
+ <w:pPr>
40
+ <w:pStyle w:val="%s" />
41
+ </w:pPr>
42
+ %s
43
+ </w:p>
44
+ XML
45
+ LIST_STYLE_MAPPING = {
46
+ ordered: "ListNumber",
47
+ unordered: "ListBullet"
48
+ }
49
+
50
+ def list_item(content, list_type)
51
+ list_style = LIST_STYLE_MAPPING[list_type]
52
+ LIST_PATTERN % [list_style, content]
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,3 @@
1
1
  module Sablon
2
- VERSION = "0.0.10"
2
+ VERSION = "0.0.11"
3
3
  end
Binary file
Binary file
Binary file
Binary file
data/sablon.gemspec CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_runtime_dependency 'nokogiri', ">= 1.6.0"
22
22
  spec.add_runtime_dependency 'rubyzip', ">= 1.1"
23
+ spec.add_runtime_dependency 'redcarpet', ">= 3.2"
23
24
 
24
25
  spec.add_development_dependency "bundler", ">= 1.6"
25
26
  spec.add_development_dependency "rake", "~> 10.0"
data/test/content_test.rb CHANGED
@@ -158,3 +158,38 @@ class ContentWordMLTest < Sablon::TestCase
158
158
  skip "Content::WordML currently removes the paragraph..."
159
159
  end
160
160
  end
161
+
162
+
163
+ class ContentMarkdownTest < Sablon::TestCase
164
+ include ContentTestSetup
165
+
166
+ def test_blank_markdown
167
+ Sablon.content(:markdown, "").append_to @paragraph, @node
168
+
169
+ assert_xml_equal "<w:p>AFTER</w:p>", @document
170
+ end
171
+
172
+ def test_inserts_markdown
173
+ Sablon.content(:markdown, "yay **bold** text").append_to @paragraph, @node
174
+
175
+ output = <<-XML.strip.gsub("\n", "")
176
+ <w:p>
177
+ <w:r><w:t xml:space=\"preserve\">yay </w:t></w:r>
178
+ <w:r>
179
+ <w:rPr><w:b/></w:rPr>
180
+ <w:t xml:space=\"preserve\">bold</w:t>
181
+ </w:r>
182
+ <w:r>
183
+ <w:t xml:space=\"preserve\"> text</w:t>
184
+ </w:r>
185
+ </w:p>
186
+ <w:p>AFTER</w:p>
187
+ XML
188
+
189
+ assert_xml_equal output, @document
190
+ end
191
+
192
+ def test_inserting_markdown_multiple_times_into_same_paragraph
193
+ skip "Content::Markdown currently removes the paragraph..."
194
+ end
195
+ end
@@ -6,23 +6,23 @@ class ExecutableTest < Sablon::TestCase
6
6
  def setup
7
7
  super
8
8
  @base_path = Pathname.new(File.expand_path("../", __FILE__))
9
- @output_path = @base_path + "sandbox/shopping_list.docx"
10
- @template_path = @base_path + "fixtures/shopping_list_template.docx"
11
- @context_path = @base_path + "fixtures/shopping_list_context.json"
9
+ @output_path = @base_path + "sandbox/recipe.docx"
10
+ @template_path = @base_path + "fixtures/recipe_template.docx"
11
+ @sample_path = @base_path + "fixtures/recipe_sample.docx"
12
+ @context_path = @base_path + "fixtures/recipe_context.json"
12
13
  @executable_path = @base_path + '../exe/sablon'
13
-
14
14
  @output_path.delete if @output_path.exist?
15
15
  end
16
16
 
17
17
  def test_generate_document_from_template_output_to_file
18
18
  `cat #{@context_path} | #{@executable_path} #{@template_path} #{@output_path}`
19
19
 
20
- assert_docx_equal @base_path + "fixtures/shopping_list_sample.docx", @output_path
20
+ assert_docx_equal @sample_path, @output_path
21
21
  end
22
22
 
23
23
  def test_generate_document_from_template_output_to_stdout
24
24
  `cat #{@context_path} | #{@executable_path} #{@template_path} > #{@output_path}`
25
25
 
26
- assert_docx_equal @base_path + "fixtures/shopping_list_sample.docx", @output_path
26
+ assert_docx_equal @sample_path, @output_path
27
27
  end
28
28
  end
Binary file
Binary file
@@ -0,0 +1,24 @@
1
+ {
2
+ "metadata": {
3
+ "generator": "Sablon",
4
+ "author": {
5
+ "name": "Brett",
6
+ "profile": "http://www.opensourcefood.com/people/Brett"
7
+ }
8
+ },
9
+ "title": "Bruschetta",
10
+ "word_ml:intro": "<w:p><w:r><w:rPr><w:b/></w:rPr><w:t xml:space=\"preserve\">Bruschetta</w:t></w:r><w:r><w:t xml:space=\"preserve\"> </w:t></w:r><w:r><w:rPr><w:i/></w:rPr><w:t xml:space=\"preserve\">(Italian pronunciation: [bruˈsketta])</w:t></w:r><w:r><w:t xml:space=\"preserve\"> is an antipasto (starter dish) from Italy consisting of grilled bread rubbed with garlic and topped with tomatoes, olive oil, salt and pepper. Variations may include toppings of tomato, vegetables, beans, cured meat, or cheese, a popular dish is Bruschetta pomodoro; the most popular recipe outside of Italy involves basil, fresh tomato, garlic and onion or mozzarella. Bruschetta is usually served as a snack or appetizer. In some countries, a topping of chopped tomato, olive oil and herbs is marketed under the bruschetta name.</w:t></w:r></w:p>",
11
+ "markdown:preparation": "## How to make Baby's Bruschetta\n\n### Preparation\nMake the bruschetta mixture one day before the event and let it sit in the fridge overnight to absorb all the flavours(be aware your fridge will smell entirely like the *tomatoes* and *garlic* \nI find it works best to slice the *baguette* on an angle to create more space. Put the broiler on the oven on to toast the bread. Line them up on a baking sheet and make a small mixture of chopped garlic and olive oil to lightly spread on the slices of *baguette*, then place into the oven. \nOnce Half toasted remove bread and place bruschetta mixture on top (after draining off the majority of fluid). Then sprinkle the grated cheese on top and place back into the oven to broil/toast to your desired effect. ~ Please note that if you prefer to not have your *cheese* melted you can skip this step and just toast the bread fully, add the mixture and *cheese* and serve. \nOnce melted, remove and place directly on a serving platter and let rest for one minute while adding fresh chopped *basil* for garnish, and **ENJOY!**\n\n### Variations\n\n1. Use fresh oregano instead of basil.\n1. Other possible toppings: prosciutto, salami, bean spreads\n\n### Notes\n- In **Italy**, bruschetta is often prepared using a brustolina grill. In the Abruzzo region of Italy a variation of bruschetta made with a salame called *ventricina* is served.\n- In **Tuscany** it is called *fettunta* and it is usually served without toppings, especially in November, to taste the very first oil of the season.\n- The chinese translation of 'Bruschetta' is '大蒜麵包' (Google Translator)",
12
+ "ingredients": [
13
+ {"name": "Ripened, chopped, medium sized tomatoes ", "amount": "6"},
14
+ {"name": "medium sized red (Spanish) onion", "amount": "1"},
15
+ {"name": "finely chopped cloves of garlic", "amount": "3 or 4"},
16
+ {"name": "fresh basil leaves finely chopped", "amount": "5 or 6"},
17
+ {"name": "a lemon's juice", "amount": "half"},
18
+ {"name": "of dried Oregano", "amount": "a small dash"},
19
+ {"name": "of balsamic vinegar", "amount": "a small dash"},
20
+ {"name": "olive oil, sea salt and cracked pepper", "amount": "to taste;"},
21
+ {"name": "grated cheese of your choice (romano/parmigiano/mozzarella)", "amount": "some"},
22
+ {"name": "baguette", "amount": "one"}
23
+ ]
24
+ }
Binary file
Binary file
@@ -0,0 +1,103 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "test_helper"
3
+
4
+ class RedcarpetRenderWordMLTest < Sablon::TestCase
5
+ def setup
6
+ @redcarpet = ::Redcarpet::Markdown.new(Sablon::Redcarpet::Render::WordML)
7
+ end
8
+
9
+ def test_normal_text
10
+ word_ml = <<-XML.gsub("\n", "")
11
+ <w:p>
12
+ <w:r><w:t xml:space=\"preserve\">normal</w:t></w:r>
13
+ </w:p>
14
+ XML
15
+ assert_equal word_ml, @redcarpet.render("normal")
16
+ end
17
+
18
+ def test_empty_string
19
+ assert_equal "", @redcarpet.render("")
20
+ end
21
+
22
+ def test_blank_string_with_newline
23
+ assert_equal "", @redcarpet.render("\n")
24
+ end
25
+
26
+ def test_newline_in_a_paragraph_starts_new_paragraph
27
+ word_ml = <<-XML.gsub("\n", "")
28
+ <w:p>
29
+ <w:r><w:t xml:space=\"preserve\">some </w:t></w:r>
30
+ </w:p>
31
+ <w:p>
32
+ <w:r><w:t xml:space=\"preserve\">text</w:t></w:r>
33
+ </w:p>
34
+ XML
35
+ assert_equal word_ml, @redcarpet.render("some \ntext")
36
+ end
37
+
38
+ def test_bold_text
39
+ word_ml = <<-XML.gsub("\n", "")
40
+ <w:p>
41
+ <w:r>
42
+ <w:rPr><w:b /></w:rPr>
43
+ <w:t xml:space="preserve">bold</w:t>
44
+ </w:r>
45
+ </w:p>
46
+ XML
47
+ assert_equal word_ml, @redcarpet.render("**bold**")
48
+ end
49
+
50
+ def test_italic_text
51
+ word_ml = <<-XML.gsub("\n", "")
52
+ <w:p>
53
+ <w:r>
54
+ <w:rPr><w:i /></w:rPr>
55
+ <w:t xml:space="preserve">italic</w:t>
56
+ </w:r>
57
+ </w:p>
58
+ XML
59
+ assert_equal word_ml, @redcarpet.render("*italic*")
60
+ end
61
+
62
+ def test_single_line_mixed_text
63
+ word_ml = <<-XML.gsub("\n", "")
64
+ <w:p>
65
+
66
+ <w:r><w:t xml:space="preserve">some </w:t></w:r>
67
+
68
+ <w:r>
69
+ <w:rPr><w:i /></w:rPr>
70
+ <w:t xml:space="preserve">random</w:t>
71
+ </w:r>
72
+
73
+ <w:r><w:t xml:space="preserve"> </w:t></w:r>
74
+ <w:r>
75
+ <w:rPr><w:b /></w:rPr>
76
+ <w:t xml:space="preserve">text</w:t>
77
+ </w:r>
78
+ </w:p>
79
+ XML
80
+ assert_equal word_ml, @redcarpet.render("some *random* **text**")
81
+ end
82
+
83
+ def test_unordered_lists
84
+ word_ml = <<-XML.gsub("\n", "")
85
+ <w:p>
86
+ <w:pPr><w:pStyle w:val="ListBullet" /></w:pPr>
87
+ <w:r><w:t xml:space="preserve">first</w:t></w:r>
88
+ </w:p>
89
+
90
+ <w:p>
91
+ <w:pPr><w:pStyle w:val="ListBullet" /></w:pPr>
92
+ <w:r><w:t xml:space="preserve">second</w:t></w:r>
93
+ </w:p>
94
+
95
+ <w:p>
96
+ <w:pPr><w:pStyle w:val="ListBullet" /></w:pPr>
97
+ <w:r><w:t xml:space="preserve">third</w:t></w:r>
98
+ </w:p>
99
+ XML
100
+
101
+ assert_equal word_ml, @redcarpet.render("- first\n- second\n- third")
102
+ end
103
+ end
data/test/sablon_test.rb CHANGED
@@ -9,34 +9,78 @@ class SablonTest < Sablon::TestCase
9
9
  def setup
10
10
  super
11
11
  @base_path = Pathname.new(File.expand_path("../", __FILE__))
12
- @output_path = @base_path + "sandbox/sablon.docx"
12
+ @template_path = @base_path + "fixtures/cv_template.docx"
13
+ @output_path = @base_path + "sandbox/cv.docx"
14
+ @sample_path = @base_path + "fixtures/cv_sample.docx"
13
15
  end
14
16
 
15
17
  def test_generate_document_from_template
16
- template = Sablon.template(@base_path + "fixtures/sablon_template.docx")
17
- person = OpenStruct.new "first_name" => "Ronald", "last_name" => "Anderson", "address" => {"street" => "Panda Bay 4A"}
18
- item = Struct.new(:index, :label, :rating)
19
- position = Struct.new(:duration, :label, :description)
18
+ template = Sablon.template @template_path
19
+
20
+ skill = Struct.new(:index, :label, :rating)
21
+ position = Struct.new(:when, :where, :tasks, :description)
20
22
  language = Struct.new(:name, :skill)
23
+ education = Struct.new(:when, :where, :what)
24
+ referee = Struct.new(:name, :company, :position, :phone)
25
+
21
26
  context = {
22
27
  current_time: Time.now.strftime("%d.%m.%Y %H:%M"),
23
- author: "Yves Senn",
24
- title: "Letter of application",
25
- person: person,
26
- about_me: Sablon.content(:word_ml, snippet("about_me_snippet").strip),
27
- items: [item.new("1.", "Ruby", "★" * 5), item.new("2.", "Java", "★" * 1), item.new("3.", "Python", "★" * 3)],
28
- career: [position.new("1999 - 2006", "Junior Java Engineer", "Lorem ipsum dolor\nsit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."),
29
- position.new("2006 - 2013", "Senior Ruby Developer", "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo."),
30
- position.new("2013 - today", "Sales...", nil)],
31
- technologies: ["HTML", "CSS", "SASS", "LESS", "JavaScript"],
32
- languages: [language.new("German", "native speaker"), language.new("English", "fluent")],
33
- training: "At vero eos et accusam et justo duo dolores et ea rebum.\n\nStet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
28
+ metadata: { generator: "Sablon" },
29
+ title: "Resume",
30
+ person: OpenStruct.new("first_name" => "Ronald", "last_name" => "Anderson",
31
+ "phone" => "630-384-2975",
32
+ "email" => "ron.anderson@gmail.com",
33
+ "address" => {
34
+ "street" => "1009 Fraggle Drive",
35
+ "municipality" => "Wheaton",
36
+ "province_zip" => "IL 60187"}),
37
+ skills: [skill.new("1.", "Java", "" * 5),
38
+ skill.new("2.", "Ruby", "★" * 3),
39
+ skill.new("3.", "Python", "★" * 1),
40
+ skill.new("4.", "XML, XSLT, JSP"),
41
+ skill.new("5.", "automated testing", "★" * 3),
42
+ ],
43
+ education: [
44
+ education.new("2005 – 2008", "Birmingham University", "Degree: BSc Hons Computer Science. 2:1 Attained."),
45
+ education.new("2003 – 2005", "Yale Sixth Form College, Bristol.", "3 A Levels - Mathematics (A), Science (A), History (B)"),
46
+ education.new("1997 – 2003", "Berry High School, Bristol.", "11 GCSE’s – 5 As, 5 Bs, 1 C")
47
+ ],
48
+ certifications: [],
49
+ career: [position.new("February 2013 - Present", "Apps Limited", [],
50
+ "Ruby on Rails Web Developer for this retail merchandising company."),
51
+ position.new("June 2010 - December 2012", "Digital Design Limited",
52
+ ["Ongoing ASP.NET website development using C#.",
53
+ "Developed CRM web application using SQL Server 2008.",
54
+ "SQL Server Reporting.",
55
+ "Helped junior developers gain understanding of C# and .NET framework and apply this accordingly."],
56
+ "Software Engineer for this financial services provider."),
57
+ position.new("June 2008 - June 2010", "Development Consultancy Limited",
58
+ ["Development of new features and testing of functionality.",
59
+ "Assisted in development and documentation of several ASP.NET based applications.",
60
+ "Web application maintenance.",
61
+ "Ensured development was signed off prior to unit testing.",
62
+ "Liaised with various service providers."])
63
+ ],
64
+ languages: [language.new("English", "native speaker"),
65
+ language.new("German", "fluent"),
66
+ language.new("French", "basics"),
67
+ ],
68
+ about_me: Sablon.content(:markdown, "I am fond of writing *short stories* and *poems* in my spare time, and have won several literary contests in pursuit of my **passion**."),
69
+ activities: ["Writing", "Photography", "Traveling"],
70
+ referees: [
71
+ referee.new("Mary P. Larsen", "Strongbod",
72
+ "Organizational development consultant", "509-471-9365"),
73
+ referee.new("Jeanne P. Eldridge", "Widdmann",
74
+ "Information designer", "530-376-1628")
75
+ ]
34
76
  }
77
+
35
78
  properties = {
36
79
  start_page_number: 7
37
80
  }
81
+
38
82
  template.render_to_file @output_path, context, properties
39
83
 
40
- assert_docx_equal @base_path + "fixtures/sablon_sample.docx", @output_path
84
+ assert_docx_equal @sample_path, @output_path
41
85
  end
42
86
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sablon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yves Senn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-13 00:00:00.000000000 Z
11
+ date: 2015-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: redcarpet
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -119,23 +133,25 @@ files:
119
133
  - lib/sablon/parser/mail_merge.rb
120
134
  - lib/sablon/processor.rb
121
135
  - lib/sablon/processor/section_properties.rb
136
+ - lib/sablon/redcarpet/render/word_ml.rb
122
137
  - lib/sablon/template.rb
123
138
  - lib/sablon/test.rb
124
139
  - lib/sablon/test/assertions.rb
125
140
  - lib/sablon/version.rb
126
- - misc/output.png
127
- - misc/template.png
141
+ - misc/cv_sample.png
142
+ - misc/cv_template.png
143
+ - misc/recipe_sample.png
144
+ - misc/recipe_template.png
128
145
  - sablon.gemspec
129
146
  - test/content_test.rb
130
147
  - test/context_test.rb
131
148
  - test/executable_test.rb
132
149
  - test/expression_test.rb
133
- - test/fixtures/sablon_sample.docx
134
- - test/fixtures/sablon_template.docx
135
- - test/fixtures/shopping_list_context.json
136
- - test/fixtures/shopping_list_sample.docx
137
- - test/fixtures/shopping_list_template.docx
138
- - test/fixtures/xml/about_me_snippet.xml
150
+ - test/fixtures/cv_sample.docx
151
+ - test/fixtures/cv_template.docx
152
+ - test/fixtures/recipe_context.json
153
+ - test/fixtures/recipe_sample.docx
154
+ - test/fixtures/recipe_template.docx
139
155
  - test/fixtures/xml/complex_field.xml
140
156
  - test/fixtures/xml/conditional.xml
141
157
  - test/fixtures/xml/conditional_with_predicate.xml
@@ -151,6 +167,7 @@ files:
151
167
  - test/fixtures/xml/table_row_loop.xml
152
168
  - test/mail_merge_parser_test.rb
153
169
  - test/processor_test.rb
170
+ - test/redcarpet_render_word_ml_test.rb
154
171
  - test/sablon_test.rb
155
172
  - test/sandbox/.gitkeep
156
173
  - test/section_properties_test.rb
@@ -186,12 +203,11 @@ test_files:
186
203
  - test/context_test.rb
187
204
  - test/executable_test.rb
188
205
  - test/expression_test.rb
189
- - test/fixtures/sablon_sample.docx
190
- - test/fixtures/sablon_template.docx
191
- - test/fixtures/shopping_list_context.json
192
- - test/fixtures/shopping_list_sample.docx
193
- - test/fixtures/shopping_list_template.docx
194
- - test/fixtures/xml/about_me_snippet.xml
206
+ - test/fixtures/cv_sample.docx
207
+ - test/fixtures/cv_template.docx
208
+ - test/fixtures/recipe_context.json
209
+ - test/fixtures/recipe_sample.docx
210
+ - test/fixtures/recipe_template.docx
195
211
  - test/fixtures/xml/complex_field.xml
196
212
  - test/fixtures/xml/conditional.xml
197
213
  - test/fixtures/xml/conditional_with_predicate.xml
@@ -207,6 +223,7 @@ test_files:
207
223
  - test/fixtures/xml/table_row_loop.xml
208
224
  - test/mail_merge_parser_test.rb
209
225
  - test/processor_test.rb
226
+ - test/redcarpet_render_word_ml_test.rb
210
227
  - test/sablon_test.rb
211
228
  - test/sandbox/.gitkeep
212
229
  - test/section_properties_test.rb
data/misc/output.png DELETED
Binary file
data/misc/template.png DELETED
Binary file
Binary file
Binary file
@@ -1,15 +0,0 @@
1
- {
2
- "title": "Shopping List",
3
- "details": {
4
- "author": {
5
- "first_name": "John",
6
- "last_name": "Doe"
7
- },
8
- "word_ml:description": "<w:p><w:r><w:t xml:space=\"preserve\">A list of items to buy at the next </w:t></w:r><w:r><w:rPr><w:b /></w:rPr><w:t>Shop</w:t></w:r><w:r><w:t xml:space=\"preserve\">.</w:t></w:r></w:p>"
9
- },
10
- "items": [
11
- {"name": "Milk", "amount": "1L"},
12
- {"name": "Sugar", "amount": "1kg"},
13
- {"name": "Tomatoes", "amount": "500g"}
14
- ]
15
- }
@@ -1 +0,0 @@
1
- <w:p><w:r><w:t xml:space="preserve">I </w:t></w:r><w:r><w:rPr><w:i /></w:rPr><w:t>am</w:t></w:r><w:r><w:t xml:space="preserve"> </w:t></w:r></w:p><w:p><w:r><w:t xml:space="preserve">a </w:t></w:r><w:r><w:rPr><w:b /></w:rPr><w:t>Software Developer</w:t></w:r></w:p>