govspeak 0.8.9 → 0.8.10

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/README.md ADDED
@@ -0,0 +1,164 @@
1
+ Govspeak is our markdown-derived mark-up language.
2
+
3
+ # Usage
4
+
5
+ Install the gem
6
+
7
+ gem install govspeak
8
+
9
+ or add it to your Gemfile
10
+
11
+ gem "govspeak", "~> 0.8.9"
12
+
13
+ then create a new document
14
+
15
+ require 'rubygems'
16
+ require 'govspeak'
17
+
18
+ doc = Govspeak::Document.new "^Test^"
19
+ puts doc.to_html
20
+
21
+ # Extensions
22
+
23
+ In addition to the [standard Markdown syntax](http://daringfireball.net/projects/markdown/syntax "Markdown syntax"), we have added our own extensions.
24
+
25
+ ## Callouts
26
+
27
+ ### Information callouts
28
+
29
+ ^This is an information callout^
30
+
31
+ creates a callout with an info (i) icon.
32
+
33
+ <div class="application-notice info-notice">
34
+ <p>This is an information callout</p>
35
+ </div>
36
+
37
+ ### Warning callouts
38
+
39
+ %This is a warning callout%
40
+
41
+ creates a callout with a warning or alert (!) icon
42
+
43
+ <div class="application-notice help-notice">
44
+ <p>This is a warning callout</p>
45
+ </div>
46
+
47
+ ### Example callout
48
+
49
+ $E
50
+ **Example**: Open the pod bay doors
51
+ $E
52
+
53
+ creates an example box
54
+
55
+ <div class="example">
56
+ <p><strong>Example:</strong> Open the pod bay doors</p>
57
+ </div>
58
+
59
+ ## Highlights
60
+
61
+ ### Advisory
62
+
63
+ @This is a very important message or warning@
64
+
65
+ highlights the enclosed text in yellow
66
+
67
+ <h3 class="advisory">
68
+ <span>This is a very important message or warning</span>
69
+ </h3>
70
+
71
+ ### Answer
72
+
73
+ {::highlight-answer}
74
+ The VAT rate is *20%*
75
+ {:/highlight-answer}
76
+
77
+ creates a large pink highlight box with optional preamble text and giant text denoted with `**`
78
+
79
+ <div class="highlight-answer">
80
+ <p>The standard VAT rate is <em>20%</em></p>
81
+ </div>
82
+
83
+ ## Points of Contact
84
+
85
+ ### Contact
86
+
87
+ $C
88
+ **Student Finance England**
89
+ **Telephone:** 0845 300 50 90
90
+ **Minicom:** 0845 604 44 34
91
+ $C
92
+
93
+ creates an contact box
94
+
95
+ <div class="contact">
96
+ <p><strong>Student Finance England</strong><br><strong>Telephone:</strong> 0845 300 50 90<br><strong>Minicom:</strong> 0845 604 44 34</p>
97
+ </div>
98
+
99
+ ### Address
100
+
101
+ $A
102
+ Hercules House
103
+ Hercules Road
104
+ London SE1 7DU
105
+ $A
106
+
107
+ creates an address box
108
+
109
+ <div class="address vcard"><div class="adr org fn"><p>
110
+ Hercules House
111
+ <br>Hercules Road
112
+ <br>London SE1 7DU
113
+ <br></p></div></div>
114
+
115
+ ## Downloads
116
+
117
+ $D
118
+ [An example form download link](http://example.com/ "Example form")
119
+
120
+ Something about this form download
121
+ $D
122
+
123
+ creates a file download box
124
+
125
+ <div class="form-download">
126
+ <p><a href="http://example.com/" title="Example form" rel="external">An example form download link.</a></p>
127
+ </div>
128
+
129
+ ## Steps
130
+
131
+ Steps can be created similar to an ordered list:
132
+
133
+ s1. numbers
134
+ s2. to the start
135
+ s3. of your list
136
+
137
+ Note that steps need an extra line break after the final step (ie. two full blank lines) or other markdown directly afterwards won't work. If you have a subhead after - add a line break after this.
138
+
139
+ ## Maps
140
+
141
+ Static Maps can be embedded by wrapping the URL in double parenthesis.
142
+
143
+ ((http://maps.google.co.uk/maps?q=Winkfield+Rd,+Windsor,+Berkshire+SL4+4AY&hl=en&sll=53.800651,-4.064941&sspn=17.759517,42.055664&vpsrc=0&z=14))
144
+
145
+ ## Abbreviations
146
+
147
+ Abbreviations can be defined at the end of the document, and any occurrences elswhere in the document will wrapped in an `<abbr>` tag. They are parsed in the order in which they are defined, so `PCSOs` should be defined before `PCSO`, for example.
148
+
149
+ Special rules apply if you’re exporting a vehicle outside the EU.
150
+
151
+ *[EU]:European Union
152
+
153
+ becomes
154
+
155
+ <p>Special rules apply if you’re exporting a vehicle outside the <abbr title="European Union">EU</abbr>.</p>
156
+
157
+ ## Devolved content
158
+
159
+ :england:content goes here:england:
160
+ :scotland:content goes here:scotland:
161
+ :london:content goes here:london:
162
+ :wales:content goes here:wales:
163
+ :northern-ireland:content goes here:northern-ireland:
164
+ :england-wales:content goes here:england-wales:
data/lib/govspeak.rb CHANGED
@@ -8,19 +8,26 @@ module Govspeak
8
8
 
9
9
  @@extensions = []
10
10
 
11
+ attr_accessor :images
12
+
11
13
  def self.to_html(source, options = {})
12
14
  new(source, options).to_html
13
15
  end
14
16
 
15
17
  def initialize(source, options = {})
16
- source ||= ""
17
- options[:entity_output] ||= :symbolic
18
- @doc = Kramdown::Document.new(preprocess(source), options)
18
+ @source = source ? source.dup : ""
19
+ @options = options.merge(entity_output: :symbolic)
20
+ @images = []
19
21
  super()
20
22
  end
21
23
 
24
+ def kramdown_doc
25
+ @kramdown_doc ||= Kramdown::Document.new(preprocess(@source), @options)
26
+ end
27
+ private :kramdown_doc
28
+
22
29
  def to_html
23
- @doc.to_html
30
+ kramdown_doc.to_html
24
31
  end
25
32
 
26
33
  def to_text
@@ -28,17 +35,22 @@ module Govspeak
28
35
  end
29
36
 
30
37
  def headers
31
- Govspeak::HeaderExtractor.convert(@doc).first
38
+ Govspeak::HeaderExtractor.convert(kramdown_doc).first
32
39
  end
33
40
 
34
41
  def preprocess(source)
35
42
  @@extensions.each do |title,regexp,block|
36
43
  source.gsub!(regexp) {|match|
37
- block.call($1)
44
+ instance_exec($1, &block)
38
45
  }
39
46
  end
40
47
  source
41
48
  end
49
+
50
+ def encode(text)
51
+ HTMLEntities.new.encode(text)
52
+ end
53
+ private :encode
42
54
 
43
55
  def self.extension(title, regexp = nil, &block)
44
56
  regexp ||= %r${::#{title}}(.*?){:/#{title}}$m
@@ -62,7 +74,7 @@ module Govspeak
62
74
  }
63
75
  end
64
76
 
65
- def self.insert_strong_inside_p(body, parser=Kramdown::Document)
77
+ def insert_strong_inside_p(body, parser=Kramdown::Document)
66
78
  parser.new(body.strip).to_html.sub(/^<p>(.*)<\/p>$/,"<p><strong>\\1</strong></p>")
67
79
  end
68
80
 
@@ -95,6 +107,25 @@ module Govspeak
95
107
  extension('map_link', surrounded_by("((", "))")) { |body|
96
108
  %{<div class="map"><iframe width="200" height="200" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="#{body.strip}&output=embed"></iframe><br /><small><a href="#{body.strip}">View Larger Map</a></small></div>}
97
109
  }
110
+
111
+ extension('attached-image', /^!!([0-9]+)/) do |image_number|
112
+ image = images[image_number.to_i - 1]
113
+ if image
114
+ caption = image.caption rescue nil
115
+ render_image(image.url, image.alt_text, caption)
116
+ else
117
+ ""
118
+ end
119
+ end
120
+
121
+ def render_image(url, alt_text, caption = nil)
122
+ lines = []
123
+ lines << '<figure class="image embedded">'
124
+ lines << %Q{ <div class="img"><img alt="#{encode(alt_text)}" src="#{encode(url)}" /></div>}
125
+ lines << %Q{ <figcaption>#{encode(caption.strip)}</figcaption>} if caption && !caption.strip.empty?
126
+ lines << '</figure>'
127
+ lines.join "\n"
128
+ end
98
129
 
99
130
  wrap_with_div('summary', '$!')
100
131
  wrap_with_div('form-download', '$D')
@@ -125,13 +156,13 @@ module Govspeak
125
156
  'london' => 'London' }
126
157
  end
127
158
 
128
- devolved_options.each do |k,v|
129
- extension("devolved-#{k}",/:#{k}:(.*?):#{k}:/m) do |body|
159
+ devolved_options.each do |k,v|
160
+ extension("devolved-#{k}",/:#{k}:(.*?):#{k}:/m) do |body|
130
161
  %{<div class="devolved-content #{k}">
131
162
  <p class="devolved-header">This section applies to #{v}</p>
132
163
  <div class="devolved-body">#{Kramdown::Document.new(body.strip).to_html}</div>
133
164
  </div>\n}
134
- end
135
- end
165
+ end
166
+ end
136
167
  end
137
168
  end
@@ -0,0 +1,3 @@
1
+ module Govspeak
2
+ VERSION = "0.8.10"
3
+ end
@@ -7,9 +7,11 @@ SimpleCov.start
7
7
  SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
8
8
 
9
9
  require 'test_helper'
10
+ require 'govspeak_test_helper'
10
11
 
11
12
  class GovspeakTest < Test::Unit::TestCase
12
-
13
+ include GovspeakTestHelper
14
+
13
15
  test "simple smoke-test" do
14
16
  rendered = Govspeak::Document.new("*this is markdown*").to_html
15
17
  assert_equal "<p><em>this is markdown</em></p>\n", rendered
@@ -69,183 +71,270 @@ Teston
69
71
  assert_equal %{<div class="address vcard"><div class="adr org fn"><p>\n123 Test Street<br />Testcase Cliffs<br />Teston<br />0123 456 7890 \n</p></div></div>\n}, doc.to_html
70
72
  end
71
73
 
72
- test "govspark extensions" do
73
- markdown_regression_tests = [
74
- {
75
- input: "^ I am very informational ^",
76
- output: %{<div class="application-notice info-notice">
77
- <p>I am very informational</p>
78
- </div>},
79
- text: "I am very informational"
80
- }, {
81
- input: "The following is very informational\n^ I am very informational ^",
82
- output: %{<p>The following is very informational</p>
83
-
84
- <div class="application-notice info-notice">
85
- <p>I am very informational</p>
86
- </div>},
87
- text: "The following is very informational I am very informational"
88
- }, {
89
- input: "^ I am very informational",
90
- output: %{<div class="application-notice info-notice">
91
- <p>I am very informational</p>
92
- </div>},
93
- text: "I am very informational"
94
- }, {
95
- input: "@ I am very important @",
96
- output: %{<div class="advisory"><p><strong>I am very important</strong></p>
97
- </div>},
98
- text: "I am very important"
99
- }, {
100
- input: "The following is very important
101
- @ I am very important @",
102
- output: %{<p>The following is very important</p>
103
-
104
- <div class="advisory"><p><strong>I am very important</strong></p>
105
- </div>},
106
- text: "The following is very important I am very important"
107
- }, {
108
- input: "% I am very helpful %",
109
- output: %{<div class="application-notice help-notice">
110
- <p>I am very helpful</p>
111
- </div>},
112
- text: "I am very helpful"
113
- }, {
114
- input: "The following is very helpful\n% I am very helpful %",
115
- output: %{<p>The following is very helpful</p>
116
-
117
- <div class="application-notice help-notice">
118
- <p>I am very helpful</p>
119
- </div>},
120
- text: "The following is very helpful I am very helpful"
121
- }, {
122
- input: "## Hello ##\n\n% I am very helpful %\r\n### Young Workers ###\n\n",
123
- output: %{<h2 id="hello">Hello</h2>
124
-
125
- <div class="application-notice help-notice">
126
- <p>I am very helpful</p>
127
- </div>
128
-
129
- <h3 id="young-workers">Young Workers</h3>},
130
- text: "Hello I am very helpful Young Workers"
131
- }, {
132
- input: "% I am very helpful",
133
- output: %{<div class="application-notice help-notice">
134
- <p>I am very helpful</p>
135
- </div>},
136
- text: "I am very helpful"
137
- }, {
138
- input: "This is a [link](http://www.google.com) isn't it?",
139
- output: '<p>This is a <a href="http://www.google.com">link</a> isn&rsquo;t it?</p>',
140
- text: "This is a link isn’t it?"
141
- }, {
142
- input: "This is a [link with an at sign in it](http://www.google.com/@dg/@this) isn't it?",
143
- output: '<p>This is a <a href="http://www.google.com/@dg/@this">link with an at sign in it</a> isn&rsquo;t it?</p>',
144
- text: "This is a link with an at sign in it isn’t it?"
145
- }, {
146
- input: "HTML
147
-
148
- *[HTML]: Hyper Text Markup Language",
149
- output: %{<p><abbr title="Hyper Text Markup Language">HTML</abbr></p>},
150
- text: "HTML"
151
- }, {
152
- input: "x[a link](http://rubyforge.org)x",
153
- output: '<p><a href="http://rubyforge.org" rel="external">a link</a></p>',
154
- text: "a link"
155
- }, {
156
- input: "$!
157
- rainbow
158
- $!",
159
- output: %{<div class="summary">
160
- <p>rainbow</p>
161
- </div>},
162
- text: "rainbow"
163
- }, {
164
- input: "$C help, send cake $C",
165
- output: %{<div class="contact">
166
- <p>help, send cake</p>
167
- </div>},
168
- text: "help, send cake"
169
- }, {
170
- input: "$A
171
- street
172
- road
173
- $A",
174
- output: %{<div class="address vcard"><div class="adr org fn"><p>
175
- street<br />road<br />
176
- </p></div></div>},
177
- text: "street road"
178
- }, {
179
- input: "$P
180
- $I
181
- help
182
- $I
183
- $P",
184
- output: %{<div class="place">\n<div class="information">\n<p>help</p>\n</div>\n</div>},
185
- text: "help"
186
- }, {
187
- input: "$D
188
- can you tell me how to get to...
189
- $D",
190
- output: %{<div class="form-download">
191
- <p>can you tell me how to get to…</p>
192
- </div>},
193
- text: "can you tell me how to get to…"
194
- }, {
195
- input: "1. rod
196
- 2. jane
197
- 3. freddy",
198
- output: "<ol>\n <li>rod</li>\n <li>jane</li>\n <li>freddy</li>\n</ol>",
199
- text: "rod jane freddy"
200
- }, {
201
- input: "
74
+ test_given_govspeak("^ I am very informational ^") do
75
+ assert_html_output %{
76
+ <div class="application-notice info-notice">
77
+ <p>I am very informational</p>
78
+ </div>}
79
+ assert_text_output "I am very informational"
80
+ end
81
+
82
+ test "processing an extension does not modify the provided input" do
83
+ input = "^ I am very informational"
84
+ Govspeak::Document.new(input).to_html
85
+ assert_equal "^ I am very informational", input
86
+ end
87
+
88
+ test_given_govspeak "The following is very informational\n^ I am very informational ^" do
89
+ assert_html_output %{
90
+ <p>The following is very informational</p>
91
+
92
+ <div class="application-notice info-notice">
93
+ <p>I am very informational</p>
94
+ </div>}
95
+ assert_text_output "The following is very informational I am very informational"
96
+ end
97
+
98
+ test_given_govspeak "^ I am very informational" do
99
+ assert_html_output %{
100
+ <div class="application-notice info-notice">
101
+ <p>I am very informational</p>
102
+ </div>}
103
+ assert_text_output "I am very informational"
104
+ end
105
+
106
+ test_given_govspeak "@ I am very important @" do
107
+ assert_html_output %{
108
+ <div class="advisory"><p><strong>I am very important</strong></p>
109
+ </div>}
110
+ assert_text_output "I am very important"
111
+ end
112
+
113
+ test_given_govspeak "
114
+ The following is very important
115
+ @ I am very important @
116
+ " do
117
+ assert_html_output %{
118
+ <p>The following is very important</p>
119
+
120
+ <div class="advisory"><p><strong>I am very important</strong></p>
121
+ </div>}
122
+ assert_text_output "The following is very important I am very important"
123
+ end
124
+
125
+ test_given_govspeak "% I am very helpful %" do
126
+ assert_html_output %{
127
+ <div class="application-notice help-notice">
128
+ <p>I am very helpful</p>
129
+ </div>}
130
+ assert_text_output "I am very helpful"
131
+ end
132
+
133
+ test_given_govspeak "The following is very helpful\n% I am very helpful %" do
134
+ assert_html_output %{
135
+ <p>The following is very helpful</p>
136
+
137
+ <div class="application-notice help-notice">
138
+ <p>I am very helpful</p>
139
+ </div>}
140
+ assert_text_output "The following is very helpful I am very helpful"
141
+ end
142
+
143
+ test_given_govspeak "## Hello ##\n\n% I am very helpful %\r\n### Young Workers ###\n\n" do
144
+ assert_html_output %{
145
+ <h2 id="hello">Hello</h2>
146
+
147
+ <div class="application-notice help-notice">
148
+ <p>I am very helpful</p>
149
+ </div>
150
+
151
+ <h3 id="young-workers">Young Workers</h3>}
152
+ assert_text_output "Hello I am very helpful Young Workers"
153
+ end
154
+
155
+ test_given_govspeak "% I am very helpful" do
156
+ assert_html_output %{
157
+ <div class="application-notice help-notice">
158
+ <p>I am very helpful</p>
159
+ </div>}
160
+ assert_text_output "I am very helpful"
161
+ end
162
+
163
+ test_given_govspeak "This is a [link](http://www.google.com) isn't it?" do
164
+ assert_html_output '<p>This is a <a href="http://www.google.com">link</a> isn&rsquo;t it?</p>'
165
+ assert_text_output "This is a link isn’t it?"
166
+ end
167
+
168
+ test_given_govspeak "This is a [link with an at sign in it](http://www.google.com/@dg/@this) isn't it?" do
169
+ assert_html_output '<p>This is a <a href="http://www.google.com/@dg/@this">link with an at sign in it</a> isn&rsquo;t it?</p>'
170
+ assert_text_output "This is a link with an at sign in it isn’t it?"
171
+ end
172
+
173
+ test_given_govspeak "
174
+ HTML
175
+
176
+ *[HTML]: Hyper Text Markup Language" do
177
+ assert_html_output %{<p><abbr title="Hyper Text Markup Language">HTML</abbr></p>}
178
+ assert_text_output "HTML"
179
+ end
180
+
181
+ test_given_govspeak "x[a link](http://rubyforge.org)x" do
182
+ assert_html_output '<p><a href="http://rubyforge.org" rel="external">a link</a></p>'
183
+ assert_text_output "a link"
184
+ end
185
+
186
+ test_given_govspeak "
187
+ $!
188
+ rainbow
189
+ $!" do
190
+ assert_html_output %{
191
+ <div class="summary">
192
+ <p>rainbow</p>
193
+ </div>}
194
+ assert_text_output "rainbow"
195
+ end
196
+
197
+ test_given_govspeak "$C help, send cake $C" do
198
+ assert_html_output %{
199
+ <div class="contact">
200
+ <p>help, send cake</p>
201
+ </div>}
202
+ assert_text_output "help, send cake"
203
+ end
204
+
205
+ test_given_govspeak "
206
+ $A
207
+ street
208
+ road
209
+ $A" do
210
+ assert_html_output %{
211
+ <div class="address vcard"><div class="adr org fn"><p>
212
+ street<br />road<br />
213
+ </p></div></div>}
214
+ assert_text_output "street road"
215
+ end
216
+
217
+ test_given_govspeak "
218
+ $P
219
+ $I
220
+ help
221
+ $I
222
+ $P" do
223
+ assert_html_output %{<div class="place">\n<div class="information">\n<p>help</p>\n</div>\n</div>}
224
+ assert_text_output "help"
225
+ end
226
+
227
+ test_given_govspeak "
228
+ $D
229
+ can you tell me how to get to...
230
+ $D" do
231
+ assert_html_output %{
232
+ <div class="form-download">
233
+ <p>can you tell me how to get to…</p>
234
+ </div>}
235
+ assert_text_output "can you tell me how to get to…"
236
+ end
237
+
238
+ test_given_govspeak "
239
+ 1. rod
240
+ 2. jane
241
+ 3. freddy" do
242
+ assert_html_output "<ol>\n <li>rod</li>\n <li>jane</li>\n <li>freddy</li>\n</ol>"
243
+ assert_text_output "rod jane freddy"
244
+ end
245
+
246
+ test_given_govspeak "
202
247
  ((http://maps.google.co.uk/maps?q=Winkfield+Rd,+Windsor,+Berkshire+SL4+4AY&hl=en&sll=53.800651,-4.064941&sspn=17.759517,42.055664&vpsrc=0&z=14))
203
- ",
204
- output: %{<div class="map"><iframe width="200" height="200" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.co.uk/maps?q=Winkfield+Rd,+Windsor,+Berkshire+SL4+4AY&amp;hl=en&amp;sll=53.800651,-4.064941&amp;sspn=17.759517,42.055664&amp;vpsrc=0&amp;z=14&amp;output=embed"></iframe><br /><small><a href="http://maps.google.co.uk/maps?q=Winkfield+Rd,+Windsor,+Berkshire+SL4+4AY&amp;hl=en&amp;sll=53.800651,-4.064941&amp;sspn=17.759517,42.055664&amp;vpsrc=0&amp;z=14">View Larger Map</a></small></div>},
205
- text: "View Larger Map"
206
- }, {
207
- input: "s1. zippy
208
- s2. bungle
209
- s3. george
210
- ",
211
- output: %{<ol class="steps">
212
- <li><p>zippy</p>\n</li>
213
- <li><p>bungle</p>\n</li>
214
- <li><p>george</p>\n</li>
215
- </ol>},
216
- text: "zippy bungle george"
217
- }
218
- ]
248
+ " do
249
+ assert_html_output %{<div class="map"><iframe width="200" height="200" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.co.uk/maps?q=Winkfield+Rd,+Windsor,+Berkshire+SL4+4AY&amp;hl=en&amp;sll=53.800651,-4.064941&amp;sspn=17.759517,42.055664&amp;vpsrc=0&amp;z=14&amp;output=embed"></iframe><br /><small><a href="http://maps.google.co.uk/maps?q=Winkfield+Rd,+Windsor,+Berkshire+SL4+4AY&amp;hl=en&amp;sll=53.800651,-4.064941&amp;sspn=17.759517,42.055664&amp;vpsrc=0&amp;z=14">View Larger Map</a></small></div>}
250
+ assert_text_output "View Larger Map"
251
+ end
252
+
253
+ test_given_govspeak "
254
+ s1. zippy
255
+ s2. bungle
256
+ s3. george
257
+ " do
258
+ assert_html_output %{
259
+ <ol class="steps">
260
+ <li><p>zippy</p>
261
+ </li>
262
+ <li><p>bungle</p>
263
+ </li>
264
+ <li><p>george</p>
265
+ </li>
266
+ </ol>}
267
+ assert_text_output "zippy bungle george"
268
+ end
269
+
270
+ test_given_govspeak ":scotland: I am very devolved\n and very scottish \n:scotland:" do
271
+ assert_html_output '
272
+ <div class="devolved-content scotland">
273
+ <p class="devolved-header">This section applies to Scotland</p>
274
+ <div class="devolved-body"><p>I am very devolved
275
+ and very scottish</p>
276
+ </div>
277
+ </div>
278
+ '
279
+ end
219
280
 
220
- markdown_regression_tests.each do |t|
221
- doc = Govspeak::Document.new(t[:input])
222
- assert_equal t[:output].strip, doc.to_html.strip
223
- assert_equal t[:text], doc.to_text
281
+ test_given_govspeak "@ Message with [a link](http://foo.bar/)@" do
282
+ assert_html_output %{
283
+ <div class="advisory"><p><strong>Message with <a href="http://foo.bar/">a link</a></strong></p>
284
+ </div>
285
+ }
286
+ end
287
+
288
+ test "can reference attached images using !!n" do
289
+ images = [OpenStruct.new(alt_text: 'my alt', url: "http://example.com/image.jpg")]
290
+ given_govspeak "!!1", images do
291
+ assert_html_output %Q{
292
+ <figure class="image embedded">
293
+ <div class="img"><img alt="my alt" src="http://example.com/image.jpg" /></div>
294
+ </figure>
295
+ }
296
+ end
224
297
  end
225
298
 
226
- end
299
+ test "alt text of referenced images is escaped" do
300
+ images = [OpenStruct.new(alt_text: %Q{my alt '&"<>}, url: "http://example.com/image.jpg")]
301
+ given_govspeak "!!1", images do
302
+ assert_html_output %Q{
303
+ <figure class="image embedded">
304
+ <div class="img"><img alt="my alt &apos;&amp;&quot;&lt;&gt;" src="http://example.com/image.jpg" /></div>
305
+ </figure>
306
+ }
307
+ end
308
+ end
227
309
 
228
- test "devolved markdown sections" do
229
- input = ":scotland: I am very devolved\n and very scottish \n:scotland:"
230
- output = '<div class="devolved-content scotland">
231
- <p class="devolved-header">This section applies to Scotland</p>
232
- <div class="devolved-body"><p>I am very devolved
233
- and very scottish</p>
234
- </div>
235
- </div>
236
- '
237
-
238
- assert_equal output, Govspeak::Document.new(input).to_html
239
- end
240
-
241
- test "links inside markdown boxes" do
242
- input = "@ Message with [a link](http://foo.bar/)@"
243
- output = %{
244
- <div class="advisory"><p><strong>Message with <a href="http://foo.bar/">a link</a></strong></p>
245
- </div>
246
- }
247
-
248
- assert_equal output, Govspeak::Document.new(input).to_html
249
- end
310
+ test "silently ignores an image attachment if the referenced image is missing" do
311
+ doc = Govspeak::Document.new("!!1")
312
+ doc.images = []
313
+
314
+ assert_equal %Q{\n}, doc.to_html
315
+ end
316
+
317
+ test "adds image caption if given" do
318
+ images = [OpenStruct.new(alt_text: "my alt", url: "http://example.com/image.jpg", caption: 'My Caption & so on')]
319
+ given_govspeak "!!1", images do
320
+ assert_html_output %Q{
321
+ <figure class="image embedded">
322
+ <div class="img"><img alt="my alt" src="http://example.com/image.jpg" /></div>
323
+ <figcaption>My Caption &amp; so on</figcaption>
324
+ </figure>
325
+ }
326
+ end
327
+ end
328
+
329
+ test "ignores a blank caption" do
330
+ images = [OpenStruct.new(alt_text: "my alt", url: "http://example.com/image.jpg", caption: ' ')]
331
+ given_govspeak "!!1", images do
332
+ assert_html_output %Q{
333
+ <figure class="image embedded">
334
+ <div class="img"><img alt="my alt" src="http://example.com/image.jpg" /></div>
335
+ </figure>
336
+ }
337
+ end
338
+ end
250
339
 
251
340
  end
@@ -0,0 +1,74 @@
1
+ module GovspeakTestHelper
2
+
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ class GovspeakAsserter
8
+ def initialize(testcase, govspeak, images = [])
9
+ @testcase = testcase
10
+ @govspeak = remove_indentation(govspeak)
11
+ @images = images
12
+ end
13
+
14
+ def document
15
+ Govspeak::Document.new(@govspeak).tap do |doc|
16
+ doc.images = @images
17
+ end
18
+ end
19
+
20
+ def assert_text_output(raw_expected)
21
+ expected = remove_indentation(raw_expected)
22
+ actual = document.to_text
23
+ @testcase.assert expected == actual, describe_error(@govspeak, expected, actual)
24
+ end
25
+
26
+ def assert_html_output(raw_expected)
27
+ expected = remove_indentation(raw_expected)
28
+ actual = document.to_html.strip
29
+ @testcase.assert expected.strip == actual, describe_error(@govspeak, expected.strip, actual)
30
+ end
31
+
32
+ def remove_indentation(raw)
33
+ lines = raw.split("\n")
34
+ if lines.first.empty?
35
+ lines.delete_at(0)
36
+ nonblanks = lines.reject { |l| l.match(/^ *$/) }
37
+ indentation = nonblanks.map do |line|
38
+ line.match(/^ */)[0].size
39
+ end.min
40
+ unindented = lines.map do |line|
41
+ line[indentation..-1]
42
+ end
43
+ unindented.join "\n"
44
+ else
45
+ raw
46
+ end
47
+ end
48
+
49
+ def describe_error(govspeak, expected, actual)
50
+ "Expected:\n#{govspeak}\n\nto produce:\n#{show_linenumbers(expected)}\n\nbut got:\n#{show_linenumbers(actual)}\n"
51
+ end
52
+
53
+ def show_linenumbers(text)
54
+ lines = text.split "\n"
55
+ digits = Math.log10(lines.size + 2).ceil
56
+ lines.map.with_index do |line, i|
57
+ "%#{digits}d: %s" % [i+1, line]
58
+ end.join "\n"
59
+ end
60
+ end
61
+
62
+ def given_govspeak(govspeak, images=[], &block)
63
+ asserter = GovspeakAsserter.new(self, govspeak, images)
64
+ asserter.instance_eval(&block)
65
+ end
66
+
67
+ module ClassMethods
68
+ def test_given_govspeak(govspeak, &block)
69
+ test "Given #{govspeak}" do
70
+ given_govspeak(govspeak, &block)
71
+ end
72
+ end
73
+ end
74
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: govspeak
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.8.9
5
+ version: 0.8.10
6
6
  platform: ruby
7
7
  authors:
8
8
  - Ben Griffiths
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2012-01-30 00:00:00 Z
14
+ date: 2012-02-15 00:00:00 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: kramdown
@@ -60,10 +60,13 @@ extra_rdoc_files: []
60
60
 
61
61
  files:
62
62
  - lib/govspeak/header_extractor.rb
63
+ - lib/govspeak/version.rb
63
64
  - lib/govspeak.rb
65
+ - README.md
64
66
  - Gemfile
65
67
  - Rakefile
66
68
  - test/govspeak_test.rb
69
+ - test/govspeak_test_helper.rb
67
70
  - test/test_helper.rb
68
71
  homepage: http://github.com/alphagov/govspeak
69
72
  licenses: []
@@ -78,7 +81,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
78
81
  requirements:
79
82
  - - ">="
80
83
  - !ruby/object:Gem::Version
81
- hash: 3606479942582695776
84
+ hash: -3286011011041893996
82
85
  segments:
83
86
  - 0
84
87
  version: "0"
@@ -87,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
90
  requirements:
88
91
  - - ">="
89
92
  - !ruby/object:Gem::Version
90
- hash: 3606479942582695776
93
+ hash: -3286011011041893996
91
94
  segments:
92
95
  - 0
93
96
  version: "0"
@@ -100,4 +103,5 @@ specification_version: 3
100
103
  summary: Markup language for single domain
101
104
  test_files:
102
105
  - test/govspeak_test.rb
106
+ - test/govspeak_test_helper.rb
103
107
  - test/test_helper.rb