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

VignetteEngine{knitr::knitr} cannot open file script src prism-core.min.js #2254

Closed
tdhock opened this issue May 1, 2023 · 7 comments
Closed

Comments

@tdhock
Copy link

tdhock commented May 1, 2023

By filing an issue to this repo, I promise that

  • [ x] I have fully read the issue guide at https://yihui.org/issue/.
  • [ x] I have provided the necessary information about my issue.
    • If I'm asking a question, I have already asked it on Stack Overflow or RStudio Community, waited for at least 24 hours, and included a link to my question there.
    • If I'm filing a bug report, I have included a minimal, self-contained, and reproducible example, and have also included xfun::session_info('knitr'). I have upgraded all my packages to their latest versions (e.g., R, RStudio, and R packages), and also tried the development version: remotes::install_github('yihui/knitr').
    • If I have posted the same issue elsewhere, I have also mentioned it in this issue.
  • [ x] I have learned the Github Markdown syntax, and formatted my issue correctly.

I understand that my issue may be closed if I don't fulfill my promises.

Hi @yihui first of all thanks for this wonderful package, which I find very useful.

I have a package on CRAN that uses VignetteEngine{knitr::knitr} to build a vignette, and it recently started failing CRAN checks with the following message (on windows only). https://cloud.r-project.org/web/checks/check_results_nc.html

Check: re-building of vignette outputs
Result: ERROR
    Error(s) in re-building vignettes:
    --- re-building 'v1-capture-first.Rmd' using knitr
    Warning in file(con, "r") :
     cannot open file 'cript src="https://cdn.jsdelivr.net/npm/[email protected]/components/prism-core.min.js" defer></script>
    <cript src="https://cdn.jsdelivr.net/npm/[email protected]/components/prism-core.min.js" defer></script>
    <': No such file or directory
    Error: processing vignette 'v1-capture-first.Rmd' failed with diagnostics:
    cannot open the connection
    --- failed re-building 'v1-capture-first.Rmd'

The issue seems to happen only on windows, and only if the Rmd file has a code chunk that prints emoji.
I expected that it should be possible on windows to render an Rmd that has a code chunk that prints emoji, or at least that there should be a more informative error message, like "Rmd with code chunks that print emoji is not supported on windows, but v1-capture-first.Rmd has a code chunk that prints emoji, please remove."

Based on the error message above and the fact that it only occurs on windows, I suspect that a fix to this vignette builder on your end would entail changing some usage of file.path / backslash separator, to a forward slash.

On my end (user who is trying to build a vignette) a fix is to change VignetteEngine{knitr::knitr} to VignetteEngine{knitr::rmarkdown}.

Code to reproduce issue is below,

