-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GTD-1 Search #28
GTD-1 Search #28
Conversation
…e can display content previews
…e sentences for each result Based on feedback from Stephen
The search results pane is positioned absolute which makes it harder to manage when it overflows the viewport but placing it directly after the search form maintains a nice tabbing order
Fixed the aria-hidden state management Added the number of search results in am aria-live region Prevented non-JS Google search submission
…lts title This should be more accessible, as it's an aria-live region
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, other than the points I commented on inline. I'm hoping to try it out on a new project during the GOV.UK firebreak next week.
Could we capture analytics about how this search functionality is being used? I.e. what people search for and what they click? Having search terms especially would be really helpful for identifying gaps in the documentation and improving it.
I understand the tech docs do already integrate with GA but I don't know the details of it. But I am familiar with how the GOV.UK site search analytics is set up and am happy to talk through that if there's anything you could reuse there.
lib/source/layouts/_search.erb
Outdated
<div id="search-results" class="search-results" aria-hidden="true"> | ||
<div class="search-results__inner"> | ||
<button class="search-results__close">Close<span class="search-results__close-label"> search results</span></button> | ||
<h2 class="search-results__title" aria-live="polite">Results</h2> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this aria-live
apply to the content below?
I would have expected a div around the heading + content with this attribute, rather than it just on the heading. Also, how does it combine with the aria-hidden
attribute on the parent div?
This is not my area of expertise so sorry if these are obvious questions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an interesting question. Originally I had the aria-live attribute around the entire search results area, but this had two detrimental effects from my POV.
- Voiceover would continuously read out "Unchanged 'Close Search Results" every time you typed. That text element never changes so it was useless noise.
- On every keypress Voiceover would start reading out all the results headings and the example sentences which felt like a lot of overwhelming noise. It felt like it would be better not to have aria-live at all.
In the end I added the update to the number of search results, so screen reader users get short feedback on their search query, and can then progress and view each results in their time.
We have a booking with the accessibility clinic. I'll open a new issue if they make any suggestions.
}); | ||
} | ||
|
||
function searchIndex(query) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think searchIndex
is a weird name for this function, since it doesn't return the search index, or do any indexing, it just does a search. Maybe getResults
would be clearer.
output += '<li class="search-result">'; | ||
output += '<h3 class="search-result__title">'; | ||
output += '<a href="' + result.url + '">'; | ||
output += result.title; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could inject HTML into the page. It's likely that at some point it will contain characters that require HTML encoding like &<> which would break the markup of the page. Can we use a templating language instead of string concatenation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started looking into potential templating systems but when writing the unit test I realised that the index we generate with lunrjs doesn't include any HTML.
I'm not against adding a templating system, but I'd rather not risk delaying this merge on a potential bike shed. How about we open a new issue for that?
content = $(content).mark(query); | ||
|
||
// Split content by sentence. | ||
var sentences = content.html().replace(/(\.+|\:|\!|\?|\r|\n)(\"*|\'*|\)*|}*|]*)/gm, "|").split("|"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you create tests for this code that generates the snippets?
I think I understand what this is doing, but it's not super clear what the intended behaviour is, and if we end up changing that regex (for example) I wouldn't want to break edge cases that you've already considered.
I expect we may want to truncate these further since matching sentences could be quite long, but I'd rather wait and see if it's actually an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expect we may want to truncate these further since matching sentences could be quite long, but I'd rather wait and see if it's actually an issue.
Yeah I can see that being an issue. It's going to be tricky to truncate without accidentally removing required context. Let's see what comes up.
function updateTitle(text) { | ||
if(typeof text == "undefined") { | ||
var count = results.length; | ||
var text = count + ' Results'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor stylistic thing - should "results" be lowercased here?
The function has to be public to unit test it. Also, display *five* sentences...
spec/javascripts/search-spec.js
Outdated
}); | ||
|
||
it('returns concatenated sentences that contain the search query', function() { | ||
expect(processedContent).toEqual(expectedResults) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was confused by this because expectedResults
is used before it's set. Would it be better to move everything into the it
block? I'm still not entirely sure we're not accidentally doing expect(null).toEqual(null)
here.
@@ -29,9 +29,11 @@ Gem::Specification.new do |spec| | |||
spec.add_dependency "middleman-livereload" | |||
spec.add_dependency "middleman-sprockets", "~> 4.0.0" | |||
spec.add_dependency "middleman-syntax", "~> 3.0.0" | |||
spec.add_dependency "middleman-search" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this conflict with the statement in the Gemfile
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not. We can't specify a git path in the spec file, but we can in the Gemfile. We don't need to add this line in the spec file but I think it's better to only use the Gemfile to override the gem location. https://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/
docs/configuration.md
Outdated
Enables search functionality. This indexes pages only and is not recommended for single-page sites. | ||
|
||
```yaml | ||
search: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this can be enable_search
for consistency with other boolean options like show_govuk_logo
?
@@ -2,3 +2,5 @@ source 'https://rubygems.org' | |||
|
|||
# Specify your gem's dependencies in govuk_tech_docs.gemspec | |||
gemspec | |||
|
|||
gem 'middleman-search', :git => "git://github.com/alphagov/middleman-search.git" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could add instructions to add this gem to docs/configuration.md
. We might keep even want to keep and not require middleman-search
by default so sites that don't use search don't need to download it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, adding this line to their tech docs gemfile would be another step to activating search? It feels like something to avoid. I don't expect tech writers to understand gemfiles and what they do, it adds another step that could break the build if done incorrectly. It's your call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚨Adding this line is now a requirement to activating search.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks sensible to me, but I think it needs a few more tests of the core functionality.
…er config options
…e jasmine:ci tests
Requires an extra copy of lunr.js as we can't include from the lunr.js provided by middleman-search
@MatMoore I've created an issue on our Jira board to add analytics events. It would be good to see the event labels used on the gov.uk search so we can keep them consistent. I do think there is a little complexity around what is classified a 'search term' for a search-as-you-type ui. I'd rather add this separately so we can get this PR merged as soon as possible this week. I've added some additional tests, let me know if there's anything else I can do to get this merged. |
See ConvivioTeam#1. I'll change the base branch to alphagov/master once this is merged |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lewisnyman that's fine with me. Feel free to ping me on slack if you want to chat about this.
I'm happy with everything conceptually. I haven't looked carefully at the frontend side of things but I think Rafal is providing another review.
…d focus when they aren't visible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - late to the party.
Add search functionality as per version 1.5.0 of the `tech-docs-gem` (alphagov/tech-docs-gem#28)
This is a bit of a big commit, but it should be fine since it's mostly deletions and it's all interconnected. Things that happen in this commit: - We remove the layout overrides that exist in these docs, in favour of the layouts provided by the gem. - The layouts now provide the meta tags functionality (alphagov/tech-docs-gem#11), so we can remove our own code for that. - The page review is now provided by the gem as well (alphagov/tech-docs-gem#12), so we get rid of the custom code for that too. - We turn on the search functionality from the gem which was added in alphagov/tech-docs-gem#28 and follow up PRs. After this commit, we're mostly running code from the gem instead of our own. This should make it easier to update, and makes it more likely that we'll contribute back to the gem.
Fixes alphagov/tech-docs-template#66
This integrates middleman-search to generate a Lunr.js index. On the frontend it's a custom Lunr.js implementation.
You'll need a forked version of middleman-search to run this locally. To do this you'll need to add this line to the Gemfile in your tech docs folders:
gem 'middleman-search', :git => "git://github.com/alphagov/middleman-search.git"
Another issue here is that middleman-search generates an index of pages, so this functionality is only useful on multi page sites. We plan to fork middleman-search and build an index of sub headings as well as pages.
In the meantime, I'd like to get this merged as soon as possible behind a config flag, so teams can start to use it and provide feedback.