govuk_content_models 12.0.0 → 12.1.0
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/CHANGELOG.md +7 -0
- data/app/models/edition.rb +1 -0
- data/app/models/part.rb +1 -3
- data/app/models/travel_advice_edition.rb +1 -2
- data/app/validators/link_validator.rb +48 -0
- data/lib/govuk_content_models/version.rb +1 -1
- data/test/models/travel_advice_edition_test.rb +0 -22
- data/test/validators/link_validator_test.rb +36 -0
- metadata +7 -5
- data/app/traits/govspeak_smart_quotes_fixer.rb +0 -19
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 12.1.0
|
2
|
+
|
3
|
+
* Add LinkValidator, which checks that links in Govspeak fields are properly
|
4
|
+
formed and do not contain title text or rel=external. Remove
|
5
|
+
GovspeakSmartQuotesFixer which is irrelevant now title text is no longer
|
6
|
+
allowed.
|
7
|
+
|
1
8
|
## 12.0.0
|
2
9
|
|
3
10
|
* Remove `SpecialistDocumentEdition` model. It is only used by the
|
data/app/models/edition.rb
CHANGED
@@ -48,6 +48,7 @@ class Edition
|
|
48
48
|
validates :version_number, presence: true, uniqueness: {scope: :panopticon_id}
|
49
49
|
validates :panopticon_id, presence: true
|
50
50
|
validates_with SafeHtml
|
51
|
+
validates_with LinkValidator
|
51
52
|
|
52
53
|
before_save :check_for_archived_artefact
|
53
54
|
before_destroy :destroy_artefact
|
data/app/models/part.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require "safe_html"
|
2
|
-
require 'govspeak_smart_quotes_fixer'
|
3
2
|
|
4
3
|
class Part
|
5
4
|
include Mongoid::Document
|
@@ -18,11 +17,10 @@ class Part
|
|
18
17
|
|
19
18
|
GOVSPEAK_FIELDS = [:body]
|
20
19
|
|
21
|
-
include GovspeakSmartQuotesFixer
|
22
|
-
|
23
20
|
validates_presence_of :title
|
24
21
|
validates_presence_of :slug
|
25
22
|
validates_exclusion_of :slug, in: ["video"], message: "Can not be video"
|
26
23
|
validates_format_of :slug, with: /^[a-z0-9\-]+$/i
|
27
24
|
validates_with SafeHtml
|
25
|
+
validates_with LinkValidator
|
28
26
|
end
|
@@ -2,7 +2,6 @@ require 'attachable'
|
|
2
2
|
require 'parted'
|
3
3
|
require 'state_machine'
|
4
4
|
require 'safe_html'
|
5
|
-
require 'govspeak_smart_quotes_fixer'
|
6
5
|
|
7
6
|
class TravelAdviceEdition
|
8
7
|
include Mongoid::Document
|
@@ -38,7 +37,6 @@ class TravelAdviceEdition
|
|
38
37
|
"avoid_all_travel_to_whole_country",
|
39
38
|
]
|
40
39
|
|
41
|
-
include GovspeakSmartQuotesFixer
|
42
40
|
before_validation :populate_version_number, :on => :create
|
43
41
|
|
44
42
|
validates_presence_of :country_slug, :title
|
@@ -47,6 +45,7 @@ class TravelAdviceEdition
|
|
47
45
|
validate :alert_status_contains_valid_values
|
48
46
|
validate :first_version_cant_be_minor_update
|
49
47
|
validates_with SafeHtml
|
48
|
+
validates_with LinkValidator
|
50
49
|
|
51
50
|
scope :published, where(:state => "published")
|
52
51
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class LinkValidator < ActiveModel::Validator
|
2
|
+
def validate(record)
|
3
|
+
record.changes.each do |field_name, (_, new_value)|
|
4
|
+
if govspeak_fields(record).include?(field_name.to_sym)
|
5
|
+
messages = errors(new_value)
|
6
|
+
record.errors[field_name] << messages if messages
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def errors(string)
|
12
|
+
link_regex = %r{
|
13
|
+
\[.*?\] # link text in literal square brackets
|
14
|
+
\( # literal opening parenthesis
|
15
|
+
(\S*?) # containing URL
|
16
|
+
(\s+"[^"]+")? # and optional space followed by title text in quotes
|
17
|
+
\) # literal close paren
|
18
|
+
(\{:rel=["']external["']\})? # optional :rel=external in literal curly brackets.
|
19
|
+
}x
|
20
|
+
|
21
|
+
errors = []
|
22
|
+
|
23
|
+
string.scan(link_regex) do |match|
|
24
|
+
|
25
|
+
error = if match[0] !~ %r{^(?:https?://|mailto:|/)}
|
26
|
+
'Internal links must start with a forward slash eg [link text](/link-destination). External links must start with http://, https://, or mailto: eg [external link text](https://www.google.co.uk)'
|
27
|
+
elsif match[1]
|
28
|
+
%q-Don't include hover text in links. Delete the text in quotation marks eg "This appears when you hover over the link."-
|
29
|
+
elsif match[2]
|
30
|
+
'Delete {:rel="external"} in links.'
|
31
|
+
end
|
32
|
+
|
33
|
+
errors << error if error
|
34
|
+
end
|
35
|
+
errors
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def govspeak_fields(record)
|
41
|
+
if record.class.const_defined?(:GOVSPEAK_FIELDS)
|
42
|
+
record.class.const_get(:GOVSPEAK_FIELDS)
|
43
|
+
else
|
44
|
+
[]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -213,28 +213,6 @@ class TravelAdviceEditionTest < ActiveSupport::TestCase
|
|
213
213
|
end
|
214
214
|
end
|
215
215
|
|
216
|
-
context "fixing user input" do
|
217
|
-
setup do
|
218
|
-
@ed = FactoryGirl.build(:travel_advice_edition)
|
219
|
-
end
|
220
|
-
|
221
|
-
should "convert smart quotes in the summary field" do
|
222
|
-
@ed.summary = "This is a [link](https://www.gov.uk/ “link”)"
|
223
|
-
@ed.save!
|
224
|
-
|
225
|
-
@ed.reload
|
226
|
-
assert_equal 'This is a [link](https://www.gov.uk/ "link")', @ed.summary
|
227
|
-
end
|
228
|
-
|
229
|
-
should "convert smart quotes in part bodies" do
|
230
|
-
@ed.parts.build(:title => 'One', :slug => 'one', :body => "This is a [link](https://www.gov.uk/ “link”)")
|
231
|
-
@ed.save!
|
232
|
-
|
233
|
-
@ed.reload
|
234
|
-
assert_equal 'This is a [link](https://www.gov.uk/ "link")', @ed.parts.first.body
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
216
|
should "have a published scope" do
|
239
217
|
e1 = FactoryGirl.create(:draft_travel_advice_edition)
|
240
218
|
e2 = FactoryGirl.create(:published_travel_advice_edition)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class LinkValidatorTest < ActiveSupport::TestCase
|
4
|
+
class Dummy
|
5
|
+
include Mongoid::Document
|
6
|
+
|
7
|
+
field "body", type: String
|
8
|
+
GOVSPEAK_FIELDS = [:body]
|
9
|
+
|
10
|
+
validates_with LinkValidator
|
11
|
+
end
|
12
|
+
|
13
|
+
context "links" do
|
14
|
+
should "start with http[s]://, mailto: or /" do
|
15
|
+
doc = Dummy.new(body: "abc [external](external.com)")
|
16
|
+
assert doc.invalid?
|
17
|
+
assert_includes doc.errors.keys, :body
|
18
|
+
|
19
|
+
doc = Dummy.new(body: "abc [external](http://external.com)")
|
20
|
+
assert doc.valid?
|
21
|
+
|
22
|
+
doc = Dummy.new(body: "abc [internal](/internal)")
|
23
|
+
assert doc.valid?
|
24
|
+
end
|
25
|
+
should "start not contain hover text" do
|
26
|
+
doc = Dummy.new(body: 'abc [foobar](foobar.com "hover")')
|
27
|
+
assert doc.invalid?
|
28
|
+
assert_includes doc.errors.keys, :body
|
29
|
+
end
|
30
|
+
should "start not set rel=external" do
|
31
|
+
doc = Dummy.new(body: 'abc [foobar](foobar.com){:rel="external"}')
|
32
|
+
assert doc.invalid?
|
33
|
+
assert_includes doc.errors.keys, :body
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govuk_content_models
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 12.
|
4
|
+
version: 12.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-06-
|
12
|
+
date: 2014-06-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bson_ext
|
@@ -389,8 +389,8 @@ files:
|
|
389
389
|
- app/models/workflow.rb
|
390
390
|
- app/models/workflow_actor.rb
|
391
391
|
- app/traits/attachable.rb
|
392
|
-
- app/traits/govspeak_smart_quotes_fixer.rb
|
393
392
|
- app/traits/taggable.rb
|
393
|
+
- app/validators/link_validator.rb
|
394
394
|
- app/validators/safe_html.rb
|
395
395
|
- app/validators/slug_validator.rb
|
396
396
|
- app/validators/tag_id_validator.rb
|
@@ -447,6 +447,7 @@ files:
|
|
447
447
|
- test/test_helper.rb
|
448
448
|
- test/traits/attachable_test.rb
|
449
449
|
- test/traits/taggable_test.rb
|
450
|
+
- test/validators/link_validator_test.rb
|
450
451
|
- test/validators/safe_html_validator_test.rb
|
451
452
|
- test/validators/slug_validator_test.rb
|
452
453
|
- test/validators/tag_id_validator_test.rb
|
@@ -465,7 +466,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
465
466
|
version: '0'
|
466
467
|
segments:
|
467
468
|
- 0
|
468
|
-
hash:
|
469
|
+
hash: 4316099945977506650
|
469
470
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
470
471
|
none: false
|
471
472
|
requirements:
|
@@ -474,7 +475,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
474
475
|
version: '0'
|
475
476
|
segments:
|
476
477
|
- 0
|
477
|
-
hash:
|
478
|
+
hash: 4316099945977506650
|
478
479
|
requirements: []
|
479
480
|
rubyforge_project:
|
480
481
|
rubygems_version: 1.8.23
|
@@ -525,6 +526,7 @@ test_files:
|
|
525
526
|
- test/test_helper.rb
|
526
527
|
- test/traits/attachable_test.rb
|
527
528
|
- test/traits/taggable_test.rb
|
529
|
+
- test/validators/link_validator_test.rb
|
528
530
|
- test/validators/safe_html_validator_test.rb
|
529
531
|
- test/validators/slug_validator_test.rb
|
530
532
|
- test/validators/tag_id_validator_test.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
module GovspeakSmartQuotesFixer
|
4
|
-
def self.included(model)
|
5
|
-
model.class_eval do
|
6
|
-
before_validation :fix_smart_quotes_in_govspeak
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
def fix_smart_quotes_in_govspeak
|
13
|
-
self.class::GOVSPEAK_FIELDS.each do |field|
|
14
|
-
if self.send(field) =~ /[“”]/
|
15
|
-
self.send(field).gsub!(/[“”]/, '"')
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|