site: a lit hero, new slogans, the wallpapers, and a better reader
Home: - The hero stands on a light from the upper left and a pool of the accent, mixed from Niveus tokens so it follows the theme. The mark sits in an .nv-tile key under a slogan: "Every layer its own -- from the first instruction to the last pixel." - New section headings: "A teaching kernel that outgrew its lessons", "Measured, not marketed", "One ISO. One stick. Your disks untouched." - A Wallpapers section with the four new ones, each downloadable as a 4K JPEG or as SVG. The four-card grids are two across, so none is left alone on its row. Docs reader: - An index filter, a breadcrumb with reading time and source path, code blocks framed with a language strip and a Copy key, previous and next keys at the foot, a reading-progress hairline, and the contents entry lit for the section on screen. - The index lists the documents it was missing: scheduler, FAT, audio, LDLS, debugging and the hardware report. - On a phone the page is no longer wider than the screen (a pre block was sizing the grid's auto column), and the index folds away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
1fd73740f8
commit
7af579a20d
4 changed files with 421 additions and 19 deletions
|
|
@ -55,6 +55,28 @@
|
||||||
|
|
||||||
/* --- Hero ------------------------------------------------------------------ */
|
/* --- Hero ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/* The band behind the hero, lit the way the Graphite wallpaper is: a light
|
||||||
|
from the upper left, and a pool of the accent on the surface the window
|
||||||
|
stands on. Mixed from the system's own tokens rather than from the picture,
|
||||||
|
so it follows the brand and the appearance instead of fighting the copy. */
|
||||||
|
.heroband {
|
||||||
|
background:
|
||||||
|
radial-gradient(ellipse 45% 38% at 68% 62%,
|
||||||
|
color-mix(in oklab, var(--nv-color-accent) 45%, transparent), transparent 72%),
|
||||||
|
radial-gradient(ellipse 60% 70% at 18% 0%,
|
||||||
|
color-mix(in oklab, var(--nv-color-text-primary) 7%, transparent), transparent 70%),
|
||||||
|
var(--nv-color-background);
|
||||||
|
padding-block-end: var(--nv-space-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero__tile {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero__slogan {
|
||||||
|
max-inline-size: 22ch;
|
||||||
|
}
|
||||||
|
|
||||||
.hero {
|
.hero {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: var(--nv-space-12);
|
gap: var(--nv-space-12);
|
||||||
|
|
@ -88,6 +110,41 @@
|
||||||
block-size: 1.15em;
|
block-size: 1.15em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- Wallpapers ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Two across, not auto-fit: four of anything at three per row leaves one
|
||||||
|
alone on the last, which reads as an afterthought. */
|
||||||
|
.walls,
|
||||||
|
#docs .nv-card-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--nv-space-5);
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 48rem) {
|
||||||
|
.walls,
|
||||||
|
#docs .nv-card-grid { grid-template-columns: 1fr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.wall {
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wall__img {
|
||||||
|
inline-size: 100%;
|
||||||
|
block-size: auto;
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wall__caption {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--nv-space-2);
|
||||||
|
padding: var(--nv-space-4) var(--nv-space-5) var(--nv-space-5);
|
||||||
|
}
|
||||||
|
|
||||||
/* --- The console ----------------------------------------------------------- */
|
/* --- The console ----------------------------------------------------------- */
|
||||||
/*
|
/*
|
||||||
A terminal is a window into the machine, so it is drawn as one: a solid
|
A terminal is a window into the machine, so it is drawn as one: a solid
|
||||||
|
|
@ -367,11 +424,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.docshell {
|
.docshell {
|
||||||
max-inline-size: var(--nv-layout-max-width);
|
/* Wider than the rest of the site: the document column carries tables and
|
||||||
|
diagrams that the prose measure would squeeze, and both side panels have
|
||||||
|
to fit beside it. */
|
||||||
|
max-inline-size: calc(var(--nv-layout-max-width) + 16rem);
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
padding-inline: var(--nv-layout-gutter);
|
padding-inline: var(--nv-layout-gutter);
|
||||||
padding-block: var(--nv-space-8) var(--nv-space-16);
|
padding-block: var(--nv-space-8) var(--nv-space-16);
|
||||||
display: grid;
|
display: grid;
|
||||||
|
/* minmax(0, ...) even with one column: a code block is white-space: pre,
|
||||||
|
and an auto column grows to its longest line -- which on a phone made
|
||||||
|
the whole page wider than the screen. */
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
gap: var(--nv-space-8);
|
gap: var(--nv-space-8);
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
@ -385,6 +449,13 @@
|
||||||
|
|
||||||
@media (max-width: 64rem) {
|
@media (max-width: 64rem) {
|
||||||
.docshell__rail { display: none; }
|
.docshell__rail { display: none; }
|
||||||
|
|
||||||
|
/* One column: the index stops following the reader and folds away, so
|
||||||
|
the document is the first thing on the screen rather than the fortieth. */
|
||||||
|
.docshell__aside {
|
||||||
|
position: static;
|
||||||
|
max-block-size: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Both panels follow the reader down the page, under the bar rather than
|
/* Both panels follow the reader down the page, under the bar rather than
|
||||||
|
|
@ -457,6 +528,36 @@
|
||||||
border-block-end: var(--nv-border-width) solid var(--nv-color-border-subtle);
|
border-block-end: var(--nv-border-width) solid var(--nv-color-border-subtle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A code block is a small window: a raised strip naming the language, with
|
||||||
|
the copy key on it, over the recess the code sits in. */
|
||||||
|
.codeframe {
|
||||||
|
margin: 0;
|
||||||
|
border-radius: var(--nv-radius-md);
|
||||||
|
overflow: hidden;
|
||||||
|
background: var(--nv-color-surface-elevated);
|
||||||
|
box-shadow: var(--nv-elevation-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeframe__bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: var(--nv-space-1) var(--nv-space-1) var(--nv-space-1) var(--nv-space-4);
|
||||||
|
border-block-end: var(--nv-border-width) solid var(--nv-color-border-subtle);
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeframe__lang {
|
||||||
|
font-family: var(--nv-font-family-mono);
|
||||||
|
font-size: var(--nv-font-size-xs);
|
||||||
|
letter-spacing: var(--nv-letter-spacing-wide);
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--nv-color-text-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeframe .doc__pre {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.doc__pre {
|
.doc__pre {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: var(--nv-space-4);
|
padding: var(--nv-space-4);
|
||||||
|
|
@ -496,3 +597,94 @@
|
||||||
.features {
|
.features {
|
||||||
--nv-scroller-item: 21rem;
|
--nv-scroller-item: 21rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- The reader's furniture ----------------------------------------------- */
|
||||||
|
|
||||||
|
/* Where this document sits, and how long it is. */
|
||||||
|
.dochead {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: var(--nv-space-2) var(--nv-space-4);
|
||||||
|
padding-block-end: var(--nv-space-4);
|
||||||
|
border-block-end: var(--nv-border-width) solid var(--nv-color-border-subtle);
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc > .dochead + * {
|
||||||
|
margin-block-start: var(--nv-space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Previous and next, as two keys. */
|
||||||
|
.docpager {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: var(--nv-space-4);
|
||||||
|
margin-block-start: var(--nv-space-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.docpager__key {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--nv-space-1);
|
||||||
|
padding: var(--nv-space-4) var(--nv-space-5);
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.docpager__key--next {
|
||||||
|
text-align: end;
|
||||||
|
align-items: flex-end;
|
||||||
|
grid-column: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 40rem) {
|
||||||
|
.docpager { grid-template-columns: 1fr; }
|
||||||
|
.docpager__key--next { grid-column: auto; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The filter well above the index. */
|
||||||
|
.docfind {
|
||||||
|
margin-block-end: var(--nv-space-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.docfind .nv-input {
|
||||||
|
inline-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reading progress: a hairline of accent under the bar, growing from the
|
||||||
|
left. Transform rather than width, so it costs a composite and no layout. */
|
||||||
|
.readbar {
|
||||||
|
position: sticky;
|
||||||
|
inset-block-start: 0;
|
||||||
|
z-index: 10;
|
||||||
|
block-size: var(--nv-border-width-strong);
|
||||||
|
margin-block-end: calc(var(--nv-border-width-strong) * -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.readbar span {
|
||||||
|
display: block;
|
||||||
|
block-size: 100%;
|
||||||
|
background: var(--nv-color-accent);
|
||||||
|
box-shadow: 0 0 var(--nv-space-2) var(--nv-color-accent);
|
||||||
|
transform: scaleX(0);
|
||||||
|
transform-origin: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The contents entry for the section being read. */
|
||||||
|
#toc .nv-nav__item[aria-current="location"] {
|
||||||
|
color: var(--nv-color-accent-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The index's fold. Open on a wide screen, where it is a column; closed on a
|
||||||
|
narrow one (docs.js), where it would push the document out of view. */
|
||||||
|
.docindex > summary {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 64rem) {
|
||||||
|
.docindex > summary {
|
||||||
|
display: flex;
|
||||||
|
margin-block-end: var(--nv-space-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,13 +52,23 @@
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<div class="readbar" aria-hidden="true"><span id="readbar"></span></div>
|
||||||
|
|
||||||
<!-- Index, document, contents. Three columns that become one on a narrow
|
<!-- Index, document, contents. Three columns that become one on a narrow
|
||||||
screen, in that order, because that is their order of importance when
|
screen, in that order, because that is their order of importance when
|
||||||
there is only room for the middle one. -->
|
there is only room for the middle one. -->
|
||||||
<div class="docshell">
|
<div class="docshell">
|
||||||
<aside class="docshell__aside" aria-label="Documentation index">
|
<aside class="docshell__aside" aria-label="Documentation index">
|
||||||
|
<details class="nv-disclosure nv-disclosure--plain docindex" id="docindex" open>
|
||||||
|
<summary class="nv-button nv-button--sm nv-disclosure__summary">All documents</summary>
|
||||||
|
<div class="docfind">
|
||||||
|
<label class="nv-visually-hidden" for="docfilter">Filter documents</label>
|
||||||
|
<input class="nv-input nv-input--sm" id="docfilter" type="search"
|
||||||
|
placeholder="Filter documents…" autocomplete="off">
|
||||||
|
</div>
|
||||||
<nav class="nv-nav nv-nav--vertical nv-nav--static docnav" id="docnav"
|
<nav class="nv-nav nv-nav--vertical nv-nav--static docnav" id="docnav"
|
||||||
style="--nv-selection-name: nv-docs-index"></nav>
|
style="--nv-selection-name: nv-docs-index"></nav>
|
||||||
|
</details>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<main class="docshell__main">
|
<main class="docshell__main">
|
||||||
|
|
|
||||||
|
|
@ -26,21 +26,27 @@
|
||||||
["architecture/README.md", "The system, layer by layer"],
|
["architecture/README.md", "The system, layer by layer"],
|
||||||
["architecture/boot.md", "Boot"],
|
["architecture/boot.md", "Boot"],
|
||||||
["architecture/kernel.md", "Kernel"],
|
["architecture/kernel.md", "Kernel"],
|
||||||
|
["architecture/scheduler.md", "Scheduler"],
|
||||||
["architecture/syscalls.md", "Syscalls"],
|
["architecture/syscalls.md", "Syscalls"],
|
||||||
["architecture/filesystem.md", "The VFS"],
|
["architecture/filesystem.md", "The VFS"],
|
||||||
["architecture/schfs.md", "SchFS"],
|
["architecture/schfs.md", "SchFS"],
|
||||||
|
["architecture/fat.md", "FAT"],
|
||||||
["architecture/terminals.md", "Virtual terminals"],
|
["architecture/terminals.md", "Virtual terminals"],
|
||||||
["architecture/devices.md", "Device model"],
|
["architecture/devices.md", "Device model"],
|
||||||
["architecture/usb.md", "USB"],
|
["architecture/usb.md", "USB"],
|
||||||
["architecture/graphics.md", "Graphics"],
|
["architecture/graphics.md", "Graphics"],
|
||||||
|
["architecture/audio.md", "Audio"],
|
||||||
["architecture/networking.md", "Networking"],
|
["architecture/networking.md", "Networking"],
|
||||||
["architecture/init.md", "init"]
|
["architecture/init.md", "init"],
|
||||||
|
["architecture/ldls.md", "Linux drivers (LDLS)"],
|
||||||
|
["architecture/debugging.md", "Debugging"]
|
||||||
]},
|
]},
|
||||||
{ group: "Guides", items: [
|
{ group: "Guides", items: [
|
||||||
["guides/building.md", "Building"],
|
["guides/building.md", "Building"],
|
||||||
["guides/testing.md", "Testing"],
|
["guides/testing.md", "Testing"],
|
||||||
["guides/layout.md", "Tree layout"],
|
["guides/layout.md", "Tree layout"],
|
||||||
["guides/adding-a-driver.md", "Adding a driver"]
|
["guides/adding-a-driver.md", "Adding a driver"],
|
||||||
|
["guides/hardware-report.md", "Reporting hardware"]
|
||||||
]},
|
]},
|
||||||
{ group: "Plan", items: [
|
{ group: "Plan", items: [
|
||||||
["plan/README.md", "What plan/ is for"],
|
["plan/README.md", "What plan/ is for"],
|
||||||
|
|
@ -57,7 +63,7 @@
|
||||||
["history/moving-to-linux.md", "Moving to Linux"]
|
["history/moving-to-linux.md", "Moving to Linux"]
|
||||||
]},
|
]},
|
||||||
{ group: "Branding", items: [
|
{ group: "Branding", items: [
|
||||||
["branding/README.md", "The three marks"]
|
["branding/README.md", "Shift, and the wallpapers"]
|
||||||
]}
|
]}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -178,9 +184,17 @@
|
||||||
i++;
|
i++;
|
||||||
while (i < L.length && !/^\s*```/.test(L[i])) buf.push(L[i++]);
|
while (i < L.length && !/^\s*```/.test(L[i])) buf.push(L[i++]);
|
||||||
i++;
|
i++;
|
||||||
out.push('<pre class="nv-code doc__pre"' +
|
/* A frame rather than a bare block: a title strip naming the language,
|
||||||
|
and a button that copies it, because the thing a reader most often
|
||||||
|
wants from a code block in these docs is to paste it somewhere. */
|
||||||
|
out.push('<figure class="codeframe">' +
|
||||||
|
'<figcaption class="codeframe__bar">' +
|
||||||
|
'<span class="codeframe__lang">' + esc(lang || "text") + "</span>" +
|
||||||
|
'<button class="nv-button nv-button--ghost nv-button--sm" type="button" data-copy>Copy</button>' +
|
||||||
|
"</figcaption>" +
|
||||||
|
'<pre class="nv-code doc__pre"' +
|
||||||
(lang ? ' data-lang="' + esc(lang) + '"' : "") +
|
(lang ? ' data-lang="' + esc(lang) + '"' : "") +
|
||||||
"><code>" + esc(buf.join("\n")) + "</code></pre>");
|
"><code>" + esc(buf.join("\n")) + "</code></pre></figure>");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,6 +321,77 @@
|
||||||
tocEl.appendChild(ul);
|
tocEl.appendChild(ul);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Every document in index order, with the group it belongs to. */
|
||||||
|
var FLAT = [];
|
||||||
|
DOCS.forEach(function (g) {
|
||||||
|
g.items.forEach(function (it) { FLAT.push({ path: it[0], title: it[1], group: g.group }); });
|
||||||
|
});
|
||||||
|
function indexOf(path) {
|
||||||
|
for (var k = 0; k < FLAT.length; k++) if (FLAT[k].path === path) return k;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Where the reader is, how long it will take, and where the file lives --
|
||||||
|
above the document, because a page arrived at from a search has no other
|
||||||
|
way to say which part of the docs it belongs to. */
|
||||||
|
function header(path, text) {
|
||||||
|
var at = FLAT[indexOf(path)] || { group: "Docs", title: path };
|
||||||
|
var words = text.split(/\s+/).length;
|
||||||
|
var mins = Math.max(1, Math.round(words / 230));
|
||||||
|
return '<header class="dochead">' +
|
||||||
|
'<ol class="nv-breadcrumbs">' +
|
||||||
|
'<li><a href="?doc=README.md">Docs</a></li>' +
|
||||||
|
"<li>" + esc(at.group) + "</li>" +
|
||||||
|
'<li aria-current="page">' + esc(at.title) + "</li>" +
|
||||||
|
"</ol>" +
|
||||||
|
'<span class="dochead__meta nv-caption nv-text-tertiary">' +
|
||||||
|
mins + " min read · " +
|
||||||
|
'<a href="../' + esc(path) + '">' + esc(path) + "</a>" +
|
||||||
|
"</span>" +
|
||||||
|
"</header>";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The next and previous document, as two keys at the foot of the page. A
|
||||||
|
reader who reaches the end of one has nearly always come to read the
|
||||||
|
section, not the file. */
|
||||||
|
function pager(path) {
|
||||||
|
var k = indexOf(path), html = '<nav class="docpager" aria-label="More documents">';
|
||||||
|
function key(d, dir) {
|
||||||
|
return '<a class="nv-card nv-card--interactive docpager__key docpager__key--' + dir +
|
||||||
|
'" href="' + docHref(d.path) + '">' +
|
||||||
|
'<span class="nv-overline nv-text-tertiary">' + (dir === "prev" ? "← Previous" : "Next →") + "</span>" +
|
||||||
|
'<span class="nv-title">' + esc(d.title) + "</span>" +
|
||||||
|
'<span class="nv-caption nv-text-tertiary">' + esc(d.group) + "</span></a>";
|
||||||
|
}
|
||||||
|
if (k > 0) html += key(FLAT[k - 1], "prev");
|
||||||
|
else html += "<span></span>";
|
||||||
|
if (k >= 0 && k < FLAT.length - 1) html += key(FLAT[k + 1], "next");
|
||||||
|
return html + "</nav>";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light the contents entry for the section being read. */
|
||||||
|
var spy;
|
||||||
|
function watchHeadings() {
|
||||||
|
if (spy) spy.disconnect();
|
||||||
|
if (!("IntersectionObserver" in window)) return;
|
||||||
|
var links = {};
|
||||||
|
Array.prototype.forEach.call(tocEl.querySelectorAll("a"), function (a) {
|
||||||
|
links[a.getAttribute("href").slice(1)] = a;
|
||||||
|
});
|
||||||
|
spy = new IntersectionObserver(function (entries) {
|
||||||
|
entries.forEach(function (e) {
|
||||||
|
if (!e.isIntersecting || !links[e.target.id]) return;
|
||||||
|
Array.prototype.forEach.call(tocEl.querySelectorAll("a"), function (a) {
|
||||||
|
a.removeAttribute("aria-current");
|
||||||
|
});
|
||||||
|
links[e.target.id].setAttribute("aria-current", "location");
|
||||||
|
});
|
||||||
|
}, { rootMargin: "0px 0px -70% 0px" });
|
||||||
|
Array.prototype.forEach.call(article.querySelectorAll("h2[id], h3[id]"), function (h) {
|
||||||
|
spy.observe(h);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function fail(title, body) {
|
function fail(title, body) {
|
||||||
article.innerHTML = "<h1>" + title + "</h1>" + body;
|
article.innerHTML = "<h1>" + title + "</h1>" + body;
|
||||||
tocEl.hidden = true;
|
tocEl.hidden = true;
|
||||||
|
|
@ -322,8 +407,9 @@
|
||||||
return r.text();
|
return r.text();
|
||||||
}).then(function (text) {
|
}).then(function (text) {
|
||||||
var headings = [];
|
var headings = [];
|
||||||
article.innerHTML = render(text, path, headings);
|
article.innerHTML = header(path, text) + render(text, path, headings) + pager(path);
|
||||||
buildToc(headings);
|
buildToc(headings);
|
||||||
|
watchHeadings();
|
||||||
article.removeAttribute("aria-busy");
|
article.removeAttribute("aria-busy");
|
||||||
if (headings.length) document.title = headings[0].text + " — SchOS docs";
|
if (headings.length) document.title = headings[0].text + " — SchOS docs";
|
||||||
var hash = location.hash.slice(1);
|
var hash = location.hash.slice(1);
|
||||||
|
|
@ -340,7 +426,7 @@
|
||||||
"<p>Browsers block <code>fetch()</code> on <code>file://</code> URLs, so the " +
|
"<p>Browsers block <code>fetch()</code> on <code>file://</code> URLs, so the " +
|
||||||
"reader cannot load the Markdown. The rest of the site works from a file; " +
|
"reader cannot load the Markdown. The rest of the site works from a file; " +
|
||||||
"this page does not. Serve the repository root:</p>" +
|
"this page does not. Serve the repository root:</p>" +
|
||||||
'<pre class="nv-code doc__pre"><code>cd /home/nexoniarz/Dokumenty/Projects/SchOS\n' +
|
'<pre class="nv-code doc__pre"><code>cd path/to/SchOS\n' +
|
||||||
"python3 -m http.server 8000</code></pre>" +
|
"python3 -m http.server 8000</code></pre>" +
|
||||||
"<p>Then open <code>http://localhost:8000/docs/Website/docs.html</code>.</p>" +
|
"<p>Then open <code>http://localhost:8000/docs/Website/docs.html</code>.</p>" +
|
||||||
'<p>Or read this one directly: <a href="../' + esc(path) + '">' + esc(path) + "</a></p>");
|
'<p>Or read this one directly: <a href="../' + esc(path) + '">' + esc(path) + "</a></p>");
|
||||||
|
|
@ -365,6 +451,54 @@
|
||||||
buildNav();
|
buildNav();
|
||||||
load(pathFromUrl());
|
load(pathFromUrl());
|
||||||
|
|
||||||
|
/* Fold the index on a narrow screen, and fold it again after picking a
|
||||||
|
document there -- the choice is made, and the document is what was asked
|
||||||
|
for. */
|
||||||
|
var fold = document.getElementById("docindex");
|
||||||
|
var narrow = window.matchMedia && window.matchMedia("(max-width: 64rem)");
|
||||||
|
if (fold && narrow && narrow.matches) fold.open = false;
|
||||||
|
nav.addEventListener("click", function () {
|
||||||
|
if (fold && narrow && narrow.matches) fold.open = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Filter the index as you type. Groups with nothing left in them go too,
|
||||||
|
so the heading of an empty section does not sit there implying a match. */
|
||||||
|
var filter = document.getElementById("docfilter");
|
||||||
|
if (filter) filter.addEventListener("input", function () {
|
||||||
|
var q = filter.value.trim().toLowerCase();
|
||||||
|
Array.prototype.forEach.call(nav.querySelectorAll(".nv-nav__list"), function (ul) {
|
||||||
|
var any = false;
|
||||||
|
Array.prototype.forEach.call(ul.querySelectorAll("li"), function (li) {
|
||||||
|
var hit = !q || li.textContent.toLowerCase().indexOf(q) >= 0;
|
||||||
|
li.hidden = !hit;
|
||||||
|
any = any || hit;
|
||||||
|
});
|
||||||
|
ul.hidden = !any;
|
||||||
|
if (ul.previousElementSibling) ul.previousElementSibling.hidden = !any;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Copy a code block. The label says what happened, then goes back. */
|
||||||
|
article.addEventListener("click", function (ev) {
|
||||||
|
var b = ev.target.closest ? ev.target.closest("[data-copy]") : null;
|
||||||
|
if (!b) return;
|
||||||
|
var code = b.closest(".codeframe").querySelector("code").textContent;
|
||||||
|
var done = function (ok) {
|
||||||
|
b.textContent = ok ? "Copied" : "Select and copy";
|
||||||
|
setTimeout(function () { b.textContent = "Copy"; }, 1600);
|
||||||
|
};
|
||||||
|
if (navigator.clipboard) navigator.clipboard.writeText(code).then(function () { done(true); }, function () { done(false); });
|
||||||
|
else done(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* How far down the document the reader is: a hairline under the bar. */
|
||||||
|
var bar = document.getElementById("readbar");
|
||||||
|
if (bar) window.addEventListener("scroll", function () {
|
||||||
|
var h = document.documentElement;
|
||||||
|
var f = h.scrollHeight > h.clientHeight ? h.scrollTop / (h.scrollHeight - h.clientHeight) : 0;
|
||||||
|
bar.style.transform = "scaleX(" + Math.min(1, Math.max(0, f)) + ")";
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
/* Intercept in-page navigation so the reader does not reload its own shell. */
|
/* Intercept in-page navigation so the reader does not reload its own shell. */
|
||||||
document.addEventListener("click", function (ev) {
|
document.addEventListener("click", function (ev) {
|
||||||
var a = ev.target.closest ? ev.target.closest("a") : null;
|
var a = ev.target.closest ? ev.target.closest("a") : null;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>SchOS — a 64-bit operating system written from scratch</title>
|
<title>SchOS — every layer its own</title>
|
||||||
<meta name="description" content="SchOS is a from-scratch x86-64 operating system: the SchIFT kernel, the SchFS copy-on-write filesystem, a UEFI loader, and a userland that runs unmodified musl and toybox.">
|
<meta name="description" content="SchOS is a from-scratch x86-64 operating system: the SchIFT kernel, the SchFS copy-on-write filesystem, a UEFI loader, and a userland that runs unmodified musl and toybox.">
|
||||||
<link rel="icon" href="Assets/shift.svg" type="image/svg+xml">
|
<link rel="icon" href="Assets/shift.svg" type="image/svg+xml">
|
||||||
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
<li><a class="nv-nav__item" href="#what">What it has</a></li>
|
<li><a class="nv-nav__item" href="#what">What it has</a></li>
|
||||||
<li><a class="nv-nav__item" href="#hybrid">Hybrid</a></li>
|
<li><a class="nv-nav__item" href="#hybrid">Hybrid</a></li>
|
||||||
<li><a class="nv-nav__item" href="#numbers">Numbers</a></li>
|
<li><a class="nv-nav__item" href="#numbers">Numbers</a></li>
|
||||||
|
<li><a class="nv-nav__item" href="#wallpapers">Wallpapers</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<span class="nv-nav__spacer"></span>
|
<span class="nv-nav__spacer"></span>
|
||||||
|
|
@ -69,7 +70,9 @@
|
||||||
<main id="top">
|
<main id="top">
|
||||||
|
|
||||||
<!-- ====================================================================== -->
|
<!-- ====================================================================== -->
|
||||||
<header class="shell hero">
|
<!-- The one full-bleed band on the page, lit like the Graphite wallpaper. -->
|
||||||
|
<header class="heroband">
|
||||||
|
<div class="shell hero">
|
||||||
<div class="hero__copy">
|
<div class="hero__copy">
|
||||||
<span class="nv-badge nv-badge--accent">
|
<span class="nv-badge nv-badge--accent">
|
||||||
<span class="nv-badge__dot"></span>
|
<span class="nv-badge__dot"></span>
|
||||||
|
|
@ -77,9 +80,11 @@
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<h1 class="nv-display hero__title">
|
<h1 class="nv-display hero__title">
|
||||||
<img class="hero__mark" src="Assets/shift.svg" alt="">SchOS
|
<span class="nv-tile nv-tile--xl hero__tile"><img src="Assets/shift.svg" alt=""></span>SchOS
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
<p class="nv-heading hero__slogan">Every layer its own — from the first instruction to the last pixel.</p>
|
||||||
|
|
||||||
<p class="nv-prose">
|
<p class="nv-prose">
|
||||||
A 64-bit operating system written from scratch — its own kernel, its own
|
A 64-bit operating system written from scratch — its own kernel, its own
|
||||||
filesystem, its own bootloader. It boots on UEFI, drives real hardware,
|
filesystem, its own bootloader. It boots on UEFI, drives real hardware,
|
||||||
|
|
@ -109,13 +114,14 @@
|
||||||
</div>
|
</div>
|
||||||
<pre class="nv-window__body nv-code console__log" id="bootlog" aria-live="polite"></pre>
|
<pre class="nv-window__body nv-code console__log" id="bootlog" aria-live="polite"></pre>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- ====================================================================== -->
|
<!-- ====================================================================== -->
|
||||||
<section id="origin" class="shell section" data-reveal>
|
<section id="origin" class="shell section" data-reveal>
|
||||||
<div class="section__head">
|
<div class="section__head">
|
||||||
<p class="nv-overline nv-text-accent">Origin</p>
|
<p class="nv-overline nv-text-accent">Origin</p>
|
||||||
<h2 class="nv-heading">It started as a teaching kernel and stopped being one</h2>
|
<h2 class="nv-heading">A teaching kernel that outgrew its lessons</h2>
|
||||||
<p class="nv-prose nv-text-secondary">
|
<p class="nv-prose nv-text-secondary">
|
||||||
SchOS began as <a href="https://github.com/mit-pdos/xv6-public">xv6</a>, MIT's
|
SchOS began as <a href="https://github.com/mit-pdos/xv6-public">xv6</a>, MIT's
|
||||||
teaching operating system: 32-bit, single core, one filesystem, a few dozen
|
teaching operating system: 32-bit, single core, one filesystem, a few dozen
|
||||||
|
|
@ -195,7 +201,7 @@
|
||||||
<section id="stack" class="shell section" data-reveal>
|
<section id="stack" class="shell section" data-reveal>
|
||||||
<div class="section__head">
|
<div class="section__head">
|
||||||
<p class="nv-overline nv-text-accent">Architecture</p>
|
<p class="nv-overline nv-text-accent">Architecture</p>
|
||||||
<h2 class="nv-heading">Three seams hold the whole thing together</h2>
|
<h2 class="nv-heading">Three seams, and everything else is arrangement</h2>
|
||||||
<p class="nv-prose nv-text-secondary">
|
<p class="nv-prose nv-text-secondary">
|
||||||
Above the syscall table, software is ordinary and portable. Below the device
|
Above the syscall table, software is ordinary and portable. Below the device
|
||||||
model, a driver never names its consumer and a consumer never names a driver.
|
model, a driver never names its consumer and a consumer never names a driver.
|
||||||
|
|
@ -261,7 +267,7 @@
|
||||||
<section id="what" class="shell section" data-reveal>
|
<section id="what" class="shell section" data-reveal>
|
||||||
<div class="section__head">
|
<div class="section__head">
|
||||||
<p class="nv-overline nv-text-accent">What it has</p>
|
<p class="nv-overline nv-text-accent">What it has</p>
|
||||||
<h2 class="nv-heading">Built and running, and honest about the rest</h2>
|
<h2 class="nv-heading">Running today, and honest about the rest</h2>
|
||||||
<p class="nv-prose nv-text-secondary">
|
<p class="nv-prose nv-text-secondary">
|
||||||
Every card marked <b>runs</b> is in the tree and works today. The tags are
|
Every card marked <b>runs</b> is in the tree and works today. The tags are
|
||||||
not aspirational; the things that are not finished say so.
|
not aspirational; the things that are not finished say so.
|
||||||
|
|
@ -536,7 +542,7 @@
|
||||||
<section id="numbers" class="shell section" data-reveal>
|
<section id="numbers" class="shell section" data-reveal>
|
||||||
<div class="section__head">
|
<div class="section__head">
|
||||||
<p class="nv-overline nv-text-accent">Numbers</p>
|
<p class="nv-overline nv-text-accent">Numbers</p>
|
||||||
<h2 class="nv-heading">The size of it</h2>
|
<h2 class="nv-heading">Measured, not marketed</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<dl class="nv-stat-group">
|
<dl class="nv-stat-group">
|
||||||
|
|
@ -583,6 +589,66 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<!-- ====================================================================== -->
|
||||||
|
<section id="wallpapers" class="shell section" data-reveal>
|
||||||
|
<div class="section__head">
|
||||||
|
<p class="nv-overline nv-text-accent">Wallpapers</p>
|
||||||
|
<h2 class="nv-heading">Four surfaces to sit on</h2>
|
||||||
|
<p class="nv-prose nv-text-secondary">
|
||||||
|
Every one is the Shift mark under a different light, generated from the
|
||||||
|
same geometry the loader draws — so they change when the mark does.
|
||||||
|
3840×2160, free to use under the same licence as the rest of the tree.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="walls">
|
||||||
|
<figure class="nv-card wall">
|
||||||
|
<img class="wall__img" src="../branding/wallpapers/graphite.jpg" alt="Graphite: Shift on warm graphite, throwing a pool of violet on the surface. The default." loading="lazy" width="3840" height="2160">
|
||||||
|
<figcaption class="wall__caption">
|
||||||
|
<span class="nv-title">Graphite</span>
|
||||||
|
<span class="nv-body nv-text-secondary">Shift on warm graphite, throwing a pool of violet on the surface. The default.</span>
|
||||||
|
<span class="nv-cluster">
|
||||||
|
<a class="nv-button nv-button--sm" href="../branding/wallpapers/graphite.jpg" download>4K JPEG</a>
|
||||||
|
<a class="nv-button nv-button--ghost nv-button--sm" href="../branding/wallpapers/graphite.svg" download>SVG</a>
|
||||||
|
</span>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure class="nv-card wall">
|
||||||
|
<img class="wall__img" src="../branding/wallpapers/strata.jpg" alt="Strata: The slabs repeated into a cascade that recedes into indigo." loading="lazy" width="3840" height="2160">
|
||||||
|
<figcaption class="wall__caption">
|
||||||
|
<span class="nv-title">Strata</span>
|
||||||
|
<span class="nv-body nv-text-secondary">The slabs repeated into a cascade that recedes into indigo.</span>
|
||||||
|
<span class="nv-cluster">
|
||||||
|
<a class="nv-button nv-button--sm" href="../branding/wallpapers/strata.jpg" download>4K JPEG</a>
|
||||||
|
<a class="nv-button nv-button--ghost nv-button--sm" href="../branding/wallpapers/strata.svg" download>SVG</a>
|
||||||
|
</span>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure class="nv-card wall">
|
||||||
|
<img class="wall__img" src="../branding/wallpapers/porcelain.jpg" alt="Porcelain: The light one: glazed porcelain on paper, the top slab in the accent." loading="lazy" width="3840" height="2160">
|
||||||
|
<figcaption class="wall__caption">
|
||||||
|
<span class="nv-title">Porcelain</span>
|
||||||
|
<span class="nv-body nv-text-secondary">The light one: glazed porcelain on paper, the top slab in the accent.</span>
|
||||||
|
<span class="nv-cluster">
|
||||||
|
<a class="nv-button nv-button--sm" href="../branding/wallpapers/porcelain.jpg" download>4K JPEG</a>
|
||||||
|
<a class="nv-button nv-button--ghost nv-button--sm" href="../branding/wallpapers/porcelain.svg" download>SVG</a>
|
||||||
|
</span>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
<figure class="nv-card wall">
|
||||||
|
<img class="wall__img" src="../branding/wallpapers/dial.jpg" alt="Dial: The SchFS uberblock ring as hardware — the newest slot and the root lit." loading="lazy" width="3840" height="2160">
|
||||||
|
<figcaption class="wall__caption">
|
||||||
|
<span class="nv-title">Dial</span>
|
||||||
|
<span class="nv-body nv-text-secondary">The SchFS uberblock ring as hardware — the newest slot and the root lit.</span>
|
||||||
|
<span class="nv-cluster">
|
||||||
|
<a class="nv-button nv-button--sm" href="../branding/wallpapers/dial.jpg" download>4K JPEG</a>
|
||||||
|
<a class="nv-button nv-button--ghost nv-button--sm" href="../branding/wallpapers/dial.svg" download>SVG</a>
|
||||||
|
</span>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- ====================================================================== -->
|
<!-- ====================================================================== -->
|
||||||
<section id="docs" class="shell section" data-reveal>
|
<section id="docs" class="shell section" data-reveal>
|
||||||
<div class="section__head">
|
<div class="section__head">
|
||||||
|
|
@ -648,7 +714,7 @@
|
||||||
<img class="getband__mark" src="Assets/usb.svg" alt="">
|
<img class="getband__mark" src="Assets/usb.svg" alt="">
|
||||||
<div class="getband__copy">
|
<div class="getband__copy">
|
||||||
<p class="nv-overline nv-text-accent">Try it</p>
|
<p class="nv-overline nv-text-accent">Try it</p>
|
||||||
<h2 class="nv-heading">One ISO, one stick, nothing written to your disks</h2>
|
<h2 class="nv-heading">One ISO. One stick. Your disks untouched.</h2>
|
||||||
<p class="nv-prose nv-text-secondary">
|
<p class="nv-prose nv-text-secondary">
|
||||||
It runs from RAM and leaves the machine as it found it. Or skip the
|
It runs from RAM and leaves the machine as it found it. Or skip the
|
||||||
stick entirely — <code class="nv-code">make qemu</code> is the same
|
stick entirely — <code class="nv-code">make qemu</code> is the same
|
||||||
|
|
@ -667,7 +733,7 @@
|
||||||
<footer class="shell site-footer">
|
<footer class="shell site-footer">
|
||||||
<div class="nv-divider"></div>
|
<div class="nv-divider"></div>
|
||||||
<div class="site-footer__row">
|
<div class="site-footer__row">
|
||||||
<span class="nv-body">SchOS — kernel <b>SchIFT</b>, filesystem <b>SchFS</b>.</span>
|
<span class="nv-body">SchOS — built from the metal up. Kernel <b>SchIFT</b>, filesystem <b>SchFS</b>.</span>
|
||||||
<span class="nv-code nv-text-tertiary">GPL-2.0-or-later, with the xv6-derived core under MIT.</span>
|
<span class="nv-code nv-text-tertiary">GPL-2.0-or-later, with the xv6-derived core under MIT.</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue