Skip to content

Adopt shiny-workflows license-note; attribute bundled lit - #4426

Draft
schloerke wants to merge 8 commits into
mainfrom
schloerke/license-note-adopt
Draft

schloerke wants to merge 8 commits into
mainfrom
schloerke/license-note-adopt

Conversation

@schloerke

@schloerke schloerke commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Adopts the license-note helper added in rstudio/shiny-workflows#69 (which closes rstudio/shiny-workflows#28), so the bundled-JavaScript list in LICENSE.note is regenerated by the routine workflow instead of maintained by hand.

What changed

  • LICENSE.note gains a marker pair. The routine workflow rewrites only the region between the markers; the hand-written entries above and all the full license texts below are never touched.
  • package.json gains licenseNote.bundled, naming what actually gets bundled from npm.
  • DESCRIPTION and LICENSE.note gain the missing lit attribution — see below.

Why only two packages are listed

Only @selectize/selectize and lit reach inst/ from node_modules:

  • tools/updateSelectize.R copies node_modules/@selectize/selectize/dist into inst/www/shared/selectize.
  • esbuild inlines lit into inst/www/shared/shiny.js, via srcts/src/components/errorConsole.ts. Confirmed by finding lit-html/lit-html and lit-html/is-server in the built shiny.js.

Everything else currently in LICENSE.note — jQuery, jQuery UI, Bootstrap, bootstrap-datepicker, ion.rangeSlider, DataTables, strftime, showdown.js, highlight.js, the tar implementation from R — is fetched from a CDN or a GitHub archive by a tools/update*.R script rather than from npm, so none of it is discoverable this way. Those entries stay hand-listed outside the markers, which is exactly why the helper only owns a delimited block.

Note that jquery and bootstrap-datepicker do appear in devDependencies but are not what ships: updatejQuery.R downloads from code.jquery.com and updateBootstrapDatepicker.R from the upstream GitHub archive, and jquery is mapped to window.jQuery by esbuild-plugin-globals rather than bundled.

The lit gap — worth a careful look

Adopting the helper surfaced that lit is redistributed in inst/www/shared/shiny.js but was documented nowhere: absent from the LICENSE.note component list, absent from the full license texts (which the file's own preamble promises are "included below"), and absent from Authors@R, where every other bundled library has a cph entry.

This PR adds lit's BSD-3-Clause text and a person(, "Google LLC", role = c("ctb", "cph"), comment = "lit library") entry, following the pattern the file already uses. This is a licensing judgement and I would like a maintainer to confirm it rather than take it on my say-so — both that the attribution is correct and that nothing else bundled is similarly missing. Authors@R was checked to still parse (35 people).

Also worth a second opinion: the generator reads @selectize/selectize as Apache-2.0 from its package.json, which matches the Apache text already under the selectize.js heading here.

Verification

  • The generator is idempotent against this branch: --check exits 0.
  • npm ci (231 packages) then generate reproduces the committed block exactly.

Sequencing

This is inert until shiny-workflows' v1 tag moves. Until then routine runs the released @v1, which has no license-note step, so the markers just sit there as ordinary text. Nothing here breaks in the meantime. To exercise it before merge, point .github/workflows/R-CMD-check.yaml's routine job at @main temporarily (rstudio/shiny-workflows#69 is merged; only the tag move is outstanding).

Merge order: rstudio/shiny-workflows#69, move v1, then this.

Adds the generated-block markers to LICENSE.note and a
`licenseNote.bundled` field to package.json, so that the list of bundled
npm components is kept current by the `routine` workflow instead of by
hand.

Only `@selectize/selectize` and `lit` reach inst/ from node_modules --
`tools/updateSelectize.R` copies selectize's dist, and esbuild inlines
lit into inst/www/shared/shiny.js via srcts/src/components/errorConsole.ts.
Everything else in LICENSE.note is downloaded from a CDN or GitHub by a
tools/update*.R script and stays hand-listed outside the markers.

Doing so surfaced that lit was undocumented: it is redistributed in
shiny.js but appeared in neither LICENSE.note nor Authors@R, while every
other bundled library has both. Adds its BSD-3-Clause text and a `cph`
entry for Google LLC.
schloerke and others added 2 commits August 14, 2026 17:26
r-pkgs asks that LICENSE.note describe "the overall license of the
package, and the specific licenses of each individual component". The
file only did the second half; {diffviewer} and {bslib} both open with
the overall statement.
@schloerke

Copy link
Copy Markdown
Collaborator Author

Re-checked this against the best practices linked in the original issue and found one more gap in this file, now fixed.

r-pkgs asks that LICENSE.note describe "the overall license of the package, and the specific licenses of each individual component". This file only ever did the second half — it opened straight into "The shiny package includes other open source software components" without saying what shiny itself is licensed under. Both {diffviewer} (the package r-pkgs holds up as the model) and {bslib} open with that statement. Added:

The shiny package as a whole is distributed under MIT (see the LICENSE file).

Also worth noting for reviewers, since it is the reason a file like this exists: shiny is MIT and bundles Apache-2.0 (@selectize/selectize), which carries restrictions MIT does not. That is a normal and disclosable situation rather than a problem, but it does make the overall-license sentence load-bearing rather than decorative.

The cph half of the guidance is what the lit commit already addresses.

Matches the upstream change in rstudio/shiny-workflows#69: this file is
about licenses, and versions here would rewrite the block on every
lockfile bump without the licensing having changed.
Both are already exact-pinned devDependencies matching the versions the
tools/update*.R scripts vendor (jquery 3.7.1, bootstrap-datepicker 1.10.0),
so they can be listed from node_modules with no new installs.

Drops their hand-written entries, along with selectize.js, which the
previous commit left listed both by hand and in the generated block.

The generated Apache-2.0 for bootstrap-datepicker matches the Apache text
already under that heading, and MIT for jquery covers both the 3.7.1 copy
and the 1.12.4 one under legacy/.
showdown.js was removed in #4306, which replaced client-side markdown
rendering in showcase mode with server-side rendering and deleted
inst/www/shared/showdown/. Its LICENSE.note entry and license section were
left behind, so the file has been claiming shiny redistributes it since.

No reference to showdown remains anywhere else in the tree.
Both update scripts fetched their files from a CDN or GitHub while the
version was pinned separately in package.json (jQuery) or nowhere at all
(strftime). Sourcing from node_modules makes package.json the single record
of what ships, and lets the license-note step report both licenses
automatically instead of them being maintained by hand.

updatejQuery.R already ran `npm install --save-exact jquery@version`; it
now does so before copying rather than after, and copies from
node_modules/jquery/dist. updateStrftime.R gains the equivalent install,
adding strftime as a devDependency.

Verified by running both scripts: every vendored asset comes out
byte-identical to what was already committed. The npm `dist/` files match
the CDN ones exactly, apart from the source map comment jQuery strips from
CDN builds, which this script already appended.

Tier 2 of the migration stops here. The remaining downloads cannot be
moved without changing what ships or without an unverifiable rebuild:

  - DataTables: npm splits the bundle across datatables.net and
    datatables.net-bs, and the five sort-indicator PNGs are CDN-only, so
    the script would stay half-download either way.
  - ion.rangeSlider, selectize-plugin-a11y: npm has the sources, but both
    are patched after download, so a migration cannot be checked by
    comparing against the committed files.
  - jQuery UI: the vendored copy is a custom download-builder subset
    ("some components"); npm ships the full library.
  - Bootstrap: vendored at 3.4.1 with no update script at all.
rstudio/shiny-workflows#70 made the step opt-in, defaulting to false, so
the markers in LICENSE.note are not enough on their own any more.
@schloerke
schloerke marked this pull request as draft August 18, 2026 15:13
@schloerke

Copy link
Copy Markdown
Collaborator Author

It's not automated well enough. Pausing for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Helper to update LICENSE.note

1 participant