Skip to content

feat(about): the third-party open-source licenses, in the About dialog (v0.18.0) - #321

Merged
MerciHanrim merged 1 commit into
mainfrom
feat/licence-screen
Oct 5, 2026
Merged

MerciHanrim merged 1 commit into
mainfrom
feat/licence-screen

Conversation

@MerciHanrim

@MerciHanrim MerciHanrim commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Part of #301 — the second of its two pull requests: the licence screen, its documentation and the release note. Version 0.18.0.

What a person sees

  • About Loop Studio → Third-party open-source licenses. The button turns the same dialog into its licence view, not a second modal. Back to About returns focus to the button; Escape, the backdrop and × close the whole dialog, and the next opening starts on About.
  • The view says first, in the UI language, that these are the notices of the third-party software Loop Studio includes and that they cover those components only, not Loop Studio itself. Loop Studio's own copyright line is unchanged.
  • Then the build's own notices, unchanged and in English, in a scrollable, focusable <pre dir="ltr" lang="en"> that the browser can search, select and copy.
  • Web and PWA: an Open as a text file link to the same-origin THIRD_PARTY_NOTICES.txt in a new tab (rel="noopener noreferrer"); the PWA has the file precached, so the view and the link work offline. The portable file has no separate file, so no link.
  • Loading and a failed read have their own states, with Try again; Back works in every state.
  • The About dialog's links now take the dialog's ink, underlined: the browser's default blue was unreadable on the dark panel.

Where the text comes from

Build Source Pinned by
web THIRD_PARTY_NOTICES.txt, same origin manifest web
PWA the same file, precached manifest pwa
portable template.content.textContent of <template id="third-party-notices"> manifest portable
dev server /THIRD_PARTY_NOTICES.txt, rebuilt in memory manifest web
  • src/licenses/notices.ts reads it once per page; a non-plain-text answer (a host's index.html fallback) or a text that does not start like the notices is a failure, not shown.
  • The dev server's file comes from thirdPartyNoticesDev: noticesFromManifest finds each package of the manifest's web section in node_modules by name and version, checks every licence and NOTICE file's SHA-256 and the whole text's, and serves it from memory or answers 500 with the reason. Nothing is written to disk or fetched. A unit test rebuilds all three sections and compares them with the manifest.

Text, never HTML

  • The notices are a React text child. A new check, check:licence-screen (also a CI step), parses notices.ts, LicensesView.tsx and AboutDialog.tsx with the TypeScript parser and fails on dangerouslySetInnerHTML, innerHTML / outerHTML, insertAdjacentHTML, document.write, createContextualFragment, DOMParser or setHTMLUnsafe, or a loader that does not read the template through .content.textContent; a file that does not parse is a failure. Its rule is tested on 15 made-up sources.

Tests

  • e2e/licenses.spec.ts (dev server): the text on screen is one text node with the manifest's web SHA-256; a selection gives it back (Chrome's selection drops the one final newline, measured and pinned); the link opens the same bytes with no opener; Escape, Back and focus; a refused read, then Try again; a host that answers with HTML; the dev server's file; the name in all 18 languages with the text left English and left to right; a 320 px phone through the More sheet, nothing cut off and no sideways scroll.
  • dist.spec.ts (production bundle), pwa.spec.ts (network down: the view and the link from the precache) and portable-file.spec.ts (the template, no link): the same SHA-256 comparison for each build.
  • The PWA test server now serves .txt as text/plain, as Cloudflare Pages does; it answered application/octet-stream, which the loader rightly refused.

Release, strings and docs

  • Declared user-facing: 0.18.0 and release:0.18.0 (three lines, dated 2026-10-05), nine interface strings, all in 18 languages. The 16 languages other than English and Korean have not been reviewed by a native speaker.
  • The per-language copy tests move their pinned counts by the twelve keys, as each release does. They declare the loanwords Italian and Dutch use (open source, software, copyright) and two Spanish homographs (original, software). pt-BR's Try again is Tentar novamente, the same as pt-PT, so pt-PT stays under its quarter bound (240 of 963), which is unchanged.
  • scripts/arrow-units.json records the view's external-link icon.
  • Docs: docs/guided-tour.md §GT7.1, licenses/README.md, README's release section (it still said "Latest — v0.15.3") and Copyright section, and CHANGELOG.md, which gains v0.16.0 to v0.18.0. The entries for v0.16.0 to v0.17.2 are written from those releases' squash commits.

Verification (local)

  • npx tsc -b, oxlint (39 warnings, the existing baseline), 3,107 unit tests and every check pass; the web, portable and PWA builds and the Cloudflare Production path build with the third-party notices unchanged.
  • End-to-end: the licence, dialog, tour, What's new and storage-session specs 172 of 172 (desktop and mobile), production bundle 16 of 16, PWA 19 of 19, portable file 16 of 16. The full five-shard suite is left to this pull request's CI.

#301 stays open until this is verified in production.

…g (v0.18.0)

Part of #301, the second of its two pull requests. Version 0.18.0.

- About Loop Studio gains a "Third-party open-source licenses" button that
  turns the same dialog into its licence view, not a second modal. The view
  says first that these are the notices of the third-party software Loop
  Studio includes and that they cover those components only, not Loop Studio
  itself; then the build's own notices, unchanged and in English, in a
  scrollable, focusable <pre dir="ltr" lang="en"> that the browser can
  search, select and copy. Back to About returns focus to the button; Escape,
  the backdrop and x close the whole dialog, and the next opening starts on
  About. Loading and a failed read have their own states, with Try again.
- src/licenses/notices.ts reads the text: the same-origin
  THIRD_PARTY_NOTICES.txt on the web and PWA builds (precached by the PWA, so
  it opens offline; a non-plain-text answer such as a host's index.html
  fallback is refused), and template.content.textContent in the portable
  file. The web and PWA builds also offer the file in a new tab with
  rel="noopener noreferrer"; the portable file has no separate file and no
  link. The text is a React text child; a new check, check:licence-screen,
  parses the loader, the view and the dialog with the TypeScript parser and
  fails on any HTML sink (dangerouslySetInnerHTML, innerHTML / outerHTML,
  insertAdjacentHTML, document.write, createContextualFragment, DOMParser,
  setHTMLUnsafe) or a loader that does not read the template's content.
- The dev server serves THIRD_PARTY_NOTICES.txt too (thirdPartyNoticesDev):
  the web build's text rebuilt in memory from the committed manifest and the
  installed packages (noticesFromManifest), with every licence file, NOTICE
  file and the whole text checked against the manifest's SHA-256; nothing is
  written to disk or fetched. A unit test rebuilds all three sections and
  compares them with the manifest.
- e2e: on the dev server, the production bundle, the PWA with the network
  down and the portable file, the text on screen is one text node whose
  SHA-256 is the manifest's for that build; the file link opens the same
  bytes with no opener (offline from the precache on the PWA); a failed read,
  Back, Escape, 18 languages and a 320 px phone are covered. The PWA test
  server now serves .txt as text/plain, as Cloudflare Pages does.
- The About dialog's links take the dialog's ink, underlined: the browser's
  default link blue was unreadable on the dark panel.
- Declared user-facing: version 0.18.0 and release note release:0.18.0, three
  lines; nine new interface strings; all in 18 languages, 16 without native
  review. The per-language copy tests move their pinned counts by those
  twelve keys, as each release does, and declare the loanwords Italian and
  Dutch use (open source, software, copyright) and two Spanish homographs;
  pt-PT stays under its quarter bound. scripts/arrow-units.json records the
  view's external-link icon.
- Docs: docs/guided-tour.md §GT7.1, licenses/README.md, and README's
  release section (it still said "Latest — v0.15.3") and Copyright section;
  CHANGELOG.md gains v0.16.0 to v0.18.0, which it did not have.
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying cozy-loop-studio with  Cloudflare Pages  Cloudflare Pages

Latest commit: 869b892
Status: ✅  Deploy successful!
Preview URL: https://8262080c.cozy-loop-studio.pages.dev
Branch Preview URL: https://feat-licence-screen.cozy-loop-studio.pages.dev

View logs

@MerciHanrim
MerciHanrim merged commit 91c03b5 into main Oct 5, 2026
10 checks passed
@MerciHanrim
MerciHanrim deleted the feat/licence-screen branch October 5, 2026 07:01
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.

1 participant