Skip to content

Commit

Permalink
🧬 Sync upstream - alphagov/main
Browse files Browse the repository at this point in the history
  • Loading branch information
Gary-H9 committed Dec 8, 2023
2 parents f645da0 + 207bcb8 commit dd17952
Show file tree
Hide file tree
Showing 31 changed files with 3,089 additions and 245 deletions.
15 changes: 9 additions & 6 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ jobs:
- uses: actions/checkout@v3

- uses: ruby/setup-ruby@v1
with:
ruby-version: '3'

- name: Check if new version to release
id: gem_version
run: |
gem_version=$( ruby -r rubygems -e "puts Gem::Specification::load('govuk_tech_docs.gemspec').version" )
echo "gem_version=${gem_version}" >> ${GITHUB_OUTPUT}
gem_version=$(ruby -r rubygems -e "puts Gem::Specification::load('govuk_tech_docs.gemspec').version")
echo "gem_version=$gem_version" >> "$GITHUB_OUTPUT"
if git fetch origin "refs/tags/v${gem_version}" >/dev/null 2>&1
then
echo "Tag 'v${gem_version}' already exists"
echo "new_version=false" >> ${GITHUB_OUTPUT}
echo "Tag 'v$gem_version' already exists"
echo "new_version=false" >> "$GITHUB_OUTPUT"
else
echo "new_version=true" >> ${GITHUB_OUTPUT}
echo "new_version=true" >> "$GITHUB_OUTPUT"
fi
deploy:
Expand All @@ -49,11 +51,12 @@ jobs:

- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
cache: 'npm'
node-version: '14'

- uses: ruby/setup-ruby@v1
with:
ruby-version: '3'
bundler-cache: true

- name: Publish
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,21 @@ jobs:
name: Test
runs-on: ubuntu-latest

strategy:
matrix:
ruby: ['2.7', '3.2']

steps:
- uses: actions/checkout@v3

- uses: actions/setup-node@v3
with:
node-version: '14'
node-version-file: '.nvmrc'
cache: 'npm'

- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true

- name: Run tests
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
14
18
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ inherit_gem:
rubocop-govuk:
- config/default.yml

AllCops:
TargetRubyVersion: 2.7

Layout/HeredocIndentation:
Enabled: false

Expand Down
1 change: 0 additions & 1 deletion .ruby-version

This file was deleted.

20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,32 @@

## Unreleased

## 3.4.0

### New features

