govspeak 5.9.1 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +1 -13
- data/lib/govspeak.rb +19 -34
- data/lib/govspeak/html_sanitizer.rb +2 -5
- data/lib/govspeak/html_validator.rb +1 -1
- data/lib/govspeak/post_processor.rb +19 -5
- data/lib/govspeak/template_renderer.rb +27 -0
- data/lib/govspeak/version.rb +1 -1
- data/lib/templates/contact.html.erb +1 -1
- data/test/govspeak_test.rb +5 -5
- data/test/html_sanitizer_test.rb +1 -6
- metadata +18 -35
- data/bin/govspeak +0 -8
- data/lib/govspeak/cli.rb +0 -53
- data/lib/templates/inline_attachment.html.erb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93b2022644e3af2c929faf57f33c9fe70680977e599bde24d59c71ee20402713
|
4
|
+
data.tar.gz: 7dec8938eedb2183514c54665dd9609f130ac535fbb336739f0f8b6e3d528bc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b96f54ac8cfdf3e0595cb2de3bc205df86c7efc9869c4e9d06f22623067f4e114d878e9f31c72817d76657b9d759e0b3344ae87724db8394a5a79a727765407
|
7
|
+
data.tar.gz: 9fc03735199e9fe6016ffe1196e57eac617a744c7aaa3421fc1a57a4ba53190c3dc85c5dda7f76b202aaf29c7c5da51f47ed0fcf71ff43a5b504097bcf8b6ebb
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 6.0.0
|
2
|
+
|
3
|
+
* BREAKING CHANGE: Input is sanitized by default, to use unsafe HTML initialize with a sanitize option of false
|
4
|
+
* Allow sanitize option on remove invalid HTML from source input
|
5
|
+
* BREAKING CHANGE: Remove `to_sanitized_html` method in favour of `sanitize` option on initialize
|
6
|
+
* BREAKING CHANGE: Remove `to_sanitized_html_without_images` as no apps use this anymore
|
7
|
+
* BREAKING CHANGE: Remove CLI usage
|
8
|
+
|
1
9
|
## 5.9.1
|
2
10
|
|
3
11
|
* Don't render `[Image: {file-name}]` within a paragraph to avoid invalid HTML
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ Install the gem
|
|
8
8
|
|
9
9
|
or add it to your Gemfile
|
10
10
|
|
11
|
-
gem "govspeak"
|
11
|
+
gem "govspeak"
|
12
12
|
|
13
13
|
then create a new document
|
14
14
|
|
@@ -18,18 +18,6 @@ then create a new document
|
|
18
18
|
doc = Govspeak::Document.new "^Test^"
|
19
19
|
puts doc.to_html
|
20
20
|
|
21
|
-
or alternatively, run it from the command line
|
22
|
-
|
23
|
-
$ govspeak "render-me"
|
24
|
-
$ govspeak --file render-me.md
|
25
|
-
$ echo "render-me" | govspeak
|
26
|
-
|
27
|
-
options can be passed in through `--options` as a string of JSON or a file
|
28
|
-
of JSON can be passed in as `--options-file options.json`.
|
29
|
-
|
30
|
-
if installed via bundler prefix commands with bundle exec eg `$ bundle exec govspeak "render-me"`
|
31
|
-
|
32
|
-
|
33
21
|
# Extensions
|
34
22
|
|
35
23
|
In addition to the [standard Markdown syntax](http://daringfireball.net/projects/markdown/syntax "Markdown syntax"), we have added our own extensions.
|
data/lib/govspeak.rb
CHANGED
@@ -13,6 +13,7 @@ require 'govspeak/kramdown_overrides'
|
|
13
13
|
require 'govspeak/blockquote_extra_quote_remover'
|
14
14
|
require 'govspeak/post_processor'
|
15
15
|
require 'govspeak/link_extractor'
|
16
|
+
require 'govspeak/template_renderer'
|
16
17
|
require 'govspeak/presenters/attachment_presenter'
|
17
18
|
require 'govspeak/presenters/contact_presenter'
|
18
19
|
require 'govspeak/presenters/h_card_presenter'
|
@@ -47,41 +48,32 @@ module Govspeak
|
|
47
48
|
def initialize(source, options = {})
|
48
49
|
options = options.dup.deep_symbolize_keys
|
49
50
|
@source = source ? source.dup : ""
|
51
|
+
|
50
52
|
@images = options.delete(:images) || []
|
51
53
|
@attachments = Array.wrap(options.delete(:attachments))
|
52
54
|
@links = Array.wrap(options.delete(:links))
|
53
55
|
@contacts = Array.wrap(options.delete(:contacts))
|
54
56
|
@locale = options.fetch(:locale, "en")
|
55
|
-
@options = { input: PARSER_CLASS_NAME }.merge(options)
|
57
|
+
@options = { input: PARSER_CLASS_NAME, sanitize: true }.merge(options)
|
56
58
|
@options[:entity_output] = :symbolic
|
57
59
|
end
|
58
60
|
|
59
61
|
def to_html
|
60
|
-
@to_html ||=
|
62
|
+
@to_html ||= begin
|
63
|
+
html = if @options[:sanitize]
|
64
|
+
HtmlSanitizer.new(kramdown_doc.to_html).sanitize
|
65
|
+
else
|
66
|
+
kramdown_doc.to_html
|
67
|
+
end
|
68
|
+
|
69
|
+
Govspeak::PostProcessor.process(html, self)
|
70
|
+
end
|
61
71
|
end
|
62
72
|
|
63
73
|
def to_liquid
|
64
74
|
to_html
|
65
75
|
end
|
66
76
|
|
67
|
-
def t(*args)
|
68
|
-
options = args.last.is_a?(Hash) ? args.last.dup : {}
|
69
|
-
key = args.shift
|
70
|
-
I18n.t!(key, options.merge(locale: locale))
|
71
|
-
end
|
72
|
-
|
73
|
-
def format_with_html_line_breaks(string)
|
74
|
-
ERB::Util.html_escape(string || "").strip.gsub(/(?:\r?\n)/, "<br/>").html_safe
|
75
|
-
end
|
76
|
-
|
77
|
-
def to_sanitized_html
|
78
|
-
HtmlSanitizer.new(to_html).sanitize
|
79
|
-
end
|
80
|
-
|
81
|
-
def to_sanitized_html_without_images
|
82
|
-
HtmlSanitizer.new(to_html).sanitize_without_images
|
83
|
-
end
|
84
|
-
|
85
77
|
def to_text
|
86
78
|
HTMLEntities.new.decode(to_html.gsub(/(?:<[^>]+>|\s)+/, " ").strip)
|
87
79
|
end
|
@@ -225,13 +217,11 @@ module Govspeak
|
|
225
217
|
render_image(ImagePresenter.new(image))
|
226
218
|
end
|
227
219
|
|
228
|
-
extension('attachment', /\[embed:attachments:(?!inline:|image:)\s*(.*?)\s*\]/) do |content_id
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
attachment =
|
233
|
-
content = File.read(__dir__ + '/templates/attachment.html.erb')
|
234
|
-
ERB.new(content).result(binding)
|
220
|
+
extension('attachment', /\[embed:attachments:(?!inline:|image:)\s*(.*?)\s*\]/) do |content_id|
|
221
|
+
# not treating this as a self closing tag seems to avoid some oddities
|
222
|
+
# such as an extra new line being inserted when explicitly closed or
|
223
|
+
# swallowing subsequent elements when not closed
|
224
|
+
%{<govspeak-embed-attachment content-id="#{content_id}"></govspeak-embed-attachment>}
|
235
225
|
end
|
236
226
|
|
237
227
|
extension('attachment inline', /\[embed:attachments:inline:\s*(.*?)\s*\]/) do |content_id|
|
@@ -353,9 +343,8 @@ module Govspeak
|
|
353
343
|
contact = contacts.detect { |c| c[:content_id] == content_id }
|
354
344
|
next "" unless contact
|
355
345
|
|
356
|
-
|
357
|
-
|
358
|
-
@renderer.result(binding)
|
346
|
+
renderer = TemplateRenderer.new('contact.html.erb', locale)
|
347
|
+
renderer.render(contact: ContactPresenter.new(contact))
|
359
348
|
end
|
360
349
|
|
361
350
|
extension('Image', /#{NEW_PARAGRAPH_LOOKBEHIND}\[Image:\s*(.*?)\s*\]/) do |image_id|
|
@@ -374,10 +363,6 @@ module Govspeak
|
|
374
363
|
def encode(text)
|
375
364
|
HTMLEntities.new.encode(text)
|
376
365
|
end
|
377
|
-
|
378
|
-
def render_hcard_address(contact_address)
|
379
|
-
HCardPresenter.new(contact_address).render
|
380
|
-
end
|
381
366
|
end
|
382
367
|
end
|
383
368
|
|
@@ -49,11 +49,6 @@ class Govspeak::HtmlSanitizer
|
|
49
49
|
Sanitize.clean(@dirty_html, Sanitize::Config.merge(sanitize_config, transformers: transformers))
|
50
50
|
end
|
51
51
|
|
52
|
-
def sanitize_without_images
|
53
|
-
config = sanitize_config
|
54
|
-
Sanitize.clean(@dirty_html, Sanitize::Config.merge(config, elements: config[:elements] - %w[img]))
|
55
|
-
end
|
56
|
-
|
57
52
|
def button_sanitize_config
|
58
53
|
[
|
59
54
|
"data-module",
|
@@ -65,11 +60,13 @@ class Govspeak::HtmlSanitizer
|
|
65
60
|
def sanitize_config
|
66
61
|
Sanitize::Config.merge(
|
67
62
|
Sanitize::Config::RELAXED,
|
63
|
+
elements: Sanitize::Config::RELAXED[:elements] + %w[govspeak-embed-attachment],
|
68
64
|
attributes: {
|
69
65
|
:all => Sanitize::Config::RELAXED[:attributes][:all] + ["role", "aria-label"],
|
70
66
|
"a" => Sanitize::Config::RELAXED[:attributes]["a"] + button_sanitize_config,
|
71
67
|
"th" => Sanitize::Config::RELAXED[:attributes]["th"] + %w[style],
|
72
68
|
"td" => Sanitize::Config::RELAXED[:attributes]["td"] + %w[style],
|
69
|
+
"govspeak-embed-attachment" => %w[content-id],
|
73
70
|
}
|
74
71
|
)
|
75
72
|
end
|
@@ -8,8 +8,8 @@ module Govspeak
|
|
8
8
|
@extensions
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.process(html)
|
12
|
-
new(html).output
|
11
|
+
def self.process(html, govspeak_document)
|
12
|
+
new(html, govspeak_document).output
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.extension(title, &block)
|
@@ -49,10 +49,25 @@ module Govspeak
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
|
52
|
+
extension("embed attachment HTML") do |document|
|
53
|
+
document.css("govspeak-embed-attachment").map do |el|
|
54
|
+
attachment = govspeak_document.attachments.detect { |a| a[:content_id] == el["content-id"] }
|
55
|
+
unless attachment
|
56
|
+
el.remove
|
57
|
+
next
|
58
|
+
end
|
53
59
|
|
54
|
-
|
60
|
+
renderer = TemplateRenderer.new('attachment.html.erb', govspeak_document.locale)
|
61
|
+
attachment_html = renderer.render(attachment: AttachmentPresenter.new(attachment))
|
62
|
+
el.swap(attachment_html)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_reader :input, :govspeak_document
|
67
|
+
|
68
|
+
def initialize(html, govspeak_document)
|
55
69
|
@input = html
|
70
|
+
@govspeak_document = govspeak_document
|
56
71
|
end
|
57
72
|
|
58
73
|
def output
|
@@ -63,7 +78,6 @@ module Govspeak
|
|
63
78
|
document.to_html
|
64
79
|
end
|
65
80
|
|
66
|
-
|
67
81
|
private
|
68
82
|
|
69
83
|
def nokogiri_document
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Govspeak
|
2
|
+
class TemplateRenderer
|
3
|
+
attr_reader :template, :locale
|
4
|
+
|
5
|
+
def initialize(template, locale)
|
6
|
+
@template = template
|
7
|
+
@locale = locale
|
8
|
+
end
|
9
|
+
|
10
|
+
def render(locals)
|
11
|
+
template_binding = binding
|
12
|
+
locals.each { |k, v| template_binding.local_variable_set(k, v) }
|
13
|
+
erb = ERB.new(File.read(__dir__ + "/../templates/#{template}"))
|
14
|
+
erb.result(template_binding)
|
15
|
+
end
|
16
|
+
|
17
|
+
def t(*args)
|
18
|
+
options = args.last.is_a?(Hash) ? args.last.dup : {}
|
19
|
+
key = args.shift
|
20
|
+
I18n.t!(key, options.merge(locale: locale))
|
21
|
+
end
|
22
|
+
|
23
|
+
def format_with_html_line_breaks(string)
|
24
|
+
ERB::Util.html_escape(string || "").strip.gsub(/(?:\r?\n)/, "<br/>").html_safe
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/govspeak/version.rb
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
<h3><%= contact.title %></h3>
|
8
8
|
<div class="vcard contact-inner">
|
9
9
|
<% contact.post_addresses.each do |address| %>
|
10
|
-
<%=
|
10
|
+
<%= Govspeak::HCardPresenter.new(address).render %>
|
11
11
|
<% end %>
|
12
12
|
<% if contact.email_addresses.any? || contact.phone_numbers.any? || contact.contact_form_links.any? %>
|
13
13
|
<div class="email-url-number">
|
data/test/govspeak_test.rb
CHANGED
@@ -632,14 +632,14 @@ Teston
|
|
632
632
|
}
|
633
633
|
end
|
634
634
|
|
635
|
-
test
|
635
|
+
test 'sanitize source input by default' do
|
636
636
|
document = Govspeak::Document.new("<script>doBadThings();</script>")
|
637
|
-
assert_equal "
|
637
|
+
assert_equal "", document.to_html.strip
|
638
638
|
end
|
639
639
|
|
640
|
-
test
|
641
|
-
document = Govspeak::Document.new("<script>
|
642
|
-
assert_equal "
|
640
|
+
test 'it can have sanitizing disabled' do
|
641
|
+
document = Govspeak::Document.new("<script>doGoodThings();</script>", sanitize: false)
|
642
|
+
assert_equal "<script>doGoodThings();</script>", document.to_html.strip
|
643
643
|
end
|
644
644
|
|
645
645
|
test "identifies a Govspeak document containing malicious HTML as invalid" do
|
data/test/html_sanitizer_test.rb
CHANGED
@@ -3,7 +3,7 @@ require "test_helper"
|
|
3
3
|
class HtmlSanitizerTest < Minitest::Test
|
4
4
|
test "disallow a script tag" do
|
5
5
|
html = "<script>alert('XSS')</script>"
|
6
|
-
assert_equal "
|
6
|
+
assert_equal "", Govspeak::HtmlSanitizer.new(html).sanitize
|
7
7
|
end
|
8
8
|
|
9
9
|
test "disallow a javascript protocol in an attribute" do
|
@@ -46,11 +46,6 @@ class HtmlSanitizerTest < Minitest::Test
|
|
46
46
|
assert_equal "", Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ['allowed.com']).sanitize
|
47
47
|
end
|
48
48
|
|
49
|
-
test "can strip images" do
|
50
|
-
html = "<img src='http://example.com/image.jgp'>"
|
51
|
-
assert_equal "", Govspeak::HtmlSanitizer.new(html).sanitize_without_images
|
52
|
-
end
|
53
|
-
|
54
49
|
test "allows table cells and table headings without a style attribute" do
|
55
50
|
html = "<table><thead><tr><th>thing</th></tr></thead><tbody><tr><td>thing</td></tr></tbody></table>"
|
56
51
|
assert_equal html, Govspeak::HtmlSanitizer.new(html).sanitize
|
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:
|
4
|
+
version: 6.0.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: 2019-03-
|
11
|
+
date: 2019-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionview
|
@@ -44,20 +44,6 @@ dependencies:
|
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '3'
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: commander
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - "~>"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '4.4'
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - "~>"
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '4.4'
|
61
47
|
- !ruby/object:Gem::Dependency
|
62
48
|
name: htmlentities
|
63
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -148,14 +134,14 @@ dependencies:
|
|
148
134
|
requirements:
|
149
135
|
- - "~>"
|
150
136
|
- !ruby/object:Gem::Version
|
151
|
-
version: '
|
137
|
+
version: '5'
|
152
138
|
type: :runtime
|
153
139
|
prerelease: false
|
154
140
|
version_requirements: !ruby/object:Gem::Requirement
|
155
141
|
requirements:
|
156
142
|
- - "~>"
|
157
143
|
- !ruby/object:Gem::Version
|
158
|
-
version: '
|
144
|
+
version: '5'
|
159
145
|
- !ruby/object:Gem::Dependency
|
160
146
|
name: govuk-lint
|
161
147
|
requirement: !ruby/object:Gem::Requirement
|
@@ -245,8 +231,7 @@ description: |-
|
|
245
231
|
library for use in the UK Government Single Domain project
|
246
232
|
email:
|
247
233
|
- govuk-dev@digital.cabinet-office.gov.uk
|
248
|
-
executables:
|
249
|
-
- govspeak
|
234
|
+
executables: []
|
250
235
|
extensions: []
|
251
236
|
extra_rdoc_files: []
|
252
237
|
files:
|
@@ -258,11 +243,9 @@ files:
|
|
258
243
|
- assets/example.png
|
259
244
|
- assets/information_callout.png
|
260
245
|
- assets/warning_callout.png
|
261
|
-
- bin/govspeak
|
262
246
|
- config/address_formats.yml
|
263
247
|
- lib/govspeak.rb
|
264
248
|
- lib/govspeak/blockquote_extra_quote_remover.rb
|
265
|
-
- lib/govspeak/cli.rb
|
266
249
|
- lib/govspeak/header_extractor.rb
|
267
250
|
- lib/govspeak/html_sanitizer.rb
|
268
251
|
- lib/govspeak/html_validator.rb
|
@@ -275,11 +258,11 @@ files:
|
|
275
258
|
- lib/govspeak/presenters/h_card_presenter.rb
|
276
259
|
- lib/govspeak/presenters/image_presenter.rb
|
277
260
|
- lib/govspeak/structured_header_extractor.rb
|
261
|
+
- lib/govspeak/template_renderer.rb
|
278
262
|
- lib/govspeak/version.rb
|
279
263
|
- lib/kramdown/parser/kramdown_with_automatic_external_links.rb
|
280
264
|
- lib/templates/attachment.html.erb
|
281
265
|
- lib/templates/contact.html.erb
|
282
|
-
- lib/templates/inline_attachment.html.erb
|
283
266
|
- locales/ar.yml
|
284
267
|
- locales/be.yml
|
285
268
|
- locales/bg.yml
|
@@ -364,21 +347,21 @@ signing_key:
|
|
364
347
|
specification_version: 4
|
365
348
|
summary: Markup language for single domain
|
366
349
|
test_files:
|
367
|
-
- test/govspeak_link_extractor_test.rb
|
368
|
-
- test/govspeak_structured_headers_test.rb
|
369
|
-
- test/govspeak_images_bang_test.rb
|
370
|
-
- test/govspeak_button_test.rb
|
371
|
-
- test/govspeak_extract_contact_content_ids_test.rb
|
372
350
|
- test/blockquote_extra_quote_remover_test.rb
|
373
351
|
- test/govspeak_test_helper.rb
|
374
|
-
- test/
|
375
|
-
- test/
|
376
|
-
- test/
|
352
|
+
- test/govspeak_structured_headers_test.rb
|
353
|
+
- test/govspeak_attachments_image_test.rb
|
354
|
+
- test/govspeak_attachments_test.rb
|
377
355
|
- test/test_helper.rb
|
378
|
-
- test/html_validator_test.rb
|
379
|
-
- test/html_sanitizer_test.rb
|
380
356
|
- test/govspeak_attachments_inline_test.rb
|
357
|
+
- test/html_sanitizer_test.rb
|
358
|
+
- test/govspeak_button_test.rb
|
359
|
+
- test/govspeak_images_bang_test.rb
|
360
|
+
- test/govspeak_images_test.rb
|
361
|
+
- test/html_validator_test.rb
|
362
|
+
- test/govspeak_extract_contact_content_ids_test.rb
|
381
363
|
- test/govspeak_test.rb
|
382
|
-
- test/
|
383
|
-
- test/
|
364
|
+
- test/govspeak_link_extractor_test.rb
|
365
|
+
- test/govspeak_link_test.rb
|
366
|
+
- test/govspeak_contacts_test.rb
|
384
367
|
- test/presenters/h_card_presenter_test.rb
|
data/bin/govspeak
DELETED
data/lib/govspeak/cli.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'govspeak/version'
|
2
|
-
require 'govspeak'
|
3
|
-
require 'commander'
|
4
|
-
|
5
|
-
module Govspeak
|
6
|
-
class CLI
|
7
|
-
include Commander::Methods
|
8
|
-
|
9
|
-
def run
|
10
|
-
program(:name, 'Govspeak')
|
11
|
-
program(:version, Govspeak::VERSION)
|
12
|
-
program(:description, "A tool for rendering the GOV.UK dialect of markdown into HTML")
|
13
|
-
default_command(:render)
|
14
|
-
command(:render) do |command|
|
15
|
-
command.syntax = "govspeak render [options] <input>"
|
16
|
-
command.description = "Render Govspeak into HTML, can be sourced from stdin, as an argument or from a file"
|
17
|
-
command.option("--file FILENAME", String, "File to render")
|
18
|
-
command.option("--options JSON", String, "JSON to use as options")
|
19
|
-
command.option("--options-file FILENAME", String, "A file of JSON options")
|
20
|
-
command.action do |args, options|
|
21
|
-
input = get_input($stdin, args, options)
|
22
|
-
raise "Nothing to render. Use --help for assistance" unless input
|
23
|
-
|
24
|
-
puts Govspeak::Document.new(input, govspeak_options(options)).to_html
|
25
|
-
end
|
26
|
-
end
|
27
|
-
run!
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def get_input(stdin, args, options)
|
33
|
-
return stdin.read unless stdin.tty?
|
34
|
-
return read_file(options.file) if options.file
|
35
|
-
|
36
|
-
args.empty? ? nil : args.join(" ")
|
37
|
-
end
|
38
|
-
|
39
|
-
def read_file(file_path)
|
40
|
-
path = Pathname.new(file_path).realpath
|
41
|
-
File.read(path)
|
42
|
-
end
|
43
|
-
|
44
|
-
def govspeak_options(command_options)
|
45
|
-
string = if command_options.options_file
|
46
|
-
read_file(command_options.options_file)
|
47
|
-
else
|
48
|
-
command_options.options
|
49
|
-
end
|
50
|
-
string ? JSON.parse(string) : {}
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,6 +0,0 @@
|
|
1
|
-
<span <% if attachment.id %>id="attachment_<%= attachment.id %>" <% end %>class="attachment-inline">
|
2
|
-
<%= attachment.link attachment.title, attachment.url %>
|
3
|
-
<% unless attachment.attachment_attributes.empty? %>
|
4
|
-
(<%= attachment.attachment_attributes %>)
|
5
|
-
<% end %>
|
6
|
-
</span>
|