Skip to content

Releases

Sashfold 0.2.0

Choose a tag to compare

@codingncaffeine codingncaffeine released this 05 Oct 15:38

Sashfold 0.2.0 is the release where pages built out of components come apart into what they are: 64 commits since 0.1.5 on 2026-10-01. Shadow trees, Web Animations, the CSS object model and the Streams Standard are written, so the sites that build themselves from web components and style themselves from script render as they are meant to. The script engine has a compiler that writes machine code, and its objects keep their properties in shapes with caches that remember them. Speed work runs through all of it. Still every byte is written in this repository, and still it does not pretend to do what it cannot.

What's New

  • Machine code for scripts — a baseline compiler turns a script's hot code into machine code for x86-64 and AArch64, on Linux, Windows and Apple silicon, over a new engine core: eight-byte values, frames on the machine's own stacks, objects that keep their properties in shapes, and property reads and writes that remember what they found.
  • Shadow trees — attachShadow, slots and slot assignment, the standard's event path through them, declarative shadow roots in markup, and styles scoped to each tree with :host, ::slotted() and ::part().
  • Web Animations, CSS animations and CSS transitions — element.animate(), @keyframes, transitions on style changes, and a real rendering update that runs requestAnimationFrame callbacks together at one time.
  • Styles written from script — the CSS object model, so a page that builds its stylesheets with insertRule or constructed sheets shows them; and nested rules and cascade layers reach the cascade.
  • Streams — readable, writable and transform streams, so the frameworks that stream their pages into place load.
  • Shadows — box-shadow and text-shadow, blurred, inset and animated, drawn with the corners the standard gives them.
  • Hover, focus and outlines — :hover, :focus, :active, :focus-visible and the other state pseudo-classes match, and outline draws.
  • Import maps, and classes that extend the platform's own interfaces, blob: URLs that load, and scripts inserted by scripts that wait their turn.
  • Placeholders that take a page's style — ::placeholder, and fields that keep only the half of their built-in look a page leaves them.
  • Pages that start loading sooner — the scripts and stylesheets a document names are asked for while the document is still arriving, and the parts of the engine a page never touches are never set up: a new tab's realm costs a fraction of what it did.

What's Fixed

  • Pictures that were a web page — every request asked for a document, so a server that answers one address with a picture or with a page to show it in sent the page, and a site's post pictures never drew; each request now asks for what it is for.
  • Content shown twice — a component moved from one place in the page to another was never told it had left, so it drew its content a second time; a video site's suggestions came out doubled.
  • Carousels and galleries drawn at the picture's full width — a scrolling box in a flex row held its row as wide as its content, a flex row ignored its own maximum height, and a box's own maximum width did not count when its parent measured it.
  • A tiny logo — a logo drawn as an SVG with only its proportions given came out square when it sat in a flex row.
  • A frame drawn inside a styled search box — a field whose page took its border away still drew the engine's own frame and a second placeholder.
  • Slow pages built from components — every style change read every component's stylesheets afresh; on a social site that made a page's busiest moment about ten seconds long, and it is about six now, its restyles three times as fast.
  • Pages that use :has() through :not() — no longer recompute the whole document's styles for a change one element away.
  • Sign-in buttons that never appeared — the user agent now carries Gecko's compatibility token, as other engines of their own do, and the sign-in services that refused the bare one serve it; and every request carries the Fetch Metadata headers every browser sends, which some sites require of anything that claims to be one.

What's Not Written Yet

  • Painting gaps — transforms still translate but do not scale, rotate or skew; filters, clip paths, masks and text-overflow are not painted.
  • Slow reactions — when a script reads layout after changing the page, the whole page is laid out again; a page that does that many times in a row stays busy for seconds after it has drawn (the window itself still answers).
  • Script speed — the compiler is the first, simple one; a video site's player takes about three seconds to show its first frame where other browsers take one and a half.
  • What getComputedStyle says — flex, grid, gap, border and alignment properties read as empty strings.
  • The newer edge of scripting — WebAssembly, WebGL, Web Audio, service workers, WebSocket and the regular-expression v flag are not written.
  • Media gaps — video is VP9 in WebM and sound is Opus and WAVE; WebP and AVIF are not read. Windows has no sound and shows no video pictures yet, and on Linux video needs a graphics driver that decodes VP9 through Vulkan Video or VA-API — there is no software path for playback yet.
  • macOS — the engine and its command line build and test on macOS in CI, but there is no window there yet.

Measured

  • CSS reference tests — 10,272 of 15,682, up from 9,877 of 15,186. The table is at sashfold.com/wpt.html.
  • WPT scripted tests — 157,846 of 192,269 subtests over 6,343 files, up from 145,667 of 174,114; the suite grew with the shadow-tree, animation, background and text-decoration directories. The table is at sashfold.com/wpt-harness.html.
  • test262 — 41,845 of 45,367, the same count as 0.1.5 with the engine underneath rebuilt; it is run with the compiler off, eager and tiered, and all three agree. The table is at sashfold.com/test262.html.
  • At 100% — both html5lib suites, WPT URL parsing, and the Unicode bidirectional and line-breaking conformance suites.
  • The Sashfold 100 — 82 of a hundred pages of the live web render on the Windows build and 85 on the Linux build, against 80 and 82 in 0.1.5, with the five deliberately bad certificates refused on both. What each page asks for that is not written yet is listed at sashfold.com/sashfold100.
  • Every score is held by CI: a test that stops passing fails the build.

