Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add R package docs to quarto page #3

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
7 changes: 3 additions & 4 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,21 @@ jobs:

- name: Install R
uses: r-lib/actions/setup-r@v2
- name: Install R dependencies
- name: Install R package and dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
working-directory: ./r-package
extra-packages:
local::.
any::knitr
any::rmarkdown
any::reticulate
install-quarto: false
- run: /usr/local/bin/R CMD INSTALL .
working-directory: ./r-package

- name: Render and Publish
uses: quarto-dev/quarto-actions/publish@v2
with:
target: gh-pages
path: quarto
path: docs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
File renamed without changes.
16 changes: 16 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
docs: docs-python docs-r docs-render

docs-python:
quartodoc build

docs-r:
./build-r-package-docs.R
cp reference/python/index.qmd reference/r/index.qmd
@sed -i '' 's/Python Package/R Package/g' reference/r/index.qmd
@sed -i '' 's/#shinymedia[.][^)]+//g' reference/r/index.qmd

docs-render:
quarto render

docs-preview: docs-python docs-r
quarto preview
20 changes: 17 additions & 3 deletions quarto/_quarto.yml → docs/_quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ project:
resources:
- "lib/"
- "mp3/"
- "r/"

metadata-files:
- _sidebar.yml
- _sidebar-python.yml
- _sidebar-r.yml

filters:
- interlinks
Expand All @@ -18,12 +20,22 @@ website:
left:
- text: "Home"
href: index.qmd
- reference/index.qmd
- text: "Reference"
menu:
- text: "Python"
href: reference/python/index.qmd
- text: "R"
href: reference/r/index.qmd

right:
- icon: github
href: https://github.com/posit-dev/shinymedia
aria-label: GitHub repository

format:
html:
theme: [default, styles.scss]

interlinks:
fast: true
sources:
Expand All @@ -33,8 +45,10 @@ interlinks:

quartodoc:
package: shinymedia
dir: reference/python
render_interlinks: true
sidebar: _sidebar.yml
sidebar: _sidebar-python.yml
title: "Python Package Reference"
sections:
- title: Media components
desc: Components to be used with Shiny for media capture/playback.
Expand Down
10 changes: 10 additions & 0 deletions docs/_sidebar-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
website:
sidebar:
- contents:
- reference/python/index.qmd
- contents:
- reference/python/input_video_clip.qmd
- reference/python/audio_spinner.qmd
section: Media components
id: reference/python
- id: dummy-sidebar
10 changes: 10 additions & 0 deletions docs/_sidebar-r.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
website:
sidebar:
- contents:
- reference/r/index.qmd
- contents:
- reference/r/input_video_clip.qmd
- reference/r/audio_spinner.qmd
section: Media components
id: r
- id: dummy-sidebar
161 changes: 161 additions & 0 deletions docs/build-r-package-docs.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#!/usr/bin/env Rscript

stopifnot(
"Requires R 4.4.1+" = getRversion() >= package_version("4.4.0"),
"Requires the {pandoc} package" = requireNamespace("pandoc", quietly = TRUE),
"Requires the {rvest} package" = requireNamespace("rvest", quietly = TRUE),
"Requires the {xml2} package" = requireNamespace("xml2", quietly = TRUE),
"Requires the {yaml} package" = requireNamespace("yaml", quietly = TRUE)
)

# Use new pkg2HTML() from R 4.4.1 to create a single-page reference doc
con <- textConnection("r_package_docs", open = "w")
tools::pkg2HTML(
"shinymedia",
"../r-package",
out = con,
toc_entry = "name",
include_description = FALSE,
prism = FALSE,
stylesheet = ""
)
close(con)

collapse <- function(x) paste(x, collapse = "\n")

# Move into XML so we can manipulate the singe-page docs. We're going to do a
# bit of cleanup to fixup the HTML, then go through several rounds of pandoc
# conversion to extract each function section individually.
html <- rvest::read_html(paste(r_package_docs, collapse = "\n"))

# Remove empty <span id="topic-{function-name}"> elements
html |>
rvest::html_nodes("span[id^='topic']") |>
xml2::xml_remove()

# Arguments in the argument tables have anchors, but they're include a mis-coded
# `":"`. Also pandoc does weird things with <code id="foo">bar</code> so we
# rewrite these as <span id="foo"><code>bar</code></span>.
arg_blocks <-
html |>
rvest::html_nodes("code[id]") |>
xml2::xml_set_name("span")

for (arg in arg_blocks) {
arg_id <-
arg |>
rvest::html_attr("id") |>
sub("_+3A_", "_", x = _, fixed = TRUE) |>
sub("...", "dotdotdot", x = _, fixed = TRUE)

xml2::xml_set_attr(arg, "id", arg_id)
arg_text <- arg |> rvest::html_text()
xml2::xml_set_text(arg, "")
xml2::xml_add_child(arg, xml2::read_xml(sprintf("<code>%s</code>", arg_text)))
}

# First round of HTML -> commonmark -> HTML to clean up the structure and to
# take advantage of pandoc's section divs feature. This wraps sections created
# by <h2> elements in a <section class="level2"> and we'll use this to easily
# split up the single-page doc into multiple pages.
html_text <-
html |>
rvest::html_node("body") |>
rvest::html_children() |>
as.character()

html_pandoc <-
pandoc::pandoc_convert(
text = html_text,
from = "html",
to = "commonmark_x"
) |>
pandoc::pandoc_convert(
text = _,
from = "commonmark_x",
to = "html5",
args = c("--section-divs")
)

# Now we can separate the single-page doc into one page per function/topic.
html_sections <-
html_pandoc |>
collapse() |>
rvest::read_html() |>
rvest::html_nodes("section.level2:not(#contents)")

