diff --git a/.dockerignore b/.dockerignore index edbe80040..36e53b377 100644 --- a/.dockerignore +++ b/.dockerignore @@ -11,9 +11,7 @@ docs features log node_modules -package.json script spec test tmp -yarn.lock diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 488eeb079..e518dd1e5 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -1,3 +1,4 @@ +/* global pasteHtmlToGovspeak */ //= require vendor/jquery-1.11.0.min //= require vendor/jquery-ui.min.js @@ -6,11 +7,15 @@ //= require length_counter //= require markdown_preview //= require toggle_display_with_checked_input - +//= require paste-html-to-govspeak jQuery(function ($) { $('.js-length-counter').each(function () { new GOVUK.LengthCounter({ $el: $(this) }) // eslint-disable-line no-new }) + $('.js-paste-html-to-govspeak').each(function () { + this.addEventListener('paste', pasteHtmlToGovspeak.pasteListener) + }) + $('.reorderable-document-list').sortable() }) diff --git a/app/views/manuals/_form.html.erb b/app/views/manuals/_form.html.erb index 3d3bce8e8..42a8043d7 100644 --- a/app/views/manuals/_form.html.erb +++ b/app/views/manuals/_form.html.erb @@ -8,7 +8,7 @@
Summary text should be 280 characters or fewer.
- <%= f.text_area :body, rows: 20, cols: 40, class: 'form-control' %> + <%= f.text_area :body, rows: 20, cols: 40, class: 'form-control js-paste-html-to-govspeak' %>
diff --git a/app/views/sections/_form.html.erb b/app/views/sections/_form.html.erb index d820af4e2..53a73cb81 100644 --- a/app/views/sections/_form.html.erb +++ b/app/views/sections/_form.html.erb @@ -6,7 +6,7 @@ <%= f.text_field :title, label: 'Section title', class: 'form-control' %> <%= f.text_area :summary, rows: 20, cols: 40, label: 'Section summary', class: 'form-control short-textarea js-length-counter', data: { :"count-message-threshold" => 280, :"count-message-selector" => ".summary-length-info" } %>
Summary text should be 280 characters or fewer.
- <%= f.text_area :body, rows: 20, cols: 40, label: 'Section body', class: 'form-control' %> + <%= f.text_area :body, rows: 20, cols: 40, label: 'Section body', class: 'form-control js-paste-html-to-govspeak' %>
diff --git a/features/creating-and-editing-a-manual.feature b/features/creating-and-editing-a-manual.feature index 306b94763..e3c3cf7d7 100644 --- a/features/creating-and-editing-a-manual.feature +++ b/features/creating-and-editing-a-manual.feature @@ -51,6 +51,12 @@ Feature: Creating and editing a manual When I edit a manual Then the manual's sections won't have changed + @javascript + Scenario: Pasting HTML into a manual + When I start creating a new manual + And I paste HTML into the manual body + Then the manual body field contains govspeak + Scenario: Try to create an invalid manual When I create a manual with an empty title Then I see errors for the title field @@ -67,6 +73,13 @@ Feature: Creating and editing a manual And I see the section isn't visually expanded And the section and table of contents will have been sent to the draft publishing api + @javascript + Scenario: Pasting HTML into a section + Given a draft manual exists without any sections + When I start creating a section for the manual + And I paste HTML into the section body + Then the section body field contains govspeak + Scenario: Add an expanded section to a manual Given a draft manual exists without any sections When I create an expanded section for the manual diff --git a/features/step_definitions/manual_steps.rb b/features/step_definitions/manual_steps.rb index f8d5b98ca..ab286d68b 100644 --- a/features/step_definitions/manual_steps.rb +++ b/features/step_definitions/manual_steps.rb @@ -278,9 +278,9 @@ When(/^I add another section and publish the manual later$/) do create_section( @manual.title, - section_title: "Another section so we can publish", - section_summary: "Another section so we can publish summary", - section_body: "Another section so we can publish body", + { section_title: "Another section so we can publish", + section_summary: "Another section so we can publish summary", + section_body: "Another section so we can publish body" }, ) go_to_manual_page(@manual.title) publish_manual @@ -667,6 +667,24 @@ create_manual(@manual_fields, save: false) end +When(/^I start creating a section for the manual$/) do + create_section(@manual_fields.fetch(:title), {}, save: false) +end + +When(/^I paste HTML into the manual body$/) do + fill_in_field("body", "") + page.execute_script(javascript_to_simulate_paste("manual_body", "

Benefits of following this advice

")) +end + +When(/^I paste HTML into the section body$/) do + fill_in_field("section body", "") + page.execute_script(javascript_to_simulate_paste("section_body", "

Benefits of following this advice

")) +end + +Then(/^the (manual|section) body field contains govspeak$/) do |content_type_name| + expect(page).to have_field("#{content_type_name}_body", with: "## Benefits of following this advice") +end + When(/^I preview the manual$/) do click_button("Preview") end diff --git a/features/support/form_helpers.rb b/features/support/form_helpers.rb index 9d1252452..0caa9cdd4 100644 --- a/features/support/form_helpers.rb +++ b/features/support/form_helpers.rb @@ -15,6 +15,18 @@ def fill_in_field(field_name, value) end end + def javascript_to_simulate_paste(element_id, paste_content) + <<~JS + var event = new Event('paste') + event.clipboardData = { + getData: function() { + return '#{paste_content}' + } + } + document.getElementById('#{element_id}').dispatchEvent(event) + JS + end + def clear_datetime(label) base_dom_id = find(:xpath, ".//label[contains(., '#{label}')]")["for"].gsub(/(_[1-5]i)$/, "") diff --git a/features/support/manual_helpers.rb b/features/support/manual_helpers.rb index ca00a3010..f6be08340 100644 --- a/features/support/manual_helpers.rb +++ b/features/support/manual_helpers.rb @@ -30,7 +30,7 @@ def create_manual_without_ui(fields, organisation_slug: "ministry-of-tea") Manual.find(manual.id, FactoryBot.build(:gds_editor)) end - def create_section(manual_title, fields) + def create_section(manual_title, fields, save: true) go_to_manual_page(manual_title) click_on "Add section" @@ -38,7 +38,7 @@ def create_section(manual_title, fields) yield if block_given? - save_as_draft + save_as_draft if save end def create_expanded_section(manual_title, fields) diff --git a/lib/tasks/assets.rake b/lib/tasks/assets.rake new file mode 100644 index 000000000..4f4f3b7a6 --- /dev/null +++ b/lib/tasks/assets.rake @@ -0,0 +1,2 @@ +# Maintain Rails < 7 behaviour of running yarn:install before assets:precompile +Rake::Task["assets:precompile"].enhance(["yarn:install"]) diff --git a/package.json b/package.json index 3f7c4be33..81a70c5fe 100644 --- a/package.json +++ b/package.json @@ -45,5 +45,8 @@ "resolutions": { "stylelint/strip-ansi": "6.0.1", "stylelint/string-width": "4.2.3" + }, + "dependencies": { + "paste-html-to-govspeak": "^0.3.0" } } diff --git a/yarn.lock b/yarn.lock index b3c102a2a..fe22dc339 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1894,6 +1894,11 @@ parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +paste-html-to-govspeak@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/paste-html-to-govspeak/-/paste-html-to-govspeak-0.3.0.tgz#9c4717690f3d6cd290c972c9bf106ead14adb177" + integrity sha512-K4jcJkZLQpvpukkiSzXZcXPbV80CDSKTI3zEs0/gVG+jx5H7v2XsdIOEuCZ56cRCCuuIH3rsrJcyoleGqPj6xw== + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"