├── .Rbuildignore ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── R ├── gif_Addin.R ├── gif_search.R └── giphyr-package.R ├── README.md ├── giphyr.Rproj ├── img ├── Screenshot.png ├── exciting_rDbelKPujYEBq.gif └── rstudio_addins.png ├── inst ├── NEWS ├── gadgets │ └── gif_Addin │ │ ├── app.css │ │ ├── app.js │ │ └── giphy.png └── rstudio │ └── addins.dcf └── man ├── add_gifs.Rd ├── gif_Addin.Rd ├── gif_search.Rd └── giphyr-package.Rd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^img$ 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: giphyr 2 | Title: R Interface to the Giphy API 3 | Version: 0.2.0 4 | Authors@R: person("Hao", "Zhu", email = "haozhu233@gmail.com", 5 | role = c("aut", "cre"), 6 | comment = c(ORCID = '0000-0002-3386-6076')) 7 | Description: An interface to the 'API' of 'Giphy', a popular index-based search 8 | engine for 'GIFs' and animated stickers (see and 9 | for more information about 'Giphy' and 10 | its 'API') . This package also provides a 'RStudio Addin', which can help 11 | users easily search and download 'GIFs' and insert them to a 'rmarkdown' 12 | presentation. 13 | Depends: 14 | R (>= 3.2.2) 15 | Imports: 16 | httr, 17 | shiny, 18 | miniUI, 19 | tibble, 20 | rstudioapi, 21 | utils, 22 | dplyr, 23 | purrr 24 | License: MIT + file LICENSE 25 | Encoding: UTF-8 26 | LazyData: true 27 | URL: https://github.com/haozhu233/giphyr 28 | BugReports: https://github.com/haozhu233/giphyr/issues 29 | RoxygenNote: 6.1.0 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2016 2 | COPYRIGHT HOLDER: Hao Zhu 3 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(add_gifs) 4 | export(gif_search) 5 | import(miniUI) 6 | importFrom(dplyr,bind_rows) 7 | importFrom(httr,GET) 8 | importFrom(httr,content) 9 | importFrom(purrr,map) 10 | importFrom(purrr,map_df) 11 | importFrom(rstudioapi,insertText) 12 | importFrom(shiny,HTML) 13 | importFrom(shiny,actionButton) 14 | importFrom(shiny,actionLink) 15 | importFrom(shiny,addResourcePath) 16 | importFrom(shiny,dialogViewer) 17 | importFrom(shiny,fillRow) 18 | importFrom(shiny,h4) 19 | importFrom(shiny,htmlOutput) 20 | importFrom(shiny,icon) 21 | importFrom(shiny,img) 22 | importFrom(shiny,includeCSS) 23 | importFrom(shiny,includeScript) 24 | importFrom(shiny,observeEvent) 25 | importFrom(shiny,paneViewer) 26 | importFrom(shiny,radioButtons) 27 | importFrom(shiny,reactive) 28 | importFrom(shiny,reactiveValues) 29 | importFrom(shiny,renderText) 30 | importFrom(shiny,renderUI) 31 | importFrom(shiny,req) 32 | importFrom(shiny,runGadget) 33 | importFrom(shiny,shinyApp) 34 | importFrom(shiny,stopApp) 35 | importFrom(shiny,tags) 36 | importFrom(shiny,textInput) 37 | importFrom(shiny,textOutput) 38 | importFrom(shiny,uiOutput) 39 | importFrom(tibble,as_tibble) 40 | importFrom(utils,download.file) 41 | -------------------------------------------------------------------------------- /R/gif_Addin.R: -------------------------------------------------------------------------------- 1 | # App UI 2 | add_gifs_ui <- miniPage( 3 | tags$head( 4 | includeCSS(system.file("gadgets/gif_Addin/app.css", package = "giphyr")) 5 | ), 6 | gadgetTitleBar("Add GIFs"), 7 | miniContentPanel( 8 | fillRow(flex = c(1, 1, 1, 6, 2, 2, 2), height = "45px", 9 | uiOutput("back_button"), uiOutput("forward_button"), 10 | uiOutput("random_button"), 11 | uiOutput("gif_search_box"), 12 | uiOutput("download_gif_button"), 13 | uiOutput("insert_gif_button"), 14 | uiOutput("insert_link_button")), 15 | fillRow(flex = c(4, 3, 3), height = "55px", 16 | uiOutput("rating_ui"), 17 | uiOutput("citation_ui"), 18 | uiOutput("size_ui")), 19 | uiOutput("preview"), 20 | htmlOutput("space_holder"), 21 | tags$div(htmlOutput("pagination_note"), 22 | class = "pagination_note pull-right"), 23 | tags$div(class = "giphylogo", 24 | img(src = file.path("rsc/giphy.png"), width = 100)) 25 | ), 26 | includeScript(system.file("gadgets/gif_Addin/app.js", package = "giphyr")) 27 | ) 28 | 29 | # App Server 30 | add_gifs_server <- function(input, output, session) { 31 | output$gif_search_box <- renderUI({ 32 | textInput("search_text", label = NULL, 33 | placeholder = "Search all the GIFs", 34 | width = "98%") 35 | }) 36 | 37 | output$download_gif_button <- renderUI({ 38 | actionButton("download_gif", 39 | label = HTML(''), 40 | width = "95%", class = "btn-primary") 41 | }) 42 | 43 | output$insert_gif_button <- renderUI({ 44 | actionButton("insert_gif", 45 | label = HTML(' ', 46 | ' ', 47 | ''), 48 | width = "95%", class = "btn-success") 49 | }) 50 | 51 | output$insert_link_button <- renderUI({ 52 | actionButton("insert_link", 53 | label = HTML(' ', 54 | ' ', 55 | ''), 56 | width = "95%", class = "btn-default") 57 | }) 58 | 59 | output$back_button <- renderUI({ 60 | actionButton("pagination_back", label = NULL, width = "95%", 61 | icon = icon("arrow-left"), title = "Previous Page") 62 | }) 63 | 64 | output$forward_button <- renderUI({ 65 | actionButton("pagination_forward", label = NULL, width = "95%", 66 | icon = icon("arrow-right"), title = "Next Page") 67 | }) 68 | output$random_button <- renderUI({ 69 | actionButton("pagination_random", label = NULL, width = "95%", 70 | icon = icon("gift"), title = "Go to a random page") 71 | }) 72 | 73 | output$size_ui <- renderUI({ 74 | radioButtons( 75 | "size", 76 | HTML('Size: '), 78 | c("medium" = "downsized", "large" = "downsized_medium", "original"), 79 | inline = T) 80 | }) 81 | 82 | output$rating_ui <- renderUI({ 83 | radioButtons( 84 | "rating", "Rating:", 85 | c("G", "Y", "PG", "PG-13", "R"), inline = T 86 | ) 87 | }) 88 | 89 | output$citation_ui <- renderUI({ 90 | radioButtons( 91 | "citation", "Citation:", 92 | c("no", "yes", "cite source"), inline = T 93 | ) 94 | }) 95 | 96 | values <- reactiveValues(offset = 0, pre_offsets = c(0), off_position = 1, 97 | total_count = 0) 98 | 99 | observeEvent(input$pagination_back, { 100 | if (values$off_position >= 2) { 101 | values$off_position <- values$off_position - 1 102 | values$offset <- values$pre_offsets[values$off_position] 103 | } 104 | }) 105 | 106 | observeEvent(input$pagination_forward, { 107 | if (values$off_position == length(values$pre_offsets)) { 108 | values$offset <- values$offset + 10 109 | values$pre_offsets <- c(values$pre_offsets, values$offset) 110 | } else { 111 | values$offset <- values$pre_offsets[values$off_position + 1] 112 | } 113 | values$off_position <- values$off_position + 1 114 | }) 115 | 116 | preview_gifs <- reactive({ 117 | req(input$search_text) 118 | out <- suppressWarnings( 119 | gif_search(input$search_text, 120 | img_format = c("fixed_height_small", "downsized", 121 | "downsized_medium", "original"), 122 | offset = values$offset, 123 | rating = tolower(input$rating))) 124 | if (is.null(out)) return(NULL) 125 | return(out) 126 | }) 127 | 128 | observeEvent(input$search_text, { 129 | if (!is.null(preview_gifs())) { 130 | values$total_count <- attr(preview_gifs(), "total_count") 131 | if (values$total_count > 4999) { 132 | values$total_count <- 4999 133 | } 134 | } 135 | }) 136 | 137 | observeEvent(input$rating, { 138 | if (!is.null(preview_gifs())) { 139 | values$total_count <- attr(preview_gifs(), "total_count") 140 | values$offset <- 0 141 | values$pre_offsets <- c(0) 142 | values$off_position <- 1 143 | if (values$total_count > 4999) { 144 | values$total_count <- 4999 145 | } 146 | } 147 | }) 148 | 149 | observeEvent(input$pagination_random, { 150 | if (values$off_position != length(values$pre_offsets)) { 151 | values$pre_offsets <- values$pre_offsets[1:values$off_position] 152 | } 153 | values$offset <- sample(10:(values$total_count - 10), 1) 154 | values$pre_offsets <- c(values$pre_offsets, values$offset) 155 | values$off_position <- values$off_position + 1 156 | }) 157 | 158 | output$pagination_note <- function() { 159 | req(preview_gifs()) 160 | page_note <- paste( 161 | attr(preview_gifs(), "offset") + 1, "~", 162 | attr(preview_gifs(), "offset") + attr(preview_gifs(), "count"), 163 | "of", attr(preview_gifs(), "total_count") 164 | ) 165 | if (values$total_count != attr(preview_gifs(), "total_count")) { 166 | page_note <- paste( 167 | page_note, 168 | '' 170 | ) 171 | } 172 | return(HTML(page_note)) 173 | } 174 | 175 | observeEvent(input$search_text, { 176 | values$offset = 0 177 | }) 178 | 179 | find_ele <- function(x, name) { 180 | x_names <- names(x) 181 | return(x[which(x_names == name)][[1]]) 182 | } 183 | 184 | output$preview <- renderUI({ 185 | req(preview_gifs()) 186 | apply(preview_gifs(), 1, function(x) { 187 | actionLink(find_ele(x, "id"), title = find_ele(x, "slug"), 188 | label = NULL, class = "gifpreview", icon = NULL, 189 | tags$img(src = find_ele(x, "fixed_height_small"))) 190 | }) 191 | }) 192 | 193 | output$space_holder <- function() { 194 | if (is.null(input$search_text)) return(NULL) 195 | if (input$search_text != "") return(NULL) 196 | app_message <- paste0( 197 | '

