Skip to content

onlyworlds 0.39.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 10:05
· 254 commits to main since this release
  • The World Anvil door (onlyworlds.worldanvil): python -m onlyworlds.worldanvil --file EXPORT.html OUT-DIR [--plan] and import_worldanvil(source, out_dir, plan_only=False) read World Anvil's "Export World" into a world folder written through write_folder. No AI, no account, no new dependency (the standard library's html.parser, through the Kanka door's HTML to Markdown). World Anvil's free export is not data: it is one print-style HTML page (/world/<slug>/export), saved from the browser, and the door reads that page. Proven on two real exports of one small world Seethe made on a free account (2026-10-23), each scrubbed of the page's scripts, forms, share links, tracking pixel and the account's handle by Boss's script (its verifier allows only World Anvil's own hosts after the cut) and banked as tests/fixtures/worldanvil/: the world's title, the World Codex of #article-<uuid> anchors under a category's heading, one div.article-print-container per article (its h1, the body, the template's filled fields as headed blocks, a Metadata tab with the template, visibility and category), and links between articles as a.article-explorer-link carrying data-article-id, data-template-type and data-article-privacy. What becomes what: an article becomes an element of its template's type by one table, TEMPLATE_TYPES (Character and person Character, Species Species, Geographic Location Location, proven; Settlement, Building / Landmark, Organization, Item, Language, Law, Spell, Military Conflict and Rank / Title believed; for the schema owner's ruling); an unknown template becomes a Narrative with supertype worldanvil and the template's name as subtype, named in the report. The body is the description as Markdown. A link to another article becomes its text and joins x_worldanvil_mentions (element ids), as a Kanka mention does; its editor anchor is page chrome. A link to an article not in the export stays as text, kept in x_worldanvil_unresolved and named. A mention World Anvil did not resolve (@Ada) stays as written and is named. A template field whose heading names a field of the type fills it when the value fits (text, a whole number, links to articles of the linked type); every other is kept as x_worldanvil_<heading> and named. The category is kept as x_worldanvil_category (no element: the export holds only its name). The template's name, a link's slug for it, the article's uuid and the Work In Progress badge are kept as x_worldanvil_template, _template_type, _id and _work_in_progress. Text in an article outside the parts the door reads is kept as x_worldanvil_unread and named; text on the page outside the articles is named. Not kept, named in the report: page chrome, the inherited default cover, who wrote an article and when, the counters, a link's address and tooltip. A Codex entry with no article (the empty draft in both files) is named, not made. Hidden, never dropped (Skeld's rule, OW Market h40 #11228; folder format §4.8): an article whose privacy is other than public in any place that gives it (a link's data-article-privacy, the Metadata tab's Visibility), or missing in one place while another gives it, is written whole with hidden: true and named with why; a Secret or subscriber block in a visible article becomes its own hidden Narrative, <article>: Secret, linked to the article. Unwalked on a real file: neither export holds an article that is not public, nor a Secret (a paid feature); both paths are tested on planted copies, and the Secret's markup is a guess. Ids are UUIDv5 of worldanvil:<world uuid>:<article uuid> (the world's uuid from the page's world block), so the two exports of one world give the same ids and a second run a byte-identical folder. producer.input is worldanvil-export (on the folder spec's §4.2 list).
  • The real files become 3 elements each: Ada Quay a Character (x_worldanvil_gender Woman, x_worldanvil_eyes Grey: the Character has neither field), Riverfolk a Species, The ferry crossing a Location; in the second, Ada and Riverfolk mention each other by id, Riverfolk carries the category "Quay folk", and the two @ mentions are named. The dist's folder lint passes both. Tests: the fixtures' hashes, and that no fixture carries the comment form's CSRF token, the account's handle, an analytics id or a Bing beacon (each pattern watched catching a planted sample); counts, types and fields; the same ids from both exports; the link round trip; the category from each place; the mentions kept as text; the report naming every unplaced item; the lint; two runs byte-identical; the round trip; --plan writing nothing; and on planted copies a private link, a Visibility other than Public, a missing privacy, a Secret block, a link out of the export, a template field naming a field, an unknown template, unread text, an article printed twice, refusals and the command line. 13 mutants watched failing, one per rule.