govspeak 8.4.1 → 8.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +28 -0
- data/lib/govspeak/embed_extractor.rb +17 -0
- data/lib/govspeak/embedded_content.rb +15 -0
- data/lib/govspeak/presenters/embed_presenter.rb +32 -0
- data/lib/govspeak/version.rb +1 -1
- data/lib/govspeak.rb +12 -1
- data/test/embed_extractor_test.rb +59 -0
- data/test/govspeak_embeds_test.rb +84 -0
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23ac40c67eb46b8265549568542bc48bb0cb96fe47c8b217a1e6135789ab2134
|
4
|
+
data.tar.gz: 26d7a270ab0163d056c0fefff53548727019128456deab21409ee3b3ae6e01eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e637261f8a573479a054e8cdcba539ed296c4c9a1d70c263ff4caea059faf80992806332922259da0d52983013a4c302a11bed5421b12534f6d1de6b105d9620
|
7
|
+
data.tar.gz: fa04e11f539f372793d6420f9dcdc81964d244530f3d9e397f0587ca22fac9e66e41b85d79cd224c88f187946bddeb04f9afdfe223328240c353b060bb45fba2
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -608,6 +608,34 @@ will output
|
|
608
608
|
</div>
|
609
609
|
```
|
610
610
|
|
611
|
+
### Content blocks
|
612
|
+
|
613
|
+
Authors can embed different types of [supported content](https://github.com/alphagov/govspeak/blob/main/lib/govspeak/embedded_content.rb#L3) created by the Content Block Manager
|
614
|
+
|
615
|
+
```
|
616
|
+
{{embed:content_block_email_address:d308f561-e5ee-45b5-90b2-3ac36a23fad9}}
|
617
|
+
```
|
618
|
+
|
619
|
+
with options provided
|
620
|
+
|
621
|
+
```
|
622
|
+
{
|
623
|
+
embeds: [
|
624
|
+
{
|
625
|
+
content_id: "d308f561-e5ee-45b5-90b2-3ac36a23fad9",
|
626
|
+
title: "Government Digital Service",
|
627
|
+
details: { email_address: "test@example.com" },
|
628
|
+
}
|
629
|
+
]
|
630
|
+
}
|
631
|
+
```
|
632
|
+
|
633
|
+
will output
|
634
|
+
|
635
|
+
```html
|
636
|
+
<span class="embed_content_block_email_address" id="embed_d308f561-e5ee-45b5-90b2-3ac36a23fad9">test@example.com</span>
|
637
|
+
```
|
638
|
+
|
611
639
|
### Button
|
612
640
|
|
613
641
|
An accessible way to add button links into content, that can also allow cross domain tracking with [Google Analytics](https://support.google.com/analytics/answer/7372977?hl=en)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Govspeak
|
2
|
+
class EmbedExtractor
|
3
|
+
def initialize(document)
|
4
|
+
@document = document
|
5
|
+
end
|
6
|
+
|
7
|
+
def content_references
|
8
|
+
@content_references ||= @document.scan(EmbeddedContent::EMBED_REGEX).map { |match|
|
9
|
+
EmbeddedContent.new(document_type: match[1], content_id: match[2], embed_code: match[0])
|
10
|
+
}.uniq
|
11
|
+
end
|
12
|
+
|
13
|
+
def content_ids
|
14
|
+
@content_ids ||= content_references.map(&:content_id)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Govspeak
|
2
|
+
class EmbeddedContent
|
3
|
+
SUPPORTED_DOCUMENT_TYPES = %w[contact content_block_email_address].freeze
|
4
|
+
UUID_REGEX = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/
|
5
|
+
EMBED_REGEX = /({{embed:(#{SUPPORTED_DOCUMENT_TYPES.join('|')}):#{UUID_REGEX}}})/
|
6
|
+
|
7
|
+
attr_reader :document_type, :content_id, :embed_code
|
8
|
+
|
9
|
+
def initialize(document_type:, content_id:, embed_code:)
|
10
|
+
@document_type = document_type
|
11
|
+
@content_id = content_id
|
12
|
+
@embed_code = embed_code
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "action_view"
|
2
|
+
require "htmlentities"
|
3
|
+
|
4
|
+
module Govspeak
|
5
|
+
class EmbedPresenter
|
6
|
+
include ActionView::Helpers::TagHelper
|
7
|
+
|
8
|
+
attr_reader :embed
|
9
|
+
|
10
|
+
def initialize(embed)
|
11
|
+
@embed = ActiveSupport::HashWithIndifferentAccess.new(embed)
|
12
|
+
end
|
13
|
+
|
14
|
+
def content_id
|
15
|
+
embed[:content_id]
|
16
|
+
end
|
17
|
+
|
18
|
+
def document_type
|
19
|
+
embed[:document_type]
|
20
|
+
end
|
21
|
+
|
22
|
+
def render
|
23
|
+
body = if document_type == "content_block_email_address"
|
24
|
+
embed.dig(:details, :email_address)
|
25
|
+
else
|
26
|
+
embed[:title]
|
27
|
+
end
|
28
|
+
|
29
|
+
content_tag(:span, body, class: "embed embed-#{document_type}", id: "embed_#{content_id}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/govspeak/version.rb
CHANGED
data/lib/govspeak.rb
CHANGED
@@ -14,11 +14,14 @@ require "govspeak/structured_header_extractor"
|
|
14
14
|
require "govspeak/html_validator"
|
15
15
|
require "govspeak/html_sanitizer"
|
16
16
|
require "govspeak/blockquote_extra_quote_remover"
|
17
|
+
require "govspeak/embed_extractor"
|
18
|
+
require "govspeak/embedded_content"
|
17
19
|
require "govspeak/post_processor"
|
18
20
|
require "govspeak/link_extractor"
|
19
21
|
require "govspeak/template_renderer"
|
20
22
|
require "govspeak/presenters/attachment_presenter"
|
21
23
|
require "govspeak/presenters/contact_presenter"
|
24
|
+
require "govspeak/presenters/embed_presenter"
|
22
25
|
require "govspeak/presenters/h_card_presenter"
|
23
26
|
require "govspeak/presenters/image_presenter"
|
24
27
|
require "govspeak/presenters/attachment_image_presenter"
|
@@ -37,7 +40,7 @@ module Govspeak
|
|
37
40
|
@extensions = []
|
38
41
|
|
39
42
|
attr_accessor :images
|
40
|
-
attr_reader :attachments, :contacts, :links, :locale
|
43
|
+
attr_reader :attachments, :contacts, :links, :locale, :embeds
|
41
44
|
|
42
45
|
def self.to_html(source, options = {})
|
43
46
|
new(source, options).to_html
|
@@ -57,6 +60,7 @@ module Govspeak
|
|
57
60
|
@attachments = Array.wrap(options.delete(:attachments))
|
58
61
|
@links = Array.wrap(options.delete(:links))
|
59
62
|
@contacts = Array.wrap(options.delete(:contacts))
|
63
|
+
@embeds = Array.wrap(options.delete(:embeds))
|
60
64
|
@locale = options.fetch(:locale, "en")
|
61
65
|
@options = { input: PARSER_CLASS_NAME,
|
62
66
|
sanitize: true,
|
@@ -255,6 +259,13 @@ module Govspeak
|
|
255
259
|
render_image(AttachmentImagePresenter.new(attachment))
|
256
260
|
end
|
257
261
|
|
262
|
+
extension("embeds", Govspeak::EmbeddedContent::EMBED_REGEX) do |_embed_code, _document_type, content_id|
|
263
|
+
embed = embeds.detect { |e| e[:content_id] == content_id }
|
264
|
+
next "" unless embed
|
265
|
+
|
266
|
+
EmbedPresenter.new(embed).render
|
267
|
+
end
|
268
|
+
|
258
269
|
# As of version 1.12.0 of Kramdown the block elements (div & figcaption)
|
259
270
|
# inside this html block will have it's < > converted into HTML Entities
|
260
271
|
# when ever this code is used inside block level elements.
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class EmbedExtractorTest < Minitest::Test
|
4
|
+
extend Minitest::Spec::DSL
|
5
|
+
|
6
|
+
describe "EmbedExtractor" do
|
7
|
+
subject { Govspeak::EmbedExtractor.new(document) }
|
8
|
+
|
9
|
+
describe "when there is no embedded content" do
|
10
|
+
let(:document) { "foo" }
|
11
|
+
|
12
|
+
describe "#content_references" do
|
13
|
+
it "returns an empty array" do
|
14
|
+
assert_equal [], subject.content_references
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#content_ids" do
|
19
|
+
it "returns an empty array" do
|
20
|
+
assert_equal [], subject.content_ids
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when there is embedded content" do
|
26
|
+
let(:contact_uuid) { SecureRandom.uuid }
|
27
|
+
let(:content_block_email_address_uuid) { SecureRandom.uuid }
|
28
|
+
|
29
|
+
let(:document) do
|
30
|
+
"""
|
31
|
+
{{embed:contact:#{contact_uuid}}}
|
32
|
+
{{embed:content_block_email_address:#{content_block_email_address_uuid}}}
|
33
|
+
"""
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#content_references" do
|
37
|
+
it "returns all references" do
|
38
|
+
result = subject.content_references
|
39
|
+
|
40
|
+
assert_equal 2, result.count
|
41
|
+
|
42
|
+
assert_equal "contact", result[0].document_type
|
43
|
+
assert_equal contact_uuid, result[0].content_id
|
44
|
+
assert_equal "{{embed:contact:#{contact_uuid}}}", result[0].embed_code
|
45
|
+
|
46
|
+
assert_equal "content_block_email_address", result[1].document_type
|
47
|
+
assert_equal content_block_email_address_uuid, result[1].content_id
|
48
|
+
assert_equal "{{embed:content_block_email_address:#{content_block_email_address_uuid}}}", result[1].embed_code
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#content_ids" do
|
53
|
+
it "returns all uuids as an array" do
|
54
|
+
assert_equal [contact_uuid, content_block_email_address_uuid], subject.content_ids
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class GovspeakEmbedsTest < Minitest::Test
|
4
|
+
extend Minitest::Spec::DSL
|
5
|
+
|
6
|
+
def compress_html(html)
|
7
|
+
html.gsub(/[\n\r]+\s*/, "")
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:content_id) { SecureRandom.uuid }
|
11
|
+
|
12
|
+
it "renders an email address when present in options[:embeds]" do
|
13
|
+
embed = {
|
14
|
+
content_id:,
|
15
|
+
document_type: "content_block_email_address",
|
16
|
+
title: "foo",
|
17
|
+
details: {
|
18
|
+
email_address: "foo@example.com",
|
19
|
+
},
|
20
|
+
}
|
21
|
+
govspeak = "{{embed:content_block_email_address:#{content_id}}}"
|
22
|
+
|
23
|
+
rendered = Govspeak::Document.new(govspeak, embeds: [embed]).to_html
|
24
|
+
|
25
|
+
expected = "<p><span class=\"embed embed-content_block_email_address\" id=\"embed_#{content_id}\">#{embed[:details][:email_address]}</span></p>"
|
26
|
+
|
27
|
+
assert_equal compress_html(expected), compress_html(rendered)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "renders the title when the document type is a contact" do
|
31
|
+
embed = {
|
32
|
+
content_id:,
|
33
|
+
document_type: "contact",
|
34
|
+
title: "foo",
|
35
|
+
}
|
36
|
+
govspeak = "{{embed:contact:#{content_id}}}"
|
37
|
+
|
38
|
+
rendered = Govspeak::Document.new(govspeak, embeds: [embed]).to_html
|
39
|
+
|
40
|
+
expected = "<p><span class=\"embed embed-contact\" id=\"embed_#{content_id}\">#{embed[:title]}</span></p>"
|
41
|
+
|
42
|
+
assert_equal compress_html(expected), compress_html(rendered)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "ignores missing embeds" do
|
46
|
+
govspeak = "{{embed:contact:#{content_id}}}"
|
47
|
+
|
48
|
+
rendered = Govspeak::Document.new(govspeak, embeds: []).to_html
|
49
|
+
|
50
|
+
assert_equal compress_html(""), compress_html(rendered)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "supports multiple embeds" do
|
54
|
+
embeds = [
|
55
|
+
{
|
56
|
+
content_id: SecureRandom.uuid,
|
57
|
+
document_type: "contact",
|
58
|
+
title: "foo",
|
59
|
+
},
|
60
|
+
{
|
61
|
+
content_id: SecureRandom.uuid,
|
62
|
+
document_type: "content_block_email_address",
|
63
|
+
title: "foo",
|
64
|
+
details: {
|
65
|
+
email_address: "foo@example.com",
|
66
|
+
},
|
67
|
+
},
|
68
|
+
]
|
69
|
+
|
70
|
+
govspeak = %(Here is a contact: {{embed:contact:#{embeds[0][:content_id]}}}
|
71
|
+
|
72
|
+
Here is an email address: {{embed:content_block_email_address:#{embeds[1][:content_id]}}}
|
73
|
+
)
|
74
|
+
|
75
|
+
rendered = Govspeak::Document.new(govspeak, embeds:).to_html
|
76
|
+
|
77
|
+
expected = """
|
78
|
+
<p>Here is a contact: <span class=\"embed embed-contact\" id=\"embed_#{embeds[0][:content_id]}\">#{embeds[0][:title]}</span></p>
|
79
|
+
<p>Here is an email address: <span class=\"embed embed-content_block_email_address\" id=\"embed_#{embeds[1][:content_id]}\">#{embeds[1][:details][:email_address]}</span></p>
|
80
|
+
"""
|
81
|
+
|
82
|
+
assert_equal compress_html(expected), compress_html(rendered)
|
83
|
+
end
|
84
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govspeak
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.
|
4
|
+
version: 8.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GOV.UK Dev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionview
|
@@ -250,6 +250,8 @@ files:
|
|
250
250
|
- config/address_formats.yml
|
251
251
|
- lib/govspeak.rb
|
252
252
|
- lib/govspeak/blockquote_extra_quote_remover.rb
|
253
|
+
- lib/govspeak/embed_extractor.rb
|
254
|
+
- lib/govspeak/embedded_content.rb
|
253
255
|
- lib/govspeak/header_extractor.rb
|
254
256
|
- lib/govspeak/html_sanitizer.rb
|
255
257
|
- lib/govspeak/html_validator.rb
|
@@ -258,6 +260,7 @@ files:
|
|
258
260
|
- lib/govspeak/presenters/attachment_image_presenter.rb
|
259
261
|
- lib/govspeak/presenters/attachment_presenter.rb
|
260
262
|
- lib/govspeak/presenters/contact_presenter.rb
|
263
|
+
- lib/govspeak/presenters/embed_presenter.rb
|
261
264
|
- lib/govspeak/presenters/h_card_presenter.rb
|
262
265
|
- lib/govspeak/presenters/image_presenter.rb
|
263
266
|
- lib/govspeak/structured_header_extractor.rb
|
@@ -306,12 +309,14 @@ files:
|
|
306
309
|
- locales/zh-tw.yml
|
307
310
|
- locales/zh.yml
|
308
311
|
- test/blockquote_extra_quote_remover_test.rb
|
312
|
+
- test/embed_extractor_test.rb
|
309
313
|
- test/govspeak_attachment_link_test.rb
|
310
314
|
- test/govspeak_attachment_test.rb
|
311
315
|
- test/govspeak_attachments_image_test.rb
|
312
316
|
- test/govspeak_attachments_inline_test.rb
|
313
317
|
- test/govspeak_button_test.rb
|
314
318
|
- test/govspeak_contacts_test.rb
|
319
|
+
- test/govspeak_embeds_test.rb
|
315
320
|
- test/govspeak_extract_contact_content_ids_test.rb
|
316
321
|
- test/govspeak_footnote_test.rb
|
317
322
|
- test/govspeak_images_bang_test.rb
|
@@ -344,18 +349,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
344
349
|
- !ruby/object:Gem::Version
|
345
350
|
version: '0'
|
346
351
|
requirements: []
|
347
|
-
rubygems_version: 3.5.
|
352
|
+
rubygems_version: 3.5.22
|
348
353
|
signing_key:
|
349
354
|
specification_version: 4
|
350
355
|
summary: Markup language for single domain
|
351
356
|
test_files:
|
352
357
|
- test/blockquote_extra_quote_remover_test.rb
|
358
|
+
- test/embed_extractor_test.rb
|
353
359
|
- test/govspeak_attachment_link_test.rb
|
354
360
|
- test/govspeak_attachment_test.rb
|
355
361
|
- test/govspeak_attachments_image_test.rb
|
356
362
|
- test/govspeak_attachments_inline_test.rb
|
357
363
|
- test/govspeak_button_test.rb
|
358
364
|
- test/govspeak_contacts_test.rb
|
365
|
+
- test/govspeak_embeds_test.rb
|
359
366
|
- test/govspeak_extract_contact_content_ids_test.rb
|
360
367
|
- test/govspeak_footnote_test.rb
|
361
368
|
- test/govspeak_images_bang_test.rb
|