Running It

  • The downloads — sashfold-0.2.0-windows-x64.zip, unzipped with themes kept beside sashfold.exe, and sashfold-0.2.0-linux-x64.tar.gz, unpacked with themes kept beside sashfold. sashfold https://en.wikipedia.org opens the window on a page; with no address it opens its own new-tab page. Downloads go to your Downloads folder.
  • A Debian package and an AUR package — sashfold_0.2.0_amd64.deb installs on Debian 13, Ubuntu 24.04 and their derivatives with sudo apt install ./sashfold_0.2.0_amd64.deb, which puts sashfold on PATH and in the applications menu with its icon; on Arch, sashfold-bin on the AUR installs the same build the same way.
  • Requirements — Windows 10 or 11, 64-bit; the binary is statically linked and imports only the operating system's own libraries, which is checked in CI. Linux needs a 64-bit machine with glibc 2.39 or newer (Ubuntu 24.04, Debian 13, Fedora 40 and their successors, Arch) and a Wayland compositor; video needs a graphics driver that decodes VP9 through Vulkan Video or VA-API, and sound a PulseAudio or PipeWire server, which the Debian package recommends; the binary carries its own C++ runtime and imports only libc and libm, checked the same way. bash tools/install-desktop-linux.sh ./sashfold --desktop puts it in the applications menu and on the desktop with its icon; that script needs ImageMagick for the icon sizes.
  • Profiles and headless rendering — --profile <dir> keeps a browser's cookies, storage and session in that folder between runs. sashfold --render page.html -o out.png draws a page to a picture with no window at all. SASHFOLD_USER_AGENT sets the user agent string to anything you like.
  • Source — macOS builds from source with CMake and Ninja; the window itself is Windows and Linux for now.

Sashfold 0.1.5

Choose a tag to compare

@codingncaffeine codingncaffeine released this 02 Oct 03:06

Sashfold 0.1.5 is the release where pages move: 172 commits since 0.1.0 on 2026-09-16. Video and sound play, and a video site's watch page plays through with its player's controls answering. Every tab's page runs on a thread of its own, so the window never waits on a page; the network speaks HTTP/2; and the DOM and Web API surface is much larger and much closer to the standard, with pointer events, WebIDL receiver checks, Trusted Types and many interfaces a page expects to find. Speed work runs through all of it. Still every byte is written in this repository, and still it does not pretend to do what it cannot.

What's New

  • Video plays on Linux — a WebM parser and Media Source Extensions feed a VP9 decoder on the machine's video hardware, through Vulkan Video and then VA-API, with pictures decoded off the page's thread, scaled smoothly and shown at their time.
  • Sound on Linux — an Opus decoder and a WAVE reader written here, played straight to the desktop's PulseAudio or PipeWire server; a video's sound plays, and a page's volume and mute reach the mixer.
  • A player's own controls — play and pause, volume, seek, settings, theater mode and full screen answer on a video site's watch page. The Fullscreen API gives an element the whole window, and Esc gives it back.
  • A page on a thread of its own — each tab's scripts, styles, layout and paint run in an engine on a thread of their own, so a busy page no longer holds the strip, the address bar or the window; dedicated workers get threads too.
  • Pages arrive sooner — stylesheets, scripts, fonts and pictures are fetched together and ahead of the page's asking, the document comes while the window stays live, and a page shows with the pictures that have come and swaps in its fonts as they land.
  • HTTP/2 — a page's requests to one host share one connection, with HPACK and the framing written from the RFCs; a request that cannot safely be repeated is never sent twice.
  • Components and observers — custom elements, a MutationObserver that delivers real records, an IntersectionObserver that measures, and load and error events on pictures and stylesheet links.
  • Canvas, IndexedDB and Intl — a canvas draws through a full 2D context, databases are kept per origin in the profile, and Intl formats numbers, dates, lists, units and relative times in English.
  • Pointer events — a page hears the pointer as the standards have it: over, enter, move, down, up, out and leave with their mouse counterparts, a click at the common ancestor, double and auxiliary clicks, and real movement.
  • A far larger Web API surface — WebIDL receiver checks, event handlers on the interfaces that own them, window and navigator objects as real interfaces, Trusted Types, TreeWalker and NodeIterator, resource-management stacks, and regular-expression lookbehind and \p{} escapes.
  • More CSS, and forms that post — @supports, display: contents, aspect-ratio, object-fit and pointer-events; a form whose method is post sends URL-encoded, multipart or plain-text bodies.
  • Menus and tabs — a right click opens a menu of what it landed on, the toolbar has a main menu, Ctrl+Shift+T brings a closed tab back, and a tab can be duplicated or pinned.
  • Bookmarks — a star and Ctrl+D, a bar under the toolbar, folders, a manager at about:bookmarks with search and undo, import from other browsers, export and dated backups.
  • Themes from other browsers — a Firefox .xpi or a Chrome .crx is converted into a theme, from the profile's folder or at one click on about:themes, with pictures behind the tabs, moving ones included.

What's Fixed

  • Pages that would not scroll or click — a page whose html and body are 100% tall now scrolls to what reaches out of them, and what is under the pointer is found in painting order, so a link laid over a whole card answers and z-index counts.
  • Dialogs nobody could see — a fixed box inside a fixed backdrop was never laid out, so a page held still under a dialog showed none.
  • Relative links and the address field — <base href> was read by nothing, and pushState left the address field behind so that Back left the site; both follow the page now.
  • A window that stopped answering — loading a page held the window until it drew, and dragging a window's edge queued half a minute of layout; the document comes on another thread, and the drag settles half a second after it ends.
  • Pictures stretched out of shape — height: auto over a picture's height attribute came out as tall as the attribute; pictures keep their shape now, and complete says whether the picture is in.
  • Buttons drawn empty — an icon button showed an empty face, and a field's placeholder, a control's padding and its baseline were missing or wrong.
  • A video that stopped partway — a video site's watch page gave up about 44 seconds in; Web API methods now refuse to run on the wrong kind of object, as every browser's do, and the video plays through.
  • Players that stalled — a stylesheet link never said its sheet had come, so a player stayed in its loading skeleton and theater mode and full screen did nothing; a click on pause was read as a click on the picture and played again; play() before the source was chosen was refused; and video stuttered while its page was busy.
  • Pages that use :has() — one :has() in a page's styles made every style change recompute the whole document; now only what the change can reach is recomputed, and entering full screen on a video player went from about three seconds to half a second.
  • Scripts that threw where other browsers do not — recursion stopped at a thousand calls where a browser reaches twelve and a half thousand, and JSON.parse and syntax errors now carry V8's wording.
  • A runaway page took the machine — a script that allocated without end now stops at a heap ceiling of its own, and the other tabs go on.
  • The web driving the browser's own pages — a link or a script could name about:bookmarks?remove= and have it done; only the page itself can ask now.

What's Not Written Yet

  • Hover and focus styling — :hover, :focus, :active and :focus-visible never match yet and there is no outline, so hover and focus styles do not show and a clicked button shows the engine's own focus ring.
  • Painting gaps — a transform can translate but not scale, rotate or skew, so a video player's progress bar draws its fill at full width; CSS shadows, filters, clip paths and masks are not painted.
  • Slow reactions — layout after a script reads it is recomputed for the whole page, which makes some page reactions slow.
  • The newer edge of scripting — WebAssembly, WebGL, Web Audio, streams, service workers, import maps, WebSocket, shadow trees and the regular-expression v flag are not written.
  • Media gaps — video is VP9 in WebM and sound is Opus and WAVE; Opus frames of the SILK and hybrid kinds play as silence, and any other codec or container, WebP and AVIF are not read. Windows has no sound and shows no video pictures yet, and on Linux video needs a graphics driver that decodes VP9 through Vulkan Video or VA-API — there is no software path for playback yet.
  • Layout and text gaps — subgrid, masonry, multi-column layout and several table behaviors; Arabic letters do not join, and Thai, Lao, Khmer and Myanmar words break between clusters.
  • macOS — the engine and its command line build and test on macOS in CI, but there is no window there yet, and no TLS client of its own either.

Measured

  • CSS reference tests — 9,877 of 15,186, up from 9,427 of 14,616. The table is at sashfold.com/wpt.html.
  • WPT scripted tests — 145,667 of 174,114 subtests over 5,555 files, against 65,822 of 74,294 in 0.1.0; the suite grew with many more directories. The table is at sashfold.com/wpt-harness.html.
  • test262 — the ECMAScript conformance suite: 41,845 of 45,367, up from 40,358 of 41,791. The table is at sashfold.com/test262.html.
  • At 100% — both html5lib suites, WPT URL parsing, and the Unicode bidirectional and line-breaking conformance suites.
  • The Sashfold 100 — 80 of a hundred pages of the live web render on the Windows build and 82 on the Linux build, against 83 and 81 in 0.1.0, with the five deliberately bad certificates refused on both. What each page asks for that is not written yet is listed at sashfold.com/sashfold100.
  • Every score is held by CI: a test that stops passing fails the build.

Running It

  • The downloads — sashfold-0.1.5-windows-x64.zip, unzipped with themes kept beside sashfold.exe, and sashfold-0.1.5-linux-x64.tar.gz, unpacked with themes kept beside sashfold. sashfold https://en.wikipedia.org opens the window on a page; with no address it opens its own new-tab page. Downloads go to your Downloads folder.
  • A Debian package and an AUR package — sashfold_0.1.5_amd64.deb installs on Debian 13, Ubuntu 24.04 and their derivatives with sudo apt install ./sashfold_0.1.5_amd64.deb, which puts sashfold on PATH and in the applications menu with its icon; on Arch, sashfold-bin on the AUR installs the same build the same way.
  • Requirements — Windows 10 or 11, 64-bit; the binary is statically linked and imports only the operating system's own libraries, which is checked in CI. Linux needs a 64-bit machine with glibc 2.39 or newer (Ubuntu 24.04, Debian 13, Fedora 40 and their successors, Arch) and a Wayland compositor; video needs a graphics driver that decodes VP9 through Vulkan Video or VA-API, and sound a PulseAudio or PipeWire server, which the Debian package recommends; the binary carries its own C++ runtime and imports only libc and libm, checked the same way, and the window is a Wayland client of its own with no toolkit underneath it. bash tools/install-desktop-linux.sh ./sashfold --desktop puts it in the applications menu and on the desktop ...
Read more

Sashfold 0.1.0

Choose a tag to compare

@codingncaffeine codingncaffeine released this 16 Sep 22:42

Sashfold 0.1.0 is the first release that is not a pre-release, and the largest by far: 142 commits since 0.0.7 on 2026-09-04. Its theme is that pages now run their scripts, the window came to Linux, and the network stack is entirely the engine's own. A JavaScript engine written in this repository runs a page's scripts against its DOM, with events, timers, promises, modules and the rest of the language behind them, and reaches out over fetch and XMLHttpRequest with the cross-origin rules a browser is supposed to keep. The window is now a Wayland client of its own on Linux, and HTTPS there runs over a TLS 1.3 and 1.2 client written here too, with no operating system TLS stack behind it at all. Frames, iframes and framesets carry real windows now, each running its own scripts and taking its own scrolling, typing and clicks. The CSS reference tests went from 8345 of 14,616 to 9427; the scripted tests are a yardstick of their own now, at 65,822 of 74,294 subtests, and so is test262, the ECMAScript conformance suite, at 40,358 of 41,791. Still every byte is written in this repository, and still it does not pretend to do what it cannot.

What's New

  • A JavaScript engine of its own — lexer, parser, an object model, and an interpreter that runs on a bytecode machine of its own devising: ES5 with let/const, arrows, template literals, destructuring, classes with private fields, generators, async functions and async generators, Map and Set, Promise, typed arrays and ArrayBuffer, BigInt, Proxy and Reflect, and ES modules with import(), import.meta and top-level await. It is scored against test262, the ECMAScript conformance suite, below.
  • Pages run their own scripts — a realm gives each document's scripts the DOM: elements, attributes, innerHTML, events with capture and bubbling, setTimeout, setInterval, requestAnimationFrame, queueMicrotask, location, history, localStorage and the rest, wired into the shell, the headless renderer and the test runner alike. A page that builds its own menus and banners with a script now shows them.
  • fetch and XMLHttpRequest, with CORS — Headers, Request, Response, FormData and AbortController, and the rules above them a browser is supposed to keep: a preflight before a request that needs one, an opaque response for no-cors, and a cross-origin response read only when its own header allows it.
  • A window for Linux — the browser's window is a Wayland client of its own now, spoken over the compositor's socket with no toolkit underneath it. It draws at the display's scale, fractions included, takes a touchscreen's taps and drags, composes with an input method at the caret, and draws its own frame — minimize, maximize, close, a drag handle and a resize band — where the compositor draws none.
  • HTTPS on Linux, homemade down to the primitives — a TLS 1.3 and TLS 1.2 client written in this repository, over cryptographic primitives also written here, checks a server's certificate against a trust store and its issuer's revocation list, and resumes a second connection to the same host from the first one's session ticket.
  • iframes, frames and framesets — each shows its document in a real window of its own, running its own scripts, held to the page's framing rules, and taking the wheel, the keyboard, typing, selection and links exactly as the page itself does; a frameset is laid out as the grid its rows and columns name, with a frame drawn in each cell.
  • object and embed elements — each shows a fetched document in a window of its own, a picture, or its fallback content, decided the way HTML asks and drawn live from whichever it turns out to be.
  • window.open — a script opens a named frame, or a new tab in the page's own container, gated on the reader's own click or keypress so a page cannot pop one open unasked.
  • Content Security Policy — a page's own headers and <meta> policies judge every fetch and every redirect hop it makes, every inline script and style by nonce or hash, and every string a script would compile, with each refusal on the page's console.
  • Content blocking and cosmetic filtering — Adblock-syntax filter lists judge every request before it leaves the machine, local phishing and malware lists keep the browser off a nefarious site with no lookup sent anywhere, and a list's element-hiding rules become a stylesheet added to the page.
  • Profiles and containers — a profile keeps its cookies and its session between runs, and containers keep a window's tabs apart from one another, each with a cookie jar of its own and a colour of its own along its tab's edge.
  • Storage — localStorage is the shell's now, one area per container and origin, kept for as long as the browser runs and written to the profile as it changes, so a page's storage outlives the page and comes back on the next start.
  • Session restore — every tab, its history and where it was scrolled comes back on the next start, written to the profile as they change.
  • The command palette and four theme presets — Ctrl+Shift+P opens a list over every command the shell has, narrowed by typing: a new tab in any container, switching to an open tab, or choosing a theme by name. Nord, Solarized Dark, High Contrast and Sashfold Light ship beside the default theme.
  • The new-tab page — a clock and a greeting over the theme's colors, or over the theme's own pictures, crossfading from one to the next.
  • An HTTP cache that matures — a stale copy with an ETag or a Last-Modified is revalidated rather than refetched, a response with no explicit freshness gets a sensible guess from its own age, and every entry is kept on disk in the profile between runs.
  • document.write — a script that writes its own markup as the parser reaches it lands in order, at the point the specification puts it.
  • SVG, drawn by a rasterizer of its own — paths, shapes, groups and transforms, linear and radial gradients, clip paths and a first cut of text, inline in a page or decoded as a picture's source.
  • CFF fonts — a Type 2 charstring interpreter reads CFF and CFF-flavored OpenType outlines, which is how most CJK faces and many web fonts are actually drawn.
  • Web fonts in WOFF and WOFF2 — the second unwrapped through a brotli decoder written in this repository, with font matching by stretch, style, weight and unicode-range for a family declared in pieces.
  • Kerning and Unicode line breaking — pairs are kerned from a font's own tables, and the complete UAX #14 line-breaking algorithm sits behind word-break, line-break and overflow-wrap.
  • Colour emoji — pictures from a font's own CBDT and sbix tables, and layered glyphs from COLR and CPAL.
  • Favicons — a page's own icon, decoded from BMP, ICO or PNG, drawn in its tab.
  • Ranges — Range and StaticRange, and a live range that every mutation moves along with the text it spans.
  • blob: URLs, structured clone and postMessage — URL.createObjectURL and a store of its own; a value posted between windows, sent through a MessagePort, or pushed into history, is cloned properly in the realm that receives it, cycles, typed arrays, dates and all.

What's Fixed

  • Minified CSS combinators failed to parse — a selector written as a>b, a+b or a~b with no spaces around the combinator was dropped whole, which cost 70 of the Sashfold 100 their rules; a script calling querySelector, matches or closest with the same kind of selector threw instead of answering.
  • Fixed and sticky boxes did not track the page's scroll — a position: fixed box drifted along with the page instead of staying at the viewport, and a position: sticky box did not re-stick as the page scrolled past it.
  • Content painted in the wrong order — floats, block backgrounds and inline text now paint in the order CSS 2.1 Appendix E gives them, so a float sits over the blocks it overlaps and under their own words, where before the layering could go either way.
  • A float's percentage height did not resolve, and an out-of-flow box's margin collapsed where it should not — a floated box's percentage height now resolves against a containing block whose height is written, as it does for any other block child, and an absolutely positioned box's top margin no longer collapses into its parent's, which used to push the parent down by a margin the positioned box does not even occupy space for.
  • A hostile JPEG could overflow the decoder's arithmetic — a stream whose dequantized coefficients reached the edge of what the format allows overflowed the inverse transform's math; the transform now runs with room to spare, and every well-formed picture still decodes to the same byte as before.

What's Not Written Yet

  • The newer edge of scripting — regular-expression lookbehind, property escapes and the v flag are not written, so a script built by a bundle that needs them fails at parse time with a syntax error that names it, and the page arrives as its markup alone; import maps, WebSocket, streams, shadow trees and MutationObserver records are not written either.
  • Layout gaps — subgrid and masonry are passed over; margin-trim, multi-column layout and several table behaviors are not read. A word in a language a dictionary segments — Thai, Lao, Khmer, Myanmar — breaks between clusters rather than at its own boundaries, and hyphenation only ever breaks at a soft hyphen already written into the text.
  • Painting gaps — shadows, outlines, filters, clip paths, masks and border-image; a transform can translate but not rotate or scale; a page fetches at most sixty-four of its pictures, so a gallery longer than that shows blank boxes past the sixty-fourth.
  • No complex-script shaping — Arabic letters do not join, a combining mark inside a right-to-left run can land on the wrong side of its base, and font hinting is not applied.
  • Media gaps — WebP, AVIF, an...
Read more

Sashfold 0.0.7

Sashfold 0.0.7 Pre-release
Pre-release

Choose a tag to compare

@codingncaffeine codingncaffeine released this 04 Sep 20:38

The fourth pre-release of Sashfold, and the largest so far: forty-seven changes since 0.0.6. The theme of it is that a page no longer has to read left to right and across the page to be laid out correctly. The whole bidirectional algorithm is written and scored, so an Arabic or Hebrew page comes out with its boxes on the right side; the vertical writing modes are laid out, so a Japanese page can run down the page and across it; and the flow-relative properties modern stylesheets are actually written in — margin-inline, padding-block and the rest — are read at last, where before they gave a page no padding at all. Boxes that scroll became boxes you can scroll. The CSS reference tests went from 7215 of 13,477 to 8345 of 14,616, the count having grown because the writing-modes directory joined the scored set. Still every byte is written in this repository, and still it does not pretend to do what it cannot.

What's New

  • Right-to-left pages — direction, the dir attribute, dir="auto", and unicode-bidi's embeddings, isolates and overrides, over the complete Unicode bidirectional algorithm — 861,948 conformance cases, all passing. A line is reordered as the algorithm says, a run that reads the other way has its characters reversed and its brackets mirrored, and the boxes follow: a flex container's two axes, a grid's columns, a table's columns, the first line's indent, the room a width leaves over, and where a box out of the flow stands when it names no offsets.
  • Vertical writing — writing-mode: vertical-rl, vertical-lr, sideways-rl and sideways-lr. Lines stack across the page, text runs down it, every glyph of a horizontal script turns a quarter circle, and a box whose mode differs from the one around it is laid out in a frame of its own and turned back into the page when it is done.
  • The flow-relative properties — margin-inline, padding-block, inset-inline-start, border-block-end, the logical sizes and the four-side shorthands. Modern stylesheets are written in these, and until now they were not read at all.
  • Boxes that scroll — overflow: auto and scroll are scroll containers, not just clipping. A wheel over a pane moves the pane and passes the notch outward when the pane has no room left, exactly as a browser should; a pane that can only move across takes a plain wheel that way, which is what a wide table in a narrow column needs. Scrollbars are drawn, their thumbs can be dragged, the track beside them pages, the keyboard follows whatever you last moved, and find-in-page and #anchor links reach inside.
  • See-through boxes — opacity between zero and one paints what it should. A box at half strength is composited as one group, so where two things inside it overlap the one underneath does not show through the one above.
  • Highlighted spans join the stack — An inline box can now carry a z-index, a transparency, a transform or position: sticky, and its words travel with it instead of being buried under its own background.
  • Boxes that stick — position: sticky holds a box inside what its offsets leave of the scrollport it is in, without letting it leave the block that contains it.
  • :has() and :nth-child(… of S) — A selector can ask what an element holds, and count only the children that match a selector of its own.
  • Lists that number themselves — Markers are placed as the specification asks, inside or outside; the automatic list-item counter carries start, an item's own value and an author's counter-reset through to the number that is drawn; counter() and counters() see what their scope can see.
  • Justified text — text-align: justify shares out the room a line did not use, with text-align-last and justify-all for the line that ends the block.
  • Text cased on the way out — text-transform: uppercase, lowercase and capitalize.
  • Intrinsic sizes — min-content, max-content and fit-content as widths, so a box can be asked to be the size of what it holds.
  • box-sizing: border-box — A written width can name the border box, which is how most stylesheets are written.
  • Flex auto margins — margin-left: auto on a flex item takes the room the line has left, which is the "push this one to the far end" navigation bar idiom. flex-basis: content with it.
  • A grid row shares a baseline — Items in a row are measured, the furthest baseline wins and the rest are pushed down to meet it.
  • A picture sits on its line properly — An image in a line of text is placed against the line's baseline, and down a vertical page it is set astride the line rather than standing on it.

What's Fixed

  • A modern stylesheet gave a page no padding — padding-inline: 1rem and its relatives were parsed as nothing at all, on an English page as much as an Arabic one.
  • A relatively positioned <span> moved nothing — offsets on an inline box were dropped, which was also why most of the line-height reference tests failed.
  • margin-left: auto did not push a box to the far end of its block.
  • A table cell's written height now belongs to its row, so a row is at least as tall as the cell that asked for it.
  • An absolutely positioned box beside a float began one float-width in and left what it was meant to cover showing. It now starts where its block's content starts.

What's Not Written Yet

  • No scripting — Pages render as served; JavaScript is not run. Pages that build themselves with scripts arrive blank, their menus and banners do not toggle, and a benchmark that drives itself cannot start.
  • Layout gaps — subgrid and masonry are passed over; a grid's columns do not share a baseline yet, and neither do a flex line's items; line-clamp; margin-trim. Scrollbars are drawn over the content rather than taking room from it, the way an overlay scrollbar does.
  • Painting gaps — Shadows, outlines, filters, border-image; a transform can translate but not rotate or scale; background-attachment: fixed scrolls with the page.
  • Text gaps — text-overflow, hyphenation, word-break, ligatures and complex-script shaping, so Arabic letters do not join and a combining mark in a reversed run lands on the wrong side. text-transform uses the simple case mappings, so sharp s stays sharp s. In vertical text, text-orientation and text-combine-upright are not written.
  • Media gaps — WOFF fonts, WebP, AVIF and SVG pictures, animated GIF beyond the first frame, audio and video.
  • Windows only for the window — The engine and its command line build and test on Linux and macOS in CI; there is no Linux or macOS window yet.

Measured

  • CSS reference tests — 8345 of 14,616 over CSS 2 and sixteen CSS module directories, up from 7215 of 13,477; the count grew because the writing-modes directory joined the scored set. The table is at sashfold.com/wpt.html.
  • At 100% — Both html5lib suites (7032 and 1784), WPT URL parsing (893), and the Unicode bidirectional conformance suites (861,948 cases).
  • The Sashfold 100 — 88 of a hundred pages of the live web now render, up from 82. What each page asks for that is not written yet is listed at sashfold.com/sashfold100.
  • Every one of these is held by CI: a test that stops passing fails the build.

Running It

  • Unzip and run sashfold.exe — Keep themes beside it. sashfold.exe https://en.wikipedia.org opens the window on a page; with no address it opens the about page. Downloads go to your Downloads folder.
  • Requirements — Windows 10 or 11, 64-bit. The binary is statically linked and imports only the operating system's own libraries, which is checked in CI.
  • Source — Linux and macOS build from source with CMake and Ninja; the window itself is Windows for now.

Sashfold 0.0.6

Sashfold 0.0.6 Pre-release
Pre-release

Choose a tag to compare

@codingncaffeine codingncaffeine released this 03 Sep 13:12

The third pre-release of Sashfold. Since 0.0.5 the work has gone into the things that make a page look like itself rather than like a wireframe: rounded corners, table borders that collapse into one line, backgrounds that tile the way they were asked to, spacing between letters and words, an indented first line, a dressed first letter, and inline boxes that finally draw their own backgrounds and borders. The CSS reference tests of the Web Platform Tests went from 6245 to 7215 of 13,477 — past half for the first time. Still every byte is written in this repository, and still it does not pretend to do what it cannot.

What's New

  • Rounded corners — border-radius in all its forms: one radius or four, elliptical corners through the slash syntax, percentages, and the pill that settles to a stadium. A rounded box clips what it holds, its border curves with it, and each side keeps its own colour around the bend.
  • Table borders that collapse — border-collapse: collapse resolves one line where two boxes meet, the widest winning and ties going to the cell, with border-style: hidden taking a line away entirely.
  • Backgrounds that tile as asked — background-repeat: space shares the remainder between the tiles and keeps the ends flush; round rescales so a whole number fits. A background written on body is handed to the canvas and laid out as if it had been written on the root, so a page's backdrop covers the window.
  • Letter and word spacing — letter-spacing and word-spacing add room after every character and after every space, in the layout and in the drawing alike, so an underline reaches the last gap and a spaced line wraps where it should.
  • An indented first line — text-indent moves the first line of a block, in pixels or as a percentage, and a negative one hangs it out to the left. It is measured from the edge a float leaves, and it inherits into the blocks inside.
  • The first letter, dressed — ::first-letter (and the one-colon spelling) in a colour, a weight or a size of its own — the drop cap a page opens with. It takes the punctuation on either side of the letter, in every script Unicode calls punctuation, and finds the letter wherever it was written, including inside the first block of a block.
  • Inline boxes draw themselves — A span's own background, border and padding are painted and take room on the line, so highlighted phrases, code spans, tags and pills look like themselves. A box broken across lines is sliced at the break, as it should be.
  • Truer text measurements — The ex and ch units are read from the font actually in use — its x-height and the width of its zero — instead of standing for half the font size, so boxes sized in them come out the width their author meant.
  • Absolutely positioned grid children — A grid container places an absolutely positioned child in the area it names.
  • Links look like links, and only links — An <a> with no address is no longer coloured and underlined as one.
  • Standards scores you can check — The CSS reference tests, 13,477 of them over CSS 2 and fifteen CSS module directories, score 7215 passing — up from 6245 — held by CI so the number only rises; the table is at sashfold.com/wpt.html. The Sashfold 100 at sashfold.com/sashfold100 shows a hundred pages of the live web rendered every night, with what each page asks for that is not written yet.

What's Not Written Yet

  • No scripting — Pages render as served; JavaScript is not run. Pages that build themselves with scripts arrive blank, their menus and banners do not toggle, and a benchmark that drives itself cannot start.
  • Layout gaps — subgrid and masonry are passed over; grid items align to the start rather than a shared baseline; min-content, max-content and fit-content are not read as sizes; text-align: justify lays out as left; counters and list markers are not placed per the specification; right-to-left pages are shown left-to-right.
  • Painting gaps — Shadows, outlines, filters, border-image; rotations and scales are passed over; opacity between zero and one paints as opaque; background-attachment: fixed scrolls with the page.
  • Text gaps — text-transform, text-overflow, hyphenation, word-break, ligatures and complex-script shaping; font-synthesis cannot be turned off.
  • Media gaps — WOFF fonts, WebP, AVIF and SVG pictures, animated GIF beyond the first frame, audio and video.
  • Windows only for the window — The engine and its command line build and test on Linux and macOS in CI; there is no Linux or macOS window yet.

Running It

  • Unzip and run sashfold.exe — Keep themes beside it. sashfold.exe https://en.wikipedia.org opens the window on a page; with no address it opens the about page. Downloads go to your Downloads folder.
  • Requirements — Windows 10 or 11, 64-bit. The binary is statically linked and imports only the operating system's own libraries, which is checked in CI.
  • Source — Linux and macOS build from source with CMake and Ninja; the window itself is Windows for now.

Sashfold 0.0.5

Sashfold 0.0.5 Pre-release
Pre-release

Choose a tag to compare

@codingncaffeine codingncaffeine released this 02 Sep 21:59

The second pre-release of Sashfold. Since 0.0.3 the engine has grown the layout the readable web is built on — floats, flexbox, grid, tables, positioning — and the browser around it has grown selection, find, reader mode and devtools. It scores itself on the Web Platform Tests' CSS reference tests now, 6245 of 13477 passing, and renders a hundred live pages every night at sashfold.com. Still every byte is written in this repository, and still it does not pretend to do what it cannot.

What's New

  • Floats, flexbox, grid and tables — Boxes float left and right with lines flowing beside them and clearing below them; flex rows and columns that wrap, grow, shrink and align, with gaps; grid containers with explicit and implicit tracks, fr, repeat(), named lines and areas, spans, auto-placement and alignment; tables with automatic and fixed column widths, colspan and rowspan, captions, header and footer groups, and cells aligned by vertical-align. The old attributes work too: cellpadding, cellspacing, border, bgcolor, align, valign, width and height.
  • Positioning and stacking — position: relative, absolute and fixed with their offsets, and painting in CSS 2.1's stacking order with z-index, so menus, badges and overlays land where their pages put them.
  • Background images and gradients — Pictures by url() placed, sized, tiled and clipped as background-position, -size, -repeat, -origin and -clip say, in layers; linear gradients by angle or toward a side or corner, and radial gradients, with color stops; the background shorthand.
  • More of CSS — Custom properties and var(), calc(), min(), max() and clamp(), the viewport units, inherit, initial and unset on every property, inline-block, vertical-align, line-height, min- and max- widths and heights, percentage heights, visibility, opacity: 0, overflow clipping, translate transforms, ::before and ::after with strings, attr() and quotation marks, hsl() and all 148 named colors, and the font shorthand.
  • Web fonts — A page's own TrueType fonts through @font-face answer its font-family.
  • Text selection and the clipboard — Select with the mouse or the keyboard, copy with Ctrl+C, paste into a field with Ctrl+V.
  • Find in page — Ctrl+F opens a bar that counts the matches, highlights them and walks them with Enter.
  • Reader mode — A page's article alone, on a clean page of its own.
  • Keyboard link-hints — Press f and every link in view gets a label; type a label to follow it.
  • Devtools — F12 opens a panel with the document's tree, and the box and computed style of the element under inspection.
  • Forms without scripts — Text fields, checkboxes, radio buttons, selects and buttons are drawn, take input, and submit by GET.
  • Faster loads — Connections are kept and reused across a page's requests; an <img> picks its source from srcset, sizes and <picture> for the window it is shown in; revoked certificates are refused.
  • Standards scores you can check — The CSS reference tests of the Web Platform Tests, 13,477 of them over CSS 2 and fifteen CSS module directories, score 6245 passing, held by CI so the number only rises; the table is at sashfold.com/wpt.html. The Sashfold 100 at sashfold.com/sashfold100 shows a hundred pages of the live web rendered every night, with what each page asks for that is not written yet.

