diff --git a/example/source/shared-subheadings/page-a.html.md b/example/source/shared-subheadings/page-a.html.md new file mode 100644 index 00000000..037eb3be --- /dev/null +++ b/example/source/shared-subheadings/page-a.html.md @@ -0,0 +1,14 @@ +--- +layout: layout +--- + +# Shared subheadings - Page A + +A page that shares headings with the other pages in this folder, +to check that the heading IDs are computed properly + +## A subheading + +### A h3 subheading + +## Another subheading diff --git a/example/source/shared-subheadings/page-b.html.md b/example/source/shared-subheadings/page-b.html.md new file mode 100644 index 00000000..1acba227 --- /dev/null +++ b/example/source/shared-subheadings/page-b.html.md @@ -0,0 +1,14 @@ +--- +layout: layout +--- + +# Shared subheadings - Page B + +A page that shares headings with the other pages in this folder, +to check that the heading IDs are computed properly + +## A subheading + +### A h3 subheading + +## Another subheading diff --git a/lib/govuk_tech_docs.rb b/lib/govuk_tech_docs.rb index 4cacd978..37843991 100644 --- a/lib/govuk_tech_docs.rb +++ b/lib/govuk_tech_docs.rb @@ -18,7 +18,6 @@ require "govuk_tech_docs/page_review" require "govuk_tech_docs/pages" require "govuk_tech_docs/tech_docs_html_renderer" -require "govuk_tech_docs/unique_identifier_extension" require "govuk_tech_docs/unique_identifier_generator" require "govuk_tech_docs/warning_text_extension" require "govuk_tech_docs/api_reference/api_reference_extension" @@ -62,7 +61,6 @@ def self.configure(context, options = {}) config_file = ENV.fetch("CONFIG_FILE", "config/tech-docs.yml") context.config[:tech_docs] = YAML.load_file(config_file).with_indifferent_access - context.activate :unique_identifier context.activate :warning_text context.activate :api_reference diff --git a/lib/govuk_tech_docs/tech_docs_html_renderer.rb b/lib/govuk_tech_docs/tech_docs_html_renderer.rb index f9f2d614..3eef19e3 100644 --- a/lib/govuk_tech_docs/tech_docs_html_renderer.rb +++ b/lib/govuk_tech_docs/tech_docs_html_renderer.rb @@ -1,4 +1,5 @@ require "middleman-core/renderers/redcarpet" +require "govuk_tech_docs/unique_identifier_generator" module GovukTechDocs class TechDocsHTMLRenderer < Middleman::Renderers::MiddlemanRedcarpetHTML @@ -10,12 +11,18 @@ def initialize(options = {}) super end + def preprocess(document) + @unique_identifier_generator = UniqueIdentifierGenerator.new + + document + end + def paragraph(text) @app.api("

#{text.strip}

\n") end def header(text, level) - anchor = UniqueIdentifierGenerator.instance.create(text, level) + anchor = @unique_identifier_generator.create(text, level) %(#{text}\n) end diff --git a/lib/govuk_tech_docs/unique_identifier_extension.rb b/lib/govuk_tech_docs/unique_identifier_extension.rb deleted file mode 100644 index bb50e943..00000000 --- a/lib/govuk_tech_docs/unique_identifier_extension.rb +++ /dev/null @@ -1,13 +0,0 @@ -module GovukTechDocs - class UniqueIdentifierExtension < Middleman::Extension - def initialize(app, options_hash = {}, &block) - super - - app.before do - UniqueIdentifierGenerator.instance.reset - end - end - end -end - -::Middleman::Extensions.register(:unique_identifier, GovukTechDocs::UniqueIdentifierExtension) diff --git a/lib/govuk_tech_docs/unique_identifier_generator.rb b/lib/govuk_tech_docs/unique_identifier_generator.rb index 62b932c5..6006fcb7 100644 --- a/lib/govuk_tech_docs/unique_identifier_generator.rb +++ b/lib/govuk_tech_docs/unique_identifier_generator.rb @@ -1,15 +1,11 @@ -require "singleton" - module GovukTechDocs class UniqueIdentifierGenerator - include Singleton - Anchor = Struct.new(:id, :level) attr_reader :anchors def initialize - reset + @anchors = [] end def create(id, level) @@ -28,10 +24,6 @@ def create(id, level) anchor end - def reset - @anchors = [] - end - private def prefixed_by_parent(anchor, level) diff --git a/spec/govuk_tech_docs/tech_docs_html_renderer_spec.rb b/spec/govuk_tech_docs/tech_docs_html_renderer_spec.rb index 83723aad..fcba3f8f 100644 --- a/spec/govuk_tech_docs/tech_docs_html_renderer_spec.rb +++ b/spec/govuk_tech_docs/tech_docs_html_renderer_spec.rb @@ -95,4 +95,51 @@ def hello_world end end end + + describe "#render unique heading IDs" do + it "Automatically assigns an ID to the heading" do + output = processor.render <<~MARKDOWN + # A heading + ## A subheading + MARKDOWN + + expect(output).to include('

A heading

') + expect(output).to include('

A subheading

') + end + + it "Ensures IDs are unique among headings in the page" do + output = processor.render <<~MARKDOWN + # A heading + ## A subheading + ### A shared heading + ### A shared heading + ### A shared heading + ## Another subheading + ### A shared heading + MARKDOWN + + # Fist heading will get its ID as a normal heading + expect(output).to include('

A shared heading

') + # Second occurence will be prefixed by the previous heading to ensure uniqueness + expect(output).to include('

A shared heading

') + # Third occurence will be get the prefix, as well as a numeric suffix, to keep ensuring uniqueness + expect(output).to include('

A shared heading

') + # Finally the last occurence will get a prefix, but no number as it's in a different section + expect(output).to include('

A shared heading

') + end + + it "Does not consider unique IDs across multiple renders" do + processor.render <<~MARKDOWN + # A heading + ## A subheading + MARKDOWN + + second_output = processor.render <<~MARKDOWN + # A heading + ## A subheading + MARKDOWN + + expect(second_output).to include('

A subheading

') + end + end end diff --git a/spec/govuk_tech_docs/unique_identifier_generator_spec.rb b/spec/govuk_tech_docs/unique_identifier_generator_spec.rb index 074ff1a0..6c79f851 100644 --- a/spec/govuk_tech_docs/unique_identifier_generator_spec.rb +++ b/spec/govuk_tech_docs/unique_identifier_generator_spec.rb @@ -1,6 +1,5 @@ RSpec.describe GovukTechDocs::UniqueIdentifierGenerator do - subject { described_class.instance } - before { subject.reset } + subject { described_class.new } describe "#create" do it "lower-cases the text" do @@ -66,13 +65,4 @@ end end end - - describe "#reset" do - it "clears the list of existing anchors" do - subject.create("An Anchor", 1) - expect(subject.anchors).to_not be_empty - subject.reset - expect(subject.anchors).to be_empty - end - end end