Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: tinyrox
Title: Minimal R Documentation Generator
Version: 0.3.3.2
Version: 0.3.3.3
Authors@R:
person("Troy", "Hernandez", email = "troy@cornball.ai", role = c("aut", "cre"),
comment = c(ORCID = "0009-0005-4248-604X"))
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# tinyrox 0.3.3.3

* Render `@section` blocks in the Rd for ordinary functions and `@rdname` groups. They were parsed but only emitted for package-level docs, so a function's `@section` was silently dropped (#10).

# tinyrox 0.3.3.2

* Fix false "undocumented parameters" warning for functions documented via a sibling block in an `@rdname` group; the check is now group-wide. Also gate the warning on `cran_check` rather than `silent` (#12).
Expand Down
37 changes: 30 additions & 7 deletions R/rd.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
#' Render User-Defined @section Blocks to Rd
#'
#' Emits one `\\section{title}{content}` per parsed `@section`. Content is
#' passed through verbatim as Rd (tinyrox does no markdown parsing), matching
#' how the title-only macros elsewhere treat hand-written Rd markup.
#'
#' @param sections List of `list(title=, content=)` from parse_tags().
#' @return Character vector of Rd lines (empty when there are no sections).
#' @keywords internal
render_sections <- function(sections) {
lines <- character()
for (sec in sections) {
lines <- c(lines, paste0("\\section{", escape_rd(sec$title), "}{"))
lines <- c(lines, sec$content)
lines <- c(lines, "}")
}
lines
}

#' Generate Rd File Content
#'
#' @param tags Parsed tags from parse_tags().
Expand Down Expand Up @@ -97,6 +116,9 @@ generate_rd <- function(tags, formals = NULL, source_file = NULL,
lines <- c(lines, "}")
}

# User-defined @section blocks (after details, like roxygen2)
lines <- c(lines, render_sections(tags$sections))

# References
if (!is.null(tags$references)) {
lines <- c(lines, "\\references{")
Expand Down Expand Up @@ -625,6 +647,13 @@ generate_rd_grouped <- function(topic, entries, all_tags,
lines <- c(lines, "}")
}

# User-defined @section blocks - concatenated from all blocks
all_sections <- list()
for (entry in entries) {
all_sections <- c(all_sections, entry$tags$sections)
}
lines <- c(lines, render_sections(all_sections))

# \references{} - from primary
if (!is.null(primary$tags$references)) {
lines <- c(lines, "\\references{")
Expand Down Expand Up @@ -881,13 +910,7 @@ generate_package_rd <- function(tags, pkg_name, source_file) {
}

# User-defined sections (@section Title: ...)
if (!is.null(tags$sections)) {
for (sec in tags$sections) {
lines <- c(lines, paste0("\\section{", escape_rd(sec$title), "}{"))
lines <- c(lines, sec$content) # Content may have Rd markup, don't escape
lines <- c(lines, "}")
}
}
lines <- c(lines, render_sections(tags$sections))

# Auto-generated function index
lines <- c(lines, paste0("\\section{Package Content}{\\packageIndices{",
Expand Down
44 changes: 44 additions & 0 deletions inst/tinytest/test_rd.R
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,50 @@ rd_alias <- tinyrox:::generate_rd(tags_alias, list(names = c("x", "y"), usage =
expect_true(grepl("\\\\alias\\{plus\\}", rd_alias))
expect_true(grepl("\\\\alias\\{sum2\\}", rd_alias))

# Test @section blocks are rendered (#10) - parse -> generate, the real path
sec_block <- c(
"Example function",
"",
"Main description.",
"",
"@section Permissions:",
"This text should appear in generated Rd.",
"@export"
)
sec_tags <- tinyrox:::parse_tags(sec_block, "f")
expect_equal(length(sec_tags$sections), 1L)
rd_sec <- tinyrox:::generate_rd(sec_tags, list(names = character(), usage = ""))
expect_true(grepl("\\\\section\\{Permissions\\}\\{", rd_sec))
expect_true(grepl("This text should appear in generated Rd", rd_sec))

# Multi-word section title
sec_block2 <- c(
"Title", "", "Desc.",
"@section Special Permissions:",
"Body text.",
"@export"
)
sec_tags2 <- tinyrox:::parse_tags(sec_block2, "g")
rd_sec2 <- tinyrox:::generate_rd(sec_tags2, list(names = character(), usage = ""))
expect_true(grepl("\\\\section\\{Special Permissions\\}\\{", rd_sec2))

# Multiple @section blocks on one function, in order
sec_block3 <- c(
"Title", "", "Desc.",
"@section First:", "One.",
"@section Second:", "Two.",
"@export"
)
sec_tags3 <- tinyrox:::parse_tags(sec_block3, "h")
expect_equal(length(sec_tags3$sections), 2L)
rd_sec3 <- tinyrox:::generate_rd(sec_tags3, list(names = character(), usage = ""))
expect_true(grepl("\\\\section\\{First\\}\\{", rd_sec3))
expect_true(grepl("\\\\section\\{Second\\}\\{", rd_sec3))
expect_true(regexpr("First", rd_sec3) < regexpr("Second", rd_sec3))

# No @section -> no \section{} block leaks in
expect_false(grepl("\\\\section\\{", rd))

# Test with keywords
tags_kw <- tags
tags_kw$keywords <- c("internal", "math")
Expand Down
32 changes: 32 additions & 0 deletions inst/tinytest/test_rdname.R
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,38 @@ expect_true(grepl("func_a\\(1\\)", rd_c))
expect_true(grepl("func_b\\(2\\)", rd_c))


# --- Test: @section blocks from all members of an @rdname group (#10) ---

blocks_sec <- list(
list(
lines = c("Topic", "", "Desc.", "@section Alpha:", "Alpha body.",
"@rdname secgroup", "@export"),
object = "sec_a",
type = "function",
formals = list(names = "x", usage = "x"),
file = "test.R",
line = 1
),
list(
lines = c("@section Beta:", "Beta body.", "@rdname secgroup", "@export"),
object = "sec_b",
type = "function",
formals = list(names = "y", usage = "y"),
file = "test.R",
line = 10
)
)
tags_sa <- tinyrox:::parse_tags(blocks_sec[[1]]$lines, "sec_a")
tags_sb <- tinyrox:::parse_tags(blocks_sec[[2]]$lines, "sec_b")
entries_s <- list(
list(tags = tags_sa, block = blocks_sec[[1]]),
list(tags = tags_sb, block = blocks_sec[[2]])
)
rd_s <- tinyrox:::generate_rd_grouped("secgroup", entries_s, list())
expect_true(grepl("\\\\section\\{Alpha\\}\\{", rd_s))
expect_true(grepl("\\\\section\\{Beta\\}\\{", rd_s))


# --- Test 7: @rdname params documented on a sibling block (issue #12) ---
# A function whose formals are documented on the primary block (not its own)
# must NOT be flagged as having undocumented parameters: blocks sharing an
Expand Down
19 changes: 19 additions & 0 deletions man/render_sections.Rd
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
% tinyrox says don't edit this manually, but it can't stop you!
\name{render_sections}
\alias{render_sections}
\title{Render User-Defined @section Blocks to Rd}
\usage{
render_sections(sections)
}
\arguments{
\item{sections}{List of `list(title=, content=)` from parse_tags().}
}
\value{
Character vector of Rd lines (empty when there are no sections).
}
\description{
Emits one `\\section{title}{content}` per parsed `@section`. Content is
passed through verbatim as Rd (tinyrox does no markdown parsing), matching
how the title-only macros elsewhere treat hand-written Rd markup.
}
\keyword{internal}