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 step in pkgdown workflow to ensure that all figures in Rmd documents have an alt text #129

Closed
Bisaloo opened this issue Feb 20, 2024 · 6 comments

Comments

@Bisaloo
Copy link
Member

Bisaloo commented Feb 20, 2024

No description provided.

@bahadzie
Copy link
Member

In my comment on #101, this was one of the things I included in the spring_clean() function.

  # - [X] Verify all images include helpful alt-text
  rmd_files <- list.files(pattern = "Rmd", recursive = TRUE)
  with_plot <- files_with(rmd_files, "plot\\(") # covers ggplot as well
  with_fig_alt <- files_with(rmd_files, "fig\\.alt")
  result <- rmd_files[xor(with_fig_alt, with_plot)]
  if (length(result) > 0) {
    say("❌ No alt-text in the following files")
    say(result)
    say("[Example: ```{r, fig.alt = 'Alt text here'}]")
  } else {
    say("🟢 All images include helpful alt-text")
  }

Happy to look into integrating it in the pkgdown workflow if you want.

@Bisaloo
Copy link
Member Author

Bisaloo commented Feb 28, 2024

Thanks! I agree the spring_clean() is better split across different workflows rather than a giant "magic" function.

In this specific case, the proposed code would not detect files that contain some figures without all text.

The R solution would be to use the xml2 package. Here is a code sample that should be used to loop over all the HTML files in the gh-pages branch:

xml2::read_html("https://github.com/epiverse-trace/ColOpenData/raw/gh-pages/articles/demographic_data.html") |> 
  xml2::xml_find_all("//img[not(@alt)]")
#> {xml_nodeset (2)}
#> [1] <img src="demographic_data_files/figure-html/data%20filtering%20and%20plo ...
#> [2] <img src="demographic_data_files/figure-html/other%20data%20plot-1.png" w ...

Created on 2024-02-28 with reprex v2.0.2

@Bisaloo
Copy link
Member Author

Bisaloo commented Feb 28, 2024

pages_without_alt <- list.files(pattern = ".html$", full.names = TRUE, recursive = TRUE) |> 
  lapply(function(page) {
    figs_without_alt <- xml2::read_html(page) |> 
      xml2::xml_find_all("//img[not(@alt)]")
    return(list(page = basename(page), missing_alts = length(figs_without_alt)))
  }) |> 
  do.call(rbind.data.frame, args = _)

stop(sum(pages_without_alt$missing_alts > 0), " pages include figures without alt text.")

@Bisaloo
Copy link
Member Author

Bisaloo commented Feb 28, 2024

The only part that is a bit disappointing is that it'd be super difficult to point out exactly where in the file the issue is since it'd require us to keep a correspondence table between lines in the HTML and corresponding Rmd document.

@bahadzie
Copy link
Member

bahadzie commented Mar 5, 2024

According to {knitr} if fig.cap is provided it will be used for fig.alt

knitr Chunk options and package options

  • fig.alt: (NULL; character) The alternative text to be used in the alt attribute of the tags of figures in HTML output. By default, the chunk option fig.cap will be used as the alternative text if provided.

In ggplot2/README.Rmd they specify fig.alt in comments, not the options

ggplot2 README.Rmd chunck options and code
{r example}

#| fig.alt = "Scatterplot of engine displacement versus highway miles per
#|  gallon, for 234 cars coloured by 7 'types' of car. The displacement and miles
#|  per gallon are inversely correlated."
library(ggplot2)

ggplot(mpg, aes(displ, hwy, colour = class)) + 
 geom_point()

One option is to standardize on fig.cap because it will produce the desired result and it's probably the one most people use. e.g. {epidemics}

epidemics vignettes/diphtheria.Rmd chunck options

{r class.source = 'fold-hide', fig.cap="Model results from a single run showing the number of individuals infectious with diphtheria over 100 days of the outbreak."}

epidemics rendered vignette output with alt text coming fromfig.cap

<img src="diphtheria_files/figure-html/unnamed-chunk-3-1.png" alt="Model results from a single run showing the number of individuals infectious with diphtheria over 100 days of the outbreak.">

Here is a code snippet that uses the source files *.Rmd instead of the output *.html. When run from the package folder it will report on all files that have code chunks with ggplot that don't have fig.cap or fig.alt.

It assumes

  • ggplot is used as the standard for plotting in epiverse
  • fig.alt is provided as part of chunk options not in a comment like in the ggplot/README.Rmd above
    NB: Both assumptions can be accounted for
# install.packages("parsermd")

parse_rmd_files <- function() {
  # inner function that does all the work  
  chunk_details <- function(filename) {
    parsed <- parsermd::parse_rmd(filename)
    ast <- parsermd::rmd_select(parsed, parsermd::has_type("rmd_chunk"))
    missing_alt_text <- lapply(ast, function(chunk) {
      caption <- !is.null(chunk$options$fig.cap)
      plot <- length(grep("ggplot\\(", chunk$code)) > 0
      alt_text <- !is.null(chunk$options$fig.alt)
      sum(as.integer(c(plot, caption, alt_text))) == 1
    })

    missing_chunk_indices <- as.list(which(unlist(missing_alt_text)))

    details <- lapply(missing_chunk_indices, function(index) {
      chunk <- ast[[index]][["code"]]
      name <- ast[[index]][["name"]]
      list(file = filename, chunk_name = name, code = chunk)
    })
    details
  }
    
  # start's here
  rmd_files <- list.files(pattern = "Rmd", recursive = TRUE)
  results <- lapply(rmd_files, chunk_details)
  results[lengths(results) > 0]
}

report <- parse_rmd_files()

I modified one of the two plots in diptheria.Rmd in {epidemics} to test it and it worked. I also ran it on the rest of {epidemics} and it picked out all the chunks in all the .Rmds with plots that didn't have fig.cap or fig.alt

@Bisaloo
Copy link
Member Author

Bisaloo commented May 21, 2024

This is now addressed upstream in r-lib/pkgdown#2522.

@Bisaloo Bisaloo closed this as completed May 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants