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

Implement "Add to Bookmarks" feature #2440

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
bikeshed = {editable = true,path = "."}
bikeshed = {editable = true, path = "."}

[packages]
aiofiles = "==22.1.0"
Expand Down
111 changes: 110 additions & 1 deletion bikeshed/boilerplate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
from .translate import _

if t.TYPE_CHECKING:
MetadataT: t.TypeAlias = t.Mapping[str, t.Sequence[MetadataValueT]]
MetadataValueT: t.TypeAlias = str | t.NodesT | None
MetadataT: t.TypeAlias = t.Mapping[str, t.Sequence[MetadataValueT]]
dlaliberte marked this conversation as resolved.
Show resolved Hide resolved


def boilerplateFromHtml(doc: t.SpecT, htmlString: str) -> t.NodesT:
Expand Down Expand Up @@ -775,6 +775,103 @@ def addIDLSection(doc: t.SpecT) -> None:
del el.attrib["id"]
h.addClass(doc, container, "highlight")

bookmarkCss = """
.material-symbols-outlined {
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24
}
.heading {
position: relative;
}
.tooltip {
opacity: 0;
display: block;
position: absolute;
top: -90%;
left: 0;
pointer-events: auto;
border: shadow 2px gray;
padding: 0;
margin: 0;
background: rgb(200 200 200 / 50%);
color: black;
border-radius: 5px;
}
a.has-tooltip {
display: block;
}
.tooltip button {
padding: 0;
background: rgb(100 100 100 / 50%);
}
.has-tooltip:hover .tooltip {
opacity: 0.8;
}
.bookmarksSection {
margin-left: 2em;
}
"""

bookmarkScript = """
"use strict";
// Add tooltip behavior to all headers.
const headers = document.querySelectorAll('.heading');
// We need to get the createElement method now, or else it is not available!?
const createElement = document.createElement;
const makeTag = (tag) => {
return createElement.call(document, tag);
}

for (let h of headers) {
const textElement = h.querySelector('span.content');
insertTooltipAction(h, 'bookmark_add', 'Add bookmark', (event) => {
addBookmark(h, textElement.textContent); })
}

function insertTooltipAction(element, className, title, action) {
const tooltipDiv = makeTag('div');
tooltipDiv.className = 'tooltip';
const button = makeTag('button');
button.setHTML(
`<span class="material-symbols-outlined"
title="${title}">${className}</span>`);
button.addEventListener('click', action);
tooltipDiv.insertAdjacentElement('beforeend', button);
element.insertAdjacentElement('beforeend', tooltipDiv);
element.classList.add('has-tooltip');
}

function addBookmark(header, text) {
// console.info('add bookmark for', header);
let bookmarksSection = document.querySelector('.bookmarksSection');
if (bookmarksSection == null) {
const tocContents = document.querySelector('#toc #contents');
bookmarksSection = makeTag('div');
bookmarksSection.className = 'bookmarksSection';
bookmarksSection.setHTML('Bookmarks <ul class="bookmarks"></ul>');
tocContents.insertAdjacentElement('afterend', bookmarksSection);
}
const bookmarksList = document.querySelector('.bookmarks');
const bookmarkItem = makeTag('li');
bookmarksList.insertAdjacentElement('beforeend', bookmarkItem);

const bookmarkLink = makeTag('a');
bookmarkLink.href = header.id;
bookmarkLink.textContent = text;
bookmarkItem.insertAdjacentElement('beforeend', bookmarkLink);

insertTooltipAction(bookmarkLink, 'bookmark_remove', 'Remove bookmark',
(event) => {
removeBookmark(bookmarkItem);
event.stopPropagation();
event.preventDefault();
});
}

function removeBookmark(bookmarkItem) {
const parentElement = bookmarkItem.parentElement;
parentElement.removeChild(bookmarkItem);
}
"""

def addTOCSection(doc: t.SpecT) -> None:
toc = getFillContainer("table-of-contents", doc=doc, default=False)
Expand All @@ -787,6 +884,18 @@ def addTOCSection(doc: t.SpecT) -> None:
_("Table of Contents"),
),
)
if True or "bookmark" not in doc.md.boilerplate:
# Load icon for "add bookmark"
h.appendChild(
toc,
h.E.link(
{ "rel": "stylesheet",
"href": "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0"}
)
)

doc.extraScripts["script-bookmark"] = bookmarkScript
doc.extraStyles["css-bookmark"] = bookmarkCss

# containers[n] holds the current <ol> for inserting each heading's <li> into.
# containers[1] is initialized with something arbitrary
Expand Down
40 changes: 40 additions & 0 deletions tests/bookmarks.bs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<pre class=metadata>
Title: Foo
Group: test
Shortname: foo
Level: 1
Status: LS
ED: http://example.com/foo
Abstract: Test algorithm auto-naming.
Editor: Example Editor
Date: 1970-01-01
</pre>

<div data-fill-with="table-of-contents"></div>

<h2 id=foo algorithm>Find a Foo</h2>

Blah blah blah, <var>foo</var>

<h3 id=bar>bar</h3>

<var>foo</var>

<h2 id=foo2>More Stuff</h2>

<div algorithm>
<dfn>find more foo</dfn>

<var>foo</var>
</div>

<div algorithm>
<var>foo</var>
</div>

<div algorithm>
<dfn>find even more foo</dfn>
but also <dfn>find some bar</dfn>

<var>foo</var>
</div>
Loading