HTML policy
Uploads may contain inline classic <script> blocks, and inert data blocks
(<script type="application/json"> / application/ld+json, which no browser
executes). Rejected at upload time: external script sources, module scripts,
importmap, inline event handlers (on*), javascript:/vbscript:/file:
URLs, <form>, <iframe>/<object>/<embed>/<applet>, <base>, <link>,
srcdoc, meta-refresh, and unsafe inline CSS. Once stored, drafts are served
verbatim.
Two rules relax per-server, off by default:
--allow-font-linksaccepts a<link>whoserelis onlystylesheet/preconnect/dns-prefetch/preloadand whosehrefhost isfonts.googleapis.comorfonts.gstatic.com.<base>and every other host stay blocked. The flag also addsstyle-src https://fonts.googleapis.comandfont-src https://fonts.gstatic.comto the CSP on served drafts, without which an accepted font link would still be blocked in the browser.--allow-safe-handlersaccepts an inlineon*handler whose body is nothing but;-separated assignments of literals or dotted property paths , the async-CSS idiomonload="this.media='all'". Anything containing(,[,<, a template literal, or a blocked scheme is still rejected, so a permitted handler can set properties but cannot call anything.
Accepting a script at upload is not the same as letting it run. Drafts serve with
script-src 'none' by default, so an inline <script> is stored and returned
byte for byte but never executes in a browser, and neither does an on* handler
accepted by --allow-safe-handlers. --allow-inline-scripts switches the served
CSP to script-src 'unsafe-inline', which covers inline scripts, event handlers
and javascript: URLs alike; upload validation is what keeps the last two in
check. connect-src stays 'none' regardless: a draft is a document, not a
client for something else.
Uploading a document with inline scripts to a server that does not have the flag returns a warning saying so, rather than leaving you to find it in the browser console.
keryx upload reads the server’s effective policy from GET /api/me before
validating locally, so the CLI never rejects a document the server would accept.
PDF publication supports semantic HTML, paginated tables, inline SVG diagrams,
and base64-embedded PNG, JPEG, and GIF <img> elements. A body-level header
becomes the cover, and top-level sections begin on new pages. Use
keryx-page-flow to keep a section in normal flow, keryx-page-break to force
another element onto a new page, and data-keryx-print="stack" to flatten a
custom multi-column layout for A4. Script-generated content, <canvas>, CSS
imports, external images, and CSS image URLs are rejected for deterministic
publication. An empty data-keryx-version element is filled with the selected
version in the render copy.