govspeak 0.8.4
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/Gemfile +7 -0
- data/Rakefile +15 -0
- data/lib/govspeak.rb +118 -0
- data/test/govspeak_test.rb +171 -0
- data/test/test_helper.rb +20 -0
- metadata +77 -0
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'bundler'
|
4
|
+
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
task :default => [:test_units]
|
8
|
+
|
9
|
+
desc "Run basic tests"
|
10
|
+
Rake::TestTask.new("test_units") { |t|
|
11
|
+
t.libs << "test"
|
12
|
+
t.pattern = 'test/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
t.warning = true
|
15
|
+
}
|
data/lib/govspeak.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'kramdown'
|
2
|
+
|
3
|
+
module Govspeak
|
4
|
+
|
5
|
+
class Document
|
6
|
+
|
7
|
+
@@extensions = []
|
8
|
+
|
9
|
+
def self.to_html(source, options = {})
|
10
|
+
new(source, options).to_html
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(source, options = {})
|
14
|
+
source ||= ""
|
15
|
+
options[:entity_output] ||= :symbolic
|
16
|
+
@doc = Kramdown::Document.new(preprocess(source), options)
|
17
|
+
super()
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_html
|
21
|
+
@doc.to_html
|
22
|
+
end
|
23
|
+
|
24
|
+
def preprocess(source)
|
25
|
+
@@extensions.each do |title,regexp,block|
|
26
|
+
source.gsub!(regexp) {|match|
|
27
|
+
block.call($1)
|
28
|
+
}
|
29
|
+
end
|
30
|
+
source
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.extension(title, regexp = nil, &block)
|
34
|
+
regexp ||= %r${::#{title}}(.*?){:/#{title}}$m
|
35
|
+
@@extensions << [title, regexp, block]
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.surrounded_by(open, close=nil)
|
39
|
+
open = Regexp::escape(open)
|
40
|
+
if close
|
41
|
+
close = Regexp::escape(close)
|
42
|
+
%r+(?:\r|\n|^)#{open}(.*?)#{close}(\r|\n|$)?+m
|
43
|
+
else
|
44
|
+
%r+(?:\r|\n|^)#{open}(.*?)#{open}?(\r|\n|$)+m
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.wrap_with_div(class_name, character, parser=Kramdown::Document)
|
49
|
+
extension(class_name, surrounded_by(character)) { |body|
|
50
|
+
content = parser ? parser.new("#{body.strip}\n").to_html : body.strip
|
51
|
+
%{<div class="#{class_name}">\n#{content}</div>\n}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
extension('reverse') { |body|
|
56
|
+
body.reverse
|
57
|
+
}
|
58
|
+
|
59
|
+
extension('external', surrounded_by("x")) { |body|
|
60
|
+
Kramdown::Document.new("#{body.strip}{:rel='external'}").to_html
|
61
|
+
}
|
62
|
+
|
63
|
+
extension('informational', surrounded_by("^")) { |body|
|
64
|
+
%{\n\n<div class="application-notice info-notice">
|
65
|
+
#{Kramdown::Document.new(body.strip).to_html}</div>\n}
|
66
|
+
}
|
67
|
+
|
68
|
+
extension('important', surrounded_by("@")) { |body|
|
69
|
+
%{\n\n<h3 class="advisory"><span>#{body.strip}</span></h3>\n}
|
70
|
+
}
|
71
|
+
|
72
|
+
extension('helpful', surrounded_by("%")) { |body|
|
73
|
+
%{\n\n<div class="application-notice help-notice">\n<p>#{body.strip}</p>\n</div>\n}
|
74
|
+
}
|
75
|
+
|
76
|
+
extension('map_link', surrounded_by("((", "))")) { |body|
|
77
|
+
%{<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>}
|
78
|
+
}
|
79
|
+
|
80
|
+
wrap_with_div('summary', '$!')
|
81
|
+
wrap_with_div('form-download', '$D')
|
82
|
+
wrap_with_div('contact', '$C')
|
83
|
+
wrap_with_div('place', '$P', Govspeak::Document)
|
84
|
+
wrap_with_div('information', '$I', Govspeak::Document)
|
85
|
+
wrap_with_div('additional-information', '$AI')
|
86
|
+
wrap_with_div('example', '$E', Govspeak::Document)
|
87
|
+
|
88
|
+
extension('address', surrounded_by("$A")) { |body|
|
89
|
+
%{<div class="address vcard"><div class="adr org fn"><p>\n#{body.sub("\n", "").gsub("\n", "<br />")}\n</p></div></div>\n}
|
90
|
+
}
|
91
|
+
|
92
|
+
extension("numbered list", /((s\d+\.\s.*(?:\n|$))+)/) do |body|
|
93
|
+
steps ||= 0
|
94
|
+
body.gsub!(/s(\d+)\.\s(.*)(?:\n|$)/) do |b|
|
95
|
+
"<li>#{Kramdown::Document.new($2.strip).to_html}</li>\n"
|
96
|
+
end
|
97
|
+
%{<ol class="steps">\n#{body}</ol>}
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.devolved_options
|
101
|
+
{ 'scotland' => 'Scotland',
|
102
|
+
'england' => 'England',
|
103
|
+
'england-wales' => 'England and Wales',
|
104
|
+
'northern-ireland' => 'Northern Ireland',
|
105
|
+
'wales' => 'Wales',
|
106
|
+
'london' => 'London' }
|
107
|
+
end
|
108
|
+
|
109
|
+
devolved_options.each do |k,v|
|
110
|
+
extension("devolved-#{k}",/:#{k}:(.*?):#{k}:/m) do |body|
|
111
|
+
%{<div class="devolved-content #{k}">
|
112
|
+
<p class="devolved-header">This section applies to #{v}</p>
|
113
|
+
<div class="devolved-body">#{Kramdown::Document.new(body.strip).to_html}</div>
|
114
|
+
</div>\n}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'simplecov-rcov'
|
3
|
+
|
4
|
+
SimpleCov.start
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
|
6
|
+
|
7
|
+
require 'test_helper'
|
8
|
+
|
9
|
+
class GovspeakTest < Test::Unit::TestCase
|
10
|
+
|
11
|
+
test "simple smoke-test" do
|
12
|
+
rendered = Govspeak::Document.new("*this is markdown*").to_html
|
13
|
+
assert_equal "<p><em>this is markdown</em></p>\n", rendered
|
14
|
+
end
|
15
|
+
|
16
|
+
test "simple smoke-test for simplified API" do
|
17
|
+
rendered = Govspeak::Document.to_html("*this is markdown*")
|
18
|
+
assert_equal "<p><em>this is markdown</em></p>\n", rendered
|
19
|
+
end
|
20
|
+
|
21
|
+
test "simple block extension" do
|
22
|
+
rendered = Govspeak::Document.new("this \n{::reverse}\n*is*\n{:/reverse}\n markdown").to_html
|
23
|
+
assert_equal "<p>this </p>\n\n<p><em>si</em></p>\n\n<p>markdown</p>\n", rendered
|
24
|
+
end
|
25
|
+
|
26
|
+
test "govspark extensions" do
|
27
|
+
markdown_regression_tests = [
|
28
|
+
{
|
29
|
+
input: "^ I am very informational ^",
|
30
|
+
output: %{<div class="application-notice info-notice">
|
31
|
+
<p>I am very informational</p>
|
32
|
+
</div>}
|
33
|
+
}, {
|
34
|
+
input: "The following is very informational\n^ I am very informational ^",
|
35
|
+
output: %{<p>The following is very informational</p>
|
36
|
+
|
37
|
+
<div class="application-notice info-notice">
|
38
|
+
<p>I am very informational</p>
|
39
|
+
</div>}
|
40
|
+
}, {
|
41
|
+
input: "^ I am very informational",
|
42
|
+
output: %{<div class="application-notice info-notice">
|
43
|
+
<p>I am very informational</p>
|
44
|
+
</div>}
|
45
|
+
}, {
|
46
|
+
input: "@ I am very important @",
|
47
|
+
output: %{<h3 class="advisory"><span>I am very important</span></h3>}
|
48
|
+
}, {
|
49
|
+
input: "The following is very important
|
50
|
+
@ I am very important @",
|
51
|
+
output: %{<p>The following is very important</p>
|
52
|
+
|
53
|
+
<h3 class="advisory"><span>I am very important</span></h3>}
|
54
|
+
}, {
|
55
|
+
input: "% I am very helpful %",
|
56
|
+
output: %{<div class="application-notice help-notice">
|
57
|
+
<p>I am very helpful</p>
|
58
|
+
</div>}
|
59
|
+
}, {
|
60
|
+
input: "The following is very helpful\n% I am very helpful %",
|
61
|
+
output: %{<p>The following is very helpful</p>
|
62
|
+
|
63
|
+
<div class="application-notice help-notice">
|
64
|
+
<p>I am very helpful</p>
|
65
|
+
</div>}
|
66
|
+
}, {
|
67
|
+
input: "## Hello ##\n\n% I am very helpful %\r\n### Young Workers ###\n\n",
|
68
|
+
output: %{<h2 id="hello">Hello</h2>
|
69
|
+
|
70
|
+
<div class="application-notice help-notice">
|
71
|
+
<p>I am very helpful</p>
|
72
|
+
</div>
|
73
|
+
|
74
|
+
<h3 id="young-workers">Young Workers</h3>}
|
75
|
+
}, {
|
76
|
+
input: "% I am very helpful",
|
77
|
+
output: %{<div class="application-notice help-notice">
|
78
|
+
<p>I am very helpful</p>
|
79
|
+
</div>}
|
80
|
+
}, {
|
81
|
+
input: "This is a [link](http://www.google.com) isn't it?",
|
82
|
+
output: '<p>This is a <a href="http://www.google.com">link</a> isn’t it?</p>'
|
83
|
+
}, {
|
84
|
+
input: "This is a [link with an at sign in it](http://www.google.com/@dg/@this) isn't it?",
|
85
|
+
output: '<p>This is a <a href="http://www.google.com/@dg/@this">link with an at sign in it</a> isn’t it?</p>'
|
86
|
+
}, {
|
87
|
+
input: "HTML
|
88
|
+
|
89
|
+
*[HTML]: Hyper Text Markup Language",
|
90
|
+
output: %{<p><abbr title="Hyper Text Markup Language">HTML</abbr></p>}
|
91
|
+
}, {
|
92
|
+
input: "x[a link](http://rubyforge.org)x",
|
93
|
+
output: '<p><a href="http://rubyforge.org" rel="external">a link</a></p>'
|
94
|
+
}, {
|
95
|
+
input: "$!
|
96
|
+
rainbow
|
97
|
+
$!",
|
98
|
+
output: %{<div class="summary">
|
99
|
+
<p>rainbow</p>
|
100
|
+
</div>}
|
101
|
+
}, {
|
102
|
+
input: "$C help, send cake $C",
|
103
|
+
output: %{<div class="contact">
|
104
|
+
<p>help, send cake</p>
|
105
|
+
</div>}
|
106
|
+
}, {
|
107
|
+
input: "$A
|
108
|
+
street
|
109
|
+
road
|
110
|
+
$A",
|
111
|
+
output: %{<div class="address vcard"><div class="adr org fn"><p>
|
112
|
+
street<br />road<br />
|
113
|
+
</p></div></div>}
|
114
|
+
}, {
|
115
|
+
input: "$P
|
116
|
+
$I
|
117
|
+
help
|
118
|
+
$I
|
119
|
+
$P",
|
120
|
+
output: %{<div class="place">\n<div class="information">\n<p>help</p>\n</div>\n</div>}
|
121
|
+
}, {
|
122
|
+
input: "$D
|
123
|
+
can you tell me how to get to...
|
124
|
+
$D",
|
125
|
+
output: %{<div class="form-download">
|
126
|
+
<p>can you tell me how to get to…</p>
|
127
|
+
</div>}
|
128
|
+
}, {
|
129
|
+
input: "1. rod
|
130
|
+
2. jane
|
131
|
+
3. freddy",
|
132
|
+
output: "<ol>\n <li>rod</li>\n <li>jane</li>\n <li>freddy</li>\n</ol>"
|
133
|
+
}, {
|
134
|
+
input: "
|
135
|
+
((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))
|
136
|
+
",
|
137
|
+
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&hl=en&sll=53.800651,-4.064941&sspn=17.759517,42.055664&vpsrc=0&z=14&output=embed"></iframe><br /><small><a href="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">View Larger Map</a></small></div>}
|
138
|
+
}, {
|
139
|
+
input: "s1. zippy
|
140
|
+
s2. bungle
|
141
|
+
s3. george
|
142
|
+
",
|
143
|
+
output: %{<ol class="steps">
|
144
|
+
<li><p>zippy</p>\n</li>
|
145
|
+
<li><p>bungle</p>\n</li>
|
146
|
+
<li><p>george</p>\n</li>
|
147
|
+
</ol>}
|
148
|
+
}
|
149
|
+
]
|
150
|
+
|
151
|
+
markdown_regression_tests.each do |t|
|
152
|
+
rendered = Govspeak::Document.new(t[:input]).to_html
|
153
|
+
assert_equal t[:output].strip, rendered.strip
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
test "devolved markdown sections" do
|
159
|
+
input = ":scotland: I am very devolved \n and very scottish \n:scotland:"
|
160
|
+
output = '<div class="devolved-content scotland">
|
161
|
+
<p class="devolved-header">This section applies to Scotland</p>
|
162
|
+
<div class="devolved-body"><p>I am very devolved
|
163
|
+
and very scottish</p>
|
164
|
+
</div>
|
165
|
+
</div>
|
166
|
+
'
|
167
|
+
|
168
|
+
assert_equal output, Govspeak::Document.new(input).to_html
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$:.unshift(File.expand_path("../lib")) unless $:.include?(File.expand_path("../lib"))
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup :default, :development, :test
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
class Test::Unit::TestCase
|
9
|
+
class << self
|
10
|
+
def test(name, &block)
|
11
|
+
clean_name = name.gsub(/\s+/,'_')
|
12
|
+
method = "test_#{clean_name.gsub(/\s+/,'_')}".to_sym
|
13
|
+
already_defined = instance_method(method) rescue false
|
14
|
+
raise "#{method} exists" if already_defined
|
15
|
+
define_method(method, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'govspeak'
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: govspeak
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ben Griffiths
|
9
|
+
- James Stewart
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2011-11-01 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: kramdown
|
17
|
+
requirement: &70159122835620 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.13.3
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70159122835620
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rake
|
28
|
+
requirement: &70159122835160 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.8.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70159122835160
|
37
|
+
description: ! "A set of extensions to markdown layered on top of the kramdown \nlibrary
|
38
|
+
for use in the UK Government Single Domain project"
|
39
|
+
email:
|
40
|
+
- ben@alphagov.co.uk
|
41
|
+
- james.stewart@digital.cabinet-office.gov.uk
|
42
|
+
executables: []
|
43
|
+
extensions: []
|
44
|
+
extra_rdoc_files: []
|
45
|
+
files:
|
46
|
+
- lib/govspeak.rb
|
47
|
+
- Gemfile
|
48
|
+
- Rakefile
|
49
|
+
- test/govspeak_test.rb
|
50
|
+
- test/test_helper.rb
|
51
|
+
homepage: http://github.com/alphagov/govspeak
|
52
|
+
licenses: []
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.8.10
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Markup language for single domain
|
75
|
+
test_files:
|
76
|
+
- test/govspeak_test.rb
|
77
|
+
- test/test_helper.rb
|