Keyboard shortcuts

← →
Previous or next page
S /
Search
?
Show this help
Esc
Close

Document previews

Strata can render local Markdown, a deliberately small HTML subset, RTF, CSV, and TSV with native GTK widgets. Each document preview has Rendered and Source views. Render documents by default under Settings → General → BROWSING chooses the initial view for each newly opened document; View source and View rendered in the preview header switch the current document without changing that preference.

Remote files never render. A remote Markdown, HTML, RTF, CSV, or TSV file previews as source only. A remote XLS, XLSX, ODS, or DOCX file is not offered for preview at all: its context menu has no Quick preview item, the preview drawer shows "No preview for this selection" in Icons and Columns view and hides in List view, and in 10xer mode i while the drawer is closed, or l in List and Columns view, shows "Nothing to preview". Copy the file to a local folder to preview it. Rendered previews are selected from the local filename or content type:

  • Markdown: .md, .markdown, .mdown, .mkd, .mkdn, .mdwn, text/markdown, and text/x-markdown;
  • HTML: .html, .htm, .xhtml, text/html, and application/xhtml+xml;
  • RTF: .rtf, application/rtf, and text/rtf;
  • delimited tables: .csv, .tsv, text/csv, and text/tab-separated-values.

Local XLS, XLSX, and ODS workbooks use the same table renderer but do not expose a raw Source view. Only the first worksheet is previewed. Formulas are not recalculated, macros are never executed, and workbook styling, charts, and merged cells are not reproduced. Values use Calamine's string conversion, not Excel's full number-format display.

Local DOCX documents render the same way and also have no Source view, since the file is a ZIP container rather than text.

Supported content

Markdown uses pulldown-cmark with tables, strikethrough, and task lists enabled. Headings, paragraphs, emphasis, lists, block quotes, web links, fenced and inline code, rules, tables, and line breaks render natively. Known fenced-code language hints use Strata's existing, theme-aware GtkSourceView syntax highlighting. Every rendered code block has a Copy code button that copies the whole block. Raw HTML is displayed as inert text, with the notice "Raw HTML is shown as inert text in Markdown previews."

Markdown images with relative paths render PNG, JPEG, GIF (first frame), WebP, BMP, and SVG content. Percent-encoded filenames are supported. Image files must be inside the document's folder or its descendants; symlinks cannot escape that folder. Inline images appear below their containing paragraph or list item. Images in tables remain alt-text placeholders. Absolute paths, file: URLs, data URLs, and remote images are not loaded; remote URLs are discarded and the notice "Remote and absolute image URLs are not loaded. Use images inside the document's folder." appears.

Fenced mermaid blocks render offline with mermaid-svg, a native Rust renderer, including flowcharts and sequence diagrams. Diagrams use the active theme's text and surface colors and update live. Copy diagram source copies the original Mermaid text. Unsupported or invalid syntax retains readable source with a fallback notice; the renderer does not promise complete Mermaid.js compatibility.

LaTeX equations use $...$ inline, $$...$$ for display math, or fenced latex/math blocks. Inline equations stay within the surrounding prose; selection/copy preserves the original LaTeX delimiters. Display equations offer Copy equation source. Equations, inline and display, use the active theme's text and surface colors and recolor when the theme changes. Base TeX and AMS notation supports fractions, roots, superscripts/subscripts, sums, integrals, and matrices. Unsupported commands fall back to readable source. Equations in table cells remain source text, and escaped dollars and code spans are not interpreted as equations. This is math notation support, not a full LaTeX document compiler.

RTF is converted in-process to the same HTML subset. Paragraphs, line breaks, bold, italic, underline, strikethrough, \'hh Windows-1252 escapes, and \uN Unicode escapes with their \ucN fallback characters are supported. Font, colour, style, list, and table control words carry no formatting: table cells and list markers become plain paragraph text, and font tables, stylesheets, pictures, headers, footers, footnotes, annotations, and other non-body destination groups are discarded. Code pages other than Windows-1252 are not honoured, so \'hh bytes in a document declaring another code page can decode to the wrong character.

DOCX is read with docx-rs inside the preview sandbox and converted to the same HTML subset. XML namespace prefixes are normalized by URI before parsing, so alternate prefixes and default namespaces preserve Word content. The helper limits both original and normalized XML parts to 64 MiB total and rejects DTDs. Headings (Heading1-Heading6, Title, Subtitle), quote styles, paragraphs, bold, italic, underline, strikethrough, line breaks, bulleted and numbered lists with their nesting level, and tables render natively; the first table row becomes the column titles. Each tab becomes a single space. Hyperlink text is kept but the link target is not, and images, drawings, text boxes, headers, footers, footnotes, comments, field instructions, and theme or style-sheet formatting are omitted. A field's displayed result text is kept. Table cells show their paragraphs joined into a single value. Nested tables inside a cell are omitted. A DOCX whose converted content exceeds the helper's size budget stops at that point and shows "Document preview reached its size budget; open the file to see all content." Legacy DOC, ODT, and presentation formats are not supported.

HTML uses html5gum tokenization and supports semantic containers, headings, paragraphs, emphasis, underline (u, ins), lists, block quotes, http and https links, pre/code, rules, simple tables, and line breaks. Normal flow whitespace is collapsed like HTML, while pre content remains exact. A known language-* class on code inside pre sets the syntax hint. language-mermaid renders a diagram, and language-latex or language-math renders a display equation, as fenced Markdown blocks do. Classes never enable CSS. Entities are decoded before their text is escaped for Pango.

CSS, classes, IDs, metadata, and other presentation attributes are ignored. Scripts, styles, forms, frames, objects, embedded content, images, media, event handlers, unsafe links, and resource-bearing tags or attributes are omitted. If a document still has useful safe content, Strata renders it with the notice "Unsupported or active HTML content was omitted." u and ins render as underline without that notice. Link schemes are checked again when a link is activated before the existing external URI launcher is used.

Limits and fallback

Rendered parsing has fixed limits:

  • 1 MiB input;
  • 20,000 parser events;
  • nesting depth 32;
  • 256 columns per Markdown or HTML table row;
  • 4 MiB of escaped Pango markup;
  • 500 ms parser time.

A truncated, malformed, contentless, timed-out, or limit-exceeding Markdown, HTML, RTF, CSV, or TSV document opens in Source. The view-switch control is hidden and the reason is shown above the source preview. A DOCX has no Source view: when its converted content is empty or exceeds these limits, the preview shows "Preview unavailable" with the reason, such as "Rendered preview exceeded the 20,000 parser-event limit". A cancelled parse, such as one interrupted by selecting another file, is discarded without a result. CSV and TSV skip the parser-event and nesting limits; a row over 256 columns stops the table at that row with the table budget warning instead (see Interactive tables).

Source previews whose language GtkSourceView recognizes, such as Markdown and HTML, use the syntax-highlighted SourceView up to the 1 MiB read limit. Other source previews use SourceView, without highlighting, up to 128 KiB and 512 lines with no logical line over 2 KiB. Larger ones, and files with longer lines, use recycled plain-text rows; long logical lines are fully represented as contiguous 2 KiB virtual rows. A Markdown, HTML, RTF, CSV, or TSV document cut at the read limit shows "Rendered view is unavailable because the document exceeds the 1 MB preview limit." above its Source view. A source preview cut at the read limit shows "Preview limited to the first 1 MB", except a document's Source view in the syntax-highlighted SourceView, such as local Markdown or HTML. A recycled-row preview whose long lines were split shows a notice that long source lines are split into virtual rows for responsive scrolling; when that preview was also cut at the read limit, one combined notice says both. Toggle word wrap in the preview header wraps source and rendered prose for Markdown, HTML, RTF, CSV, and TSV. It defaults to off, applies in every open window, and survives restart. DOCX and workbook previews have no wrap button, and their rendered text does not wrap. In wide previews the Rendered view stops growing at 1280 px and stays centered; Source views and standalone tables keep the full width. Selection and model-backed copy preserve the original line breaks. File reading remains limited to 1 MiB; Open in default application in the preview header opens the complete file. The file chooser's preview has no such button.

When Source is the initial view, parsing is deferred until the user requests Rendered. Rendered paragraphs and code are grouped around a 32 KiB target, while individual pathological lines are divided into contiguous 2 KiB virtual rows before GTK layout; tables remain atomic document-selection units but use their own recycled, vertically scrolling rows, with exceptionally large cell displays bounded while table copy retains complete text. Cell formatting that expands beyond 16 KiB is shown as plain text with an explanatory accessible description. Complete code blocks use syntax highlighting, while blocks split for virtualization remain plain to keep highlighting bounded and lexically correct. Both large source and rendered previews use GTK list virtualization, so only visible rows own Pango layouts, text buffers, table grids, or cells. Drag selection is stored in document coordinates and survives row recycling; copy reads from the model, with tables represented as tab-separated text.

Text selection and find

Rendered prose and code, and large source previews shown as recycled rows, support double-click word selection, triple-click selection of a logical line (a whole paragraph in prose), Shift+click extension, and Shift+Left, Shift+Right, Shift+Up, Shift+Down, Shift+Home, and Shift+End. Ctrl+Shift+Left and Ctrl+Shift+Right extend by words; Ctrl+Home and Ctrl+End move to the start and end of the loaded document. Ctrl+A selects the whole loaded document, and Ctrl+C copies the selection. Selection and copy use document coordinates and survive recycled rows. In 10xer mode, while a document preview owns the keys, these keys still select text: Shift with an arrow, Home, or End (with or without Ctrl), and Ctrl+Home and Ctrl+End, reach the document instead of scrolling it. Ctrl+A and Ctrl+C select and copy the document's own text, never listing items.

Shift+Left and Shift+Right step over a whole grapheme cluster, such as an emoji with a skin-tone modifier. Right with a selection collapses it to its end. With the default key map, plain Left returns focus to the file listing. A click past the end of a wrapped line puts the caret at that display line's end. A Shift+click or double-click on a link selects its text; only a plain single click opens the link. Keyboard selection never changes the listing's selection. Smaller source previews use a native read-only text view with a caret and native keyboard text selection.

The header shows Find in preview only while the preview has searchable text. It sits after View source or View rendered and before Open in default application. Its tooltip reads "Find in preview (Ctrl+F)", or "Find in preview (/)" in 10xer mode, and toggling 10xer mode updates it. Click it, or press Ctrl+F (/ or keypad / in 10xer mode) while the preview owns focus, to search loaded source text or rendered prose and code. The find bar opens with its entry focused and the previous query selected. Search is literal and case-insensitive, and matches do not overlap: "aa" in "aaa" counts once. The query holds at most 256 characters.

The selected match is revealed and can be copied. The status reads "Match 1 of N" or "No matches", and is hidden while the query is empty. Enter and Next match, or Shift+Enter and Previous match, move between matches and wrap at either end; with zero matches both buttons are unavailable. An open find re-runs as an incrementally loaded source preview grows. Escape or Close find hides the bar and returns focus to the document without closing its preview; the selected match stays selected for Ctrl+C. The query follows Source and Rendered switching and survives reloading the same file. Previewing a different file, or closing the drawer, closes the find bar and clears the query.

Find does not read beyond the existing preview limits, search other files, or perform OCR. Rendered table cells, PDF pages, images, archives, and media are not searched. A Rendered view holding only tables shows no Find in preview button; textual tables can be searched in Source view. In 10xer mode, / in a preview with no searchable text returns the keys to the file listing and opens the listing's find prompt. Ctrl+F still filters filenames when the file listing owns focus, and in 10xer mode it keeps paging the preview.

Interactive tables

CSV and TSV use quote-aware parsing, preserve multiline fields, and tolerate ragged rows. The first row becomes column titles. Markdown and HTML tables share the same native ColumnView; HTML row headers remain styled cells when the first row is not entirely headers.

Tables open sorted ascending by the first column. Hover a column title for the pointer cursor, click to sort ascending or descending, and drag its divider to resize it. A compact up/down caret at the right of the header indicates the current direction. Standalone tables fill the preview's available height with a minimum height; tables embedded in prose retain their own bounded scrolling area. Sorting uses finite numeric values first, case-insensitive text next, and empty values last in ascending order; descending reverses that order. Sorting changes only the preview, never the file. Initial widths sample up to 64 rows, reserve enough room for compact fields, and give spare width to longer text. Every column, including the last, can be resized. Manual widths and sort order survive row recycling while that rendered view remains open.

Drag through cells and rows to select a continuous range in displayed sort order; dragging near an edge scrolls the table and preserves selection across recycled rows. Ctrl+C copies that range with tabs between cells and newlines between rows. A single click in any cell or empty space, or changing the sort, clears the selection. With a range selected, Ctrl+A, Ctrl+Shift+A, Escape, an arrow key, Home, or End also clears it; Ctrl+Alt+A leaves it. Native keyboard selection within a cell remains available. With focus on the table rather than a cell label, Ctrl+C copies all loaded rows in their current sorted order, with original full cell text and tab separators. Ctrl+Shift+C, Ctrl+Alt+C, and Ctrl+Super+C copy nothing from a focused table. With a non-Latin layout such as Russian, Ctrl+A in a focused cell selects that cell's text, and with no range selected Ctrl+C copies the cell's own selection, not the whole table. Cross-document selection also copies tables in their current order. Native sortable column titles are plain text; body cells retain supported inline styling and safe links.

Tables have no fixed row cap: a table over 200 rows or 512 cells renders in full. Markdown, HTML, and DOCX tables still count toward the 20,000-event and 4 MiB markup limits, so a table of a few thousand rows can exceed them (see Limits and fallback). Delimited and workbook output stops at 100,000 values, 4 MiB of cell text, or 256 columns, and a limited table shows "Table preview reached its text, column, or value budget; open the file to see all data." CSV/TSV retain the 1 MiB source-reading limit and Source fallback. Virtualization bounds resident row widgets; it does not make parsing or model memory unlimited.

Images, diagrams, and equations load asynchronously as rows are visited. Each preview renders at most 16 of them; every later image, diagram, or display equation shows "Preview limited to 16 images, diagrams, and equations" with its alt text or source, and a later inline equation shows its LaTeX source. Local images are limited to 8 MiB, Mermaid input to 16 KiB and 256 lines, equation input to 4 KiB, and decoded output to 800 × 800 pixels. Larger Mermaid blocks remain virtualized code. Media renderers run as per-request jobs inside the pooled preview supervisors (10-second CPU and bounded wall deadlines). That pool is separate from the file-list thumbnail pool, so a folder's thumbnail backlog does not delay a document's images, diagrams, or equations. Closing the preview cancels pending work. Missing files, unsupported formats, and decoder errors preserve alt text or diagram source without preventing the rest of the document from rendering.

Trust boundary

Document parsing and layout derivation run off the GTK thread through gio::spawn_blocking. The in-process, pure Rust parsers consume only the already bounded source string and produce escaped Pango markup. The layout boundary immediately decodes that reviewed markup into plain text and semantic spans before GTK receives it. Parser cancellation and preview request identity are checked before results are published.

Workbooks and Word documents are different: Calamine can allocate a complete worksheet before rows are extracted, and docx-rs decompresses every document part into memory. XLS/XLSX/ODS and DOCX parsing therefore runs in the preview sandbox, with a 20 MiB input-file limit, 2 GiB address-space limit, 10-second CPU limit, and 12-second wall deadline. Cancellation terminates the helper. The application validates bounded JSON cell or HTML output before parsing and deriving the shared document layout; DOCX HTML is generated by the helper, escaped, and reparsed by the same bounded HTML parser local .html files use. Compressed file size alone is not a decompression-memory limit.

This path does not use WebKit, Chromium, document script execution, or document CSS rendering. Document text parsers do not access files or the network. Markdown image references are opened atomically beneath the document directory, checked for regular-file type and size, then copied to private temporary inputs. Image decoding, Mermaid rendering, and equation rendering run in the existing resource-limited Bubblewrap sandbox, with no network or document-directory mount. Equations use a bundled, pinned MathJax program in QuickJS with no host bindings or module loader; user input is a string argument, never executable JavaScript. The JavaScript heap and stack are capped at 64 MiB and 1 MiB, with a two-second interrupt deadline. Only base and AMS TeX packages are registered; autoload, require, and HTML extensions are unavailable. No external TeX executable or npm installation is needed at runtime. See renderer build inputs. SVG subresource resolvers are disabled, including embedded images. Only validated bounded PNG output crosses back to GTK. Native GTK creates the final widgets; only a user-activated, revalidated http or https link can launch an external application.