Skip to content
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

New Table of Contents element #30

Merged
merged 23 commits into from
Dec 29, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions src/Builtins.jl
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,105 @@ function show(io::IO, ::MIME"text/html", radio::Radio)
end

get(radio::Radio) = radio.default


"""Generate Table of Contents using Markdown cells. Headers h1-h6 are used.

`title` is the custom Title header to this element.
`indent` aligns header elements in a heirarchy.

# Examples
`@bind TableOfContents()`

`@bind TableOfContents(indent=True)`

`@bind TableOfContents(title="Table of Contents")`

"""
struct TableOfContents
title::AbstractString
indent::Bool
end
TableOfContents(;title::AbstractString="", indent::Bool=false) = TableOfContents(title, indent)

function show(io::IO, ::MIME"text/html", toc::TableOfContents)

if length(toc.title) > 0
print(io, """<div class="title">$(toc.title)</div>""")
end

withtag(io, :script) do
print(io, """
const elementsOfType = (type) => Array.from(
document.querySelectorAll(
"pluto-notebook pluto-output " + type
)
).map(el => {
const parentCellId = function(el) {
while (el.nodeName != 'PLUTO-CELL') {
el = el.parentNode;
if (!el) return null;
}
return el.id;
}
return {
"el": el,
"parentCellId": parentCellId(el)
}
})

const plutoCellIds = Array.from(
document.querySelectorAll(
"pluto-notebook pluto-cell"
)
).map(el => el.id)

const headers = [...elementsOfType("h1"), ...elementsOfType("h2"),...elementsOfType("h3"),...elementsOfType("h4"), ...elementsOfType("h5"),...elementsOfType("h6")]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to have the allowed headers as input argument? E.g. the user would provide the level depth they require (1 to 6) and only headers up to this depth are used in the ToC?

If LaTeX has any value here, I would argue that the default depth should be 3 (because in latex by default you get section numbering up to e.g. 2.2.3)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(but this is a minor comment - please don't let it hold this PR back)

Copy link
Contributor Author

@shashankp shashankp Sep 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the depth limit. ✅
Tempted to do auto numbering, but wouldn't it be jarring? a section name would have a number in the TOC, but not in the actual location. I'd rather let user do the numbering.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how the plugin of Jupyter does it, but the autonumbering there is reflected in both the TOC and the headers. So the headers will literally display 1.1 Header. But maybe this is too invasive or just too hard to do from the design of Pluto?

(to be honest I actually liked the auto numbering)

Copy link
Contributor Author

@shashankp shashankp Sep 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, updating the user created content itself would be invasive & fraught with assumptions.
Lets see the feedback on auto-numbering only in TOC.

Copy link

@Datseris Datseris Sep 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked Jupyter again and they only change the display. So if I have markdown sections:

# Title
## Subtitle

# Next title

they will be displayed (or rendered) as "1. Title, 1.1 Subtitle, 2. Next title", but when I double click the markdown cells to edit them, the numbers are not there. So it is only what displayed that is altered and thus I would call it non-invasive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header cells would need to store the numbering in their state making them special markdown cells. Adding this hidden state from an external PlutoUI addon seems invasive 🤔

headers.sort((a,b) => plutoCellIds.indexOf(a.parentCellId)-plutoCellIds.indexOf(b.parentCellId))

return html`\${headers.map(h => html`<div><a class="\${h.el.nodeName}" href="#\${h.parentCellId}">\${h.el.innerText}</a></div>`)}`
""")
end

withtag(io, :style) do
print(io, """
a {
text-decoration: none;
}
.title{
display: block;
font-size: 2em;
margin-top: 0.67em;
margin-bottom: 0.67em;
margin-left: 0;
margin-right: 0;
font-weight: bold;
}
""")

if toc.indent
print(io, """
.H1 {
padding: 0px 0px;
}
.H2 {
padding: 0px 10px;
}
.H3 {
padding: 0px 20px;
}
.H4 {
padding: 0px 30px;
}
.H5 {
padding: 0px 40px;
}
.H6 {
padding: 0px 50px;
}"""
)
end
end
end

get(toc::TableOfContents) = toc.default