Step 1. Search any keywords

', 198 | '

Step 2. Select a GIF you like

', 199 | '

Step 3. Download it / ', 200 | 'Download & insert it to a Rmd document ', 201 | ' ', 202 | ' ', 203 | ' / ', 204 | 'Simply insert a link to a Rmd document ', 205 | ' ', 206 | ' ', 207 | '', 208 | '


' 209 | ) 210 | app_tips <- c( 211 | ' will drop you at a random page. Use it to discover more fun gifs!', 212 | 'Unfortunately, GIPHY API can only export the first 5000 gifs. :(', 213 | 'Downloaded GIFs are saved in the "img" folder in your project directory.', 214 | "For download file sizes, medium: file < 2 MB, large: file < 5 MB & original: no restriction.", 215 | "If you choose to cite source, be cautious because some links might have been expired after a few years.", 216 | "Regular citations will direct readers to the image on giphy.com, where they can find source information as well. " 217 | ) 218 | HTML( 219 | '
', app_message, 220 | 'Tip:
', app_tips[sample(1:length(app_tips), 1)], 221 | '
' 222 | ) 223 | } 224 | 225 | observeEvent(input$done, { 226 | invisible(stopApp()) 227 | }) 228 | 229 | observeEvent(input$download_gif, { 230 | if (!is.null(input$clickedgif) & !is.null(input$search_text)) { 231 | dir.create("img", showWarnings = F) 232 | dl_file_name <- paste0( 233 | "img/", search_query_parser(input$search_text), 234 | "_", input$clickedgif, ".gif" 235 | ) 236 | status <- try(download.file( 237 | preview_gifs()[[input$size]][preview_gifs()$id == input$clickedgif], 238 | dl_file_name 239 | ), silent = T) 240 | } 241 | }) 242 | 243 | observeEvent(input$insert_gif, { 244 | if (!is.null(input$clickedgif) & !is.null(input$search_text)) { 245 | dir.create("img", showWarnings = F) 246 | dl_file_name <- paste0( 247 | "img/", search_query_parser(input$search_text), 248 | "_", input$clickedgif, ".gif" 249 | ) 250 | status <- try(download.file( 251 | preview_gifs()[[input$size]][preview_gifs()$id == input$clickedgif], 252 | dl_file_name 253 | ), silent = T) 254 | bitly_link <- preview_gifs()$bitly_url[ 255 | preview_gifs()$id == input$clickedgif] 256 | citation_source <- preview_gifs()$source[ 257 | preview_gifs()$id == input$clickedgif] 258 | source_date <- preview_gifs()$import_datetime[ 259 | preview_gifs()$id == input$clickedgif] 260 | citation_text <- switch( 261 | input$citation, 262 | "no" = NULL, 263 | "yes" = paste0("
(Available at [", 264 | bitly_link, "](", bitly_link, "), ", 265 | format(Sys.Date(), "%b %d, %Y"), ")
\n"), 266 | "cite source" = paste0("
([Source link](", 267 | citation_source, "), accessed ", 268 | format(as.Date(source_date), "%b %d, %Y"), 269 | ")
\n") 270 | ) 271 | if (citation_source == "" & input$citation == "cite source") { 272 | citation_text <- NULL 273 | cat("Source info is not available. ") 274 | } 275 | rstudioapi::insertText( 276 | text = paste0('![', search_query_parser(input$search_text), "](", 277 | dl_file_name, ")\n", citation_text)) 278 | } 279 | }) 280 | 281 | observeEvent(input$insert_link, { 282 | if (!is.null(input$clickedgif) & !is.null(input$search_text)) { 283 | img_link <- preview_gifs()[[input$size]][ 284 | preview_gifs()$id == input$clickedgif] 285 | bitly_link <- preview_gifs()$bitly_url[ 286 | preview_gifs()$id == input$clickedgif] 287 | citation_source <- preview_gifs()$source[ 288 | preview_gifs()$id == input$clickedgif] 289 | source_date <- preview_gifs()$import_datetime[ 290 | preview_gifs()$id == input$clickedgif] 291 | citation_text <- switch( 292 | input$citation, 293 | "no" = NULL, 294 | "yes" = paste0("
(Available at [", 295 | bitly_link, "](", bitly_link, "), ", 296 | format(Sys.Date(), "%b %d, %Y"), ")
\n"), 297 | "cite source" = paste0("
([Source link](", 298 | citation_source, "), accessed ", 299 | format(as.Date(source_date), "%b %d, %Y"), 300 | ")
\n") 301 | ) 302 | if (citation_source == "" & input$citation == "cite source") { 303 | citation_text <- NULL 304 | cat("Source info is not available. ") 305 | } 306 | rstudioapi::insertText( 307 | text = paste0('![', search_query_parser(input$search_text), "](", 308 | img_link, ") \n", citation_text)) 309 | } 310 | }) 311 | } 312 | 313 | #' giphyr RStudio Addin 314 | gif_Addin <- function() { 315 | addResourcePath("rsc", 316 | system.file("gadgets/gif_Addin", package = "giphyr")) 317 | runGadget(add_gifs_ui, add_gifs_server, viewer = paneViewer()) 318 | } 319 | 320 | #' Add GIFs through a shiny app 321 | #' 322 | #' @description A shiny app alternative to the RStudio Addin for non-RStudio 323 | #' users. 324 | #' 325 | #' @export 326 | add_gifs <- function() { 327 | shinyApp(add_gifs_ui, add_gifs_server) 328 | } 329 | -------------------------------------------------------------------------------- /R/gif_search.R: -------------------------------------------------------------------------------- 1 | #' Search GIFs by key words throught giphy API 2 | #' 3 | #' @param query search query term or phrase. 4 | #' @param limit (optional) number of results to return, maximum 100. Default 10. 5 | #' @param offset (optional) results offset, defaults to 0. 6 | #' @param rating limit results to those rated (y,g, pg, pg-13 or r). Default g. 7 | #' @param img_format A vector of strings deciding what formats of images you 8 | #' want to receive. Possible options include "fixed_height", 9 | #' "fixed_height_still", "fixed_height_downsampled", "fixed_width", 10 | #' "fixed_width_still", "fixed_width_downsampled", "fixed_height_small", 11 | #' "fixed_height_small_still", "fixed_width_small", "fixed_width_small_still", 12 | #' "downsized", "downsized_still", "downsized_large", "downsized_medium", 13 | #' "original", "original_still", "preview_gif", "fixed_height_mp4", 14 | #' "fixed_width_mp4", "fixed_height_small_mp4", "fixed_width_small_mp4", 15 | #' "original_mp4", "looping_mp4", "preview_mp4" & "downsized_small_mp4". An Image 16 | #' with fixed height or width has a fixed length of the edge at 200px. A small 17 | #' fixed height or width images has a 100px-long fixed edge. "Downsampled" 18 | #' images are compressed and are good for preview. "Still" images is not a GIF 19 | #' and will not be animated. 20 | #' 21 | #' @examples 22 | #' gif_search("cat") 23 | #' gif_search("dog", img_format = "downsized") 24 | #' gif_search("panda", limit = 100, img_format = "downsized_small_mp4") 25 | #' 26 | #' @export 27 | gif_search <- function(query, limit = 10, offset = 0, rating = "g", 28 | img_format = c( 29 | "fixed_height", "fixed_height_still", 30 | "fixed_height_downsampled", "fixed_width", 31 | "fixed_width_still", "fixed_width_downsampled", 32 | "fixed_height_small", "fixed_height_small_still", 33 | "fixed_width_small", "fixed_width_small_still", 34 | "downsized", "downsized_still", 35 | "downsized_large", "downsized_medium", 36 | "original", "original_still", 37 | "preview_gif", "fixed_height_mp4", 38 | "fixed_width_mp4", "fixed_height_small_mp4", 39 | "fixed_width_small_mp4", "original_mp4", 40 | "looping_mp4", "preview_mp4", 41 | "downsized_small_mp4" 42 | )) { 43 | 44 | img_format <- match.arg( 45 | img_format, 46 | c( 47 | "fixed_height", "fixed_height_still", 48 | "fixed_height_downsampled", "fixed_width", 49 | "fixed_width_still", "fixed_width_downsampled", 50 | "fixed_height_small", "fixed_height_small_still", 51 | "fixed_width_small", "fixed_width_small_still", 52 | "downsized", "downsized_still", 53 | "downsized_large", "downsized_medium", 54 | "original", "original_still", 55 | "preview_gif", "fixed_height_mp4", 56 | "fixed_width_mp4", "fixed_height_small_mp4", 57 | "fixed_width_small_mp4", "original_mp4", 58 | "looping_mp4", "preview_mp4", 59 | "downsized_small_mp4" 60 | ), several.ok = TRUE 61 | ) 62 | 63 | search_api_path <- "/v1/gifs/search" 64 | 65 | search_raw <- GET( 66 | url = .giphy_url(), 67 | path = search_api_path, 68 | query = list( 69 | q = search_query_parser(query), 70 | limit = limit, 71 | offset = offset, 72 | rating = rating, 73 | api_key = .giphy_api_key() 74 | )) 75 | 76 | if (search_raw$status_code != 200) { 77 | stop("HTML status code ", search_raw$status_code, " received. ", 78 | "Please wait for a while and retry.") 79 | } 80 | 81 | search_content <- content(search_raw) 82 | 83 | if (search_content$pagination$total_count == 0) { 84 | warning("Search returns no results. Please try again") 85 | return() 86 | } 87 | 88 | out <- content_exporter(search_content) 89 | 90 | out_variables <- intersect(names(out), img_format) 91 | out_variables <- c( 92 | names(out)[1:(which(names(out) == "fixed_height") - 1)], 93 | out_variables 94 | ) 95 | out <- out[out_variables] 96 | 97 | attr(out, "total_count") <- search_content$pagination$total_count 98 | attr(out, "count") <- search_content$pagination$count 99 | attr(out, "offset") <- search_content$pagination$offset 100 | 101 | 102 | return(out) 103 | } 104 | 105 | .giphy_api_key <- function()"GAUeYalixQovJJGRACGEaKRpNunOoH1q" 106 | 107 | .giphy_url <- function()"http://api.giphy.com/" 108 | 109 | search_query_parser <- function(x) { 110 | return(gsub("\\s+", "+", x)) 111 | } 112 | 113 | content_exporter <- function(x) { 114 | non_scalar <- map_df(x$data, ~map(.x, length)) 115 | non_scalar <- unlist(map(non_scalar, ~mean(.x, na.rm = T) == 1)) 116 | non_scalar <- non_scalar[!non_scalar] 117 | non_scalar <- names(non_scalar) 118 | map_df(x$data, ~c( 119 | .x[which(!names(.x) %in% non_scalar)], 120 | gif_url(.x$images), 121 | mp4_url(.x$images)) 122 | ) 123 | } 124 | 125 | gif_url <- function(images) { 126 | images <- images[which(names(images) %in% c( 127 | "fixed_height", "fixed_height_still", "fixed_height_downsampled", 128 | "fixed_width", "fixed_width_still", "fixed_width_downsampled", 129 | "fixed_height_small", "fixed_height_small_still", "fixed_width_small", 130 | "fixed_width_small_still", "downsized", "downsized_still", 131 | "downsized_large", "downsized_medium", "original", 132 | "original_still","preview_gif" 133 | ))] 134 | out <- lapply(images, function(x) { 135 | if ("url" %in% names(x)) { 136 | x[[which(names(x) == "url")]] 137 | } 138 | }) 139 | return(out) 140 | } 141 | 142 | mp4_url <- function(images) { 143 | mp4_variables <- c( 144 | "fixed_height", "fixed_width", "fixed_height_small", "fixed_width_small", 145 | "original", "looping", "preview", "downsized_small" 146 | ) 147 | images <- images[which(names(images) %in% mp4_variables)] 148 | out <- lapply(images, function(x) { 149 | if ("mp4" %in% names(x)) { 150 | x[[which(names(x) == "mp4")]] 151 | } 152 | }) 153 | names(out) <- paste0(mp4_variables, "_mp4") 154 | return(out) 155 | } 156 | 157 | 158 | -------------------------------------------------------------------------------- /R/giphyr-package.R: -------------------------------------------------------------------------------- 1 | #' giphyr 2 | #' 3 | #' @importFrom httr GET content 4 | #' @importFrom tibble as_tibble 5 | #' @importFrom shiny h4 fillRow htmlOutput renderUI textInput actionButton req 6 | #' HTML observeEvent stopApp dialogViewer runGadget uiOutput actionLink icon 7 | #' reactiveValues reactive includeCSS includeScript tags img addResourcePath 8 | #' radioButtons textOutput renderText shinyApp paneViewer 9 | #' @import miniUI 10 | #' @importFrom rstudioapi insertText 11 | #' @importFrom utils download.file 12 | #' @importFrom purrr map_df map 13 | #' @importFrom dplyr bind_rows 14 | #' @name giphyr-package 15 | #' @aliases giphyr 16 | #' @docType package 17 | #' @keywords package 18 | NULL 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # giphyr 2 | ![CRAN_version](http://www.r-pkg.org/badges/version/giphyr) 3 | ![CRAN_download](http://cranlogs.r-pkg.org/badges/giphyr) 4 | 5 | 6 | Want to add some GIFs to your awesome rmarkdown presentation? 7 | 8 | ![exciting](https://raw.githubusercontent.com/haozhu233/giphyr/master/img/exciting_rDbelKPujYEBq.gif) 9 | 10 | ## Introduction 11 | I guess this is one of the least productive R packages in our community... 12 | 13 | No more to say. Enjoy more GIFs in your Rmarkdown documents. 14 | 15 | ![Screenshot](https://raw.githubusercontent.com/haozhu233/giphyr/master/img/Screenshot.png) 16 | 17 | ## Install 18 | ```r 19 | install.packages("giphyr") 20 | 21 | # For dev version 22 | devtools::install_github("haozhu233/giphyr") 23 | ``` 24 | 25 | ## Usage 26 | If you are using a recent version of RStudio (v0.99.878 or later), you should be able to find an "Addins" dropdown menu on the toolbar. This package comes with a RStudio Addin called "Add GIFs", which has a user friendly interface you can use to browse, download or insert GIFs or links to a rmarkdown document. 27 | 28 | 29 | 30 | For useRs who are not using RStudio, I'm planning to include a stand-alone shiny app that can be run directly in the console in the next release. 31 | 32 | ## Note 33 | I'm currently using the public beta key for the Giphy API. They say there is a rate limit. I will request a Production key if needed. 34 | 35 | Also, I noticed that after GIPHY made some API change recently (the link is no longer point directly to a .gif file but a web page), GIF images can't be seen correctly on some old versions of RStudio. You might need to update your RStudio version if it occurs to you. 36 | -------------------------------------------------------------------------------- /giphyr.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: XeLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageCheckArgs: --as-cran 22 | PackageRoxygenize: rd,collate,namespace 23 | -------------------------------------------------------------------------------- /img/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haozhu233/giphyr/f161bfbed30b8f427a60b9f3a195ab9535214269/img/Screenshot.png -------------------------------------------------------------------------------- /img/exciting_rDbelKPujYEBq.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haozhu233/giphyr/f161bfbed30b8f427a60b9f3a195ab9535214269/img/exciting_rDbelKPujYEBq.gif -------------------------------------------------------------------------------- /img/rstudio_addins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haozhu233/giphyr/f161bfbed30b8f427a60b9f3a195ab9535214269/img/rstudio_addins.png -------------------------------------------------------------------------------- /inst/NEWS: -------------------------------------------------------------------------------- 1 | giphyr 0.1.1 2 | -------------------------------------------------------------------------------- 3 | 4 | * Added a stand alone `add_gifs()` function to start the addin outside of 5 | RStudio. 6 | 7 | * Add `dplyr` to imports to accommodate incoming purrr release. 8 | 9 | 10 | giphyr 0.1.0 11 | -------------------------------------------------------------------------------- 12 | 13 | * Initial Release 14 | -------------------------------------------------------------------------------- /inst/gadgets/gif_Addin/app.css: -------------------------------------------------------------------------------- 1 | .gifpreview { 2 | margin-bottom: 10px; 3 | margin-left: 5px; 4 | display: inline-block; 5 | } 6 | 7 | .gifselected { 8 | box-shadow: 0 1px 1px 2px #377BB5; 9 | background-color: #fff; 10 | position: relative; 11 | } 12 | 13 | .gifselected::before, 14 | .gifselected::after { 15 | content: ''; 16 | position: absolute; 17 | top: 0; 18 | right: 0; 19 | border-color: transparent; 20 | border-style: solid; 21 | } 22 | 23 | .gifselected::before { 24 | border-width: 1.25em; 25 | } 26 | 27 | .gifselected::after { 28 | border-width: 1em; 29 | border-right-color: #377BB5; 30 | border-top-color: #377BB5; 31 | } 32 | 33 | .spaceHolder { 34 | font-size: 24px; 35 | color: #999; 36 | margin-top: 50px; 37 | margin-left: 50px; 38 | } 39 | 40 | .giphylogo { 41 | position: absolute; 42 | bottom: 0; 43 | right: 0; 44 | } 45 | 46 | .pagination_note { 47 | color: #999; 48 | font: 70%; 49 | } 50 | -------------------------------------------------------------------------------- /inst/gadgets/gif_Addin/app.js: -------------------------------------------------------------------------------- 1 | $('#preview').on('click', '.gifpreview', function(){ 2 | Shiny.onInputChange('clickedgif', this.id); 3 | $('.gifpreview').removeClass('gifselected'); 4 | $(this).addClass('gifselected'); 5 | }); 6 | -------------------------------------------------------------------------------- /inst/gadgets/gif_Addin/giphy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haozhu233/giphyr/f161bfbed30b8f427a60b9f3a195ab9535214269/inst/gadgets/gif_Addin/giphy.png -------------------------------------------------------------------------------- /inst/rstudio/addins.dcf: -------------------------------------------------------------------------------- 1 | Name: Add GIFs 2 | Description: Search GIFs through Giphy API and use them in Rmarkdown documents 3 | Binding: gif_Addin 4 | Interactive: true 5 | -------------------------------------------------------------------------------- /man/add_gifs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gif_Addin.R 3 | \name{add_gifs} 4 | \alias{add_gifs} 5 | \title{Add GIFs through a shiny app} 6 | \usage{ 7 | add_gifs() 8 | } 9 | \description{ 10 | A shiny app alternative to the RStudio Addin for non-RStudio 11 | users. 12 | } 13 | -------------------------------------------------------------------------------- /man/gif_Addin.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gif_Addin.R 3 | \name{gif_Addin} 4 | \alias{gif_Addin} 5 | \title{giphyr RStudio Addin} 6 | \usage{ 7 | gif_Addin() 8 | } 9 | \description{ 10 | giphyr RStudio Addin 11 | } 12 | -------------------------------------------------------------------------------- /man/gif_search.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gif_search.R 3 | \name{gif_search} 4 | \alias{gif_search} 5 | \title{Search GIFs by key words throught giphy API} 6 | \usage{ 7 | gif_search(query, limit = 10, offset = 0, rating = "g", 8 | img_format = c("fixed_height", "fixed_height_still", 9 | "fixed_height_downsampled", "fixed_width", "fixed_width_still", 10 | "fixed_width_downsampled", "fixed_height_small", 11 | "fixed_height_small_still", "fixed_width_small", 12 | "fixed_width_small_still", "downsized", "downsized_still", 13 | "downsized_large", "downsized_medium", "original", "original_still", 14 | "preview_gif", "fixed_height_mp4", "fixed_width_mp4", 15 | "fixed_height_small_mp4", "fixed_width_small_mp4", "original_mp4", 16 | "looping_mp4", "preview_mp4", "downsized_small_mp4")) 17 | } 18 | \arguments{ 19 | \item{query}{search query term or phrase.} 20 | 21 | \item{limit}{(optional) number of results to return, maximum 100. Default 10.} 22 | 23 | \item{offset}{(optional) results offset, defaults to 0.} 24 | 25 | \item{rating}{limit results to those rated (y,g, pg, pg-13 or r). Default g.} 26 | 27 | \item{img_format}{A vector of strings deciding what formats of images you 28 | want to receive. Possible options include "fixed_height", 29 | "fixed_height_still", "fixed_height_downsampled", "fixed_width", 30 | "fixed_width_still", "fixed_width_downsampled", "fixed_height_small", 31 | "fixed_height_small_still", "fixed_width_small", "fixed_width_small_still", 32 | "downsized", "downsized_still", "downsized_large", "downsized_medium", 33 | "original", "original_still", "preview_gif", "fixed_height_mp4", 34 | "fixed_width_mp4", "fixed_height_small_mp4", "fixed_width_small_mp4", 35 | "original_mp4", "looping_mp4", "preview_mp4" & "downsized_small_mp4". An Image 36 | with fixed height or width has a fixed length of the edge at 200px. A small 37 | fixed height or width images has a 100px-long fixed edge. "Downsampled" 38 | images are compressed and are good for preview. "Still" images is not a GIF 39 | and will not be animated.} 40 | } 41 | \description{ 42 | Search GIFs by key words throught giphy API 43 | } 44 | \examples{ 45 | gif_search("cat") 46 | gif_search("dog", img_format = "downsized") 47 | gif_search("panda", limit = 100, img_format = "downsized_small_mp4") 48 | 49 | } 50 | -------------------------------------------------------------------------------- /man/giphyr-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/giphyr-package.R 3 | \docType{package} 4 | \name{giphyr-package} 5 | \alias{giphyr-package} 6 | \alias{giphyr} 7 | \title{giphyr} 8 | \description{ 9 | giphyr 10 | } 11 | \keyword{package} 12 | --------------------------------------------------------------------------------