Skip to content

Commit

Permalink
Add TOC to manifest spec
Browse files Browse the repository at this point in the history
  • Loading branch information
kzu committed Feb 18, 2024
1 parent 1497614 commit df008e5
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ compress_html:
envs: all

kramdown:
parse_block_html: true
syntax_highlighter_opts:
block:
line_numbers: true
182 changes: 182 additions & 0 deletions docs/_includes/toc.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
{% capture tocWorkspace %}
{% comment %}
Copyright (c) 2017 Vladimir "allejo" Jimenez

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
{% endcomment %}
{% comment %}
Version 1.2.0
https://github.com/allejo/jekyll-toc

"...like all things liquid - where there's a will, and ~36 hours to spare, there's usually a/some way" ~jaybe

Usage:
{% include toc.html html=content sanitize=true class="inline_toc" id="my_toc" h_min=2 h_max=3 %}

Parameters:
* html (string) - the HTML of compiled markdown generated by kramdown in Jekyll

Optional Parameters:
* sanitize (bool) : false - when set to true, the headers will be stripped of any HTML in the TOC
* class (string) : '' - a CSS class assigned to the TOC
* id (string) : '' - an ID to assigned to the TOC
* h_min (int) : 1 - the minimum TOC header level to use; any header lower than this value will be ignored
* h_max (int) : 6 - the maximum TOC header level to use; any header greater than this value will be ignored
* ordered (bool) : false - when set to true, an ordered list will be outputted instead of an unordered list
* item_class (string) : '' - add custom class(es) for each list item; has support for '%level%' placeholder, which is the current heading level
* submenu_class (string) : '' - add custom class(es) for each child group of headings; has support for '%level%' placeholder which is the current "submenu" heading level
* base_url (string) : '' - add a base url to the TOC links for when your TOC is on another page than the actual content
* anchor_class (string) : '' - add custom class(es) for each anchor element
* skip_no_ids (bool) : false - skip headers that do not have an `id` attribute

Output:
An ordered or unordered list representing the table of contents of a markdown block. This snippet will only
generate the table of contents and will NOT output the markdown given to it
{% endcomment %}

{% capture newline %}
{% endcapture %}
{% assign newline = newline | rstrip %} <!-- Remove the extra spacing but preserve the newline -->

{% capture deprecation_warnings %}{% endcapture %}

{% if include.baseurl %}
{% capture deprecation_warnings %}{{ deprecation_warnings }}<!-- jekyll-toc :: "baseurl" has been deprecated, use "base_url" instead -->{{ newline }}{% endcapture %}
{% endif %}

{% if include.skipNoIDs %}
{% capture deprecation_warnings %}{{ deprecation_warnings }}<!-- jekyll-toc :: "skipNoIDs" has been deprecated, use "skip_no_ids" instead -->{{ newline }}{% endcapture %}
{% endif %}

{% capture jekyll_toc %}{% endcapture %}
{% assign orderedList = include.ordered | default: false %}
{% assign baseURL = include.base_url | default: include.baseurl | default: '' %}
{% assign skipNoIDs = include.skip_no_ids | default: include.skipNoIDs | default: false %}
{% assign minHeader = include.h_min | default: 1 %}
{% assign maxHeader = include.h_max | default: 6 %}
{% assign nodes = include.html | strip | split: '<h' %}

{% assign firstHeader = true %}
{% assign currLevel = 0 %}
{% assign lastLevel = 0 %}

{% capture listModifier %}{% if orderedList %}ol{% else %}ul{% endif %}{% endcapture %}

{% for node in nodes %}
{% if node == "" %}
{% continue %}
{% endif %}

{% assign currLevel = node | replace: '"', '' | slice: 0, 1 | times: 1 %}

{% if currLevel < minHeader or currLevel > maxHeader %}
{% continue %}
{% endif %}

{% assign _workspace = node | split: '</h' %}

{% assign _idWorkspace = _workspace[0] | split: 'id="' %}
{% assign _idWorkspace = _idWorkspace[1] | split: '"' %}
{% assign htmlID = _idWorkspace[0] %}

{% assign _classWorkspace = _workspace[0] | split: 'class="' %}
{% assign _classWorkspace = _classWorkspace[1] | split: '"' %}
{% assign htmlClass = _classWorkspace[0] %}

{% if htmlClass contains "no_toc" %}
{% continue %}
{% endif %}

{% if firstHeader %}
{% assign minHeader = currLevel %}
{% endif %}

{% capture _hAttrToStrip %}{{ _workspace[0] | split: '>' | first }}>{% endcapture %}
{% assign header = _workspace[0] | replace: _hAttrToStrip, '' %}

{% if include.item_class and include.item_class != blank %}
{% capture listItemClass %} class="{{ include.item_class | replace: '%level%', currLevel | split: '.' | join: ' ' }}"{% endcapture %}
{% endif %}

{% if include.submenu_class and include.submenu_class != blank %}
{% assign subMenuLevel = currLevel | minus: 1 %}
{% capture subMenuClass %} class="{{ include.submenu_class | replace: '%level%', subMenuLevel | split: '.' | join: ' ' }}"{% endcapture %}
{% endif %}

{% capture anchorBody %}{% if include.sanitize %}{{ header | strip_html }}{% else %}{{ header }}{% endif %}{% endcapture %}

{% if htmlID %}
{% capture anchorAttributes %} href="{% if baseURL %}{{ baseURL }}{% endif %}#{{ htmlID }}"{% endcapture %}

{% if include.anchor_class %}
{% capture anchorAttributes %}{{ anchorAttributes }} class="{{ include.anchor_class | split: '.' | join: ' ' }}"{% endcapture %}
{% endif %}

{% capture listItem %}<a{{ anchorAttributes }}>{{ anchorBody }}</a>{% endcapture %}
{% elsif skipNoIDs == true %}
{% continue %}
{% else %}
{% capture listItem %}{{ anchorBody }}{% endcapture %}
{% endif %}

{% if currLevel > lastLevel %}
{% capture jekyll_toc %}{{ jekyll_toc }}<{{ listModifier }}{{ subMenuClass }}>{% endcapture %}
{% elsif currLevel < lastLevel %}
{% assign repeatCount = lastLevel | minus: currLevel %}

{% for i in (1..repeatCount) %}
{% capture jekyll_toc %}{{ jekyll_toc }}</li></{{ listModifier }}>{% endcapture %}
{% endfor %}

{% capture jekyll_toc %}{{ jekyll_toc }}</li>{% endcapture %}
{% else %}
{% capture jekyll_toc %}{{ jekyll_toc }}</li>{% endcapture %}
{% endif %}

{% capture jekyll_toc %}{{ jekyll_toc }}<li{{ listItemClass }}>{{ listItem }}{% endcapture %}

{% assign lastLevel = currLevel %}
{% assign firstHeader = false %}
{% endfor %}

{% assign repeatCount = minHeader | minus: 1 %}
{% assign repeatCount = lastLevel | minus: repeatCount %}
{% for i in (1..repeatCount) %}
{% capture jekyll_toc %}{{ jekyll_toc }}</li></{{ listModifier }}>{% endcapture %}
{% endfor %}

{% if jekyll_toc != '' %}
{% assign rootAttributes = '' %}
{% if include.class and include.class != blank %}
{% capture rootAttributes %} class="{{ include.class | split: '.' | join: ' ' }}"{% endcapture %}
{% endif %}

{% if include.id and include.id != blank %}
{% capture rootAttributes %}{{ rootAttributes }} id="{{ include.id }}"{% endcapture %}
{% endif %}

{% if rootAttributes %}
{% assign nodes = jekyll_toc | split: '>' %}
{% capture jekyll_toc %}<{{ listModifier }}{{ rootAttributes }}>{{ nodes | shift | join: '>' }}>{% endcapture %}
{% endif %}
{% endif %}
{% endcapture %}{% assign tocWorkspace = '' %}{{ deprecation_warnings }}{{ jekyll_toc -}}
50 changes: 50 additions & 0 deletions docs/_layouts/default.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
layout: table_wrappers
---

<!DOCTYPE html>

