slimmer 11.1.1 → 13.2.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.
Files changed (34) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +1 -50
  4. data/Rakefile +1 -1
  5. data/lib/slimmer.rb +1 -9
  6. data/lib/slimmer/app.rb +19 -17
  7. data/lib/slimmer/cucumber.rb +0 -7
  8. data/lib/slimmer/headers.rb +14 -18
  9. data/lib/slimmer/processors/body_inserter.rb +2 -2
  10. data/lib/slimmer/processors/conditional_comment_mover.rb +0 -2
  11. data/lib/slimmer/processors/footer_remover.rb +1 -1
  12. data/lib/slimmer/processors/header_context_inserter.rb +3 -3
  13. data/lib/slimmer/processors/metadata_inserter.rb +1 -1
  14. data/lib/slimmer/processors/navigation_mover.rb +0 -1
  15. data/lib/slimmer/processors/search_parameter_inserter.rb +1 -1
  16. data/lib/slimmer/processors/search_path_setter.rb +1 -1
  17. data/lib/slimmer/processors/search_remover.rb +1 -1
  18. data/lib/slimmer/processors/tag_mover.rb +16 -9
  19. data/lib/slimmer/processors/title_inserter.rb +2 -2
  20. data/lib/slimmer/rspec.rb +0 -7
  21. data/lib/slimmer/skin.rb +11 -20
  22. data/lib/slimmer/test_templates/header_footer_only.html +2 -0
  23. data/lib/slimmer/test_templates/wrapper.html +2 -0
  24. data/lib/slimmer/version.rb +1 -1
  25. data/lib/tasks/slimmer.rake +1 -1
  26. metadata +7 -16
  27. data/lib/slimmer/component_resolver.rb +0 -26
  28. data/lib/slimmer/govuk_components.rb +0 -57
  29. data/lib/slimmer/i18n_backend.rb +0 -56
  30. data/lib/slimmer/local_component_resolver.rb +0 -19
  31. data/lib/slimmer/local_govuk_components.rb +0 -49
  32. data/lib/slimmer/network_component_resolver.rb +0 -45
  33. data/lib/slimmer/processors/report_a_problem_inserter.rb +0 -32
  34. data/lib/slimmer/test_helpers/govuk_components.rb +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 882c71d5e22c37f0dfe1f0598975f4c19e27ceb9
4
- data.tar.gz: 6c115e9e40c73fa7216316ffe727663eb26f2b8c
2
+ SHA256:
3
+ metadata.gz: 966481420a36ac4cbaf811706d2ae142b9ce1556c6b8be10ca682766cbe8e2e6
4
+ data.tar.gz: 79cb54e5f8d0db751cbc40ff3acd6c573395fec2e13e4bb9e43021b93c69a3a4
5
5
  SHA512:
6
- metadata.gz: 25ec33d5397c26d2392389bf173619c617ad41c8c54f64d7028c575b217f58f9c4104659c4eee671630412c2d367303c442f502d22bd204eed68cb1bbb4d380e
7
- data.tar.gz: aa90a515cae94a8d23d530cf4543be9dba85955ca0421bd59848805803dd7d40d20b9362e2bcb1b009e985ccd898d6bb74b6a6e2b0aa2e07ddcf1e7d98415094
6
+ metadata.gz: cd9b2d065c5cc805cc92f84728fb4990352030ac25ad5f8ad024b5794e90bc52b82c04f08eb1a7adfbd45abef17849e2ae977d95f579f3d184d290af5a9a4d3b
7
+ data.tar.gz: d846dd0e2ce3edcb9503708e0c162e5899530e988abf6513a785bef995cc2193df948718892e3200d4408e3ee79b34aead7a9ccec4af042b6214a98f480444b7
@@ -1,3 +1,28 @@
1
+ # 13.2.0
2
+
3
+ * Upgrade Ruby version to 2.6.5. (#234)
4
+ * Fix linting issues. (#234)
5
+
6
+ # 13.1.0
7
+
8
+ * Add `js-enabled` to body tag of test templates. (#226)
9
+
10
+ # 13.0.0
11
+
12
+ * Drop cache TTL to 60 seconds.
13
+ * BREAKING: Remove the component system, components are now consumed via the [govuk_publishing_components gem](https://github.com/alphagov/govuk_publishing_components)
14
+
15
+ # 12.1.0
16
+
17
+ * Make sure that the metatags defined in the application are inserted at the
18
+ top of the page. This means that third parties will see the custom metatags
19
+ like `og:image` first, and template tags like the default sharing image second (#218)
20
+
21
+ # 12.0.0
22
+
23
+ * Remove the "report a problem" feature. This is now being covered by the
24
+ feedback component (#213)
25
+
1
26
  # 11.1.1
2
27
 
3
28
  * Make the 'Inside Header Inserter' more resillient so that it doesn't throw
data/README.md CHANGED
@@ -15,8 +15,7 @@ Slimmer provides a Railtie so no configuration is necessary.
15
15
 
16
16
  ## Caching
17
17
 
18
- Slimmer makes HTTP requests to `static` for templates, components and locales. These
19
- are cached for 15 minutes. Slimmer uses `Rails.cache` for this.
18
+ Slimmer makes HTTP requests to `static` for templates. These are cached using `Rails.cache`.
20
19
 
21
20
  ## Asset tag helpers
22
21
 
@@ -82,54 +81,6 @@ YourApp::Application.configure do
82
81
  end
83
82
  ```
84
83
 
85
- ## GOV.UK Components
86
-
87
- To use [shared template components](https://govuk-static.herokuapp.com/component-guide) you need to include the GOV.UK component module:
88
-
89
- ```rb
90
- class ApplicationController < ActionController::Base
91
- include Slimmer::GovukComponents
92
- end
93
- ```
94
-
95
- This will make calls out to static when you try and render a partial prefixed with `govuk_component`:
96
-
97
- ```erb
98
- <%= render partial: 'govuk_component/example_component' %>
99
- ```
100
-
101
- You will need a copy of static running for the templates to be loaded from.
102
-
103
- ### Testing components
104
-
105
- In test mode (when `Rails.env.test?` returns `true`), shared components are not
106
- fetched from Static. Instead they are rendered as a dummy tag which contains a
107
- JSON dump of the `locals` - the arguments passed to the component.
108
-
109
- A test helper is included which returns a CSS selector for finding a given
110
- component to assert that it was used. You can make it available in your tests
111
- with:
112
-
113
- ```rb
114
- require 'slimmer/test_helpers/govuk_components'
115
- include Slimmer::TestHelpers::GovukComponents
116
- ```
117
-
118
- And then assert that the component has been used:
119
-
120
- ```rb
121
- page.should have_css(shared_component_selector('metadata'))
122
- ```
123
-
124
- Or look for one of the arguments to the component which will have been
125
- `JSON.dump`ed inside the tag:
126
-
127
- ```rb
128
- within(shared_component_selector('title')) do
129
- expect(page).to have_content(expected_title_text)
130
- end
131
- ```
132
-
133
84
  ### Cucumber
134
85
 
135
86
  Add the following code to features/support:
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ RDoc::Task.new do |rd|
12
12
  end
13
13
 
14
14
  Rake::TestTask.new("test") do |t|
15
- t.ruby_opts << "-rubygems"
15
+ t.ruby_opts << "-rrubygems"
16
16
  t.libs << "test"
17
17
  t.test_files = FileList["test/**/*_test.rb"]
18
18
  t.verbose = true
@@ -7,7 +7,7 @@ require 'slimmer/version'
7
7
  require 'slimmer/railtie' if defined? Rails
8
8
 
9
9
  module Slimmer
10
- CACHE_TTL = 900
10
+ CACHE_TTL = 60
11
11
 
12
12
  def self.cache
13
13
  @cache ||= defined?(Rails) ? Rails.cache : NoCache.new
@@ -27,13 +27,6 @@ module Slimmer
27
27
  autoload :Headers, 'slimmer/headers'
28
28
  autoload :HTTPClient, 'slimmer/http_client'
29
29
 
30
- autoload :GovukComponents, 'slimmer/govuk_components'
31
- autoload :LocalGovukComponents, 'slimmer/local_govuk_components'
32
- autoload :ComponentResolver, 'slimmer/component_resolver'
33
- autoload :NetworkComponentResolver, 'slimmer/network_component_resolver'
34
- autoload :LocalComponentResolver, 'slimmer/local_component_resolver'
35
- autoload :I18nBackend, 'slimmer/i18n_backend'
36
-
37
30
  module Processors
38
31
  autoload :BodyClassCopier, 'slimmer/processors/body_class_copier'
39
32
  autoload :BodyInserter, 'slimmer/processors/body_inserter'
@@ -43,7 +36,6 @@ module Slimmer
43
36
  autoload :HeaderContextInserter, 'slimmer/processors/header_context_inserter'
44
37
  autoload :InsideHeaderInserter, 'slimmer/processors/inside_header_inserter'
45
38
  autoload :NavigationMover, 'slimmer/processors/navigation_mover'
46
- autoload :ReportAProblemInserter, 'slimmer/processors/report_a_problem_inserter'
47
39
  autoload :SearchIndexSetter, 'slimmer/processors/search_index_setter'
48
40
  autoload :SearchPathSetter, 'slimmer/processors/search_path_setter'
49
41
  autoload :SearchParameterInserter, 'slimmer/processors/search_parameter_inserter'
@@ -4,20 +4,21 @@ module Slimmer
4
4
  class App
5
5
  attr_accessor :logger
6
6
 
7
- def initialize(app, *args, &block)
7
+ def initialize(app, *args)
8
8
  options = args.first || {}
9
9
  @app = app
10
10
 
11
11
  logger = options[:logger] || NullLogger.instance
12
12
  self.logger = logger
13
13
  begin
14
- if logger.level == 0 # Log set to debug level
14
+ if logger.level.zero? # Log set to debug level
15
15
  unless options[:enable_debugging]
16
16
  self.logger = logger.dup
17
17
  self.logger.level = 1 # info
18
18
  end
19
19
  end
20
- rescue NoMethodError # In case logger doesn't respond_to? :level
20
+ rescue NoMethodError # rubocop:disable Lint/HandleExceptions
21
+ # In case logger doesn't respond_to? :level
21
22
  end
22
23
 
23
24
  if options.key? :template_path
@@ -60,7 +61,7 @@ module Slimmer
60
61
 
61
62
  def skip_slimmer_param?(env)
62
63
  skip = Rack::Request.new(env).params['skip_slimmer']
63
- skip and skip.to_i > 0
64
+ skip && skip.to_i.positive?
64
65
  end
65
66
 
66
67
  def skip_slimmer_header?(response)
@@ -69,8 +70,9 @@ module Slimmer
69
70
 
70
71
  def s(body)
71
72
  return body.to_s unless body.respond_to?(:each)
73
+
72
74
  b = ""
73
- body.each {|a| b << a }
75
+ body.each { |a| b << a }
74
76
  b
75
77
  end
76
78
 
@@ -87,17 +89,17 @@ module Slimmer
87
89
  GovukRequestId.value = env['HTTP_GOVUK_REQUEST_ID']
88
90
 
89
91
  rewritten_body = case response.status
90
- when 200
91
- @skin.success request, response, s(response.body)
92
- when 403
93
- @skin.error '403', s(response.body), request.env
94
- when 404
95
- @skin.error '404', s(response.body), request.env
96
- when 410
97
- @skin.error '410', s(response.body), request.env
98
- else
99
- @skin.error '500', s(response.body), request.env
100
- end
92
+ when 200
93
+ @skin.success request, response, s(response.body)
94
+ when 403
95
+ @skin.error '403', s(response.body), request.env
96
+ when 404
97
+ @skin.error '404', s(response.body), request.env
98
+ when 410
99
+ @skin.error '410', s(response.body), request.env
100
+ else
101
+ @skin.error '500', s(response.body), request.env
102
+ end
101
103
 
102
104
  rewritten_body = [rewritten_body] unless rewritten_body.respond_to?(:each)
103
105
  response.body = rewritten_body
@@ -107,7 +109,7 @@ module Slimmer
107
109
  end
108
110
 
109
111
  def strip_slimmer_headers(headers)
110
- headers.reject {|k, v| k =~ /\A#{Headers::HEADER_PREFIX}/ }
112
+ headers.reject { |k, _v| k =~ /\A#{Headers::HEADER_PREFIX}/ }
111
113
  end
112
114
  end
113
115
  end
@@ -1,10 +1,3 @@
1
1
  require 'cucumber'
2
2
 
3
3
  require 'slimmer/test'
4
- require 'slimmer/test_helpers/govuk_components'
5
-
6
- World(Slimmer::TestHelpers::GovukComponents)
7
-
8
- Before do
9
- stub_shared_component_locales
10
- end
@@ -5,7 +5,7 @@ module Slimmer
5
5
  InvalidHeader = Class.new(RuntimeError)
6
6
 
7
7
  # @private
8
- HEADER_PREFIX = "X-Slimmer"
8
+ HEADER_PREFIX = "X-Slimmer".freeze
9
9
 
10
10
  # @private
11
11
  SLIMMER_HEADER_MAPPING = {
@@ -13,7 +13,6 @@ module Slimmer
13
13
  format: "Format",
14
14
  page_owner: "Page-Owner",
15
15
  organisations: "Organisations",
16
- report_a_problem: "Report-a-Problem",
17
16
  world_locations: "World-Locations",
18
17
  result_count: "Result-Count",
19
18
  search_parameters: "Search-Parameters",
@@ -21,43 +20,40 @@ module Slimmer
21
20
  skip: "Skip",
22
21
  template: "Template",
23
22
  remove_search: "Remove-Search",
24
- }
23
+ }.freeze
25
24
 
26
25
  # @private
27
- APPLICATION_NAME_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:application_name]}"
26
+ APPLICATION_NAME_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:application_name]}".freeze
28
27
 
29
28
  # @private
30
- FORMAT_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:format]}"
29
+ FORMAT_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:format]}".freeze
31
30
 
32
31
  # @private
33
- ORGANISATIONS_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:organisations]}"
32
+ ORGANISATIONS_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:organisations]}".freeze
34
33
 
35
34
  # @private
36
- REPORT_A_PROBLEM_FORM = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:report_a_problem]}"
35
+ WORLD_LOCATIONS_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:world_locations]}".freeze
37
36
 
38
37
  # @private
39
- WORLD_LOCATIONS_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:world_locations]}"
38
+ PAGE_OWNER_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:page_owner]}".freeze
40
39
 
41
40
  # @private
42
- PAGE_OWNER_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:page_owner]}"
41
+ RESULT_COUNT_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:result_count]}".freeze
43
42
 
44
43
  # @private
45
- RESULT_COUNT_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:result_count]}"
44
+ SEARCH_PATH_HEADER = "#{HEADER_PREFIX}-Search-Path".freeze
46
45
 
47
46
  # @private
48
- SEARCH_PATH_HEADER = "#{HEADER_PREFIX}-Search-Path"
47
+ SEARCH_PARAMETERS_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:search_parameters]}".freeze
49
48
 
50
49
  # @private
51
- SEARCH_PARAMETERS_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:search_parameters]}"
50
+ SKIP_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:skip]}".freeze
52
51
 
53
52
  # @private
54
- SKIP_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:skip]}"
53
+ TEMPLATE_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:template]}".freeze
55
54
 
56
55
  # @private
57
- TEMPLATE_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:template]}"
58
-
59
- # @private
60
- REMOVE_SEARCH_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:remove_search]}"
56
+ REMOVE_SEARCH_HEADER = "#{HEADER_PREFIX}-#{SLIMMER_HEADER_MAPPING[:remove_search]}".freeze
61
57
 
62
58
  # Set the "slimmer headers" to configure the page
63
59
  #
@@ -67,7 +63,6 @@ module Slimmer
67
63
  # @option hash [String] organisations
68
64
  # @option hash [String] page_owner
69
65
  # @option hash [String] remove_search
70
- # @option hash [String] report_a_problem
71
66
  # @option hash [String] result_count
72
67
  # @option hash [String] search_parameters
73
68
  # @option hash [String] section
@@ -76,6 +71,7 @@ module Slimmer
76
71
  # @option hash [String] world_locations
77
72
  def set_slimmer_headers(hash)
78
73
  raise InvalidHeader if (hash.keys - SLIMMER_HEADER_MAPPING.keys).any?
74
+
79
75
  SLIMMER_HEADER_MAPPING.each do |hash_key, header_suffix|
80
76
  value = hash[hash_key]
81
77
  headers["#{HEADER_PREFIX}-#{header_suffix}"] = value.to_s if value
@@ -1,11 +1,11 @@
1
1
  module Slimmer::Processors
2
2
  class BodyInserter
3
- def initialize(source_id='wrapper', destination_id='wrapper')
3
+ def initialize(source_id = 'wrapper', destination_id = 'wrapper')
4
4
  @source_selector = '#' + source_id
5
5
  @destination_selector = '#' + destination_id
6
6
  end
7
7
 
8
- def filter(src,dest)
8
+ def filter(src, dest)
9
9
  body = Nokogiri::HTML.fragment(src.at_css(@source_selector).to_html)
10
10
  dest.at_css(@destination_selector).replace(body)
11
11
  end
@@ -13,5 +13,3 @@ module Slimmer::Processors
13
13
  end
14
14
  end
15
15
  end
16
-
17
-
@@ -1,6 +1,6 @@
1
1
  module Slimmer::Processors
2
2
  class FooterRemover
3
- def filter(src,dest)
3
+ def filter(src, _dest)
4
4
  footer = src.at_css("#footer")
5
5
  footer.remove if footer
6
6
  end
@@ -1,11 +1,11 @@
1
1
  module Slimmer::Processors
2
2
  class HeaderContextInserter
3
- def initialize(path='.header-context')
3
+ def initialize(path = '.header-context')
4
4
  @path = path
5
5
  end
6
6
 
7
- def filter(src,dest)
8
- if dest.at_css(@path) && replacement = src.at_css(@path)
7
+ def filter(src, dest)
8
+ if dest.at_css(@path) && (replacement = src.at_css(@path))
9
9
  header_context = src.fragment(replacement)
10
10
  dest.at_css(@path).replace(header_context)
11
11
  end
@@ -5,7 +5,7 @@ module Slimmer::Processors
5
5
  @app_name = app_name
6
6
  end
7
7
 
8
- def filter(src, dest)
8
+ def filter(_src, dest)
9
9
  head = dest.at_css('head')
10
10
 
11
11
  add_meta_tag('analytics:organisations', @headers[Slimmer::Headers::ORGANISATIONS_HEADER], head)
@@ -1,5 +1,4 @@
1
1
  class Slimmer::Processors::NavigationMover
2
-
3
2
  def initialize(skin)
4
3
  @skin = skin
5
4
  end
@@ -6,7 +6,7 @@ module Slimmer::Processors
6
6
  @response = response
7
7
  end
8
8
 
9
- def filter(content_document, page_template)
9
+ def filter(_content_document, page_template)
10
10
  search_form = page_template.at_css('form#search')
11
11
  if search_parameters && search_form
12
12
  search_parameters.each_pair do |name, value|
@@ -4,7 +4,7 @@ module Slimmer::Processors
4
4
  @response = response
5
5
  end
6
6
 
7
- def filter(content_document, page_template)
7
+ def filter(_content_document, page_template)
8
8
  if search_scope && page_template.at_css('form#search')
9
9
  page_template.at_css('form#search').attributes["action"].value = search_scope
10
10
  end
@@ -4,7 +4,7 @@ module Slimmer::Processors
4
4
  @headers = headers
5
5
  end
6
6
 
7
- def filter(src,dest)
7
+ def filter(_src, dest)
8
8
  if @headers.include?(Slimmer::Headers::REMOVE_SEARCH_HEADER)
9
9
  search = dest.at_css("#global-header #search")
10
10
  search.remove if search
@@ -1,10 +1,10 @@
1
1
  module Slimmer::Processors
2
2
  class TagMover
3
- def filter(src,dest)
4
- move_tags(src, dest, 'script', :dest_node => 'body', :keys => ['src', 'inner_html'])
5
- move_tags(src, dest, 'link', :must_have => ['href'])
6
- move_tags(src, dest, 'meta', :must_have => ['name', 'content'], :keys => ['name', 'content', 'http-equiv'])
7
- move_tags(src, dest, 'meta', :must_have => ['property', 'content'], :keys => ['property', 'content'])
3
+ def filter(src, dest)
4
+ move_tags(src, dest, 'script', dest_node: 'body', keys: %w(src inner_html))
5
+ move_tags(src, dest, 'link', must_have: %w[href])
6
+ move_tags(src, dest, 'meta', must_have: %w(name content), keys: %w[name content http-equiv], insertion_location: :top)
7
+ move_tags(src, dest, 'meta', must_have: %w(property content), keys: %w(property content), insertion_location: :top)
8
8
  end
9
9
 
10
10
  def include_tag?(node, min_attrs)
@@ -12,17 +12,19 @@ module Slimmer::Processors
12
12
  end
13
13
 
14
14
  def tag_fingerprint(node, attrs)
15
- attrs.collect do |attr_name|
15
+ collected_attrs = attrs.collect do |attr_name|
16
16
  if attr_name == 'inner_html'
17
17
  node.content
18
18
  else
19
19
  node.has_attribute?(attr_name) ? node.attr(attr_name) : nil
20
20
  end
21
- end.compact.sort
21
+ end
22
+
23
+ collected_attrs.compact.sort
22
24
  end
23
25
 
24
26
  def wrap_node(src, node)
25
- if node.previous_sibling.to_s =~ /<!--\[if[^\]]+\]><!-->/ and node.next_sibling.to_s == '<!--<![endif]-->'
27
+ if node.previous_sibling.to_s =~ /<!--\[if[^\]]+\]><!-->/ && node.next_sibling.to_s == '<!--<![endif]-->'
26
28
  node = Nokogiri::XML::NodeSet.new(src, [node.previous_sibling, node, node.next_sibling])
27
29
  end
28
30
  node
@@ -40,7 +42,12 @@ module Slimmer::Processors
40
42
  if include_tag?(node, min_attrs) && !already_there.include?(tag_fingerprint(node, comparison_attrs))
41
43
  node = wrap_node(src, node)
42
44
  node.remove
43
- dest.at_xpath("/html/#{dest_node}") << node
45
+
46
+ if opts[:insertion_location] == :top
47
+ dest.at_xpath("/html/#{dest_node}").prepend_child(node)
48
+ else
49
+ dest.at_xpath("/html/#{dest_node}") << node
50
+ end
44
51
  end
45
52
  end
46
53
  end
@@ -1,10 +1,10 @@
1
1
  module Slimmer::Processors
2
2
  class TitleInserter
3
- def filter(src,dest)
3
+ def filter(src, dest)
4
4
  title = src.at_css('head title')
5
5
  head = dest.at_xpath('/html/head')
6
6
  if head && title
7
- insert_title(title,head)
7
+ insert_title(title, head)
8
8
  end
9
9
  end
10
10
 
@@ -2,10 +2,3 @@ require 'rspec/core'
2
2
 
3
3
  require 'slimmer'
4
4
  require 'slimmer/test'
5
- require 'slimmer/test_helpers/govuk_components'
6
-
7
- RSpec.configure do |config|
8
- config.include Slimmer::TestHelpers::GovukComponents
9
-
10
- config.before { stub_shared_component_locales }
11
- end
@@ -10,7 +10,7 @@ module Slimmer
10
10
  @asset_host = options[:asset_host]
11
11
 
12
12
  @logger = options[:logger] || NullLogger.instance
13
- @strict = options[:strict] || (%w{development test}.include?(ENV['RACK_ENV']))
13
+ @strict = options[:strict] || %w{development test}.include?(ENV['RACK_ENV'])
14
14
  end
15
15
 
16
16
  def template(template_name)
@@ -34,15 +34,15 @@ module Slimmer
34
34
  "#{host}templates/#{template_name}.html.erb"
35
35
  end
36
36
 
37
- def report_parse_errors_if_strict!(nokogiri_doc, description_for_error_message)
37
+ def report_parse_errors_if_strict!(nokogiri_doc, _description_for_error_message)
38
38
  nokogiri_doc
39
39
  end
40
40
 
41
41
  def parse_html(html, description_for_error_message)
42
42
  doc = Nokogiri::HTML.parse(html)
43
43
  if strict
44
- errors = doc.errors.select {|e| e.error?}.reject {|e| ignorable?(e)}
45
- if errors.size > 0
44
+ errors = doc.errors.select(&:error?).reject { |e| ignorable?(e) }
45
+ if !errors.empty?
46
46
  error = errors.first
47
47
  message = "In #{description_for_error_message}: '#{error.message}' at line #{error.line} col #{error.column} (code #{error.code}).\n"
48
48
  message << "Add ?skip_slimmer=1 to the url to show the raw backend request.\n\n"
@@ -59,7 +59,7 @@ module Slimmer
59
59
  lines = [""] + html.split("\n")
60
60
  from = [1, error.line - context_size].max
61
61
  to = [lines.size - 1, error.line + context_size].min
62
- context = (from..to).zip(lines[from..to]).map {|lineno, line| "%4d: %s" % [lineno, line] }
62
+ context = (from..to).zip(lines[from..to]).map { |lineno, line| "%4d: %s" % [lineno, line] } # rubocop:disable Style/FormatStringToken
63
63
  marker = " " * (error.column - 1) + "-----v"
64
64
  context.insert(context_size, marker)
65
65
  context.join("\n")
@@ -70,7 +70,7 @@ module Slimmer
70
70
  ignorable_codes.include?(error.code) || error.message.match(/Element script embeds close tag/) || error.message.match(/Unexpected end tag : noscript/)
71
71
  end
72
72
 
73
- def process(processors,body,template, rack_env)
73
+ def process(processors, body, template, _rack_env)
74
74
  logger.debug "Slimmer: starting skinning process"
75
75
  src = parse_html(body.to_s, "backend response")
76
76
  dest = parse_html(template, "template")
@@ -94,27 +94,18 @@ module Slimmer
94
94
  def success(source_request, response, body)
95
95
  wrapper_id = options[:wrapper_id] || 'wrapper'
96
96
 
97
- # The variables set in the source request might not be encoded as UTF-8,
98
- # Unicorn, for instance, will set them to be ASCII. This shouldn't matter
99
- # normally because URI's should have UTF-8 characters percent encoded,
100
- # but not all agents follow this.
101
- request_url = source_request.url.force_encoding(Encoding::UTF_8)
102
97
  processors = [
103
- Processors::TitleInserter.new(),
104
- Processors::TagMover.new(),
98
+ Processors::TitleInserter.new,
99
+ Processors::TagMover.new,
105
100
  Processors::NavigationMover.new(self),
106
- Processors::ConditionalCommentMover.new(),
101
+ Processors::ConditionalCommentMover.new,
107
102
  Processors::BodyInserter.new(wrapper_id),
108
103
  Processors::BodyClassCopier.new,
109
104
  Processors::InsideHeaderInserter.new,
110
- Processors::HeaderContextInserter.new(),
105
+ Processors::HeaderContextInserter.new,
111
106
  Processors::MetadataInserter.new(response, options[:app_name]),
112
107
  Processors::SearchParameterInserter.new(response),
113
108
  Processors::SearchPathSetter.new(response),
114
- Processors::ReportAProblemInserter.new(self,
115
- request_url,
116
- response.headers,
117
- wrapper_id),
118
109
  Processors::SearchRemover.new(response.headers),
119
110
  ]
120
111
 
@@ -124,7 +115,7 @@ module Slimmer
124
115
 
125
116
  def error(template_name, body, rack_env)
126
117
  processors = [
127
- Processors::TitleInserter.new()
118
+ Processors::TitleInserter.new
128
119
  ]
129
120
  process(processors, body, template(template_name), rack_env)
130
121
  end
@@ -3,6 +3,8 @@
3
3
  <title>Test Template</title>
4
4
  </head>
5
5
  <body>
6
+ <script>document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');</script>
7
+
6
8
  <header id="global-header">
7
9
  <div class="header-wrapper"></div>
8
10
  </header>
@@ -3,6 +3,8 @@
3
3
  <title>Test Template</title>
4
4
  </head>
5
5
  <body>
6
+ <script>document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');</script>
7
+
6
8
  <header id="global-header">
7
9
  <div class="header-wrapper"></div>
8
10
  </header>
@@ -1,3 +1,3 @@
1
1
  module Slimmer
2
- VERSION = '11.1.1'
2
+ VERSION = '13.2.0'.freeze
3
3
  end
@@ -6,7 +6,7 @@ namespace :slimmer do
6
6
  path_to_static = "../static/public"
7
7
  path_to_public = "public"
8
8
  commands = ["cd #{path_to_public}"]
9
- dirs_to_link = Dir.glob("../static/public/*") {|f|
9
+ Dir.glob("../static/public/*") { |f|
10
10
  commands << "ln -s #{path_to_static}/#{f}"
11
11
  }
12
12
  commands << ["cd .."]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slimmer
3
3
  version: !ruby/object:Gem::Version
4
- version: 11.1.1
4
+ version: 13.2.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: 2017-09-19 00:00:00.000000000 Z
11
+ date: 2019-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - '='
186
186
  - !ruby/object:Gem::Version
187
- version: 1.18.0
187
+ version: 3.5.0
188
188
  type: :development
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - '='
193
193
  - !ruby/object:Gem::Version
194
- version: 1.18.0
194
+ version: 3.5.0
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: timecop
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -212,14 +212,14 @@ dependencies:
212
212
  requirements:
213
213
  - - "~>"
214
214
  - !ruby/object:Gem::Version
215
- version: 0.5.1
215
+ version: 3.11.5
216
216
  type: :development
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
220
  - - "~>"
221
221
  - !ruby/object:Gem::Version
222
- version: 0.5.1
222
+ version: 3.11.5
223
223
  description: Rack middleware for skinning pages using a specific template
224
224
  email:
225
225
  - govuk-dev@digital.cabinet-office.gov.uk
@@ -234,16 +234,10 @@ files:
234
234
  - bin/render_slimmer_error
235
235
  - lib/slimmer.rb
236
236
  - lib/slimmer/app.rb
237
- - lib/slimmer/component_resolver.rb
238
237
  - lib/slimmer/cucumber.rb
239
- - lib/slimmer/govuk_components.rb
240
238
  - lib/slimmer/govuk_request_id.rb
241
239
  - lib/slimmer/headers.rb
242
240
  - lib/slimmer/http_client.rb
243
- - lib/slimmer/i18n_backend.rb
244
- - lib/slimmer/local_component_resolver.rb
245
- - lib/slimmer/local_govuk_components.rb
246
- - lib/slimmer/network_component_resolver.rb
247
241
  - lib/slimmer/processors/body_class_copier.rb
248
242
  - lib/slimmer/processors/body_inserter.rb
249
243
  - lib/slimmer/processors/conditional_comment_mover.rb
@@ -252,7 +246,6 @@ files:
252
246
  - lib/slimmer/processors/inside_header_inserter.rb
253
247
  - lib/slimmer/processors/metadata_inserter.rb
254
248
  - lib/slimmer/processors/navigation_mover.rb
255
- - lib/slimmer/processors/report_a_problem_inserter.rb
256
249
  - lib/slimmer/processors/search_parameter_inserter.rb
257
250
  - lib/slimmer/processors/search_path_setter.rb
258
251
  - lib/slimmer/processors/search_remover.rb
@@ -263,7 +256,6 @@ files:
263
256
  - lib/slimmer/skin.rb
264
257
  - lib/slimmer/template.rb
265
258
  - lib/slimmer/test.rb
266
- - lib/slimmer/test_helpers/govuk_components.rb
267
259
  - lib/slimmer/test_templates/header_footer_only.html
268
260
  - lib/slimmer/test_templates/proposition_menu.html
269
261
  - lib/slimmer/test_templates/wrapper.html
@@ -289,8 +281,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
289
281
  - !ruby/object:Gem::Version
290
282
  version: '0'
291
283
  requirements: []
292
- rubyforge_project: slimmer
293
- rubygems_version: 2.5.1
284
+ rubygems_version: 3.0.3
294
285
  signing_key:
295
286
  specification_version: 4
296
287
  summary: Thinner than the skinner
@@ -1,26 +0,0 @@
1
- module Slimmer
2
- class ComponentResolver < ::ActionView::Resolver
3
- TEST_TAG_NAME = 'test-govuk-component'
4
-
5
- def find_templates(name, prefix, partial, details, outside_app_allowed = false)
6
- return [] unless prefix == 'govuk_component'
7
- template_path = [prefix, name].join('/')
8
- details = {
9
- :format => 'text/html',
10
- :updated_at => Time.now,
11
- :virtual_path => template_path
12
- }
13
-
14
- [ActionView::Template.new(template_body(template_path), template_path, erb_handler, details)]
15
- end
16
-
17
- private
18
- def erb_handler
19
- @erb_handler ||= ActionView::Template.registered_template_handler(:erb)
20
- end
21
-
22
- def template_body(_template_path)
23
- raise NotImplementedError, "Use NetworkComponentResolver or LocalComponentResolver"
24
- end
25
- end
26
- end
@@ -1,57 +0,0 @@
1
- module Slimmer
2
- # @api public
3
- #
4
- # Include this module to add the GOV.UK Components to your app.
5
- # @example
6
- # class ApplicationController < ActionController::Base
7
- # include Slimmer::GovukComponents
8
- # end
9
- #
10
- # # In your views:
11
- #
12
- # <%= render partial: 'govuk_component/example_component' %>
13
- module GovukComponents
14
- def self.included into
15
- into.before_action :add_govuk_components
16
- end
17
-
18
- # @private
19
- def add_govuk_components
20
- append_view_path GovukComponents.expiring_resolver_cache.resolver
21
-
22
- return if slimmer_backend_included?
23
- I18n.backend = I18n::Backend::Chain.new(I18n.backend, Slimmer::I18nBackend.new)
24
- end
25
-
26
- # @private
27
- def self.expiring_resolver_cache
28
- @expiring_resolver_cache ||= TimedExpirationResolverCache.new
29
- end
30
-
31
- private
32
-
33
- def slimmer_backend_included?
34
- I18n.backend.is_a?(I18n::Backend::Chain) &&
35
- I18n.backend.backends.any? { |b| b.is_a? Slimmer::I18nBackend }
36
- end
37
-
38
- # Slimmer::ComponentResolver instantiates a lot of large objects and leaks
39
- # memory. This class will cache the resolver so that it doesn't have to
40
- # create new ActionView::Template objects for each request. The cache is
41
- # timed to allow frontends to pick up changes made to components in `static`.
42
- class TimedExpirationResolverCache
43
- def initialize
44
- @cache_last_reset = Time.now
45
- end
46
-
47
- def resolver
48
- if (@cache_last_reset + Slimmer::CACHE_TTL) < Time.now
49
- @resolver = nil
50
- @cache_last_reset = Time.now
51
- end
52
-
53
- @resolver ||= Slimmer::NetworkComponentResolver.new
54
- end
55
- end
56
- end
57
- end
@@ -1,56 +0,0 @@
1
- require 'json'
2
- require 'i18n'
3
-
4
- module Slimmer
5
- class I18nBackend
6
- include I18n::Backend::Base, I18n::Backend::Flatten
7
-
8
- def available_locales
9
- Slimmer.cache.fetch("available_locales", expires_in: Slimmer::CACHE_TTL) do
10
- locale_json = fetch(static_locales_url)
11
- JSON.parse(locale_json).map(&:to_sym)
12
- end
13
- end
14
-
15
- def lookup(locale, key, scope = [], options = {})
16
- key = normalize_flat_keys(locale, key, scope, options[:separator])
17
- translations = translations(locale)
18
- translations["#{locale}.#{key}".to_sym]
19
- end
20
-
21
- private
22
-
23
- def translations(locale)
24
- Slimmer.cache.fetch("translations/#{locale}", expires_in: Slimmer::CACHE_TTL) do
25
- fetch_translations(locale)
26
- end
27
- end
28
-
29
- def static_locales_url(locale=nil)
30
- [static_host, "templates", "locales", locale].compact.join('/')
31
- end
32
-
33
- def static_host
34
- @static_host ||= Plek.new.find('static')
35
- end
36
-
37
- def fetch_translations(locale)
38
- url = static_locales_url(locale)
39
- json_data = fetch(url)
40
- translations = JSON.parse(json_data)
41
- flatten_translations(locale, translations, false, false)
42
- rescue TemplateNotFoundException
43
- {}
44
- end
45
-
46
- def fetch(url)
47
- HTTPClient.get(url)
48
- rescue RestClient::Exception => e
49
- raise TemplateNotFoundException, "Unable to fetch: '#{url}' because #{e}", caller
50
- rescue Errno::ECONNREFUSED => e
51
- raise CouldNotRetrieveTemplate, "Unable to fetch: '#{url}' because #{e}", caller
52
- rescue SocketError => e
53
- raise CouldNotRetrieveTemplate, "Unable to fetch: '#{url}' because #{e}", caller
54
- end
55
- end
56
- end
@@ -1,19 +0,0 @@
1
- module Slimmer
2
- class LocalComponentResolver < ComponentResolver
3
- private
4
-
5
- def template_body(template_path)
6
- File.read(template_file(template_path))
7
- end
8
-
9
- def template_file(template_path)
10
- path = template_path.sub(/\.raw(\.html\.erb)?$/, '')
11
-
12
- if defined?(Rails)
13
- Rails.root.join("app", "views", "#{path}.raw.html.erb")
14
- else
15
- "#{path}.raw.html.erb"
16
- end
17
- end
18
- end
19
- end
@@ -1,49 +0,0 @@
1
- module Slimmer
2
- # @api public
3
- #
4
- # Include this module to avoid loading components over the network
5
- # @example
6
- # class ApplicationController < ActionController::Base
7
- # include Slimmer::LocalGovukComponents
8
- # end
9
- #
10
- # # In your views:
11
- #
12
- # <%= render partial: 'govuk_component/example_component' %>
13
- module LocalGovukComponents
14
- def self.included into
15
- into.before_action :add_govuk_components
16
- end
17
-
18
- # @private
19
- def add_govuk_components
20
- append_view_path LocalGovukComponents.expiring_resolver_cache.resolver
21
- end
22
-
23
- # @private
24
- def self.expiring_resolver_cache
25
- @expiring_resolver_cache ||= TimedExpirationResolverCache.new
26
- end
27
-
28
- private
29
-
30
- # Slimmer::ComponentResolver instantiates a lot of large objects and leaks
31
- # memory. This class will cache the resolver so that it doesn't have to
32
- # create new ActionView::Template objects for each request. The cache is
33
- # timed to allow frontends to pick up changes made to components in `static`.
34
- class TimedExpirationResolverCache
35
- def initialize
36
- @cache_last_reset = Time.now
37
- end
38
-
39
- def resolver
40
- if (@cache_last_reset + Slimmer::CACHE_TTL) < Time.now
41
- @resolver = nil
42
- @cache_last_reset = Time.now
43
- end
44
-
45
- @resolver ||= Slimmer::LocalComponentResolver.new
46
- end
47
- end
48
- end
49
- end
@@ -1,45 +0,0 @@
1
- require 'slimmer/govuk_request_id'
2
- require 'active_support/core_ext/string/inflections'
3
-
4
- module Slimmer
5
- class NetworkComponentResolver < ComponentResolver
6
- private
7
-
8
- def template_body(template_path)
9
- if test?
10
- test_body(template_path)
11
- else
12
- Slimmer.cache.fetch(template_path, expires_in: Slimmer::CACHE_TTL) do
13
- fetch(template_url(template_path))
14
- end
15
- end
16
- end
17
-
18
- def test?
19
- defined?(Rails) && Rails.env.test?
20
- end
21
-
22
- def fetch(template_url)
23
- HTTPClient.get(template_url)
24
- rescue RestClient::Exception => e
25
- raise TemplateNotFoundException, "Unable to fetch: '#{template_url}' because #{e}", caller
26
- rescue Errno::ECONNREFUSED => e
27
- raise CouldNotRetrieveTemplate, "Unable to fetch: '#{template_url}' because #{e}", caller
28
- rescue SocketError => e
29
- raise CouldNotRetrieveTemplate, "Unable to fetch: '#{template_url}' because #{e}", caller
30
- end
31
-
32
- def template_url(template_path)
33
- path = template_path.sub(/\.raw(\.html\.erb)?$/, '')
34
- [static_host, "templates", "#{path}.raw.html.erb"].join('/')
35
- end
36
-
37
- def static_host
38
- @static_host ||= Plek.new.find('static')
39
- end
40
-
41
- def test_body(path)
42
- %{<#{TEST_TAG_NAME} data-template="#{path.parameterize}"><%= JSON.dump(local_assigns) %></#{TEST_TAG_NAME}>}
43
- end
44
- end
45
- end
@@ -1,32 +0,0 @@
1
- module Slimmer::Processors
2
- class ReportAProblemInserter
3
- include ERB::Util
4
-
5
- def initialize(skin, url, headers, wrapper_id)
6
- @skin = skin
7
- @request_url = url
8
- @headers = headers
9
- @wrapper_id = wrapper_id
10
- end
11
-
12
- def filter(content_document, page_template)
13
- if enabled? && container = page_template.at_css('#' + @wrapper_id)
14
- container.add_child(report_a_problem_block)
15
- end
16
- end
17
-
18
- def report_a_problem_block
19
- request_url = @request_url
20
- source = @headers[Slimmer::Headers::APPLICATION_NAME_HEADER]
21
- page_owner = @headers[Slimmer::Headers::PAGE_OWNER_HEADER]
22
- report_a_problem_template = @skin.template('report_a_problem.raw')
23
- html = ERB.new(report_a_problem_template).result(binding)
24
- Nokogiri::HTML.fragment(html)
25
- end
26
-
27
- private
28
- def enabled?
29
- @headers[Slimmer::Headers::REPORT_A_PROBLEM_FORM] != 'false'
30
- end
31
- end
32
- end
@@ -1,18 +0,0 @@
1
- require 'webmock'
2
-
3
- module Slimmer
4
- module TestHelpers
5
- module GovukComponents
6
- def stub_shared_component_locales
7
- stub_request(:get, /https?:\/\/\S+.gov.uk\/templates\/locales\/.+/).
8
- to_return(status: 400, headers: {})
9
- stub_request(:get, /https?:\/\/\S+.gov.uk\/templates\/locales/).
10
- to_return(status: 200, body: '{}', headers: {})
11
- end
12
-
13
- def shared_component_selector(name)
14
- "#{Slimmer::ComponentResolver::TEST_TAG_NAME}[data-template='govuk_component-#{name}']"
15
- end
16
- end
17
- end
18
- end