github Foblex/f-flow v19.3.0
v19.3.0 - Strict CSP Support Without unsafe-inline and Connection Worker Cleanup

3 hours ago

v19.3 is a community release: both changes in it were contributed by @chris-perry, from the problem statement to the pull request.

There are no breaking changes. The documented CSS classes and the shipped SCSS theme are untouched.

Styles a strict CSP can hash

Angular injects component styles at runtime as <style> elements. Under emulated encapsulation every rule is rewritten with generated scoping attributes:

/* what the source says */
:host { position: absolute; }

/* what the browser receives */
[_nghost-ng-c2570364828] { position: absolute; }

Those attributes are an artifact of the build — hash the style text today, and a refactor that changes component registration order can change it tomorrow. Nonces avoid that, but need a server rendering HTML per response, which rules out static hosting. So a strict style-src effectively required 'unsafe-inline'.

As of v19.3.0 all 14 styled components declare ViewEncapsulation.None, and every rule is written against the component's own element selector — f-selection-area { … } instead of :host { … } (#329). The emitted CSS is byte-for-byte what's in the source, so it can be hashed once:

// collect the hashes for style-src from a running build
await Promise.all(
  [...document.querySelectorAll('style')].map(async (s) => {
    const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(s.textContent));
    return `'sha256-${btoa(String.fromCharCode(...new Uint8Array(digest)))}'`;
  }),
);
Content-Security-Policy: style-src 'self' 'sha256-…' 'sha256-…'

Verified against a production build served with a real, enforced header: with the collected hashes everything renders and a full drag-to-connect gesture works — zero violations, zero 'unsafe-inline'.

One scoping subtlety is covered by a follow-up and a regression spec: emulated encapsulation limited rules like :host svg to the component's own template, so the shipped rules use the child combinator (f-connection > svg) — projected user content (custom svg[fMarker] markers, icons inside [fConnectionContent]) keeps its own layout.

The connection worker shuts down with its flow

The connection worker state is provided per f-flow instance, but its dispose() had no caller: destroy a flow, and its worker thread and blob URL stayed alive (#330). For applications that open and close editors — a dialog with a flow inside, a tab switcher, a router that recreates the page — that was a slow leak of threads.

Disposal is now wired into the flow's own teardown: ngOnDestroy terminates the worker, revokes its blob URL, and rejects in-flight requests. Each flow cleans up exactly what it created.

Upgrade notes

  • No breaking changes.
  • Library rules lost the specificity that emulated scoping attributes added — application overrides that previously lost a specificity tie may now win. If you override library internals, a quick visual pass after upgrading is worth it.
  • To adopt a strict CSP: build, collect the injected style hashes, and ship style-src 'self' 'sha256-…'. No nonce infrastructure required.

Thanks

@chris-perry — the CSP argument in #329 was one of the best-argued reports this project has received, and both pull requests (#333, #334) followed the library's architecture closely enough that review only had to guard the edges.

If Foblex Flow is useful to you, a ⭐ on the repo helps a lot 🙌

Full changelog: CHANGELOG.md

Don't miss a new f-flow release

NewReleases is sending notifications on new releases.