<html lang="{{ site.lang | default: 'en-US' }}">
{% include head.html %}
<body>
<a class="skip-to-main" href="#main-content">Skip to main content</a>
{% include icons/icons.html %}
{% include components/sidebar.html %}
<div class="main" id="top">
{% include components/header.html %}
<div class="main-content-wrap">
{% include components/breadcrumbs.html %}
<div id="main-content" class="main-content">
<main>
{% if site.heading_anchors != false %}
{% if page.page_toc != false %}
{%- capture source -%}
{% include vendor/anchor_headings.html html=content %}
{%- endcapture -%}
<nav id="toc" class="fs-2">
<h4>In this page</h4>
{% include toc.html html=source h_min=2 %}
</nav>
{% endif %}
{% include vendor/anchor_headings.html html=content beforeHeading="true" anchorBody="<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><use xlink:href=\"#svg-link\"></use></svg>" anchorClass="anchor-heading" anchorAttrs="aria-labelledby=\"%html_id%\"" %}
{% else %}
{{ content }}
{% endif %}

{% if page.has_children == true and page.has_toc != false %}
{% include components/children_nav.html %}
{% endif %}
</main>
{% include components/footer.html %}
</div>
</div>
{% if site.search_enabled != false %}
{% include components/search_footer.html %}
{% endif %}
</div>

{% if site.mermaid %}
{% include components/mermaid.html %}
{% endif %}
</body>
</html>
8 changes: 8 additions & 0 deletions docs/assets/css/site.css
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
/* Copy styles from GH, i.e. https://docs.github.com/en/rest/overview/about-githubs-apis?apiVersion=2022-11-28 */

#toc {
position: sticky;
float: right;
overflow-y: auto;
max-width: 200px;
padding-top: 16px;
padding-left: 24px;
}
1 change: 1 addition & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: FAQ
nav_order: 2
page_toc: false
---
# Reference Implementation FAQ
<!-- #content -->
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Home
nav_order: 1
page_toc: false
---
# ![](https://github.com/devlooped/SponsorLink/raw/main/assets/img/sponsorlink-32.png) SponsorLink

Expand Down
12 changes: 5 additions & 7 deletions docs/privacy.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ apps, extensions and other related software.
This statement applies to the interactions SponsorLink has with you and the SponsorLink products listed below,
as well as other SponsorLink products that display this statement.

# Personal data we collect
## Personal data we collect

SponsorLink does not collect any data unless you explicitly consent to it. You provide this data directly,
by interacting with the SponsorLink GitHub CLI extension and indirectly afterward by interacting with
Expand Down Expand Up @@ -43,7 +43,7 @@ Where providing the data is optional (e.g. it is only used to avoid displaying a
product), and you choose not to share personal data, features like personalization that use such data will
not work for you.

## Email
### Email

Your email is collected *locally* as part of the process of generating a manifest of your sponsorships,
using the SponsorLink GitHub CLI extension. This is done by reading the email(s) associated with your
Expand All @@ -60,7 +60,7 @@ is done *locally* and *offline* by the integrator, by usually running `git confi
and then hashing the result with the sponsorable account to check. If the manifest contains a matching
hash, the integrator can be sure that you are sponsoring the given account.

# How we use personal data
## How we use personal data

SponsorLink uses the data we collect to provide integrators with a mechanism to enable proper attribution
of your (or your organization's) sponsorships to improve the products you use. In particular, we use data to:
Expand All @@ -80,7 +80,7 @@ experience.
> manifest is not present (which requires explicit consent for signing), nothing gets persisted or used
> for any purpose at any time.
# How to access and control your personal data
## How to access and control your personal data

You can also make choices about the collection and use of your data by SponsorLink. You can control your personal
data that SponsorLink has obtained, and exercise your data protection rights, by contacting SponsorLink or using
Expand All @@ -93,7 +93,7 @@ Using the tool, you can:

All personal data processed by SponsorLink can be accessed or controlled via this tool.

# SponsorLink Account
## SponsorLink Account

With a SponsorLink account, you can sign your sponsorship manifest. Personal data associated with your SponsorLink
account includes only your GitHub user identifier. Signing in to your SponsorLink account (using your GitHub account
Expand All @@ -103,5 +103,3 @@ When you remove your data using the above tool, we delete all data associated wi
Subsequent authentication with SponsorLink will create a new account, even if the same GitHub user identifier is used.
This will be manifest in the tool by a different GUID being used for salting hashes, as well as the authorization
flow from github.com being triggered again.

<!-- ../privacy.md -->

0 comments on commit df008e5

Please sign in to comment.