- Footer and header links now work with relative links. Thanks to [@eddgrant](https://github.com/eddgrant) for contributing this feature.

See [pull request #325: Support sites deployed on a path other than "/" when generating header and footer links](https://github.com/alphagov/tech-docs-gem/pull/325) for more details.

### Fixes

- You no longer need to downgrade Haml yourself, `bundle install` will now make sure Haml 6 is not installed (see issue [#318: Error: Filters is not a module](https://github.com/alphagov/tech-docs/gem/issues/318)).

## 3.3.2

_from ministryofjustice_
Added `lib/source/images/govuk-large.png` from `https://github.com/alphagov/govuk-frontend/blob/main/src/govuk/assets/images/govuk-opengraph-image.png`

## 3.3.1

_from alphagov_
This change solves a potential security issue with HTML snippets. Pages indexed in search results have their entire contents indexed, including any HTML code snippets. These HTML snippets would appear in the search results unsanitised, making it possible to render arbitrary HTML or run arbitrary scripts.

You can see more detail about this issue at [#323: Fix XSS vulnerability on search results page](https://github.com/alphagov/tech-docs-gem/pull/323)

_from ministryofjustice_

If your tech-docs live in a directory within a repo (such as `docs`), you can add the following to `config/tech-docs.yml`

```yaml
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
source 'https://rubygems.org'
source "https://rubygems.org"

# Specify your gem's dependencies in govuk_tech_docs.gemspec
gemspec
22 changes: 13 additions & 9 deletions govuk_tech_docs.gemspec
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# coding: utf-8
lib = File.expand_path("../lib", __FILE__)
require "English"

lib = File.expand_path("lib", __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "govuk_tech_docs/version"

`npm install`
abort 'npm install failed' unless $?.success?
abort "npm install failed" unless $CHILD_STATUS.success?

unless File.exist?('node_modules/govuk-frontend/govuk/all.scss')
abort 'govuk-frontend npm package not installed'
unless File.exist?("node_modules/govuk-frontend/govuk/all.scss")
abort "govuk-frontend npm package not installed"
end

Gem::Specification.new do |spec|
Expand All @@ -16,8 +17,8 @@ Gem::Specification.new do |spec|
spec.authors = ["Government Digital Service"]
spec.email = ["[email protected]"]

spec.summary = %q{Gem to distribute the GOV.UK Tech Docs Template}
spec.description = %q{Gem to distribute the GOV.UK Tech Docs Template. See https://github.com/alphagov/tech-docs-gem for the project.}
spec.summary = "Gem to distribute the GOV.UK Tech Docs Template"
spec.description = "Gem to distribute the GOV.UK Tech Docs Template. See https://github.com/alphagov/tech-docs-gem for the project."
spec.homepage = "https://github.com/alphagov/tech-docs-gem"
spec.license = "MIT"

Expand All @@ -30,10 +31,13 @@ Gem::Specification.new do |spec|

spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.require_paths = %w[lib]

spec.required_ruby_version = ">= 2.7.0"

spec.add_dependency "autoprefixer-rails", "~> 10.2"
spec.add_dependency "chronic", "~> 0.10.2"
spec.add_dependency "haml", "< 6.0.0"
spec.add_dependency "middleman", "~> 4.0"
spec.add_dependency "middleman-autoprefixer", "~> 2.10.0"
spec.add_dependency "middleman-compass", ">= 4.0.0"
Expand All @@ -50,5 +54,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "jasmine", "~> 3.5.0"
spec.add_development_dependency "rake", "~> 13.0"
spec.add_development_dependency "rspec", "~> 3.9.0"
spec.add_development_dependency "rubocop-govuk", "~> 3.5.0"
spec.add_development_dependency "rubocop-govuk", "~> 4.10.0"
end
4 changes: 2 additions & 2 deletions lib/assets/javascripts/_modules/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@

this.processContent = function processContent (content, query) {
var output
content = '<div>' + content + '</div>'
content = $(content).mark(query)
var sanitizedContent = $('<div></div>').text(content).html()
content = $('<div>' + sanitizedContent + '</div>').mark(query)

// Split content by sentence.
var sentences = content.html().replace(/(\.+|:|!|\?|\r|\n)("*|'*|\)*|}*|]*)/gm, '|').split('|')
Expand Down
8 changes: 4 additions & 4 deletions lib/govuk_tech_docs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ def format_date(date)
def active_page(page_path)
[
page_path == "/" && current_page.path == "index.html",
("/" + current_page.path) == page_path,
current_page.data.parent != nil && current_page.data.parent.to_s == page_path,
"/#{current_page.path}" == page_path,
!current_page.data.parent.nil? && current_page.data.parent.to_s == page_path,
].any?
end
end
Expand All @@ -109,9 +109,9 @@ def active_page(page_path)
search.resources = [""]

search.fields = {
title: { boost: 100, store: true, required: true },
title: { boost: 100, store: true, required: true },
content: { boost: 50, store: true },
url: { index: false, store: true },
url: { index: false, store: true },
}

search.pipeline_remove = %w[stemmer stopWordFilter]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def initialize(app, options_hash = {}, &block)

def uri?(string)
uri = URI.parse(string)
%w(http https).include?(uri.scheme)
%w[http https].include?(uri.scheme)
rescue URI::BadURIError
false
rescue URI::InvalidURIError
Expand Down
20 changes: 10 additions & 10 deletions lib/govuk_tech_docs/api_reference/api_reference_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,15 @@ def schema_properties(schema_data)
properties.merge!(all_of_schema.properties.to_h)
end

properties.each_with_object({}) do |(name, schema), memo|
memo[name] = case schema.type
when "object"
schema_properties(schema.items || schema)
when "array"
schema.items ? [schema_properties(schema.items)] : []
else
schema.example || schema.type
end
properties.transform_values do |schema|
case schema.type
when "object"
schema_properties(schema.items || schema)
when "array"
schema.items ? [schema_properties(schema.items)] : []
else
schema.example || schema.type
end
end
end

Expand All @@ -144,7 +144,7 @@ def build_redcarpet(app)
end

def get_renderer(file)
template_path = File.join(File.dirname(__FILE__), "templates/" + file)
template_path = File.join(File.dirname(__FILE__), "templates/#{file}")
template = File.open(template_path, "r").read
ERB.new(template)
end
Expand Down
50 changes: 40 additions & 10 deletions lib/govuk_tech_docs/path_helpers.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
require "uri"
module GovukTechDocs
module PathHelpers
def get_path_to_resource(config, resource, current_page)
if config[:relative_links]
resource_path_segments = resource.path.split("/").reject(&:empty?)[0..-2]
resource_file_name = resource.path.split("/")[-1]
# Some useful notes from https://www.rubydoc.info/github/middleman/middleman/Middleman/Sitemap/Resource#url-instance_method :
# 'resource.path' is "The source path of this resource (relative to the source directory, without template extensions)."
# 'resource.destination_path', which is: "The output path in the build directory for this resource."
# 'resource.url' is based on 'resource.destination_path', but is further tweaked to optionally strip the index file and prefixed with any :http_prefix.

path_to_site_root = path_to_site_root config, current_page.path
resource_path = path_to_site_root + resource_path_segments
.push(resource_file_name)
.join("/")
# Calculates the path to the sought resource, taking in to account whether the site has been configured
# to generate relative or absolute links.
# Identifies whether the sought resource is an internal or external target: External targets are returned untouched. Path calculation is performed for internal targets.
# Works for both "Middleman::Sitemap::Resource" resources and plain strings (which may be passed from the site configuration when generating header links).
#
# @param [Object] config
# @param [Object] resource
# @param [Object] current_page
def get_path_to_resource(config, resource, current_page)
if resource.is_a?(Middleman::Sitemap::Resource)
config[:relative_links] ? get_resource_path_relative_to_current_page(config, current_page.path, resource.path) : resource.url
elsif external_url?(resource)
resource
elsif config[:relative_links]
get_resource_path_relative_to_current_page(config, current_page.path, resource)
else
resource_path = resource.url
resource
end
resource_path
end

def path_to_site_root(config, page_path)
Expand All @@ -26,5 +37,24 @@ def path_to_site_root(config, page_path)
end
path_to_site_root
end

private

# Calculates the path to the sought resource, relative to the current page.
# @param [Object] config Middleman config.
# @param [String] current_page path of the current page, from the site root.
# @param [String] resource_path_from_site_root path of the sought resource, from the site root.
def get_resource_path_relative_to_current_page(config, current_page, resource_path_from_site_root)
path_segments = resource_path_from_site_root.split("/").reject(&:empty?)[0..-2]
path_file_name = resource_path_from_site_root.split("/")[-1]

path_to_site_root = path_to_site_root config, current_page
path_to_site_root + path_segments.push(path_file_name).join("/")
end

def external_url?(url)
uri = URI.parse(url)
uri.scheme || uri.to_s.split("/")[0]&.include?(".")
end
end
end
4 changes: 2 additions & 2 deletions lib/govuk_tech_docs/redirects.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module GovukTechDocs
class Redirects
LEADING_SLASH = %r[\A\/].freeze
LEADING_SLASH = %r{\A/}.freeze

def initialize(context)
@context = context
Expand All @@ -11,7 +11,7 @@ def redirects

all_redirects.map do |from, to|
# Middleman needs paths without leading slashes
[from.sub(LEADING_SLASH, ""), to: to.sub(LEADING_SLASH, "")]
[from.sub(LEADING_SLASH, ""), { to: to.sub(LEADING_SLASH, "") }]
end
end

Expand Down
4 changes: 2 additions & 2 deletions lib/govuk_tech_docs/table_of_contents/heading.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ def initialize(element_name:, text:, attributes:, page_url: "")
end

def size
@element_name.scan(/h(\d)/) && $1 && Integer($1)
@element_name.scan(/h(\d)/) && ::Regexp.last_match(1) && Integer(::Regexp.last_match(1))
end

def href
if @page_url != "" && size == 1
@page_url
else
@page_url + "#" + @attributes["id"]
"#{@page_url}##{@attributes['id']}"
end
end

Expand Down
10 changes: 5 additions & 5 deletions lib/govuk_tech_docs/table_of_contents/heading_tree_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ def render_tree(tree, indentation: DEFAULT_INDENTATION, level: nil)
output = ""

if tree.heading
output += indentation + %{<a href="#{tree.heading.href}"><span>#{tree.heading.title}</span></a>\n}
output += indentation + %(<a href="#{tree.heading.href}"><span>#{tree.heading.title}</span></a>\n)
end

if tree.children.any? && level < @max_level
output += indentation + "<ul>\n" unless level.zero?
output += "#{indentation}<ul>\n" unless level.zero?

tree.children.each do |child|
output += indentation + INDENTATION_INCREMENT + "<li>\n"
output += "#{indentation}#{INDENTATION_INCREMENT}<li>\n"
output += render_tree(
child,
indentation: indentation + INDENTATION_INCREMENT * 2,
level: level + 1,
)
output += indentation + INDENTATION_INCREMENT + "</li>\n"
output += "#{indentation}#{INDENTATION_INCREMENT}</li>\n"
end

output += indentation + "</ul>\n" unless level.zero?
output += "#{indentation}</ul>\n" unless level.zero?
end

output
Expand Down
6 changes: 3 additions & 3 deletions lib/govuk_tech_docs/table_of_contents/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def list_items_from_headings(html, url: "", max_level: nil)
headings = HeadingsBuilder.new(html, url).headings

if headings.none? { |heading| heading.size == 1 }
raise "No H1 tag found. You have to at least add one H1 heading to the page: " + url
raise "No H1 tag found. You have to at least add one H1 heading to the page: #{url}"
end

tree = HeadingTreeBuilder.new(headings).tree
Expand Down Expand Up @@ -67,12 +67,12 @@ def render_page_tree(resources, current_page, config, current_page_html)
if config[:http_prefix].end_with?("/")
config[:http_prefix]
else
config[:http_prefix] + "/"
"#{config[:http_prefix]}/"
end

link_value = get_path_to_resource(config, resource, current_page)
if resource.children.any? && resource.url != home_url
output += %{<li><a href="#{link_value}"><span>#{resource.data.title}</span></a>\n}
output += %(<li><a href="#{link_value}"><span>#{resource.data.title}</span></a>\n)
output += render_page_tree(resource.children, current_page, config, current_page_html)
output += "</li>\n"
else
Expand Down
Loading

0 comments on commit dd17952

Please sign in to comment.