Documenter.jl icon indicating copy to clipboard operation
Documenter.jl copied to clipboard

Towards a more flexible `pages` interface

Open asinghvi17 opened this issue 11 months ago • 7 comments

In makedocs, the way to specify pages is currently pretty rigid - you can only pass in a very rigid nested array of strings (and indicate title / page path).

I, and many others, would like to have a more flexible way to define pages for the sidebar, so that we can e.g. define a section header that is also a page / clickable, and has sub-pages associated with it. This is already possible in DocumenterVitepress although you have to define the sidebar manually in the config.mts. The basic DimensionalData docs is a good example - the "Getting started" is a page, but is also the section header for that section of the docs. There are also subsidiary pages.

Another example is choosing which subsections of the sidebar to expand on a more granular level. At the moment, we only have the ability to set a global threshold for the nesting level at which things collapse. But I may want a top level section to be collapsed by default, and a lower level section to not be collapsed.

There is some current functionality that is slightly similar, and that's hide - which takes any pages-compatible structure / type, and returns a 4-tuple of (hidden::Bool, title::String, path::String, children::Vector) (I think). So my first thought is that we should make this a struct that people can instantiate, and include some more metadata. A basic prototype might be (borrowing from Documenter.NavNode):

struct PageNode
    # page contents
    page::Union{String, Nothing}
    children::Vector{PageNode}
    # metadata
    title_override::Union{String, Nothing}
    visible::Union{Bool, Nothing}
    collapsed::Union{Bool, Nothing} # nothing here indicates that we follow the global spec
end
Constructor
PageNode(input::Pair; kw...) = PageNode(input[1], input[2]; kw...)
PageNode(input::String; visible = nothing, collapsed = nothing) = PageNode(input, PageNode[], nothing, visible, collapsed)

function PageNode(input::Vector; kw...)

	children = PageNode.(input; kw...)

	return PageNode(nothing, children, nothing, visible, collapsed)

end

function PageNode(titlechildren::Pair{String, Vector}; kw...)

	children = PageNode.(titlechildren[2]; kw...)

	return PageNode(nothing, children, titlechildren[1], visible, collapsed)
end

function PageNode(original_page, children::Vector; kw...)
	pn1 = PageNode(original_page; kw...)

	@assert isempty(pn1.children) "You can't specify multiple children!  Look at the type of the first argument to this function."

	return PageNode(pn1.page, PageNode.(children; kw...), pn1.title_override, pn1.visible, pn1.collapsed)
end

and then we can recursively parse all input to pages into PageNodes.

@mortenpi mentioned that we could initially disallow collapsing pagenodes that have a non-nothing page but non-empty children, pending a section collapser element in the UI.

The main parser is in walk_navpages so that's where we have to inject the override.

https://github.com/JuliaDocs/Documenter.jl/blob/6abd8288164285ac58e4234f36c64b13029792e1/src/builder_pipeline.jl#L181

cc: @mortenpi @fredrikekre

asinghvi17 avatar Jan 28 '25 20:01 asinghvi17

x-ref https://github.com/JuliaDocs/Documenter.jl/issues/344

odow avatar Jan 28 '25 21:01 odow

Thanks! That seems to be incompatible with the current NavNode structure, see here:

https://github.com/JuliaDocs/Documenter.jl/blob/6abd8288164285ac58e4234f36c64b13029792e1/src/documents.jl#L236-L241

but I'm sure that with some effort we could fix that...

asinghvi17 avatar Jan 28 '25 21:01 asinghvi17

Yeah if you're thinking about making it more flexible, this is something that people keep asking for.

odow avatar Jan 28 '25 21:01 odow

See also https://github.com/JuliaDocs/Documenter.jl/issues/701.

fredrikekre avatar Jan 28 '25 22:01 fredrikekre

Initial prototype up and running (pages but no external links or collapsing spec yet) - it just worked!!

https://github.com/asinghvi17/DocumenterPages.jl

asinghvi17 avatar Jan 28 '25 22:01 asinghvi17

https://github.com/JuliaDocs/Documenter.jl/blob/6abd8288164285ac58e4234f36c64b13029792e1/src/html/HTMLWriter.jl#L1237 is where the collapsing logic goes

asinghvi17 avatar Jan 29 '25 02:01 asinghvi17

Please add the collapsing logic. Our docs organize pages into folders and now the navbar is way too long for an easy overview. It would be nice to have the folders collapsed with an arrow (>) that expands to show the pages.

For example, I would like the Tutorials folder to be collapsed until they click on it. From what I've seen of 'hide', it doesn't work for this case because the pages would never become visible.

Image

clizbe avatar Oct 04 '25 19:10 clizbe