govspeak 0.8.9 → 0.8.10

Sign up to get free protection for your applications and to get access to all the features.
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