Skip to content

Commit 2381e3c

Browse files
authored
Customize search_data for an extra (#2017)
This allows configuring the "search data" for any given extra. When you do this, you take over the way that the extra appears both in autocomplete and in search_data. The current system assumes that you give this information in markdown, which I think is a safe assumption, but we could do something like allow for an html_body or markdown_body to be given, etc. This will be used in Spark where we generate markdown files for DSL documentation. With this change, we can add a function called Spark.Dsl.search_data_for(Your.Dsl) which will improve the autocomplete experience and the search experience in various ways (by adding more things to autocomplete than just headers, and by customizing the type of the search data nodes
1 parent 3139d3f commit 2381e3c

File tree

8 files changed

+218
-29
lines changed

8 files changed

+218
-29
lines changed

assets/js/autocomplete/suggestions.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,15 @@ export function getSuggestions (query, limit = 8) {
5252
* Finds suggestions in top level sidebar nodes.
5353
*/
5454
function findSuggestionsInTopLevelNodes (nodes, query, category, label) {
55-
return nodes.map(node => nodeSuggestion(node, query, category, label))
55+
return nodes.map(node => {
56+
if (node.searchData) {
57+
// When searchData is present, all search results are found by findSuggestionsInSectionsOfNodes
58+
return null
59+
}
60+
61+
return nodeSuggestion(node, query, category, label)
62+
}
63+
)
5664
}
5765

5866
/**
@@ -88,7 +96,11 @@ function findSuggestionsInSectionsOfNodes (nodes, query, category, label) {
8896
* Returns any sections of the given parent node.
8997
*/
9098
function nodeSections (node) {
91-
return (node.sections || []).concat(node.headers || [])
99+
if (node.searchData) {
100+
return node.searchData
101+
} else {
102+
return (node.sections || []).concat(node.headers || [])
103+
}
92104
}
93105

94106
/**
@@ -133,12 +145,20 @@ function childNodeSuggestion (childNode, parentId, query, category, label) {
133145
function nodeSectionSuggestion (node, section, query, category, label) {
134146
if (!matchesAny(section.id, query)) { return null }
135147

148+
let link
149+
150+
if (section.anchor === '') {
151+
link = `${node.id}.html`
152+
} else {
153+
link = `${node.id}.html#${section.anchor}`
154+
}
155+
136156
return {
137-
link: `${node.id}.html#${section.anchor}`,
157+
link,
138158
title: highlightMatches(section.id, query),
139159
description: node.title,
140160
matchQuality: matchQuality(section.id, query),
141-
labels: [label, 'section'],
161+
labels: section.labels || [label, 'section'],
142162
category
143163
}
144164
}

assets/test/autocomplete/suggestions.spec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ describe('getSuggestions', () => {
6363
id: 'api-reference',
6464
title: 'API Reference'
6565
},
66+
{
67+
id: "how-to-make-things",
68+
title: "How to make things",
69+
searchData: [
70+
{
71+
id: "custom-text",
72+
anchor: "Some Custom Text",
73+
labels: ["custom"]
74+
}
75+
]
76+
},
6677
{
6778
id: 'library-guidelines',
6879
title: 'Library Guidelines',
@@ -89,6 +100,10 @@ describe('getSuggestions', () => {
89100
expect(getSuggestions('Gua').length).to.eql(1)
90101
})
91102

103+
it('returns custom searchData of extras', () => {
104+
expect(getSuggestions('custom text').length).to.eql(1)
105+
})
106+
92107
it('returns matching functions, callbacks and types', () => {
93108
expect(getSuggestions('get_by').length).to.eql(1)
94109
expect(getSuggestions('fetch').length).to.eql(1)

formatters/html/dist/html-APUAZXLV.js renamed to formatters/html/dist/html-HDRJYJCE.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/ex_doc/formatter/html.ex

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ defmodule ExDoc.Formatter.HTML do
66

77
@main "api-reference"
88
@assets_dir "assets"
9+
@search_data_keys [:anchor, :body, :title, :type]
910

1011
@doc """
1112
Generates HTML documentation for the given modules.
@@ -184,6 +185,7 @@ defmodule ExDoc.Formatter.HTML do
184185

185186
defp generate_sidebar_items(nodes_map, extras, config) do
186187
content = Templates.create_sidebar_items(nodes_map, extras)
188+
187189
path = "dist/sidebar_items-#{digest(content)}.js"
188190
File.write!(Path.join(config.output, path), content)
189191
[path]
@@ -429,13 +431,16 @@ defmodule ExDoc.Formatter.HTML do
429431
source_path = source_file |> Path.relative_to(File.cwd!()) |> String.replace_leading("./", "")
430432
source_url = Utils.source_url_pattern(source_url_pattern, source_path, 1)
431433

434+
search_data = normalize_search_data!(input_options[:search_data])
435+
432436
%{
433437
source: source,
434438
content: content_html,
435439
group: group,
436440
id: id,
437441
source_path: source_path,
438442
source_url: source_url,
443+
search_data: search_data,
439444
title: title,
440445
title_content: title_html || title
441446
}
@@ -445,6 +450,26 @@ defmodule ExDoc.Formatter.HTML do
445450
build_extra({input, []}, groups, language, autolink_opts, source_url_pattern)
446451
end
447452

453+
defp normalize_search_data!(nil), do: nil
454+
455+
defp normalize_search_data!(search_data) when is_list(search_data) do
456+
Enum.each(search_data, fn search_data ->
457+
has_keys = Map.keys(search_data)
458+
459+
if Enum.sort(has_keys) != @search_data_keys do
460+
raise ArgumentError,
461+
"Expected search data to be a list of maps with the keys: #{inspect(@search_data_keys)}, found keys: #{inspect(has_keys)}"
462+
end
463+
end)
464+
465+
search_data
466+
end
467+
468+
defp normalize_search_data!(search_data) do
469+
raise ArgumentError,
470+
"Expected search data to be a list of maps with the keys: #{inspect(@search_data_keys)}, found: #{inspect(search_data)}"
471+
end
472+
448473
defp extension_name(input) do
449474
input
450475
|> Path.extname()

0 commit comments

Comments
 (0)