(vignette.Rmd <- tempfile(fileext=".Rmd"))
cat('<!--
%\\VignetteEngine{knitr::knitr}
-->\n```{r}
"a\\U0001F60E#"\n```
', file=vignette.Rmd)
tools::vignetteEngine("knitr::knitr")$weave(vignette.Rmd)
traceback()
sessionInfo()

The output I got on my system is below,

> (vignette.Rmd <- tempfile(fileext=".Rmd"))
[1] "C:\\Users\\th798\\AppData\\Local\\Temp\\Rtmpo9uKmD\\file3da45f2e511a.Rmd"
> cat('<!--
+ %\\VignetteEngine{knitr::knitr}
+ -->\n```{r}
+ "a\\U0001F60E#"\n```
+ ', file=vignette.Rmd)
> tools::vignetteEngine("knitr::knitr")$weave(vignette.Rmd)


processing file: C:\Users\th798\AppData\Local\Temp\Rtmpo9uKmD\file3da45f2e511a.Rmd
                                                                                                            
output file: file3da45f2e511a.md

Error in file(con, "r") : cannot open the connection
In addition: Warning message:
In file(con, "r") :
  cannot open file 'script src="https://cdn.jsdelivr.net/npm/[email protected]/components/prism-core.min.js" defer></script>
script src="https://cdn.jsdelivr.net/npm/[email protected]/components/prism-core.min.js" defer></script>
': Invalid argument
> traceback()
22: file(con, "r")
21: readLines(con, encoding = "UTF-8", warn = FALSE)
20: xfun::read_utf8(x)
19: base64_url(x, xfun::read_utf8(x), ext)
18: resolve_external(x, is_web, ext)
17: unique.default(c("AsIs", oldClass(x)))
16: I(c(t2[1], resolve_external(x, is_web, ext), t2[2]))
15: one_string(I(c(t2[1], resolve_external(x, is_web, ext), t2[2])))
14: (function (x, ext = "", embed_https = FALSE, embed_local = FALSE) 
    {
        if (ext == "css") {
            t1 = "<link rel=\"stylesheet\" href=\"%s\">"
            t2 = c("<style type=\"text/css\">", "</style>")
        }
        else if (ext == "js") {
            t1 = "<script src=\"%s\" defer></script>"
            t2 = c("<script>", "</script>")
        }
        else stop("The file extension '", ext, "' is not supported.")
        is_web = is_https(x)
        is_rel = !is_web && xfun::is_rel_path(x)
        if (is_web && embed_https && xfun::url_filename(x) == "MathJax.js") {
            warning("MathJax.js cannot be embedded. Please use MathJax v3 instead.")
            embed_https = FALSE
        }
        if ((is_rel && !embed_local) || (is_web && !embed_https)) {
            sprintf(t1, x)
        }
        else {
            one_string(I(c(t2[1], resolve_external(x, is_web, ext), 
                t2[2])))
        }
    })(dots[[1L]][[1L]], dots[[2L]][[1L]], dots[[3L]][[1L]], dots[[4L]][[1L]])
13: mapply(gen_tag, ...)
12: gen_tags(z3[i1], ifelse(js[i1], "js", "css"), embed[1], embed[2])
11: replace(z)
10: FUN(X[[i]], ...)
9: lapply(regmatches(x, m), function(z) {
       if (length(z)) 
           replace(z)
       else z
   })
8: match_replace(x, r, function(z) {
       z1 = sub(r, "\\1", z)
       z2 = sub(r, "\\2", z)
       js = z2 != ""
       z3 = paste0(z1, z2)
       i1 = !grepl("^data:.+;base64,.+", z3)
       z3[i1] = gen_tags(z3[i1], ifelse(js[i1], "js", "css"), embed[1], 
           embed[2])
       i2 = grepl(" (defer|async)(>| )", z) & js
       x2 <<- c(x2, z3[i2])
       z3[i2] = ""
       z3
   })
7: embed_resources(ret, options[["embed_resources"]])
6: xfun::in_dir(if (is_file(file, TRUE)) dirname(file) else ".", 
       embed_resources(ret, options[["embed_resources"]]))
5: mark(..., format = "html", template = template)
4: markdown::mark_html(...)
3: mark_html(out, output, ...)
2: (if (grepl("\\.[Rr]md$", file)) knit2html else if (grepl("\\.[Rr]rst$", 
       file)) knit2pandoc else knit)(file, encoding = encoding, 
       quiet = quiet, envir = globalenv(), ...)
1: tools::vignetteEngine("knitr::knitr")$weave(vignette.Rmd)
> sessionInfo()
R version 4.3.0 (2023-04-21 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19045)

Matrix products: default


locale:
[1] LC_COLLATE=English_United States.utf8 
[2] LC_CTYPE=English_United States.utf8   
[3] LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C                          
[5] LC_TIME=English_United States.utf8    

time zone: America/Phoenix
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] compiler_4.3.0   markdown_1.6     tools_4.3.0      knitr_1.42      
[5] xfun_0.39        commonmark_1.9.0 evaluate_0.20   
> 

Thanks again and hope this helps.
Toby

@yihui
Copy link
Owner

yihui commented May 1, 2023

This could be a bug in base R. Here is a minimal reproducible example:

x = '\U0001F60E abc'
m = gregexpr('a', x)
regmatches(x, m)

It should return 'a', but returns 'b' instead; m should start from 3 instead of 4. I can work around it by using perl = TRUE in gregexpr(). I'm not sure if it's worth reporting this problem to the R core team.

@yihui yihui moved this to Todo In Progress in R Markdown Team Projects May 1, 2023
@github-project-automation github-project-automation bot moved this from Todo In Progress to Done in R Markdown Team Projects May 2, 2023
@yihui
Copy link
Owner

yihui commented May 2, 2023

Should be fixed in the markdown package now:

if (packageVersion('markdown') < '1.6.3')
  install.packages('markdown', repos = c('https://rstudio.r-universe.dev', 'https://cloud.r-project.org'))

@tdhock
Copy link
Author

tdhock commented May 2, 2023

thanks!

@cderv
Copy link
Collaborator

cderv commented May 2, 2023

My understanding with Emoji character and more generally multibyte character is that useBytes = TRUE should be used.

x = '\U0001F60E abc'
m = gregexpr('a', x, useBytes = TRUE)
regmatches(x, m)
#> [[1]]
#> [1] "a"

Not sure it is a bug.

Anyway, using perl =TRUE is probably an ok change around that.

@yihui
Copy link
Owner

yihui commented May 2, 2023

Thanks! My understanding is that an emoji character is not necessarily one character, which makes it tricky to deal with. I've had some pain with this some time ago in JavaScript.

It seems that R core tends to discourage using useBytes = TRUE, so I often try to avoid it:

@cderv
Copy link
Collaborator

cderv commented May 2, 2023

It seems that R core tends to discourage using useBytes = TRUE, so I often try to avoid it:

Oh good to know ! thank you for the blog post

clrpackages pushed a commit to clearlinux-pkgs/R-markdown that referenced this issue May 16, 2023
Yihui Xie (11):
      start the next version
      change license to MIT
      rewrite readme
      typo
      the <link> tag doesn't need to be closed
      typo: slides.css -> snap.css
      close #100: don't check the file extension of the `file` argument of mark(); simply treat it as file if the file exists and the value is not from I()
      convert roxygen docs to markdown
      fix yihui/knitr#2254: use PCRE in embed_resources() in case there are emojis in text
      perl = TRUE is the default in match_replace() now
      CRAN release v1.7
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this issue Jun 3, 2023
# CHANGES IN markdown VERSION 1.7

- The `file` argument of `mark()` will be treated as a file path only
  if the file exists and the value is not wrapped in
  `I()`. Previously, it would be treated as a file path when it has a
  file extension, which could lead to confusing errors like #100
  (thanks, @LukasWallrich).

- When there are emojis in the text, `mark()` may fail to identify and
  embed web resources (thanks, @tdhock, yihui/knitr#2254).

# CHANGES IN markdown VERSION 1.6

- Added support for footnotes, fenced `Div`s, section numbers, `{}`
  attributes for images/headings/fenced `Div`s, and appendices. See
  `vignette('intro', package = 'markdown')` for details.

- A lot of enhancements to the HTML slides format. See
  `vignette('slides', package = 'markdown')` for details.

- Added `vignette('article', package = 'markdown')` to demonstrate how
  to write an HTML article.

- If the input to `mark()` is a file, the output will also be a file
  by default. Previously the output would be text. If you want
  `mark()` to return text output when the input is a file, you may
  specify the argument `output = NULL`.

- The Markdown option `base64_images` has been renamed to
  `embed_resources`. This option can take two possible values,
  `"local"` and `"https"`, meaning whether to embed local and/or web
  (https) resources. You can specify none, either, or both of
  them. See `vignette('intro', package = 'markdown')` for details.

- Removed the option `standalone` from the list of Markdown
  options. Please use the argument `template = TRUE/FALSE` of `mark()`
  instead. The option `standalone = TRUE` was equivalent to `template
  = TRUE`.

- Added the option `auto_identifiers` (enabled by default) to
  automatically add IDs to headings, e.g., `# Hello world!` will be
  converted to `<h1 id="hello-world">Hello world!</h1>`. You can
  certainly override the automatic ID by providing an ID manually via
  the `{#id}` attribute, e.g., `# Hello world! {#hello}`.

- Renamed the `mathjax` option to `js_math` to allow for other JS math
  libraries. The default library was changed from MathJax to KaTeX. To
  continue using MathJax, you may set `js_math: mathjax`.

- Removed the option `mathjax_embed` from the list of Markdown
  options. To embed the MathJax library, enable `"https"` in the
  `embed_resources` option instead. Note that only MathJax v3 can be
  partially embedded, and lower versions cannot.

- Renamed the option `highlight_code` to `js_highlight`, and added
  support for an alternative syntax highlighting JS library Prism.js,
  which became the default. To continue using the old default
  `highlight.js`, you may set the `js_highlight` option to
  `highlight`.

- The default version of MathJax has been changed from v2 to v3.

- The default version of highlight.js has been changed from 11.6.0 to
  11.7.0, and the default style has been switched from `github` to
  `xcode`.
Copy link

github-actions bot commented Nov 1, 2023

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue by following the issue guide (https://yihui.org/issue/), and link to this old issue if necessary.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 1, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants