Commit Graph
60 Commits
Author SHA1 Message Date
LeoVasanko 22c4f0e752 Layout: breakable paragraphs across columns, sidebar gets its own flexible track at every width, cols requires multiple paragraphs; h3 size fix in corporate theme 2026-08-28 23:23:51 +00:00
LeoVasanko c801fdc929 Make the page transition configurable, add crossfade/slide/reveal
The cube view-transition block moves out of pagerite.css into transition
designs (pagerite/themes/{name}/transition.css), handled like banner
designs: served from disk at /_themes/..., injected by the backend as
#pagerite-transition after the banner sheet, and picked site-wide in the
site settings (Data.transition, default cube; GET/PUT /_api/settings
carry transition + the designs found on disk). The site editor swaps the
sheet in place on change; the dev-mode order fixup knows the new id.

Designs: cube (unchanged), crossfade (all navigations), slide (sideways,
both pages moving together) and reveal (clip-path wipe over the
stationary old page) — the latter two mirrored on history-back and
crossfading within a section like cube.

Also compress the site settings form into a two-column grid: site name +
favicon on one row, theme + transition on the next.
2026-08-28 20:04:21 +00:00
LeoVasanko 7743639812 List markers: balanced indent via a centered full-indent box (--list-indent), ordered-list counters, task checkboxes seated as markers with label-wrapped toggle text, summer ⚜️ bullets. 2026-08-28 19:26:51 +00:00
LeoVasanko f659f5f6be Sibling-combinator top margins for h1/h2: no gap when first in a container (aside, admonition, colseg), h1 + h2 stacks tighter, page-top headings keep their banner spacing. 2026-08-28 18:01:00 +00:00
LeoVasanko f962d70e3b Section edit pens, cursor-driven piecewise scroll sync, URL-following editor.
Anchored h1/h2s carry data-line (markdown source line, top-level
headings only) and h2s get dimmed section pens that open the page
editor at that section. Editor scroll sync is now piecewise-linear
keyed on those anchors: the page follows the cursor (fractional,
wrap-aware, fixed window anchor; editor scroll no longer drives it),
the editor follows page scroll with a progress-based viewport anchor,
so document ends line up exactly in both directions. The editor always
follows the URL — fetch-navigation retargets it — with unsaved text
stashed per path for the session and restored on return. Banner pen
removed (the tab stays in the shell); top-right order is now
analytics, site settings, login/logout.
2026-08-28 17:42:35 +00:00
LeoVasanko 6910ccad73 Navigable section anchors: slug ids + self-links on h1/h2, scroll-tracked location hash.
Long-enough articles (3+ in-body h1/h2) get slug ids (python-slugify,
mirroring the editor's slugify.js) and the heading text becomes a
self-link (a.anchor) for clean link copying; {#id} always wins,
duplicates get -2/-3 suffixes, h3+ never. The implicit page title is
now injected as '# {title}' into the markdown (render(title=...)), so
it takes the same first-h1 path as an explicit one: no id, href=""
self-link scrolling to top, not counted toward the threshold. The
.body wrapper is gone — segments are direct article children — and the
editor preview swaps the whole article in one go. pagerite.js tracks
the reading position in the location hash (last tagged heading above
the viewport middle; cleared at the top, never on unscrollable pages)
and scrolls to anchors after fetch-navigation.
2026-08-28 16:12:17 +00:00
LeoVasanko ffa7200a6e Automatic navigational cards on index pages, replacing the sidebar menu. 2026-08-28 00:25:10 +00:00
LeoVasanko a116d78951 Flood fill images in aside. 2026-08-27 22:42:20 +00:00
LeoVasanko 825379ca2a Long articles become a bounded composition: fluid text lanes with a side zone for marginalia, centered in vacant space that grows with the viewport instead of stretching the content. 2026-08-27 22:15:17 +00:00
LeoVasanko ddf323bf41 Render the column layout structure on the backend, cap at two columns, add a left-margin breakout.
render() now segments the body into .colseg wrappers and flags .multicol
itself, replacing the fragile colseg injection in pagerite.js. Columns
are capped at two; shrink-wrapped figures left-align inside columns.
New {.margin} breakout (and ::: aside) drops blocks into the left gutter
on wide viewports, falling back to in-column floats.
2026-08-27 18:36:49 +00:00
LeoVasanko f708e1dbca Avoid breaks inside lists. 2026-08-27 17:24:08 +00:00
LeoVasanko 3518ac9ac7 Fixes to markdown extensions/styling. Sort crawlers most recent first. 2026-08-27 01:27:49 +00:00
LeoVasanko 5c2433b766 Correct font scaling by x size. Fix code receiving twice a smaller font size. 2026-08-27 00:15:47 +00:00
LeoVasanko 2959f971bc Implement support for {} attrs on code blocks (line right after the closing fence) and containers (::: aside {...}). 2026-08-27 00:08:51 +00:00
LeoVasanko 8ee22de060 Many more Markdown extensions and formatting improvements. 2026-08-26 23:51:05 +00:00
LeoVasanko 9be1491f0e Improved mobile layout. Banner section gets smaller and editor goes full screen. 2026-08-26 18:44:17 +00:00
LeoVasanko 56fd5f854d Selection color from base theme. 2026-08-26 17:03:01 +00:00
LeoVasanko 9cbc4ab59d Smoother scroll effects on banners using --pry. 2026-08-26 15:09:29 +00:00
LeoVasanko 38b894a789 Layout transition lags fixed with better editor panel handling. This was causing .wide sections visibly lag behind on viewport width changes. 2026-08-26 13:47:51 +00:00
LeoVasanko 7ba6094360 Proper cube transition background colors via base CSS mixing in theme bg. 2026-08-26 13:01:42 +00:00
LeoVasanko 6563eebdba Improve list bullet positioning. 2026-08-25 22:49:02 +00:00
LeoVasanko 8b1bb6f994 Avoid column break right after heading. 2026-08-25 22:31:52 +00:00
LeoVasanko 3173a113b6 Improved theme banner consistency across themes. 2026-08-25 22:29:28 +00:00
LeoVasanko 158b5f1961 Editor panel layout fixes, use body scroll and bidirectional sync with editor. 2026-08-24 21:41:33 +00:00
LeoVasanko 2d595f8c15 Reduce #brand to actual size, avoid clicks on empty banner space touching it. 2026-08-24 20:58:50 +00:00
LeoVasanko b1fc8e24d7 Eyes banner follows taps not just mouse. 2026-08-24 20:54:50 +00:00
LeoVasanko c5cf799f68 Better nav layout for portrait phones. 2026-08-24 20:43:18 +00:00
LeoVasanko b7fc543a83 Transition graph layout follows navigation. 2026-08-22 18:10:44 +00:00
LeoVasanko 8aad64cced Analytics layout update, larger, consistent text sizing. 2026-08-22 14:45:56 +00:00
LeoVasanko 319163ee7e Page caching and zstd compression. Avoid useless fetching. Mobile layouts of navigation menus improved. 2026-08-22 14:05:12 +00:00
LeoVasanko b4e8fad090 Implement analytics feature
Add server-side visit analytics collection, a public-page ping endpoint,
and a full-screen AnalyticsView for admins.

Backend:
- Add pagerite/analytics.py: Analytics/Visit model, Store, and persistence
- Wire /_a ping endpoint and GET /_api/analytics into pagerite/app.py

Frontend:
- Add full-screen AnalyticsView with visitor charts and transition map
- Add VisitorCharts and TransitionGraph subcomponents
- Add analytics JS helpers in frontend/src/analytics/
- Send navigation pings from frontend/src/pagerite.js
- Mount AnalyticsView from frontend/src/main.js
- Document the feature in docs/analytics.md and update AGENTS.md
2026-08-20 18:43:57 +00:00
LeoVasanko 512ed91b31 Bottom-anchor banner artwork, instant navigation via in-memory page cache, seed/stars/structure tweaks
- Fix banner artwork sizing: explicit 100% grid track so children
  stretch instead of resolving height:100% against a content-sized row
  (SVG intrinsic ratio bloated the row, cropping the artwork's bottom).
  Bottom-anchor via object-position, transform-origin and YMax slice.
- pagerite.js: in-memory page cache — preload every visible internal
  link once, serve navigation from memory without fetching; editors'
  loadPlain keeps the cache in sync (pagerite:page-fetched).
- Structure editor: delete pages directly, no two-step confirmation.
- New 'stars' banner design (drifting starfield) alongside 'eyes'.
- Rewrite seed content: welcome page, three-level docs section covering
  all Markdown features (source + rendered), showcase hierarchy with
  image positioning and a simple leaf-page banner example.
2026-08-19 01:40:26 +00:00
LeoVasanko 58e5d3ef2b Replace Paskia iframe auth flow with plain /auth/ links
Paskia does not support being iframed; the login/profile buttons are now
plain anchors, and a pageshow handler re-probes auth when history
navigation restores a cached page. Drops the paskia JS dependency.
2026-08-19 00:57:35 +00:00
LeoVasanko a9693e1dcb Nested sidebar nav, banner inherit label fix, editor UX polish
- Sidebar renders the section's whole subtree as nested lists (third
  level and deeper, article-list-style markers); the one-item sidebar
  rule yields when that item has children of its own; only the viewed
  page is highlighted (navbar keeps ancestor highlighting); first_leaf
  skips unpublished branches
- Banner design selector: inherit option names the resolved design and
  its true source (backend banner_design_source excludes the node's own
  setting; doc payload carries banner_design_inherited)
- Article editor: fenced code block on empty lines, table size picker
  popup, borderless save icon disabled by saturate(0) alone
- While editing, window scroll is locked and only #main scrolls; the
  panel exactly fills the available window height; editor scroll drives
  the article
2026-08-19 00:25:07 +00:00
LeoVasanko 4dac16a9ac Unify admin editors into a tabbed EditorShell (site, structure, article, banner)
- One mounted shell with four kept-alive tabs; pens open/switch tabs,
  closing only hides the shell so unsaved page-editor state survives
  until a real reload; admin panels never reload the page, regions are
  refreshed in place via the shared swapdoc.js helper
- SiteEditor split: site settings vs. the new StructureEditor tree tab;
  BannerEditor split out of the old site editor
- Article editor format bar (bold/italic/code/link/table/image) with a
  table size picker and Ctrl/Cmd-B/I/S bindings; fenced code block on an
  empty line; icon-only save button disabled (saturate(0)) when clean
- Media uploads use icon buttons; favicon upload by clicking the preview
  tile; placeholders reserved for actual defaults in effect
- Banner/site pens and auth buttons grouped in an .editor-pens container;
  page pen no longer shown to anonymous visitors
- While editing, window scroll is locked, the panel exactly fills the
  available window height, and only #main scrolls; editor scroll drives
  the article
- Banner design inherit label names the design and its true source;
  backend banner_design_source excludes the node's own setting and the
  doc payload carries banner_design_inherited
2026-08-19 00:14:05 +00:00
LeoVasanko 43b841ebb6 Add a mobile layout (48rem breakpoint) and the missing viewport meta
Pages now declare width=device-width, so phones render at real device
width instead of a scaled-down 980px layout viewport. Below 48rem the
content becomes a single column with the sidebar lifted above the
article as a wrapping link strip; floated .left/.right figures fall back
to plain centered figures (explicit img widths still shrink-wrap) and
.wide keeps its centered full-viewport bleed.
2026-08-18 22:33:11 +00:00
LeoVasanko f8cdfd53c0 Add admonitions plus autolink and sub/superscript markdown extensions
!!! note/warning/tip/... blocks (mdit-py-plugins admon) render as
lightweight callouts: accent bar + faint wash in the blockquote idiom,
recolored per type (tip green, warning pink/red via --admonition-color),
rounded and softly shadowed in the summer theme. Also enabled
gfm_autolink (bare URLs) and H~2~O / x^2^ sub/superscripts.
2026-08-18 22:00:00 +00:00
LeoVasanko 2140f06501 Restyle tables and definition lists in the base theme
Tables drop the hard 1px grid: a soft accent-tinted vertical gradient
header (overridable via --table-head-a/b), a very faint diagonal
--table-tint wash lifting the cells apart, and only a whisper of a row
separator. Definition lists become a lightweight two-column grid
(minmax term column, explicit grid-column placement so runs of
dt/dd stack right) with accent terms and no borders or fills. Tables
also join the bottom-margin-only spacing convention.
2026-08-18 21:54:37 +00:00
LeoVasanko a75ad6f5da Overlay scrollbars via OverlayScrollbars
overflow: overlay is dead in current Chromium, so an appearing native
scrollbar shifted the layout again. OverlayScrollbars replaces it with
floating auto-hiding scrollbars that never reserve space (native window
scroll APIs unaffected on a body target). Themed via --os-* variables in
pagerite.css; the html scrollbar-color styling stays as no-JS fallback.
(package-lock.json is gitignored.)
2026-08-18 20:30:08 +00:00
LeoVasanko 7f140001fa Simplify image/figure styling: markdown always renders standalone images as figures
Standalone markdown images (captioned or not) now become block <figure>
elements; only inline-with-text images and raw author <img> HTML stay
plain. This collapses the img/figure selector duplication in pagerite.css
into a default + override structure: figure fills the column, floats go
30% (1em text gap), an explicit width attribute shrink-wraps the figure
(images with width are left untouched by CSS so the attribute hint
survives), and .wide re-anchors are grouped with the main rule.
2026-08-18 20:29:56 +00:00
LeoVasanko 0ec9be330e Add the 'eyes' banner design; seed banners only on select sub pages
Banner designs can now ship arbitrary markup as banner.html (canvas +
style + script), taking precedence over banner.svg; the artwork is
inlined in a div[data-design] wrapper either way, which the editor's
live preview preserves (and never re-runs its scripts).

The bundled 'eyes' design (themes/eyes/banner.html + banner.css sizing
the stage) replaces the eyes canvas script that was embedded in the
notes-on-urls page's own banner — the page now just picks the design.
Seeds set banners only on select sub pages (the-long-read gradient,
canvas-nights stars): the front page no longer gets a banner image and
shows the theme's default design. Seed entries carry a banner_design
field.
2026-08-18 06:36:05 +00:00
LeoVasanko 87c0aac3c0 Add Server/Last-Modified headers and a {dates} dateline tag
An http middleware sets 'Server: pagerite' (dropping uvicorn's versioned
default) and content pages return Last-Modified from Node.modified. In
markdown, a {dates} line expands to the article's published/updated
dateline (updated shown only when it falls on a later day); the editor
preview resolves it for pages that exist, unsaved pages show it literal.
Demonstrated in the long-read seed page.
2026-08-18 06:15:45 +00:00
LeoVasanko 3cefdec56e Scrap the right gutter on fluid (multicol) articles
Long articles now span from the left gutter (which holds the overlaying
sidebar) to the right viewport edge instead of reserving a symmetric
right gutter. The .wide breakout is re-anchored accordingly: left margin
is the gutter share (20vw of the 1fr+4fr grid, 1/5 of the post-editor
width while editing) plus main's padding; the <=102rem sidebar case keeps
its constant -13.25rem margin.
2026-08-18 06:09:03 +00:00
LeoVasanko 6303d5ae6d Fix multicol layout pinning two fixed columns at narrow widths
The 78rem minimum on the center track prevented the article from ever
shrinking, locking long articles into two fixed-width columns that
overflowed the window. Drop the floor: the 4fr center share now scales
with the window in both directions, so column widths flex continuously
and the count falls to 1 when space runs out.
2026-08-18 05:53:56 +00:00
LeoVasanko 30947df16b Backend-served themes and selectable, inheritable banner designs
Themes move from Vite-built frontend assets to pagerite/themes/{name}/
folders holding theme.css and/or banner.css (+ banner.svg), served by the
backend at /_themes/{name}/... and re-read from disk per request (etag by
mtime), so on-disk edits show on the next page load even in prod and new
themes need no build or config. The theme and banner-design selectors
enumerate these folders via GET /_api/settings.

Banner designs: Node.banner_design picks a design per page (None inherits
from ancestors, then the front page, then the active theme's own design;
"" = none). The design's banner.css is linked in <head> (id
pagerite-banner, between theme and custom CSS) and its banner.svg inlined
into #page-banner first (marked svg[data-design]); the page's own
Node.banner HTML renders after it, so author code always wins. #page-banner
is now a stacking grid so artwork and author code overlay.

Dev/prod hot loading unified: the backend renders the theme/design links
in both modes; in dev pagerite.js only re-appends them (and the custom
CSS) after the Vite-injected base styles. Theme switches just swap the
link href. The pagerite:theme meta and Vite theme build entries are gone.
2026-08-18 05:46:02 +00:00
LeoVasanko d03ee7fa8f Make article layout fluid: CSS-driven column count, uncapped width
Replace the fixed 100rem two-column breakpoint with 'columns: 30rem' so
CSS fits as many >=30rem columns as the article's width allows, and let
long (.multicol) articles grow past the 78rem cap (4:1 share against the
gutters, keeping them symmetric for the .wide breakout math). Also treat
mid-article h1s as full-width column separators like h2s.
2026-08-18 05:14:21 +00:00
LeoVasanko 87deaa380b Exclude script and style tags from page banner styling to avoid them becoming visible on page. 2026-08-18 02:59:49 +00:00
LeoVasanko f11b772493 Integrate Paskia auth UI flows, hide delete for empty pages. 2026-08-17 22:32:18 +00:00
LeoVasanko a45a575f72 Login button styling 2026-08-17 22:09:48 +00:00
LeoVasanko a01d539cd0 Tidier scroll bar 2026-08-17 20:22:16 +00:00