diff --git a/book.toml b/book.toml index 936e582..e2d91b3 100644 --- a/book.toml +++ b/book.toml @@ -21,6 +21,7 @@ edit-url-template = "https://github.com/KaiserY/trpl-zh-cn/edit/main/{path}" [output.typst-pdf] pdf = true section-number = true +rust-book = true [rust] edition = "2021" diff --git a/ferris.css b/ferris.css index caa2ee7..513efa1 100644 --- a/ferris.css +++ b/ferris.css @@ -42,4 +42,26 @@ body.ayu .not_desired_behavior { .ferris-explain { width: 100px; -} \ No newline at end of file +} + +/* + A bit of a hack to make small Ferris use the existing buttons container but + only show/hide the buttons on hover over the `pre`. Targeting `.listing` + increases the specificity of this rule. +*/ +pre > .buttons { + visibility: visible; + opacity: 1; + transition: none; +} + +pre > .buttons button { + visibility: hidden; + opacity: 0; + transition: visibility 0.1s linear, opacity 0.1s linear; +} + +pre:hover > .buttons button { + visibility: visible; + opacity: 1; +} diff --git a/ferris.js b/ferris.js index 4fd025e..13b1ceb 100644 --- a/ferris.js +++ b/ferris.js @@ -1,65 +1,102 @@ -var ferrisTypes = [ +// @ts-check + +/** + * @typedef {{ attr: string, title: string }} FerrisType + */ + +/** @type {Array} */ +const FERRIS_TYPES = [ { - attr: 'does_not_compile', - title: '这段代码无法通过编译!' + attr: "does_not_compile", + title: "This code does not compile!", }, { - attr: 'panics', - title: '这段代码会 Panic!' + attr: "panics", + title: "This code panics!", }, { - attr: 'not_desired_behavior', - title: '这段代码的运行结果不符合预期。' - } -] + attr: "not_desired_behavior", + title: "This code does not produce the desired behavior.", + }, +]; -document.addEventListener('DOMContentLoaded', () => { - for (var ferrisType of ferrisTypes) { - attachFerrises(ferrisType) +document.addEventListener("DOMContentLoaded", () => { + for (let ferrisType of FERRIS_TYPES) { + attachFerrises(ferrisType); } -}) +}); +/** + * @param {FerrisType} type + */ function attachFerrises(type) { - var elements = document.getElementsByClassName(type.attr) + let elements = document.getElementsByClassName(type.attr); - for (var codeBlock of elements) { - var lines = codeBlock.innerText.replace(/\n$/, '').split(/\n/).length - var size = 'large' - if (lines < 4) { - size = 'small' + for (let codeBlock of elements) { + // Skip SVG etc.: in principle, these should never be attached to those, but + // this means if someone happens to have a browser extension which *is* + // attaching them, it will not break the code. + if (!(codeBlock instanceof HTMLElement)) { + continue; } - var container = prepareFerrisContainer(codeBlock, size == 'small') - container.appendChild(createFerris(type, size)) + let codeLines = codeBlock.innerText; + let extra = codeLines.endsWith("\n") ? 1 : 0; + let numLines = codeLines.split("\n").length - extra; + + /** @type {'small' | 'large'} */ + let size = numLines < 4 ? "small" : "large"; + + let container = prepareFerrisContainer(codeBlock, size == "small"); + if (!container) { + continue; + } + + container.appendChild(createFerris(type, size)); } } +/** + * @param {HTMLElement} element - Code block element to attach a Ferris to. + * @param {boolean} useButtons - Whether to attach to existing buttons. + * @returns {Element | null} - The container element to use. + */ function prepareFerrisContainer(element, useButtons) { - var foundButtons = element.parentElement.querySelector('.buttons') + let foundButtons = element.parentElement?.querySelector(".buttons"); if (useButtons && foundButtons) { - return foundButtons + return foundButtons; } - var div = document.createElement('div') - div.classList.add('ferris-container') + let div = document.createElement("div"); + div.classList.add("ferris-container"); - element.parentElement.insertBefore(div, element) + if (!element.parentElement) { + console.error(`Could not install Ferris on ${element}, which is missing a parent`); + return null; + } - return div + element.parentElement.insertBefore(div, element); + + return div; } +/** + * @param {FerrisType} type + * @param {'small' | 'large'} size + * @returns {HTMLAnchorElement} - The generated anchor element. + */ function createFerris(type, size) { - var a = document.createElement('a') - a.setAttribute('href', 'ch00-00-introduction.html#ferris') - a.setAttribute('target', '_blank') + let a = document.createElement("a"); + a.setAttribute("href", "ch00-00-introduction.html#ferris"); + a.setAttribute("target", "_blank"); - var img = document.createElement('img') - img.setAttribute('src', 'img/ferris/' + type.attr + '.svg') - img.setAttribute('title', type.title) - img.classList.add('ferris') - img.classList.add('ferris-' + size) + let img = document.createElement("img"); + img.setAttribute("src", "img/ferris/" + type.attr + ".svg"); + img.setAttribute("title", type.title); + img.classList.add("ferris"); + img.classList.add("ferris-" + size); - a.appendChild(img) + a.appendChild(img); - return a -} \ No newline at end of file + return a; +} diff --git a/theme/2018-edition.css b/theme/2018-edition.css index b1dcf93..2276ccb 100644 --- a/theme/2018-edition.css +++ b/theme/2018-edition.css @@ -1,9 +1,9 @@ span.caption { - font-size: .8em; - font-weight: 600; + font-size: 0.8em; + font-weight: 600; } span.caption code { - font-size: 0.875em; - font-weight: 400; + font-size: 0.875em; + font-weight: 400; } diff --git a/theme/listing.css b/theme/listing.css index 5998d39..40ae35a 100644 --- a/theme/listing.css +++ b/theme/listing.css @@ -1,8 +1,8 @@ figure.listing { - margin: 0; + margin: 0; } .listing figcaption { - font-size: .8em; - font-weight: 600; + font-size: 0.8em; + font-weight: 600; } diff --git a/theme/semantic-notes.css b/theme/semantic-notes.css index 7e68eb3..b6852a0 100644 --- a/theme/semantic-notes.css +++ b/theme/semantic-notes.css @@ -4,10 +4,10 @@ identical while updating the presentation. */ .note { - margin: 20px 0; - padding: 0 20px; - color: var(--fg); - background-color: var(--quote-bg); - border-block-start: 0.1em solid var(--quote-border); - border-block-end: 0.1em solid var(--quote-border); + margin: 20px 0; + padding: 0 20px; + color: var(--fg); + background-color: var(--quote-bg); + border-block-start: 0.1em solid var(--quote-border); + border-block-end: 0.1em solid var(--quote-border); }