| Type: | Package |
| Title: | Lightweight Tables via JSON Specs and JavaScript |
| Version: | 0.2 |
| Description: | A lightweight grammar of tables. Build a table by declaring a JSON spec (titles, spanners, row groups, footnotes, formatting functions, etc.); a tiny vanilla JavaScript runtime builds the HTML table from the spec on page load. No 'sass', no 'V8', no 'htmlwidgets' — just base R and 'xfun' ('htmltools' is used only for the optional Shiny binding). |
| License: | MIT + file LICENSE |
| URL: | https://github.com/yihui/lt |
| BugReports: | https://github.com/yihui/lt/issues |
| Depends: | R (≥ 4.1.0) |
| Encoding: | UTF-8 |
| Imports: | xfun (≥ 0.60) |
| Suggests: | htmltools, knitr, litedown, magick, repr, shiny, testit |
| Config/lt.js: | 1.14.67 |
| Config/roxygen2/version: | 8.0.0 |
| NeedsCompilation: | no |
| Packaged: | 2026-07-09 20:21:06 UTC; yihui |
| Author: | Yihui Xie |
| Maintainer: | Yihui Xie <xie@yihui.name> |
| Repository: | CRAN |
| Date/Publication: | 2026-07-09 21:00:02 UTC |
lt: Lightweight Tables via JSON Specs and JavaScript
Description
A small grammar of tables. A table is a data frame plus a list of operations (title, spanner, footnote, ...); the operations are serialized to a JSON spec and applied to a plain semantic HTML table by a tiny vanilla JavaScript runtime at render time.
Author(s)
Maintainer: Yihui Xie xie@yihui.name (ORCID) (URL: https://yihui.org) [copyright holder]
Authors:
Yihui Xie xie@yihui.name (ORCID) (URL: https://yihui.org) [copyright holder]
See Also
Useful links:
Report bugs at https://github.com/yihui/lt/issues
Render an lt_tbl to HTML
Description
Emits the CSS+JS runtime and a script block carrying the table's JSON spec. Multiple tables on the same page only need the runtime once.
Usage
## S3 method for class 'lt_tbl'
format(x, fragment = TRUE, inline_assets = TRUE, assets = TRUE, ...)
Arguments
x |
An |
fragment |
If |
inline_assets |
If |
assets |
Which runtime assets to include: |
... |
Reserved for future use. |
Value
A character scalar containing HTML.
Examples
tbl = lt(head(mtcars))
html = format(tbl)
format(tbl, fragment = FALSE, inline_assets = FALSE)
Create a Table Specification
Description
Entry point of the lightweight grammar of tables. Returns an object (a
list) that records the data plus a list of table-modifying operations. The
object is rendered to HTML by format() (called automatically by the
print method).
Usage
lt(data, ...)
## Default S3 method:
lt(data, auto_format = TRUE, auto_label = TRUE, ...)
Arguments
data |
A data frame (or anything coercible to one). |
... |
Arguments passed to methods. |
auto_format |
Whether to automatically format numeric columns (rounding,
thousand separators, percentage detection). Set to |
auto_label |
Whether to automatically clean column names for display
by replacing separators ( |
Value
A table object that can be piped into lt_*() functions.
HTML in cells
By default all cell values and text (titles, labels, footnotes, ...) are
HTML-escaped, so special characters like <, >, and & render as
literal text. To emit content as raw HTML instead:
For body cells, mark whole columns with
lt_html().For a title, subtitle, column label, spanner, footnote, or note, wrap the text in
I(). For example,lt_header(x, I("<b>Report</b>"))renders the title as raw HTML, whilelt_header(x, "<b>Report</b>")shows the literal<b>tags.
Interactivity
When a cell value has been formatted (e.g., by auto-formatting or
lt_format()), the original value is stored in the cell's title
attribute and shown as a tooltip on hover. Additionally:
-
Alt + Clickon a table toggles display of all raw values in that table. -
Alt + Double-Clickon a table toggles raw values globally (all tables on the page).
Raw values are shown as (value) after the formatted text, highlighted
with a light yellow background.
Examples
lt(head(mtcars[, 1:4]))
Set Column Alignment
Description
Override the auto-detected alignment for specific columns. By default, numeric columns are right-aligned and character columns are left-aligned.
Usage
lt_align(x, columns, align = c("left", "center", "right"))
Arguments
x |
An |
columns |
Character vector of column names (or a one-sided formula). |
align |
One of |
Value
x with the alignment recorded.
Examples
lt(head(mtcars)) |> lt_align(~ cyl + gear, "center")
Attach Custom CSS
Description
Add user-supplied stylesheets or inline rules that render after the built-in CSS, so rules can override the defaults.
Usage
lt_css(x, ...)
Arguments
x |
An |
... |
Unnamed arguments are stylesheet paths or URLs. A bare
filename (no directory component) that does not exist in the working
directory is resolved against the stylesheets shipped with lt, so
e.g. Named arguments define inline CSS rules scoped to |
Value
x with the stylesheets recorded.
Examples
tbl = lt(head(mtcars))
tbl |>
lt_style("mpg", test = "v => v > 20", class = "high") |>
lt_css(.high = list(background = "#cfc", fontWeight = "bold"))
Format Date/Time Columns
Description
Format date or datetime columns using JavaScript's native Date methods.
The underlying data should be Date or POSIXt in R (serialized as
new Date(...) for the browser).
Usage
lt_date(x, columns, method = NULL, locale = NULL, options = NULL)
Arguments
x |
An |
columns |
Column selection (formula, character, or numeric). |
method |
A JS Date method name to call (e.g., |
locale |
A BCP 47 locale string (e.g., |
options |
A named list of
|
Value
x with the date formatting recorded.
Note
The formatted date may differ from the input date depending on the
viewer's local timezone. JavaScript's new Date("2024-01-15") parses
date-only strings as UTC midnight, but toLocaleDateString() converts to
the local timezone. For example, 2024-01-15 will display as
2024-01-14 for a viewer at GMT-6. To avoid this, pass
options = list(timeZone = "UTC").
Examples
d = data.frame(
event = c("Launch", "Update"),
date = as.Date(c("2024-01-15", "2024-06-30"))
)
lt(d) |> lt_date(~ date)
lt(d) |> lt_date(~ date, options = list(year = "numeric", month = "short"))
Export an lt table to a file
Description
Save a table to disk. The output format is chosen from the file extension
of output: .html writes an HTML table, .pdf writes a vector PDF, and
any other extension writes a PNG. PDF and PNG are produced by rendering the
table in a headless Chromium browser (via xfun::browser_print()).
Usage
lt_export(
x,
output = "lt.html",
method = c("auto", "node", "browser", "raw"),
css = TRUE,
fragment = FALSE,
tidy = FALSE,
crop = TRUE,
width = NULL,
padding = 8,
browser = NULL,
...
)
Arguments
x |
An |
output |
Output file path. Its extension selects the format: |
method |
How to produce the HTML |
css |
Whether to include the lt.css runtime stylesheet in the HTML
output. User CSS from |
fragment |
If |
tidy |
Whether to pretty-print the baked |
crop |
Whether to crop the PDF/PNG tightly to the table, removing the
surrounding page whitespace. This adds a preliminary browser pass to
measure the rendered table. Set to |
width |
The width of the table in CSS pixels. By default ( |
padding |
Padding in CSS pixels to keep around the table when
cropping. A single value (all sides) or a length-two vector
|
browser |
Path to the Chromium-based browser; passed to
|
... |
Passed to |
Details
For .html output, method controls how the <table> is produced:
"raw" writes the JavaScript-spec HTML, so the table is built in the
browser by the lt.js runtime when the file is viewed; the other methods
bake a static <table> up front by running lt.js once (via "node" in
Node.js or "browser" in a headless Chromium browser; "auto" picks Node
if available, else the browser), so the saved file needs no JavaScript to
view. method, css, fragment, and tidy apply only to .html output.
Value
The output path, or (when output is NA) the HTML as a string.
Global option
When the option lt.lt_static is set to a list of arguments (e.g.,
options(lt.lt_static = list(css = FALSE))), the
knit_print and record_print
methods emit the same static HTML table as lt_export(x, "*.html") (using
those arguments as method/css/fragment) instead of the default
JavaScript-based spec. This is useful for output formats that support raw
HTML but cannot run JavaScript (e.g., GitHub Flavored Markdown).
Examples
tbl = lt(head(mtcars))
# HTML with the JavaScript spec (table built by lt.js when viewed)
lt_export(tbl, NA, method = 'raw') # character output
f1 = tempfile(fileext = '.html')
lt_export(tbl, f1, method = 'raw') # file output
# Bake a static <table> (needs Node.js or a headless browser).
if (lt:::can_bake())
lt_export(tbl, NA, method = 'auto', fragment = TRUE, css = FALSE)
# PDF / PNG are rendered in a headless browser and cropped to the table.
f2 = tempfile(fileext = '.pdf')
f3 = tempfile(fileext = '.png')
if (lt:::has_browser()) {
lt_export(tbl, f2)
lt_export(tbl, f3, width = 400)
}
unlink(c(f1, f2, f3))
Add a Footnote
Description
Attaches a footnote text to a table region. Footnotes are numbered
automatically in the order they are added (de-duplicated by text).
Usage
lt_footnote(x, text, where, columns = NULL, rows = NULL, match = NULL)
Arguments
x |
An |
text |
Footnote text. |
where |
One of |
columns |
Character vector of column names or a one-sided formula (for
|
rows |
Integer vector of 1-based row indices (for |
match |
For |
Value
x with the footnote recorded.
Examples
lt(head(mtcars)) |>
lt_footnote("Source: 1974 Motor Trend US magazine.", "title")
# raw HTML footnote (wrap in I())
lt(head(mtcars)) |>
lt_footnote(I("See <a href='#'>docs</a>."), "title")
Format Numeric Columns
Description
Control the number of decimal places and thousands separator for numeric
columns. Columns passed to this function are excluded from automatic
formatting (see the auto_format argument of lt()). To disable auto-format
for a column without otherwise changing its display, call lt_format(x, ~col) with no other arguments.
Usage
lt_format(
x,
columns,
decimals = NULL,
big_mark = NULL,
percent = NULL,
prefix = NULL,
suffix = NULL
)
Arguments
x |
An |
columns |
Character or integer vector of columns (or a one-sided formula). |
decimals |
Number of decimal places (default |
big_mark |
Thousands separator (e.g., |
percent |
If |
prefix |
String prepended to each formatted value (e.g., |
suffix |
String appended to each formatted value (e.g., |
Value
x with the formatting recorded.
Examples
lt(head(mtcars)) |> lt_format(~ mpg + wt, decimals = 1, big_mark = ",")
d = data.frame(Item = c("A", "B"), Price = c(1234.5, 678.9))
lt(d) |> lt_format(~ Price, decimals = 2, big_mark = ",", prefix = "$")
Define Row Groups
Description
Partition rows into labeled groups. Pass column names to group by those
columns' values (the columns are removed from the body and rendered as
rowspan cells on the left). Use sep = TRUE to render groups as
full-width separator rows instead of rowspan.
Usage
lt_group(x, ..., sep = "auto", sort = TRUE)
Arguments
x |
An |
... |
A column name or formula (e.g., |
sep |
If |
sort |
If |
Value
x with the row groups recorded.
Examples
# Group by a column (rowspan, default)
d = data.frame(arm = c("Placebo", "Placebo", "Treatment", "Treatment"),
stat = c("n", "Mean", "n", "Mean"), value = c(30, 4.2, 31, 6.8))
lt(d) |> lt_group(~ arm)
# Separator-row style
lt(d) |> lt_group(~ arm, sep = TRUE)
# Manual groups (always separator rows)
lt(head(mtcars)) |>
lt_group("First three" = 1:3, "Last three" = 4:6)
Add a Title and Subtitle
Description
Add a Title and Subtitle
Usage
lt_header(x, title = NULL, subtitle = NULL)
Arguments
x |
An |
title |
A character scalar. Wrap in |
subtitle |
A character scalar. Wrap in |
Value
x with the header recorded.
Examples
lt(head(mtcars)) |> lt_header("Motor Trend Cars", "First 6 rows")
# raw HTML title
lt(head(mtcars)) |> lt_header(I("<em>Motor Trend</em> Cars"))
Render Column Cells as Raw HTML
Description
Mark whole columns so their body cells are emitted as raw HTML instead of
being escaped. By default every cell is HTML-escaped (so <, >, and &
render as literal text); use this to embed links, emphasis, or other markup
in a column's cells.
Usage
lt_html(x, columns)
Arguments
x |
An |
columns |
Column names (character or one-sided formula) whose cells are raw HTML. If missing, all columns are treated as raw HTML. |
Details
To emit raw HTML in other regions (title, column labels, footnotes, ...),
wrap the text in I() in the corresponding lt_*() function instead.
Value
x with the raw-HTML columns recorded.
Examples
d = data.frame(
name = c("<a href='#a'>A</a>", "<a href='#b'>B</a>"), n = 1:2
)
lt(d) |> lt_html(~ name)
Indent Rows
Description
Add hierarchical indentation to the first column of specified rows.
Usage
lt_indent(x, rows, level = 1)
Arguments
x |
An |
rows |
Integer vector of 1-based row indices to indent. |
level |
Indent level (default 1). Each level adds one unit of left padding. |
Value
x with the indentation recorded.
Examples
d = data.frame(label = c("Overall", "Male", "Female"), n = c(100, 55, 45))
lt(d) |> lt_indent(2:3)
Rename Column Labels
Description
Override column headers without modifying the underlying data frame.
Usage
lt_label(x, ...)
Arguments
x |
An |
... |
Named arguments of the form |
Value
x with the column label overrides recorded.
Examples
lt(head(mtcars)) |> lt_label(mpg = "Miles/Gallon", cyl = "Cylinders")
# raw HTML label (wrap in I())
lt(head(mtcars)) |> lt_label(mpg = I("Miles/Gallon<sup>*</sup>"))
Merge Columns
Description
Combine values from multiple columns into a single display column using a pattern. Source columns (all except the first) are hidden by default.
Usage
lt_merge(x, columns, pattern = NULL, hide = TRUE)
Arguments
x |
An |
columns |
Character vector of column names (or a one-sided formula). The first column is the target (receives merged content); the rest are sources. |
pattern |
A glue-style template using |
hide |
If |
Value
x with the merge recorded.
Examples
d = data.frame(stat = c("Mean", "SD"), value = c(4.2, 1.1), ci = c("(2.0, 6.4)", "(0.5, 1.7)"))
lt(d) |> lt_merge(~ value + ci, pattern = "{1} {2}")
Move Columns
Description
Rearrange column display order without modifying the data frame.
Usage
lt_move(x, columns, after = NULL)
Arguments
x |
An |
columns |
Character vector of column names (or a one-sided formula). |
after |
Column name after which to place the moved columns. Use
|
Value
x with the column move recorded.
Examples
lt(head(mtcars)) |> lt_move(~ gear + carb, after = "mpg")
Add a Note
Description
Notes are rendered in the table footer below numbered footnotes.
Usage
lt_note(x, text)
Arguments
x |
An |
text |
Note text. Wrap in |
Value
x with the note recorded.
Examples
lt(head(mtcars)) |> lt_note("CI = confidence interval.")
# raw HTML note (wrap in I())
lt(head(mtcars)) |> lt_note(I("CI = <em>confidence interval</em>."))
Shiny Bindings for lt
Description
lt_output() creates a UI placeholder; render_lt() supplies the table
spec from the server. Together they render an lt() table as a custom
Shiny output — no renderUI() involved.
Usage
lt_output(outputId, ...)
render_lt(expr, env = parent.frame(), quoted = FALSE)
Arguments
outputId |
Output variable name to read the table from. |
... |
Reserved for future use. |
expr |
An expression that returns an |
env |
Environment in which to evaluate |
quoted |
Whether |
Value
lt_output() returns a Shiny UI element; render_lt() returns a
render function.
Examples
if (interactive()) {
library(shiny)
ui = fluidPage(lt_output("tbl"))
server = function(input, output) {
output$tbl = render_lt(lt(head(mtcars)) |> lt_header("Motor Trend"))
}
shinyApp(ui, server)
}
Add a Column Spanner
Description
A spanner is a label rendered above a contiguous group of column headers.
Usage
lt_spanner(x, label, columns, sep = "[._]")
Arguments
x |
An |
label |
A character scalar — the spanner text. Alternatively, a
two-sided formula |
columns |
Column names (character or formula). When missing, inferred from column names. |
sep |
Separator pattern for auto-inference (default |
Details
When called with no label or columns, infers spanners from column
names by splitting on the first . or _ separator. Contiguous columns
sharing a prefix are grouped under that prefix, and column labels are
shortened to the suffix.
Value
x with the spanner recorded.
Note
The columns must be contiguous in the body of the table.
Examples
tbl = lt(head(iris))
# Explicit spanner
tbl |> lt_spanner(Sepal ~ Sepal.Length + Sepal.Width)
# Auto-infer from column names
tbl |> lt_spanner()
# raw HTML label (wrap in I())
tbl |> lt_spanner(I("<em>Sepal</em>"), ~ Sepal.Length + Sepal.Width)
Style Cells
Description
Apply CSS styling to specific cells. Target cells by column, row, or both.
When test is provided, styles are applied conditionally based on cell
values (evaluated in JavaScript).
Usage
lt_style(
x,
columns = NULL,
rows = NULL,
test = NULL,
class = NULL,
bold = NULL,
italic = NULL,
color = NULL,
bg = NULL,
...
)
Arguments
x |
An |
columns |
Character vector of column names, a one-sided formula, or
|
rows |
Integer vector of 1-based row indices (or |
test |
A JavaScript function as a string (e.g., |
class |
CSS class name(s) to add to matching cells. Define the
corresponding rules in an external stylesheet via |
bold |
Logical: apply bold weight? |
italic |
Logical: apply italic style? |
color |
Text color (any CSS color value, e.g., |
bg |
Background color. |
... |
Additional CSS properties as named arguments. Names can be
camelCase (e.g., |
Value
x with the style recorded.
Examples
tbl = lt(head(mtcars))
tbl |>
lt_style("mpg", rows = 1L, bold = TRUE, borderBottom = "2px solid red")
tbl |>
lt_style("mpg", test = "v => v > 20", class = "high") |>
lt_css(.high = list(background = "#cfc"))
Substitute Cell Values
Description
Replace NA, zero, or small values with display text.
Usage
lt_sub(
x,
columns = NULL,
missing = NULL,
zero = NULL,
small = NULL,
small_text = NULL
)
Arguments
x |
An |
columns |
Character vector of column names, a one-sided formula, or
|
missing |
Replacement for |
zero |
Replacement for zero values (e.g., |
small |
Threshold: values whose absolute value is below this are
replaced by |
small_text |
Text shown for values below |
Value
x with the substitution recorded.
Examples
d = data.frame(x = c(1, 0, NA, 0.001))
lt(d) |> lt_sub(missing = "—", zero = "—", small = 0.01, small_text = "<0.01")
Set Column Widths
Description
Set Column Widths
Usage
lt_width(x, ...)
Arguments
x |
An |
... |
Named arguments of the form |
Value
x with the column widths recorded.
Examples
lt(head(mtcars)) |> lt_width(mpg = "100px", cyl = "50px")
Print an lt_tbl (Opens in the Viewer or Browser)
Description
Print an lt_tbl (Opens in the Viewer or Browser)
Usage
## S3 method for class 'lt_tbl'
print(x, ...)
Arguments
x |
An |
... |
Passed to |
Value
x, invisibly.
Examples
print(lt(head(mtcars)))