Sometimes it is even hard for myself to believe how long it would take for me to implement a simple feature. Last year, when I saw Steven Fazzio’s blogdown feature request on GitHub (to embed the Rmd source file in the HTML output so readers can download it), I had an idea how to implement it. I knew it wouldn’t be hard.
Actually two years ago, Noam Ross sent a pull request to the rmarkdown repo, which was related to Steven’s request. I felt the implementation could be easier.
xfun::embed_file()
While deciding the issues/features for the next release of rmarkdown, I revisited the rmarkdown PR and the blogdown issue. At one late night, I finally typed out the two lines of code to implement it in the xfun package, so now you can embed an arbitrary file, or multiple files, or a whole directory, in the HTML output of an R Markdown document. For now you need the development version of xfun:
remotes::install_github('yihui/xfun')
# embed_file() requires a few more packages
xfun::pkg_load2(c('htmltools', 'mime'))
Basically, you can use one of the functions xfun::embed_file(), xfun::embed_dir(), or xfun::embed_files() in an R code chunk to embed one or multiple files or an entire directory in the HTML output, e.g.,
```{r echo=FALSE}
# a single file
xfun::embed_file('source.Rmd')
# multiple files
xfun::embed_files(c('source.Rmd', 'data.csv'))
# a directory
xfun::embed_dir('data/', text = 'Download full data')
```
You can also provide the list of files programmatically, e.g.,
# embed all Rmd and csv files
xfun::embed_files(list.files('.', '[.](Rmd|csv)$'))
For multiple files, they are first compressed to a zip file, and the zip file will be embedded. These functions return a link, which a reader can click on the HTML page to download the embedded file.
The trick <a href="base64 data" download="filename">
Under the hood, xfun::embed_file() simply generates a link of the form <a href="base64 data" download="filename">text</a>, where "base64 data" is the file encoded as a base64 string. If you are using a modern web browser (you are fine if it is not IE), it should be able to decode the base64 string into the file and download it when you click the link.
When to use these functions?
If your project is public, for example, on GitHub, there is no need to embed files in the HTML output: just give other people the address of the repo. If you are using blogdown, it is also possible to automatically generate a link on each page pointing to the corresponding source file on GitHub (e.g., on my website, you can click the link “Edit this page” to edit the source files of most pages).
If you project is completely private, you may compress the whole directory as a zip file and send it via email. That is common and fine, but you may not want to manually compress the directory every time you update any files in it. These embed_*() functions can automatically read and embed files in your HTML output, so all you need to do is knit the Rmd source document again, and you will only need to email an HTML file.
If the source project is private, but the output is expected to be public, that is when you may also consider embedding certain files on the output page, e.g., your Rmd source file, and/or data files. Readers who are interested in reproducing your results or analyzing the data differently can download the necessary files. This way, you only need to publish a single HTML file.
Donate
As a freelancer (currently working as a contractor) and a dad of three kids, I truly appreciate your donation to support my writing and open-source software development! Your contribution helps me cope with financial uncertainty better, so I can spend more time on producing high-quality content and software. You can make a donation through methods below.
-
Venmo:
@yihui_xie, or Zelle:xie@yihui.name -
Paypal
-
If you have a Paypal account, you can follow the link https://paypal.me/YihuiXie or find me on Paypal via my email
xie@yihui.name. Please choose the payment type as “Family and Friends” (instead of “Goods and Services”) to avoid extra fees. -
If you don’t have Paypal, you may donate through this link via your debit or credit card. Paypal will charge a fee on my side.
-
-
Other ways:
WeChat Pay (微信支付:谢益辉) Alipay (支付宝:谢益辉) 

When sending money, please be sure to add a note “gift” or “donation” if possible, so it won’t be treated as my taxable income but a genuine gift. Needless to say, donation is completely voluntary and I appreciate any amount you can give.
Please feel free to email me if you prefer a different way to give. Thank you very much!
I’ll give back a significant portion of the donations to the open-source community and charities. For the record, I received about $30,000 in total (before tax) in 2024-25, and gave back about $15,000 (after tax).