r
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
3.2KB

  1. # Heavily borrowed from https://github.com/ropenscilabs/trackmd
  2. # Might end up in worded/officedown? Best place to use seems to
  3. # be the knitr document hook
  4. #' Process Critic Markup syntax for processing by pandoc
  5. #'
  6. #' Converts critic markup syntax in markdown to syntax appropriate for
  7. #' processing by pandoc. If converted to to `docx` format, will display
  8. #' as MS Word tracked changes.
  9. #'
  10. #' A good place to put this function is in the `document` knitr hook of an
  11. #' [R Markdown output format][rmarkdown::output_format()].
  12. #'
  13. #' @param md markdown input with critic markup, a length-1 character vector
  14. #' @param author Name to attribute Critic Markup changes to. If NULL,
  15. #' defaults to system user information via [whoami::fullname()].
  16. #' @return A character vector of markdown, split by lines
  17. #' @noRd
  18. #' @importFrom whoami fullname username
  19. #' @importFrom stringi stri_replace_all_regex stri_replace_first_fixed stri_join
  20. #' stri_extract_all_regex
  21. criticmarkup_to_pandoc <- function(md, author = NULL) {
  22. if (is.null(author)) {
  23. author <- fullname(fallback = username(fallback = "R User"))
  24. }
  25. timestamp <- as.character(Sys.time(), format = "%Y-%m-%dT%H:%M:%SZ")
  26. captures <- c(
  27. insertion = "(?s)\\{\\+\\+(.*?)\\+\\+\\}",
  28. deletion = "(?s)\\{--(.*?)--\\}",
  29. substitution = "\\{~~(.*?)~>(.*?)~~\\}",
  30. highlight = "(?s)\\{==(.*?)==\\}\\{>>(.*?)<<\\}\\[\\[(\\d+)\\]\\]",
  31. comment = "(?s)\\{>>(.*?)<<\\}\\[\\[(\\d+)\\]\\]"
  32. )
  33. insertions <- stri_extract_all_regex(md, captures["insertion"],
  34. omit_no_match = TRUE
  35. )[[1]]
  36. deletions <- stri_extract_all_regex(md, captures["deletion"],
  37. omit_no_match = TRUE
  38. )[[1]]
  39. comments <- stri_extract_all_regex(md, "(?s)\\{>>(.*?)<<\\}",
  40. omit_no_match = TRUE
  41. )[[1]]
  42. # Mark paragraph breaks in insertions and deletions
  43. for (i in insertions) {
  44. md <- stri_replace_first_fixed(
  45. md, i,
  46. stri_replace_all_regex(
  47. i, "\n{2,}",
  48. "++}[]{.paragraph-insertion}\n\n{++"
  49. )
  50. )
  51. }
  52. for (i in deletions) {
  53. md <- stri_replace_first_fixed(
  54. md, i,
  55. stri_replace_all_regex(
  56. i, "\n{2,}",
  57. "--}[]{.paragraph-deletion}\n\n{--"
  58. )
  59. )
  60. }
  61. # Number comments
  62. for (i in seq_along(comments)) {
  63. md <- stri_replace_first_fixed(
  64. md, comments[i],
  65. stri_join(comments[i], "[[", i, "]]")
  66. )
  67. }
  68. replacements <- c(
  69. insertion = stri_join(
  70. "[$1]{.insertion author=\"", author, "\" date=\"",
  71. timestamp, "\"}"
  72. ),
  73. deletion = stri_join(
  74. "[$1]{.deletion author=\"", author, "\" date=\"",
  75. timestamp, "\"}"
  76. ),
  77. substitution = stri_join(
  78. "[$1]{.deletion author=\"", author, "\" date=\"",
  79. timestamp, "\"}",
  80. "[$2]{.insertion author=\"", author, "\" date=\"",
  81. timestamp, "\"}"
  82. ),
  83. highlight = stri_join(
  84. "[$2]{.comment-start id=\"$3\" author=\"", author,
  85. "\" date=\"", timestamp,
  86. "\"}$1[]{.comment-end id=\"$3\"}"
  87. ),
  88. comment = stri_join(
  89. "[$1]{.comment-start id=\"$2\" author=\"", author,
  90. "\" date=\"", timestamp,
  91. "\"}[]{.comment-end id=\"$2\"}"
  92. )
  93. )
  94. md <- stri_replace_all_regex(md, captures, replacements,
  95. vectorize_all = FALSE
  96. )
  97. md
  98. }
  99. cmwrap <- function(rmd) {
  100. rmd$text <- criticmarkup_to_pandoc(rmd$text)
  101. return(rmd)
  102. }