@@ -69,7 +69,9 @@ auto_mark = function(data, aesthetics, ts = FALSE) {
6969 list (list (type = ' line' ))
7070 } else if (xt == ' numeric' && yt == ' none' ) {
7171 list (list (
72- type = ' interval' , transform = list (list (type = ' binX' , y = ' count' ))
72+ type = ' rect' ,
73+ transform = list (list (type = ' binX' , y = ' count' )),
74+ style = list (stroke = ' white' )
7375 ))
7476 } else if (xt == ' categorical' && yt == ' none' ) {
7577 list (list (
@@ -303,45 +305,77 @@ cdn_scripts = function() {
303305 sprintf(' <script src="%s" defer></script>' , c(g2_cdn(), g2_patches_cdn ))
304306}
305307
308+ g2_html_page = function (body ) {
309+ paste(c(
310+ ' <!DOCTYPE html>' , ' <html>' , ' <head>' ,
311+ ' <meta charset="utf-8">' ,
312+ cdn_scripts(),
313+ ' </head>' , ' <body>' ,
314+ body ,
315+ ' </body>' , ' </html>'
316+ ), collapse = ' \n ' )
317+ }
318+
306319# ' Preview a Chart in the Viewer or Browser
307320# '
308321# ' @param x A `g2` object.
309322# ' @param ... Additional arguments passed to [chart_html()].
310323# ' @return The chart object (invisibly).
311324# ' @export
312325print.g2 = function (x , ... ) {
313- body = chart_html(x , ... )
314- html = c(
315- ' <!DOCTYPE html>' , ' <html>' , ' <head>' ,
316- ' <meta charset="utf-8">' ,
317- cdn_scripts(),
318- ' </head>' , ' <body>' ,
319- body ,
320- ' </body>' , ' </html>'
321- )
322326 # TODO: xfun >= 0.57.3 no longer needs paste()
323- xfun :: html_view(paste( html , collapse = ' \n ' ))
327+ xfun :: html_view(g2_html_page(chart_html( x , ... ) ))
324328 invisible (x )
325329}
326330
331+ # Document-scoped flag stored in opts_knit to include CDN scripts only once per
332+ # knit session. opts_knit is restored between documents, so the flag resets
333+ # automatically, which also allows Quarto (which rejects non-disk-based
334+ # htmltools::htmlDependency sources).
335+ .knitr.flag = ' gglite.scripts_added'
336+
327337# ' Custom Printing in Knitr
328338# '
329339# ' @param x A `g2` object.
330340# ' @param ... Ignored.
331341# ' @return A `knit_asis` character vector.
332342knit_print.g2 = function (x , ... ) {
333- if (requireNamespace(' htmltools' , quietly = TRUE )) {
334- dep = htmltools :: htmlDependency(
335- name = ' antv-g2' , version = ' 5' ,
336- src = c(href = ' ' ),
337- head = paste(cdn_scripts(), collapse = ' \n ' )
338- )
339- knitr :: knit_meta_add(list (dep ))
340- structure(chart_html(x ), class = c(' knit_asis' , ' html' ))
341- } else {
342- out = paste(c(cdn_scripts(), chart_html(x )), collapse = ' \n ' )
343- structure(out , class = c(' knit_asis' , ' html' ))
343+ html = chart_html(x )
344+ if (! isTRUE(knitr :: opts_knit $ get(.knitr.flag ))) {
345+ knitr :: opts_knit $ set(setNames(list (TRUE ), .knitr.flag ))
346+ html = paste(c(cdn_scripts(), html ), collapse = ' \n ' )
344347 }
348+ structure(html , class = c(' knit_asis' , ' html' ))
349+ }
350+
351+ # ' HTML Representation for Jupyter Notebooks
352+ # '
353+ # ' Called by the `repr` package (used by IRkernel) to render g2 charts in
354+ # ' Jupyter notebooks. Returns a complete HTML page so the chart is displayed
355+ # ' inside a sandboxed output cell.
356+ # '
357+ # ' @param obj A `g2` object.
358+ # ' @param ... Ignored.
359+ # ' @return A character string of complete HTML.
360+ # ' @noRd
361+ repr_html.g2 = function (obj , ... ) g2_html_page(chart_html(obj ))
362+
363+ # ' Text Representation for Jupyter Notebooks
364+ # '
365+ # ' Returns a brief text description so IRkernel's MIME bundle includes a
366+ # ' non-empty `text/plain` entry, which is required before any rich display
367+ # ' (including HTML) is sent to the Jupyter frontend.
368+ # '
369+ # ' @param obj A `g2` object.
370+ # ' @param ... Ignored.
371+ # ' @return A character string.
372+ # ' @noRd
373+ repr_text.g2 = function (obj , ... ) {
374+ n = if (is.data.frame(obj $ data )) nrow(obj $ data ) else NULL
375+ marks = paste(vapply(obj $ layers , `[[` , ' ' , ' type' ), collapse = ' , ' )
376+ if (! nzchar(marks )) marks = ' auto'
377+ n_str = if (is.null(n )) ' no data' else as.character(n )
378+ sprintf(' G2 chart (%s; %s rows)' , marks , n_str )
345379}
346380
347381# ' @importFrom xfun record_print
@@ -350,11 +384,24 @@ record_print.g2 = function(x, ...) {
350384 xfun :: new_record(c(cdn_scripts(), chart_html(x , ... ), ' ' ), ' asis' )
351385}
352386
353- register_knit_print = function () {
354- registerS3method(' knit_print' , ' g2' , knit_print.g2 , envir = asNamespace(' knitr' ))
387+ register_methods = function (pkgs , generics ) {
388+ for (i in seq_along(pkgs )) local({
389+ pkg = pkgs [[i ]]; generic = generics [[i ]]
390+ hook = function (... ) {
391+ registerS3method(
392+ generic , ' g2' ,
393+ asNamespace(' gglite' )[[paste0(generic , ' .g2' )]],
394+ envir = asNamespace(pkg )
395+ )
396+ }
397+ if (isNamespaceLoaded(pkg )) hook()
398+ setHook(packageEvent(pkg , ' onLoad' ), hook )
399+ })
355400}
356401
357402.onLoad = function (... ) {
358- if (isNamespaceLoaded(' knitr' )) register_knit_print()
359- setHook(packageEvent(' knitr' , ' onLoad' ), function (... ) register_knit_print())
403+ register_methods(
404+ c(' knitr' , ' repr' , ' repr' ),
405+ c(' knit_print' , ' repr_html' , ' repr_text' )
406+ )
360407}
0 commit comments