NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name hammerspoon.org Documentation
// @license MIT
// @version 2019.08.16
// @description Add TOC
// @author krasnovpro
// @include /^https?://(.*hammerspoon\.org/(docs|Spoons)|(127\.0\.0\.1|localhost):12345)/.*$/
// @updateURL https://openuserjs.org/meta/krasnovpro/hammerspoon.org_Documentation.meta.js
// @downloadURL https://openuserjs.org/src/scripts/krasnovpro/hammerspoon.org_Documentation.user.js
// @require https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
// @grant none
// ==/UserScript==
let cssToc = `<style>
html {
left: 0;
top: 30px;
}
body {
background: var(--line);
padding: 0;
margin-top: 0;
}
td, p, li {
font-family: var(--ftitle);
font-size: var(--fsize);
font-weight: 100;
}
.api-documentation-overview th,
.api-documentation-overview td {
border-top: 1px solid #444;
padding-top: calc(var(--margin) / 3);
padding-left: var(--margin);
}
</style>`.trim();
let cssIndex = `<style>
header>h1 {
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
}
/* top urls block */
.urls {
height: 1.3em;
overflow: hidden;
margin-bottom: var(--margin);
padding: var(--margin);
padding-top: 0;
transition: height .3s ease-in-out;
}
.urls:hover {
height: 13em;
}
.urls * {
font-size: var(--fsize);
line-height: var(--flheight);
}
.urls tr:first-of-type,
.urls+br,
body>br {
display: none !important;
}
.api-documentation-overview th,
.api-documentation-overview td {
border-top: 1px solid var(--line);
padding-top: calc(var(--margin) / 3);
padding-left: var(--margin);
}
.api-documentation-overview p {
font-family: var(--ftitle);
font-weight: 100;
font-size: var(--fsize);
}
/* search */
#search,
#search_desc {
left: calc(var(--mleft) + var(--margin));
top: 4rem;
width: calc(100% - var(--mleft) - var(--mright) - var(--margin) * 3);
}
#search_desc {
left: calc(100% - var(--mright) - var(--margin) * 2);
width: var(--margin);
}
</style>`.trim();
let cssInner = `<style>
:root {
--bg: #222;
--line: #333;
--text: #bbb;
--link: #b73;
--desc: white;
--ftitle: "Open Sans", "Roboto", Helvetica, Arial, sans-serif;
--ftext: var(--ftitle);
--fcode: "PragmataPro", "Menlo", "Lucida Console", Courier, monospace;
--fsize: .7rem;
--flheight: 1.5;
--margin: 15px;
--mleft: 20%;
--mleft: 20vw;
--mright: calc(var(--mleft)/2);
--mbot: var(--mleft);
}
/* toc */
#toc {
border: none;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
box-shadow: 0 calc(var(--margin) / 2) calc(var(--margin) * 2) calc(var(--margin) / -2) #000f;
height: 20px;
left: var(--mleft);
opacity: 0;
position: fixed;
top: 51px;
transition: height .2s ease-in-out, opacity .2s ease-in-out;
width: calc(100% - var(--mleft) - var(--mright));
}
#toc:hover {
height: calc(100% - var(--mbot));
opacity: 1;
}
#hint {
background: var(--line);
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
color: var(--link);
font-family: var(--ftext);
font-size: var(--fsize);
left: calc(var(--mleft) + 10px);
line-height: 10px;
margin: 0;
margin-left: -10px;
padding: 10px;
padding-top: 0;
position: fixed;
top: 52px;
}
/* sidebar */
.sidebar {
height: 100%;
left: 0;
overflow-y: scroll;
padding: calc(var(--margin) / 2) var(--margin);
position: fixed;
top: 0;
width: var(--mleft);
}
.sidebar * {
font-size: var(--fsize);
line-height: var(--flheight);
list-style: none;
padding: 0;
}
.sidebar ul ul {
margin: 0;
margin-bottom: var(--margin);
}
.sidebar ul ul li {
font-family: var(--fcode);
}
/* common */
html {
bottom: 0;
left: var(--mleft);
overflow: auto;
position: fixed;
top: 92px;
}
body {
background: var(--bg);
border: none;
color: var(--text);
height: 100%;
margin: 0;
padding: 0 var(--mright) 10px 0;
width: 100%;
overflow: auto;
}
h1, h2, h3, h4, h5, h6 {
border: none;
font-family: var(--ftitle);
font-weight: 100;
margin: 0;
}
h1 {font-size: 4rem;}
h2 {font-size: 3.5rem;}
h3 {font-size: 3rem;}
h4 {font-size: 2.5rem;}
h5 {font-size: 2rem;}
h6 {font-size: 1.5rem;}
a {
color: var(--link);
text-decoration: none;
}
a:hover {
border-bottom: 1px solid #b737;
text-decoration: none;
}
.api-documentation-overview,
.api-documentation-overview p {
margin: 0;
}
table {
padding: 0;
margin: 0;
}
table tr,
table th,
table td,
table tr:nth-child(2n),
.documentation-section {
border: none;
background: none;
padding: 0;
padding-right: 10px;
}
td, p, li {
font-family: var(--ftext);
font-size: 1.2rem;
font-weight: 300;
letter-spacing: .02rem;
line-height: var(--flheight);
}
ul {
list-style-type: circle;
padding-left: 1.5rem;
}
.highlight pre,
pre,
code {
background: var(--line);
color: var(--text);
font-family: var(--fcode);
padding: 0;
white-space: pre-wrap !important;
}
code:before,
code:after {
content: "";
}
td:nth-child(2) {
word-break: break-word;
}
/* index */
section table th:nth-child(1),
.tabcontent table td:nth-child(1) {
font-family: var(--fcode);
font-size: var(--fsize);
font-weight: normal;
padding-right: var(--margin);
}
section table.api-documentation-overview tr:not(:nth-child(1)) td,
section table.api-documentation-overview tr:not(:nth-child(1)) th {
padding-bottom: calc(var(--margin) / 2);
}
/* header */
header>h1 {
background: var(--line);
border-bottom: 1px solid var(--line);
color: var(--desc);
font-size: 2.5rem;
height: 52px;
left: var(--mleft);
margin: 0;
padding: 0 10px;
position: fixed;
top: 0;
width: calc(100% - var(--mleft) - var(--mright));
}
/* search */
#search,
#search_desc {
background-color: transparent;
border: none;
color: var(--text);
font-family: var(--fcode);
font-size: 1rem;
height: 1rem;
left: var(--margin);
outline: none;
padding: 0;
position: fixed;
top: 0;
width: calc(100% - var(--margin) * 3);
}
#search_desc {
left: calc(100% - var(--margin) * 2);
width: var(--margin);
}
.searchresults {
margin: 0 var(--margin);
}
.searchresults h2 {
display: none;
}
.searchresults h3 {
color: var(--text);
font-size: var(--fsize);
margin-top: var(--margin);
}
.searchresults h3:first-of-type {
margin-top: 0;
}
.searchresults ul.results {
list-style: none;
margin: 0;
}
.searchresults li {
font-family: var(--fcode);
font-size: var(--fsize);
list-style: none;
}
.searchresults li:last-of-type {
margin-bottom: calc(var(--margin) * 2);
}
/* items title */
h3:nth-of-type(2),
section[id] table tr th {
display: none;
}
/* signature */
section[id] table tr:nth-child(1) td code {
font-family: var(--fcode);
}
/* type */
section[id] table tr:nth-child(2) td,
.note {
font-family: var(--fcode);
font-size: var(--fsize);
margin: 0;
opacity: .5;
padding: 0;
}
/* description */
section[id] table tr:nth-child(3) td>p:nth-child(1) {
color: var(--desc);
font-family: var(--ftitle);
font-weight: 100;
letter-spacing: .05em;
margin-top: var(--margin);
}
/* tabbar */
div.tab {
background-color: inherit;
border: none;
}
div.tab button {
color: var(--link);
background-color: inherit;
padding: calc(var(--margin) / 2) var(--margin);
}
div.tab button:hover {
background-color: var(--link);
color: var(--bg);
}
div.tab button.tablinks.active {
background-color: inherit;
color: var(--text);
}
</style>`.trim();
(() => {
if (document.title.match(/^Hammerspoon (.poons )*.ocs$/)) { // index page
$('body').append(cssInner + cssIndex);
for (let find of [
'h3',
]) $(find).remove();
$('th:contains("Resource"), td:contains("Resource")').parents('section').addClass('urls');
$('#search_desc').attr('title', 'search descriptions');
}
else { // inner pages
for (let find of [
'Parameters:',
'Paramters:',
'Returns:',
'Notes:',
]) $('p:contains(' + find + ')').addClass('note');
$('h3:contains("API Overview")+ul').wrap('<div class="sidebar"></div>');
$('body').append(cssInner + '<div id="hint">⌘</div>');
let toc = document.createElement('iframe'); // add toc menu
toc.id = 'toc';
toc.src = $('header>h1>a:first-child').attr('href');
$('body').append(toc);
$('#toc').on('load', () => {
toc = $('#toc').contents();
toc.find('header').remove();
toc.find('th:contains("Resource")').parents('section').remove();
toc.find('html').append(cssInner + cssToc);
toc.find('head').append('<base target="_top">');
toc.find('#search_desc').attr('alt', 'Search descriptions');
});
}
// all pages
for (let find of [
'API Overview',
'API Documentation',
]) $('h3:contains(' + find + ')').remove();
$('section:contains("Search descriptions")').contents().filter(function () {
return this.nodeType === 3;
}).remove();
$('#search').focus();
})();