What's Not Written Yet

  • No scripting — Pages render as served; JavaScript is not run. Pages that build themselves with scripts arrive blank, and their menus and banners do not toggle.
  • Layout gaps — Table borders do not collapse (each box draws its own); subgrid and masonry are passed over; inline boxes do not paint their own backgrounds and borders; right-to-left pages are shown left-to-right.
  • Painting gaps — Rounded corners, shadows, outlines, filters; background-repeat: space and round tile plainly; rotations and scales are passed over; opacity between zero and one paints as opaque.
  • Media gaps — WOFF fonts, WebP, AVIF and SVG pictures, animated GIF beyond the first frame, audio and video.
  • Windows only for the window — The engine and its command line build and test on Linux and macOS in CI; there is no Linux or macOS window yet.

Running It

  • Unzip and run sashfold.exe — Keep themes beside it. sashfold.exe https://en.wikipedia.org opens the window on a page; with no address it opens the about page. Downloads go to your Downloads folder.
  • Requirements — Windows 10 or 11, 64-bit. The binary is statically linked and imports only the operating system's own libraries, which is checked in CI.
  • Source — Linux and macOS build from source with CMake and Ninja; the window itself is Windows for now.

Sashfold 0.0.3

Sashfold 0.0.3 Pre-release
Pre-release

Choose a tag to compare

@codingncaffeine codingncaffeine released this 02 Sep 03:33

The first pre-release of Sashfold: a web browser engine, and a Windows browser around it, written from scratch. Every byte that runs is in this repository: the HTML and CSS parsers, layout, text, the font engine, the image decoders, HTTP, cookies, the cache, and the window. It is early. It reads the readable web, and it does not pretend to do the rest.

What's New

  • A window that browses the live web over HTTPS — Tabs (Ctrl+T, Ctrl+W, Ctrl+Tab, middle-click on a link), history that keeps each page's bytes so Back never refetches, an address bar, link hit-testing, wheel and keyboard scrolling. Every pixel of the chrome comes from themes/default.json, which reloads while the window is open.
  • Your installed fonts — A TrueType reader and a rasterizer written here, a font manager that catalogues the system's fonts by their naming tables alone and matches CSS font-family, weight and slant, and a fallback chain by coverage, so a page mixes its own fonts with whatever the machine has for the characters they lack. Sashfold Mono, an original monospace face, is the last fallback and draws an honest box for anything no font has.
  • Images — PNG (every color type, bit depth and filter, interlaced), GIF (LZW, interlace, transparency; the first frame), and JPEG (baseline and progressive), each decoder written and fuzzed here, sized by CSS, attributes or the picture itself, drawn scaled with integer arithmetic.
  • A site's own stylesheets — <link rel="stylesheet"> and @import, decoded by the CSS charset rules, with media queries evaluated against the real window size and re-evaluated when it changes.
  • Rendering that is the same everywhere — The reference tests render with the built-in face alone and compare PNG bytes, so the same page produces byte-identical pixels on Windows, Linux and macOS, and the outline rasterizer is held to the built-in face's pixels exactly.
  • Privacy and safety defaults — Third-party cookies blocked, HTTPS first for typed addresses, strict-origin-when-cross-origin referrers, a certificate error page with no way through, downloads saved with the mark of the web and never opened, no default search, no telemetry, no self-updater.
  • Standards scores you can check — The HTML tokenizer at 7032/7032 and tree construction at 1784/1784 on the html5lib suites; the URL parser at 893/893 on WPT's urltestdata. Both are enforced in CI by baselines that only ratchet upward.
  • A command line for the engine — sashfold --render page.html -o out.png renders any page or URL to a PNG; --bench times parse, stylesheets, style, layout and paint; --dump-dom prints the tree; --font-info and --font-list show what the font engine sees.

What's Not Written Yet

  • Layout gaps — Floats, flexbox, grid, tables and positioning are not written, so pages built on them fall into one column. Nothing stands in for them: what Sashfold cannot do, it does not do.
  • No scripting — Pages render as served; JavaScript is not run.
  • No text selection or clipboard yet, no find-in-page, no animated GIF — The first frame of a GIF is shown.
  • Windows only for the window — The engine and its command line build and test on Linux and macOS in CI; there is no Linux or macOS window yet.
  • Loading blocks while it fetches — Each stylesheet and image is fetched in turn; a page with many pictures takes a moment to appear.

Running It

  • Unzip and run sashfold.exe — Keep themes beside it. sashfold.exe https://en.wikipedia.org opens the window on a page; with no address it opens the about page. Downloads go to your Downloads folder.
  • Requirements — Windows 10 or 11, 64-bit. The binary is statically linked and imports only the operating system's own libraries, which is checked in CI.
  • Source — Linux and macOS build from source with CMake and Ninja; the window itself is Windows for now.