Skip to content

Instantly share code, notes, and snippets.

@philschatz
Last active May 27, 2020 16:57
Show Gist options
  • Save philschatz/1521fa5e746b970b43d1dce34ac5bbad to your computer and use it in GitHub Desktop.
Save philschatz/1521fa5e746b970b43d1dce34ac5bbad to your computer and use it in GitHub Desktop.
Greasemonkey Script for QA'ing openstax content
// ==UserScript==
// @name Openstax QA Helpers
// @version 2
// @grant none
// @include https://cnx.org/*
// @include https://*.cnx.org/*
// @include https://openstax.org/*
// @include https://*.openstax.org/*
// ==/UserScript==
// Examples:
// https://openstax.org/books/astronomy/pages/3-2-newtons-great-synthesis#fs-id1163976559032
// https://archive-qa.cnx.org/contents/[email protected]:jccCTwYm@15/3-2-Newton-s-Great-Synthesis#fs-id1163976529854
(function() {
'use strict';
const style = window.document.createElement('style')
style.textContent = `/* Greasemonkey-injected styling */
/* Linking to a specific element should highlight the element */
:target {
background-color: #ffffcc;
border: 1px dotted #000000;
animation-name: cssAnimation;
animation-duration: 10s;
animation-timing-function: ease-out;
animation-delay: 0s;
animation-fill-mode: forwards;
}
@keyframes cssAnimation {
to {
background-color: initial;
border: initial;
}
}
/* Style footnotes so that they stand out */
[role="doc-footnote"] { background-color: #ffcccc; border: 1px dashed #ff0000; }
[role="doc-footnote"]:before { content: "FOOTNOTE " ; }
/* Show a permalink when hovering over a heading or paragraph */
*:not(:hover) > a.-permalinker { display: none; }
* > a.-permalinker {
margin-left: .1rem;
font-weight: bold;
text-decoration: none;
}
`
window.document.head.appendChild(style)
const pilcrow = '¶'
const headingsSelector = [
'*[id] > h1:not([data-dev-has-permalink])',
'*[id] > h2:not([data-dev-has-permalink])',
'*[id] > h3:not([data-dev-has-permalink])',
'*[id] > h4:not([data-dev-has-permalink])',
'*[id] > h5:not([data-dev-has-permalink])',
'*[id] > h6:not([data-dev-has-permalink])'
].join(', ')
const grandHeadingsSelector = [
'*[id] > header > h1:not([data-dev-has-permalink])',
'*[id] > header > h2:not([data-dev-has-permalink])',
'*[id] > header > h3:not([data-dev-has-permalink])',
'*[id] > header > h4:not([data-dev-has-permalink])',
'*[id] > header > h5:not([data-dev-has-permalink])',
'*[id] > header > h6:not([data-dev-has-permalink])',
].join(', ')
function addPermalink(parent, id) {
const link = window.document.createElement('a')
link.classList.add('-permalinker')
link.setAttribute('href', `#${id}`)
link.textContent = pilcrow
parent.setAttribute('data-dev-has-permalink', true)
parent.appendChild(link)
}
function addLinks() {
const paragraphs = Array.from(window.document.querySelectorAll('p[id]:not([data-dev-has-permalink])'))
paragraphs.forEach(p => addPermalink(p, p.getAttribute('id')) )
Array.from(window.document.querySelectorAll(headingsSelector)).forEach(h => addPermalink(h, h.parentElement.getAttribute('id')) )
Array.from(window.document.querySelectorAll(grandHeadingsSelector)).forEach(h => addPermalink(h, h.parentElement.parentElement.getAttribute('id')) )
}
// Loop because SinglePageApps reload the content
setInterval(addLinks, 5 * 1000)
addLinks()
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment