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
Original text:
「我記得我有一個想要用 swift 腳本來做成 word 的想法,我在想是不是可以寫一個 R 的 package 可以直接從分析結果整理成 swift 的 docx 腳本?」
— Source: Claude Code session 2026-04-19
word-builder-swift 0.9.0 (#71) shipped a fluent Swift API for programmatically building .docx — a Swift-side equivalent of docx.js. R users doing statistical analysis still generate Word reports through older toolchains (officer, flextable, rmarkdown → pandoc) that have their own quirks and limited styling control.
Proposal: an R package that serialises R analysis artefacts (data frames, ggplot2 plots, model summaries, character vectors, lists) into a runnable .swift script that imports WordBuilderSwift and emits a .docx. The R function call shells out to swift run, captures the produced .docx, and returns its path to R.
Type
feature
Motivation
Unifies the "analysis in R, formatted report in Swift" pipeline. R stays the analytical engine; Swift owns layout/styling.
Keeps word-builder-swift as the single canonical .docx writer across the macdoc ecosystem — R integration becomes "just another caller," not a parallel DOCX generator.
The produced .swift file is a first-class artefact — committable, re-runnable, reviewable, diffable against last week's report. Beats "black-box PDF" reproducibility by a wide margin.
Forces a clean R ↔ Swift type mapping (data.frame → Table, ggplot → ImageRun when that lands in Phase 2, character heading → Paragraph(heading:), etc.) — exercising word-builder-swift's API surface and surfacing Phase 2/3 needs.
Expected
R user writes:
library(wordBuilder) # or whatever the package ends up nameddoc<- word_document()
doc<- add_heading(doc, "Q1 Report", level=1)
doc<- add_paragraph(doc, paste("Revenue grew", scales::percent(0.15)))
doc<- add_table(doc, mtcars[1:5, ])
doc<- add_plot(doc, ggplot(mtcars, aes(mpg, hp)) + geom_point())
render(doc, output="q1-report.docx")
# Internally:# 1. Emits q1-report.swift (calls WordBuilderSwift)# 2. Emits any plot as media/{png}# 3. `swift run --package-path <tempdir> q1-report.swift`# 4. Returns path to q1-report.docx
The intermediate q1-report.swift is retained (not deleted) so users can:
Read / edit it for fine-grained control
Check it into git alongside R analysis code
Re-run Swift-side without re-running R
Actual
No such package exists. R users wanting .docx output today use:
officer + flextable — most common, but styling API is idiosyncratic, Windows-biased, and has long-standing table-inside-body quirks
rmarkdown → pandoc — converts markdown to docx, but loses fine control over run-level formatting
Manual copy-paste from R → Word (still the most common "pipeline" in practice)
None of these produce a reviewable intermediate artefact like the Swift script approach would.
APA-style reporting becomes easier — R already has great citation/bibliography tooling (bibtex, citr); combined with bib-apa-*-swift the Swift-side emission can consume that
Reports become rerunnable single-file artefacts (the .swift) — superior reproducibility story vs. black-box .docx
Potentially drives Phase 2 priorities for word-builder-swift (headers/footers, numbering, images — all high-value for scientific reports)
Negative / risk:
Platform: Swift toolchain is required on the R user's machine. macOS native; Linux requires swift.org toolchain; Windows is painful. Scope is macOS-first, explicitly.
Dependency surface: R package pulls in nothing extra (pure R + shelling to Swift), but runtime needs swift binary on $PATH. Document prominently.
Performance: each render() call compiles the generated Swift file (~5–20s for a fresh compile, cached after). Acceptable for "run once per report" workflow; bad for "iterate 50 times" — mitigation: provide a persistent compile cache or a long-lived SPM project under ~/.wordBuilder/.
Scope (Phase 1 MVP)
R package (proposed name: wordBuilder, rswiftdocx, or docx.swift — open for bikeshed)
API mirrors word-builder-swift idioms where sensible: word_document(), add_heading(), add_paragraph(), add_text_run(), add_table()
Code generator: R state → .swift file using WordBuilderSwift
Shell-out runner: swift run the generated file, return .docx path
Type mapping Phase 1: character → heading/paragraph, data.frame → Table (no styling), list of character → mixed runs
Test suite: R-side unit tests (generated .swift matches golden files) + integration test (runs Swift, reads-back .docx via officer to assert content)
Vignette: "Your first report" translating an existing R markdown example
Windows support (revisit when Swift/Windows matures)
Open design questions (for diagnosis)
Repo location: PsychQuant/r-word-builder? Separate org? CRAN vs GitHub-only?
Package name: any opinion? Short + searchable matters more than clever.
Runner abstraction: should render() call macdoc's convert subcommand, or swift run directly on the generated file? (Former keeps macdoc as the single binary surface; latter is more direct.)
Intermediate .swift retention: default retain vs default cleanup? Users likely want both modes.
ggplot → image: wait for word-builder-swift Phase 2 ImageRun, or inline image embedding as raw OOXML in Phase 1 R-side? Probably wait — scope creep.
Relationship to existing R → docx packages: compete with officer, or position as "officer for Swift users who want reviewable intermediates"?
Testing strategy: how to assert generated .swift correctness without running Swift in every R CI (Swift toolchain install is slow)? Golden-file comparison + periodic end-to-end runs?
After the proposal is accepted, next action is creating/using the implementation repository and applying r-word-builder-mvp there or mirroring the accepted tasks into that repo.
Problem
word-builder-swift 0.9.0(#71) shipped a fluent Swift API for programmatically building.docx— a Swift-side equivalent ofdocx.js. R users doing statistical analysis still generate Word reports through older toolchains (officer,flextable,rmarkdown→pandoc) that have their own quirks and limited styling control.Proposal: an R package that serialises R analysis artefacts (data frames, ggplot2 plots, model summaries, character vectors, lists) into a runnable
.swiftscript that importsWordBuilderSwiftand emits a.docx. The R function call shells out toswift run, captures the produced.docx, and returns its path to R.Type
feature
Motivation
word-builder-swiftas the single canonical.docxwriter across the macdoc ecosystem — R integration becomes "just another caller," not a parallel DOCX generator..swiftfile is a first-class artefact — committable, re-runnable, reviewable, diffable against last week's report. Beats "black-box PDF" reproducibility by a wide margin.Expected
R user writes:
The intermediate
q1-report.swiftis retained (not deleted) so users can:Actual
No such package exists. R users wanting
.docxoutput today use:officer+flextable— most common, but styling API is idiosyncratic, Windows-biased, and has long-standing table-inside-body quirksrmarkdown→ pandoc — converts markdown to docx, but loses fine control over run-level formattingNone of these produce a reviewable intermediate artefact like the Swift script approach would.
Impact
Positive:
word-builder-swift(feat: 新增 word-builder-swift — Swift fluent API 直接寫 .docx(類 docx.js) #71) — forces the API to be good enough for scientific/statistical reporting, which often exposes gaps earlybibtex,citr); combined withbib-apa-*-swiftthe Swift-side emission can consume that.swift) — superior reproducibility story vs. black-box.docxword-builder-swift(headers/footers, numbering, images — all high-value for scientific reports)Negative / risk:
swiftbinary on$PATH. Document prominently.render()call compiles the generated Swift file (~5–20s for a fresh compile, cached after). Acceptable for "run once per report" workflow; bad for "iterate 50 times" — mitigation: provide a persistent compile cache or a long-lived SPM project under~/.wordBuilder/.Scope (Phase 1 MVP)
wordBuilder,rswiftdocx, ordocx.swift— open for bikeshed)word-builder-swiftidioms where sensible:word_document(),add_heading(),add_paragraph(),add_text_run(),add_table().swiftfile usingWordBuilderSwiftswift runthe generated file, return.docxpath.swiftmatches golden files) + integration test (runs Swift, reads-back.docxviaofficerto assert content)Scope (later phases, explicitly out)
word-builder-swiftPhase 2ImageRun)word-builder-swiftPhase 2Styles)Open design questions (for diagnosis)
PsychQuant/r-word-builder? Separate org? CRAN vs GitHub-only?render()call macdoc'sconvertsubcommand, orswift rundirectly on the generated file? (Former keeps macdoc as the single binary surface; latter is more direct.).swiftretention: default retain vs default cleanup? Users likely want both modes.word-builder-swiftPhase 2ImageRun, or inline image embedding as raw OOXML in Phase 1 R-side? Probably wait — scope creep.officer, or position as "officer for Swift users who want reviewable intermediates"?.swiftcorrectness without running Swift in every R CI (Swift toolchain install is slow)? Golden-file comparison + periodic end-to-end runs?Related
word-builder-swift 0.9.0(the Swift-side API this R package would wrap)note-to-html-swift(different "R → X" territory but same "R as caller" pattern)Current Status
Phase: diagnosed
Last updated: 2026-04-22 by idd-diagnose (batch)
Current Status
Phase: diagnosed / MVP Spectra proposal ready
Last updated: 2026-05-02 by Codex
Key Decisions
wordbuilder.word_document(),add_heading(),add_paragraph(),add_text_run(),add_table(), andrender().render()generates Swift directly, runs Swift through a persistent package cache, and retains the generated.swiftartifact by default.Spectra Proposal
r-word-builder-mvpopenspec/changes/r-word-builder-mvp/proposal.md,design.md,tasks.md, andspecs/r-word-builder-mvp/spec.mdspectra analyze r-word-builder-mvp --json,spectra validate r-word-builder-mvp, andgit diff --check -- openspec/changes/r-word-builder-mvpBlocking
r-word-builder-mvpthere or mirroring the accepted tasks into that repo.Commits