From e8bf846f0ba046358e7fb8708db1d43f6c6d7fbe Mon Sep 17 00:00:00 2001 From: Sam Schweigel Date: Tue, 6 May 2025 16:24:09 -0700 Subject: [PATCH 1/7] Include content in search_index.js path; make script async --- src/html/HTMLWriter.jl | 48 ++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/html/HTMLWriter.jl b/src/html/HTMLWriter.jl index 21cb8f6d11..9f8b083fc6 100644 --- a/src/html/HTMLWriter.jl +++ b/src/html/HTMLWriter.jl @@ -771,7 +771,6 @@ function render(doc::Documenter.Document, settings::HTML = HTML()) end ctx = HTMLContext(doc, settings) - ctx.search_index_js = "search_index.js" ctx.themeswap_js = copy_asset("themeswap.js", doc) ctx.warner_js = copy_asset("warner.js", doc) @@ -800,9 +799,34 @@ function render(doc::Documenter.Document, settings::HTML = HTML()) copy_asset("themes/$(theme).css", doc) end - size_limit_successes = map(collect(keys(doc.blueprint.pages))) do page + function page_navnode(page) idx = findfirst(nn -> nn.page == page, doc.internal.navlist) nn = (idx === nothing) ? Documenter.NavNode(page, nothing, nothing) : doc.internal.navlist[idx] + nn, idx + end + + foreach(keys(doc.blueprint.pages)) do page + nn, idx = page_navnode(page) + @debug "Indexing $(page) [$(repr(idx))]" + generate_index!(ctx, nn) + end + + # Make an attempt at avoiding spurious changes to the search index hash. + sort!(ctx.search_index; by=r -> (r.src, r.fragment, r.text)) + search_index_buf = let io = IOBuffer() + println(io, "var documenterSearchIndex = {\"docs\":") + # convert Vector{SearchRecord} to a JSON string + do additional JS escaping + println(io, JSDependencies.json_jsescape(ctx.search_index), "\n}") + take!(io) + end + # Put the index's hash in its filename so it can have a long max-age. + ctx.search_index_js = "search_index_$(dataslug(search_index_buf)).js" + open(joinpath(doc.user.build, ctx.search_index_js), "w") do io + write(io, search_index_buf) + end + + size_limit_successes = map(collect(keys(doc.blueprint.pages))) do page + nn, idx = page_navnode(page) @debug "Rendering $(page) [$(repr(idx))]" render_page(ctx, nn) end @@ -837,12 +861,6 @@ function render(doc::Documenter.Document, settings::HTML = HTML()) # Check that all HTML files are smaller or equal to size_threshold option all(size_limit_successes) || throw(HTMLSizeThresholdError()) - open(joinpath(doc.user.build, ctx.search_index_js), "w") do io - println(io, "var documenterSearchIndex = {\"docs\":") - # convert Vector{SearchRecord} to a JSON string + do additional JS escaping - println(io, JSDependencies.json_jsescape(ctx.search_index), "\n}") - end - write_inventory(doc, ctx) return generate_siteinfo_json(doc.user.build) @@ -1027,7 +1045,7 @@ function render_head(ctx, navnode) :src => RD.requirejs_cdn, Symbol("data-main") => relhref(src, ctx.documenter_js), ], - script[:src => relhref(src, ctx.search_index_js)], + script[:src => relhref(src, ctx.search_index_js), :async], script[:src => relhref(src, "siteinfo.js")], script[:src => relhref(src, "../versions.js")], @@ -1700,10 +1718,6 @@ end function domify(dctx::DCtx) ctx, navnode = dctx.ctx, dctx.navnode return map(getpage(ctx, navnode).mdast.children) do node - rec = searchrecord(ctx, navnode, node) - if !isnothing(rec) - push!(ctx.search_index, rec) - end domify(dctx, node, node.element) end end @@ -1848,6 +1862,14 @@ function domify(::DCtx, ::Node, rawnode::Documenter.RawNode) return rawnode.name === :html ? DOM.Tag(Symbol("#RAW#"))(rawnode.text) : DOM.Node[] end +function generate_index!(ctx::HTMLContext, navnode::Documenter.NavNode) + map(getpage(ctx, navnode).mdast.children) do node + rec = searchrecord(ctx, navnode, node) + if !isnothing(rec) + push!(ctx.search_index, rec) + end + end +end # Utilities # ------------------------------------------------------------------------------ From 5e7c1965a73aa088227acf10b5fea43288446623 Mon Sep 17 00:00:00 2001 From: Sam Schweigel Date: Tue, 6 May 2025 16:55:06 -0700 Subject: [PATCH 2/7] Listen for the load event instead of polling for search index --- assets/html/js/search.js | 3 ++- src/html/HTMLWriter.jl | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/assets/html/js/search.js b/assets/html/js/search.js index 050731aa9f..bc35f7d6c1 100644 --- a/assets/html/js/search.js +++ b/assets/html/js/search.js @@ -610,7 +610,8 @@ function waitUntilSearchIndexAvailable() { runSearchMainCode(); } else { console.warn("Search Index not available, waiting"); - setTimeout(waitUntilSearchIndexAvailable, 1000); + document.getElementById("documenter-search-index-script") + .addEventListener("load", waitUntilSearchIndexAvailable); } } diff --git a/src/html/HTMLWriter.jl b/src/html/HTMLWriter.jl index 9f8b083fc6..ca3d33f7a6 100644 --- a/src/html/HTMLWriter.jl +++ b/src/html/HTMLWriter.jl @@ -1045,7 +1045,7 @@ function render_head(ctx, navnode) :src => RD.requirejs_cdn, Symbol("data-main") => relhref(src, ctx.documenter_js), ], - script[:src => relhref(src, ctx.search_index_js), :async], + script[:src => relhref(src, ctx.search_index_js), :async, :id => "documenter-search-index-script"], script[:src => relhref(src, "siteinfo.js")], script[:src => relhref(src, "../versions.js")], From 7da80d667d28d717b7972e4dddae901f043599ce Mon Sep 17 00:00:00 2001 From: Sam Schweigel Date: Tue, 6 May 2025 16:57:18 -0700 Subject: [PATCH 3/7] Fix Julia formatting issues --- src/html/HTMLWriter.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/html/HTMLWriter.jl b/src/html/HTMLWriter.jl index ca3d33f7a6..546dfb4e96 100644 --- a/src/html/HTMLWriter.jl +++ b/src/html/HTMLWriter.jl @@ -802,7 +802,7 @@ function render(doc::Documenter.Document, settings::HTML = HTML()) function page_navnode(page) idx = findfirst(nn -> nn.page == page, doc.internal.navlist) nn = (idx === nothing) ? Documenter.NavNode(page, nothing, nothing) : doc.internal.navlist[idx] - nn, idx + return nn, idx end foreach(keys(doc.blueprint.pages)) do page @@ -1863,7 +1863,7 @@ function domify(::DCtx, ::Node, rawnode::Documenter.RawNode) end function generate_index!(ctx::HTMLContext, navnode::Documenter.NavNode) - map(getpage(ctx, navnode).mdast.children) do node + foreach(getpage(ctx, navnode).mdast.children) do node rec = searchrecord(ctx, navnode, node) if !isnothing(rec) push!(ctx.search_index, rec) From f80982f3e7fd8d4bc9f4ef03e9b6449d05c7e67d Mon Sep 17 00:00:00 2001 From: Sam Schweigel Date: Tue, 6 May 2025 17:44:11 -0700 Subject: [PATCH 4/7] Run code formatters on JS and Julia --- assets/html/js/search.js | 13 +++++++------ src/html/HTMLWriter.jl | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/assets/html/js/search.js b/assets/html/js/search.js index bc35f7d6c1..d524c64156 100644 --- a/assets/html/js/search.js +++ b/assets/html/js/search.js @@ -67,7 +67,7 @@ update_search function worker_function(documenterSearchIndex, documenterBaseURL, filters) { importScripts( - "https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js" + "https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js", ); let data = documenterSearchIndex.map((x, key) => { @@ -278,8 +278,8 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) { Math.max(textindex.index - 100, 0), Math.min( textindex.index + querystring.length + 100, - result.text.length - ) + result.text.length, + ), ) : ""; // cut-off text before and after from the match @@ -289,7 +289,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) { ? "..." + text.replace( new RegExp(`${escape(searchstring)}`, "i"), // For first occurrence - '$&' + '$&', ) + "..." : ""; // highlights the match @@ -302,7 +302,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) { // We encode the full url to escape some special characters which can lead to broken links let result_div = `
(r.src, r.fragment, r.text)) + sort!(ctx.search_index; by = r -> (r.src, r.fragment, r.text)) search_index_buf = let io = IOBuffer() println(io, "var documenterSearchIndex = {\"docs\":") # convert Vector{SearchRecord} to a JSON string + do additional JS escaping @@ -1863,7 +1863,7 @@ function domify(::DCtx, ::Node, rawnode::Documenter.RawNode) end function generate_index!(ctx::HTMLContext, navnode::Documenter.NavNode) - foreach(getpage(ctx, navnode).mdast.children) do node + return foreach(getpage(ctx, navnode).mdast.children) do node rec = searchrecord(ctx, navnode, node) if !isnothing(rec) push!(ctx.search_index, rec) From 6c98c4f09abc5b372d20a7d68bf009ca5b9805c2 Mon Sep 17 00:00:00 2001 From: Sam Schweigel Date: Wed, 7 May 2025 10:59:28 -0700 Subject: [PATCH 5/7] Use right version of prettier this time --- assets/html/js/search.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/html/js/search.js b/assets/html/js/search.js index d524c64156..719798e9a2 100644 --- a/assets/html/js/search.js +++ b/assets/html/js/search.js @@ -67,7 +67,7 @@ update_search function worker_function(documenterSearchIndex, documenterBaseURL, filters) { importScripts( - "https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js", + "https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js" ); let data = documenterSearchIndex.map((x, key) => { @@ -278,8 +278,8 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) { Math.max(textindex.index - 100, 0), Math.min( textindex.index + querystring.length + 100, - result.text.length, - ), + result.text.length + ) ) : ""; // cut-off text before and after from the match @@ -289,7 +289,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) { ? "..." + text.replace( new RegExp(`${escape(searchstring)}`, "i"), // For first occurrence - '$&', + '$&' ) + "..." : ""; // highlights the match @@ -302,7 +302,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) { // We encode the full url to escape some special characters which can lead to broken links let result_div = `