Skip to content

Commit cfbca58

Browse files
committed
feat: Introduce write_docx function to convert RTF content to DOCX format and add corresponding tests.
1 parent 5d865ed commit cfbca58

8 files changed

Lines changed: 173 additions & 3 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ r2rtf.Rcheck/
1010
r2rtf*.tar.gz
1111
r2rtf*.tgz
1212
revdep/
13+
Rplots.pdf

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@ Suggests:
5252
xml2
5353
Config/testthat/edition: 3
5454
Roxygen: list(markdown = TRUE)
55-
RoxygenNote: 7.3.2
55+
RoxygenNote: 7.3.3

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export(rtf_source)
1717
export(rtf_subline)
1818
export(rtf_title)
1919
export(utf8Tortf)
20+
export(write_docx)
2021
export(write_rtf)
2122
importFrom(grDevices,colors)
2223
importFrom(utils,tail)

R/rtf_convert_format.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
#' @param output_file A vector of filename for the output file.
2626
#' Default is the same filename for input.
2727
#' @param output_dir The output directory for the converted `output_dir`.
28-
#' @param format Converted file format extension. Currently support "pdf" or "docx"
28+
#' @param format Converted file format extension. Currently support "pdf"
29+
#' or "docx" or "html"
2930
#' @param overwrite logical; should existing destination files be overwritten?
3031
#'
3132
#' @return A vector of file paths for the converted files.

R/write_rtf.R

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,61 @@ write_rtf_para <- function(rtf, file) {
7272

7373
invisible(file)
7474
}
75+
76+
#' Write an RTF Table or Figure to a DOCX File
77+
#'
78+
#' @description
79+
#' The write_docx function writes an RTF encoding string to a .docx file
80+
#' by first writing to a temporary RTF file and then converting it to DOCX
81+
#' using LibreOffice.
82+
#'
83+
#' @section Specification:
84+
#' \if{latex}{
85+
#' \itemize{
86+
#' \item Write RTF encoding to a temporary RTF file.
87+
#' \item Convert RTF to DOCX using LibreOffice command-line tool via \code{rtf_convert_format()}.
88+
#' }
89+
#' }
90+
#' \if{html}{The contents of this section are shown in PDF user manual only.}
91+
#'
92+
#' @param rtf A character rtf encoding string rendered by `rtf_encode()`.
93+
#' @param file A character string naming a file to save docx file.
94+
#'
95+
#' @details
96+
#' This function requires LibreOffice to be installed on the system.
97+
#' The function uses the internal \code{rtf_convert_format()} function
98+
#' to perform the conversion from RTF to DOCX format.
99+
#'
100+
#' Currently only Unix/Linux/macOS systems are supported.
101+
#'
102+
#' @export
103+
write_docx <- function(rtf, file) {
104+
# Normalize the output file path
105+
file <- normalizePath(file, mustWork = FALSE)
106+
107+
# Create output directory if it doesn't exist
108+
output_dir <- dirname(file)
109+
if (!dir.exists(output_dir)) {
110+
dir.create(output_dir, recursive = TRUE)
111+
}
112+
113+
# Create a temporary RTF file
114+
tmpdir <- tempfile(pattern = "r2rtf_")
115+
dir.create(tmpdir)
116+
on.exit(unlink(tmpdir, recursive = TRUE), add = TRUE)
117+
118+
file_basename <- tools::file_path_sans_ext(basename(file))
119+
rtf_path <- file.path(tmpdir, paste0(file_basename, ".rtf"))
120+
write_rtf(rtf, rtf_path)
121+
122+
# Convert RTF to DOCX using existing rtf_convert_format function
123+
rtf_convert_format(
124+
input = rtf_path,
125+
output_file = basename(file),
126+
output_dir = output_dir,
127+
format = "docx",
128+
overwrite = TRUE
129+
)
130+
131+
invisible(file)
132+
}

man/assemble_docx.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/write_docx.Rd

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-independent-testing-write_rtf.R

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,76 @@ test_that("Write function test for dataset input", {
4040

4141
expect_equal(y, z)
4242
})
43+
44+
test_that("write_docx creates DOCX file from RTF encoding", {
45+
skip_on_os("windows") # rtf_convert_format only supports Unix/Linux/macOS
46+
skip_if_not(
47+
nzchar(Sys.which("libreoffice")) ||
48+
nzchar(Sys.which("libreoffice24.8")) ||
49+
nzchar(Sys.which("libreoffice7.6")),
50+
"LibreOffice is not installed"
51+
)
52+
53+
# Create RTF encoding
54+
rtf <- head(iris) |>
55+
rtf_body() |>
56+
rtf_encode()
57+
58+
# Write to DOCX
59+
docx_file <- file.path(tempdir(), "test_table.docx")
60+
result <- write_docx(rtf, docx_file)
61+
62+
# Verify file was created
63+
expect_true(file.exists(docx_file))
64+
expect_equal(result, docx_file)
65+
66+
# Clean up
67+
unlink(docx_file)
68+
})
69+
70+
test_that("write_docx creates output directory if needed", {
71+
skip_on_os("windows") # rtf_convert_format only supports Unix/Linux/macOS
72+
skip_if_not(
73+
nzchar(Sys.which("libreoffice")) ||
74+
nzchar(Sys.which("libreoffice24.8")) ||
75+
nzchar(Sys.which("libreoffice7.6")),
76+
"LibreOffice is not installed"
77+
)
78+
79+
# Create RTF encoding
80+
rtf <- head(cars) |>
81+
rtf_body() |>
82+
rtf_encode()
83+
84+
# Create nested path
85+
nested_path <- file.path(tempdir(), "test_output_dir", "nested", "test.docx")
86+
87+
# Write to DOCX
88+
result <- write_docx(rtf, nested_path)
89+
90+
# Verify directory and file were created
91+
expect_true(dir.exists(dirname(nested_path)))
92+
expect_true(file.exists(nested_path))
93+
94+
# Clean up
95+
unlink(file.path(tempdir(), "test_output_dir"), recursive = TRUE)
96+
})
97+
98+
test_that("write_docx fails gracefully when LibreOffice is not available", {
99+
skip_on_os("windows") # rtf_convert_format only supports Unix/Linux/macOS
100+
skip_if(
101+
nzchar(Sys.which("libreoffice")) ||
102+
nzchar(Sys.which("libreoffice24.8")) ||
103+
nzchar(Sys.which("libreoffice7.6")),
104+
"Skip if LibreOffice IS installed"
105+
)
106+
107+
rtf <- head(iris) |>
108+
rtf_body() |>
109+
rtf_encode()
110+
111+
expect_error(
112+
write_docx(rtf, file.path(tempdir(), "test.docx")),
113+
"Can't find libreoffice"
114+
)
115+
})

0 commit comments

Comments
 (0)