for (section in html_sections) {
# Extract the section ID and title from the <section> and <h2> element, then
# discard them.
section_id <- section |> rvest::html_attr("id")
section_title <- section |> rvest::html_node("h2") |> rvest::html_text()

section |> rvest::html_node("h2") |> xml2::xml_remove()
section |> rvest::html_nodes("hr") |> xml2::xml_remove()

for (node in rvest::html_nodes(section, "div.sourceCode")) {
# replace "div.sourceCode#cbN" blocks with their children
after <- node
for (child_node in xml2::xml_children(node)) {
xml2::xml_add_sibling(after, child_node)
after <- child_node
}
xml2::xml_remove(node)
}

for (node in rvest::html_nodes(section, ".sourceCode")) {
# Clean up .sourceCode elements for nicer markdown
xml2::xml_set_attr(
node,
"class",
sub("sourceCode", "", xml2::xml_attr(node, "class"))
)
}

# We used <h2> to define the page-level heading, so move all others up one,
# i.e. <h3> --> <h2>, etc.
heading_levels <- c("h2", "h3", "h4", "h5", "h6")
for (i in seq_along(heading_levels)[-1]) {
h_up <- heading_levels[i]
h_down <- heading_levels[i - 1]
heading_nodes <- rvest::html_nodes(section, h_up)
for (node in heading_nodes) {
xml2::xml_set_name(node, h_down)
}
}

# Now we'll get rid of the <section> containers since they've served their
# purpose and would otherwise clutter the markup with unnecessary divs.
contents <- xml2::xml_new_document()
for (node in rvest::html_nodes(section, "section")) {
for (child_node in rvest::html_children(node)) {
xml2::xml_add_child(contents, child_node)
}
}

# Final conversion to markdown (commonmark_x == commonmark with extensions)
section_pandoc <-
pandoc::pandoc_convert(
text = as.character(contents),
from = "html",
to = "commonmark_x"
)

if (!dir.exists("reference/r")) {
dir.create("reference/r", FALSE, recursive = TRUE)
}

writeLines(
c(
"---",
yaml::as.yaml(list(
title = sprintf("`%s`", section_id),
subtitle = section_title
)),
"---",
"",
section_pandoc
),
paste0("reference/r/", section_id, ".qmd")
)
}
10 changes: 5 additions & 5 deletions quarto/index.qmd → docs/index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ input_video_clip(
library(shinymedia)

input_video_clip(
"clip1",
video_bits_per_second=256000,
audio_bits_per_second=64000,
style="width: 400px; max-width: 100%;",
"clip1",
video_bits_per_second = 256000,
audio_bits_per_second = 64000,
style = "width: 400px; max-width: 100%;",
)
```

Expand Down Expand Up @@ -121,7 +121,7 @@ audio_spinner(

:::

There are many options for customizing the appearance and behavior of the spinner. Here is an example with a dark background, faster rotation, more blades, and a thinner stroke. See the [reference docs](reference/audio_spinner.qmd) for more information on these and other options.
There are many options for customizing the appearance and behavior of the spinner. Here is an example with a dark background, faster rotation, more blades, and a thinner stroke. See the reference docs for [Python](reference/python/audio_spinner.qmd) or [R](reference/r/audio_spinner.qmd) for more information on these and other options.

::: {.panel-tabset group="lang"}

Expand Down
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions docs/objects.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"project": "shinymedia", "version": "0.0.9999", "count": 4, "items": [{"name": "shinymedia.input_video_clip", "domain": "py", "role": "function", "priority": "1", "uri": "reference/python/input_video_clip.html#shinymedia.input_video_clip", "dispname": "-"}, {"name": "shinymedia.ui.input_video_clip", "domain": "py", "role": "function", "priority": "1", "uri": "reference/python/input_video_clip.html#shinymedia.input_video_clip", "dispname": "shinymedia.input_video_clip"}, {"name": "shinymedia.audio_spinner", "domain": "py", "role": "function", "priority": "1", "uri": "reference/python/audio_spinner.html#shinymedia.audio_spinner", "dispname": "-"}, {"name": "shinymedia.ui.audio_spinner", "domain": "py", "role": "function", "priority": "1", "uri": "reference/python/audio_spinner.html#shinymedia.audio_spinner", "dispname": "shinymedia.audio_spinner"}]}
8 changes: 8 additions & 0 deletions docs/objects.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Sphinx inventory version 2
# Project: shinymedia
# Version: 0.0.9999
# The remainder of this file is compressed using zlib.
shinymedia.input_video_clip py:function 1 reference/python/input_video_clip.html#shinymedia.input_video_clip -
shinymedia.ui.input_video_clip py:function 1 reference/python/input_video_clip.html#shinymedia.input_video_clip shinymedia.input_video_clip
shinymedia.audio_spinner py:function 1 reference/python/audio_spinner.html#shinymedia.audio_spinner -
shinymedia.ui.audio_spinner py:function 1 reference/python/audio_spinner.html#shinymedia.audio_spinner shinymedia.audio_spinner
24 changes: 24 additions & 0 deletions docs/reference/index.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Function Reference
---

```{=html}
<div class="container">
<div class="row d-grid" style="grid-template-columns: repeat(auto-fill, minmax(325px, 1fr)); gap: 1em;">
<!-- card -->
<div class="card card-as-link">
<img src="python-logo.svg" class="card-img-top card-img-logo" alt="">
<div class="card-body d-flex align-items-end">
<div class="card-title mt-0 mb-3 h3"><a href="python/index.html" class="card-primary-link card-header-link text-decoration-none">Python Reference</a></div>
</div>
</div>
<!-- card -->
<div class="card card-as-link">
<img src="r-logo.svg" class="card-img-top card-img-logo" alt="">
<div class="card-body d-flex align-items-end">
<div class="card-title mt-0 mb-3 h3"><a href="r/index.html" class="card-primary-link card-header-link text-decoration-none">R Reference</a></div>
</div>
</div>
</div>
</div>
```
Loading
Loading