Skip to content

chore: v3.5.13 — 2026-05-10 quality pass#102

Merged
heznpc merged 1 commit intomainfrom
chore/quality-pass-2026-05-10
May 10, 2026
Merged

chore: v3.5.13 — 2026-05-10 quality pass#102
heznpc merged 1 commit intomainfrom
chore/quality-pass-2026-05-10

Conversation

@heznpc
Copy link
Copy Markdown
Owner

@heznpc heznpc commented May 10, 2026

Summary

Multi-front cleanup from a 2026-05-10 review covering the items the recent hotfix train (v3.5.6 → v3.5.12) repeatedly touched: long single-purpose files, missing static type signal, no enforced i18n drift check, and a few production-realistic edge cases in shared helpers.

Refactor

  • src/content/sidebar-chat.js (1224 → 815 lines, –33%) split into:
    • chat-render.js (new) — formatResponse / applyInline / sanitizeHtml. Pure DOM-free markdown→HTML + the trusted-structure HTML sanitizer used by both the live chat bubble and history detail view.
    • chat-history.js (new) — IndexedDB conversation store + history sub-panel. Calls back into sidebar-chat through _sb._chat.{closeSubPanel,formatResponse,sanitizeHtml}.
    • Sub-panel state (savedChatHTML, historyPanelOpen, flashcardPanelOpen) hoisted to _sb._chat.state so the modules share one source of truth instead of duplicating local flags.
    • manifest.json content_scripts.js order updated; tests/format-response.test.js follows the functions to their new home.

Added

  • tsconfig.jsonallowJs + checkJs for IDE / tsc --noEmit. strict:false so the rollout doesn't surface a wave of pre-existing nullability warnings; tighten incrementally.
  • src/lib/_sb-typedef.js — JSDoc-only contract for window._sb and the new _chat / ProtectedTermsApi / GeminiBlockApi sub-namespaces. Not loaded at runtime (no manifest entry).
  • scripts/check-i18n-keys.js + CI step + npm run check:i18n — validates (1) every _locales/<lang>/messages.json matches the English key set, and (2) every *_LABELS / *_GREETINGS / *_PLACEHOLDERS dictionary in constants.js is shape-consistent across the 11 premium languages. Handles flat, lang-outer, and section-outer shapes; skips language-agnostic lookups like SKILLBRIDGE_MODEL_LABELS.
  • docs/E2E_PLAN.md — working spec for the deferred Playwright suite. Records the 6 priority coverage targets (golden translation, SPA mid-stream, cache-cleanup alarm, stream-cancel, protected-terms, panel switch) so the next pass doesn't restart from zero.

Fixed

  • restoreProtectedTerms defends against three production-realistic edge cases: null/undefined/non-string input (returned safe fallback instead of throwing on .includes); empty-string wrong-forms (would have inserted the correct form between every char via replaceAll('', x)); self-mapping entries where wrong-form === correct-form (silent no-op cycle bloating the hot loop on long pages).
  • Background SW + content-script handlers gain _logMisroutedMessage defensive logs: a {action: ...}-shaped message reaching the background (or {type: ...} reaching a content script) warns loudly with the discriminator. Catches the v3.5.6 cache-cleanup class of bug at first occurrence in dev instead of silent fallthrough to "Unknown action".

Build

  • scripts/build-bundle.js esbuild gains pure: ['console.debug', 'console.info']. With minify: true already on, those calls get tree-shaken from production output (verified 0 occurrences in dist/bundled/*.bundle.js). console.warn / console.error preserved on purpose so real degradation/errors still reach DevTools.

Tests

  • tests/protected-terms.test.js (+6 tests): null/undefined/non-string safety, idempotence (f(f(x)) == f(x)), empty-wrong-form skip, self-mapping skip, non-string-array-element skip. Total 24 tests against the helper.
  • Suite: 343/343 pass (was 336).

Deferred

  • Full TypeScript migration — tsconfig.json + _sb-typedef.js are the foundation; per-file JSDoc tightening is incremental work for follow-up PRs.
  • Playwright E2E implementation — docs/E2E_PLAN.md captures the spec; needs a dedicated PR with browser fixtures + network stubs.
  • chat-flashcards.js extraction — flashcard logic is the most tangled with savedChatHTML panel state; safer to split in a focused PR after the _sb._chat panel API has been validated in production.
  • Jest coverage threshold — current test harness loads sources via fs.readFileSync + new Function, which istanbul cannot instrument. Real coverage tracking needs a test-harness refactor first.

Test plan

  • npm test — 343/343 pass
  • npm run lint clean
  • npm run format:check clean
  • npm run validate / glossary / check:sync / check:dicts / check:i18n / check:selectors all pass
  • npm run build:bundle — succeeds, 0 console.debug/console.info in bundled output
  • npm run build:firefox — succeeds
  • Smoke test in unpacked Chrome: load dist/bundled, switch language to Korean on a Skilljar page, open sidebar, send chat, open history, open flashcards, close sidebar (verifies the _sb._chat.state shared flags work end-to-end)

… prod log strip, protected-terms hardening)

Multi-front cleanup from a 2026-05-10 review covering the items the recent
hotfix train (v3.5.6 → v3.5.12) repeatedly touched: long single-purpose
files, missing static type signal, no enforced i18n drift check, and a few
production-realistic edge cases in shared helpers.

Refactor — `src/content/sidebar-chat.js` (1224 → 815 lines, –33%) split into:
  * `chat-render.js` (formatResponse / applyInline / sanitizeHtml)
  * `chat-history.js` (IDB store + history sub-panel)
  * Sub-panel state (savedChatHTML, history/flashcard flags) hoisted to
    `_sb._chat.state` so the modules share one source of truth.
  * Manifest content_scripts.js order updated; format-response.test.js
    follows the functions to chat-render.js.

Added:
  * `tsconfig.json` (allowJs + checkJs, strict:false) for IDE / `tsc --noEmit`.
  * `src/lib/_sb-typedef.js` — JSDoc-only contract for `window._sb` and the
    new `_chat` / ProtectedTermsApi / GeminiBlockApi sub-namespaces.
  * `scripts/check-i18n-keys.js` + CI step + `npm run check:i18n` —
    validates _locales/ key parity and constants.js label-dict shape across
    the 11 premium languages (handles flat, lang-outer, and section-outer
    shapes; skips language-agnostic lookups like SKILLBRIDGE_MODEL_LABELS).
  * `docs/E2E_PLAN.md` — working spec for the deferred Playwright suite
    (6 priority targets) so the next pass doesn't restart from zero.

Fixed:
  * `restoreProtectedTerms` defends against null/undefined/non-string input,
    empty-string wrong-forms (would have inserted between every char via
    `replaceAll('', x)`), and self-mapping entries.
  * Background SW + content-script handlers now warn on misrouted
    `action`/`type` discriminators (catches the v3.5.6 cache-cleanup class
    of bug at first occurrence in dev instead of silent fallthrough).

Build:
  * `build-bundle.js` esbuild gains `pure: ['console.debug','console.info']`
    so production bundles strip dev-only logs (verified 0 occurrences in
    dist/bundled). `console.warn`/`error` preserved on purpose.

Tests: 343/343 (+7 new, +6 in protected-terms covering the new edge cases).
@heznpc heznpc merged commit 04ec872 into main May 10, 2026
3 checks passed
@heznpc heznpc deleted the chore/quality-pass-2026-05-10 branch May 10, 2026 16:14
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