You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The current ResourcesPanel is a placeholder ("Coming Soon"). This issue tracks the full design and implementation of a resources system covering:
An uploader / manager for bitmap images, SVGs, and HTML tables.
A built-in table editor supporting postext's markdown microformats, inline math, and col-span / row-span.
A per-resource caption that renders as the resource's figure/table foot in the viewer.
A configurable list of resource types (figure, table, diagram, image, …) managed separately, each with its own auto-numbering format and reset scope.
A markdown syntax extension so authors can reference resources inline, with numbers resolved automatically.
Automatic numbering follows order of first reference in the document, not creation order in the panel. Inserting a new reference earlier in the text renumbers the rest automatically.
typeResourceKind='bitmap'|'svg'|'table';interfaceResource{id: string;// slug-like, user-editable; must be uniquetypeId: string;// references ResourceType.idkind: ResourceKind;caption?: string;// rich text — parsed with the same inline microformats as body textaltText?: string;// accessibility; for bitmap/svgcreatedAt: number;updatedAt: number;// Kind-specific payloadbitmap?: {fileId: string;format: 'png'|'jpeg'|'webp'|'gif';width: number;height: number;};svg?: {fileId: string;};table?: {model: TableModel;};}
Binary blobs (bitmap / SVG source) live in IndexedDB, referenced by fileId — same pattern as custom fonts in #44. Tables are stored structurally (TableModel), not as raw HTML, to stay editable.
List of resources grouped by type, with thumbnails for bitmaps and a glyph for SVG / tables.
"New" affordance with sub-options: Upload image, Upload SVG, New table.
Per-resource detail pane: id (editable, auto-suggested from filename/caption), type selector, caption editor (uses the same inline microformat input as body text so **bold** / $x^2$ etc. work), alt text for a11y, and kind-specific controls (replace file for bitmap/svg, open the table editor for tables).
Preview region showing exactly how the resource will render in the document, including the generated caption prefix (fig. 1.7. …) based on its type and a mock reference position.
Delete with confirmation — the confirmation must warn if the resource is referenced anywhere in the markdown, listing the reference count.
The markdown language must be extended so authors can reference resources inline. Two syntaxes:
5a. Block embed — places the resource at this point in the flow
::resource{id="lighthouse-diagram"}
On its own line, this directive embeds the resource here (caption included). This is what establishes the first-reference position for numbering purposes. If a resource is only ever ::resource-embedded once, its number is assigned at that embed point.
5b. Inline reference — cross-reference only, does not embed
As shown in :ref{id="lighthouse-diagram"}, the light is visible at 20 miles.
Renders inline as the formatted reference text — by default the resource type's shortLabel + number (e.g. fig. 1.7), but with options:
:ref{id="lighthouse-diagram"} → "fig. 1.7"
:ref{id="lighthouse-diagram"style="number"} → "1.7"
:ref{id="lighthouse-diagram"style="full"} → "Figure 1.7"
:ref{id="lighthouse-diagram"text="see it"} → "see it" (link text, number hidden)
An inline :ref before any ::resource embed counts as the first-reference position for numbering — this is what makes renumbering-on-insert work the way the user described. Embeds and references share the same numbering pass.
SVG block rendering — rasterize for canvas preview, embed as vector in PDF.
Table block rendering — lay out cells with col-span / row-span, measure via existing text measurement utilities, apply microformats and inline math inside cells.
Caption rendering below the resource, prefixed per the resource type's captionPrefix template.
Inline :ref rendered as a styled link (clickable in HTML, annotated in PDF) pointing at the embed location.
All resources must participate in the existing measurement / placement pipeline so they paginate correctly and respect keepWithNext-style constraints (resource + caption shouldn't split).
The .postext bundle format must carry resources/ binaries and a resources/index.json with the resource metadata + table models. Resource types belong in config.json (they're configuration).
Overview
The current
ResourcesPanelis a placeholder ("Coming Soon"). This issue tracks the full design and implementation of a resources system covering:Automatic numbering follows order of first reference in the document, not creation order in the panel. Inserting a new reference earlier in the text renumbers the rest automatically.
1. Resource types — a separate concept
Location: new section in
packages/postext-sandbox/src/sidebar/ConfigPanel.tsx, new config inpackages/postext/src/types.tsResource types are a first-class, user-editable list. Each type defines:
The
{h1},{h2}, … tokens resolve to the current section number at the resource's first-reference point. The{n}token is the per-type counter.Example:
resetOn: 'h1',numberingTemplate: '{h1}.{n}'gives numbers like1.1,1.2, …,2.1— exactly the book convention the user described.Each resource type keeps an independent counter: figures and tables don't interfere.
Built-in defaults provided out-of-the-box:
figure,table. Users can adddiagram,listing,equation, etc. from the settings UI.2. Resource storage
Location: new
packages/postext-sandbox/src/storage/resources.ts(IndexedDB), wired into theSandboxContextBinary blobs (bitmap / SVG source) live in IndexedDB, referenced by
fileId— same pattern as custom fonts in #44. Tables are stored structurally (TableModel), not as raw HTML, to stay editable.3. Table model & editor
Location: new
packages/postext-sandbox/src/panels/resources/TableEditor/Cell
contentis parsed with the same inline microformat pipeline as body text:**...**, italic*...*, code`...`— viainlineFormatting.ts$...$— viainlineMath.tsReuse is mandatory, not optional. The editor calls the existing parsers so tables can't drift from body text semantics.
Editor UX must support:
4. Resources panel UI
Location:
packages/postext-sandbox/src/sidebar/ResourcesPanel.tsx(currently a placeholder)Replace the placeholder with a full manager:
**bold**/$x^2$etc. work), alt text for a11y, and kind-specific controls (replace file for bitmap/svg, open the table editor for tables).fig. 1.7. …) based on its type and a mock reference position.5. Inline reference syntax — markdown extension
Location:
packages/postext/src/parse/inlineFormatting.ts,packages/postext/src/parse/blockParser.tsThe markdown language must be extended so authors can reference resources inline. Two syntaxes:
5a. Block embed — places the resource at this point in the flow
On its own line, this directive embeds the resource here (caption included). This is what establishes the first-reference position for numbering purposes. If a resource is only ever
::resource-embedded once, its number is assigned at that embed point.5b. Inline reference — cross-reference only, does not embed
Renders inline as the formatted reference text — by default the resource type's
shortLabel+ number (e.g.fig. 1.7), but with options:An inline
:refbefore any::resourceembed counts as the first-reference position for numbering — this is what makes renumbering-on-insert work the way the user described. Embeds and references share the same numbering pass.5c. Numbering pass
Location: new
packages/postext/src/pipeline/resourceNumbering.tsA new pipeline step, running after block parsing but before rendering:
idencountered (via either syntax), record the first occurrence.resetOnsetting.ResourceNumberingMap: Record<resourceId, { number: string; heading: HeadingContext; }>.::resourceembeds get captions and:refinlines get formatted numbers.This mirrors the existing heading numbering pattern in
packages/postext/src/numbering.ts— extend/parallel, don't duplicate.6. Rendering
Location:
packages/postext/src/canvas-backend/blockRender.ts,packages/postext-pdf/src/pdf-backend/index.tsCanvas and PDF backends must gain:
captionPrefixtemplate.:refrendered as a styled link (clickable in HTML, annotated in PDF) pointing at the embed location.All resources must participate in the existing measurement / placement pipeline so they paginate correctly and respect
keepWithNext-style constraints (resource + caption shouldn't split).7. Warnings
Location:
packages/postext-sandbox/src/warnings/compute.ts::resourceor:refwith anidthat doesn't exist in the resources panel.idduplicated (two resources sharing an id).:refpointing at a resource whose typeId was deleted from the type list.8. Bundle integration
Location: issue #47
The
.postextbundle format must carryresources/binaries and aresources/index.jsonwith the resource metadata + table models. Resource types belong inconfig.json(they're configuration).Acceptance criteria
ResourceTypelist + editor UI in config settingsResourcestorage in IndexedDB, binaries byfileIdResourcesPanelwith upload / create / edit / delete UX:ref)::resource{id=...}block directive:ref{id=... style=... text=...}inline directiveresetOn(none / h1 / h2 / …):refis clickable and navigates to the embed in HTML; PDF emits a link annotation.postextbundle from #47 round-trips resources and typesdocs/document-format-en.mdx,docs/configuration-en.mdx, and-es) with the new directives and type managementOut of scope (follow-ups)
Related code
packages/postext-sandbox/src/sidebar/ResourcesPanel.tsxpackages/postext/src/parse/inlineFormatting.ts,packages/postext/src/parse/inlineMath.tspackages/postext/src/parse/blockParser.tspackages/postext/src/numbering.tspackages/postext/src/types.tspackages/postext/src/canvas-backend/blockRender.tspackages/postext-pdf/src/pdf-backend/index.tspackages/postext-sandbox/src/storage/persistence.tspackages/postext-sandbox/src/warnings/compute.tsRelated issues
{h1}context for numbering templates