[med-svn] [r-cran-htmlwidgets] 05/07: New upstream version 0.8

Andreas Tille tille at debian.org
Tue Oct 10 15:01:35 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository r-cran-htmlwidgets.

commit 24306df96a7c10518b06f298f4455ab56cbb9675
Author: Andreas Tille <tille at debian.org>
Date:   Tue Oct 10 16:57:40 2017 +0200

    New upstream version 0.8
---
 DESCRIPTION                    |  35 ++
 LICENSE                        |   2 +
 MD5                            |  42 +++
 NAMESPACE                      |  22 ++
 R/htmlwidgets.R                | 463 +++++++++++++++++++++++
 R/imports.R                    |   5 +
 R/knitr-methods.R              |  44 +++
 R/pandoc.R                     | 243 ++++++++++++
 R/savewidget.R                 |  44 +++
 R/scaffold.R                   | 193 ++++++++++
 R/seed.R                       |   0
 R/sizing.R                     | 226 +++++++++++
 R/utils.R                      | 218 +++++++++++
 R/widgetid.R                   |  43 +++
 build/vignette.rds             | Bin 0 -> 260 bytes
 debian/changelog               |  21 --
 debian/compat                  |   1 -
 debian/control                 |  27 --
 debian/copyright               |  34 --
 debian/rules                   |   4 -
 debian/source/format           |   1 -
 debian/watch                   |   2 -
 inst/NEWS                      |  93 +++++
 inst/doc/develop_advanced.R    |  57 +++
 inst/doc/develop_advanced.Rmd  | 188 +++++++++
 inst/doc/develop_advanced.html | 359 ++++++++++++++++++
 inst/doc/develop_intro.R       |   5 +
 inst/doc/develop_intro.Rmd     | 320 ++++++++++++++++
 inst/doc/develop_intro.html    | 435 +++++++++++++++++++++
 inst/doc/develop_sizing.Rmd    | 170 +++++++++
 inst/doc/develop_sizing.html   | 378 +++++++++++++++++++
 inst/templates/widget_js.txt   |  28 ++
 inst/templates/widget_r.txt    |  53 +++
 inst/www/htmlwidgets.js        | 836 +++++++++++++++++++++++++++++++++++++++++
 man/JS.Rd                      |  27 ++
 man/createWidget.Rd            |  62 +++
 man/getDependency.Rd           |  17 +
 man/htmlwidgets-package.Rd     |  30 ++
 man/htmlwidgets-shiny.Rd       |  63 ++++
 man/onRender.Rd                |  86 +++++
 man/onStaticRenderComplete.Rd  |  52 +++
 man/prependContent.Rd          |  29 ++
 man/saveWidget.Rd              |  30 ++
 man/scaffoldWidget.Rd          |  27 ++
 man/setWidgetIdSeed.Rd         |  27 ++
 man/sizingPolicy.Rd            | 104 +++++
 vignettes/develop_advanced.Rmd | 188 +++++++++
 vignettes/develop_intro.Rmd    | 320 ++++++++++++++++
 vignettes/develop_sizing.Rmd   | 170 +++++++++
 vignettes/images/sigma.png     | Bin 0 -> 115423 bytes
 50 files changed, 5734 insertions(+), 90 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
