SCRIPT FOR SCRIPT_AUTO_RUNNER TO MAKE SICP TEXTBOOK MORE READABLE

Overview

Help me improve my English!
As you probably see, I'm not a native English speaker.
If you find an English expression that feel incorrect or awkward, please let me know.

Message box of Disqus is under the article.
Or my E-Mail is here.

ABOUT THIS ARTICLE

Brief Summary

We can do syntax-highlighting to unhighlighted code-blocks using a library from CDN.
We use ScriptAutoRunner for execution environment.

Hello, I'm dede.

In this article, I'll introduce a way to make SICP textbook, which is available to the public on the web, more readable
by using a short script.

WHAT'S SICP

ABOUT

SICP textbook is one of the most famous and effective CS books.
It describes frequent patterns in computer programming, such as recursive procedures and the benefits of modularity.

PUBLISHED WEB SITE

Here is a published content in web site equivalent to its book version.

SOME PROBREMS

About above web site I found myself a bit difficult to read in several respects.

  • The book uses Scheme, one of the variations of lisp language, but code blocks are not syntax-highlighted so are not very readable.
  • The texts in footnote are a bit small.

I wrote a JS script to modify their design which runs on browser.

Normally in order to run self-made Javascript code on browser, we take a way either to run it interactively in developer-console or to register the code as a Bookmarklet and run it.
But both of them have a disadvantage that we must run it whenever we reload the page.

However there is a useful extension with respect to Chrome.

WHAT'S SCRIPT_AUTO_RUNNER

[ScriptAutoRunner

This is a useful Chrome extension in which we register a pair of specific domain string and script code we want to run, and whenever we open/reload a page of target domain the code runs automatically.

ScriptAutoRunner from official

CREATION ENVIRONMENT AND USED TOOL

  • Google Chrome version: 101.0.4951.67
  • highlight.js v11.5.1

SCRIPT CODE

WHOLE CODE

Here is a whole code.
Following sections describe meaning of each and its behavior.

 1// if document is not fully loaded, load event take the place
 2if (document.readyState === "complete") {
 3    restyleSICP();
 4} else {
 5    window.addEventListener("load", restyleSICP);
 6}
 7
 8function restyleSICP() {
 9    // only in specific paths this script runs
10    if (!window.location.pathname.startsWith("/sites/default/files/sicp/full-text/book")) return;
11    highlightSchemeCode();
12    expandFootnote();
13}
14
15function highlightSchemeCode() {
16    // exclude elements which contain some img elements
17    const targetTts = Array.from(document.querySelectorAll("p > tt:first-child:last-child")).filter(e => !e.querySelector("img"));
18
19    for (const tt of targetTts) {
20        const pre = document.createElement("pre");
21        const code = document.createElement("code");
22
23        code.classList.add("language-scheme");
24        code.innerHTML = tt.innerHTML;
25
26        // replace tt element with pre + code elements
27        pre.append(code);
28        tt.before(pre);
29        tt.remove();
30    }
31
32    const link = document.createElement("link");
33    link.rel = "stylesheet";
34    link.href = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/a11y-dark.min.css";
35
36    const hlScr = document.createElement("script");
37    hlScr.src = "//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js";
38    hlScr.onload = () => {
39        hljs.configure({
40            ignoreUnescapedHTML: true
41        });
42        const schemeScr = document.createElement("script");
43        schemeScr.src = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/scheme.min.js";
44        schemeScr.onload = () => hljs.highlightAll();
45        document.head.append(schemeScr);
46
47    }
48    document.head.append(link, hlScr);
49
50
51}
52
53function expandFootnote() {
54    document.querySelector(".footnote").style.fontSize = "1rem";
55}

LAUNCHING

1// if document is not fully loaded, load event take the place
2if (document.readyState === "complete") {
3    restyleSICP();
4} else {
5    window.addEventListener("load", restyleSICP);
6}

The running timing of main processing is diferrent between the case in which DOM reading of the page is not yet complete and the case in which it has already been complete.

CHECK IF RUN OR NOT

1function restyleSICP() {
2    // only in specific paths this script runs
3    if (!window.location.pathname.startsWith("/sites/default/files/sicp/full-text/book")) return;
4    // ...
5}

Unfortunately ScriptAutoRunner allows us to specify a domain but not a path, so we check if it can run Subsequent processing or not by fetching the page's url.

HIGHLIGHTING

 1function highlightSchemeCode() {
 2    // exclude elements which contain some img elements
 3    const targetTts = Array.from(document.querySelectorAll("p > tt:first-child:last-child")).filter(e => !e.querySelector("img"));
 4
 5    for (const tt of targetTts) {
 6        const pre = document.createElement("pre");
 7        const code = document.createElement("code");
 8
 9        code.classList.add("language-scheme");
10        code.innerHTML = tt.innerHTML;
11
12        // replace tt element with pre + code elements
13        pre.append(code);
14        tt.before(pre);
15        tt.remove();
16    }
17
18    

All Page's Elements corresponding to Scheme code block are tt elements.
We search them and replace pre element + code element so that highlight.js finds them as a highlighting target.

Some code blocks contains img elementsm and We exclude them because highlighting is not effective for them.

 1const link = document.createElement("link");
 2    link.rel = "stylesheet";
 3    link.href = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/a11y-dark.min.css";
 4
 5    const hlScr = document.createElement("script");
 6    hlScr.src = "//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/highlight.min.js";
 7    hlScr.onload = () => {
 8        hljs.configure({
 9            ignoreUnescapedHTML: true
10        });
11        const schemeScr = document.createElement("script");
12        schemeScr.src = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/scheme.min.js";
13        schemeScr.onload = () => hljs.highlightAll();
14        document.head.append(schemeScr);
15
16    }
17    document.head.append(link, hlScr);
18
19
20}

Via CDN we read main script of hl and optional script for Scheme successively and when all completed highlightAll runs.

RESTYLE A FOOTNOTE

1function expandFootnote() {
2    document.querySelector(".footnote").style.fontSize = "1rem";
3}

DEMO

before

after

comments powered by Disqus

Translations: