sablon 0.0.19 → 0.0.20

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: e1c2c9b769fd159749fb61b9b78230df84538365
4
- data.tar.gz: 579139d21b1b06e6dd7ee1dca688b766269fd932
3
+ metadata.gz: 698e85a00ad9dace7dd51e7cf8887d59612edf60
4
+ data.tar.gz: 06fefc2d6ae9d747ca0d5cad4aca1cef80036cbd
5
5
  SHA512:
6
- metadata.gz: ab4593d0368b40eb82a3daa381d0121ca2b8e339a9e195980ef8afc6f75f063ad88f2f7753e8075107c13d67ca831436bd849e5e7ccb118d690659a6d3129908
7
- data.tar.gz: f419b97772e4572e5b567eb649eef3471a78b1fcede8e50962142988ab603c3bc428e2503b32f29e2676a22d1a2c37a49315e79d4115cada442248754686eab6
6
+ metadata.gz: f86083620b300bd83e48721ba92cd9909556692bec0362990997c8f1f9c7b78155929628a104995ba8c586e90afce5c8505eedeb3cc84ac6e23c347afae02c09
7
+ data.tar.gz: 4c2320a98d95071d4ea0ee3d9ec88f3cd7ba93f6618b016c3a97eb94339d7850561bf51bba5e1821b0d2f93d06123de06f41d1a35e381f240875416e46f47c05
@@ -1,21 +1,21 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sablon (0.0.19)
4
+ sablon (0.0.20)
5
5
  nokogiri (>= 1.6.0)
6
- redcarpet (>= 3.2)
7
6
  rubyzip (>= 1.1)
8
7
 
9
8
  GEM
10
9
  remote: https://rubygems.org/
11
10
  specs:
12
- mini_portile2 (2.0.0)
11
+ mini_portile2 (2.1.0)
13
12
  minitest (5.8.0)
14
- nokogiri (1.6.7.1)
15
- mini_portile2 (~> 2.0.0.rc2)
13
+ nokogiri (1.6.8)
14
+ mini_portile2 (~> 2.1.0)
15
+ pkg-config (~> 1.1.7)
16
+ pkg-config (1.1.7)
16
17
  rake (10.4.2)
17
- redcarpet (3.3.3)
18
- rubyzip (1.1.7)
18
+ rubyzip (1.2.0)
19
19
  xml-simple (1.1.5)
20
20
 
21
21
  PLATFORMS
@@ -29,4 +29,4 @@ DEPENDENCIES
29
29
  xml-simple
30
30
 
31
31
  BUNDLED WITH
32
- 1.10.6
32
+ 1.12.5
data/README.md CHANGED
@@ -24,7 +24,7 @@ require "sablon"
24
24
  template = Sablon.template(File.expand_path("~/Desktop/template.docx"))
25
25
  context = {
26
26
  title: "Fabulous Document",
27
- technologies: ["Ruby", "Markdown", "ODF"]
27
+ technologies: ["Ruby", "HTML", "ODF"]
28
28
  }
29
29
  template.render_to_file File.expand_path("~/Desktop/output.docx"), context
30
30
  ```
@@ -100,54 +100,6 @@ IMPORTANT: This feature is very much *experimental*. Currently, the insertion
100
100
  will replace the containing paragraph. This means that other content in the same
101
101
  paragraph is discarded.
102
102
 
103
- ##### Markdown [deprecated]
104
-
105
- IMPORTANT: Markdown insertion has been deprecated in favor of HTML
106
- insertion. For now the behavior is still packaged with sablon. Note that the
107
- implementation of `Sablon::Content::Markdown` is already based on
108
- `Sablon::Content::HTML`. Markdown insertion will be removed in the future.
109
-
110
- Similar to WordProcessingML it's possible to use markdown while processing the
111
- tempalte. You don't need to modify your templates, a simple insertion operation
112
- is sufficient:
113
-
114
- ```
115
- «=article.body»
116
- ```
117
-
118
- To use Markdown insertion prepare the context like so:
119
-
120
- ```ruby
121
- markdown_body = <<-MD
122
- This text can contain *additional formatting*
123
- according to the **Markdown** specification.
124
- MD
125
- context = {
126
- article: { body: Sablon.content(:markdown, markdown_body) }
127
- }
128
- template.render_to_file File.expand_path("~/Desktop/output.docx"), context
129
- ```
130
-
131
- Markdown insertion has built-in support for:
132
-
133
- * [Headers](http://spec.commonmark.org/0.17/#atx-header)
134
- * [Paragraphs](http://spec.commonmark.org/0.17/#paragraphs)
135
- * [Emphasis and strong emphasis](http://spec.commonmark.org/0.17/#emphasis-and-strong-emphasis)
136
- * [Hard line breaks](http://spec.commonmark.org/0.17/#hard-line-breaks)
137
- * [Lists](http://spec.commonmark.org/0.17/#lists)
138
-
139
- For headings and lists to function properly it is necessary that the template
140
- defines specific styles. Headings use styles called `Heading1`, `Heading2`,
141
- etc. according to the header level. Ordered lists will use the style
142
- `ListNumber` and unordered lists use `ListBullet`. Nested lists are not
143
- supported. Normal text paragraphs use the style `Paragraph`. It's not necessary
144
- to have that style in the template. Word will fall back to using the `Normal` style.
145
-
146
- IMPORTANT: This feature is very much *experimental*. Currently, the insertion
147
- will replace the containing paragraph. This means that other content in the same
148
- paragraph is discarded. In the near future this feature will most likely be
149
- implemented on top of HTML insertion.
150
-
151
103
  ##### HTML [experimental]
152
104
 
153
105
  Similar to WordProcessingML it's possible to use html as input while processing the
@@ -14,8 +14,6 @@ require "sablon/operations"
14
14
  require "sablon/html/converter"
15
15
  require "sablon/content"
16
16
 
17
- require 'redcarpet'
18
-
19
17
  module Sablon
20
18
  class TemplateError < ArgumentError; end
21
19
  class ContextError < ArgumentError; end
@@ -77,23 +77,6 @@ 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
- warn "[DEPRECATION] `Sablon::Content::Markdown` is deprecated. Please use `Sablon::Content::HTML` instead."
87
- redcarpet = ::Redcarpet::Markdown.new(::Redcarpet::Render::HTML.new)
88
- word_ml = Sablon.content(:html, redcarpet.render(markdown))
89
- super word_ml
90
- end
91
-
92
- def append_to(*args)
93
- word_ml.append_to(*args)
94
- end
95
- end
96
-
97
80
  class HTML < Struct.new(:word_ml)
98
81
  include Sablon::Content
99
82
  def self.id; :html end
@@ -112,7 +95,6 @@ module Sablon
112
95
 
113
96
  register Sablon::Content::String
114
97
  register Sablon::Content::WordML
115
- register Sablon::Content::Markdown
116
98
  register Sablon::Content::HTML
117
99
  end
118
100
  end
@@ -73,6 +73,7 @@ module Sablon
73
73
  end
74
74
 
75
75
  def replace(content)
76
+ remove_extra_runs!
76
77
  replace_field_display(@node, content)
77
78
  @node.replace(@node.children)
78
79
  end
@@ -89,6 +90,11 @@ module Sablon
89
90
  @node
90
91
  end
91
92
  alias_method :end_node, :start_node
93
+
94
+ private
95
+ def remove_extra_runs!
96
+ @node.search(".//w:r")[1..-1].each(&:remove)
97
+ end
92
98
  end
93
99
 
94
100
  def parse_fields(xml)
@@ -1,3 +1,3 @@
1
1
  module Sablon
2
- VERSION = "0.0.19"
2
+ VERSION = "0.0.20"
3
3
  end
@@ -21,7 +21,6 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_runtime_dependency 'nokogiri', ">= 1.6.0"
23
23
  spec.add_runtime_dependency 'rubyzip', ">= 1.1"
24
- spec.add_runtime_dependency 'redcarpet', ">= 3.2"
25
24
 
26
25
  spec.add_development_dependency "bundler", ">= 1.6"
27
26
  spec.add_development_dependency "rake", "~> 10.0"
@@ -158,47 +158,3 @@ 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_is_deprecated
167
- previous_stderr, $stderr = $stderr, StringIO.new
168
- Sablon.content(:markdown, "")
169
- assert_equal "[DEPRECATION] `Sablon::Content::Markdown` is deprecated. Please use `Sablon::Content::HTML` instead.\n", $stderr.string
170
- ensure
171
- $stderr = previous_stderr
172
- end
173
-
174
- def test_blank_markdown
175
- Sablon.content(:markdown, "").append_to @paragraph, @node
176
-
177
- assert_xml_equal "<w:p>AFTER</w:p>", @document
178
- end
179
-
180
- def test_inserts_markdown
181
- Sablon.content(:markdown, "yay **bold** text").append_to @paragraph, @node
182
-
183
- output = <<-XML.strip.gsub("\n", "")
184
- <w:p>
185
- <w:pPr><w:pStyle w:val=\"Paragraph\"/></w:pPr>
186
- <w:r><w:t xml:space=\"preserve\">yay </w:t></w:r>
187
- <w:r>
188
- <w:rPr><w:b/></w:rPr>
189
- <w:t xml:space=\"preserve\">bold</w:t>
190
- </w:r>
191
- <w:r>
192
- <w:t xml:space=\"preserve\"> text</w:t>
193
- </w:r>
194
- </w:p>
195
- <w:p>AFTER</w:p>
196
- XML
197
-
198
- assert_xml_equal output, @document
199
- end
200
-
201
- def test_inserting_markdown_multiple_times_into_same_paragraph
202
- skip "Content::Markdown currently removes the paragraph..."
203
- end
204
- end
@@ -13,14 +13,14 @@ class ContextTest < Sablon::TestCase
13
13
  "otherkey"=>"<nope>"}, transformed)
14
14
  end
15
15
 
16
- def test_recognizes_markdown_keys
17
- transformed = Sablon::Context.transform({"markdown:mykey" => "**yay**", "otherkey" => "<nope>"})
18
- assert_equal({ "mykey"=>Sablon.content(:markdown, "**yay**"),
16
+ def test_recognizes_html_keys
17
+ transformed = Sablon::Context.transform({"html:mykey" => "**yay**", "otherkey" => "<nope>"})
18
+ assert_equal({ "mykey"=>Sablon.content(:html, "**yay**"),
19
19
  "otherkey"=>"<nope>"}, transformed)
20
20
  end
21
21
 
22
- def test_does_not_wrap_markdown_and_wordml_with_nil_value
23
- transformed = Sablon::Context.transform({"markdown:mykey" => nil, "word_ml:otherkey" => nil, "normalkey" => nil})
22
+ def test_does_not_wrap_html_and_wordml_with_nil_value
23
+ transformed = Sablon::Context.transform({"html:mykey" => nil, "word_ml:otherkey" => nil, "normalkey" => nil})
24
24
  assert_equal({ "mykey" => nil,
25
25
  "otherkey" => nil,
26
26
  "normalkey" => nil}, transformed)
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "title": "Bruschetta",
15
15
  "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>",
16
- "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*\n\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.\n\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.\n\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, \nespecially in November, to taste the very first oil of the season.\n- The chinese translation of 'Bruschetta' is '大蒜麵包' (Google Translator)",
16
+ "html:preparation": "<h2>How to make Baby's Bruschetta</h2>\n<h3>Preparation</h3><p>Make 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 <i>tomatoes</i> and <i>garlic</i></p><p>I find it works best to slice the <i>baguette</i> 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 <i>baguette</i>, then place into the oven.</p><p>Once 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 <i>cheese</i> melted you can skip this step and just toast the bread fully, add the mixture and <i>cheese</i> and serve.</p><p>Once melted, remove and place directly on a serving platter and let rest for one minute while adding fresh chopped *basil* for garnish, and <strong>ENJOY!</strong></p><h3>Variations</h3><ol><li>Use fresh oregano instead of basil.</li><li>Other possible toppings: prosciutto, salami, bean spreads</li></ol><h3>Notes</h3><ul><li>In <b>Italy</b>, bruschetta is often prepared using a brustolina grill. In the Abruzzo region of Italy a variation of bruschetta made with a salame called <em>ventricina</em> is served.</li><li>In <strong>Tuscany</strong> it is called <em>fettunta</em> and it is usually served without toppings, especially in November, to taste the very first oil of the season.</li><li>The chinese translation of 'Bruschetta' is '大蒜麵包' (Google Translator)</li></ul>",
17
17
  "ingredients": [
18
18
  {"name": "Ripened, chopped, medium sized tomatoes ", "amount": "6"},
19
19
  {"name": "medium sized red (Spanish) onion", "amount": "1"},
@@ -0,0 +1,20 @@
1
+ <w:p>
2
+ <w:r><w:t xml:space="preserve">Generated by </w:t></w:r>
3
+ <w:fldSimple w:instr=" MERGEFIELD =system_name \* MERGEFORMAT ">
4
+ <w:r w:rsidR="002D39A9">
5
+ <w:rPr>
6
+ <w:rFonts w:hint="eastAsia"/>
7
+ <w:noProof/>
8
+ </w:rPr>
9
+ <w:t>«</w:t>
10
+ </w:r>
11
+ <w:r w:rsidR="002D39A9">
12
+ <w:rPr><w:noProof/></w:rPr>
13
+ <w:t>=system_name</w:t>
14
+ </w:r>
15
+ <w:r w:rsidR="002D39A9">
16
+ <w:rPr><w:rFonts w:hint="eastAsia"/><w:noProof/></w:rPr>
17
+ <w:t>»</w:t>
18
+ </w:r>
19
+ </w:fldSimple>
20
+ </w:p>
@@ -40,6 +40,24 @@ class ProcessorDocumentTest < Sablon::TestCase
40
40
  document
41
41
  end
42
42
 
43
+ def test_simple_field_with_styling_replacement
44
+ result = process(snippet("simple_field_with_styling"), {"system_name" => "Sablon 1 million"})
45
+
46
+ assert_equal "Generated by Sablon 1 million", text(result)
47
+ assert_xml_equal <<-document, result
48
+ <w:p>
49
+ <w:r><w:t xml:space="preserve">Generated by </w:t></w:r>
50
+ <w:r w:rsidR="002D39A9">
51
+ <w:rPr>
52
+ <w:rFonts w:hint="eastAsia"/>
53
+ <w:noProof/>
54
+ </w:rPr>
55
+ <w:t>Sablon 1 million</w:t>
56
+ </w:r>
57
+ </w:p>
58
+ document
59
+ end
60
+
43
61
  def test_context_can_contain_string_and_symbol_keys
44
62
  result = process(snippet("simple_fields"), {"first_name" => "Jack", last_name: "Davis"})
45
63
  assert_equal "Jack Davis", text(result)
@@ -65,7 +65,7 @@ class SablonTest < Sablon::TestCase
65
65
  language.new("German", "fluent"),
66
66
  language.new("French", "basics"),
67
67
  ],
68
- about_me: Sablon.content(:markdown, "I am fond of writing *short stories* and *poems* in my spare time, \nand have won several literary contests in pursuit of my **passion**."),
68
+ about_me: Sablon.content(:html, "I am fond of writing <i>short stories</i> and <i>poems</i> in my spare time, <br />and have won several literary contests in pursuit of my <b>passion</b>."),
69
69
  activities: ["Writing", "Photography", "Traveling"],
70
70
  referees: [
71
71
  referee.new("Mary P. Larsen", "Strongbod",
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.19
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yves Senn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-01-25 00:00:00.000000000 Z
11
+ date: 2016-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -38,20 +38,6 @@ 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'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: bundler
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -175,13 +161,13 @@ files:
175
161
  - test/fixtures/xml/paragraph_loop.xml
176
162
  - test/fixtures/xml/paragraph_loop_within_table_cell.xml
177
163
  - test/fixtures/xml/simple_field.xml
164
+ - test/fixtures/xml/simple_field_with_styling.xml
178
165
  - test/fixtures/xml/simple_fields.xml
179
166
  - test/fixtures/xml/table_multi_row_loop.xml
180
167
  - test/fixtures/xml/table_row_loop.xml
181
168
  - test/html/converter_test.rb
182
169
  - test/html_test.rb
183
170
  - test/mail_merge_parser_test.rb
184
- - test/markdown_test.rb
185
171
  - test/processor/document_test.rb
186
172
  - test/sablon_test.rb
187
173
  - test/sandbox/.gitkeep
@@ -209,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
209
195
  version: '0'
210
196
  requirements: []
211
197
  rubyforge_project:
212
- rubygems_version: 2.4.5.1
198
+ rubygems_version: 2.5.1
213
199
  signing_key:
214
200
  specification_version: 4
215
201
  summary: docx tempalte processor
@@ -242,13 +228,13 @@ test_files:
242
228
  - test/fixtures/xml/paragraph_loop.xml
243
229
  - test/fixtures/xml/paragraph_loop_within_table_cell.xml
244
230
  - test/fixtures/xml/simple_field.xml
231
+ - test/fixtures/xml/simple_field_with_styling.xml
245
232
  - test/fixtures/xml/simple_fields.xml
246
233
  - test/fixtures/xml/table_multi_row_loop.xml
247
234
  - test/fixtures/xml/table_row_loop.xml
248
235
  - test/html/converter_test.rb
249
236
  - test/html_test.rb
250
237
  - test/mail_merge_parser_test.rb
251
- - test/markdown_test.rb
252
238
  - test/processor/document_test.rb
253
239
  - test/sablon_test.rb
254
240
  - test/sandbox/.gitkeep
@@ -1,81 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require "test_helper"
3
- require "support/xml_snippets"
4
-
5
- class SablonMarkdownTest < Sablon::TestCase
6
- include Sablon::Test::Assertions
7
-
8
- def setup
9
- super
10
- @base_path = Pathname.new(File.expand_path("../", __FILE__))
11
-
12
- @sample_path = @base_path + "fixtures/markdown_sample.docx"
13
- end
14
-
15
- def test_generate_document_from_template_with_styles_and_markdown
16
- template_path = @base_path + "fixtures/insertion_template.docx"
17
- output_path = @base_path + "sandbox/markdown.docx"
18
- template = Sablon.template template_path
19
- context = {'markdown:content' => content}
20
- template.render_to_file output_path, context
21
-
22
- assert_docx_equal @sample_path, output_path
23
- end
24
-
25
- private
26
- def content
27
- <<-MARKDOWN
28
- # Sablon Markdown insertion
29
-
30
- ## Text
31
-
32
- **_Lorem ipsum_ dolor sit amet, consectetur adipiscing elit. Suspendisse at libero at elit posuere convallis ac vitae augue. Morbi pretium diam et leo pulvinar, sit amet placerat mauris scelerisque.** Vivamus sollicitudin ante ligula, non egestas diam molestie at.
33
-
34
- Nunc tincidunt massa id libero mollis bibendum.
35
- Sed vel arcu blandit, scelerisque ex ut, semper justo.
36
- Nunc tempor velit a tortor lacinia, vel mattis diam sollicitudin.
37
- Etiam eget faucibus enim.
38
-
39
- Curabitur rutrum vestibulum nisi, vel posuere ligula commodo a. Sed nibh odio, convallis vitae orci a, cursus venenatis tellus. Duis consequat auctor elementum. Quisque blandit augue id faucibus dignissim. Aenean malesuada placerat turpis. Mauris tincidunt lorem sit amet est ultricies, eu tristique arcu dapibus. Nam ultrices vulputate tellus, quis feugiat ante faucibus non. Donec lectus est, suscipit in arcu molestie, pharetra cursus massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
40
-
41
- ## Lists
42
-
43
- * Etiam vulputate elementum mi, at porta est malesuada sit amet.
44
- * Praesent porttitor arcu id justo dignissim, vitae dignissim lectus pharetra.
45
- * Curabitur efficitur mauris ac justo porta dignissim. Integer sed dui justo.
46
-
47
- Donec finibus lectus a erat pharetra dapibus.
48
-
49
- 1. Nulla facilisis aliquet ex.
50
- 1. Mauris eget ante sed purus dictum tempus eu non dolor.
51
- 1. Aliquam finibus, leo at rutrum euismod, urna quam scelerisque ante, eu finibus dolor lectus vel ipsum.
52
-
53
- Ut id condimentum ante, eget convallis justo. Quisque accumsan porta interdum. Integer sit amet luctus felis.
54
-
55
- Nunc imperdiet, massa id ultricies porttitor, felis magna tincidunt augue, a egestas orci neque sed odio.
56
-
57
- 1. Suspendisse
58
- 1. tempor
59
- 1. turpis
60
- 1. turpis
61
- 1. vitae
62
- 1. tristique
63
- 1. nulla
64
- 1. pulvinar
65
- 1. nec.
66
-
67
- * Suspendisse
68
- * potenti
69
- * In condimentum
70
- * enim ut nibh cursus imperdiet.
71
- * Aliquam
72
- * lacinia
73
- * scelerisque
74
- * tristique.
75
-
76
- Phasellus consectetur placerat ornare. Nulla facilisi. Morbi fringilla est vitae pulvinar dictum. Praesent quis malesuada ex. Pellentesque posuere facilisis molestie.
77
-
78
- Maecenas pretium erat vitae neque convallis consectetur. Cras ultricies mi nec mauris consectetur, eu blandit purus mattis. Quisque ante nulla, sagittis sed interdum non, eleifend quis augue. Curabitur vestibulum quam sed blandit rhoncus. Morbi eget vestibulum felis. Nulla vitae molestie elit. Etiam sagittis lorem elit, sit amet rhoncus eros dapibus non. Praesent nec dignissim dui. Quisque quis vehicula turpis, sit amet aliquet leo. Ut urna magna, malesuada eget fringilla ut, laoreet sed diam. Maecenas a ipsum varius, efficitur eros quis, vulputate mauris.
79
- MARKDOWN
80
- end
81
- end