Nexoniarz is the sole author and SchOS was never published under Apache-2.0, so this is a straight relicence. LICENSE is the FSF GPLv2 text, every first-party SPDX header moves to GPL-2.0-or-later, and NOTICE, README.md, docs/licensing.md and the site say so. projects/schfs-linux follows the rest of the tree. The GPL gives copyleft: a fork has to ship its source. It also lifts the old "Linux drivers, never" rule, since GPL-2.0-only code combines with GPL-2.0-or-later. "Or later" leaves room for GPLv3, but one binary still has to pick one version, so docs/licensing.md now keeps Apache-2.0 and GPLv3 code out of the kernel to keep Linux code possible there. BSD 4-clause code goes from "avoid" to "no", because the advertising clause is GPL-incompatible. LDLS still ships no .ko. That boundary is now project policy rather than a legal requirement, and ldls.md, devices.md and licensing.md section 6 say so. refmod declares license=GPL, and ldls-check passes (27 checks). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
115 lines
4.4 KiB
JavaScript
115 lines
4.4 KiB
JavaScript
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*
|
|
* Three behaviours, no framework:
|
|
* 1. the hero console types a real boot log
|
|
* 2. sections fade in once, as they arrive
|
|
* 3. the bar takes a shadow once the page has scrolled under it
|
|
*
|
|
* All three are decoration. If this file fails to load the page is still
|
|
* complete and still readable, which is the test any script on a
|
|
* documentation site should have to pass.
|
|
*
|
|
* Niveus does the rest: its own niveus.js wires the appearance buttons, and
|
|
* everything visual comes from the stylesheet. Nothing here sets a style.
|
|
*/
|
|
(function () {
|
|
"use strict";
|
|
|
|
var reduced = window.matchMedia &&
|
|
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
|
|
/* ---- 1. the boot log ------------------------------------------------
|
|
* These are real lines from a real boot, not invented ones. The timer
|
|
* calibration line in particular is there because of what it cost: the
|
|
* clock ran seven times slow until a graphics driver was made to
|
|
* acknowledge its own interrupt. See docs/history/kernel.md.
|
|
*/
|
|
var LINES = [
|
|
{ t: "[ 0.000]", k: "SchIFT", s: " 64-bit, 2 cpus" },
|
|
{ t: "[ 0.004]", k: "cpu0", s: ": lapic timer 999941980 Hz, tsc 3792 MHz" },
|
|
{ t: "[ 0.049]", k: "virtio-gpu", s: ": 1280x800, 4000 KB framebuffer" },
|
|
{ t: "[ 0.088]", k: "e1000", s: ": 52:54:00:12:34:56, link up, irq 11" },
|
|
{ t: "[ 0.143]", k: "schfs", s: ": mounted 'schos', generation 2" },
|
|
{ t: "[ 0.169]", k: "net", s: ": eth0 10.0.2.15/255.255.255.0" },
|
|
{ t: "[ 0.204]", k: "schinit", s: ": ready (pid 1)" },
|
|
{ t: "[ 0.212]", k: "schinitd", s: ": 2 job(s) loaded, generation 1", g: true },
|
|
{ t: "", k: "", s: "# " }
|
|
];
|
|
|
|
var out = document.getElementById("bootlog");
|
|
|
|
/* The classes are Niveus text roles, so the log is coloured by the same
|
|
tokens as the rest of the page and follows the appearance with it. */
|
|
function span(cls, text) {
|
|
var e = document.createElement("span");
|
|
if (cls) e.className = cls;
|
|
e.textContent = text;
|
|
return e;
|
|
}
|
|
|
|
function emit(line) {
|
|
if (line.t) {
|
|
out.appendChild(span("nv-text-tertiary", line.t + " "));
|
|
out.appendChild(span("nv-text-accent", line.k));
|
|
}
|
|
out.appendChild(span(line.g ? "nv-text-success" : "", line.s));
|
|
out.appendChild(document.createTextNode("\n"));
|
|
}
|
|
|
|
if (out && reduced) {
|
|
LINES.forEach(emit); // the whole log at once, no animation
|
|
} else if (out) {
|
|
var i = 0;
|
|
(function step() {
|
|
if (i >= LINES.length) return;
|
|
emit(LINES[i++]);
|
|
/* Uneven on purpose: a boot that ticks out at a metronome's pace reads
|
|
as a progress bar rather than as a machine doing different work. */
|
|
setTimeout(step, 180 + Math.random() * 220);
|
|
})();
|
|
}
|
|
|
|
/* ---- 2. reveal on scroll ------------------------------------------ */
|
|
|
|
var targets = document.querySelectorAll("[data-reveal]");
|
|
|
|
if (reduced || !("IntersectionObserver" in window)) {
|
|
Array.prototype.forEach.call(targets, function (el) {
|
|
el.classList.add("is-revealed");
|
|
});
|
|
} else {
|
|
var io = new IntersectionObserver(function (entries) {
|
|
entries.forEach(function (entry) {
|
|
if (!entry.isIntersecting) return;
|
|
entry.target.classList.add("is-revealed");
|
|
io.unobserve(entry.target); // once, not on every scroll past
|
|
});
|
|
}, { rootMargin: "0px 0px -12% 0px", threshold: 0.05 });
|
|
|
|
Array.prototype.forEach.call(targets, function (el) { io.observe(el); });
|
|
}
|
|
|
|
/* ---- 3. the bar, once something has passed under it ---------------- */
|
|
|
|
var bar = document.querySelector(".nv-nav");
|
|
|
|
if (bar) {
|
|
var onScroll = function () {
|
|
if (window.scrollY > 8) bar.setAttribute("data-scrolled", "");
|
|
else bar.removeAttribute("data-scrolled");
|
|
};
|
|
addEventListener("scroll", onScroll, { passive: true });
|
|
onScroll();
|
|
}
|
|
|
|
/* ---- and remember the appearance ----------------------------------- */
|
|
/*
|
|
* Niveus changes the appearance; which one was chosen is this site's to
|
|
* keep. The inline script in <head> reads it back before first paint.
|
|
*/
|
|
document.documentElement.addEventListener("nv:theme", function (event) {
|
|
try {
|
|
localStorage.setItem("schos-theme", (event.detail && event.detail.theme) || "system");
|
|
} catch (e) { /* storage unavailable — the choice lasts this visit */ }
|
|
});
|
|
})();
|