new file mode 100644
index 0000000..5a9724e
--- /dev/null
+++ b/DESCRIPTION
@@ -0,0 +1,35 @@
+Package: htmlwidgets
+Type: Package
+Title: HTML Widgets for R
+Version: 0.8
+Date: 2016-11-09
+Authors at R: c(
+    person("Ramnath", "Vaidyanathan", role = c("aut", "cph")),
+    person("Yihui", "Xie", role = c("aut")),
+    person("JJ", "Allaire", role = c("aut", "cre"), email = "jj at rstudio.com"),
+    person("Joe", "Cheng", role = c("aut")),
+    person("Kenton", "Russell", role = c("aut", "cph")),
+    person(family = "RStudio", role = "cph")
+    )
+Description: A framework for creating HTML widgets that render in various
+    contexts including the R console, 'R Markdown' documents, and 'Shiny'
+    web applications.
+License: MIT + file LICENSE
+VignetteBuilder: knitr
+Imports: htmltools (>= 0.3), jsonlite (>= 0.9.16), yaml
+Suggests: knitr (>= 1.8)
+Enhances: shiny (>= 0.12)
+URL: https://github.com/ramnathv/htmlwidgets
+BugReports: https://github.com/ramnathv/htmlwidgets/issues
+RoxygenNote: 5.0.1
+NeedsCompilation: no
+Packaged: 2016-11-09 20:41:12 UTC; jjallaire
+Author: Ramnath Vaidyanathan [aut, cph],
+  Yihui Xie [aut],
+  JJ Allaire [aut, cre],
+  Joe Cheng [aut],
+  Kenton Russell [aut, cph],
+  RStudio [cph]
+Maintainer: JJ Allaire <jj at rstudio.com>
+Repository: CRAN
+Date/Publication: 2016-11-09 23:48:13
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0b93d3a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,2 @@
+YEAR: 2016
+COPYRIGHT HOLDER: Ramnath Vaidyanathan, Joe Cheng, JJ Allaire, Yihui Xie, and Kenton Russell
diff --git a/MD5 b/MD5
new file mode 100644
index 0000000..0bc360c
--- /dev/null
+++ b/MD5
@@ -0,0 +1,42 @@
+a91857d8fa3a6bf68ab21da333cd58bc *DESCRIPTION
+d5e014920944fd879bfd6c3b9d943512 *LICENSE
+27ad3bb8893369b9e179fb99f2034ae4 *NAMESPACE
+5d40ec402a74a27043d6284c00adb2d8 *R/htmlwidgets.R
+f844096ad2e59400797dd567d94499d8 *R/imports.R
+e73b61f39eb5e67d5dd03e7ba998a162 *R/knitr-methods.R
+43429cc31b011b0d6fc7752d438b8b7c *R/pandoc.R
+82585e95d4a99164fc8382532f467cdf *R/savewidget.R
+7855788fc6a789530f884750e46e36bf *R/scaffold.R
+d41d8cd98f00b204e9800998ecf8427e *R/seed.R
+eb659aebd3386aef1e6a7a848d48cb26 *R/sizing.R
+4fa0fea9284213ad9b7cfd657c82c6d7 *R/utils.R
+73e905bb777de64e1082024236238431 *R/widgetid.R
+6e2a1cf81f0637c4eb2dff370aa1e52e *build/vignette.rds
+50cb4cdc3576a6a6c58ce54b48eb7c13 *inst/NEWS
+b0d05e654c9f3175c75491e87233ab47 *inst/doc/develop_advanced.R
+f77a13a750cce7eaec6acc820a49ab4b *inst/doc/develop_advanced.Rmd
+d87c1b7662725c265794bb9bd081ff11 *inst/doc/develop_advanced.html
+ea858a6de2f9809b7e584d806c18d245 *inst/doc/develop_intro.R
+fd0b57315c679845dc5321d0519bfb50 *inst/doc/develop_intro.Rmd
+53f8ce832331080ef3bea7a0f33be524 *inst/doc/develop_intro.html
+32446f6d3b91105f157004b2a7330507 *inst/doc/develop_sizing.Rmd
+64c6307c306fa40ff70dc19e7ad9a4b2 *inst/doc/develop_sizing.html
+6349641ac577c3e0f6459d53600dafff *inst/templates/widget_js.txt
+69d850c68c74097c3a832af2de2e3193 *inst/templates/widget_r.txt
+82172261bc7bdf063eec4fe95f2529e6 *inst/www/htmlwidgets.js
+a03b857226ed22140b03506574ff56d1 *man/JS.Rd
+ce08f3c143431b044b42928528ad0adc *man/createWidget.Rd
+2264197ab32493d53ec0835b1c3d2b6a *man/getDependency.Rd
+e106fffad1042fb001c4e011eba913ee *man/htmlwidgets-package.Rd
+d96c88940eb097f3b4acde673e35a2a2 *man/htmlwidgets-shiny.Rd
+21ed501c2e102abb0dda660d12fabfb2 *man/onRender.Rd
+88bbe83b0ac92022498b14cb8a9417d3 *man/onStaticRenderComplete.Rd
+1282e2416190142eb838368c96c72a21 *man/prependContent.Rd
+e8dac74a46c488354eb077b3fc922029 *man/saveWidget.Rd
+91e926eea50ddf44c1b283b740951241 *man/scaffoldWidget.Rd
+8e9e5e2938fa86fbf2568a4700fd7440 *man/setWidgetIdSeed.Rd
+9702ebdcb96869c2d384a02814f2736f *man/sizingPolicy.Rd
+f77a13a750cce7eaec6acc820a49ab4b *vignettes/develop_advanced.Rmd
+fd0b57315c679845dc5321d0519bfb50 *vignettes/develop_intro.Rmd
+32446f6d3b91105f157004b2a7330507 *vignettes/develop_sizing.Rmd
+41cec90e8b03ec9a2dfcf0d4313201b5 *vignettes/images/sigma.png
diff --git a/NAMESPACE b/NAMESPACE
new file mode 100644
index 0000000..c37ce80
--- /dev/null
+++ b/NAMESPACE
@@ -0,0 +1,22 @@
+# Generated by roxygen2: do not edit by hand
+
+S3method(as.tags,htmlwidget)
+S3method(print,htmlwidget)
+S3method(print,suppress_viewer)
+export(JS)
+export(appendContent)
+export(createWidget)
+export(getDependency)
+export(onRender)
+export(onStaticRenderComplete)
+export(prependContent)
+export(saveWidget)
+export(scaffoldWidget)
+export(setWidgetIdSeed)
+export(shinyRenderWidget)
+export(shinyWidgetOutput)
+export(sizingPolicy)
+import(htmltools)
+importFrom(utils,browseURL)
+importFrom(utils,file.edit)
+importFrom(utils,packageVersion)
diff --git a/R/htmlwidgets.R b/R/htmlwidgets.R
new file mode 100644
index 0000000..5a7ca03
--- /dev/null
+++ b/R/htmlwidgets.R
@@ -0,0 +1,463 @@
+#' @export
+print.htmlwidget <- function(x, ..., view = interactive()) {
+
+  # if we have a viewer then forward viewer pane height (if any)
+  viewer <- getOption("viewer")
+  if (!is.null(viewer)) {
+    viewerFunc <- function(url) {
+
+      # get the requested pane height (it defaults to NULL)
+      paneHeight <- x$sizingPolicy$viewer$paneHeight
+
+      # convert maximize to -1 for compatibility with older versions of rstudio
+      # (newer versions convert 'maximize' to -1 interally, older versions
+      # will simply ignore the height if it's less than zero)
+      if (identical(paneHeight, "maximize"))
+        paneHeight <- -1
+
+      # call the viewer
+      viewer(url, height = paneHeight)
+    }
+  } else {
+    viewerFunc <- utils::browseURL
+  }
+
+  # call html_print with the viewer
+  html_print(htmltools::as.tags(x, standalone=TRUE), viewer = if (view) viewerFunc)
+
+  # return value
+  invisible(x)
+}
+
+#' @export
+print.suppress_viewer <- function(x, ..., view = interactive()) {
+  html_print(htmltools::as.tags(x, standalone=TRUE), viewer = if (view) browseURL)
+  invisible(x)
+}
+
+#' @method as.tags htmlwidget
+#' @export
+as.tags.htmlwidget <- function(x, standalone = FALSE) {
+  toHTML(x, standalone = standalone)
+}
+
+#' Prepend/append extra HTML content to a widget
+#'
+#' Use these functions to attach extra HTML content (primarily JavaScript and/or
+#' CSS styles) to a widget, for rendering in standalone mode (i.e. printing at
+#' the R console) or in a knitr document. These functions are NOT supported when
+#' running in a Shiny widget rendering function, and will result in a warning if
+#' used in that context. Multiple calls are allowed, and later calls do not undo
+#' the effects of previous calls.
+#'
+#' @param x An HTML Widget object
+#' @param ... Valid \link[htmltools]{tags}, text, and/or
+#'   \code{\link[htmltools]{HTML}}, or lists thereof.
+#' @return A modified HTML Widget object.
+#'
+#' @export
+prependContent <- function(x, ...) {
+  x$prepend <- c(x$prepend, list(...))
+  x
+}
+
+#' @rdname prependContent
+#' @export
+appendContent <- function(x, ...) {
+  x$append <- c(x$append, list(...))
+  x
+}
+
+#' Execute custom JavaScript code after rendering
+#'
+#' Use this function to supplement the widget's built-in JavaScript rendering
+#' logic with additional custom JavaScript code, just for this specific widget
+#' object.
+#'
+#' @param x An HTML Widget object
+#' @param jsCode Character vector containing JavaScript code (see Details)
+#' @param data An additional argument to pass to the \code{jsCode} function.
+#'   This can be any R object that can be serialized to JSON. If you have
+#'   multiple objects to pass to the function, use a named list.
+#' @return The modified widget object
+#'
+#' @details The \code{jsCode} parameter must be a valid JavaScript expression
+#'   that returns a function.
+#'
+#'   The function will be invoked with three arguments: the first is the widget's
+#'   main HTML element, and the second is the data to be rendered (the \code{x}
+#'   parameter in \code{createWidget}). The third argument is the JavaScript
+#'   equivalent of the R object passed into \code{onRender} as the \code{data}
+#'   argument; this is an easy way to transfer e.g. data frames without having
+#'   to manually do the JSON encoding.
+#'
+#'   When the function is invoked, the \code{this} keyword will refer to the
+#'   widget instance object.
+#'
+#' @seealso \code{\link{onStaticRenderComplete}}, for writing custom JavaScript
+#'   that involves multiple widgets.
+#'
+#' @examples
+#' \dontrun{
+#' library(leaflet)
+#'
+#' # This example uses browser geolocation. RStudio users:
+#' # this won't work in the Viewer pane; try popping it
+#' # out into your system web browser.
+#' leaflet() %>% addTiles() %>%
+#'   onRender("
+#'     function(el, x) {
+#'       // Navigate the map to the user's location
+#'       this.locate({setView: true});
+#'     }
+#'   ")
+#'
+#'
+#' # This example shows how you can make an R data frame available
+#' # to your JavaScript code.
+#'
+#' meh <- "&#x1F610;";
+#' yikes <- "&#x1F628;";
+#'
+#' df <- data.frame(
+#'   lng = quakes$long,
+#'   lat = quakes$lat,
+#'   html = ifelse(quakes$mag < 5.5, meh, yikes),
+#'   stringsAsFactors = FALSE
+#' )
+#'
+#' leaflet() %>% addTiles() %>%
+#'   fitBounds(min(df$lng), min(df$lat), max(df$lng), max(df$lat)) %>%
+#'   onRender("
+#'     function(el, x, data) {
+#'       for (var i = 0; i < data.lng.length; i++) {
+#'         var icon = L.divIcon({className: '', html: data.html[i]});
+#'         L.marker([data.lat[i], data.lng[i]], {icon: icon}).addTo(this);
+#'       }
+#'     }
+#'   ", data = df)
+#' }
+#'
+#' @export
+onRender <- function(x, jsCode, data = NULL) {
+  addHook(x, "render", jsCode, data)
+}
+
+addHook <- function(x, hookName, jsCode, data = NULL) {
+  if (length(jsCode) == 0)
+    return(x)
+
+  if (length(jsCode) > 1)
+    jsCode <- paste(jsCode, collapse = "\n")
+
+  x$jsHooks[[hookName]] <- c(x$jsHooks[[hookName]], list(list(code = jsCode, data = data)))
+  x
+}
+
+
+toHTML <- function(x, standalone = FALSE, knitrOptions = NULL) {
+
+  sizeInfo <- resolveSizing(x, x$sizingPolicy, standalone = standalone, knitrOptions = knitrOptions)
+
+  if (!is.null(x$elementId))
+    id <- x$elementId
+  else
+    id <- paste("htmlwidget", createWidgetId(), sep="-")
+
+  w <- validateCssUnit(sizeInfo$width)
+  h <- validateCssUnit(sizeInfo$height)
+
+  # create a style attribute for the width and height
+  style <- paste(
+    "width:", w, ";",
+    "height:", h, ";",
+    sep = "")
+
+  x$id <- id
+
+  container <- if (isTRUE(standalone)) {
+    function(x) {
+      div(id="htmlwidget_container", x)
+    }
+  } else {
+    identity
+  }
+
+  html <- htmltools::tagList(
+    container(
+      htmltools::tagList(
+        x$prepend,
+        widget_html(
+          name = class(x)[1],
+          package = attr(x, "package"),
+          id = id,
+          style = style,
+          class = paste(class(x)[1], "html-widget"),
+          width = sizeInfo$width,
+          height = sizeInfo$height
+        ),
+        x$append
+      )
+    ),
+    widget_data(x, id),
+    if (!is.null(sizeInfo$runtime)) {
+      tags$script(type="application/htmlwidget-sizing", `data-for` = id,
+        toJSON(sizeInfo$runtime)
+      )
+    }
+  )
+  html <- htmltools::attachDependencies(html,
+    c(widget_dependencies(class(x)[1], attr(x, 'package')),
+      x$dependencies)
+  )
+
+  htmltools::browsable(html)
+
+}
+
+
+widget_html <- function(name, package, id, style, class, inline = FALSE, ...){
+
+  # attempt to lookup custom html function for widget
+  fn <- tryCatch(get(paste0(name, "_html"),
+                     asNamespace(package),
+                     inherits = FALSE),
+                 error = function(e) NULL)
+
+  # call the custom function if we have one, otherwise create a div
+  if (is.function(fn)) {
+    fn(id = id, style = style, class = class, ...)
+  } else if (inline) {
+    tags$span(id = id, style = style, class = class)
+  } else {
+    tags$div(id = id, style = style, class = class)
+  }
+}
+
+widget_dependencies <- function(name, package){
+  getDependency(name, package)
+}
+
+# Generates a <script type="application/json"> tag with the JSON-encoded data,
+# to be picked up by htmlwidgets.js for static rendering.
+widget_data <- function(x, id, ...){
+  # It's illegal for </script> to appear inside of a script tag, even if it's
+  # inside a quoted string. Fortunately we know that in JSON, the only place
+  # the '<' character can appear is inside a quoted string, where a Unicode
+  # escape has the same effect, without confusing the browser's parser. The
+  # repro for the bug this gsub fixes is to have the string "</script>" appear
+  # anywhere in the data/metadata of a widget--you will get a syntax error
+  # instead of a properly rendered widget.
+  #
+  # Another issue is that if </body></html> appears inside a quoted string,
+  # then when pandoc coverts it with --self-contained, the escaping gets messed
+  # up. There may be other patterns that trigger this behavior, so to be safe
+  # we can replace all instances of "</" with "\\u003c/".
+  payload <- toJSON(createPayload(x))
+  payload <- gsub("</", "\\u003c/", payload, fixed = TRUE)
+  tags$script(type = "application/json", `data-for` = id, HTML(payload))
+}
+
+#' Create an HTML Widget
+#'
+#' Create an HTML widget based on widget YAML and JavaScript contained within
+#' the specified package.
+#'
+#' For additional details on developing widgets, see package vignettes:
+#' \code{vignette("develop_intro", package = "htmlwidgets")}.
+#'
+#' @param name Widget name (should match the base name of the YAML and
+#'   JavaScript files used to implement the widget)
+#' @param x Widget instance data (underlying data to render and options that
+#'   govern how it's rendered). This value will be converted to JSON using
+#'   \code{\link[jsonlite]{toJSON}} and made available to the widget's
+#'   JavaScript \code{renderValue} function.
+#' @param width Fixed width for widget (in css units). The default is
+#'   \code{NULL}, which results in intelligent automatic sizing based on the
+#'   widget's container.
+#' @param height Fixed height for widget (in css units). The default is
+#'   \code{NULL}, which results in intelligent automatic sizing based on the
+#'   widget's container.
+#' @param sizingPolicy Options that govern how the widget is sized in various
+#'   containers (e.g. a standalone browser, the RStudio Viewer, a knitr figure,
+#'   or a Shiny output binding). These options can be specified by calling the
+#'   \code{\link{sizingPolicy}} function.
+#' @param package Package where the widget is defined (defaults to the widget
+#'   name).
+#' @param dependencies Additional widget HTML dependencies (over and above those
+#'   defined in the widget YAML). This is useful for dynamic dependencies that
+#'   only exist when selected widget options are enabled (e.g. sets of map tiles
+#'   or projections).
+#' @param elementId Use an explicit element ID for the widget (rather than an
+#'   automatically generated one). Useful if you have other JavaScript that
+#'   needs to explicitly discover and interact with a specific widget instance.
+#' @param preRenderHook A function to be run on the widget, just prior to
+#'   rendering. It accepts the entire widget object as input, and should return
+#'   a modified widget object.
+#'
+#' @return An object of class \code{htmlwidget} that will intelligently print
+#'   itself into HTML in a variety of contexts including the R console, within R
+#'   Markdown documents, and within Shiny output bindings.
+#' @export
+createWidget <- function(name,
+                         x,
+                         width = NULL,
+                         height = NULL,
+                         sizingPolicy = htmlwidgets::sizingPolicy(),
+                         package = name,
+                         dependencies = NULL,
+                         elementId = NULL,
+                         preRenderHook = NULL) {
+  # Turn single dependency object into list of dependencies, if necessary
+  if (inherits(dependencies, "html_dependency"))
+    dependencies <- list(dependencies)
+  structure(
+    list(x = x,
+         width = width,
+         height = height,
+         sizingPolicy = sizingPolicy,
+         dependencies = dependencies,
+         elementId = elementId,
+         preRenderHook = preRenderHook,
+         jsHooks = list()),
+    class = c(name,
+              if (sizingPolicy$viewer$suppress) "suppress_viewer",
+              "htmlwidget"),
+    package = package
+  )
+}
+
+
+#' Shiny bindings for HTML widgets
+#'
+#' Helpers to create output and render functions for using HTML widgets within
+#' Shiny applications and interactive Rmd documents.
+#'
+#' @param outputId output variable to read from
+#' @param name Name of widget to create output binding for
+#' @param width,height Must be a valid CSS unit (like \code{"100\%"},
+#'   \code{"400px"}, \code{"auto"}) or a number, which will be coerced to a
+#'   string and have \code{"px"} appended.
+#' @param package Package containing widget (defaults to \code{name})
+#' @param inline use an inline (\code{span()}) or block container (\code{div()})
+#' for the output
+#' @param outputFunction Shiny output function corresponding to this render
+#'   function.
+#' @param expr An expression that generates an HTML widget
+#' @param env The environment in which to evaluate \code{expr}.
+#' @param quoted Is \code{expr} a quoted expression (with \code{quote()})? This
+#'   is useful if you want to save an expression in a variable.
+#'
+#' @return An output or render function that enables the use of the widget
+#'   within Shiny applications.
+#'
+#' @details These functions are delegated to from within your widgets own shiny
+#'   output and render functions. The delegation is boilerplate and always works
+#'   the same for all widgets (see example below).
+#'
+#' @examples
+#' # shiny output binding for a widget named 'foo'
+#' fooOutput <- function(outputId, width = "100%", height = "400px") {
+#'   htmlwidgets::shinyWidgetOutput(outputId, "foo", width, height)
+#' }
+#'
+#' # shiny render function for a widget named 'foo'
+#' renderFoo <- function(expr, env = parent.frame(), quoted = FALSE) {
+#'   if (!quoted) { expr <- substitute(expr) } # force quoted
+#'   htmlwidgets::shinyRenderWidget(expr, fooOutput, env, quoted = TRUE)
+#' }
+#' @name htmlwidgets-shiny
+#'
+#' @export
+shinyWidgetOutput <- function(outputId, name, width, height, package = name,
+                              inline = FALSE) {
+
+  checkShinyVersion()
+  # generate html
+  html <- htmltools::tagList(
+    widget_html(name, package, id = outputId,
+      class = paste(name, "html-widget html-widget-output"),
+      style = sprintf("width:%s; height:%s; %s",
+        htmltools::validateCssUnit(width),
+        htmltools::validateCssUnit(height),
+        if (inline) "display: inline-block;" else ""
+      ), width = width, height = height
+    )
+  )
+
+  # attach dependencies
+  dependencies = widget_dependencies(name, package)
+  htmltools::attachDependencies(html, dependencies)
+}
+
+
+#' @rdname htmlwidgets-shiny
+#' @export
+shinyRenderWidget <- function(expr, outputFunction, env, quoted) {
+
+  checkShinyVersion()
+  # generate a function for the expression
+  func <- shiny::exprToFunction(expr, env, quoted)
+
+  # create the render function
+  renderFunc <- function() {
+    instance <- func()
+    if (!is.null(instance$elementId)) {
+      warning("Ignoring explicitly provided widget ID \"",
+        instance$elementId, "\"; Shiny doesn't use them"
+      )
+    }
+
+    # We don't support prependContent/appendContent in dynamic Shiny contexts
+    # because the Shiny equivalent of onStaticRenderComplete is unclear. If we
+    # ever figure that out it would be great to support it. One possibility
+    # would be to have a dedicated property for "post-render customization JS",
+    # I suppose. In any case, it's less of a big deal for Shiny since there are
+    # other mechanisms (that are at least as natural) for putting custom JS in a
+    # Shiny app.
+    if (!is.null(instance$prepend)) {
+      warning("Ignoring prepended content; prependContent can't be used in a ",
+        "Shiny render call")
+    }
+    if (!is.null(instance$append)) {
+      warning("Ignoring appended content; appendContent can't be used in a ",
+        "Shiny render call")
+    }
+
+    deps <- .subset2(instance, "dependencies")
+    deps <- lapply(
+      htmltools::resolveDependencies(deps),
+      shiny::createWebDependency
+    )
+    payload <- c(createPayload(instance), list(deps = deps))
+    toJSON(payload)
+  }
+
+  # mark it with the output function so we can use it in Rmd files
+  shiny::markRenderFunction(outputFunction, renderFunc)
+}
+
+checkShinyVersion <- function(error = TRUE) {
+  x <- utils::packageDescription('htmlwidgets', fields = 'Enhances')
+  r <- '^.*?shiny \\(>= ([0-9.]+)\\).*$'
+  if (is.na(x) || length(grep(r, x)) == 0 || system.file(package = 'shiny') == '')
+    return()
+  v <- gsub(r, '\\1', x)
+  f <- if (error) stop else packageStartupMessage
+  if (utils::packageVersion('shiny') < v)
+    f("Please upgrade the 'shiny' package to (at least) version ", v)
+}
+
+# Helper function to create payload
+createPayload <- function(instance){
+  if (!is.null(instance$preRenderHook)){
+    instance <- instance$preRenderHook(instance)
+    instance$preRenderHook <- NULL
+  }
+  x <- .subset2(instance, "x")
+  list(x = x, evals = JSEvals(x), jsHooks = instance$jsHooks)
+}
+
+# package globals
+.globals <- new.env(parent = emptyenv())
+
diff --git a/R/imports.R b/R/imports.R
new file mode 100644
index 0000000..0f3a24f
--- /dev/null
+++ b/R/imports.R
@@ -0,0 +1,5 @@
+#' @import htmltools
+NULL
+
+#' @importFrom utils browseURL file.edit packageVersion
+NULL
diff --git a/R/knitr-methods.R b/R/knitr-methods.R
new file mode 100644
index 0000000..a1a108d
--- /dev/null
+++ b/R/knitr-methods.R
@@ -0,0 +1,44 @@
+# Reusable function for registering a set of methods with S3 manually. The
+# methods argument is a list of character vectors, each of which has the form
+# c(package, genname, class).
+registerMethods <- function(methods) {
+  lapply(methods, function(method) {
+    pkg <- method[[1]]
+    generic <- method[[2]]
+    class <- method[[3]]
+    func <- get(paste(generic, class, sep="."))
+    if (pkg %in% loadedNamespaces()) {
+      registerS3method(generic, class, func, envir = asNamespace(pkg))
+    }
+    setHook(
+      packageEvent(pkg, "onLoad"),
+      function(...) {
+        registerS3method(generic, class, func, envir = asNamespace(pkg))
+      }
+    )
+  })
+}
+
+.onLoad <- function(...) {
+  # htmlwidgets provides methods for knitr::knit_print, but knitr isn't a Depends or
+  # Imports of htmltools, only an Enhances. Therefore, the NAMESPACE file has to
+  # declare it as an export, not an S3method. That means that R will only know to
+  # use our methods if htmlwidgets is actually attached, i.e., you have to use
+  # library(htmlwidgets) in a knitr document or else you'll get escaped HTML in your
+  # document. This code snippet manually registers our method(s) with S3 once both
+  # htmlwidgets and knitr are loaded.
+  registerMethods(list(
+    # c(package, genname, class)
+    c("knitr", "knit_print", "htmlwidget")
+  ))
+}
+
+.onAttach <- function(...) {
+  # warn if the version of shiny is lower than what was specified in DESCRIPTION
+  checkShinyVersion(error = FALSE)
+}
+
+knit_print.htmlwidget <- function(x, ..., options = NULL) {
+  knitr::knit_print(toHTML(x, standalone = FALSE, knitrOptions = options), options = options,  ...)
+}
+
diff --git a/R/pandoc.R b/R/pandoc.R
new file mode 100644
index 0000000..d702ffc
--- /dev/null
+++ b/R/pandoc.R
@@ -0,0 +1,243 @@
+
+pandoc_available <- function(version = NULL) {
+
+  # ensure we've scanned for pandoc
+  find_pandoc()
+
+  # check availability
+  if (!is.null(.pandoc$dir))
+    if (!is.null(version))
+      .pandoc$version >= version
+  else
+    TRUE
+  else
+    FALSE
+}
+
+pandoc_self_contained_html <- function(input, output) {
+
+  # make input file path absolute
+  input <- normalizePath(input)
+
+  # ensure output file exists and make it's path absolute
+  if (!file.exists(output))
+    file.create(output)
+  output <- normalizePath(output)
+
+  # create a simple body-only template
+  template <- tempfile(fileext = ".html")
+  writeLines("$body$", template)
+
+  # convert from markdown to html to get base64 encoding
+  # (note there is no markdown in the source document but
+  # we still need to do this "conversion" to get the
+  # base64 encoding)
+  pandoc_convert(
+    input = input,
+    from = "markdown",
+    output = output,
+    options = c(
+      "--self-contained",
+      "--template", template
+    )
+  )
+
+  invisible(output)
+}
+
+
+pandoc_convert <- function(input,
+                           to = NULL,
+                           from = NULL,
+                           output = NULL,
+                           citeproc = FALSE,
+                           options = NULL,
+                           verbose = FALSE,
+                           wd = NULL) {
+
+  # ensure we've scanned for pandoc
+  find_pandoc()
+
+  # execute in specified working directory
+  if (is.null(wd)) {
+    wd <- base_dir(input)
+  }
+  oldwd <- setwd(wd)
+  on.exit(setwd(oldwd), add = TRUE)
+
+
+  # input file and formats
+  args <- c(input)
+  if (!is.null(to))
+    args <- c(args, "--to", to)
+  if (!is.null(from))
+    args <- c(args, "--from", from)
+
+  #  output file
+  if (!is.null(output))
+    args <- c(args, "--output", output)
+
+  # additional command line options
+  args <- c(args, options)
+
+  # set pandoc stack size
+  stack_size <- getOption("pandoc.stack.size", default = "512m")
+  args <- c(c("+RTS", paste0("-K", stack_size), "-RTS"), args)
+
+  # build the conversion command
+  command <- paste(quoted(pandoc()), paste(quoted(args), collapse = " "))
+
+  # show it in verbose mode
+  if (verbose)
+    cat(command, "\n")
+
+  # run the conversion
+  with_pandoc_safe_environment({
+    result <- system(command)
+  })
+  if (result != 0)
+    stop("pandoc document conversion failed with error ", result, call. = FALSE)
+
+  invisible(NULL)
+}
+
+# get the path to the pandoc binary
+pandoc <- function() {
+  find_pandoc()
+  file.path(.pandoc$dir, "pandoc")
+}
+
+# Scan for a copy of pandoc and set the internal cache if it's found.
+find_pandoc <- function() {
+
+  if (is.null(.pandoc$dir)) {
+
+    # define potential sources
+    sys_pandoc <- Sys.which("pandoc")
+    sources <- c(Sys.getenv("RSTUDIO_PANDOC"),
+                 ifelse(nzchar(sys_pandoc), dirname(sys_pandoc), ""))
+    if (!is_windows())
+      sources <- c(sources, path.expand("~/opt/pandoc"))
+
+    # determine the versions of the sources
+    versions <- lapply(sources, function(src) {
+      if (file.exists(src))
+        get_pandoc_version(src)
+      else
+        numeric_version("0")
+    })
+
+    # find the maximum version
+    found_src <- NULL
+    found_ver <- numeric_version("0")
+    for (i in 1:length(sources)) {
+      ver <- versions[[i]]
+      if (ver > found_ver) {
+        found_ver <- ver
+        found_src <- sources[[i]]
+      }
+    }
+
+    # did we find a version?
+    if (!is.null(found_src)) {
+      .pandoc$dir <- found_src
+      .pandoc$version <- found_ver
+    }
+  }
+}
+
+# wrap a system call to pandoc so that LC_ALL is not set
+# see: https://github.com/rstudio/rmarkdown/issues/31
+# see: https://ghc.haskell.org/trac/ghc/ticket/7344
+with_pandoc_safe_environment <- function(code) {
+  lc_all <- Sys.getenv("LC_ALL", unset = NA)
+  if (!is.na(lc_all)) {
+    Sys.unsetenv("LC_ALL")
+    on.exit(Sys.setenv(LC_ALL = lc_all), add = TRUE)
+  }
+  lc_ctype <- Sys.getenv("LC_CTYPE", unset = NA)
+  if (!is.na(lc_ctype)) {
+    Sys.unsetenv("LC_CTYPE")
+    on.exit(Sys.setenv(LC_CTYPE = lc_ctype), add = TRUE)
+  }
+  if (Sys.info()['sysname'] == "Linux" &&
+      is.na(Sys.getenv("HOME", unset = NA))) {
+    stop("The 'HOME' environment variable must be set before running Pandoc.")
+  }
+  if (Sys.info()['sysname'] == "Linux" &&
+      is.na(Sys.getenv("LANG", unset = NA))) {
+    # fill in a the LANG environment variable if it doesn't exist
+    Sys.setenv(LANG=detect_generic_lang())
+    on.exit(Sys.unsetenv("LANG"), add = TRUE)
+  }
+  if (Sys.info()['sysname'] == "Linux" &&
+      identical(Sys.getenv("LANG"), "en_US")) {
+    Sys.setenv(LANG="en_US.UTF-8")
+    on.exit(Sys.setenv(LANG="en_US"), add = TRUE)
+  }
+  force(code)
+}
+
+
+# if there is no LANG environment variable set pandoc is going to hang so
+# we need to specify a "generic" lang setting. With glibc >= 2.13 you can
+# specify C.UTF-8 so we prefer that. If we can't find that then we fall back
+# to en_US.UTF-8.
+detect_generic_lang <- function() {
+
+  locale_util <- Sys.which("locale")
+
+  if (nzchar(locale_util)) {
+    locales <- system(paste(locale_util, "-a"), intern = TRUE)
+    locales <- suppressWarnings(
+      strsplit(locales, split = "\n", fixed = TRUE)
+    )
+    if ("C.UTF-8" %in% locales)
+      return ("C.UTF-8")
+  }
+
+  # default to en_US.UTF-8
+  "en_US.UTF-8"
+}
+
+# quote args if they need it
+quoted <- function(args) {
+  spaces <- grepl(' ', args, fixed=TRUE)
+  args[spaces] <- shQuote(args[spaces])
+  args
+}
+
+# Find common base directory, throw error if it doesn't exist
+base_dir <- function(x) {
+  abs <- vapply(x, tools::file_path_as_absolute, character(1))
+
+  base <- unique(dirname(abs))
+  if (length(base) > 1) {
+    stop("Input files not all in same directory, please supply explicit wd",
+         call. = FALSE)
+  }
+
+  base
+}
+
+# Get an S3 numeric_version for the pandoc utility at the specified path
+get_pandoc_version <- function(pandoc_dir) {
+  pandoc_path <- file.path(pandoc_dir, "pandoc")
+  with_pandoc_safe_environment({
+    version_info <- system(paste(shQuote(pandoc_path), "--version"),
+                           intern = TRUE)
+  })
+  version <- strsplit(version_info, "\n")[[1]][1]
+  version <- strsplit(version, " ")[[1]][2]
+  numeric_version(version)
+}
+
+is_windows <- function() {
+  identical(.Platform$OS.type, "windows")
+}
+
+# Environment used to cache the current pandoc directory and version
+.pandoc <- new.env()
+.pandoc$dir <- NULL
+.pandoc$version <- NULL
+
diff --git a/R/savewidget.R b/R/savewidget.R
new file mode 100644
index 0000000..d19cc66
--- /dev/null
+++ b/R/savewidget.R
@@ -0,0 +1,44 @@
+#' Save a widget to an HTML file
+#'
+#' Save a rendered widget to an HTML file (e.g. for sharing with others).
+#'
+#' @param widget Widget to save
+#' @param file File to save HTML into
+#' @param selfcontained Whether to save the HTML as a single self-contained file
+#'   (with external resources base64 encoded) or a file with external resources
+#'   placed in an adjacent directory.
+#' @param libdir Directory to copy HTML dependencies into (defaults to
+#'   filename_files).
+#' @param background Text string giving the html background color of the widget.
+#'   Defaults to white.
+#' @param knitrOptions A list of \pkg{knitr} chunk options.
+#' @export
+saveWidget <- function(widget, file, selfcontained = TRUE, libdir = NULL,
+                       background = "white", knitrOptions = list()) {
+
+  # convert to HTML tags
+  html <- toHTML(widget, standalone = TRUE, knitrOptions = knitrOptions)
+
+  # form a path for dependenent files
+  if (is.null(libdir)){
+    libdir <- paste(tools::file_path_sans_ext(basename(file)), "_files",
+      sep = "")
+  }
+
+  # save the file
+  htmltools::save_html(html, file = file, libdir = libdir, background=background)
+
+  # make it self-contained if requested
+  if (selfcontained) {
+
+    if (!pandoc_available()) {
+      stop("Saving a widget with selfcontained = TRUE requires pandoc. For details see:\n",
+           "https://github.com/rstudio/rmarkdown/blob/master/PANDOC.md")
+    }
+
+    pandoc_self_contained_html(file, file)
+    unlink(libdir, recursive = TRUE)
+  }
+
+  invisible(NULL)
+}
diff --git a/R/scaffold.R b/R/scaffold.R
new file mode 100644
index 0000000..d31c3c1
--- /dev/null
+++ b/R/scaffold.R
@@ -0,0 +1,193 @@
+#' Create implementation scaffolding for an HTML widget
+#'
+#' Add the minimal code required to implement an HTML widget to an R package.
+#'
+#' @param name Name of widget
+#' @param bowerPkg Optional name of \href{http://bower.io/}{Bower} package upon
+#'   which this widget is based. If you specify this parameter then bower will
+#'   be used to automatically download the widget's source code and dependencies
+#'   and add them to the widget's YAML.
+#' @param edit Automatically open the widget's JavaScript source file after
+#'   creating the scaffolding.
+#'
+#' @note This function must be executed from the root directory of the package
+#'   you wish to add the widget to.
+#'
+#' @export
+scaffoldWidget <- function(name, bowerPkg = NULL, edit = interactive()){
+  if (!file.exists('DESCRIPTION')){
+    stop(
+      "You need to create a package to house your widget first!",
+      call. = F
+    )
+  }
+  if (!file.exists('inst')){
+    dir.create('inst')
+  }
+  package = read.dcf('DESCRIPTION')[[1,"Package"]]
+  addWidgetConstructor(name, package, edit)
+  addWidgetYAML(name, bowerPkg, edit)
+  addWidgetJS(name, edit)
+}
+
+addWidgetConstructor <- function(name, package, edit){
+  tpl <- paste(readLines(
+    system.file('templates/widget_r.txt', package = 'htmlwidgets')
+  ), collapse = "\n")
+
+  capName = function(name){
+    paste0(toupper(substring(name, 1, 1)), substring(name, 2))
+  }
+  if (!file.exists(file_ <- sprintf("R/%s.R", name))){
+    cat(
+      sprintf(tpl, name, name, package, name, name, name, name, name, name,
+         package, name, capName(name), name),
+      file = file_
+    )
+    message('Created boilerplate for widget constructor ', file_)
+  } else {
+    message(file_, " already exists")
+  }
+  if (edit) fileEdit(file_)
+}
+
+addWidgetYAML <- function(name, bowerPkg, edit){
+  tpl <- "# (uncomment to add a dependency)
+# dependencies:
+#  - name:
+#    version:
+#    src:
+#    script:
+#    stylesheet:
+"
+  if (!file.exists('inst/htmlwidgets')){
+    dir.create('inst/htmlwidgets')
+  }
+  if (!is.null(bowerPkg)){
+    installBowerPkg(bowerPkg)
+    tpl <- getConfig(bowerPkg)
+  }
+  if (!file.exists(file_ <- sprintf('inst/htmlwidgets/%s.yaml', name))){
+    cat(tpl, file = file_)
+    message('Created boilerplate for widget dependencies at ',
+      sprintf('inst/htmlwidgets/%s.yaml', name)
+    )
+  } else {
+    message(file_, " already exists")
+  }
+  if (edit) fileEdit(file_)
+}
+
+addWidgetJS <- function(name, edit){
+  tpl <- paste(readLines(
+    system.file('templates/widget_js.txt', package = 'htmlwidgets')
+  ), collapse = "\n")
+
+  if (!file.exists(file_ <- sprintf('inst/htmlwidgets/%s.js', name))){
+    cat(sprintf(tpl, name), file = file_)
+    message('Created boilerplate for widget javascript bindings at ',
+      sprintf('inst/htmlwidgets/%s.js', name)
+    )
+  } else {
+    message(file_, " already exists")
+  }
+  if (edit) fileEdit(file_)
+}
+
+# Install bower package to inst/htmlwidgets/lib
+#
+# This function uses bower to install a javascript package along with
+# its dependencies.
+installBowerPkg <- function(pkg){
+  # check if bower is installed
+  if (findBower() == ""){
+    stop(
+      "Please install bower from http://bower.io",
+      call. = FALSE
+    )
+  }
+  #check if we are in the root directory of a package
+  if (!file.exists('DESCRIPTION')){
+    stop("You need to be in a package directory to run this!",
+      call. = F)
+  }
+  # set up .bowerrc to install packages to correct directory
+  if (!file.exists('.bowerrc')){
+    x = '{"directory": "inst/htmlwidgets/lib"}'
+    cat(x, file = '.bowerrc')
+  }
+  # Install package
+  message("Installing ", pkg, " using bower...", "\n\n")
+  cmd <- sprintf('%s install %s', findBower(), pkg)
+  system(cmd)
+  message("... Done! installing ", pkg)
+}
+
+# Try really hard to find bower in Windows
+findBower <- function(){
+  # a slightly more robust finder of bower for windows
+  # which does not require PATH environment variable to be set
+  bowerPath = if(Sys.which("bower") == "") {
+    # if it does not find Sys.which('bower')
+    # also check APPDATA to see if found there
+    if(identical(.Platform$OS.type,"windows")) {
+      Sys.which(file.path(Sys.getenv("APPDATA"),"npm","bower."))
+    }
+  } else {
+    Sys.which("bower")
+  }
+  return(bowerPath)
+}
+
+# Read the bower.json file
+readBower <- function(pkg, src = "inst/htmlwidgets/lib"){
+  bower = jsonlite::fromJSON(
+    file.path(src, pkg, 'bower.json')
+  )
+  spec = list(
+    name = basename(bower$name),
+    version = bower$version,
+    src = paste0('htmlwidgets/lib/', pkg),
+    script = getMinified(
+      bower$main[grepl('^.*\\.js$', bower$main)], basename(bower$name)
+    ),
+    style = getMinified(
+      bower$main[grepl('^.*\\.css$', bower$main)], basename(bower$name)
+    )
+  )
+  deps = bower$dependencies
+  spec = Filter(function(x) length(x) != 0, spec)
+  list(spec = spec, deps = deps)
+}
+
+# Get YAML configuration for widget
+getConfig <- function(pkg, src = "inst/htmlwidgets/lib"){
+  deps = readBower(pkg, src)$deps
+  all = c(names(deps),pkg)
+  config = lapply(all, function(pkg){
+    readBower(pkg, src = src)$spec
+  })
+  yaml::as.yaml(list(dependencies = config))
+}
+
+# Replace dependency with minified version if it exists
+getMinified <- function(x, name, src = 'inst/htmlwidgets/lib'){
+  xFile = file.path(src, name, x)
+  ext = tools::file_ext(xFile)
+  minFile = paste0(tools::file_path_sans_ext(xFile), '.min.', ext)
+  sapply(seq_along(x), function(i){
+    if (file.exists(minFile[i])) {
+      file.path(dirname(x[i]), basename(minFile[i]))
+    } else {
+      x[i]
+    }
+  })
+}
+
+# invoke file.edit in a way that will bind to the RStudio editor
+# when running inside RStudio
+fileEdit <- function(file) {
+  fileEditFunc <- eval(parse(text = "file.edit"), envir = globalenv())
+  fileEditFunc(file)
+}
+
diff --git a/R/seed.R b/R/seed.R
new file mode 100644
index 0000000..e69de29
diff --git a/R/sizing.R b/R/sizing.R
new file mode 100644
index 0000000..6692b99
--- /dev/null
+++ b/R/sizing.R
@@ -0,0 +1,226 @@
+#' Create a widget sizing policy
+#'
+#' Define the policy by which HTML widgets will be sized in various containers
+#' (e.g. Browser, RStudio Viewer, R Markdown, Shiny). Note that typically
+#' widgets can accept the default sizing policy (or override only one or two
+#' aspects of it) and get satisfactory sizing behavior via the automatic sizing
+#' logic built into the htmlwidgets framework (see the notes below for the most
+#' typical exceptions to this).
+#'
+#' @param defaultWidth The default width used to display the widget. This
+#'   parameter specifies the default width for viewing in all contexts (browser,
+#'   viewer, and knitr) unless it is specifically overridden with e.g.
+#'   \code{browser.defaultWidth}.
+#' @param viewer.defaultWidth The default width used to display the widget
+#'   within the RStudio Viewer.
+#' @param browser.defaultWidth The default width used to display the widget
+#'   within a standalone web browser.
+#' @param knitr.defaultWidth The default width used to display the widget within
+#'   documents generated by knitr (e.g. R Markdown).
+#' @param defaultHeight The default height used to display the widget. This
+#'   parameter specifies the default height for viewing in all contexts
+#'   (browser, viewer, and knitr) unless it is specifically overridden with e.g.
+#'   \code{browser.defaultHeight}.
+#' @param viewer.defaultHeight The default height used to display the widget
+#'   within the RStudio Viewer.
+#' @param browser.defaultHeight The default height used to display the widget
+#'   within a standalone web browser.
+#' @param knitr.defaultHeight The default height used to display the widget
+#'   within documents generated by knitr (e.g. R Markdown).
+#' @param padding Padding around the widget (in pixels). This parameter
+#'   specifies the padding for viewing in all contexts (browser and viewer)
+#'   unless it is specifically overriden by e.g. \code{browser.padding}.
+#' @param browser.padding Padding around the widget when displayed in a
+#'   standalone browser (defaults to 40 pixels).
+#' @param viewer.padding Padding around the widget when displayed in the RStudio
+#'   Viewer (defaults to 15 pixels).
+#' @param viewer.fill When displayed in the RStudio Viewer, automatically size
+#'   the widget to the viewer dimensions (note that \code{viewer.padding} is
+#'   still applied). Default to \code{TRUE}.
+#' @param browser.fill When displayed in a standalone web browser, automatically
+#'   size the widget to the browser dimensions (note that \code{browser.padding}
+#'   is still applied). Defaults to \code{FALSE}.
+#' @param viewer.paneHeight Request that the RStudio Viewer be forced to a
+#'   specific height when displaying this widget.
+#' @param viewer.suppress Never display the widget within the RStudio Viewer
+#'   (useful for widgets that require a large amount of space for rendering).
+#'   Defaults to \code{FALSE}.
+#' @param knitr.figure Apply the default knitr fig.width and fig.height to the
+#'   widget when it's rendered within R Markdown documents. Defaults to
+#'   \code{TRUE}.
+#'
+#' @return A widget sizing policy
+#'
+#' @details
+#'
+#' The default HTML widget sizing policy treats the widget with the same sizing
+#' semantics as an R plot. When printed at the R console the widget is displayed
+#' within the RStudio Viewer and sized to fill the Viewer pane (modulo any
+#' padding). When rendered inside an R Markdown document the widget is sized
+#' based on the default size of figures in the document.
+#'
+#' You might need to change the default behavior if your widget is extremely
+#' large. In this case you might specify \code{viewer.suppress = TRUE} and
+#' \code{knitr.figure = FALSE} as well provide for a larger default width and
+#' height for knitr.
+#'
+#' You also might need to change the default behavior if you widget already
+#' incorporates padding. In this case you might specify \code{viewer.padding =
+#' 0}.
+#'
+#' For additional details on widget sizing:
+#'
+#' \code{vignette("develop_sizing", package = "htmlwidgets")}
+#'
+#'
+#' @export
+sizingPolicy <- function(
+  defaultWidth = NULL, defaultHeight = NULL, padding = NULL,
+  viewer.defaultWidth = NULL, viewer.defaultHeight = NULL,
+  viewer.padding = NULL, viewer.fill = TRUE, viewer.suppress = FALSE,
+  viewer.paneHeight = NULL,
+  browser.defaultWidth = NULL, browser.defaultHeight = NULL,
+  browser.padding = NULL, browser.fill = FALSE,
+  knitr.defaultWidth = NULL, knitr.defaultHeight = NULL,
+  knitr.figure = TRUE) {
+
+  list(
+    defaultWidth = defaultWidth,
+    defaultHeight = defaultHeight,
+    padding = padding,
+    viewer = list(
+      defaultWidth = viewer.defaultWidth,
+      defaultHeight = viewer.defaultHeight,
+      padding = viewer.padding,
+      fill = viewer.fill,
+      suppress = viewer.suppress,
+      paneHeight = viewer.paneHeight
+    ),
+    browser = list(
+      defaultWidth = browser.defaultWidth,
+      defaultHeight = browser.defaultHeight,
+      padding = browser.padding,
+      fill = browser.fill
+    ),
+    knitr = list(
+      defaultWidth = knitr.defaultWidth,
+      defaultHeight = knitr.defaultHeight,
+      figure = knitr.figure
+    )
+  )
+}
+
+
+DEFAULT_WIDTH <- 960
+DEFAULT_HEIGHT <- 500
+DEFAULT_PADDING <- 40
+DEFAULT_WIDTH_VIEWER <- 450
+DEFAULT_HEIGHT_VIEWER <- 350
+DEFAULT_PADDING_VIEWER <- 15
+
+#' Resolve widget sizing policy
+#'
+#' Take a widget object and sizing policy, and some other contextual details,
+#' and figure out what width/height to use, if possible. Some decisions may need
+#' to be deferred until runtime; include any metadata that's needed for that
+#' decision in the result as well.
+#'
+#' @param x The widget object whose size is to be determined. It may have $width
+#'   and $height directly on it, which means we should obey those.
+#' @param sp The sizing policy to use.
+#' @param standalone Logical value indicating whether the widget is being
+#'   rendered in a standalone context (where it's the only thing on the page;
+#'   this is usually via `print.htmlwidget()`).
+#' @param knitrOptions Object representing the knitr options passed to us via
+#'   `knit_print`. If we're not doing a `knit_print` right now, then the value
+#'   should be `NULL`.
+#' @return A list that is guaranteed to have `width` and `height` values, each of
+#'   which is either a number or CSS unit string. If `standalone=TRUE` then the
+#'   list will also have a `runtime` value that is a list, that contains two
+#'   nested lists `viewer` and `browser`. Each of those in turn has `width`,
+#'   `height`, `padding` (between 1 and 4 numbers), and `fill` (`TRUE`/`FALSE`).
+#' @keywords internal
+#' @examples
+#' x <- list(
+#'   sizingPolicy = list(
+#'     defaultWidth = 800,
+#'     defaultHeight = 500,
+#'     padding = 15,
+#'     viewer = list(
+#'       fill = TRUE,
+#'       padding = 0
+#'     ),
+#'     browser = list(
+#'       fill = FALSE,
+#'       defaultWidth = 960,
+#'       defaultHeight = 600,
+#'       padding = 20
+#'     ),
+#'     knitr = list(
+#'       # Actually knitr$defaultWidth and knitr$defaultHeight
+#'       # are ignored if figure = TRUE
+#'       defaultWidth = 800,
+#'       defaultHeight = 600,
+#'       figure = TRUE
+#'     )
+#'   )
+#' )
+#'
+#' # Sizing for standalone mode
+#' str(resolveSizing(x, x$sizingPolicy, TRUE, NULL))
+#' # Sizing for knitr
+#' str(resolveSizing(x, x$sizingPolicy, FALSE,
+#'   list(out.width.px = 150, out.height.px = 100)))
+#'
+#' # Explicit width/height provided by user--overrides any
+#' # default width/height
+#' x$width <- 300
+#' x$height <- 250
+#' str(resolveSizing(x, x$sizingPolicy, FALSE,
+#'   list(out.width.px = 150, out.height.px = 100)))
+#' @keywords internal
+#' @noRd
+resolveSizing <- function(x, sp, standalone, knitrOptions = NULL) {
+  if (isTRUE(standalone)) {
+    userSized <- !is.null(x$width) || !is.null(x$height)
+    viewerScopes <- list(sp$viewer, sp)
+    browserScopes <- list(sp$browser, sp)
+    # Precompute the width, height, padding, and fill for each scenario.
+    return(list(
+      runtime = list(
+        viewer = list(
+          width = x$width %||% any_prop(viewerScopes, "defaultWidth") %||% DEFAULT_WIDTH_VIEWER,
+          height = x$height %||% any_prop(viewerScopes, "defaultHeight") %||% DEFAULT_HEIGHT_VIEWER,
+          padding = any_prop(viewerScopes, "padding") %||% DEFAULT_PADDING_VIEWER,
+          fill = !userSized && any_prop(viewerScopes, "fill") %||% TRUE
+        ),
+        browser = list(
+          width = x$width %||% any_prop(browserScopes, "defaultWidth") %||% DEFAULT_WIDTH,
+          height = x$height %||% any_prop(browserScopes, "defaultHeight") %||% DEFAULT_HEIGHT,
+          padding = any_prop(browserScopes, "padding") %||% DEFAULT_PADDING,
+          fill = !userSized && any_prop(browserScopes, "fill") %||% FALSE
+        )
+      ),
+      width = x$width %||% prop(sp, "defaultWidth") %||% DEFAULT_WIDTH,
+      height = x$height %||% prop(sp, "defaultHeight") %||% DEFAULT_HEIGHT
+    ))
+  } else if (!is.null(knitrOptions)) {
+    knitrScopes <- list(sp$knitr, sp)
+    isFigure <- any_prop(knitrScopes, "figure")
+    figWidth <- if (isFigure) knitrOptions$out.width.px else NULL
+    figHeight <- if (isFigure) knitrOptions$out.height.px else NULL
+    # Compute the width and height
+    return(list(
+      width = x$width %||% figWidth %||% any_prop(knitrScopes, "defaultWidth") %||% DEFAULT_WIDTH,
+      height = x$height %||% figHeight %||% any_prop(knitrScopes, "defaultHeight") %||% DEFAULT_HEIGHT
+    ))
+  } else {
+    # Some non-knitr, non-print scenario.
+    # Just resolve the width/height vs. defaultWidth/defaultHeight
+    return(list(
+      width = x$width %||% prop(sp, "defaultWidth") %||% DEFAULT_WIDTH,
+      height = x$height %||% prop(sp, "defaultHeight") %||% DEFAULT_HEIGHT
+    ))
+  }
+}
+
diff --git a/R/utils.R b/R/utils.R
new file mode 100644
index 0000000..4cd2a8a
--- /dev/null
+++ b/R/utils.R
@@ -0,0 +1,218 @@
+# Copied from shiny 0.14.2
+toJSON2 <- function(
+  x, ...,  dataframe = "columns", null = "null", na = "null", auto_unbox = TRUE,
+  digits = getOption("shiny.json.digits", 16), use_signif = TRUE, force = TRUE,
+  POSIXt = "ISO8601", UTC = TRUE, rownames = FALSE, keep_vec_names = TRUE,
+  strict_atomic = TRUE
+) {
+  if (strict_atomic) x <- I(x)
+  jsonlite::toJSON(
+    x, dataframe = dataframe, null = null, na = na, auto_unbox = auto_unbox,
+    digits = digits, use_signif = use_signif, force = force, POSIXt = POSIXt,
+    UTC = UTC, rownames = rownames, keep_vec_names = keep_vec_names,
+    json_verbatim = TRUE, ...
+  )
+}
+
+if (requireNamespace('shiny') && packageVersion('shiny') >= '0.12.0') local({
+  tryCatch({
+    toJSON <- getFromNamespace('toJSON', 'shiny')
+    args2 <- formals(toJSON2)
+    args1 <- formals(toJSON)
+    if (!identical(args1, args2)) {
+      warning('Check shiny:::toJSON and make sure htmlwidgets:::toJSON is in sync')
+    }
+  })
+})
+
+toJSON <- function(x) {
+  if (!is.list(x) || !('x' %in% names(x))) return(toJSON2(x))
+  func <- attr(x$x, 'TOJSON_FUNC', exact = TRUE)
+  args <- attr(x$x, 'TOJSON_ARGS', exact = TRUE)
+  if (length(args) == 0) args <- getOption('htmlwidgets.TOJSON_ARGS')
+  if (!is.function(func)) func <- toJSON2
+  res <- if (length(args) == 0) func(x) else do.call(func, c(list(x = x), args))
+  # make sure shiny:::toJSON() does not encode it again
+  structure(res, class = 'json')
+}
+
+#' Get js and css dependencies for  a htmlwidget
+#'
+#' @param name name of the widget.
+#' @param package name of the package, defaults to the widget name.
+#' @export
+getDependency <- function(name, package = name){
+  config = sprintf("htmlwidgets/%s.yaml", name)
+  jsfile = sprintf("htmlwidgets/%s.js", name)
+
+  config = yaml::yaml.load_file(
+    system.file(config, package = package)
+  )
+  widgetDep <- lapply(config$dependencies, function(l){
+    l$src = system.file(l$src, package = package)
+    do.call(htmlDependency, l)
+  })
+
+  bindingDir <- system.file("htmlwidgets", package = package)
+  argsDep <- NULL
+  copyBindingDir <- getOption('htmlwidgets.copybindingdir', TRUE)
+  # TODO: remove this trick when htmltools >= 0.3.3 is on CRAN
+  if (copyBindingDir) {
+    if (packageVersion('htmltools') < '0.3.3') {
+      bindingDir <- tempfile("widgetbinding")
+      dir.create(bindingDir, mode = "0700")
+      file.copy(system.file(jsfile, package = package), bindingDir)
+    } else argsDep <- list(all_files = FALSE)
+  }
+  bindingDep <- do.call(htmlDependency, c(list(
+    paste0(name, "-binding"), packageVersion(package),
+    bindingDir, script = basename(jsfile)
+  ), argsDep))
+
+  c(
+    list(htmlDependency("htmlwidgets", packageVersion("htmlwidgets"),
+      src = system.file("www", package="htmlwidgets"),
+      script = "htmlwidgets.js"
+    )),
+    widgetDep,
+    list(bindingDep)
+  )
+}
+
+`%||%` <- function(x, y){
+  if (is.null(x)) y else x
+}
+
+prop <- function(x, path) {
+  tryCatch({
+    for (i in strsplit(path, "$", fixed = TRUE)[[1]]) {
+      if (is.null(x))
+        return(NULL)
+      x <- x[[i]]
+    }
+    return(x)
+  }, error = function(e) {
+    return(NULL)
+  })
+}
+
+any_prop <- function(scopes, path) {
+  for (scope in scopes) {
+    result <- prop(scope, path)
+    if (!is.null(result))
+      return(result)
+  }
+  return(NULL)
+}
+
+#' Mark character strings as literal JavaScript code
+#'
+#' This function \code{JS()} marks character vectors with a special class, so
+#' that it will be treated as literal JavaScript code when evaluated on the
+#' client-side.
+#' @param ... character vectors as the JavaScript source code (all arguments
+#'   will be pasted into one character string)
+#' @author Yihui Xie
+#' @export
+#' @examples library(htmlwidgets)
+#' JS('1 + 1')
+#' list(x = JS('function(foo) {return foo;}'), y = 1:10)
+#' JS('function(x) {', 'return x + 1;', '}')
+JS <- function(...) {
+  x <- c(...)
+  if (is.null(x)) return()
+  if (!is.character(x))
+    stop("The arguments for JS() must be a character vector")
+  x <- paste(x, collapse = '\n')
+  structure(x, class = unique(c("JS_EVAL", oldClass(x))))
+}
+
+# Creates a list of keys whose values need to be evaluated on the client-side.
+#
+# It works by transforming \code{list(foo = list(1, list(bar =
+# I('function(){}')), 2))} to \code{list("foo.2.bar")}. Later on the JS side, we
+# will split foo.2.bar to ['foo', '2', 'bar'] and evaluate the JSON object
+# member. Note '2' (character) should have been 2 (integer) but it does not seem
+# to matter in JS: x[2] is the same as x['2'] when all child members of x are
+# unnamed, and ('2' in x) will be true even if x is an array without names. This
+# is a little hackish.
+#
+# @param list a list in which the elements that should be evaluated as
+#   JavaScript are to be identified
+# @author Yihui Xie
+JSEvals <- function(list) {
+  evals <- names(which(unlist(shouldEval(list))))
+  I(evals)  # need I() to prevent toJSON() from converting it to scalar
+}
+
+#' JSON elements that are character with the class JS_EVAL will be evaluated
+#'
+#' @noRd
+#' @keywords internal
+shouldEval <- function(options) {
+  if (is.list(options)) {
+    if ((n <- length(options)) == 0) return(FALSE)
+    # use numeric indices as names (remember JS indexes from 0, hence -1 here)
+    if (is.null(names(options)))
+      names(options) <- seq_len(n) - 1L
+    # Escape '\' and '.' by prefixing them with '\'. This allows us to tell the
+    # difference between periods as separators and periods that are part of the
+    # name itself.
+    names(options) <- gsub("([\\.])", "\\\\\\1", names(options))
+    nms <- names(options)
+    if (length(nms) != n || any(nms == ''))
+      stop("'options' must be a fully named list, or have no names (NULL)")
+    lapply(options, shouldEval)
+  } else {
+    is.character(options) && inherits(options, 'JS_EVAL')
+  }
+}
+# JSEvals(list(list(foo.bar=JS("hi"), baz.qux="bye"))) == "0.foo\\.bar"
+
+#' Execute JavaScript code after static render
+#'
+#' Convenience function for wrapping a JavaScript code string with a
+#' \code{<script>} tag and the boilerplate necessary to delay the execution of
+#' the code until after the next time htmlwidgets completes rendering any
+#' widgets that are in the page. This mechanism is designed for running code to
+#' customize widget instances, which can't be done at page load time since the
+#' widget instances will not have been created yet.
+#'
+#' Each call to \code{onStaticRenderComplete} will result in at most one
+#' invocation of the given code. In some edge cases in Shiny, it's possible for
+#' static rendering to happen more than once (e.g. a \code{renderUI} that
+#' contains static HTML widgets). \code{onStaticRenderComplete} calls only
+#' schedule execution for the next static render operation.
+#'
+#' The pure JavaScript equivalent of \code{onStaticRenderComplete} is
+#' \code{HTMLWidgets.addPostRenderHandler(callback)}, where \code{callback} is a
+#' JavaScript function that takes no arguments.
+#'
+#' @param jsCode A character vector containing JavaScript code. No R error will
+#'   be raised if the code is invalid, not even on JavaScript syntax errors.
+#'   However, the web browser will throw errors at runtime.
+#' @return An htmltools \code{\link[htmltools]{tags}$script} object.
+#'
+#' @examples
+#' \dontrun{
+#' library(leaflet)
+#' library(htmltools)
+#' library(htmlwidgets)
+#'
+#' page <- tagList(
+#'   leaflet() %>% addTiles(),
+#'   onStaticRenderComplete(
+#'     "HTMLWidgets.find('.leaflet').setZoom(4);"
+#'   )
+#' )
+#' print(page, browse = TRUE)
+#' }
+#'
+#' @export
+onStaticRenderComplete <- function(jsCode) {
+  tags$script(
+    "HTMLWidgets.addPostRenderHandler(function() {",
+    HTML(paste0(jsCode, collapse = "\n")),
+    "});"
+  )
+}
diff --git a/R/widgetid.R b/R/widgetid.R
new file mode 100644
index 0000000..b3dccdf
--- /dev/null
+++ b/R/widgetid.R
@@ -0,0 +1,43 @@
+
+#' Set the random seed for widget element ids
+#'
+#' Set a random seed for generating widget element ids. Calling this
+#' function rather than relying on the default behavior ensures
+#' stable widget ids across sessions.
+#'
+#' @inheritParams base::set.seed
+#'
+#' @export
+setWidgetIdSeed <- function(seed, kind = NULL, normal.kind = NULL) {
+  sysSeed <- .GlobalEnv$.Random.seed
+  on.exit({
+    .globals$idSeed <- .GlobalEnv$.Random.seed
+    if (!is.null(sysSeed))
+      .GlobalEnv$.Random.seed <- sysSeed
+    else
+      rm(".Random.seed", envir = .GlobalEnv)
+  })
+  set.seed(seed, kind = kind, normal.kind = normal.kind)
+}
+
+# create a new unique widget id
+createWidgetId <- function(bytes = 10) {
+
+  # Note what the system's random seed is before we start, so we can restore it after
+  sysSeed <- .GlobalEnv$.Random.seed
+  # Replace system seed with our own seed
+  if (!is.null(.globals$idSeed)) {
+    .GlobalEnv$.Random.seed <- .globals$idSeed
+  }
+  on.exit({
+    # Change our own seed to match the current seed
+    .globals$idSeed <- .GlobalEnv$.Random.seed
+    # Restore the system seed--we were never here
+    .GlobalEnv$.Random.seed <- sysSeed
+  })
+
+  paste(
+    format(as.hexmode(sample(256, bytes, replace = TRUE)-1), width=2),
+    collapse = "")
+}
+
diff --git a/build/vignette.rds b/build/vignette.rds
new file mode 100644
index 0000000..5b7f854
Binary files /dev/null and b/build/vignette.rds differ
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 92d53bd..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,21 +0,0 @@
-r-cran-htmlwidgets (0.8-1) unstable; urgency=medium
-
-  * New upstream version
-  * Convert to dh-r
-  * Canonical homepage for CRAN
-  * d/watch: version=4
-
- -- Andreas Tille <tille at debian.org>  Thu, 10 Nov 2016 21:52:11 +0100
-
-r-cran-htmlwidgets (0.7-1) unstable; urgency=medium
-
-  * New upstream version
-    Closes: #837251
-
- -- Andreas Tille <tille at debian.org>  Sat, 10 Sep 2016 22:06:07 +0200
-
-r-cran-htmlwidgets (0.6-1) unstable; urgency=low
-
-  * Initial release (closes: #828860)
-
- -- Andreas Tille <tille at debian.org>  Tue, 28 Jun 2016 17:20:39 +0200
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
deleted file mode 100644
index 16863c6..0000000
--- a/debian/control
+++ /dev/null
@@ -1,27 +0,0 @@
-Source: r-cran-htmlwidgets
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Andreas Tille <tille at debian.org>
-Section: gnu-r
-Priority: optional
-Build-Depends: debhelper (>= 9),
-               dh-r,
-               r-base-dev,
-               r-cran-htmltools,
-               r-cran-jsonlite,
-               r-cran-yaml
-Standards-Version: 3.9.8
-Vcs-Browser: https://anonscm.debian.org/viewvc/debian-med/trunk/packages/R/r-cran-htmlwidgets/trunk/
-Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/R/r-cran-htmlwidgets/trunk/
-Homepage: https://cran.r-project.org/package=htmlwidgets
-
-Package: r-cran-htmlwidgets
-Architecture: any
-Depends: ${shlibs:Depends},
-         ${misc:Depends},
-         ${R:Depends}
-Recommends: ${R:Recommends}
-Suggests: ${R:Suggests}
-Description: GNU R HTML Widgets
- This package provides a framework for creating HTML widgets that render
- in various contexts including the R console, 'R Markdown' documents, and
- 'Shiny' web applications.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index 185ccbe..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,34 +0,0 @@
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: htmlwidgets
-Upstream-Contact: JJ Allaire <jj at rstudio.com>
-Source: https://cran.r-project.org/package=htmlwidgets
-
-Files: *
-Copyright: 2012-2016 Ramnath Vaidyanathan, Yihui Xie, JJ Allaire, Joe Cheng,
-                     Kenton Russell, RStudio 
-License: MIT
-
-Files: debian/*
-Copyright: 2016 Chris Lawrence <lawrencc at debian.org>,
-                Andreas Tille <tille at debian.org>
-License: MIT
-
-License: MIT
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
- .
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
- .
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index 68d9a36..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/make -f
-
-%:
-	dh $@ --buildsystem R
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index 2fec850..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,2 +0,0 @@
-version=4
-http://cran.r-project.org/src/contrib/htmlwidgets_([-\d.]*)\.tar\.gz
diff --git a/inst/NEWS b/inst/NEWS
new file mode 100644
index 0000000..0b38d00
--- /dev/null
+++ b/inst/NEWS
@@ -0,0 +1,93 @@
+htmlwidgets 0.8
+-----------------------------------------------------------------------
+
+* Export getDependency function
+
+* `onRender` hooks were firing too early when used in Shiny apps.
+
+* Widget IDs: only restore random.seed when non-NULL
+
+
+htmlwidgets 0.7
+-----------------------------------------------------------------------
+
+* Pass knitr options to saveWidget
+
+* Ensure that scaffoldWidget opens files correctly within RStudio
+
+* The resize handler also works for the JavaScript events `shown.bs.collapse`
+  and `hidden.bs.collapse` now so that widgets inside the Bootstrap collapse
+  class can be displayed
+
+* Fix references to vignettes in documentation
+
+* Add elementId parameter to widget function generated by scaffoldWidget
+
+* More robust method of generating unique widget IDs
+
+* Modify advanced and sizing vignettes to use new style widget declarations
+
+
+htmlwidgets 0.6
+-----------------------------------------------------------------------
+
+* Introduce new scheme for defining JavaScript bindings that will make
+  it easier for widgets to gain access to other widget instances on
+  the page.
+
+* Add `onRender` hook for widgets to execute custom JavaScript code
+  after rendering.
+
+* Add `appendContent` and `prependContent` functions for adding HTML
+  to a widget rendered in a static context (i.e. R console or Rmd)
+
+* Fix a bug where the string "</body></html>" in the widget data caused
+  `saveWidget()` to have malformed output. (#168)
+
+* Tweak pandoc conversion used in saveWidget to prevent hanging with
+  large htmlwidget script data elements (use "markdown" rather than
+  "markdown-strict" as input format)
+
+* Increase pandoc stack size to 512M for saveWidget (often required for
+  e.g. larger embedded leaflet maps). Stack size can also be controlled
+  by the pandoc.stack.size option.
+
+* Import latest version of with_pandoc_safe_environment from rmarkdown
+
+* Fix issue that prevented calling renderValue() from within resize()
+
+
+htmlwidgets 0.5
+-----------------------------------------------------------------------
+
+* Add background parameter to saveWidget function
+
+* Fix a bug where "</script>" appearing in widget data would break
+  parsing
+
+* Fix a bug where multiple widgets on a page caused all but one to miss
+  resize events
+
+* Sync vignettes with contents of htmlwidgets website
+
+
+htmlwidgets 0.4
+-----------------------------------------------------------------------
+
+* Use minified files while scaffolding widget wherever available
+
+* Suppress viewing widgets in non-interactive R sessions by default
+
+* Export the HTMLWidgets.staticRender function
+
+* Add a preRenderHook for widgets
+
+* Use jsonlite rather than RJSONIO for JSON serialization
+
+* Call widget.resize in more situations
+
+
+htmlwidgets 0.3.2
+-----------------------------------------------------------------------
+
+* Initial release to CRAN
diff --git a/inst/doc/develop_advanced.R b/inst/doc/develop_advanced.R
new file mode 100644
index 0000000..0c7f59b
--- /dev/null
+++ b/inst/doc/develop_advanced.R
@@ -0,0 +1,57 @@
+## ----echo=FALSE, comment=''----------------------------------------------
+htmlwidgets:::toJSON2(head(iris, 3), pretty = TRUE)
+
+## ----echo=FALSE, comment=''----------------------------------------------
+htmlwidgets:::toJSON2(head(iris, 3), dataframe = 'row', pretty = TRUE)
+
+## ----echo=FALSE, comment=''----------------------------------------------
+htmlwidgets:::toJSON2(unname(head(iris, 8)), dataframe = 'column', pretty = TRUE)
+
+## ----echo=FALSE, comment=''----------------------------------------------
+htmlwidgets:::toJSON2(head(iris, 8), dataframe = 'values', pretty = TRUE)
+
+## ----eval=FALSE, code=head(capture.output(htmlwidgets:::toJSON2),-1), tidy=FALSE----
+#  function (x, ..., dataframe = "columns", null = "null", na = "null",
+#      auto_unbox = TRUE, digits = getOption("shiny.json.digits",
+#          16), use_signif = TRUE, force = TRUE, POSIXt = "ISO8601",
+#      UTC = TRUE, rownames = FALSE, keep_vec_names = TRUE, strict_atomic = TRUE)
+#  {
+#      if (strict_atomic)
+#          x <- I(x)
+#      jsonlite::toJSON(x, dataframe = dataframe, null = null, na = na,
+#          auto_unbox = auto_unbox, digits = digits, use_signif = use_signif,
+#          force = force, POSIXt = POSIXt, UTC = UTC, rownames = rownames,
+#          keep_vec_names = keep_vec_names, json_verbatim = TRUE,
+#          ...)
+#  }
+
+## ----eval=FALSE----------------------------------------------------------
+#  fooWidget <- function(data, name, ...) {
+#    # ... process the data ...
+#    params <- list(foo = data, bar = TRUE)
+#    # customize toJSON() argument values
+#    attr(params, 'TOJSON_ARGS') <- list(digits = 7, na = 'string')
+#    htmlwidgets::createWidget(name, x = params, ...)
+#  }
+
+## ----eval=FALSE----------------------------------------------------------
+#  fooWidget <- function(data, name, ..., JSONArgs = list(digits = 7)) {
+#    # ... process the data ...
+#    params <- list(foo = data, bar = TRUE)
+#    # customize toJSON() argument values
+#    attr(params, 'TOJSON_ARGS') <- JSONArgs
+#    htmlwidgets::createWidget(name, x = params, ...)
+#  }
+
+## ----eval=FALSE----------------------------------------------------------
+#  options(htmlwidgets.TOJSON_ARGS = list(digits = 7, pretty = TRUE))
+
+## ----eval=FALSE----------------------------------------------------------
+#  fooWidget <- function(data, name, ...) {
+#    # ... process the data ...
+#    params <- list(foo = data, bar = TRUE)
+#    # customize the JSON serializer
+#    attr(params, 'TOJSON_FUNC') <- MY_OWN_JSON_FUNCTION
+#    htmlwidgets::createWidget(name, x = params, ...)
+#  }
+
diff --git a/inst/doc/develop_advanced.Rmd b/inst/doc/develop_advanced.Rmd
new file mode 100644
index 0000000..b00e8fd
--- /dev/null
+++ b/inst/doc/develop_advanced.Rmd
@@ -0,0 +1,188 @@
+---
+title: "HTML Widgets: Advanced Topics"
+date: "`r Sys.Date()`"
+output: 
+  html_document:
+    highlight: kate
+    toc: true
+    toc_depth: 4
+    mathjax: null
+vignette: >
+  %\VignetteIndexEntry{Advanced}
+  %\VignetteEngine{knitr::rmarkdown}
+  \usepackage[utf8]{inputenc}
+---
+
+## Overview
+
+This article covers several aspects of creating widgets that are not required by all widgets, but are an essential part of getting bindings to certain types of JavaScript libraries to work properly. Topics covered include:
+
+* Transforming JSON representations of R objects into representations required by JavaScript libraries (e.g. an R data frame to a d3 dataset).
+
+* Tracking instance-specific widget data within JavaScript bindings.
+
+* Passing JavaScript functions from R to JavaScript (e.g. a user provided formatting or drawing function)
+
+* Generating custom HTML to enclose a widget (the default is a `<div>` but some libraries require a different element e.g. a `<span>`).
+
+
+## Data transformation
+
+R objects passed as part of the `x` parameter to the `createWidget()` function are transformed to JSON using the internal function `htmlwidgets:::toJSON()`^[N.B. It is not exported from **htmlwidgets**, so you are not supposed to call this function directly.], which is basically a wrapper function of `jsonlite::toJSON()` by default. However, sometimes this representation is not what is required by the JavaScript library you are interfacing with. There are two JavaScript functions that yo [...]
+
+### HTMLWidgets.dataframeToD3()
+
+R data frames are represented in "long" form (an array of named vectors) whereas d3 typically requires "wide" form (an array of objects each of which includes all names and values). Since the R representation is smaller in size and much faster to transmit over the network, we create the long-form representation of R data, and then transform the data in JavaScript using the `dataframeToD3()` helper function. 
+
+Here is an example of the long-form representation of an R data frame:
+
+```{r echo=FALSE, comment=''}
+htmlwidgets:::toJSON2(head(iris, 3), pretty = TRUE)
+```
+
+After we apply `HTMLWidgets.dataframeToD3()`, it will become:
+
+```{r echo=FALSE, comment=''}
+htmlwidgets:::toJSON2(head(iris, 3), dataframe = 'row', pretty = TRUE)
+```
+
+
+As a real example, the [simpleNetwork](https://christophergandrud.github.io/networkD3/#simple) widget accepts a data frame containing network links on the R side, then transforms it to a d3 representation within the JavaScript `renderValue` function:
+
+```javascript
+renderValue: function(x) {
+
+  // convert links data frame to d3 friendly format
+  var links = HTMLWidgets.dataframeToD3(x.links);
+  
+  // ... use the links, etc ...
+
+}
+```
+
+### HTMLWidgets.transposeArray2D()
+
+Sometimes a 2-dimensional array requires a similar transposition. For this the `transposeArray2D()` function is provided. Here is an example array:
+
+```{r echo=FALSE, comment=''}
+htmlwidgets:::toJSON2(unname(head(iris, 8)), dataframe = 'column', pretty = TRUE)
+```
+
+`HTMLWidgets.transposeArray2D()` can transpose it to:
+
+```{r echo=FALSE, comment=''}
+htmlwidgets:::toJSON2(head(iris, 8), dataframe = 'values', pretty = TRUE)
+```
+
+As a real example, the [dygraphs](https://rstudio.github.io/dygraphs) widget uses this function to transpose the "file" (data) argument it gets from the R side before passing it on to the dygraphs library:
+
+```javascript
+renderValue: function(x) {
+   
+    // ... code excluded ...
+    
+    // transpose array
+    x.attrs.file = HTMLWidgets.transposeArray2D(x.attrs.file);
+    
+    // ... more code excluded ...
+}
+```
+
+### Custom JSON serializer
+
+You may find it necessary to customize the JSON serialization of widget data when the default serializer in **htmlwidgets** does not work in the way you have expected. For widget package authors, there are two levels of customization for the JSON serialization: you can either customize the default values of arguments for `jsonlite::toJSON()`, or just customize the whole function.
+
+1. `jsonlite::toJSON()` has a lot of arguments, and we have already changed some of its default values. Below is the JSON serializer we use in **htmlwidgets** at the moment:
+
+    ```{r eval=FALSE, code=head(capture.output(htmlwidgets:::toJSON2),-1), tidy=FALSE}
+    ```
+
+    For example, we convert data frames to JSON by columns instead of rows (the latter is `jsonlite::toJSON`'s default). If you want to change the default values of any arguments, you can attach an attribute `TOJSON_ARGS` to the widget data to be passed to `createWidget()`, e.g.
+
+    ```{r eval=FALSE}
+    fooWidget <- function(data, name, ...) {
+      # ... process the data ...
+      params <- list(foo = data, bar = TRUE)
+      # customize toJSON() argument values
+      attr(params, 'TOJSON_ARGS') <- list(digits = 7, na = 'string')
+      htmlwidgets::createWidget(name, x = params, ...)
+    }
+    ```
+
+    We changed the default value of `digits` from 16 to 7, and `na` from `null` to `string` in the above example. It is up to you, the package author, whether you want to expose such customization to users. For example, you can leave an extra argument in your widget function so that users can customize the behavior of the JSON serializer:
+
+    ```{r eval=FALSE}
+    fooWidget <- function(data, name, ..., JSONArgs = list(digits = 7)) {
+      # ... process the data ...
+      params <- list(foo = data, bar = TRUE)
+      # customize toJSON() argument values
+      attr(params, 'TOJSON_ARGS') <- JSONArgs
+      htmlwidgets::createWidget(name, x = params, ...)
+    }
+    ```
+
+    You can also use a global option `htmlwidgets.TOJSON_ARGS` to customize the JSON serializer arguments for all widgets in the current R session, e.g.
+
+    ```{r eval=FALSE}
+    options(htmlwidgets.TOJSON_ARGS = list(digits = 7, pretty = TRUE))
+    ```
+
+1. If you do not want to use **jsonlite**, you can completely override the serializer function by attaching an attribute `TOJSON_FUNC` to the widget data, e.g.
+
+    ```{r eval=FALSE}
+    fooWidget <- function(data, name, ...) {
+      # ... process the data ...
+      params <- list(foo = data, bar = TRUE)
+      # customize the JSON serializer
+      attr(params, 'TOJSON_FUNC') <- MY_OWN_JSON_FUNCTION
+      htmlwidgets::createWidget(name, x = params, ...)
+    }
+    ```
+
+    Here `MY_OWN_JSON_FUNCTION` can be an arbitrary R function that converts R objects to JSON. If you have also specified the `TOJSON_ARGS` attribute, it will be passed to your custom JSON function as well.
+
+Note these features about custom JSON serializers require the **shiny** version to be greater than 0.11.1 if you render the widgets in Shiny apps.
+
+## Passing JavaScript functions
+
+As you would expect, character vectors passed from R to JavaScript are converted to JavaScript strings. However, what if you want to allow users to provide custom JavaScript functions for formatting, drawing, or event handling? For this case, the **htmlwidgets** package includes a `JS()` function that allows you to request that a character value is evaluated as JavaScript when it is received on the client.
+
+For example, the [dygraphs](https://rstudio.github.io/dygraphs) widget includes a `dyCallbacks` function that allows the user to provide callback functions for a variety of contexts. These callbacks are "marked" as containing JavaScript so that they can be converted to actual JavaScript functions on the client:
+
+```r
+callbacks <- list(
+  clickCallback = JS(clickCallback)
+  drawCallback = JS(drawCallback)
+  highlightCallback = JS(highlightCallback)
+  pointClickCallback = JS(pointClickCallback)
+  underlayCallback = JS(underlayCallback)
+)
+```
+
+Another example is in the [DT](https://rstudio.github.io/DT) (DataTables) widget, where users can specify an `initCallback` with JavaScript to execute after the table is loaded and initialized:
+
+```r
+datatable(head(iris, 20), options = list(
+  initComplete = JS(
+    "function(settings, json) {",
+    "$(this.api().table().header()).css({'background-color': '#000', 'color': '#fff'});",
+    "}")
+))
+```
+
+If multiple arguments are passed to `JS()` (as in the above example), they will be concatenated into a single string separated by `\n`.
+
+## Custom widget HTML
+
+Typically the HTML "housing" for a widget is just a `<div>` element, and this is correspondingly the default behavior for new widgets that don't specify otherwise. However, sometimes you need a different element type. For example, the [sparkline](https://github.com/htmlwidgets/sparkline) widget requires a `<span>` element so implements the following custom HTML generation function:
+
+```r
+sparkline_html <- function(id, style, class, ...){
+  tags$span(id = id, class = class)
+}
+```
+
+Note that this function is looked up within the package implementing the widget by the convention `widgetname_html` so it need not be formally exported from your package or otherwise registered with **htmlwidgets**.
+
+Most widgets won't need a custom HTML function but if you need to generate custom HTML for your widget (e.g. you need an `<input>` or a `<span>` rather than a `<div>`) then you should use the **htmltools** package (as demonstrated by the code above).
+
diff --git a/inst/doc/develop_advanced.html b/inst/doc/develop_advanced.html
new file mode 100644
index 0000000..5e8e9b6
--- /dev/null
+++ b/inst/doc/develop_advanced.html
@@ -0,0 +1,359 @@
+<!DOCTYPE html>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+
+<meta charset="utf-8">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="pandoc" />
+
+
+
+<meta name="date" content="2016-11-09" />
+
+<title>HTML Widgets: Advanced Topics</title>
+
+<script src="data:application/x-javascript;base64,LyohIGpRdWVyeSB2MS4xMS4zIHwgKGMpIDIwMDUsIDIwMTUgalF1ZXJ5IEZvdW5kYXRpb24sIEluYy4gfCBqcXVlcnkub3JnL2xpY2Vuc2UgKi8KIWZ1bmN0aW9uKGEsYil7Im9iamVjdCI9PXR5cGVvZiBtb2R1bGUmJiJvYmplY3QiPT10eXBlb2YgbW9kdWxlLmV4cG9ydHM/bW9kdWxlLmV4cG9ydHM9YS5kb2N1bWVudD9iKGEsITApOmZ1bmN0aW9uKGEpe2lmKCFhLmRvY3VtZW50KXRocm93IG5ldyBFcnJvcigialF1ZXJ5IHJlcXVpcmVzIGEgd2luZG93IHdpdGggYSBkb2N1bWVudCIpO3JldHVybiBiKGEpfTpiKGEpfSgidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdz93aW5kb3c6dG [...]
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<link href="data:text/css;charset=utf-8,html%7Bfont%2Dfamily%3Asans%2Dserif%3B%2Dwebkit%2Dtext%2Dsize%2Dadjust%3A100%25%3B%2Dms%2Dtext%2Dsize%2Dadjust%3A100%25%7Dbody%7Bmargin%3A0%7Darticle%2Caside%2Cdetails%2Cfigcaption%2Cfigure%2Cfooter%2Cheader%2Chgroup%2Cmain%2Cmenu%2Cnav%2Csection%2Csummary%7Bdisplay%3Ablock%7Daudio%2Ccanvas%2Cprogress%2Cvideo%7Bdisplay%3Ainline%2Dblock%3Bvertical%2Dalign%3Abaseline%7Daudio%3Anot%28%5Bcontrols%5D%29%7Bdisplay%3Anone%3Bheight%3A0%7D%5Bhidden%5D%2Ctem [...]
+<script src="data:application/x-javascript;base64,LyohCiAqIEJvb3RzdHJhcCB2My4zLjUgKGh0dHA6Ly9nZXRib290c3RyYXAuY29tKQogKiBDb3B5cmlnaHQgMjAxMS0yMDE1IFR3aXR0ZXIsIEluYy4KICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlCiAqLwppZigidW5kZWZpbmVkIj09dHlwZW9mIGpRdWVyeSl0aHJvdyBuZXcgRXJyb3IoIkJvb3RzdHJhcCdzIEphdmFTY3JpcHQgcmVxdWlyZXMgalF1ZXJ5Iik7K2Z1bmN0aW9uKGEpeyJ1c2Ugc3RyaWN0Ijt2YXIgYj1hLmZuLmpxdWVyeS5zcGxpdCgiICIpWzBdLnNwbGl0KCIuIik7aWYoYlswXTwyJiZiWzFdPDl8fDE9PWJbMF0mJjk9PWJbMV0mJmJbMl08MSl0aHJvdy [...]
+<script src="data:application/x-javascript;base64,LyoqCiogQHByZXNlcnZlIEhUTUw1IFNoaXYgMy43LjIgfCBAYWZhcmthcyBAamRhbHRvbiBAam9uX25lYWwgQHJlbSB8IE1JVC9HUEwyIExpY2Vuc2VkCiovCi8vIE9ubHkgcnVuIHRoaXMgY29kZSBpbiBJRSA4CmlmICghIXdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKCJNU0lFIDgiKSkgewohZnVuY3Rpb24oYSxiKXtmdW5jdGlvbiBjKGEsYil7dmFyIGM9YS5jcmVhdGVFbGVtZW50KCJwIiksZD1hLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJoZWFkIilbMF18fGEuZG9jdW1lbnRFbGVtZW50O3JldHVybiBjLmlubmVySFRNTD0ieDxzdHlsZT4iK2IrIjwvc3R5bGU+IixkLm [...]
+<script src="data:application/x-javascript;base64,LyohIFJlc3BvbmQuanMgdjEuNC4yOiBtaW4vbWF4LXdpZHRoIG1lZGlhIHF1ZXJ5IHBvbHlmaWxsICogQ29weXJpZ2h0IDIwMTMgU2NvdHQgSmVobAogKiBMaWNlbnNlZCB1bmRlciBodHRwczovL2dpdGh1Yi5jb20vc2NvdHRqZWhsL1Jlc3BvbmQvYmxvYi9tYXN0ZXIvTElDRU5TRS1NSVQKICogICovCgovLyBPbmx5IHJ1biB0aGlzIGNvZGUgaW4gSUUgOAppZiAoISF3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgiTVNJRSA4IikpIHsKIWZ1bmN0aW9uKGEpeyJ1c2Ugc3RyaWN0IjthLm1hdGNoTWVkaWE9YS5tYXRjaE1lZGlhfHxmdW5jdGlvbihhKXt2YXIgYixjPWEuZG [...]
+<script src="data:application/x-javascript;base64,Cgp3aW5kb3cuYnVpbGRUYWJzZXRzID0gZnVuY3Rpb24odG9jSUQpIHsKCiAgLy8gYnVpbGQgYSB0YWJzZXQgZnJvbSBhIHNlY3Rpb24gZGl2IHdpdGggdGhlIC50YWJzZXQgY2xhc3MKICBmdW5jdGlvbiBidWlsZFRhYnNldCh0YWJzZXQpIHsKCiAgICAvLyBjaGVjayBmb3IgZmFkZSBhbmQgcGlsbHMgb3B0aW9ucwogICAgdmFyIGZhZGUgPSB0YWJzZXQuaGFzQ2xhc3MoInRhYnNldC1mYWRlIik7CiAgICB2YXIgcGlsbHMgPSB0YWJzZXQuaGFzQ2xhc3MoInRhYnNldC1waWxscyIpOwogICAgdmFyIG5hdkNsYXNzID0gcGlsbHMgPyAibmF2LXBpbGxzIiA6ICJuYXYtdGFicyI7CgogIC [...]
+
+
+<style type="text/css">code{white-space: pre;}</style>
+<style type="text/css">
+div.sourceCode { overflow-x: auto; }
+table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
+  margin: 0; padding: 0; vertical-align: baseline; border: none; }
+table.sourceCode { width: 100%; line-height: 100%; }
+td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; background-color: #dddddd; }
+td.sourceCode { padding-left: 5px; }
+code > span.kw { font-weight: bold; } /* Keyword */
+code > span.dt { color: #800000; } /* DataType */
+code > span.dv { color: #0000ff; } /* DecVal */
+code > span.bn { color: #0000ff; } /* BaseN */
+code > span.fl { color: #800080; } /* Float */
+code > span.ch { color: #ff00ff; } /* Char */
+code > span.st { color: #dd0000; } /* String */
+code > span.co { color: #808080; font-style: italic; } /* Comment */
+code > span.al { color: #00ff00; font-weight: bold; } /* Alert */
+code > span.fu { color: #000080; } /* Function */
+code > span.er { color: #ff0000; font-weight: bold; } /* Error */
+code > span.wa { color: #ff0000; font-weight: bold; } /* Warning */
+code > span.cn { color: #000000; } /* Constant */
+code > span.sc { color: #ff00ff; } /* SpecialChar */
+code > span.vs { color: #dd0000; } /* VerbatimString */
+code > span.ss { color: #dd0000; } /* SpecialString */
+code > span.im { } /* Import */
+code > span.va { } /* Variable */
+code > span.cf { } /* ControlFlow */
+code > span.op { } /* Operator */
+code > span.bu { } /* BuiltIn */
+code > span.ex { } /* Extension */
+code > span.pp { font-weight: bold; } /* Preprocessor */
+code > span.at { } /* Attribute */
+code > span.do { color: #808080; font-style: italic; } /* Documentation */
+code > span.an { color: #808080; font-weight: bold; font-style: italic; } /* Annotation */
+code > span.cv { color: #808080; font-weight: bold; font-style: italic; } /* CommentVar */
+code > span.in { color: #808080; font-weight: bold; font-style: italic; } /* Information */
+</style>
+<style type="text/css">
+  pre:not([class]) {
+    background-color: white;
+  }
+</style>
+
+
+<style type="text/css">
+h1 {
+  font-size: 34px;
+}
+h1.title {
+  font-size: 38px;
+}
+h2 {
+  font-size: 30px;
+}
+h3 {
+  font-size: 24px;
+}
+h4 {
+  font-size: 18px;
+}
+h5 {
+  font-size: 16px;
+}
+h6 {
+  font-size: 12px;
+}
+.table th:not([align]) {
+  text-align: left;
+}
+</style>
+
+
+</head>
+
+<body>
+
+<style type="text/css">
+.main-container {
+  max-width: 940px;
+  margin-left: auto;
+  margin-right: auto;
+}
+code {
+  color: inherit;
+  background-color: rgba(0, 0, 0, 0.04);
+}
+img {
+  max-width:100%;
+  height: auto;
+}
+.tabbed-pane {
+  padding-top: 12px;
+}
+button.code-folding-btn:focus {
+  outline: none;
+}
+</style>
+
+
+
+<div class="container-fluid main-container">
+
+<!-- tabsets -->
+<script>
+$(document).ready(function () {
+  window.buildTabsets("TOC");
+});
+</script>
+
+<!-- code folding -->
+
+
+
+
+
+
+<div class="fluid-row" id="header">
+
+
+
+<h1 class="title toc-ignore">HTML Widgets: Advanced Topics</h1>
+<h4 class="date"><em>2016-11-09</em></h4>
+
+</div>
+
+<div id="TOC">
+<ul>
+<li><a href="#overview">Overview</a></li>
+<li><a href="#data-transformation">Data transformation</a><ul>
+<li><a href="#htmlwidgets.dataframetod3">HTMLWidgets.dataframeToD3()</a></li>
+<li><a href="#htmlwidgets.transposearray2d">HTMLWidgets.transposeArray2D()</a></li>
+<li><a href="#custom-json-serializer">Custom JSON serializer</a></li>
+</ul></li>
+<li><a href="#passing-javascript-functions">Passing JavaScript functions</a></li>
+<li><a href="#custom-widget-html">Custom widget HTML</a></li>
+</ul>
+</div>
+
+<div id="overview" class="section level2">
+<h2>Overview</h2>
+<p>This article covers several aspects of creating widgets that are not required by all widgets, but are an essential part of getting bindings to certain types of JavaScript libraries to work properly. Topics covered include:</p>
+<ul>
+<li><p>Transforming JSON representations of R objects into representations required by JavaScript libraries (e.g. an R data frame to a d3 dataset).</p></li>
+<li><p>Tracking instance-specific widget data within JavaScript bindings.</p></li>
+<li><p>Passing JavaScript functions from R to JavaScript (e.g. a user provided formatting or drawing function)</p></li>
+<li><p>Generating custom HTML to enclose a widget (the default is a <code><div></code> but some libraries require a different element e.g. a <code><span></code>).</p></li>
+</ul>
+</div>
+<div id="data-transformation" class="section level2">
+<h2>Data transformation</h2>
+<p>R objects passed as part of the <code>x</code> parameter to the <code>createWidget()</code> function are transformed to JSON using the internal function <code>htmlwidgets:::toJSON()</code><a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>, which is basically a wrapper function of <code>jsonlite::toJSON()</code> by default. However, sometimes this representation is not what is required by the JavaScript library you are interfacing with. There are two JavaScript functions t [...]
+<div id="htmlwidgets.dataframetod3" class="section level3">
+<h3>HTMLWidgets.dataframeToD3()</h3>
+<p>R data frames are represented in “long” form (an array of named vectors) whereas d3 typically requires “wide” form (an array of objects each of which includes all names and values). Since the R representation is smaller in size and much faster to transmit over the network, we create the long-form representation of R data, and then transform the data in JavaScript using the <code>dataframeToD3()</code> helper function.</p>
+<p>Here is an example of the long-form representation of an R data frame:</p>
+<pre><code>{
+  "Sepal.Length": [5.1, 4.9, 4.7],
+  "Sepal.Width": [3.5, 3, 3.2],
+  "Petal.Length": [1.4, 1.4, 1.3],
+  "Petal.Width": [0.2, 0.2, 0.2],
+  "Species": ["setosa", "setosa", "setosa"]
+} </code></pre>
+<p>After we apply <code>HTMLWidgets.dataframeToD3()</code>, it will become:</p>
+<pre><code>[
+  {
+    "Sepal.Length": 5.1,
+    "Sepal.Width": 3.5,
+    "Petal.Length": 1.4,
+    "Petal.Width": 0.2,
+    "Species": "setosa"
+  },
+  {
+    "Sepal.Length": 4.9,
+    "Sepal.Width": 3,
+    "Petal.Length": 1.4,
+    "Petal.Width": 0.2,
+    "Species": "setosa"
+  },
+  {
+    "Sepal.Length": 4.7,
+    "Sepal.Width": 3.2,
+    "Petal.Length": 1.3,
+    "Petal.Width": 0.2,
+    "Species": "setosa"
+  }
+] </code></pre>
+<p>As a real example, the <a href="https://christophergandrud.github.io/networkD3/#simple">simpleNetwork</a> widget accepts a data frame containing network links on the R side, then transforms it to a d3 representation within the JavaScript <code>renderValue</code> function:</p>
+<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript">renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span>
+
+  <span class="co">// convert links data frame to d3 friendly format</span>
+  <span class="kw">var</span> links <span class="op">=</span> <span class="va">HTMLWidgets</span>.<span class="at">dataframeToD3</span>(<span class="va">x</span>.<span class="at">links</span>)<span class="op">;</span>
+  
+  <span class="co">// ... use the links, etc ...</span>
+
+<span class="op">}</span></code></pre></div>
+</div>
+<div id="htmlwidgets.transposearray2d" class="section level3">
+<h3>HTMLWidgets.transposeArray2D()</h3>
+<p>Sometimes a 2-dimensional array requires a similar transposition. For this the <code>transposeArray2D()</code> function is provided. Here is an example array:</p>
+<pre><code>[
+  [5.1, 4.9, 4.7, 4.6, 5, 5.4, 4.6, 5],
+  [3.5, 3, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4],
+  [1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5],
+  [0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2],
+  ["setosa", "setosa", "setosa", "setosa", "setosa", "setosa", "setosa", "setosa"]
+] </code></pre>
+<p><code>HTMLWidgets.transposeArray2D()</code> can transpose it to:</p>
+<pre><code>[
+  [5.1, 3.5, 1.4, 0.2, "setosa"],
+  [4.9, 3, 1.4, 0.2, "setosa"],
+  [4.7, 3.2, 1.3, 0.2, "setosa"],
+  [4.6, 3.1, 1.5, 0.2, "setosa"],
+  [5, 3.6, 1.4, 0.2, "setosa"],
+  [5.4, 3.9, 1.7, 0.4, "setosa"],
+  [4.6, 3.4, 1.4, 0.3, "setosa"],
+  [5, 3.4, 1.5, 0.2, "setosa"]
+] </code></pre>
+<p>As a real example, the <a href="https://rstudio.github.io/dygraphs">dygraphs</a> widget uses this function to transpose the “file” (data) argument it gets from the R side before passing it on to the dygraphs library:</p>
+<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript">renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span>
+   
+    <span class="co">// ... code excluded ...</span>
+    
+    <span class="co">// transpose array</span>
+    <span class="va">x</span>.<span class="va">attrs</span>.<span class="at">file</span> <span class="op">=</span> <span class="va">HTMLWidgets</span>.<span class="at">transposeArray2D</span>(<span class="va">x</span>.<span class="va">attrs</span>.<span class="at">file</span>)<span class="op">;</span>
+    
+    <span class="co">// ... more code excluded ...</span>
+<span class="op">}</span></code></pre></div>
+</div>
+<div id="custom-json-serializer" class="section level3">
+<h3>Custom JSON serializer</h3>
+<p>You may find it necessary to customize the JSON serialization of widget data when the default serializer in <strong>htmlwidgets</strong> does not work in the way you have expected. For widget package authors, there are two levels of customization for the JSON serialization: you can either customize the default values of arguments for <code>jsonlite::toJSON()</code>, or just customize the whole function.</p>
+<ol style="list-style-type: decimal">
+<li><p><code>jsonlite::toJSON()</code> has a lot of arguments, and we have already changed some of its default values. Below is the JSON serializer we use in <strong>htmlwidgets</strong> at the moment:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">function (x, ..., <span class="dt">dataframe =</span> <span class="st">"columns"</span>, <span class="dt">null =</span> <span class="st">"null"</span>, <span class="dt">na =</span> <span class="st">"null"</span>, 
+    <span class="dt">auto_unbox =</span> <span class="ot">TRUE</span>, <span class="dt">digits =</span> <span class="kw">getOption</span>(<span class="st">"shiny.json.digits"</span>, 
+        <span class="dv">16</span>), <span class="dt">use_signif =</span> <span class="ot">TRUE</span>, <span class="dt">force =</span> <span class="ot">TRUE</span>, <span class="dt">POSIXt =</span> <span class="st">"ISO8601"</span>, 
+    <span class="dt">UTC =</span> <span class="ot">TRUE</span>, <span class="dt">rownames =</span> <span class="ot">FALSE</span>, <span class="dt">keep_vec_names =</span> <span class="ot">TRUE</span>, <span class="dt">strict_atomic =</span> <span class="ot">TRUE</span>) 
+{
+    if (strict_atomic) 
+        x <-<span class="st"> </span><span class="kw">I</span>(x)
+    jsonlite::<span class="kw">toJSON</span>(x, <span class="dt">dataframe =</span> dataframe, <span class="dt">null =</span> null, <span class="dt">na =</span> na, 
+        <span class="dt">auto_unbox =</span> auto_unbox, <span class="dt">digits =</span> digits, <span class="dt">use_signif =</span> use_signif, 
+        <span class="dt">force =</span> force, <span class="dt">POSIXt =</span> POSIXt, <span class="dt">UTC =</span> UTC, <span class="dt">rownames =</span> rownames, 
+        <span class="dt">keep_vec_names =</span> keep_vec_names, <span class="dt">json_verbatim =</span> <span class="ot">TRUE</span>, 
+        ...)
+}</code></pre></div>
+<p>For example, we convert data frames to JSON by columns instead of rows (the latter is <code>jsonlite::toJSON</code>’s default). If you want to change the default values of any arguments, you can attach an attribute <code>TOJSON_ARGS</code> to the widget data to be passed to <code>createWidget()</code>, e.g.</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">fooWidget <-<span class="st"> </span>function(data, name, ...) {
+  <span class="co"># ... process the data ...</span>
+  params <-<span class="st"> </span><span class="kw">list</span>(<span class="dt">foo =</span> data, <span class="dt">bar =</span> <span class="ot">TRUE</span>)
+  <span class="co"># customize toJSON() argument values</span>
+  <span class="kw">attr</span>(params, <span class="st">'TOJSON_ARGS'</span>) <-<span class="st"> </span><span class="kw">list</span>(<span class="dt">digits =</span> <span class="dv">7</span>, <span class="dt">na =</span> <span class="st">'string'</span>)
+  htmlwidgets::<span class="kw">createWidget</span>(name, <span class="dt">x =</span> params, ...)
+}</code></pre></div>
+<p>We changed the default value of <code>digits</code> from 16 to 7, and <code>na</code> from <code>null</code> to <code>string</code> in the above example. It is up to you, the package author, whether you want to expose such customization to users. For example, you can leave an extra argument in your widget function so that users can customize the behavior of the JSON serializer:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">fooWidget <-<span class="st"> </span>function(data, name, ..., <span class="dt">JSONArgs =</span> <span class="kw">list</span>(<span class="dt">digits =</span> <span class="dv">7</span>)) {
+  <span class="co"># ... process the data ...</span>
+  params <-<span class="st"> </span><span class="kw">list</span>(<span class="dt">foo =</span> data, <span class="dt">bar =</span> <span class="ot">TRUE</span>)
+  <span class="co"># customize toJSON() argument values</span>
+  <span class="kw">attr</span>(params, <span class="st">'TOJSON_ARGS'</span>) <-<span class="st"> </span>JSONArgs
+  htmlwidgets::<span class="kw">createWidget</span>(name, <span class="dt">x =</span> params, ...)
+}</code></pre></div>
+<p>You can also use a global option <code>htmlwidgets.TOJSON_ARGS</code> to customize the JSON serializer arguments for all widgets in the current R session, e.g.</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">options</span>(<span class="dt">htmlwidgets.TOJSON_ARGS =</span> <span class="kw">list</span>(<span class="dt">digits =</span> <span class="dv">7</span>, <span class="dt">pretty =</span> <span class="ot">TRUE</span>))</code></pre></div></li>
+<li><p>If you do not want to use <strong>jsonlite</strong>, you can completely override the serializer function by attaching an attribute <code>TOJSON_FUNC</code> to the widget data, e.g.</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">fooWidget <-<span class="st"> </span>function(data, name, ...) {
+  <span class="co"># ... process the data ...</span>
+  params <-<span class="st"> </span><span class="kw">list</span>(<span class="dt">foo =</span> data, <span class="dt">bar =</span> <span class="ot">TRUE</span>)
+  <span class="co"># customize the JSON serializer</span>
+  <span class="kw">attr</span>(params, <span class="st">'TOJSON_FUNC'</span>) <-<span class="st"> </span>MY_OWN_JSON_FUNCTION
+  htmlwidgets::<span class="kw">createWidget</span>(name, <span class="dt">x =</span> params, ...)
+}</code></pre></div>
+<p>Here <code>MY_OWN_JSON_FUNCTION</code> can be an arbitrary R function that converts R objects to JSON. If you have also specified the <code>TOJSON_ARGS</code> attribute, it will be passed to your custom JSON function as well.</p></li>
+</ol>
+<p>Note these features about custom JSON serializers require the <strong>shiny</strong> version to be greater than 0.11.1 if you render the widgets in Shiny apps.</p>
+</div>
+</div>
+<div id="passing-javascript-functions" class="section level2">
+<h2>Passing JavaScript functions</h2>
+<p>As you would expect, character vectors passed from R to JavaScript are converted to JavaScript strings. However, what if you want to allow users to provide custom JavaScript functions for formatting, drawing, or event handling? For this case, the <strong>htmlwidgets</strong> package includes a <code>JS()</code> function that allows you to request that a character value is evaluated as JavaScript when it is received on the client.</p>
+<p>For example, the <a href="https://rstudio.github.io/dygraphs">dygraphs</a> widget includes a <code>dyCallbacks</code> function that allows the user to provide callback functions for a variety of contexts. These callbacks are “marked” as containing JavaScript so that they can be converted to actual JavaScript functions on the client:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">callbacks <-<span class="st"> </span><span class="kw">list</span>(
+  <span class="dt">clickCallback =</span> <span class="kw">JS</span>(clickCallback)
+  <span class="dt">drawCallback =</span> <span class="kw">JS</span>(drawCallback)
+  <span class="dt">highlightCallback =</span> <span class="kw">JS</span>(highlightCallback)
+  <span class="dt">pointClickCallback =</span> <span class="kw">JS</span>(pointClickCallback)
+  <span class="dt">underlayCallback =</span> <span class="kw">JS</span>(underlayCallback)
+)</code></pre></div>
+<p>Another example is in the <a href="https://rstudio.github.io/DT">DT</a> (DataTables) widget, where users can specify an <code>initCallback</code> with JavaScript to execute after the table is loaded and initialized:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">datatable</span>(<span class="kw">head</span>(iris, <span class="dv">20</span>), <span class="dt">options =</span> <span class="kw">list</span>(
+  <span class="dt">initComplete =</span> <span class="kw">JS</span>(
+    <span class="st">"function(settings, json) {"</span>,
+    <span class="st">"$(this.api().table().header()).css({'background-color': '#000', 'color': '#fff'});"</span>,
+    <span class="st">"}"</span>)
+))</code></pre></div>
+<p>If multiple arguments are passed to <code>JS()</code> (as in the above example), they will be concatenated into a single string separated by <code>\n</code>.</p>
+</div>
+<div id="custom-widget-html" class="section level2">
+<h2>Custom widget HTML</h2>
+<p>Typically the HTML “housing” for a widget is just a <code><div></code> element, and this is correspondingly the default behavior for new widgets that don’t specify otherwise. However, sometimes you need a different element type. For example, the <a href="https://github.com/htmlwidgets/sparkline">sparkline</a> widget requires a <code><span></code> element so implements the following custom HTML generation function:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">sparkline_html <-<span class="st"> </span>function(id, style, class, ...){
+  tags$<span class="kw">span</span>(<span class="dt">id =</span> id, <span class="dt">class =</span> class)
+}</code></pre></div>
+<p>Note that this function is looked up within the package implementing the widget by the convention <code>widgetname_html</code> so it need not be formally exported from your package or otherwise registered with <strong>htmlwidgets</strong>.</p>
+<p>Most widgets won’t need a custom HTML function but if you need to generate custom HTML for your widget (e.g. you need an <code><input></code> or a <code><span></code> rather than a <code><div></code>) then you should use the <strong>htmltools</strong> package (as demonstrated by the code above).</p>
+</div>
+<div class="footnotes">
+<hr />
+<ol>
+<li id="fn1"><p>N.B. It is not exported from <strong>htmlwidgets</strong>, so you are not supposed to call this function directly.<a href="#fnref1">↩</a></p></li>
+</ol>
+</div>
+
+
+
+
+</div>
+
+<script>
+
+// add bootstrap table styles to pandoc tables
+function bootstrapStylePandocTables() {
+  $('tr.header').parent('thead').parent('table').addClass('table table-condensed');
+}
+$(document).ready(function () {
+  bootstrapStylePandocTables();
+});
+
+
+</script>
+
+
+</body>
+</html>
diff --git a/inst/doc/develop_intro.R b/inst/doc/develop_intro.R
new file mode 100644
index 0000000..d81b1b6
--- /dev/null
+++ b/inst/doc/develop_intro.R
@@ -0,0 +1,5 @@
+## ---- eval=FALSE---------------------------------------------------------
+#  library(sigma)
+#  data <- system.file("examples/ediaspora.gexf.xml", package = "sigma")
+#  sigma(data)
+
diff --git a/inst/doc/develop_intro.Rmd b/inst/doc/develop_intro.Rmd
new file mode 100644
index 0000000..258e025
--- /dev/null
+++ b/inst/doc/develop_intro.Rmd
@@ -0,0 +1,320 @@
+---
+title: "Introduction to HTML Widgets"
+date: "`r Sys.Date()`"
+output: 
+  html_document:
+    highlight: kate
+    toc: true
+    toc_depth: 4
+    mathjax: null
+vignette: >
+  %\VignetteIndexEntry{Introduction}
+  %\VignetteEngine{knitr::rmarkdown}
+  \usepackage[utf8]{inputenc}
+---
+
+## Overview
+
+The **[htmlwidgets](https://cran.r-project.org/package=htmlwidgets)** package provides a framework for creating R bindings to JavaScript libraries. HTML Widgets can be:
+
+* Used at the R console for data analysis just like conventional R plots.
+* Embedded within [R Markdown](http://rmarkdown.rstudio.com) documents
+* Incorporated into [Shiny](http://shiny.rstudio.com) web applications.
+* Saved as standalone web pages for ad-hoc sharing via email, Dropbox, etc.
+
+By following a small set of easy-to-follow conventions, it is possible to create HTML widgets with very little code. All widgets include the following components:
+
+1. **Dependencies**. These are the JavaScript and CSS assets used by the widget (e.g. the library you are creating a wrapper for).
+
+3. **R binding**. This is the function that end users will call to provide input data to the widget as well as specify various options for how the widget should render. This also includes some short boilerplate functions required to use the widget within Shiny applications.
+
+3. **JavaScript binding**. This is the JavaScript code that glues everything together, passing the data and options gathered in the R binding to the underlying JavaScript library.
+
+HTML widgets are always hosted within an R package and should include all of the source code for their dependencies. This is to ensure that code which depends on widgets is fully reproducible (i.e. doesn't require an internet connection or the ongoing availability of an internet service to run).
+
+## Example (sigma.js)
+
+To start with we'll walk through the creation of a simple widget that wraps the [sigma.js](http://sigmajs.org) graph visualization library. When we're done we'll be able to use it to display interactive visualizations of [GEXF](http://gexf.net) (Graph Exchange XML Format) data files. For example:
+
+```{r, eval=FALSE}
+library(sigma)
+data <- system.file("examples/ediaspora.gexf.xml", package = "sigma")
+sigma(data)
+```
+
+<img src="images/sigma.png" alt="sigma" data-toggle="tooltip" data-placement="right" title="" data-original-title="Note this is just an image of the visualization so it's not interactive. You can play with the interactive version by following the steps in the demo section below." onload="$(this).tooltip()">
+
+Note that the above is just an image of the visualization so it's not interactive. You can play with the interactive version by following the steps in the demo section below. 
+
+There is remarkably little code required to create this binding. Below we'll go through all of the components step-by-step. Then we'll describe how you can create your own widgets (including automatically generating basic scaffolding for all of the core components).
+
+### File layout
+
+Let's assume that our widget is named **sigma** and is located within an R package of the same name. Our JavaScript binding source code file is named sigma.js. Since our widget will read GEXF data files we'll also need to include both the base sigma.min.js library as well as its GEXF plugin. Here are the files that we'll add to the package:
+
+```text
+R/
+| sigma.R
+
+inst/
+|-- htmlwidgets/
+|   |-- sigma.js
+|   |-- sigma.yaml
+|   |-- lib/
+|   |   |-- sigma-1.0.3/
+|   |   |   |-- sigma.min.js
+|   |   |   |-- plugins/
+|   |   |   |   |-- sigma.parsers.gexf.min.js
+```
+
+Note the convention that the JavaScript, YAML, and other dependencies are all contained within the `inst/htmlwidgets` directory (which will subsequently be installed into a package sub-directory named `htmlwidgets`).
+
+### Dependencies
+
+Dependencies are the JavaScript and CSS assets used by a widget. Dependencies are included within the `inst/htmlwidgets/lib` directory. Dependencies are specified using a YAML configuration file which uses the name of the widget as its base file name. Here's what our **sigma.yaml** file looks like:
+
+```yaml
+dependencies:
+  - name: sigma
+    version: 1.0.3
+    src: htmlwidgets/lib/sigma-1.0.3
+    script: 
+      - sigma.min.js
+      - plugins/sigma.parsers.gexf.min.js
+```
+
+The dependency `src` specification refers to the directory that contains the library and `script` refers to specific JavaScript files. If your library contains multiple JavaScript files specify each one on a line beginning with `-` as shown here. You can also add `stylesheet` entries and even `meta` or `head` entries. Multiple dependencies may be specified in one YAML file. See the documentation on the `htmlDependency` function in the [**htmltools**](https://cran.r-project.org/package=ht [...]
+
+### R binding
+
+We need to provide users with an R function that invokes our widget. Typically this function will accept input data as well as various options that control the widget's display. Here's the R function for `sigma`:
+
+```r
+#' @import htmlwidgets
+#' @export
+sigma <- function(gexf, drawEdges = TRUE, drawNodes = TRUE,
+                  width = NULL, height = NULL) {
+  
+  # read the gexf file
+  data <- paste(readLines(gexf), collapse="\n")
+  
+  # create a list that contains the settings
+  settings <- list(
+    drawEdges = drawEdges,
+    drawNodes = drawNodes
+  )
+  
+  # pass the data and settings using 'x'
+  x <- list(
+    data = data,
+    settings = settings
+  )
+  
+  # create the widget
+  htmlwidgets::createWidget("sigma", x, width = width, height = height)
+}
+```
+
+The function takes two classes of input: the GEXF data file to render and some additional settings which control how it is rendered. This input is collected into a list named `x` which is then passed on to the `htmlwidgets::createWidget` function. This `x` variable will subsequently be made available to the JavaScript binding for sigma (this is described below). Any width or height parameter specified is also forwarded to the widget (widgets size themselves automatically by default so ty [...]
+
+We want our sigma widget to also work in Shiny applications, so we add the following boilerplate Shiny output and render functions (these are always the same for all widgets):
+
+```r
+#' @export
+sigmaOutput <- function(outputId, width = "100%", height = "400px") {
+  htmlwidgets::shinyWidgetOutput(outputId, "sigma", width, height, package = "sigma")
+}
+#' @export
+renderSigma <- function(expr, env = parent.frame(), quoted = FALSE) {
+  if (!quoted) { expr <- substitute(expr) } # force quoted
+  htmlwidgets::shinyRenderWidget(expr, sigmaOutput, env, quoted = TRUE)
+}
+```
+
+### JavaScript binding
+
+_**Note:** An older, less intuitive JavaScript binding API was used in htmlwidgets 0.5.2 and earlier, and continues to be supported in newer versions of htmlwidgets. See this [archived version](https://cdn.rawgit.com/ramnathv/htmlwidgets/f735840bf938d35d3c4143c0d16515da6ff252bd/develop_intro.html#javascript-binding) for details on the legacy binding API. New widgets are encouraged to use the newer API described below._
+
+The third piece in the puzzle is the JavaScript required to activate the widget. By convention we'll define our JavaScript binding in the file `inst/htmlwidgets/sigma.js`. Here is the full source code of the binding:
+
+```javascript
+HTMLWidgets.widget({
+
+  name: "sigma",
+  
+  type: "output",
+  
+  factory: function(el, width, height) {
+  
+    // create our sigma object and bind it to the element
+    var sig = new sigma(el.id);
+    
+    return {
+      renderValue: function(x) {
+          
+        // parse gexf data
+        var parser = new DOMParser();
+        var data = parser.parseFromString(x.data, "application/xml");
+        
+        // apply settings
+        for (var name in x.settings)
+          sig.settings(name, x.settings[name]);
+        
+        // update the sigma object
+        sigma.parsers.gexf(
+          data,          // parsed gexf data
+          sig,           // sigma object
+          function() {
+            // need to call refresh to reflect new settings and data
+            sig.refresh();
+          }
+        );
+      },
+      
+      resize: function(width, height) {
+        
+        // forward resize on to sigma renderers
+        for (var name in sig.renderers)
+          sig.renderers[name].resize(width, height);  
+      },
+      
+      // Make the sigma object available as a property on the widget
+      // instance we're returning from factory(). This is generally a
+      // good idea for extensibility--it helps users of this widget
+      // interact directly with sigma, if needed.
+      s: sig
+    };
+  }
+});
+```
+
+We provide a name and type for the widget, plus a `factory` function that takes `el` (the HTML element that will host this widget), `width`, and `height` (width and height of the HTML element, in pixels--you can always use `offsetWidth` and `offsetHeight` for this).
+
+The `factory` function should prepare the HTML element to start receiving values. In this case we create a new sigma element and pass it the `id` of the DOM element that hosts the widget on the page.
+
+We're going to need access to the sigma object later (to update its data and settings) so we save it as a variable `sig`. Note that variables declared directly inside of the factory function are tied to a particular widget instance/`el`.
+
+The return value of the `factory` function is called a _widget instance object_. It is a bridge between the htmlwidgets runtime, and the JavaScript visualization that you're wrapping. As the name implies, each widget instance object is responsible for managing a single widget instance on a page.
+
+The widget instance object you create must have one required method, and may have one optional method:
+
+1. The required `renderValue` method actually pours our dynamic data and settings into the widget's DOM element. The `x` parameter contains the widget data and settings. We parse and update the GEXF data, apply the settings to our previously-created `sig` sigma object, and finally call `refresh` to reflect the new values on-screen. This method may be called repeatedly with different data (i.e. in Shiny), so be sure to account for that possibility. If it makes sense for your widget, consi [...]
+
+2. The optional `resize` method is called whenever the element containing the widget is resized. The only reason not to implement this method is if your widget naturally scales (without additional JavaScript code needing to be invoked) when its element size changes. In the case of sigma.js, we forward the sizing information on to each of the underlying sigma renderers.
+
+All JavaScript libraries handle initialization, binding to DOM elements, dynamically updating data, and resizing slightly differently. Most of the work on the JavaScript side of creating widgets is mapping these three functions---`factory`, `renderValue`, and `resize`---correctly onto the behavior of the underlying library.
+
+The sigma.js example uses a simple object literal to create its widget instance object, but you can also use [class based objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Custom_objects) or any other style of object, as long as `obj.renderValue(x)` and `obj.resize(width, height)` can be invoked on it.
+
+You can add additional methods and properties on the widget instance object. Although they won't be called by htmlwidgets itself, they might be useful to users of your widget that know some JavaScript and want to further customize your widget by adding custom JS code (e.g. using the `htmlwidgets::onRender` R function). In this case we add an `s` property to make the sigma object itself available.
+
+### Demo
+
+Our widget is now complete! If you want to test drive it without reproducing all of the code locally you can install it from GitHub as follows:
+
+```r
+devtools::install_github('jjallaire/sigma')
+```
+
+Here's the code to try it out with some sample data included with the package:
+
+```r
+library(sigma)
+sigma(system.file("examples/ediaspora.gexf.xml", package = "sigma"))
+```
+
+If you execute this code in the R console you'll see the widget displayed in the RStudio Viewer (or in an external browser if you aren't running RStudio). If you include it within an R Markdown document the widget will be embedded into the document.
+
+We can also use the widget in a Shiny application:
+
+```r
+library(shiny)
+library(sigma)
+
+gexf <- system.file("examples/ediaspora.gexf.xml", package = "sigma")
+
+ui = shinyUI(fluidPage(
+  checkboxInput("drawEdges", "Draw Edges", value = TRUE),
+  checkboxInput("drawNodes", "Draw Nodes", value = TRUE),
+  sigmaOutput('sigma')
+))
+
+server = function(input, output) {
+  output$sigma <- renderSigma(
+    sigma(gexf, 
+          drawEdges = input$drawEdges, 
+          drawNodes = input$drawNodes)
+  )
+}
+
+shinyApp(ui = ui, server = server)
+```
+
+## Creating your own widgets
+
+### Requirements
+
+To implement a widget you need to create a new R package that in turn depends on the **htmlwidgets** package. You can install the package from CRAN as follows:
+
+```r
+install.packages("htmlwidgets")
+```
+
+While it's not strictly required, the step-by-step instructions below for getting started also make use of the **devtools** package which you can also install from CRAN:
+
+```r
+install.packages("devtools")
+```
+
+### Scaffolding
+
+To create a new widget you can call the `scaffoldWidget` function to generate the basic structure for your widget. This function will:
+
+* Create the .R, .js, and .yaml files required for your widget;
+
+* If provided, take a [Bower](https://bower.io/) package name and automatically download the JavaScript library (and its dependencies) and add the required entries to the .yaml file.
+
+This method is highly recommended as it ensures that you get started with the right file structure. Here's an example that assumes you want to create a widget named 'mywidget' in a new package of the same name:
+
+```r
+devtools::create("mywidget")               # create package using devtools
+setwd("mywidget")                          # navigate to package dir
+htmlwidgets::scaffoldWidget("mywidget")    # create widget scaffolding
+devtools::install()                        # install the package so we can try it
+```
+
+This creates a simple widget that takes a single `text` argument and displays that text within the widgets HTML element. You can try it like this:
+
+```r
+library(mywidget)
+mywidget("hello, world")
+```
+
+This is the most minimal widget possible and doesn't yet include a JavaScript library to interface to (note that `scaffoldWidget` can optionally include JavaScript library dependencies via the `bowerPkg` argument). Before getting started with development you should review the introductory example above to make sure you understand the various components and also review the additional articles and examples linked to in the next section.
+
+### Learning more
+
+#### Additional articles
+
+There are additional articles that cover more advanced ground:
+
+* [HTML Widget Sizing](develop_sizing.html) explains custom sizing policies and when you might need to use them and describes implementing a `resize` method within JavaScript bindings.
+
+* [HTML Widgets: Advanced Topics](develop_advanced.html) describes framework features that support per-widget instance data, data transformations (e.g. converting a data frame into a d3 dataset), and providing widget options that are live JavaScript objects (e.g. function definitions).
+
+The Sizing article is particularly important as most JavaScript libraries require some additional interaction to keep their size synchronized with their containing element.
+
+#### Examples
+
+Studying the code of other packages is a great way to learn more about creating widgets:
+
+1. The [networkD3](https://github.com/christophergandrud/networkD3) package illustrates creating a widget on top of [D3](http://d3js.org), using a custom sizing policy for a larger widget, and providing multiple widgets from a single package.
+
+2. The [dygraphs](https://github.com/rstudio/dygraphs/) package illustrates using widget instance data, handling dynamic re-sizing, and using [magrittr](https://github.com/smbache/magrittr) to decompose a large and flat JavaScript API into a more modular and pipeable R API.
+
+3. The [sparkline](https://github.com/htmlwidgets/sparkline) package illustrates  providing a custom HTML generation function (since sparklines must be housed in `<span>` rather than `<div>` elements).
+ 
+#### Questions and issues
+
+If you have questions about developing widgets or run into problems during development please don't hesitate to [post an issue](https://github.com/ramnathv/htmlwidgets/issues) on the project's GitHub repository.
+
diff --git a/inst/doc/develop_intro.html b/inst/doc/develop_intro.html
new file mode 100644
index 0000000..4a433d6
--- /dev/null
+++ b/inst/doc/develop_intro.html
@@ -0,0 +1,435 @@
+<!DOCTYPE html>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+
+<meta charset="utf-8">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="pandoc" />
+
+
+
+<meta name="date" content="2016-11-09" />
+
+<title>Introduction to HTML Widgets</title>
+
+<script src="data:application/x-javascript;base64,LyohIGpRdWVyeSB2MS4xMS4zIHwgKGMpIDIwMDUsIDIwMTUgalF1ZXJ5IEZvdW5kYXRpb24sIEluYy4gfCBqcXVlcnkub3JnL2xpY2Vuc2UgKi8KIWZ1bmN0aW9uKGEsYil7Im9iamVjdCI9PXR5cGVvZiBtb2R1bGUmJiJvYmplY3QiPT10eXBlb2YgbW9kdWxlLmV4cG9ydHM/bW9kdWxlLmV4cG9ydHM9YS5kb2N1bWVudD9iKGEsITApOmZ1bmN0aW9uKGEpe2lmKCFhLmRvY3VtZW50KXRocm93IG5ldyBFcnJvcigialF1ZXJ5IHJlcXVpcmVzIGEgd2luZG93IHdpdGggYSBkb2N1bWVudCIpO3JldHVybiBiKGEpfTpiKGEpfSgidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdz93aW5kb3c6dG [...]
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<link href="data:text/css;charset=utf-8,html%7Bfont%2Dfamily%3Asans%2Dserif%3B%2Dwebkit%2Dtext%2Dsize%2Dadjust%3A100%25%3B%2Dms%2Dtext%2Dsize%2Dadjust%3A100%25%7Dbody%7Bmargin%3A0%7Darticle%2Caside%2Cdetails%2Cfigcaption%2Cfigure%2Cfooter%2Cheader%2Chgroup%2Cmain%2Cmenu%2Cnav%2Csection%2Csummary%7Bdisplay%3Ablock%7Daudio%2Ccanvas%2Cprogress%2Cvideo%7Bdisplay%3Ainline%2Dblock%3Bvertical%2Dalign%3Abaseline%7Daudio%3Anot%28%5Bcontrols%5D%29%7Bdisplay%3Anone%3Bheight%3A0%7D%5Bhidden%5D%2Ctem [...]
+<script src="data:application/x-javascript;base64,LyohCiAqIEJvb3RzdHJhcCB2My4zLjUgKGh0dHA6Ly9nZXRib290c3RyYXAuY29tKQogKiBDb3B5cmlnaHQgMjAxMS0yMDE1IFR3aXR0ZXIsIEluYy4KICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlCiAqLwppZigidW5kZWZpbmVkIj09dHlwZW9mIGpRdWVyeSl0aHJvdyBuZXcgRXJyb3IoIkJvb3RzdHJhcCdzIEphdmFTY3JpcHQgcmVxdWlyZXMgalF1ZXJ5Iik7K2Z1bmN0aW9uKGEpeyJ1c2Ugc3RyaWN0Ijt2YXIgYj1hLmZuLmpxdWVyeS5zcGxpdCgiICIpWzBdLnNwbGl0KCIuIik7aWYoYlswXTwyJiZiWzFdPDl8fDE9PWJbMF0mJjk9PWJbMV0mJmJbMl08MSl0aHJvdy [...]
+<script src="data:application/x-javascript;base64,LyoqCiogQHByZXNlcnZlIEhUTUw1IFNoaXYgMy43LjIgfCBAYWZhcmthcyBAamRhbHRvbiBAam9uX25lYWwgQHJlbSB8IE1JVC9HUEwyIExpY2Vuc2VkCiovCi8vIE9ubHkgcnVuIHRoaXMgY29kZSBpbiBJRSA4CmlmICghIXdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKCJNU0lFIDgiKSkgewohZnVuY3Rpb24oYSxiKXtmdW5jdGlvbiBjKGEsYil7dmFyIGM9YS5jcmVhdGVFbGVtZW50KCJwIiksZD1hLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJoZWFkIilbMF18fGEuZG9jdW1lbnRFbGVtZW50O3JldHVybiBjLmlubmVySFRNTD0ieDxzdHlsZT4iK2IrIjwvc3R5bGU+IixkLm [...]
+<script src="data:application/x-javascript;base64,LyohIFJlc3BvbmQuanMgdjEuNC4yOiBtaW4vbWF4LXdpZHRoIG1lZGlhIHF1ZXJ5IHBvbHlmaWxsICogQ29weXJpZ2h0IDIwMTMgU2NvdHQgSmVobAogKiBMaWNlbnNlZCB1bmRlciBodHRwczovL2dpdGh1Yi5jb20vc2NvdHRqZWhsL1Jlc3BvbmQvYmxvYi9tYXN0ZXIvTElDRU5TRS1NSVQKICogICovCgovLyBPbmx5IHJ1biB0aGlzIGNvZGUgaW4gSUUgOAppZiAoISF3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgiTVNJRSA4IikpIHsKIWZ1bmN0aW9uKGEpeyJ1c2Ugc3RyaWN0IjthLm1hdGNoTWVkaWE9YS5tYXRjaE1lZGlhfHxmdW5jdGlvbihhKXt2YXIgYixjPWEuZG [...]
+<script src="data:application/x-javascript;base64,Cgp3aW5kb3cuYnVpbGRUYWJzZXRzID0gZnVuY3Rpb24odG9jSUQpIHsKCiAgLy8gYnVpbGQgYSB0YWJzZXQgZnJvbSBhIHNlY3Rpb24gZGl2IHdpdGggdGhlIC50YWJzZXQgY2xhc3MKICBmdW5jdGlvbiBidWlsZFRhYnNldCh0YWJzZXQpIHsKCiAgICAvLyBjaGVjayBmb3IgZmFkZSBhbmQgcGlsbHMgb3B0aW9ucwogICAgdmFyIGZhZGUgPSB0YWJzZXQuaGFzQ2xhc3MoInRhYnNldC1mYWRlIik7CiAgICB2YXIgcGlsbHMgPSB0YWJzZXQuaGFzQ2xhc3MoInRhYnNldC1waWxscyIpOwogICAgdmFyIG5hdkNsYXNzID0gcGlsbHMgPyAibmF2LXBpbGxzIiA6ICJuYXYtdGFicyI7CgogIC [...]
+
+
+<style type="text/css">code{white-space: pre;}</style>
+<style type="text/css">
+div.sourceCode { overflow-x: auto; }
+table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
+  margin: 0; padding: 0; vertical-align: baseline; border: none; }
+table.sourceCode { width: 100%; line-height: 100%; }
+td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; background-color: #dddddd; }
+td.sourceCode { padding-left: 5px; }
+code > span.kw { font-weight: bold; } /* Keyword */
+code > span.dt { color: #800000; } /* DataType */
+code > span.dv { color: #0000ff; } /* DecVal */
+code > span.bn { color: #0000ff; } /* BaseN */
+code > span.fl { color: #800080; } /* Float */
+code > span.ch { color: #ff00ff; } /* Char */
+code > span.st { color: #dd0000; } /* String */
+code > span.co { color: #808080; font-style: italic; } /* Comment */
+code > span.al { color: #00ff00; font-weight: bold; } /* Alert */
+code > span.fu { color: #000080; } /* Function */
+code > span.er { color: #ff0000; font-weight: bold; } /* Error */
+code > span.wa { color: #ff0000; font-weight: bold; } /* Warning */
+code > span.cn { color: #000000; } /* Constant */
+code > span.sc { color: #ff00ff; } /* SpecialChar */
+code > span.vs { color: #dd0000; } /* VerbatimString */
+code > span.ss { color: #dd0000; } /* SpecialString */
+code > span.im { } /* Import */
+code > span.va { } /* Variable */
+code > span.cf { } /* ControlFlow */
+code > span.op { } /* Operator */
+code > span.bu { } /* BuiltIn */
+code > span.ex { } /* Extension */
+code > span.pp { font-weight: bold; } /* Preprocessor */
+code > span.at { } /* Attribute */
+code > span.do { color: #808080; font-style: italic; } /* Documentation */
+code > span.an { color: #808080; font-weight: bold; font-style: italic; } /* Annotation */
+code > span.cv { color: #808080; font-weight: bold; font-style: italic; } /* CommentVar */
+code > span.in { color: #808080; font-weight: bold; font-style: italic; } /* Information */
+</style>
+<style type="text/css">
+  pre:not([class]) {
+    background-color: white;
+  }
+</style>
+
+
+<style type="text/css">
+h1 {
+  font-size: 34px;
+}
+h1.title {
+  font-size: 38px;
+}
+h2 {
+  font-size: 30px;
+}
+h3 {
+  font-size: 24px;
+}
+h4 {
+  font-size: 18px;
+}
+h5 {
+  font-size: 16px;
+}
+h6 {
+  font-size: 12px;
+}
+.table th:not([align]) {
+  text-align: left;
+}
+</style>
+
+
+</head>
+
+<body>
+
+<style type="text/css">
+.main-container {
+  max-width: 940px;
+  margin-left: auto;
+  margin-right: auto;
+}
+code {
+  color: inherit;
+  background-color: rgba(0, 0, 0, 0.04);
+}
+img {
+  max-width:100%;
+  height: auto;
+}
+.tabbed-pane {
+  padding-top: 12px;
+}
+button.code-folding-btn:focus {
+  outline: none;
+}
+</style>
+
+
+
+<div class="container-fluid main-container">
+
+<!-- tabsets -->
+<script>
+$(document).ready(function () {
+  window.buildTabsets("TOC");
+});
+</script>
+
+<!-- code folding -->
+
+
+
+
+
+
+<div class="fluid-row" id="header">
+
+
+
+<h1 class="title toc-ignore">Introduction to HTML Widgets</h1>
+<h4 class="date"><em>2016-11-09</em></h4>
+
+</div>
+
+<div id="TOC">
+<ul>
+<li><a href="#overview">Overview</a></li>
+<li><a href="#example-sigma.js">Example (sigma.js)</a><ul>
+<li><a href="#file-layout">File layout</a></li>
+<li><a href="#dependencies">Dependencies</a></li>
+<li><a href="#r-binding">R binding</a></li>
+<li><a href="#javascript-binding">JavaScript binding</a></li>
+<li><a href="#demo">Demo</a></li>
+</ul></li>
+<li><a href="#creating-your-own-widgets">Creating your own widgets</a><ul>
+<li><a href="#requirements">Requirements</a></li>
+<li><a href="#scaffolding">Scaffolding</a></li>
+<li><a href="#learning-more">Learning more</a><ul>
+<li><a href="#additional-articles">Additional articles</a></li>
+<li><a href="#examples">Examples</a></li>
+<li><a href="#questions-and-issues">Questions and issues</a></li>
+</ul></li>
+</ul></li>
+</ul>
+</div>
+
+<div id="overview" class="section level2">
+<h2>Overview</h2>
+<p>The <strong><a href="https://cran.r-project.org/package=htmlwidgets">htmlwidgets</a></strong> package provides a framework for creating R bindings to JavaScript libraries. HTML Widgets can be:</p>
+<ul>
+<li>Used at the R console for data analysis just like conventional R plots.</li>
+<li>Embedded within <a href="http://rmarkdown.rstudio.com">R Markdown</a> documents</li>
+<li>Incorporated into <a href="http://shiny.rstudio.com">Shiny</a> web applications.</li>
+<li>Saved as standalone web pages for ad-hoc sharing via email, Dropbox, etc.</li>
+</ul>
+<p>By following a small set of easy-to-follow conventions, it is possible to create HTML widgets with very little code. All widgets include the following components:</p>
+<ol style="list-style-type: decimal">
+<li><p><strong>Dependencies</strong>. These are the JavaScript and CSS assets used by the widget (e.g. the library you are creating a wrapper for).</p></li>
+<li><p><strong>R binding</strong>. This is the function that end users will call to provide input data to the widget as well as specify various options for how the widget should render. This also includes some short boilerplate functions required to use the widget within Shiny applications.</p></li>
+<li><p><strong>JavaScript binding</strong>. This is the JavaScript code that glues everything together, passing the data and options gathered in the R binding to the underlying JavaScript library.</p></li>
+</ol>
+<p>HTML widgets are always hosted within an R package and should include all of the source code for their dependencies. This is to ensure that code which depends on widgets is fully reproducible (i.e. doesn’t require an internet connection or the ongoing availability of an internet service to run).</p>
+</div>
+<div id="example-sigma.js" class="section level2">
+<h2>Example (sigma.js)</h2>
+<p>To start with we’ll walk through the creation of a simple widget that wraps the <a href="http://sigmajs.org">sigma.js</a> graph visualization library. When we’re done we’ll be able to use it to display interactive visualizations of <a href="http://gexf.net">GEXF</a> (Graph Exchange XML Format) data files. For example:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(sigma)
+data <-<span class="st"> </span><span class="kw">system.file</span>(<span class="st">"examples/ediaspora.gexf.xml"</span>, <span class="dt">package =</span> <span class="st">"sigma"</span>)
+<span class="kw">sigma</span>(data)</code></pre></div>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfAAAAFsCAYAAAAzCOveAAAMRmlDQ1BJQ0MgUHJvZmlsZQAASA2tV2dYE1kXPlOSQEhCCURASuhNlF6ld0FBqrAWQhJIKDEEgorddXEF14KKBSu6KmJbXQFZCyJ2F8XuWj7URUFZFws2VL47objfPrv/vnmee+ed95x75j1n7ty5A6BpK5DLc3EtgDxZoSI+Ipg/ITWNz3gATDAFTbAFPYGwQB4UFxcD/3q8vQkYZbzmSMX6V7d/NmiLxAVCACwOmTNEBcI8hH8GIDlCuaIQgNaMeItphXIKdyCsq0ACEf5E4SwVpiP1oJvRjy1VPonxIQB0LwA1lkCgyALghCKeXyTMQnE4IoSdZCKpDOFVCPsLJQLEca4jPCIvbyrCmgiCbcZf4mT9BQsEGUMxBYKsIdyfCzUU1EKlBfJcwQzVxf+zy8tVo [...]
+<p>Note that the above is just an image of the visualization so it’s not interactive. You can play with the interactive version by following the steps in the demo section below.</p>
+<p>There is remarkably little code required to create this binding. Below we’ll go through all of the components step-by-step. Then we’ll describe how you can create your own widgets (including automatically generating basic scaffolding for all of the core components).</p>
+<div id="file-layout" class="section level3">
+<h3>File layout</h3>
+<p>Let’s assume that our widget is named <strong>sigma</strong> and is located within an R package of the same name. Our JavaScript binding source code file is named sigma.js. Since our widget will read GEXF data files we’ll also need to include both the base sigma.min.js library as well as its GEXF plugin. Here are the files that we’ll add to the package:</p>
+<pre class="text"><code>R/
+| sigma.R
+
+inst/
+|-- htmlwidgets/
+|   |-- sigma.js
+|   |-- sigma.yaml
+|   |-- lib/
+|   |   |-- sigma-1.0.3/
+|   |   |   |-- sigma.min.js
+|   |   |   |-- plugins/
+|   |   |   |   |-- sigma.parsers.gexf.min.js</code></pre>
+<p>Note the convention that the JavaScript, YAML, and other dependencies are all contained within the <code>inst/htmlwidgets</code> directory (which will subsequently be installed into a package sub-directory named <code>htmlwidgets</code>).</p>
+</div>
+<div id="dependencies" class="section level3">
+<h3>Dependencies</h3>
+<p>Dependencies are the JavaScript and CSS assets used by a widget. Dependencies are included within the <code>inst/htmlwidgets/lib</code> directory. Dependencies are specified using a YAML configuration file which uses the name of the widget as its base file name. Here’s what our <strong>sigma.yaml</strong> file looks like:</p>
+<div class="sourceCode"><pre class="sourceCode yaml"><code class="sourceCode yaml"><span class="fu">dependencies:</span>
+  <span class="kw">-</span> <span class="fu">name:</span> sigma
+    <span class="fu">version:</span> 1.0.3
+    <span class="fu">src:</span> htmlwidgets/lib/sigma-1.0.3
+    <span class="fu">script:</span> 
+      <span class="kw">-</span> sigma.min.js
+      <span class="kw">-</span> plugins/sigma.parsers.gexf.min.js</code></pre></div>
+<p>The dependency <code>src</code> specification refers to the directory that contains the library and <code>script</code> refers to specific JavaScript files. If your library contains multiple JavaScript files specify each one on a line beginning with <code>-</code> as shown here. You can also add <code>stylesheet</code> entries and even <code>meta</code> or <code>head</code> entries. Multiple dependencies may be specified in one YAML file. See the documentation on the <code>htmlDepende [...]
+</div>
+<div id="r-binding" class="section level3">
+<h3>R binding</h3>
+<p>We need to provide users with an R function that invokes our widget. Typically this function will accept input data as well as various options that control the widget’s display. Here’s the R function for <code>sigma</code>:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="co">#' @import htmlwidgets</span>
+<span class="co">#' @export</span>
+sigma <-<span class="st"> </span>function(gexf, <span class="dt">drawEdges =</span> <span class="ot">TRUE</span>, <span class="dt">drawNodes =</span> <span class="ot">TRUE</span>,
+                  <span class="dt">width =</span> <span class="ot">NULL</span>, <span class="dt">height =</span> <span class="ot">NULL</span>) {
+  
+  <span class="co"># read the gexf file</span>
+  data <-<span class="st"> </span><span class="kw">paste</span>(<span class="kw">readLines</span>(gexf), <span class="dt">collapse=</span><span class="st">"</span><span class="ch">\n</span><span class="st">"</span>)
+  
+  <span class="co"># create a list that contains the settings</span>
+  settings <-<span class="st"> </span><span class="kw">list</span>(
+    <span class="dt">drawEdges =</span> drawEdges,
+    <span class="dt">drawNodes =</span> drawNodes
+  )
+  
+  <span class="co"># pass the data and settings using 'x'</span>
+  x <-<span class="st"> </span><span class="kw">list</span>(
+    <span class="dt">data =</span> data,
+    <span class="dt">settings =</span> settings
+  )
+  
+  <span class="co"># create the widget</span>
+  htmlwidgets::<span class="kw">createWidget</span>(<span class="st">"sigma"</span>, x, <span class="dt">width =</span> width, <span class="dt">height =</span> height)
+}</code></pre></div>
+<p>The function takes two classes of input: the GEXF data file to render and some additional settings which control how it is rendered. This input is collected into a list named <code>x</code> which is then passed on to the <code>htmlwidgets::createWidget</code> function. This <code>x</code> variable will subsequently be made available to the JavaScript binding for sigma (this is described below). Any width or height parameter specified is also forwarded to the widget (widgets size thems [...]
+<p>We want our sigma widget to also work in Shiny applications, so we add the following boilerplate Shiny output and render functions (these are always the same for all widgets):</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="co">#' @export</span>
+sigmaOutput <-<span class="st"> </span>function(outputId, <span class="dt">width =</span> <span class="st">"100%"</span>, <span class="dt">height =</span> <span class="st">"400px"</span>) {
+  htmlwidgets::<span class="kw">shinyWidgetOutput</span>(outputId, <span class="st">"sigma"</span>, width, height, <span class="dt">package =</span> <span class="st">"sigma"</span>)
+}
+<span class="co">#' @export</span>
+renderSigma <-<span class="st"> </span>function(expr, <span class="dt">env =</span> <span class="kw">parent.frame</span>(), <span class="dt">quoted =</span> <span class="ot">FALSE</span>) {
+  if (!quoted) { expr <-<span class="st"> </span><span class="kw">substitute</span>(expr) } <span class="co"># force quoted</span>
+  htmlwidgets::<span class="kw">shinyRenderWidget</span>(expr, sigmaOutput, env, <span class="dt">quoted =</span> <span class="ot">TRUE</span>)
+}</code></pre></div>
+</div>
+<div id="javascript-binding" class="section level3">
+<h3>JavaScript binding</h3>
+<p><em><strong>Note:</strong> An older, less intuitive JavaScript binding API was used in htmlwidgets 0.5.2 and earlier, and continues to be supported in newer versions of htmlwidgets. See this <a href="https://cdn.rawgit.com/ramnathv/htmlwidgets/f735840bf938d35d3c4143c0d16515da6ff252bd/develop_intro.html#javascript-binding">archived version</a> for details on the legacy binding API. New widgets are encouraged to use the newer API described below.</em></p>
+<p>The third piece in the puzzle is the JavaScript required to activate the widget. By convention we’ll define our JavaScript binding in the file <code>inst/htmlwidgets/sigma.js</code>. Here is the full source code of the binding:</p>
+<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">HTMLWidgets</span>.<span class="at">widget</span>(<span class="op">{</span>
+
+  <span class="dt">name</span><span class="op">:</span> <span class="st">"sigma"</span><span class="op">,</span>
+  
+  <span class="dt">type</span><span class="op">:</span> <span class="st">"output"</span><span class="op">,</span>
+  
+  <span class="dt">factory</span><span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> width<span class="op">,</span> height) <span class="op">{</span>
+  
+    <span class="co">// create our sigma object and bind it to the element</span>
+    <span class="kw">var</span> sig <span class="op">=</span> <span class="kw">new</span> <span class="at">sigma</span>(<span class="va">el</span>.<span class="at">id</span>)<span class="op">;</span>
+    
+    <span class="cf">return</span> <span class="op">{</span>
+      <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span>
+          
+        <span class="co">// parse gexf data</span>
+        <span class="kw">var</span> parser <span class="op">=</span> <span class="kw">new</span> <span class="at">DOMParser</span>()<span class="op">;</span>
+        <span class="kw">var</span> data <span class="op">=</span> <span class="va">parser</span>.<span class="at">parseFromString</span>(<span class="va">x</span>.<span class="at">data</span><span class="op">,</span> <span class="st">"application/xml"</span>)<span class="op">;</span>
+        
+        <span class="co">// apply settings</span>
+        <span class="cf">for</span> (<span class="kw">var</span> name <span class="kw">in</span> <span class="va">x</span>.<span class="at">settings</span>)
+          <span class="va">sig</span>.<span class="at">settings</span>(name<span class="op">,</span> <span class="va">x</span>.<span class="at">settings</span>[name])<span class="op">;</span>
+        
+        <span class="co">// update the sigma object</span>
+        <span class="va">sigma</span>.<span class="va">parsers</span>.<span class="at">gexf</span>(
+          data<span class="op">,</span>          <span class="co">// parsed gexf data</span>
+          sig<span class="op">,</span>           <span class="co">// sigma object</span>
+          <span class="kw">function</span>() <span class="op">{</span>
+            <span class="co">// need to call refresh to reflect new settings and data</span>
+            <span class="va">sig</span>.<span class="at">refresh</span>()<span class="op">;</span>
+          <span class="op">}</span>
+        )<span class="op">;</span>
+      <span class="op">},</span>
+      
+      <span class="dt">resize</span><span class="op">:</span> <span class="kw">function</span>(width<span class="op">,</span> height) <span class="op">{</span>
+        
+        <span class="co">// forward resize on to sigma renderers</span>
+        <span class="cf">for</span> (<span class="kw">var</span> name <span class="kw">in</span> <span class="va">sig</span>.<span class="at">renderers</span>)
+          <span class="va">sig</span>.<span class="at">renderers</span>[name].<span class="at">resize</span>(width<span class="op">,</span> height)<span class="op">;</span>  
+      <span class="op">},</span>
+      
+      <span class="co">// Make the sigma object available as a property on the widget</span>
+      <span class="co">// instance we're returning from factory(). This is generally a</span>
+      <span class="co">// good idea for extensibility--it helps users of this widget</span>
+      <span class="co">// interact directly with sigma, if needed.</span>
+      <span class="dt">s</span><span class="op">:</span> sig
+    <span class="op">};</span>
+  <span class="op">}</span>
+<span class="op">}</span>)<span class="op">;</span></code></pre></div>
+<p>We provide a name and type for the widget, plus a <code>factory</code> function that takes <code>el</code> (the HTML element that will host this widget), <code>width</code>, and <code>height</code> (width and height of the HTML element, in pixels–you can always use <code>offsetWidth</code> and <code>offsetHeight</code> for this).</p>
+<p>The <code>factory</code> function should prepare the HTML element to start receiving values. In this case we create a new sigma element and pass it the <code>id</code> of the DOM element that hosts the widget on the page.</p>
+<p>We’re going to need access to the sigma object later (to update its data and settings) so we save it as a variable <code>sig</code>. Note that variables declared directly inside of the factory function are tied to a particular widget instance/<code>el</code>.</p>
+<p>The return value of the <code>factory</code> function is called a <em>widget instance object</em>. It is a bridge between the htmlwidgets runtime, and the JavaScript visualization that you’re wrapping. As the name implies, each widget instance object is responsible for managing a single widget instance on a page.</p>
+<p>The widget instance object you create must have one required method, and may have one optional method:</p>
+<ol style="list-style-type: decimal">
+<li><p>The required <code>renderValue</code> method actually pours our dynamic data and settings into the widget’s DOM element. The <code>x</code> parameter contains the widget data and settings. We parse and update the GEXF data, apply the settings to our previously-created <code>sig</code> sigma object, and finally call <code>refresh</code> to reflect the new values on-screen. This method may be called repeatedly with different data (i.e. in Shiny), so be sure to account for that possi [...]
+<li><p>The optional <code>resize</code> method is called whenever the element containing the widget is resized. The only reason not to implement this method is if your widget naturally scales (without additional JavaScript code needing to be invoked) when its element size changes. In the case of sigma.js, we forward the sizing information on to each of the underlying sigma renderers.</p></li>
+</ol>
+<p>All JavaScript libraries handle initialization, binding to DOM elements, dynamically updating data, and resizing slightly differently. Most of the work on the JavaScript side of creating widgets is mapping these three functions—<code>factory</code>, <code>renderValue</code>, and <code>resize</code>—correctly onto the behavior of the underlying library.</p>
+<p>The sigma.js example uses a simple object literal to create its widget instance object, but you can also use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Custom_objects">class based objects</a> or any other style of object, as long as <code>obj.renderValue(x)</code> and <code>obj.resize(width, height)</code> can be invoked on it.</p>
+<p>You can add additional methods and properties on the widget instance object. Although they won’t be called by htmlwidgets itself, they might be useful to users of your widget that know some JavaScript and want to further customize your widget by adding custom JS code (e.g. using the <code>htmlwidgets::onRender</code> R function). In this case we add an <code>s</code> property to make the sigma object itself available.</p>
+</div>
+<div id="demo" class="section level3">
+<h3>Demo</h3>
+<p>Our widget is now complete! If you want to test drive it without reproducing all of the code locally you can install it from GitHub as follows:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">devtools::<span class="kw">install_github</span>(<span class="st">'jjallaire/sigma'</span>)</code></pre></div>
+<p>Here’s the code to try it out with some sample data included with the package:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(sigma)
+<span class="kw">sigma</span>(<span class="kw">system.file</span>(<span class="st">"examples/ediaspora.gexf.xml"</span>, <span class="dt">package =</span> <span class="st">"sigma"</span>))</code></pre></div>
+<p>If you execute this code in the R console you’ll see the widget displayed in the RStudio Viewer (or in an external browser if you aren’t running RStudio). If you include it within an R Markdown document the widget will be embedded into the document.</p>
+<p>We can also use the widget in a Shiny application:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(shiny)
+<span class="kw">library</span>(sigma)
+
+gexf <-<span class="st"> </span><span class="kw">system.file</span>(<span class="st">"examples/ediaspora.gexf.xml"</span>, <span class="dt">package =</span> <span class="st">"sigma"</span>)
+
+ui =<span class="st"> </span><span class="kw">shinyUI</span>(<span class="kw">fluidPage</span>(
+  <span class="kw">checkboxInput</span>(<span class="st">"drawEdges"</span>, <span class="st">"Draw Edges"</span>, <span class="dt">value =</span> <span class="ot">TRUE</span>),
+  <span class="kw">checkboxInput</span>(<span class="st">"drawNodes"</span>, <span class="st">"Draw Nodes"</span>, <span class="dt">value =</span> <span class="ot">TRUE</span>),
+  <span class="kw">sigmaOutput</span>(<span class="st">'sigma'</span>)
+))
+
+server =<span class="st"> </span>function(input, output) {
+  output$sigma <-<span class="st"> </span><span class="kw">renderSigma</span>(
+    <span class="kw">sigma</span>(gexf, 
+          <span class="dt">drawEdges =</span> input$drawEdges, 
+          <span class="dt">drawNodes =</span> input$drawNodes)
+  )
+}
+
+<span class="kw">shinyApp</span>(<span class="dt">ui =</span> ui, <span class="dt">server =</span> server)</code></pre></div>
+</div>
+</div>
+<div id="creating-your-own-widgets" class="section level2">
+<h2>Creating your own widgets</h2>
+<div id="requirements" class="section level3">
+<h3>Requirements</h3>
+<p>To implement a widget you need to create a new R package that in turn depends on the <strong>htmlwidgets</strong> package. You can install the package from CRAN as follows:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">install.packages</span>(<span class="st">"htmlwidgets"</span>)</code></pre></div>
+<p>While it’s not strictly required, the step-by-step instructions below for getting started also make use of the <strong>devtools</strong> package which you can also install from CRAN:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">install.packages</span>(<span class="st">"devtools"</span>)</code></pre></div>
+</div>
+<div id="scaffolding" class="section level3">
+<h3>Scaffolding</h3>
+<p>To create a new widget you can call the <code>scaffoldWidget</code> function to generate the basic structure for your widget. This function will:</p>
+<ul>
+<li><p>Create the .R, .js, and .yaml files required for your widget;</p></li>
+<li><p>If provided, take a <a href="https://bower.io/">Bower</a> package name and automatically download the JavaScript library (and its dependencies) and add the required entries to the .yaml file.</p></li>
+</ul>
+<p>This method is highly recommended as it ensures that you get started with the right file structure. Here’s an example that assumes you want to create a widget named ‘mywidget’ in a new package of the same name:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">devtools::<span class="kw">create</span>(<span class="st">"mywidget"</span>)               <span class="co"># create package using devtools</span>
+<span class="kw">setwd</span>(<span class="st">"mywidget"</span>)                          <span class="co"># navigate to package dir</span>
+htmlwidgets::<span class="kw">scaffoldWidget</span>(<span class="st">"mywidget"</span>)    <span class="co"># create widget scaffolding</span>
+devtools::<span class="kw">install</span>()                        <span class="co"># install the package so we can try it</span></code></pre></div>
+<p>This creates a simple widget that takes a single <code>text</code> argument and displays that text within the widgets HTML element. You can try it like this:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(mywidget)
+<span class="kw">mywidget</span>(<span class="st">"hello, world"</span>)</code></pre></div>
+<p>This is the most minimal widget possible and doesn’t yet include a JavaScript library to interface to (note that <code>scaffoldWidget</code> can optionally include JavaScript library dependencies via the <code>bowerPkg</code> argument). Before getting started with development you should review the introductory example above to make sure you understand the various components and also review the additional articles and examples linked to in the next section.</p>
+</div>
+<div id="learning-more" class="section level3">
+<h3>Learning more</h3>
+<div id="additional-articles" class="section level4">
+<h4>Additional articles</h4>
+<p>There are additional articles that cover more advanced ground:</p>
+<ul>
+<li><p><a href="develop_sizing.html">HTML Widget Sizing</a> explains custom sizing policies and when you might need to use them and describes implementing a <code>resize</code> method within JavaScript bindings.</p></li>
+<li><p><a href="develop_advanced.html">HTML Widgets: Advanced Topics</a> describes framework features that support per-widget instance data, data transformations (e.g. converting a data frame into a d3 dataset), and providing widget options that are live JavaScript objects (e.g. function definitions).</p></li>
+</ul>
+<p>The Sizing article is particularly important as most JavaScript libraries require some additional interaction to keep their size synchronized with their containing element.</p>
+</div>
+<div id="examples" class="section level4">
+<h4>Examples</h4>
+<p>Studying the code of other packages is a great way to learn more about creating widgets:</p>
+<ol style="list-style-type: decimal">
+<li><p>The <a href="https://github.com/christophergandrud/networkD3">networkD3</a> package illustrates creating a widget on top of <a href="http://d3js.org">D3</a>, using a custom sizing policy for a larger widget, and providing multiple widgets from a single package.</p></li>
+<li><p>The <a href="https://github.com/rstudio/dygraphs/">dygraphs</a> package illustrates using widget instance data, handling dynamic re-sizing, and using <a href="https://github.com/smbache/magrittr">magrittr</a> to decompose a large and flat JavaScript API into a more modular and pipeable R API.</p></li>
+<li><p>The <a href="https://github.com/htmlwidgets/sparkline">sparkline</a> package illustrates providing a custom HTML generation function (since sparklines must be housed in <code><span></code> rather than <code><div></code> elements).</p></li>
+</ol>
+</div>
+<div id="questions-and-issues" class="section level4">
+<h4>Questions and issues</h4>
+<p>If you have questions about developing widgets or run into problems during development please don’t hesitate to <a href="https://github.com/ramnathv/htmlwidgets/issues">post an issue</a> on the project’s GitHub repository.</p>
+</div>
+</div>
+</div>
+
+
+
+
+</div>
+
+<script>
+
+// add bootstrap table styles to pandoc tables
+function bootstrapStylePandocTables() {
+  $('tr.header').parent('thead').parent('table').addClass('table table-condensed');
+}
+$(document).ready(function () {
+  bootstrapStylePandocTables();
+});
+
+
+</script>
+
+
+</body>
+</html>
diff --git a/inst/doc/develop_sizing.Rmd b/inst/doc/develop_sizing.Rmd
new file mode 100644
index 0000000..4fdefe4
--- /dev/null
+++ b/inst/doc/develop_sizing.Rmd
@@ -0,0 +1,170 @@
+---
+title: "HTML Widget Sizing"
+date: "`r Sys.Date()`"
+output: 
+  html_document:
+    highlight: kate
+    toc: true
+    toc_depth: 4
+    mathjax: null
+vignette: >
+  %\VignetteIndexEntry{Sizing}
+  %\VignetteEngine{knitr::rmarkdown}
+  \usepackage[utf8]{inputenc}
+---
+
+## Overview
+
+In the spirit of HTML widgets working just like plots in R, it's important that HTML widgets intelligently size themselves to their container, whether it be the RStudio Viewer, a figure in knitr, or a UI panel within a Shiny application. The **htmlwidgets** framework provides a rich mechanism for specifying the sizing behavior of widgets.
+
+This sizing mechanism is designed to address the following constraints that affect the natural size of a widget:
+
+- **The kind of widget it is.** Some widgets may only be designed to look good at small, fixed sizes (like [sparklines](https://github.com/htmlwidgets/sparkline)) while other widgets may want every pixel that can be spared (like [network graphs](http://christophergandrud.github.io/networkD3/)).
+
+- **The context into which the widget is rendered.** While a given widget might look great at 960px by 480px in an R Markdown document, the same widget would look silly at that size in the RStudio Viewer pane, which is typically much smaller.
+
+Widget sizing is handled in two steps:
+
+1. First, a sizing policy is specified for the widget. This is done via the `sizingPolicy` argument to the `createWidget` function. Most widgets can accept the default sizing policy (or override only one or two aspects of it) and get satisfactory sizing behavior (see details below).
+
+2. The sizing policy is used by the framework to compute the correct width and height for a widget given where it is being rendered. This size information is then passed to the `initialize` and `resize` methods of the widgets JavaScript binding. It's up to the widget to then forward this size information to the underlying JavaScript library.
+
+## Specifying a sizing policy
+
+The default HTML widget sizing policy treats the widget with the same sizing semantics as an R plot. When printed at the R console the widget is displayed within the RStudio Viewer and sized to fill the Viewer pane (modulo any padding). When rendered inside an R Markdown document the widget is sized based on the default size of figures in the document.
+
+Note that for most widgets the default sizing behavior is fine and you won't need to create a custom sizing policy. If you need a slightly different behavior than the default you can also selectively override the default behavior by calling the `sizingPolicy` function and passing the result to `createWidget`. For example:
+
+```r
+htmlwidgets::createWidget(
+  "sigma", 
+  x, 
+  width = width, 
+  height = height,
+  sizingPolicy = htmlwidgets::sizingPolicy(
+    viewer.padding = 0,
+    viewer.paneHeight = 500,
+    browser.fill = TRUE
+  )
+)
+```
+
+### Examples
+
+The [networkD3](http://christophergandrud.github.io/networkD3/) package uses custom sizing policies for all of its widgets. The `simpleNetwork` widget eliminates padding (as d3 is already providing padding) and specifies that it wants to fill up as much space as possible when displayed in a standalone web browser:
+
+```r
+sizingPolicy(padding = 0, browser.fill = TRUE)
+```
+
+The `sankeyNetwork` widget requires much more space than is afforded by the RStudio Viewer or a typical knitr figure so it disables those automatic sizing behaviors. It also provides a more reasonable default width and height for knitr documents:
+
+```r
+sizingPolicy(viewer.suppress = TRUE,
+             knitr.figure = FALSE,
+             browser.fill = TRUE,
+             browser.padding = 75,
+             knitr.defaultWidth = 800,
+             knitr.defaultHeight = 500)
+```
+
+### Available options
+
+Here are the various options that can be specified within a sizing policy:
+
+| Option | Description |
+|---|---|
+| **defaultWidth** | The default width used to display the widget. This parameter specifies the default width for viewing in all contexts (browser, viewer, and knitr) unless it is specifically overridden with e.g. browser.defaultWidth. |
+| **defaultHeight** | The default height used to display the widget. This parameter specifies the default height for viewing in all contexts (browser, viewer, and knitr) unless it is specifically overridden with e.g. browser.defaultHeight. |
+| **padding** | Padding around the widget (in pixels). This parameter specifies the padding for viewing in all contexts (browser and viewer) unless it is specifically overridden by e.g. browser.padding. |
+| **viewer.defaultWidth** | The default width used to display the widget within the RStudio Viewer. |
+| **viewer.defaultHeight** | The default height used to display the widget within the RStudio Viewer. |
+| **viewer.padding** | Padding around the widget when displayed in the RStudio Viewer (defaults to 15 pixels). |
+| **viewer.fill** | When displayed in the RStudio Viewer, automatically size the widget to the viewer dimensions (note that viewer.padding is still applied). Default to TRUE. |
+| **viewer.suppress** | Never display the widget within the RStudio Viewer (useful for widgets that require a large amount of space for rendering). Defaults to FALSE. |
+| **viewer.paneHeight** | Request that the RStudio Viewer be forced to a specific height when displaying this widget. |
+| **browser.defaultWidth** | The default width used to display the widget within a standalone web browser. |
+| **browser.defaultHeight** | The default height used to display the widget within a standalone web browser. |
+| **browser.padding** | Padding around the widget when displayed in a standalone browser (defaults to 40 pixels). |
+| **browser.fill** | When displayed in a standalone web browser, automatically size the widget to the browser dimensions (note that browser.padding is still applied). Defaults to FALSE. |
+| **knitr.defaultWidth** | The default width used to display the widget within documents generated by knitr (e.g. R Markdown). |
+| **knitr.defaultHeight** | The default height used to display the widget within documents generated by knitr (e.g. R Markdown). |
+| **knitr.figure** | Apply the default knitr fig.width and fig.height to the widget when it's rendered within R Markdown documents. Defaults to TRUE. |
+
+## JavaScript resize method
+
+Specifying a sizing policy allows htmlwidgets to calculate the width and height of your widget based on where it's being displayed. However, you still need to forward this sizing information on to the underlying JavaScript library you are creating a widget for.
+
+Every JavaScript library handles dynamic sizing a bit differently. Some do it automatically, some have a resize() call to force a layout, and some require that size be set only along with data and other options. Whatever the case, the **htmlwidgets** framework will pass the computed sizes to both your `factory` function and `resize` function. Here's an empty JavaScript binding that illustrates:
+
+```javascript
+HTMLWidgets.widget({
+
+  name: "demo",
+  
+  type: "output",
+  
+  factory: function(el, width, height) {
+  
+    return {
+      renderValue: function(x) {
+      
+      },
+      
+      resize: function(width, height) {
+        
+      }
+    };
+  }
+});
+```
+
+What you do with the passed width and height is up to you and depends on the re-sizing semantics of the underlying JavaScript library you are creating a widget for. A couple of illustrative examples are included in the next section.
+
+### Examples
+
+#### dygraphs
+
+In the [dygraphs](http://rstudio.github.io/dygraphs) widget the implementation of re-sizing is relatively simple since the **dygraphs** library includes a resize() method to automatically size the graph to it's enclosing HTML element:
+
+```javascript
+resize: function(width, height) {
+  if (dygraph)
+    dygraph.resize();
+}
+```
+
+#### forceNetwork
+
+In the [forceNetwork](http://christophergandrud.github.io/networkD3/#force) widget, the passed width and height are applied to the `<svg>` element that hosts the d3 network visualization, as well as forwarded on to the underlying d3 force simulation object:
+
+```javascript
+factory: function(el, width, height) {
+
+  // instance data
+  var el = el;
+  var force = d3.layout.force();
+
+  d3.select(el).append("svg")
+    .attr("width", width)
+    .attr("height", height);
+      
+  return {
+    renderValue: function(x) {
+      // implementation excluded
+    },
+      
+    resize: function(width, height) {
+         
+      d3.select(el).select("svg")
+        .attr("width", width)
+        .attr("height", height);
+
+      force.size([width, height]).resume();
+    }
+  };
+}
+```
+
+As you can see, re-sizing is handled in a wide variety of fashions in different JavaScript libraries. The `resize` method is intended to provide a flexible way to map the automatic sizing logic of **htmlwidgets** directly into the underlying library.
+
diff --git a/inst/doc/develop_sizing.html b/inst/doc/develop_sizing.html
new file mode 100644
index 0000000..de96721
--- /dev/null
+++ b/inst/doc/develop_sizing.html
@@ -0,0 +1,378 @@
+<!DOCTYPE html>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+
+<meta charset="utf-8">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="pandoc" />
+
+
+
+<meta name="date" content="2016-11-09" />
+
+<title>HTML Widget Sizing</title>
+
+<script src="data:application/x-javascript;base64,LyohIGpRdWVyeSB2MS4xMS4zIHwgKGMpIDIwMDUsIDIwMTUgalF1ZXJ5IEZvdW5kYXRpb24sIEluYy4gfCBqcXVlcnkub3JnL2xpY2Vuc2UgKi8KIWZ1bmN0aW9uKGEsYil7Im9iamVjdCI9PXR5cGVvZiBtb2R1bGUmJiJvYmplY3QiPT10eXBlb2YgbW9kdWxlLmV4cG9ydHM/bW9kdWxlLmV4cG9ydHM9YS5kb2N1bWVudD9iKGEsITApOmZ1bmN0aW9uKGEpe2lmKCFhLmRvY3VtZW50KXRocm93IG5ldyBFcnJvcigialF1ZXJ5IHJlcXVpcmVzIGEgd2luZG93IHdpdGggYSBkb2N1bWVudCIpO3JldHVybiBiKGEpfTpiKGEpfSgidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdz93aW5kb3c6dG [...]
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<link href="data:text/css;charset=utf-8,html%7Bfont%2Dfamily%3Asans%2Dserif%3B%2Dwebkit%2Dtext%2Dsize%2Dadjust%3A100%25%3B%2Dms%2Dtext%2Dsize%2Dadjust%3A100%25%7Dbody%7Bmargin%3A0%7Darticle%2Caside%2Cdetails%2Cfigcaption%2Cfigure%2Cfooter%2Cheader%2Chgroup%2Cmain%2Cmenu%2Cnav%2Csection%2Csummary%7Bdisplay%3Ablock%7Daudio%2Ccanvas%2Cprogress%2Cvideo%7Bdisplay%3Ainline%2Dblock%3Bvertical%2Dalign%3Abaseline%7Daudio%3Anot%28%5Bcontrols%5D%29%7Bdisplay%3Anone%3Bheight%3A0%7D%5Bhidden%5D%2Ctem [...]
+<script src="data:application/x-javascript;base64,LyohCiAqIEJvb3RzdHJhcCB2My4zLjUgKGh0dHA6Ly9nZXRib290c3RyYXAuY29tKQogKiBDb3B5cmlnaHQgMjAxMS0yMDE1IFR3aXR0ZXIsIEluYy4KICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlCiAqLwppZigidW5kZWZpbmVkIj09dHlwZW9mIGpRdWVyeSl0aHJvdyBuZXcgRXJyb3IoIkJvb3RzdHJhcCdzIEphdmFTY3JpcHQgcmVxdWlyZXMgalF1ZXJ5Iik7K2Z1bmN0aW9uKGEpeyJ1c2Ugc3RyaWN0Ijt2YXIgYj1hLmZuLmpxdWVyeS5zcGxpdCgiICIpWzBdLnNwbGl0KCIuIik7aWYoYlswXTwyJiZiWzFdPDl8fDE9PWJbMF0mJjk9PWJbMV0mJmJbMl08MSl0aHJvdy [...]
+<script src="data:application/x-javascript;base64,LyoqCiogQHByZXNlcnZlIEhUTUw1IFNoaXYgMy43LjIgfCBAYWZhcmthcyBAamRhbHRvbiBAam9uX25lYWwgQHJlbSB8IE1JVC9HUEwyIExpY2Vuc2VkCiovCi8vIE9ubHkgcnVuIHRoaXMgY29kZSBpbiBJRSA4CmlmICghIXdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKCJNU0lFIDgiKSkgewohZnVuY3Rpb24oYSxiKXtmdW5jdGlvbiBjKGEsYil7dmFyIGM9YS5jcmVhdGVFbGVtZW50KCJwIiksZD1hLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJoZWFkIilbMF18fGEuZG9jdW1lbnRFbGVtZW50O3JldHVybiBjLmlubmVySFRNTD0ieDxzdHlsZT4iK2IrIjwvc3R5bGU+IixkLm [...]
+<script src="data:application/x-javascript;base64,LyohIFJlc3BvbmQuanMgdjEuNC4yOiBtaW4vbWF4LXdpZHRoIG1lZGlhIHF1ZXJ5IHBvbHlmaWxsICogQ29weXJpZ2h0IDIwMTMgU2NvdHQgSmVobAogKiBMaWNlbnNlZCB1bmRlciBodHRwczovL2dpdGh1Yi5jb20vc2NvdHRqZWhsL1Jlc3BvbmQvYmxvYi9tYXN0ZXIvTElDRU5TRS1NSVQKICogICovCgovLyBPbmx5IHJ1biB0aGlzIGNvZGUgaW4gSUUgOAppZiAoISF3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgiTVNJRSA4IikpIHsKIWZ1bmN0aW9uKGEpeyJ1c2Ugc3RyaWN0IjthLm1hdGNoTWVkaWE9YS5tYXRjaE1lZGlhfHxmdW5jdGlvbihhKXt2YXIgYixjPWEuZG [...]
+<script src="data:application/x-javascript;base64,Cgp3aW5kb3cuYnVpbGRUYWJzZXRzID0gZnVuY3Rpb24odG9jSUQpIHsKCiAgLy8gYnVpbGQgYSB0YWJzZXQgZnJvbSBhIHNlY3Rpb24gZGl2IHdpdGggdGhlIC50YWJzZXQgY2xhc3MKICBmdW5jdGlvbiBidWlsZFRhYnNldCh0YWJzZXQpIHsKCiAgICAvLyBjaGVjayBmb3IgZmFkZSBhbmQgcGlsbHMgb3B0aW9ucwogICAgdmFyIGZhZGUgPSB0YWJzZXQuaGFzQ2xhc3MoInRhYnNldC1mYWRlIik7CiAgICB2YXIgcGlsbHMgPSB0YWJzZXQuaGFzQ2xhc3MoInRhYnNldC1waWxscyIpOwogICAgdmFyIG5hdkNsYXNzID0gcGlsbHMgPyAibmF2LXBpbGxzIiA6ICJuYXYtdGFicyI7CgogIC [...]
+
+
+<style type="text/css">code{white-space: pre;}</style>
+<style type="text/css">
+div.sourceCode { overflow-x: auto; }
+table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
+  margin: 0; padding: 0; vertical-align: baseline; border: none; }
+table.sourceCode { width: 100%; line-height: 100%; }
+td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; background-color: #dddddd; }
+td.sourceCode { padding-left: 5px; }
+code > span.kw { font-weight: bold; } /* Keyword */
+code > span.dt { color: #800000; } /* DataType */
+code > span.dv { color: #0000ff; } /* DecVal */
+code > span.bn { color: #0000ff; } /* BaseN */
+code > span.fl { color: #800080; } /* Float */
+code > span.ch { color: #ff00ff; } /* Char */
+code > span.st { color: #dd0000; } /* String */
+code > span.co { color: #808080; font-style: italic; } /* Comment */
+code > span.al { color: #00ff00; font-weight: bold; } /* Alert */
+code > span.fu { color: #000080; } /* Function */
+code > span.er { color: #ff0000; font-weight: bold; } /* Error */
+code > span.wa { color: #ff0000; font-weight: bold; } /* Warning */
+code > span.cn { color: #000000; } /* Constant */
+code > span.sc { color: #ff00ff; } /* SpecialChar */
+code > span.vs { color: #dd0000; } /* VerbatimString */
+code > span.ss { color: #dd0000; } /* SpecialString */
+code > span.im { } /* Import */
+code > span.va { } /* Variable */
+code > span.cf { } /* ControlFlow */
+code > span.op { } /* Operator */
+code > span.bu { } /* BuiltIn */
+code > span.ex { } /* Extension */
+code > span.pp { font-weight: bold; } /* Preprocessor */
+code > span.at { } /* Attribute */
+code > span.do { color: #808080; font-style: italic; } /* Documentation */
+code > span.an { color: #808080; font-weight: bold; font-style: italic; } /* Annotation */
+code > span.cv { color: #808080; font-weight: bold; font-style: italic; } /* CommentVar */
+code > span.in { color: #808080; font-weight: bold; font-style: italic; } /* Information */
+</style>
+<style type="text/css">
+  pre:not([class]) {
+    background-color: white;
+  }
+</style>
+
+
+<style type="text/css">
+h1 {
+  font-size: 34px;
+}
+h1.title {
+  font-size: 38px;
+}
+h2 {
+  font-size: 30px;
+}
+h3 {
+  font-size: 24px;
+}
+h4 {
+  font-size: 18px;
+}
+h5 {
+  font-size: 16px;
+}
+h6 {
+  font-size: 12px;
+}
+.table th:not([align]) {
+  text-align: left;
+}
+</style>
+
+
+</head>
+
+<body>
+
+<style type="text/css">
+.main-container {
+  max-width: 940px;
+  margin-left: auto;
+  margin-right: auto;
+}
+code {
+  color: inherit;
+  background-color: rgba(0, 0, 0, 0.04);
+}
+img {
+  max-width:100%;
+  height: auto;
+}
+.tabbed-pane {
+  padding-top: 12px;
+}
+button.code-folding-btn:focus {
+  outline: none;
+}
+</style>
+
+
+
+<div class="container-fluid main-container">
+
+<!-- tabsets -->
+<script>
+$(document).ready(function () {
+  window.buildTabsets("TOC");
+});
+</script>
+
+<!-- code folding -->
+
+
+
+
+
+
+<div class="fluid-row" id="header">
+
+
+
+<h1 class="title toc-ignore">HTML Widget Sizing</h1>
+<h4 class="date"><em>2016-11-09</em></h4>
+
+</div>
+
+<div id="TOC">
+<ul>
+<li><a href="#overview">Overview</a></li>
+<li><a href="#specifying-a-sizing-policy">Specifying a sizing policy</a><ul>
+<li><a href="#examples">Examples</a></li>
+<li><a href="#available-options">Available options</a></li>
+</ul></li>
+<li><a href="#javascript-resize-method">JavaScript resize method</a><ul>
+<li><a href="#examples-1">Examples</a><ul>
+<li><a href="#dygraphs">dygraphs</a></li>
+<li><a href="#forcenetwork">forceNetwork</a></li>
+</ul></li>
+</ul></li>
+</ul>
+</div>
+
+<div id="overview" class="section level2">
+<h2>Overview</h2>
+<p>In the spirit of HTML widgets working just like plots in R, it’s important that HTML widgets intelligently size themselves to their container, whether it be the RStudio Viewer, a figure in knitr, or a UI panel within a Shiny application. The <strong>htmlwidgets</strong> framework provides a rich mechanism for specifying the sizing behavior of widgets.</p>
+<p>This sizing mechanism is designed to address the following constraints that affect the natural size of a widget:</p>
+<ul>
+<li><p><strong>The kind of widget it is.</strong> Some widgets may only be designed to look good at small, fixed sizes (like <a href="https://github.com/htmlwidgets/sparkline">sparklines</a>) while other widgets may want every pixel that can be spared (like <a href="http://christophergandrud.github.io/networkD3/">network graphs</a>).</p></li>
+<li><p><strong>The context into which the widget is rendered.</strong> While a given widget might look great at 960px by 480px in an R Markdown document, the same widget would look silly at that size in the RStudio Viewer pane, which is typically much smaller.</p></li>
+</ul>
+<p>Widget sizing is handled in two steps:</p>
+<ol style="list-style-type: decimal">
+<li><p>First, a sizing policy is specified for the widget. This is done via the <code>sizingPolicy</code> argument to the <code>createWidget</code> function. Most widgets can accept the default sizing policy (or override only one or two aspects of it) and get satisfactory sizing behavior (see details below).</p></li>
+<li><p>The sizing policy is used by the framework to compute the correct width and height for a widget given where it is being rendered. This size information is then passed to the <code>initialize</code> and <code>resize</code> methods of the widgets JavaScript binding. It’s up to the widget to then forward this size information to the underlying JavaScript library.</p></li>
+</ol>
+</div>
+<div id="specifying-a-sizing-policy" class="section level2">
+<h2>Specifying a sizing policy</h2>
+<p>The default HTML widget sizing policy treats the widget with the same sizing semantics as an R plot. When printed at the R console the widget is displayed within the RStudio Viewer and sized to fill the Viewer pane (modulo any padding). When rendered inside an R Markdown document the widget is sized based on the default size of figures in the document.</p>
+<p>Note that for most widgets the default sizing behavior is fine and you won’t need to create a custom sizing policy. If you need a slightly different behavior than the default you can also selectively override the default behavior by calling the <code>sizingPolicy</code> function and passing the result to <code>createWidget</code>. For example:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">htmlwidgets::<span class="kw">createWidget</span>(
+  <span class="st">"sigma"</span>, 
+  x, 
+  <span class="dt">width =</span> width, 
+  <span class="dt">height =</span> height,
+  <span class="dt">sizingPolicy =</span> htmlwidgets::<span class="kw">sizingPolicy</span>(
+    <span class="dt">viewer.padding =</span> <span class="dv">0</span>,
+    <span class="dt">viewer.paneHeight =</span> <span class="dv">500</span>,
+    <span class="dt">browser.fill =</span> <span class="ot">TRUE</span>
+  )
+)</code></pre></div>
+<div id="examples" class="section level3">
+<h3>Examples</h3>
+<p>The <a href="http://christophergandrud.github.io/networkD3/">networkD3</a> package uses custom sizing policies for all of its widgets. The <code>simpleNetwork</code> widget eliminates padding (as d3 is already providing padding) and specifies that it wants to fill up as much space as possible when displayed in a standalone web browser:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">sizingPolicy</span>(<span class="dt">padding =</span> <span class="dv">0</span>, <span class="dt">browser.fill =</span> <span class="ot">TRUE</span>)</code></pre></div>
+<p>The <code>sankeyNetwork</code> widget requires much more space than is afforded by the RStudio Viewer or a typical knitr figure so it disables those automatic sizing behaviors. It also provides a more reasonable default width and height for knitr documents:</p>
+<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">sizingPolicy</span>(<span class="dt">viewer.suppress =</span> <span class="ot">TRUE</span>,
+             <span class="dt">knitr.figure =</span> <span class="ot">FALSE</span>,
+             <span class="dt">browser.fill =</span> <span class="ot">TRUE</span>,
+             <span class="dt">browser.padding =</span> <span class="dv">75</span>,
+             <span class="dt">knitr.defaultWidth =</span> <span class="dv">800</span>,
+             <span class="dt">knitr.defaultHeight =</span> <span class="dv">500</span>)</code></pre></div>
+</div>
+<div id="available-options" class="section level3">
+<h3>Available options</h3>
+<p>Here are the various options that can be specified within a sizing policy:</p>
+<table style="width:11%;">
+<colgroup>
+<col width="5%"></col>
+<col width="5%"></col>
+</colgroup>
+<thead>
+<tr class="header">
+<th>Option</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td><strong>defaultWidth</strong></td>
+<td>The default width used to display the widget. This parameter specifies the default width for viewing in all contexts (browser, viewer, and knitr) unless it is specifically overridden with e.g. browser.defaultWidth.</td>
+</tr>
+<tr class="even">
+<td><strong>defaultHeight</strong></td>
+<td>The default height used to display the widget. This parameter specifies the default height for viewing in all contexts (browser, viewer, and knitr) unless it is specifically overridden with e.g. browser.defaultHeight.</td>
+</tr>
+<tr class="odd">
+<td><strong>padding</strong></td>
+<td>Padding around the widget (in pixels). This parameter specifies the padding for viewing in all contexts (browser and viewer) unless it is specifically overridden by e.g. browser.padding.</td>
+</tr>
+<tr class="even">
+<td><strong>viewer.defaultWidth</strong></td>
+<td>The default width used to display the widget within the RStudio Viewer.</td>
+</tr>
+<tr class="odd">
+<td><strong>viewer.defaultHeight</strong></td>
+<td>The default height used to display the widget within the RStudio Viewer.</td>
+</tr>
+<tr class="even">
+<td><strong>viewer.padding</strong></td>
+<td>Padding around the widget when displayed in the RStudio Viewer (defaults to 15 pixels).</td>
+</tr>
+<tr class="odd">
+<td><strong>viewer.fill</strong></td>
+<td>When displayed in the RStudio Viewer, automatically size the widget to the viewer dimensions (note that viewer.padding is still applied). Default to TRUE.</td>
+</tr>
+<tr class="even">
+<td><strong>viewer.suppress</strong></td>
+<td>Never display the widget within the RStudio Viewer (useful for widgets that require a large amount of space for rendering). Defaults to FALSE.</td>
+</tr>
+<tr class="odd">
+<td><strong>viewer.paneHeight</strong></td>
+<td>Request that the RStudio Viewer be forced to a specific height when displaying this widget.</td>
+</tr>
+<tr class="even">
+<td><strong>browser.defaultWidth</strong></td>
+<td>The default width used to display the widget within a standalone web browser.</td>
+</tr>
+<tr class="odd">
+<td><strong>browser.defaultHeight</strong></td>
+<td>The default height used to display the widget within a standalone web browser.</td>
+</tr>
+<tr class="even">
+<td><strong>browser.padding</strong></td>
+<td>Padding around the widget when displayed in a standalone browser (defaults to 40 pixels).</td>
+</tr>
+<tr class="odd">
+<td><strong>browser.fill</strong></td>
+<td>When displayed in a standalone web browser, automatically size the widget to the browser dimensions (note that browser.padding is still applied). Defaults to FALSE.</td>
+</tr>
+<tr class="even">
+<td><strong>knitr.defaultWidth</strong></td>
+<td>The default width used to display the widget within documents generated by knitr (e.g. R Markdown).</td>
+</tr>
+<tr class="odd">
+<td><strong>knitr.defaultHeight</strong></td>
+<td>The default height used to display the widget within documents generated by knitr (e.g. R Markdown).</td>
+</tr>
+<tr class="even">
+<td><strong>knitr.figure</strong></td>
+<td>Apply the default knitr fig.width and fig.height to the widget when it’s rendered within R Markdown documents. Defaults to TRUE.</td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div id="javascript-resize-method" class="section level2">
+<h2>JavaScript resize method</h2>
+<p>Specifying a sizing policy allows htmlwidgets to calculate the width and height of your widget based on where it’s being displayed. However, you still need to forward this sizing information on to the underlying JavaScript library you are creating a widget for.</p>
+<p>Every JavaScript library handles dynamic sizing a bit differently. Some do it automatically, some have a resize() call to force a layout, and some require that size be set only along with data and other options. Whatever the case, the <strong>htmlwidgets</strong> framework will pass the computed sizes to both your <code>factory</code> function and <code>resize</code> function. Here’s an empty JavaScript binding that illustrates:</p>
+<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span class="va">HTMLWidgets</span>.<span class="at">widget</span>(<span class="op">{</span>
+
+  <span class="dt">name</span><span class="op">:</span> <span class="st">"demo"</span><span class="op">,</span>
+  
+  <span class="dt">type</span><span class="op">:</span> <span class="st">"output"</span><span class="op">,</span>
+  
+  <span class="dt">factory</span><span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> width<span class="op">,</span> height) <span class="op">{</span>
+  
+    <span class="cf">return</span> <span class="op">{</span>
+      <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span>
+      
+      <span class="op">},</span>
+      
+      <span class="dt">resize</span><span class="op">:</span> <span class="kw">function</span>(width<span class="op">,</span> height) <span class="op">{</span>
+        
+      <span class="op">}</span>
+    <span class="op">};</span>
+  <span class="op">}</span>
+<span class="op">}</span>)<span class="op">;</span></code></pre></div>
+<p>What you do with the passed width and height is up to you and depends on the re-sizing semantics of the underlying JavaScript library you are creating a widget for. A couple of illustrative examples are included in the next section.</p>
+<div id="examples-1" class="section level3">
+<h3>Examples</h3>
+<div id="dygraphs" class="section level4">
+<h4>dygraphs</h4>
+<p>In the <a href="http://rstudio.github.io/dygraphs">dygraphs</a> widget the implementation of re-sizing is relatively simple since the <strong>dygraphs</strong> library includes a resize() method to automatically size the graph to it’s enclosing HTML element:</p>
+<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript">resize<span class="op">:</span> <span class="kw">function</span>(width<span class="op">,</span> height) <span class="op">{</span>
+  <span class="cf">if</span> (dygraph)
+    <span class="va">dygraph</span>.<span class="at">resize</span>()<span class="op">;</span>
+<span class="op">}</span></code></pre></div>
+</div>
+<div id="forcenetwork" class="section level4">
+<h4>forceNetwork</h4>
+<p>In the <a href="http://christophergandrud.github.io/networkD3/#force">forceNetwork</a> widget, the passed width and height are applied to the <code><svg></code> element that hosts the d3 network visualization, as well as forwarded on to the underlying d3 force simulation object:</p>
+<div class="sourceCode"><pre class="sourceCode javascript"><code class="sourceCode javascript">factory<span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> width<span class="op">,</span> height) <span class="op">{</span>
+
+  <span class="co">// instance data</span>
+  <span class="kw">var</span> el <span class="op">=</span> el<span class="op">;</span>
+  <span class="kw">var</span> force <span class="op">=</span> <span class="va">d3</span>.<span class="va">layout</span>.<span class="at">force</span>()<span class="op">;</span>
+
+  <span class="va">d3</span>.<span class="at">select</span>(el).<span class="at">append</span>(<span class="st">"svg"</span>)
+    .<span class="at">attr</span>(<span class="st">"width"</span><span class="op">,</span> width)
+    .<span class="at">attr</span>(<span class="st">"height"</span><span class="op">,</span> height)<span class="op">;</span>
+      
+  <span class="cf">return</span> <span class="op">{</span>
+    <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span>
+      <span class="co">// implementation excluded</span>
+    <span class="op">},</span>
+      
+    <span class="dt">resize</span><span class="op">:</span> <span class="kw">function</span>(width<span class="op">,</span> height) <span class="op">{</span>
+         
+      <span class="va">d3</span>.<span class="at">select</span>(el).<span class="at">select</span>(<span class="st">"svg"</span>)
+        .<span class="at">attr</span>(<span class="st">"width"</span><span class="op">,</span> width)
+        .<span class="at">attr</span>(<span class="st">"height"</span><span class="op">,</span> height)<span class="op">;</span>
+
+      <span class="va">force</span>.<span class="at">size</span>([width<span class="op">,</span> height]).<span class="at">resume</span>()<span class="op">;</span>
+    <span class="op">}</span>
+  <span class="op">};</span>
+<span class="op">}</span></code></pre></div>
+<p>As you can see, re-sizing is handled in a wide variety of fashions in different JavaScript libraries. The <code>resize</code> method is intended to provide a flexible way to map the automatic sizing logic of <strong>htmlwidgets</strong> directly into the underlying library.</p>
+</div>
+</div>
+</div>
+
+
+
+
+</div>
+
+<script>
+
+// add bootstrap table styles to pandoc tables
+function bootstrapStylePandocTables() {
+  $('tr.header').parent('thead').parent('table').addClass('table table-condensed');
+}
+$(document).ready(function () {
+  bootstrapStylePandocTables();
+});
+
+
+</script>
+
+
+</body>
+</html>
diff --git a/inst/templates/widget_js.txt b/inst/templates/widget_js.txt
new file mode 100644
index 0000000..fa883e0
--- /dev/null
+++ b/inst/templates/widget_js.txt
@@ -0,0 +1,28 @@
+HTMLWidgets.widget({
+
+  name: '%s',
+
+  type: 'output',
+
+  factory: function(el, width, height) {
+
+    // TODO: define shared variables for this instance
+
+    return {
+
+      renderValue: function(x) {
+
+        // TODO: code to render the widget, e.g.
+        el.innerText = x.message;
+
+      },
+
+      resize: function(width, height) {
+
+        // TODO: code to re-render the widget with a new size
+
+      }
+
+    };
+  }
+});
diff --git a/inst/templates/widget_r.txt b/inst/templates/widget_r.txt
new file mode 100644
index 0000000..89b1c23
--- /dev/null
+++ b/inst/templates/widget_r.txt
@@ -0,0 +1,53 @@
+#' <Add Title>
+#'
+#' <Add Description>
+#'
+#' @import htmlwidgets
+#'
+#' @export
+%s <- function(message, width = NULL, height = NULL, elementId = NULL) {
+
+  # forward options using x
+  x = list(
+    message = message
+  )
+
+  # create widget
+  htmlwidgets::createWidget(
+    name = '%s',
+    x,
+    width = width,
+    height = height,
+    package = '%s',
+    elementId = elementId
+  )
+}
+
+#' Shiny bindings for %s
+#'
+#' Output and render functions for using %s within Shiny
+#' applications and interactive Rmd documents.
+#'
+#' @param outputId output variable to read from
+#' @param width,height Must be a valid CSS unit (like \code{'100\%%'},
+#'   \code{'400px'}, \code{'auto'}) or a number, which will be coerced to a
+#'   string and have \code{'px'} appended.
+#' @param expr An expression that generates a %s
+#' @param env The environment in which to evaluate \code{expr}.
+#' @param quoted Is \code{expr} a quoted expression (with \code{quote()})? This
+#'   is useful if you want to save an expression in a variable.
+#'
+#' @name %s-shiny
+#'
+#' @export
+%sOutput <- function(outputId, width = '100%%', height = '400px'){
+  htmlwidgets::shinyWidgetOutput(outputId, '%s', width, height, package = '%s')
+}
+
+#' @rdname %s-shiny
+#' @export
+render%s <- function(expr, env = parent.frame(), quoted = FALSE) {
+  if (!quoted) { expr <- substitute(expr) } # force quoted
+  htmlwidgets::shinyRenderWidget(expr, %sOutput, env, quoted = TRUE)
+}
+
diff --git a/inst/www/htmlwidgets.js b/inst/www/htmlwidgets.js
new file mode 100644
index 0000000..7193c78
--- /dev/null
+++ b/inst/www/htmlwidgets.js
@@ -0,0 +1,836 @@
+(function() {
+  // If window.HTMLWidgets is already defined, then use it; otherwise create a
+  // new object. This allows preceding code to set options that affect the
+  // initialization process (though none currently exist).
+  window.HTMLWidgets = window.HTMLWidgets || {};
+
+  // See if we're running in a viewer pane. If not, we're in a web browser.
+  var viewerMode = window.HTMLWidgets.viewerMode =
+      /\bviewer_pane=1\b/.test(window.location);
+
+  // See if we're running in Shiny mode. If not, it's a static document.
+  // Note that static widgets can appear in both Shiny and static modes, but
+  // obviously, Shiny widgets can only appear in Shiny apps/documents.
+  var shinyMode = window.HTMLWidgets.shinyMode =
+      typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings;
+
+  // We can't count on jQuery being available, so we implement our own
+  // version if necessary.
+  function querySelectorAll(scope, selector) {
+    if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) {
+      return scope.find(selector);
+    }
+    if (scope.querySelectorAll) {
+      return scope.querySelectorAll(selector);
+    }
+  }
+
+  function asArray(value) {
+    if (value === null)
+      return [];
+    if ($.isArray(value))
+      return value;
+    return [value];
+  }
+
+  // Implement jQuery's extend
+  function extend(target /*, ... */) {
+    if (arguments.length == 1) {
+      return target;
+    }
+    for (var i = 1; i < arguments.length; i++) {
+      var source = arguments[i];
+      for (var prop in source) {
+        if (source.hasOwnProperty(prop)) {
+          target[prop] = source[prop];
+        }
+      }
+    }
+    return target;
+  }
+
+  // IE8 doesn't support Array.forEach.
+  function forEach(values, callback, thisArg) {
+    if (values.forEach) {
+      values.forEach(callback, thisArg);
+    } else {
+      for (var i = 0; i < values.length; i++) {
+        callback.call(thisArg, values[i], i, values);
+      }
+    }
+  }
+
+  // Replaces the specified method with the return value of funcSource.
+  //
+  // Note that funcSource should not BE the new method, it should be a function
+  // that RETURNS the new method. funcSource receives a single argument that is
+  // the overridden method, it can be called from the new method. The overridden
+  // method can be called like a regular function, it has the target permanently
+  // bound to it so "this" will work correctly.
+  function overrideMethod(target, methodName, funcSource) {
+    var superFunc = target[methodName] || function() {};
+    var superFuncBound = function() {
+      return superFunc.apply(target, arguments);
+    };
+    target[methodName] = funcSource(superFuncBound);
+  }
+
+  // Add a method to delegator that, when invoked, calls
+  // delegatee.methodName. If there is no such method on
+  // the delegatee, but there was one on delegator before
+  // delegateMethod was called, then the original version
+  // is invoked instead.
+  // For example:
+  //
+  // var a = {
+  //   method1: function() { console.log('a1'); }
+  //   method2: function() { console.log('a2'); }
+  // };
+  // var b = {
+  //   method1: function() { console.log('b1'); }
+  // };
+  // delegateMethod(a, b, "method1");
+  // delegateMethod(a, b, "method2");
+  // a.method1();
+  // a.method2();
+  //
+  // The output would be "b1", "a2".
+  function delegateMethod(delegator, delegatee, methodName) {
+    var inherited = delegator[methodName];
+    delegator[methodName] = function() {
+      var target = delegatee;
+      var method = delegatee[methodName];
+
+      // The method doesn't exist on the delegatee. Instead,
+      // call the method on the delegator, if it exists.
+      if (!method) {
+        target = delegator;
+        method = inherited;
+      }
+
+      if (method) {
+        return method.apply(target, arguments);
+      }
+    };
+  }
+
+  // Implement a vague facsimilie of jQuery's data method
+  function elementData(el, name, value) {
+    if (arguments.length == 2) {
+      return el["htmlwidget_data_" + name];
+    } else if (arguments.length == 3) {
+      el["htmlwidget_data_" + name] = value;
+      return el;
+    } else {
+      throw new Error("Wrong number of arguments for elementData: " +
+        arguments.length);
+    }
+  }
+
+  // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
+  function escapeRegExp(str) {
+    return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+  }
+
+  function hasClass(el, className) {
+    var re = new RegExp("\\b" + escapeRegExp(className) + "\\b");
+    return re.test(el.className);
+  }
+
+  // elements - array (or array-like object) of HTML elements
+  // className - class name to test for
+  // include - if true, only return elements with given className;
+  //   if false, only return elements *without* given className
+  function filterByClass(elements, className, include) {
+    var results = [];
+    for (var i = 0; i < elements.length; i++) {
+      if (hasClass(elements[i], className) == include)
+        results.push(elements[i]);
+    }
+    return results;
+  }
+
+  function on(obj, eventName, func) {
+    if (obj.addEventListener) {
+      obj.addEventListener(eventName, func, false);
+    } else if (obj.attachEvent) {
+      obj.attachEvent(eventName, func);
+    }
+  }
+
+  function off(obj, eventName, func) {
+    if (obj.removeEventListener)
+      obj.removeEventListener(eventName, func, false);
+    else if (obj.detachEvent) {
+      obj.detachEvent(eventName, func);
+    }
+  }
+
+  // Translate array of values to top/right/bottom/left, as usual with
+  // the "padding" CSS property
+  // https://developer.mozilla.org/en-US/docs/Web/CSS/padding
+  function unpackPadding(value) {
+    if (typeof(value) === "number")
+      value = [value];
+    if (value.length === 1) {
+      return {top: value[0], right: value[0], bottom: value[0], left: value[0]};
+    }
+    if (value.length === 2) {
+      return {top: value[0], right: value[1], bottom: value[0], left: value[1]};
+    }
+    if (value.length === 3) {
+      return {top: value[0], right: value[1], bottom: value[2], left: value[1]};
+    }
+    if (value.length === 4) {
+      return {top: value[0], right: value[1], bottom: value[2], left: value[3]};
+    }
+  }
+
+  // Convert an unpacked padding object to a CSS value
+  function paddingToCss(paddingObj) {
+    return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px";
+  }
+
+  // Makes a number suitable for CSS
+  function px(x) {
+    if (typeof(x) === "number")
+      return x + "px";
+    else
+      return x;
+  }
+
+  // Retrieves runtime widget sizing information for an element.
+  // The return value is either null, or an object with fill, padding,
+  // defaultWidth, defaultHeight fields.
+  function sizingPolicy(el) {
+    var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']");
+    if (!sizingEl)
+      return null;
+    var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}");
+    if (viewerMode) {
+      return sp.viewer;
+    } else {
+      return sp.browser;
+    }
+  }
+
+  // @param tasks Array of strings (or falsy value, in which case no-op).
+  //   Each element must be a valid JavaScript expression that yields a
+  //   function. Or, can be an array of objects with "code" and "data"
+  //   properties; in this case, the "code" property should be a string
+  //   of JS that's an expr that yields a function, and "data" should be
+  //   an object that will be added as an additional argument when that
+  //   function is called.
+  // @param target The object that will be "this" for each function
+  //   execution.
+  // @param args Array of arguments to be passed to the functions. (The
+  //   same arguments will be passed to all functions.)
+  function evalAndRun(tasks, target, args) {
+    if (tasks) {
+      forEach(tasks, function(task) {
+        var theseArgs = args;
+        if (typeof(task) === "object") {
+          theseArgs = theseArgs.concat([task.data]);
+          task = task.code;
+        }
+        var taskFunc = eval("(" + task + ")");
+        if (typeof(taskFunc) !== "function") {
+          throw new Error("Task must be a function! Source:\n" + task);
+        }
+        taskFunc.apply(target, theseArgs);
+      });
+    }
+  }
+
+  function initSizing(el) {
+    var sizing = sizingPolicy(el);
+    if (!sizing)
+      return;
+
+    var cel = document.getElementById("htmlwidget_container");
+    if (!cel)
+      return;
+
+    if (typeof(sizing.padding) !== "undefined") {
+      document.body.style.margin = "0";
+      document.body.style.padding = paddingToCss(unpackPadding(sizing.padding));
+    }
+
+    if (sizing.fill) {
+      document.body.style.overflow = "hidden";
+      document.body.style.width = "100%";
+      document.body.style.height = "100%";
+      document.documentElement.style.width = "100%";
+      document.documentElement.style.height = "100%";
+      if (cel) {
+        cel.style.position = "absolute";
+        var pad = unpackPadding(sizing.padding);
+        cel.style.top = pad.top + "px";
+        cel.style.right = pad.right + "px";
+        cel.style.bottom = pad.bottom + "px";
+        cel.style.left = pad.left + "px";
+        el.style.width = "100%";
+        el.style.height = "100%";
+      }
+
+      return {
+        getWidth: function() { return cel.offsetWidth; },
+        getHeight: function() { return cel.offsetHeight; }
+      };
+
+    } else {
+      el.style.width = px(sizing.width);
+      el.style.height = px(sizing.height);
+
+      return {
+        getWidth: function() { return el.offsetWidth; },
+        getHeight: function() { return el.offsetHeight; }
+      };
+    }
+  }
+
+  // Default implementations for methods
+  var defaults = {
+    find: function(scope) {
+      return querySelectorAll(scope, "." + this.name);
+    },
+    renderError: function(el, err) {
+      var $el = $(el);
+
+      this.clearError(el);
+
+      // Add all these error classes, as Shiny does
+      var errClass = "shiny-output-error";
+      if (err.type !== null) {
+        // use the classes of the error condition as CSS class names
+        errClass = errClass + " " + $.map(asArray(err.type), function(type) {
+          return errClass + "-" + type;
+        }).join(" ");
+      }
+      errClass = errClass + " htmlwidgets-error";
+
+      // Is el inline or block? If inline or inline-block, just display:none it
+      // and add an inline error.
+      var display = $el.css("display");
+      $el.data("restore-display-mode", display);
+
+      if (display === "inline" || display === "inline-block") {
+        $el.hide();
+        if (err.message !== "") {
+          var errorSpan = $("<span>").addClass(errClass);
+          errorSpan.text(err.message);
+          $el.after(errorSpan);
+        }
+      } else if (display === "block") {
+        // If block, add an error just after the el, set visibility:none on the
+        // el, and position the error to be on top of the el.
+        // Mark it with a unique ID and CSS class so we can remove it later.
+        $el.css("visibility", "hidden");
+        if (err.message !== "") {
+          var errorDiv = $("<div>").addClass(errClass).css("position", "absolute")
+            .css("top", el.offsetTop)
+            .css("left", el.offsetLeft)
+            // setting width can push out the page size, forcing otherwise
+            // unnecessary scrollbars to appear and making it impossible for
+            // the element to shrink; so use max-width instead
+            .css("maxWidth", el.offsetWidth)
+            .css("height", el.offsetHeight);
+          errorDiv.text(err.message);
+          $el.after(errorDiv);
+
+          // Really dumb way to keep the size/position of the error in sync with
+          // the parent element as the window is resized or whatever.
+          var intId = setInterval(function() {
+            if (!errorDiv[0].parentElement) {
+              clearInterval(intId);
+              return;
+            }
+            errorDiv
+              .css("top", el.offsetTop)
+              .css("left", el.offsetLeft)
+              .css("maxWidth", el.offsetWidth)
+              .css("height", el.offsetHeight);
+          }, 500);
+        }
+      }
+    },
+    clearError: function(el) {
+      var $el = $(el);
+      var display = $el.data("restore-display-mode");
+      $el.data("restore-display-mode", null);
+
+      if (display === "inline" || display === "inline-block") {
+        if (display)
+          $el.css("display", display);
+        $(el.nextSibling).filter(".htmlwidgets-error").remove();
+      } else if (display === "block"){
+        $el.css("visibility", "inherit");
+        $(el.nextSibling).filter(".htmlwidgets-error").remove();
+      }
+    },
+    sizing: {}
+  };
+
+  // Called by widget bindings to register a new type of widget. The definition
+  // object can contain the following properties:
+  // - name (required) - A string indicating the binding name, which will be
+  //   used by default as the CSS classname to look for.
+  // - initialize (optional) - A function(el) that will be called once per
+  //   widget element; if a value is returned, it will be passed as the third
+  //   value to renderValue.
+  // - renderValue (required) - A function(el, data, initValue) that will be
+  //   called with data. Static contexts will cause this to be called once per
+  //   element; Shiny apps will cause this to be called multiple times per
+  //   element, as the data changes.
+  window.HTMLWidgets.widget = function(definition) {
+    if (!definition.name) {
+      throw new Error("Widget must have a name");
+    }
+    if (!definition.type) {
+      throw new Error("Widget must have a type");
+    }
+    // Currently we only support output widgets
+    if (definition.type !== "output") {
+      throw new Error("Unrecognized widget type '" + definition.type + "'");
+    }
+    // TODO: Verify that .name is a valid CSS classname
+
+    // Support new-style instance-bound definitions. Old-style class-bound
+    // definitions have one widget "object" per widget per type/class of
+    // widget; the renderValue and resize methods on such widget objects
+    // take el and instance arguments, because the widget object can't
+    // store them. New-style instance-bound definitions have one widget
+    // object per widget instance; the definition that's passed in doesn't
+    // provide renderValue or resize methods at all, just the single method
+    //   factory(el, width, height)
+    // which returns an object that has renderValue(x) and resize(w, h).
+    // This enables a far more natural programming style for the widget
+    // author, who can store per-instance state using either OO-style
+    // instance fields or functional-style closure variables (I guess this
+    // is in contrast to what can only be called C-style pseudo-OO which is
+    // what we required before).
+    if (definition.factory) {
+      definition = createLegacyDefinitionAdapter(definition);
+    }
+
+    if (!definition.renderValue) {
+      throw new Error("Widget must have a renderValue function");
+    }
+
+    // For static rendering (non-Shiny), use a simple widget registration
+    // scheme. We also use this scheme for Shiny apps/documents that also
+    // contain static widgets.
+    window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || [];
+    // Merge defaults into the definition; don't mutate the original definition.
+    var staticBinding = extend({}, defaults, definition);
+    overrideMethod(staticBinding, "find", function(superfunc) {
+      return function(scope) {
+        var results = superfunc(scope);
+        // Filter out Shiny outputs, we only want the static kind
+        return filterByClass(results, "html-widget-output", false);
+      };
+    });
+    window.HTMLWidgets.widgets.push(staticBinding);
+
+    if (shinyMode) {
+      // Shiny is running. Register the definition with an output binding.
+      // The definition itself will not be the output binding, instead
+      // we will make an output binding object that delegates to the
+      // definition. This is because we foolishly used the same method
+      // name (renderValue) for htmlwidgets definition and Shiny bindings
+      // but they actually have quite different semantics (the Shiny
+      // bindings receive data that includes lots of metadata that it
+      // strips off before calling htmlwidgets renderValue). We can't
+      // just ignore the difference because in some widgets it's helpful
+      // to call this.renderValue() from inside of resize(), and if
+      // we're not delegating, then that call will go to the Shiny
+      // version instead of the htmlwidgets version.
+
+      // Merge defaults with definition, without mutating either.
+      var bindingDef = extend({}, defaults, definition);
+
+      // This object will be our actual Shiny binding.
+      var shinyBinding = new Shiny.OutputBinding();
+
+      // With a few exceptions, we'll want to simply use the bindingDef's
+      // version of methods if they are available, otherwise fall back to
+      // Shiny's defaults. NOTE: If Shiny's output bindings gain additional
+      // methods in the future, and we want them to be overrideable by
+      // HTMLWidget binding definitions, then we'll need to add them to this
+      // list.
+      delegateMethod(shinyBinding, bindingDef, "getId");
+      delegateMethod(shinyBinding, bindingDef, "onValueChange");
+      delegateMethod(shinyBinding, bindingDef, "onValueError");
+      delegateMethod(shinyBinding, bindingDef, "renderError");
+      delegateMethod(shinyBinding, bindingDef, "clearError");
+      delegateMethod(shinyBinding, bindingDef, "showProgress");
+
+      // The find, renderValue, and resize are handled differently, because we
+      // want to actually decorate the behavior of the bindingDef methods.
+
+      shinyBinding.find = function(scope) {
+        var results = bindingDef.find(scope);
+
+        // Only return elements that are Shiny outputs, not static ones
+        var dynamicResults = results.filter(".html-widget-output");
+
+        // It's possible that whatever caused Shiny to think there might be
+        // new dynamic outputs, also caused there to be new static outputs.
+        // Since there might be lots of different htmlwidgets bindings, we
+        // schedule execution for later--no need to staticRender multiple
+        // times.
+        if (results.length !== dynamicResults.length)
+          scheduleStaticRender();
+
+        return dynamicResults;
+      };
+
+      // Wrap renderValue to handle initialization, which unfortunately isn't
+      // supported natively by Shiny at the time of this writing.
+
+      shinyBinding.renderValue = function(el, data) {
+        // Resolve strings marked as javascript literals to objects
+        if (!(data.evals instanceof Array)) data.evals = [data.evals];
+        for (var i = 0; data.evals && i < data.evals.length; i++) {
+          window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]);
+        }
+        if (!bindingDef.renderOnNullValue) {
+          if (data.x === null) {
+            el.style.visibility = "hidden";
+            return;
+          } else {
+            el.style.visibility = "inherit";
+          }
+        }
+        if (!elementData(el, "initialized")) {
+          initSizing(el);
+
+          elementData(el, "initialized", true);
+          if (bindingDef.initialize) {
+            var result = bindingDef.initialize(el, el.offsetWidth,
+              el.offsetHeight);
+            elementData(el, "init_result", result);
+          }
+        }
+        Shiny.renderDependencies(data.deps);
+        bindingDef.renderValue(el, data.x, elementData(el, "init_result"));
+        evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]);
+      };
+
+      // Only override resize if bindingDef implements it
+      if (bindingDef.resize) {
+        shinyBinding.resize = function(el, width, height) {
+          // Shiny can call resize before initialize/renderValue have been
+          // called, which doesn't make sense for widgets.
+          if (elementData(el, "initialized")) {
+            bindingDef.resize(el, width, height, elementData(el, "init_result"));
+          }
+        };
+      }
+
+      Shiny.outputBindings.register(shinyBinding, bindingDef.name);
+    }
+  };
+
+  var scheduleStaticRenderTimerId = null;
+  function scheduleStaticRender() {
+    if (!scheduleStaticRenderTimerId) {
+      scheduleStaticRenderTimerId = setTimeout(function() {
+        scheduleStaticRenderTimerId = null;
+        window.HTMLWidgets.staticRender();
+      }, 1);
+    }
+  }
+
+  // Render static widgets after the document finishes loading
+  // Statically render all elements that are of this widget's class
+  window.HTMLWidgets.staticRender = function() {
+    var bindings = window.HTMLWidgets.widgets || [];
+    forEach(bindings, function(binding) {
+      var matches = binding.find(document.documentElement);
+      forEach(matches, function(el) {
+        var sizeObj = initSizing(el, binding);
+
+        if (hasClass(el, "html-widget-static-bound"))
+          return;
+        el.className = el.className + " html-widget-static-bound";
+
+        var initResult;
+        if (binding.initialize) {
+          initResult = binding.initialize(el,
+            sizeObj ? sizeObj.getWidth() : el.offsetWidth,
+            sizeObj ? sizeObj.getHeight() : el.offsetHeight
+          );
+          elementData(el, "init_result", initResult);
+        }
+
+        if (binding.resize) {
+          var lastSize = {};
+          var resizeHandler = function(e) {
+            var size = {
+              w: sizeObj ? sizeObj.getWidth() : el.offsetWidth,
+              h: sizeObj ? sizeObj.getHeight() : el.offsetHeight
+            };
+            if (size.w === 0 && size.h === 0)
+              return;
+            if (size.w === lastSize.w && size.h === lastSize.h)
+              return;
+            lastSize = size;
+            binding.resize(el, size.w, size.h, initResult);
+          };
+
+          on(window, "resize", resizeHandler);
+
+          // This is needed for cases where we're running in a Shiny
+          // app, but the widget itself is not a Shiny output, but
+          // rather a simple static widget. One example of this is
+          // an rmarkdown document that has runtime:shiny and widget
+          // that isn't in a render function. Shiny only knows to
+          // call resize handlers for Shiny outputs, not for static
+          // widgets, so we do it ourselves.
+          if (window.jQuery) {
+            window.jQuery(document).on(
+              "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets",
+              resizeHandler
+            );
+            window.jQuery(document).on(
+              "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets",
+              resizeHandler
+            );
+          }
+
+          // This is needed for the specific case of ioslides, which
+          // flips slides between display:none and display:block.
+          // Ideally we would not have to have ioslide-specific code
+          // here, but rather have ioslides raise a generic event,
+          // but the rmarkdown package just went to CRAN so the
+          // window to getting that fixed may be long.
+          if (window.addEventListener) {
+            // It's OK to limit this to window.addEventListener
+            // browsers because ioslides itself only supports
+            // such browsers.
+            on(document, "slideenter", resizeHandler);
+            on(document, "slideleave", resizeHandler);
+          }
+        }
+
+        var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']");
+        if (scriptData) {
+          var data = JSON.parse(scriptData.textContent || scriptData.text);
+          // Resolve strings marked as javascript literals to objects
+          if (!(data.evals instanceof Array)) data.evals = [data.evals];
+          for (var k = 0; data.evals && k < data.evals.length; k++) {
+            window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]);
+          }
+          binding.renderValue(el, data.x, initResult);
+          evalAndRun(data.jsHooks.render, initResult, [el, data.x]);
+        }
+      });
+    });
+
+    invokePostRenderHandlers();
+  }
+
+  // Wait until after the document has loaded to render the widgets.
+  if (document.addEventListener) {
+    document.addEventListener("DOMContentLoaded", function() {
+      document.removeEventListener("DOMContentLoaded", arguments.callee, false);
+      window.HTMLWidgets.staticRender();
+    }, false);
+  } else if (document.attachEvent) {
+    document.attachEvent("onreadystatechange", function() {
+      if (document.readyState === "complete") {
+        document.detachEvent("onreadystatechange", arguments.callee);
+        window.HTMLWidgets.staticRender();
+      }
+    });
+  }
+
+
+  window.HTMLWidgets.getAttachmentUrl = function(depname, key) {
+    // If no key, default to the first item
+    if (typeof(key) === "undefined")
+      key = 1;
+
+    var link = document.getElementById(depname + "-" + key + "-attachment");
+    if (!link) {
+      throw new Error("Attachment " + depname + "/" + key + " not found in document");
+    }
+    return link.getAttribute("href");
+  };
+
+  window.HTMLWidgets.dataframeToD3 = function(df) {
+    var names = [];
+    var length;
+    for (var name in df) {
+        if (df.hasOwnProperty(name))
+            names.push(name);
+        if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") {
+            throw new Error("All fields must be arrays");
+        } else if (typeof(length) !== "undefined" && length !== df[name].length) {
+            throw new Error("All fields must be arrays of the same length");
+        }
+        length = df[name].length;
+    }
+    var results = [];
+    var item;
+    for (var row = 0; row < length; row++) {
+        item = {};
+        for (var col = 0; col < names.length; col++) {
+            item[names[col]] = df[names[col]][row];
+        }
+        results.push(item);
+    }
+    return results;
+  };
+
+  window.HTMLWidgets.transposeArray2D = function(array) {
+      if (array.length === 0) return array;
+      var newArray = array[0].map(function(col, i) {
+          return array.map(function(row) {
+              return row[i]
+          })
+      });
+      return newArray;
+  };
+  // Split value at splitChar, but allow splitChar to be escaped
+  // using escapeChar. Any other characters escaped by escapeChar
+  // will be included as usual (including escapeChar itself).
+  function splitWithEscape(value, splitChar, escapeChar) {
+    var results = [];
+    var escapeMode = false;
+    var currentResult = "";
+    for (var pos = 0; pos < value.length; pos++) {
+      if (!escapeMode) {
+        if (value[pos] === splitChar) {
+          results.push(currentResult);
+          currentResult = "";
+        } else if (value[pos] === escapeChar) {
+          escapeMode = true;
+        } else {
+          currentResult += value[pos];
+        }
+      } else {
+        currentResult += value[pos];
+        escapeMode = false;
+      }
+    }
+    if (currentResult !== "") {
+      results.push(currentResult);
+    }
+    return results;
+  }
+  // Function authored by Yihui/JJ Allaire
+  window.HTMLWidgets.evaluateStringMember = function(o, member) {
+    var parts = splitWithEscape(member, '.', '\\');
+    for (var i = 0, l = parts.length; i < l; i++) {
+      var part = parts[i];
+      // part may be a character or 'numeric' member name
+      if (o !== null && typeof o === "object" && part in o) {
+        if (i == (l - 1)) { // if we are at the end of the line then evalulate
+          if (typeof o[part] === "string")
+            o[part] = eval("(" + o[part] + ")");
+        } else { // otherwise continue to next embedded object
+          o = o[part];
+        }
+      }
+    }
+  };
+
+  // Retrieve the HTMLWidget instance (i.e. the return value of an
+  // HTMLWidget binding's initialize() or factory() function)
+  // associated with an element, or null if none.
+  window.HTMLWidgets.getInstance = function(el) {
+    return elementData(el, "init_result");
+  };
+
+  // Finds the first element in the scope that matches the selector,
+  // and returns the HTMLWidget instance (i.e. the return value of
+  // an HTMLWidget binding's initialize() or factory() function)
+  // associated with that element, if any. If no element matches the
+  // selector, or the first matching element has no HTMLWidget
+  // instance associated with it, then null is returned.
+  //
+  // The scope argument is optional, and defaults to window.document.
+  window.HTMLWidgets.find = function(scope, selector) {
+    if (arguments.length == 1) {
+      selector = scope;
+      scope = document;
+    }
+
+    var el = scope.querySelector(selector);
+    if (el === null) {
+      return null;
+    } else {
+      return window.HTMLWidgets.getInstance(el);
+    }
+  };
+
+  // Finds all elements in the scope that match the selector, and
+  // returns the HTMLWidget instances (i.e. the return values of
+  // an HTMLWidget binding's initialize() or factory() function)
+  // associated with the elements, in an array. If elements that
+  // match the selector don't have an associated HTMLWidget
+  // instance, the returned array will contain nulls.
+  //
+  // The scope argument is optional, and defaults to window.document.
+  window.HTMLWidgets.findAll = function(scope, selector) {
+    if (arguments.length == 1) {
+      selector = scope;
+      scope = document;
+    }
+
+    var nodes = scope.querySelectorAll(selector);
+    var results = [];
+    for (var i = 0; i < nodes.length; i++) {
+      results.push(window.HTMLWidgets.getInstance(nodes[i]));
+    }
+    return results;
+  };
+
+  var postRenderHandlers = [];
+  function invokePostRenderHandlers() {
+    while (postRenderHandlers.length) {
+      var handler = postRenderHandlers.shift();
+      if (handler) {
+        handler();
+      }
+    }
+  }
+
+  // Register the given callback function to be invoked after the
+  // next time static widgets are rendered.
+  window.HTMLWidgets.addPostRenderHandler = function(callback) {
+    postRenderHandlers.push(callback);
+  };
+
+  // Takes a new-style instance-bound definition, and returns an
+  // old-style class-bound definition. This saves us from having
+  // to rewrite all the logic in this file to accomodate both
+  // types of definitions.
+  function createLegacyDefinitionAdapter(defn) {
+    var result = {
+      name: defn.name,
+      type: defn.type,
+      initialize: function(el, width, height) {
+        return defn.factory(el, width, height);
+      },
+      renderValue: function(el, x, instance) {
+        return instance.renderValue(x);
+      },
+      resize: function(el, width, height, instance) {
+        return instance.resize(width, height);
+      }
+    };
+
+    if (defn.find)
+      result.find = defn.find;
+    if (defn.renderError)
+      result.renderError = defn.renderError;
+    if (defn.clearError)
+      result.clearError = defn.clearError;
+
+    return result;
+  }
+})();
+
diff --git a/man/JS.Rd b/man/JS.Rd
new file mode 100644
index 0000000..efe3965
--- /dev/null
+++ b/man/JS.Rd
@@ -0,0 +1,27 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{JS}
+\alias{JS}
+\title{Mark character strings as literal JavaScript code}
+\usage{
+JS(...)
+}
+\arguments{
+\item{...}{character vectors as the JavaScript source code (all arguments
+will be pasted into one character string)}
+}
+\description{
+This function \code{JS()} marks character vectors with a special class, so
+that it will be treated as literal JavaScript code when evaluated on the
+client-side.
+}
+\examples{
+library(htmlwidgets)
+JS('1 + 1')
+list(x = JS('function(foo) {return foo;}'), y = 1:10)
+JS('function(x) {', 'return x + 1;', '}')
+}
+\author{
+Yihui Xie
+}
+
diff --git a/man/createWidget.Rd b/man/createWidget.Rd
new file mode 100644
index 0000000..fa79f84
--- /dev/null
+++ b/man/createWidget.Rd
@@ -0,0 +1,62 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/htmlwidgets.R
+\name{createWidget}
+\alias{createWidget}
+\title{Create an HTML Widget}
+\usage{
+createWidget(name, x, width = NULL, height = NULL,
+  sizingPolicy = htmlwidgets::sizingPolicy(), package = name,
+  dependencies = NULL, elementId = NULL, preRenderHook = NULL)
+}
+\arguments{
+\item{name}{Widget name (should match the base name of the YAML and
+JavaScript files used to implement the widget)}
+
+\item{x}{Widget instance data (underlying data to render and options that
+govern how it's rendered). This value will be converted to JSON using
+\code{\link[jsonlite]{toJSON}} and made available to the widget's
+JavaScript \code{renderValue} function.}
+
+\item{width}{Fixed width for widget (in css units). The default is
+\code{NULL}, which results in intelligent automatic sizing based on the
+widget's container.}
+
+\item{height}{Fixed height for widget (in css units). The default is
+\code{NULL}, which results in intelligent automatic sizing based on the
+widget's container.}
+
+\item{sizingPolicy}{Options that govern how the widget is sized in various
+containers (e.g. a standalone browser, the RStudio Viewer, a knitr figure,
+or a Shiny output binding). These options can be specified by calling the
+\code{\link{sizingPolicy}} function.}
+
+\item{package}{Package where the widget is defined (defaults to the widget
+name).}
+
+\item{dependencies}{Additional widget HTML dependencies (over and above those
+defined in the widget YAML). This is useful for dynamic dependencies that
+only exist when selected widget options are enabled (e.g. sets of map tiles
+or projections).}
+
+\item{elementId}{Use an explicit element ID for the widget (rather than an
+automatically generated one). Useful if you have other JavaScript that
+needs to explicitly discover and interact with a specific widget instance.}
+
+\item{preRenderHook}{A function to be run on the widget, just prior to
+rendering. It accepts the entire widget object as input, and should return
+a modified widget object.}
+}
+\value{
+An object of class \code{htmlwidget} that will intelligently print
+  itself into HTML in a variety of contexts including the R console, within R
+  Markdown documents, and within Shiny output bindings.
+}
+\description{
+Create an HTML widget based on widget YAML and JavaScript contained within
+the specified package.
+}
+\details{
+For additional details on developing widgets, see package vignettes:
+\code{vignette("develop_intro", package = "htmlwidgets")}.
+}
+
diff --git a/man/getDependency.Rd b/man/getDependency.Rd
new file mode 100644
index 0000000..eb5dd2b
--- /dev/null
+++ b/man/getDependency.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{getDependency}
+\alias{getDependency}
+\title{Get js and css dependencies for  a htmlwidget}
+\usage{
+getDependency(name, package = name)
+}
+\arguments{
+\item{name}{name of the widget.}
+
+\item{package}{name of the package, defaults to the widget name.}
+}
+\description{
+Get js and css dependencies for  a htmlwidget
+}
+
diff --git a/man/htmlwidgets-package.Rd b/man/htmlwidgets-package.Rd
new file mode 100644
index 0000000..c82127f
--- /dev/null
+++ b/man/htmlwidgets-package.Rd
@@ -0,0 +1,30 @@
+\docType{package}
+\name{htmlwidgets-package}
+\alias{htmlwidgets}
+\alias{htmlwidgets-package}
+\title{HTML Widgets for R}
+\description{
+The \pkg{htmlwidgets} package provides a framework for easily creating R bindings to JavaScript libraries. Widgets created using the framework can be:
+\enumerate{
+\item Used at the R console for data analysis just like conventional R plots (via RStudio Viewer)
+\item Seamlessly embedded within \href{http://rmarkdown.rstudio.com}{R Markdown} documents and \href{http://shiny.rstudio.com}{Shiny} web applications.
+\item Saved as standalone web pages for ad-hoc sharing via email, Dropbox, etc.
+}
+
+To get started creating your own HTML widgets, see the documentation available in the package vignettes:
+
+\preformatted{
+   vignette("develop_intro", package = "htmlwidgets")
+   vignette("develop_sizing", package = "htmlwidgets")
+   vignette("develop_advanced", package = "htmlwidgets")
+}
+
+Source code for the package is available on GitHub:
+
+\href{https://github.com/ramnathv/htmlwidgets}{https://github.com/ramnathv/htmlwidgets}
+
+}
+\author{
+Ramnath Vaidyanathan, Joe Cheng, JJ Allaire, and Yihui Xie
+}
+
diff --git a/man/htmlwidgets-shiny.Rd b/man/htmlwidgets-shiny.Rd
new file mode 100644
index 0000000..89708a4
--- /dev/null
+++ b/man/htmlwidgets-shiny.Rd
@@ -0,0 +1,63 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/htmlwidgets.R
+\name{htmlwidgets-shiny}
+\alias{htmlwidgets-shiny}
+\alias{shinyRenderWidget}
+\alias{shinyWidgetOutput}
+\title{Shiny bindings for HTML widgets}
+\usage{
+shinyWidgetOutput(outputId, name, width, height, package = name,
+  inline = FALSE)
+
+shinyRenderWidget(expr, outputFunction, env, quoted)
+}
+\arguments{
+\item{outputId}{output variable to read from}
+
+\item{name}{Name of widget to create output binding for}
+
+\item{width, height}{Must be a valid CSS unit (like \code{"100\%"},
+\code{"400px"}, \code{"auto"}) or a number, which will be coerced to a
+string and have \code{"px"} appended.}
+
+\item{package}{Package containing widget (defaults to \code{name})}
+
+\item{inline}{use an inline (\code{span()}) or block container (\code{div()})
+for the output}
+
+\item{expr}{An expression that generates an HTML widget}
+
+\item{outputFunction}{Shiny output function corresponding to this render
+function.}
+
+\item{env}{The environment in which to evaluate \code{expr}.}
+
+\item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})? This
+is useful if you want to save an expression in a variable.}
+}
+\value{
+An output or render function that enables the use of the widget
+  within Shiny applications.
+}
+\description{
+Helpers to create output and render functions for using HTML widgets within
+Shiny applications and interactive Rmd documents.
+}
+\details{
+These functions are delegated to from within your widgets own shiny
+  output and render functions. The delegation is boilerplate and always works
+  the same for all widgets (see example below).
+}
+\examples{
+# shiny output binding for a widget named 'foo'
+fooOutput <- function(outputId, width = "100\%", height = "400px") {
+  htmlwidgets::shinyWidgetOutput(outputId, "foo", width, height)
+}
+
+# shiny render function for a widget named 'foo'
+renderFoo <- function(expr, env = parent.frame(), quoted = FALSE) {
+  if (!quoted) { expr <- substitute(expr) } # force quoted
+  htmlwidgets::shinyRenderWidget(expr, fooOutput, env, quoted = TRUE)
+}
+}
+
diff --git a/man/onRender.Rd b/man/onRender.Rd
new file mode 100644
index 0000000..c996b6b
--- /dev/null
+++ b/man/onRender.Rd
@@ -0,0 +1,86 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/htmlwidgets.R
+\name{onRender}
+\alias{onRender}
+\title{Execute custom JavaScript code after rendering}
+\usage{
+onRender(x, jsCode, data = NULL)
+}
+\arguments{
+\item{x}{An HTML Widget object}
+
+\item{jsCode}{Character vector containing JavaScript code (see Details)}
+
+\item{data}{An additional argument to pass to the \code{jsCode} function.
+This can be any R object that can be serialized to JSON. If you have
+multiple objects to pass to the function, use a named list.}
+}
+\value{
+The modified widget object
+}
+\description{
+Use this function to supplement the widget's built-in JavaScript rendering
+logic with additional custom JavaScript code, just for this specific widget
+object.
+}
+\details{
+The \code{jsCode} parameter must be a valid JavaScript expression
+  that returns a function.
+
+  The function will be invoked with three arguments: the first is the widget's
+  main HTML element, and the second is the data to be rendered (the \code{x}
+  parameter in \code{createWidget}). The third argument is the JavaScript
+  equivalent of the R object passed into \code{onRender} as the \code{data}
+  argument; this is an easy way to transfer e.g. data frames without having
+  to manually do the JSON encoding.
+
+  When the function is invoked, the \code{this} keyword will refer to the
+  widget instance object.
+}
+\examples{
+\dontrun{
+library(leaflet)
+
+# This example uses browser geolocation. RStudio users:
+# this won't work in the Viewer pane; try popping it
+# out into your system web browser.
+leaflet() \%>\% addTiles() \%>\%
+  onRender("
+    function(el, x) {
+      // Navigate the map to the user's location
+      this.locate({setView: true});
+    }
+  ")
+
+
+# This example shows how you can make an R data frame available
+# to your JavaScript code.
+
+meh <- "&#x1F610;";
+yikes <- "&#x1F628;";
+
+df <- data.frame(
+  lng = quakes$long,
+  lat = quakes$lat,
+  html = ifelse(quakes$mag < 5.5, meh, yikes),
+  stringsAsFactors = FALSE
+)
+
+leaflet() \%>\% addTiles() \%>\%
+  fitBounds(min(df$lng), min(df$lat), max(df$lng), max(df$lat)) \%>\%
+  onRender("
+    function(el, x, data) {
+      for (var i = 0; i < data.lng.length; i++) {
+        var icon = L.divIcon({className: '', html: data.html[i]});
+        L.marker([data.lat[i], data.lng[i]], {icon: icon}).addTo(this);
+      }
+    }
+  ", data = df)
+}
+
+}
+\seealso{
+\code{\link{onStaticRenderComplete}}, for writing custom JavaScript
+  that involves multiple widgets.
+}
+
diff --git a/man/onStaticRenderComplete.Rd b/man/onStaticRenderComplete.Rd
new file mode 100644
index 0000000..4b2b2c0
--- /dev/null
+++ b/man/onStaticRenderComplete.Rd
@@ -0,0 +1,52 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/utils.R
+\name{onStaticRenderComplete}
+\alias{onStaticRenderComplete}
+\title{Execute JavaScript code after static render}
+\usage{
+onStaticRenderComplete(jsCode)
+}
+\arguments{
+\item{jsCode}{A character vector containing JavaScript code. No R error will
+be raised if the code is invalid, not even on JavaScript syntax errors.
+However, the web browser will throw errors at runtime.}
+}
+\value{
+An htmltools \code{\link[htmltools]{tags}$script} object.
+}
+\description{
+Convenience function for wrapping a JavaScript code string with a
+\code{<script>} tag and the boilerplate necessary to delay the execution of
+the code until after the next time htmlwidgets completes rendering any
+widgets that are in the page. This mechanism is designed for running code to
+customize widget instances, which can't be done at page load time since the
+widget instances will not have been created yet.
+}
+\details{
+Each call to \code{onStaticRenderComplete} will result in at most one
+invocation of the given code. In some edge cases in Shiny, it's possible for
+static rendering to happen more than once (e.g. a \code{renderUI} that
+contains static HTML widgets). \code{onStaticRenderComplete} calls only
+schedule execution for the next static render operation.
+
+The pure JavaScript equivalent of \code{onStaticRenderComplete} is
+\code{HTMLWidgets.addPostRenderHandler(callback)}, where \code{callback} is a
+JavaScript function that takes no arguments.
+}
+\examples{
+\dontrun{
+library(leaflet)
+library(htmltools)
+library(htmlwidgets)
+
+page <- tagList(
+  leaflet() \%>\% addTiles(),
+  onStaticRenderComplete(
+    "HTMLWidgets.find('.leaflet').setZoom(4);"
+  )
+)
+print(page, browse = TRUE)
+}
+
+}
+
diff --git a/man/prependContent.Rd b/man/prependContent.Rd
new file mode 100644
index 0000000..93fe9d0
--- /dev/null
+++ b/man/prependContent.Rd
@@ -0,0 +1,29 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/htmlwidgets.R
+\name{prependContent}
+\alias{appendContent}
+\alias{prependContent}
+\title{Prepend/append extra HTML content to a widget}
+\usage{
+prependContent(x, ...)
+
+appendContent(x, ...)
+}
+\arguments{
+\item{x}{An HTML Widget object}
+
+\item{...}{Valid \link[htmltools]{tags}, text, and/or
+\code{\link[htmltools]{HTML}}, or lists thereof.}
+}
+\value{
+A modified HTML Widget object.
+}
+\description{
+Use these functions to attach extra HTML content (primarily JavaScript and/or
+CSS styles) to a widget, for rendering in standalone mode (i.e. printing at
+the R console) or in a knitr document. These functions are NOT supported when
+running in a Shiny widget rendering function, and will result in a warning if
+used in that context. Multiple calls are allowed, and later calls do not undo
+the effects of previous calls.
+}
+
diff --git a/man/saveWidget.Rd b/man/saveWidget.Rd
new file mode 100644
index 0000000..7668bdc
--- /dev/null
+++ b/man/saveWidget.Rd
@@ -0,0 +1,30 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/savewidget.R
+\name{saveWidget}
+\alias{saveWidget}
+\title{Save a widget to an HTML file}
+\usage{
+saveWidget(widget, file, selfcontained = TRUE, libdir = NULL,
+  background = "white", knitrOptions = list())
+}
+\arguments{
+\item{widget}{Widget to save}
+
+\item{file}{File to save HTML into}
+
+\item{selfcontained}{Whether to save the HTML as a single self-contained file
+(with external resources base64 encoded) or a file with external resources
+placed in an adjacent directory.}
+
+\item{libdir}{Directory to copy HTML dependencies into (defaults to
+filename_files).}
+
+\item{background}{Text string giving the html background color of the widget.
+Defaults to white.}
+
+\item{knitrOptions}{A list of \pkg{knitr} chunk options.}
+}
+\description{
+Save a rendered widget to an HTML file (e.g. for sharing with others).
+}
+
diff --git a/man/scaffoldWidget.Rd b/man/scaffoldWidget.Rd
new file mode 100644
index 0000000..762c7a1
--- /dev/null
+++ b/man/scaffoldWidget.Rd
@@ -0,0 +1,27 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/scaffold.R
+\name{scaffoldWidget}
+\alias{scaffoldWidget}
+\title{Create implementation scaffolding for an HTML widget}
+\usage{
+scaffoldWidget(name, bowerPkg = NULL, edit = interactive())
+}
+\arguments{
+\item{name}{Name of widget}
+
+\item{bowerPkg}{Optional name of \href{http://bower.io/}{Bower} package upon
+which this widget is based. If you specify this parameter then bower will
+be used to automatically download the widget's source code and dependencies
+and add them to the widget's YAML.}
+
+\item{edit}{Automatically open the widget's JavaScript source file after
+creating the scaffolding.}
+}
+\description{
+Add the minimal code required to implement an HTML widget to an R package.
+}
+\note{
+This function must be executed from the root directory of the package
+  you wish to add the widget to.
+}
+
diff --git a/man/setWidgetIdSeed.Rd b/man/setWidgetIdSeed.Rd
new file mode 100644
index 0000000..1d6e90e
--- /dev/null
+++ b/man/setWidgetIdSeed.Rd
@@ -0,0 +1,27 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/widgetid.R
+\name{setWidgetIdSeed}
+\alias{setWidgetIdSeed}
+\title{Set the random seed for widget element ids}
+\usage{
+setWidgetIdSeed(seed, kind = NULL, normal.kind = NULL)
+}
+\arguments{
+\item{seed}{a single value, interpreted as an integer, or \code{NULL}
+    (see \sQuote{Details}).}
+
+\item{kind}{character or \code{NULL}.  If \code{kind} is a character
+    string, set \R's RNG to the kind desired.  Use \code{"default"} to
+    return to the \R default.  See \sQuote{Details} for the
+    interpretation of \code{NULL}.}
+
+\item{normal.kind}{character string or \code{NULL}.  If it is a character
+    string, set the method of Normal generation.  Use \code{"default"}
+    to return to the \R default.  \code{NULL} makes no change.}
+}
+\description{
+Set a random seed for generating widget element ids. Calling this
+function rather than relying on the default behavior ensures
+stable widget ids across sessions.
+}
+
diff --git a/man/sizingPolicy.Rd b/man/sizingPolicy.Rd
new file mode 100644
index 0000000..027d4bf
--- /dev/null
+++ b/man/sizingPolicy.Rd
@@ -0,0 +1,104 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sizing.R
+\name{sizingPolicy}
+\alias{sizingPolicy}
+\title{Create a widget sizing policy}
+\usage{
+sizingPolicy(defaultWidth = NULL, defaultHeight = NULL, padding = NULL,
+  viewer.defaultWidth = NULL, viewer.defaultHeight = NULL,
+  viewer.padding = NULL, viewer.fill = TRUE, viewer.suppress = FALSE,
+  viewer.paneHeight = NULL, browser.defaultWidth = NULL,
+  browser.defaultHeight = NULL, browser.padding = NULL,
+  browser.fill = FALSE, knitr.defaultWidth = NULL,
+  knitr.defaultHeight = NULL, knitr.figure = TRUE)
+}
+\arguments{
+\item{defaultWidth}{The default width used to display the widget. This
+parameter specifies the default width for viewing in all contexts (browser,
+viewer, and knitr) unless it is specifically overridden with e.g.
+\code{browser.defaultWidth}.}
+
+\item{defaultHeight}{The default height used to display the widget. This
+parameter specifies the default height for viewing in all contexts
+(browser, viewer, and knitr) unless it is specifically overridden with e.g.
+\code{browser.defaultHeight}.}
+
+\item{padding}{Padding around the widget (in pixels). This parameter
+specifies the padding for viewing in all contexts (browser and viewer)
+unless it is specifically overriden by e.g. \code{browser.padding}.}
+
+\item{viewer.defaultWidth}{The default width used to display the widget
+within the RStudio Viewer.}
+
+\item{viewer.defaultHeight}{The default height used to display the widget
+within the RStudio Viewer.}
+
+\item{viewer.padding}{Padding around the widget when displayed in the RStudio
+Viewer (defaults to 15 pixels).}
+
+\item{viewer.fill}{When displayed in the RStudio Viewer, automatically size
+the widget to the viewer dimensions (note that \code{viewer.padding} is
+still applied). Default to \code{TRUE}.}
+
+\item{viewer.suppress}{Never display the widget within the RStudio Viewer
+(useful for widgets that require a large amount of space for rendering).
+Defaults to \code{FALSE}.}
+
+\item{viewer.paneHeight}{Request that the RStudio Viewer be forced to a
+specific height when displaying this widget.}
+
+\item{browser.defaultWidth}{The default width used to display the widget
+within a standalone web browser.}
+
+\item{browser.defaultHeight}{The default height used to display the widget
+within a standalone web browser.}
+
+\item{browser.padding}{Padding around the widget when displayed in a
+standalone browser (defaults to 40 pixels).}
+
+\item{browser.fill}{When displayed in a standalone web browser, automatically
+size the widget to the browser dimensions (note that \code{browser.padding}
+is still applied). Defaults to \code{FALSE}.}
+
+\item{knitr.defaultWidth}{The default width used to display the widget within
+documents generated by knitr (e.g. R Markdown).}
+
+\item{knitr.defaultHeight}{The default height used to display the widget
+within documents generated by knitr (e.g. R Markdown).}
+
+\item{knitr.figure}{Apply the default knitr fig.width and fig.height to the
+widget when it's rendered within R Markdown documents. Defaults to
+\code{TRUE}.}
+}
+\value{
+A widget sizing policy
+}
+\description{
+Define the policy by which HTML widgets will be sized in various containers
+(e.g. Browser, RStudio Viewer, R Markdown, Shiny). Note that typically
+widgets can accept the default sizing policy (or override only one or two
+aspects of it) and get satisfactory sizing behavior via the automatic sizing
+logic built into the htmlwidgets framework (see the notes below for the most
+typical exceptions to this).
+}
+\details{
+The default HTML widget sizing policy treats the widget with the same sizing
+semantics as an R plot. When printed at the R console the widget is displayed
+within the RStudio Viewer and sized to fill the Viewer pane (modulo any
+padding). When rendered inside an R Markdown document the widget is sized
+based on the default size of figures in the document.
+
+You might need to change the default behavior if your widget is extremely
+large. In this case you might specify \code{viewer.suppress = TRUE} and
+\code{knitr.figure = FALSE} as well provide for a larger default width and
+height for knitr.
+
+You also might need to change the default behavior if you widget already
+incorporates padding. In this case you might specify \code{viewer.padding =
+0}.
+
+For additional details on widget sizing:
+
+\code{vignette("develop_sizing", package = "htmlwidgets")}
+}
+
diff --git a/vignettes/develop_advanced.Rmd b/vignettes/develop_advanced.Rmd
new file mode 100644
index 0000000..b00e8fd
--- /dev/null
+++ b/vignettes/develop_advanced.Rmd
@@ -0,0 +1,188 @@
+---
+title: "HTML Widgets: Advanced Topics"
+date: "`r Sys.Date()`"
+output: 
+  html_document:
+    highlight: kate
+    toc: true
+    toc_depth: 4
+    mathjax: null
+vignette: >
+  %\VignetteIndexEntry{Advanced}
+  %\VignetteEngine{knitr::rmarkdown}
+  \usepackage[utf8]{inputenc}
+---
+
+## Overview
+
+This article covers several aspects of creating widgets that are not required by all widgets, but are an essential part of getting bindings to certain types of JavaScript libraries to work properly. Topics covered include:
+
+* Transforming JSON representations of R objects into representations required by JavaScript libraries (e.g. an R data frame to a d3 dataset).
+
+* Tracking instance-specific widget data within JavaScript bindings.
+
+* Passing JavaScript functions from R to JavaScript (e.g. a user provided formatting or drawing function)
+
+* Generating custom HTML to enclose a widget (the default is a `<div>` but some libraries require a different element e.g. a `<span>`).
+
+
+## Data transformation
+
+R objects passed as part of the `x` parameter to the `createWidget()` function are transformed to JSON using the internal function `htmlwidgets:::toJSON()`^[N.B. It is not exported from **htmlwidgets**, so you are not supposed to call this function directly.], which is basically a wrapper function of `jsonlite::toJSON()` by default. However, sometimes this representation is not what is required by the JavaScript library you are interfacing with. There are two JavaScript functions that yo [...]
+
+### HTMLWidgets.dataframeToD3()
+
+R data frames are represented in "long" form (an array of named vectors) whereas d3 typically requires "wide" form (an array of objects each of which includes all names and values). Since the R representation is smaller in size and much faster to transmit over the network, we create the long-form representation of R data, and then transform the data in JavaScript using the `dataframeToD3()` helper function. 
+
+Here is an example of the long-form representation of an R data frame:
+
+```{r echo=FALSE, comment=''}
+htmlwidgets:::toJSON2(head(iris, 3), pretty = TRUE)
+```
+
+After we apply `HTMLWidgets.dataframeToD3()`, it will become:
+
+```{r echo=FALSE, comment=''}
+htmlwidgets:::toJSON2(head(iris, 3), dataframe = 'row', pretty = TRUE)
+```
+
+
+As a real example, the [simpleNetwork](https://christophergandrud.github.io/networkD3/#simple) widget accepts a data frame containing network links on the R side, then transforms it to a d3 representation within the JavaScript `renderValue` function:
+
+```javascript
+renderValue: function(x) {
+
+  // convert links data frame to d3 friendly format
+  var links = HTMLWidgets.dataframeToD3(x.links);
+  
+  // ... use the links, etc ...
+
+}
+```
+
+### HTMLWidgets.transposeArray2D()
+
+Sometimes a 2-dimensional array requires a similar transposition. For this the `transposeArray2D()` function is provided. Here is an example array:
+
+```{r echo=FALSE, comment=''}
+htmlwidgets:::toJSON2(unname(head(iris, 8)), dataframe = 'column', pretty = TRUE)
+```
+
+`HTMLWidgets.transposeArray2D()` can transpose it to:
+
+```{r echo=FALSE, comment=''}
+htmlwidgets:::toJSON2(head(iris, 8), dataframe = 'values', pretty = TRUE)
+```
+
+As a real example, the [dygraphs](https://rstudio.github.io/dygraphs) widget uses this function to transpose the "file" (data) argument it gets from the R side before passing it on to the dygraphs library:
+
+```javascript
+renderValue: function(x) {
+   
+    // ... code excluded ...
+    
+    // transpose array
+    x.attrs.file = HTMLWidgets.transposeArray2D(x.attrs.file);
+    
+    // ... more code excluded ...
+}
+```
+
+### Custom JSON serializer
+
+You may find it necessary to customize the JSON serialization of widget data when the default serializer in **htmlwidgets** does not work in the way you have expected. For widget package authors, there are two levels of customization for the JSON serialization: you can either customize the default values of arguments for `jsonlite::toJSON()`, or just customize the whole function.
+
+1. `jsonlite::toJSON()` has a lot of arguments, and we have already changed some of its default values. Below is the JSON serializer we use in **htmlwidgets** at the moment:
+
+    ```{r eval=FALSE, code=head(capture.output(htmlwidgets:::toJSON2),-1), tidy=FALSE}
+    ```
+
+    For example, we convert data frames to JSON by columns instead of rows (the latter is `jsonlite::toJSON`'s default). If you want to change the default values of any arguments, you can attach an attribute `TOJSON_ARGS` to the widget data to be passed to `createWidget()`, e.g.
+
+    ```{r eval=FALSE}
+    fooWidget <- function(data, name, ...) {
+      # ... process the data ...
+      params <- list(foo = data, bar = TRUE)
+      # customize toJSON() argument values
+      attr(params, 'TOJSON_ARGS') <- list(digits = 7, na = 'string')
+      htmlwidgets::createWidget(name, x = params, ...)
+    }
+    ```
+
+    We changed the default value of `digits` from 16 to 7, and `na` from `null` to `string` in the above example. It is up to you, the package author, whether you want to expose such customization to users. For example, you can leave an extra argument in your widget function so that users can customize the behavior of the JSON serializer:
+
+    ```{r eval=FALSE}
+    fooWidget <- function(data, name, ..., JSONArgs = list(digits = 7)) {
+      # ... process the data ...
+      params <- list(foo = data, bar = TRUE)
+      # customize toJSON() argument values
+      attr(params, 'TOJSON_ARGS') <- JSONArgs
+      htmlwidgets::createWidget(name, x = params, ...)
+    }
+    ```
+
+    You can also use a global option `htmlwidgets.TOJSON_ARGS` to customize the JSON serializer arguments for all widgets in the current R session, e.g.
+
+    ```{r eval=FALSE}
+    options(htmlwidgets.TOJSON_ARGS = list(digits = 7, pretty = TRUE))
+    ```
+
+1. If you do not want to use **jsonlite**, you can completely override the serializer function by attaching an attribute `TOJSON_FUNC` to the widget data, e.g.
+
+    ```{r eval=FALSE}
+    fooWidget <- function(data, name, ...) {
+      # ... process the data ...
+      params <- list(foo = data, bar = TRUE)
+      # customize the JSON serializer
+      attr(params, 'TOJSON_FUNC') <- MY_OWN_JSON_FUNCTION
+      htmlwidgets::createWidget(name, x = params, ...)
+    }
+    ```
+
+    Here `MY_OWN_JSON_FUNCTION` can be an arbitrary R function that converts R objects to JSON. If you have also specified the `TOJSON_ARGS` attribute, it will be passed to your custom JSON function as well.
+
+Note these features about custom JSON serializers require the **shiny** version to be greater than 0.11.1 if you render the widgets in Shiny apps.
+
+## Passing JavaScript functions
+
+As you would expect, character vectors passed from R to JavaScript are converted to JavaScript strings. However, what if you want to allow users to provide custom JavaScript functions for formatting, drawing, or event handling? For this case, the **htmlwidgets** package includes a `JS()` function that allows you to request that a character value is evaluated as JavaScript when it is received on the client.
+
+For example, the [dygraphs](https://rstudio.github.io/dygraphs) widget includes a `dyCallbacks` function that allows the user to provide callback functions for a variety of contexts. These callbacks are "marked" as containing JavaScript so that they can be converted to actual JavaScript functions on the client:
+
+```r
+callbacks <- list(
+  clickCallback = JS(clickCallback)
+  drawCallback = JS(drawCallback)
+  highlightCallback = JS(highlightCallback)
+  pointClickCallback = JS(pointClickCallback)
+  underlayCallback = JS(underlayCallback)
+)
+```
+
+Another example is in the [DT](https://rstudio.github.io/DT) (DataTables) widget, where users can specify an `initCallback` with JavaScript to execute after the table is loaded and initialized:
+
+```r
+datatable(head(iris, 20), options = list(
+  initComplete = JS(
+    "function(settings, json) {",
+    "$(this.api().table().header()).css({'background-color': '#000', 'color': '#fff'});",
+    "}")
+))
+```
+
+If multiple arguments are passed to `JS()` (as in the above example), they will be concatenated into a single string separated by `\n`.
+
+## Custom widget HTML
+
+Typically the HTML "housing" for a widget is just a `<div>` element, and this is correspondingly the default behavior for new widgets that don't specify otherwise. However, sometimes you need a different element type. For example, the [sparkline](https://github.com/htmlwidgets/sparkline) widget requires a `<span>` element so implements the following custom HTML generation function:
+
+```r
+sparkline_html <- function(id, style, class, ...){
+  tags$span(id = id, class = class)
+}
+```
+
+Note that this function is looked up within the package implementing the widget by the convention `widgetname_html` so it need not be formally exported from your package or otherwise registered with **htmlwidgets**.
+
+Most widgets won't need a custom HTML function but if you need to generate custom HTML for your widget (e.g. you need an `<input>` or a `<span>` rather than a `<div>`) then you should use the **htmltools** package (as demonstrated by the code above).
+
diff --git a/vignettes/develop_intro.Rmd b/vignettes/develop_intro.Rmd
new file mode 100644
index 0000000..258e025
--- /dev/null
+++ b/vignettes/develop_intro.Rmd
@@ -0,0 +1,320 @@
+---
+title: "Introduction to HTML Widgets"
+date: "`r Sys.Date()`"
+output: 
+  html_document:
+    highlight: kate
+    toc: true
+    toc_depth: 4
+    mathjax: null
+vignette: >
+  %\VignetteIndexEntry{Introduction}
+  %\VignetteEngine{knitr::rmarkdown}
+  \usepackage[utf8]{inputenc}
+---
+
+## Overview
+
+The **[htmlwidgets](https://cran.r-project.org/package=htmlwidgets)** package provides a framework for creating R bindings to JavaScript libraries. HTML Widgets can be:
+
+* Used at the R console for data analysis just like conventional R plots.
+* Embedded within [R Markdown](http://rmarkdown.rstudio.com) documents
+* Incorporated into [Shiny](http://shiny.rstudio.com) web applications.
+* Saved as standalone web pages for ad-hoc sharing via email, Dropbox, etc.
+
+By following a small set of easy-to-follow conventions, it is possible to create HTML widgets with very little code. All widgets include the following components:
+
+1. **Dependencies**. These are the JavaScript and CSS assets used by the widget (e.g. the library you are creating a wrapper for).
+
+3. **R binding**. This is the function that end users will call to provide input data to the widget as well as specify various options for how the widget should render. This also includes some short boilerplate functions required to use the widget within Shiny applications.
+
+3. **JavaScript binding**. This is the JavaScript code that glues everything together, passing the data and options gathered in the R binding to the underlying JavaScript library.
+
+HTML widgets are always hosted within an R package and should include all of the source code for their dependencies. This is to ensure that code which depends on widgets is fully reproducible (i.e. doesn't require an internet connection or the ongoing availability of an internet service to run).
+
+## Example (sigma.js)
+
+To start with we'll walk through the creation of a simple widget that wraps the [sigma.js](http://sigmajs.org) graph visualization library. When we're done we'll be able to use it to display interactive visualizations of [GEXF](http://gexf.net) (Graph Exchange XML Format) data files. For example:
+
+```{r, eval=FALSE}
+library(sigma)
+data <- system.file("examples/ediaspora.gexf.xml", package = "sigma")
+sigma(data)
+```
+
+<img src="images/sigma.png" alt="sigma" data-toggle="tooltip" data-placement="right" title="" data-original-title="Note this is just an image of the visualization so it's not interactive. You can play with the interactive version by following the steps in the demo section below." onload="$(this).tooltip()">
+
+Note that the above is just an image of the visualization so it's not interactive. You can play with the interactive version by following the steps in the demo section below. 
+
+There is remarkably little code required to create this binding. Below we'll go through all of the components step-by-step. Then we'll describe how you can create your own widgets (including automatically generating basic scaffolding for all of the core components).
+
+### File layout
+
+Let's assume that our widget is named **sigma** and is located within an R package of the same name. Our JavaScript binding source code file is named sigma.js. Since our widget will read GEXF data files we'll also need to include both the base sigma.min.js library as well as its GEXF plugin. Here are the files that we'll add to the package:
+
+```text
+R/
+| sigma.R
+
+inst/
+|-- htmlwidgets/
+|   |-- sigma.js
+|   |-- sigma.yaml
+|   |-- lib/
+|   |   |-- sigma-1.0.3/
+|   |   |   |-- sigma.min.js
+|   |   |   |-- plugins/
+|   |   |   |   |-- sigma.parsers.gexf.min.js
+```
+
+Note the convention that the JavaScript, YAML, and other dependencies are all contained within the `inst/htmlwidgets` directory (which will subsequently be installed into a package sub-directory named `htmlwidgets`).
+
+### Dependencies
+
+Dependencies are the JavaScript and CSS assets used by a widget. Dependencies are included within the `inst/htmlwidgets/lib` directory. Dependencies are specified using a YAML configuration file which uses the name of the widget as its base file name. Here's what our **sigma.yaml** file looks like:
+
+```yaml
+dependencies:
+  - name: sigma
+    version: 1.0.3
+    src: htmlwidgets/lib/sigma-1.0.3
+    script: 
+      - sigma.min.js
+      - plugins/sigma.parsers.gexf.min.js
+```
+
+The dependency `src` specification refers to the directory that contains the library and `script` refers to specific JavaScript files. If your library contains multiple JavaScript files specify each one on a line beginning with `-` as shown here. You can also add `stylesheet` entries and even `meta` or `head` entries. Multiple dependencies may be specified in one YAML file. See the documentation on the `htmlDependency` function in the [**htmltools**](https://cran.r-project.org/package=ht [...]
+
+### R binding
+
+We need to provide users with an R function that invokes our widget. Typically this function will accept input data as well as various options that control the widget's display. Here's the R function for `sigma`:
+
+```r
+#' @import htmlwidgets
+#' @export
+sigma <- function(gexf, drawEdges = TRUE, drawNodes = TRUE,
+                  width = NULL, height = NULL) {
+  
+  # read the gexf file
+  data <- paste(readLines(gexf), collapse="\n")
+  
+  # create a list that contains the settings
+  settings <- list(
+    drawEdges = drawEdges,
+    drawNodes = drawNodes
+  )
+  
+  # pass the data and settings using 'x'
+  x <- list(
+    data = data,
+    settings = settings
+  )
+  
+  # create the widget
+  htmlwidgets::createWidget("sigma", x, width = width, height = height)
+}
+```
+
+The function takes two classes of input: the GEXF data file to render and some additional settings which control how it is rendered. This input is collected into a list named `x` which is then passed on to the `htmlwidgets::createWidget` function. This `x` variable will subsequently be made available to the JavaScript binding for sigma (this is described below). Any width or height parameter specified is also forwarded to the widget (widgets size themselves automatically by default so ty [...]
+
+We want our sigma widget to also work in Shiny applications, so we add the following boilerplate Shiny output and render functions (these are always the same for all widgets):
+
+```r
+#' @export
+sigmaOutput <- function(outputId, width = "100%", height = "400px") {
+  htmlwidgets::shinyWidgetOutput(outputId, "sigma", width, height, package = "sigma")
+}
+#' @export
+renderSigma <- function(expr, env = parent.frame(), quoted = FALSE) {
+  if (!quoted) { expr <- substitute(expr) } # force quoted
+  htmlwidgets::shinyRenderWidget(expr, sigmaOutput, env, quoted = TRUE)
+}
+```
+
+### JavaScript binding
+
+_**Note:** An older, less intuitive JavaScript binding API was used in htmlwidgets 0.5.2 and earlier, and continues to be supported in newer versions of htmlwidgets. See this [archived version](https://cdn.rawgit.com/ramnathv/htmlwidgets/f735840bf938d35d3c4143c0d16515da6ff252bd/develop_intro.html#javascript-binding) for details on the legacy binding API. New widgets are encouraged to use the newer API described below._
+
+The third piece in the puzzle is the JavaScript required to activate the widget. By convention we'll define our JavaScript binding in the file `inst/htmlwidgets/sigma.js`. Here is the full source code of the binding:
+
+```javascript
+HTMLWidgets.widget({
+
+  name: "sigma",
+  
+  type: "output",
+  
+  factory: function(el, width, height) {
+  
+    // create our sigma object and bind it to the element
+    var sig = new sigma(el.id);
+    
+    return {
+      renderValue: function(x) {
+          
+        // parse gexf data
+        var parser = new DOMParser();
+        var data = parser.parseFromString(x.data, "application/xml");
+        
+        // apply settings
+        for (var name in x.settings)
+          sig.settings(name, x.settings[name]);
+        
+        // update the sigma object
+        sigma.parsers.gexf(
+          data,          // parsed gexf data
+          sig,           // sigma object
+          function() {
+            // need to call refresh to reflect new settings and data
+            sig.refresh();
+          }
+        );
+      },
+      
+      resize: function(width, height) {
+        
+        // forward resize on to sigma renderers
+        for (var name in sig.renderers)
+          sig.renderers[name].resize(width, height);  
+      },
+      
+      // Make the sigma object available as a property on the widget
+      // instance we're returning from factory(). This is generally a
+      // good idea for extensibility--it helps users of this widget
+      // interact directly with sigma, if needed.
+      s: sig
+    };
+  }
+});
+```
+
+We provide a name and type for the widget, plus a `factory` function that takes `el` (the HTML element that will host this widget), `width`, and `height` (width and height of the HTML element, in pixels--you can always use `offsetWidth` and `offsetHeight` for this).
+
+The `factory` function should prepare the HTML element to start receiving values. In this case we create a new sigma element and pass it the `id` of the DOM element that hosts the widget on the page.
+
+We're going to need access to the sigma object later (to update its data and settings) so we save it as a variable `sig`. Note that variables declared directly inside of the factory function are tied to a particular widget instance/`el`.
+
+The return value of the `factory` function is called a _widget instance object_. It is a bridge between the htmlwidgets runtime, and the JavaScript visualization that you're wrapping. As the name implies, each widget instance object is responsible for managing a single widget instance on a page.
+
+The widget instance object you create must have one required method, and may have one optional method:
+
+1. The required `renderValue` method actually pours our dynamic data and settings into the widget's DOM element. The `x` parameter contains the widget data and settings. We parse and update the GEXF data, apply the settings to our previously-created `sig` sigma object, and finally call `refresh` to reflect the new values on-screen. This method may be called repeatedly with different data (i.e. in Shiny), so be sure to account for that possibility. If it makes sense for your widget, consi [...]
+
+2. The optional `resize` method is called whenever the element containing the widget is resized. The only reason not to implement this method is if your widget naturally scales (without additional JavaScript code needing to be invoked) when its element size changes. In the case of sigma.js, we forward the sizing information on to each of the underlying sigma renderers.
+
+All JavaScript libraries handle initialization, binding to DOM elements, dynamically updating data, and resizing slightly differently. Most of the work on the JavaScript side of creating widgets is mapping these three functions---`factory`, `renderValue`, and `resize`---correctly onto the behavior of the underlying library.
+
+The sigma.js example uses a simple object literal to create its widget instance object, but you can also use [class based objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Custom_objects) or any other style of object, as long as `obj.renderValue(x)` and `obj.resize(width, height)` can be invoked on it.
+
+You can add additional methods and properties on the widget instance object. Although they won't be called by htmlwidgets itself, they might be useful to users of your widget that know some JavaScript and want to further customize your widget by adding custom JS code (e.g. using the `htmlwidgets::onRender` R function). In this case we add an `s` property to make the sigma object itself available.
+
+### Demo
+
+Our widget is now complete! If you want to test drive it without reproducing all of the code locally you can install it from GitHub as follows:
+
+```r
+devtools::install_github('jjallaire/sigma')
+```
+
+Here's the code to try it out with some sample data included with the package:
+
+```r
+library(sigma)
+sigma(system.file("examples/ediaspora.gexf.xml", package = "sigma"))
+```
+
+If you execute this code in the R console you'll see the widget displayed in the RStudio Viewer (or in an external browser if you aren't running RStudio). If you include it within an R Markdown document the widget will be embedded into the document.
+
+We can also use the widget in a Shiny application:
+
+```r
+library(shiny)
+library(sigma)
+
+gexf <- system.file("examples/ediaspora.gexf.xml", package = "sigma")
+
+ui = shinyUI(fluidPage(
+  checkboxInput("drawEdges", "Draw Edges", value = TRUE),
+  checkboxInput("drawNodes", "Draw Nodes", value = TRUE),
+  sigmaOutput('sigma')
+))
+
+server = function(input, output) {
+  output$sigma <- renderSigma(
+    sigma(gexf, 
+          drawEdges = input$drawEdges, 
+          drawNodes = input$drawNodes)
+  )
+}
+
+shinyApp(ui = ui, server = server)
+```
+
+## Creating your own widgets
+
+### Requirements
+
+To implement a widget you need to create a new R package that in turn depends on the **htmlwidgets** package. You can install the package from CRAN as follows:
+
+```r
+install.packages("htmlwidgets")
+```
+
+While it's not strictly required, the step-by-step instructions below for getting started also make use of the **devtools** package which you can also install from CRAN:
+
+```r
+install.packages("devtools")
+```
+
+### Scaffolding
+
+To create a new widget you can call the `scaffoldWidget` function to generate the basic structure for your widget. This function will:
+
+* Create the .R, .js, and .yaml files required for your widget;
+
+* If provided, take a [Bower](https://bower.io/) package name and automatically download the JavaScript library (and its dependencies) and add the required entries to the .yaml file.
+
+This method is highly recommended as it ensures that you get started with the right file structure. Here's an example that assumes you want to create a widget named 'mywidget' in a new package of the same name:
+
+```r
+devtools::create("mywidget")               # create package using devtools
+setwd("mywidget")                          # navigate to package dir
+htmlwidgets::scaffoldWidget("mywidget")    # create widget scaffolding
+devtools::install()                        # install the package so we can try it
+```
+
+This creates a simple widget that takes a single `text` argument and displays that text within the widgets HTML element. You can try it like this:
+
+```r
+library(mywidget)
+mywidget("hello, world")
+```
+
+This is the most minimal widget possible and doesn't yet include a JavaScript library to interface to (note that `scaffoldWidget` can optionally include JavaScript library dependencies via the `bowerPkg` argument). Before getting started with development you should review the introductory example above to make sure you understand the various components and also review the additional articles and examples linked to in the next section.
+
+### Learning more
+
+#### Additional articles
+
+There are additional articles that cover more advanced ground:
+
+* [HTML Widget Sizing](develop_sizing.html) explains custom sizing policies and when you might need to use them and describes implementing a `resize` method within JavaScript bindings.
+
+* [HTML Widgets: Advanced Topics](develop_advanced.html) describes framework features that support per-widget instance data, data transformations (e.g. converting a data frame into a d3 dataset), and providing widget options that are live JavaScript objects (e.g. function definitions).
+
+The Sizing article is particularly important as most JavaScript libraries require some additional interaction to keep their size synchronized with their containing element.
+
+#### Examples
+
+Studying the code of other packages is a great way to learn more about creating widgets:
+
+1. The [networkD3](https://github.com/christophergandrud/networkD3) package illustrates creating a widget on top of [D3](http://d3js.org), using a custom sizing policy for a larger widget, and providing multiple widgets from a single package.
+
+2. The [dygraphs](https://github.com/rstudio/dygraphs/) package illustrates using widget instance data, handling dynamic re-sizing, and using [magrittr](https://github.com/smbache/magrittr) to decompose a large and flat JavaScript API into a more modular and pipeable R API.
+
+3. The [sparkline](https://github.com/htmlwidgets/sparkline) package illustrates  providing a custom HTML generation function (since sparklines must be housed in `<span>` rather than `<div>` elements).
+ 
+#### Questions and issues
+
+If you have questions about developing widgets or run into problems during development please don't hesitate to [post an issue](https://github.com/ramnathv/htmlwidgets/issues) on the project's GitHub repository.
+
diff --git a/vignettes/develop_sizing.Rmd b/vignettes/develop_sizing.Rmd
new file mode 100644
index 0000000..4fdefe4
--- /dev/null
+++ b/vignettes/develop_sizing.Rmd
@@ -0,0 +1,170 @@
+---
+title: "HTML Widget Sizing"
+date: "`r Sys.Date()`"
+output: 
+  html_document:
+    highlight: kate
+    toc: true
+    toc_depth: 4
+    mathjax: null
+vignette: >
+  %\VignetteIndexEntry{Sizing}
+  %\VignetteEngine{knitr::rmarkdown}
+  \usepackage[utf8]{inputenc}
+---
+
+## Overview
+
+In the spirit of HTML widgets working just like plots in R, it's important that HTML widgets intelligently size themselves to their container, whether it be the RStudio Viewer, a figure in knitr, or a UI panel within a Shiny application. The **htmlwidgets** framework provides a rich mechanism for specifying the sizing behavior of widgets.
+
+This sizing mechanism is designed to address the following constraints that affect the natural size of a widget:
+
+- **The kind of widget it is.** Some widgets may only be designed to look good at small, fixed sizes (like [sparklines](https://github.com/htmlwidgets/sparkline)) while other widgets may want every pixel that can be spared (like [network graphs](http://christophergandrud.github.io/networkD3/)).
+
+- **The context into which the widget is rendered.** While a given widget might look great at 960px by 480px in an R Markdown document, the same widget would look silly at that size in the RStudio Viewer pane, which is typically much smaller.
+
+Widget sizing is handled in two steps:
+
+1. First, a sizing policy is specified for the widget. This is done via the `sizingPolicy` argument to the `createWidget` function. Most widgets can accept the default sizing policy (or override only one or two aspects of it) and get satisfactory sizing behavior (see details below).
+
+2. The sizing policy is used by the framework to compute the correct width and height for a widget given where it is being rendered. This size information is then passed to the `initialize` and `resize` methods of the widgets JavaScript binding. It's up to the widget to then forward this size information to the underlying JavaScript library.
+
+## Specifying a sizing policy
+
+The default HTML widget sizing policy treats the widget with the same sizing semantics as an R plot. When printed at the R console the widget is displayed within the RStudio Viewer and sized to fill the Viewer pane (modulo any padding). When rendered inside an R Markdown document the widget is sized based on the default size of figures in the document.
+
+Note that for most widgets the default sizing behavior is fine and you won't need to create a custom sizing policy. If you need a slightly different behavior than the default you can also selectively override the default behavior by calling the `sizingPolicy` function and passing the result to `createWidget`. For example:
+
+```r
+htmlwidgets::createWidget(
+  "sigma", 
+  x, 
+  width = width, 
+  height = height,
+  sizingPolicy = htmlwidgets::sizingPolicy(
+    viewer.padding = 0,
+    viewer.paneHeight = 500,
+    browser.fill = TRUE
+  )
+)
+```
+
+### Examples
+
+The [networkD3](http://christophergandrud.github.io/networkD3/) package uses custom sizing policies for all of its widgets. The `simpleNetwork` widget eliminates padding (as d3 is already providing padding) and specifies that it wants to fill up as much space as possible when displayed in a standalone web browser:
+
+```r
+sizingPolicy(padding = 0, browser.fill = TRUE)
+```
+
+The `sankeyNetwork` widget requires much more space than is afforded by the RStudio Viewer or a typical knitr figure so it disables those automatic sizing behaviors. It also provides a more reasonable default width and height for knitr documents:
+
+```r
+sizingPolicy(viewer.suppress = TRUE,
+             knitr.figure = FALSE,
+             browser.fill = TRUE,
+             browser.padding = 75,
+             knitr.defaultWidth = 800,
+             knitr.defaultHeight = 500)
+```
+
+### Available options
+
+Here are the various options that can be specified within a sizing policy:
+
+| Option | Description |
+|---|---|
+| **defaultWidth** | The default width used to display the widget. This parameter specifies the default width for viewing in all contexts (browser, viewer, and knitr) unless it is specifically overridden with e.g. browser.defaultWidth. |
+| **defaultHeight** | The default height used to display the widget. This parameter specifies the default height for viewing in all contexts (browser, viewer, and knitr) unless it is specifically overridden with e.g. browser.defaultHeight. |
+| **padding** | Padding around the widget (in pixels). This parameter specifies the padding for viewing in all contexts (browser and viewer) unless it is specifically overridden by e.g. browser.padding. |
+| **viewer.defaultWidth** | The default width used to display the widget within the RStudio Viewer. |
+| **viewer.defaultHeight** | The default height used to display the widget within the RStudio Viewer. |
+| **viewer.padding** | Padding around the widget when displayed in the RStudio Viewer (defaults to 15 pixels). |
+| **viewer.fill** | When displayed in the RStudio Viewer, automatically size the widget to the viewer dimensions (note that viewer.padding is still applied). Default to TRUE. |
+| **viewer.suppress** | Never display the widget within the RStudio Viewer (useful for widgets that require a large amount of space for rendering). Defaults to FALSE. |
+| **viewer.paneHeight** | Request that the RStudio Viewer be forced to a specific height when displaying this widget. |
+| **browser.defaultWidth** | The default width used to display the widget within a standalone web browser. |
+| **browser.defaultHeight** | The default height used to display the widget within a standalone web browser. |
+| **browser.padding** | Padding around the widget when displayed in a standalone browser (defaults to 40 pixels). |
+| **browser.fill** | When displayed in a standalone web browser, automatically size the widget to the browser dimensions (note that browser.padding is still applied). Defaults to FALSE. |
+| **knitr.defaultWidth** | The default width used to display the widget within documents generated by knitr (e.g. R Markdown). |
+| **knitr.defaultHeight** | The default height used to display the widget within documents generated by knitr (e.g. R Markdown). |
+| **knitr.figure** | Apply the default knitr fig.width and fig.height to the widget when it's rendered within R Markdown documents. Defaults to TRUE. |
+
+## JavaScript resize method
+
+Specifying a sizing policy allows htmlwidgets to calculate the width and height of your widget based on where it's being displayed. However, you still need to forward this sizing information on to the underlying JavaScript library you are creating a widget for.
+
+Every JavaScript library handles dynamic sizing a bit differently. Some do it automatically, some have a resize() call to force a layout, and some require that size be set only along with data and other options. Whatever the case, the **htmlwidgets** framework will pass the computed sizes to both your `factory` function and `resize` function. Here's an empty JavaScript binding that illustrates:
+
+```javascript
+HTMLWidgets.widget({
+
+  name: "demo",
+  
+  type: "output",
+  
+  factory: function(el, width, height) {
+  
+    return {
+      renderValue: function(x) {
+      
+      },
+      
+      resize: function(width, height) {
+        
+      }
+    };
+  }
+});
+```
+
+What you do with the passed width and height is up to you and depends on the re-sizing semantics of the underlying JavaScript library you are creating a widget for. A couple of illustrative examples are included in the next section.
+
+### Examples
+
+#### dygraphs
+
+In the [dygraphs](http://rstudio.github.io/dygraphs) widget the implementation of re-sizing is relatively simple since the **dygraphs** library includes a resize() method to automatically size the graph to it's enclosing HTML element:
+
+```javascript
+resize: function(width, height) {
+  if (dygraph)
+    dygraph.resize();
+}
+```
+
+#### forceNetwork
+
+In the [forceNetwork](http://christophergandrud.github.io/networkD3/#force) widget, the passed width and height are applied to the `<svg>` element that hosts the d3 network visualization, as well as forwarded on to the underlying d3 force simulation object:
+
+```javascript
+factory: function(el, width, height) {
+
+  // instance data
+  var el = el;
+  var force = d3.layout.force();
+
+  d3.select(el).append("svg")
+    .attr("width", width)
+    .attr("height", height);
+      
+  return {
+    renderValue: function(x) {
+      // implementation excluded
+    },
+      
+    resize: function(width, height) {
+         
+      d3.select(el).select("svg")
+        .attr("width", width)
+        .attr("height", height);
+
+      force.size([width, height]).resume();
+    }
+  };
+}
+```
+
+As you can see, re-sizing is handled in a wide variety of fashions in different JavaScript libraries. The `resize` method is intended to provide a flexible way to map the automatic sizing logic of **htmlwidgets** directly into the underlying library.
+
diff --git a/vignettes/images/sigma.png b/vignettes/images/sigma.png
new file mode 100644
index 0000000..ecfd2e1
Binary files /dev/null and b/vignettes/images/sigma.png differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-htmlwidgets.git



More information about the debian-med-commit mailing list