Add a [new feature]: a native SpikerSoft Angular implementation of RegExr-style regex authoring — the interactive editor / cheatsheet / test surface (regexr.com UX: expression bar + flags, cheatsheet sidebar, Text/Tests area with match highlighting, Tools tabs such as Explain / Replace / List / Details). Not an iframe of regexr.com; not the separate “Regexp People–style regex game” — see #41 — regex game (sister ticket, also regex-themed but different product).
Route (target):/tools/(tools:regex) under the tools area — clarify naming/docs so learners don’t confuse it with #41.
Relationship to existing code
We already host a Regular Expression surface in lib-reg-ex (tools library → RegExComponent path). Use it as the starting integration point, but evolve toward a full RegExr-parity tool ported into our ecosystem (standalone components/services, routing, theme). After the port landed, ongoing work tracks SpikerSoft — upstream is only the initial baseline / inspiration, not perpetual sync.
Approach
Baseline: Fork mentally from gskinner/regexr [latest default branch] as the port reference snapshot — reimplement client-side behaviors we need inside Angular, SpikerSoft theme, and our component patterns.
Scope:Client-side UX + JS regex evaluation aligned with screenshot: cheatsheet/reference panel, highlighted expression editing, corpus editor with highlighted matches & timing/summary, tools panel (Explain, Replace, List, Details, Tests tab as feasible). Omit or defer server regexr pieces (PHP/community save/etc.) unless we add our own backends later.
Fork policy: Once ported, development continues on SpikerSoft — we intentionally stop following upstream as source of truth beyond the migration baseline unless we selectively cherry-pick.
License
RegExr is GPL-3.0. Our codebase is public, which aligns with redistribution expectations — still file NOTICE / attribution to Grant Skinner & gskinner, link to upstream, and comply with GPLv3 obligations for this derivative feature (legal review if anything is unclear).
Acceptance (draft)
Tools route /tools/(tools:regex) (or documented equivalent) hosts the ported tool.
Behavioral parity target: core editor UX from screenshot — expression + flags + text + cheatsheet + primary Tools (Explain/Replace/List/Details) as scoped for v1.
Theming integrates with SpikerSoft (glass/light-dark), not pasted regexr.com CSS verbatim long-term.
License + credits visible.
Cross-linked: this ticket (#42) = RegEx authoring tool; #41 = ManzDev Regexp People game native port.
## Summary
Add a **[new feature]**: a **native SpikerSoft Angular** implementation of **[RegExr](https://github.com/gskinner/regexr)**-style regex authoring — the **interactive editor / cheatsheet / test surface** ([regexr.com](https://regexr.com/) UX: expression bar + flags, cheatsheet sidebar, Text/Tests area with match highlighting, Tools tabs such as Explain / Replace / List / Details). **Not** an iframe of regexr.com; **not** the separate “Regexp People–style regex **game**” — see **[#41 — regex game](https://git.spikersoft.com/spikerj/spikersoft-issues/issues/41)** (*sister ticket*, also regex-themed but **different product**).
**Route (target):** `/tools/(tools:regex)` under the tools area — clarify naming/docs so learners don’t confuse it with [#41](https://git.spikersoft.com/spikerj/spikersoft-issues/issues/41).
## Relationship to existing code
We already host a **Regular Expression** surface in **`lib-reg-ex`** (`tools` library → `RegExComponent` path). Use it as the **starting integration point**, but evolve toward a **full RegExr-parity tool** ported into our ecosystem (standalone components/services, routing, theme). After the port landed, ongoing work **tracks SpikerSoft** — upstream is only the initial baseline / inspiration, not perpetual sync.
## Approach
- **Baseline:** Fork mentally from **`gskinner/regexr` [latest default branch]** as **the port reference snapshot** — reimplement client-side behaviors we need inside **Angular**, **SpikerSoft theme**, and our component patterns.
- **Scope:** **Client-side UX + JS regex evaluation** aligned with screenshot: cheatsheet/reference panel, highlighted expression editing, corpus editor with highlighted matches & timing/summary, tools panel (**Explain**, **Replace**, **List**, **Details**, Tests tab as feasible). Omit or defer **server** regexr pieces (PHP/community save/etc.) unless we add our own backends later.
- **Fork policy:** Once ported, **development continues on SpikerSoft** — we intentionally **stop following upstream** as source of truth beyond the migration baseline unless we selectively cherry-pick.
## License
RegExr is **[GPL-3.0](https://github.com/gskinner/regexr/blob/master/LICENSE)**. Our codebase is **public**, which aligns with redistribution expectations — still file **NOTICE** / attribution to Grant Skinner & gskinner, link to upstream, and comply with GPLv3 obligations for this derivative feature (legal review if anything is unclear).
## Acceptance (draft)
- [ ] Tools route `/tools/(tools:regex)` (or documented equivalent) hosts the ported tool.
- [ ] Behavioral parity target: core editor UX from screenshot — expression + flags + text + cheatsheet + primary Tools (**Explain**/Replace/List/Details) as scoped for v1.
- [ ] Theming integrates with SpikerSoft (glass/light-dark), not pasted regexr.com CSS verbatim long-term.
- [ ] License + credits visible.
- [ ] Cross-linked: **this ticket (#42)** = RegEx **authoring tool**; **[#41](https://git.spikersoft.com/spikerj/spikersoft-issues/issues/41)** = ManzDev **Regexp People game** native port.
## Links
- Upstream repo: https://github.com/gskinner/regexr/
- Product reference: https://regexr.com/
Closing — RegExr-style port shipped, evolved well past v1
The RegEx authoring tool has been live in lib-reg-ex for several sprints and has grown well beyond the original v1 acceptance bar. Closing this ticket as done; new work continues against discrete tickets.
Acceptance checklist
Tools route — /tools/(tools:regex) hosts the ported tool. Lesson deep links via ?lessonId=NNNNN.
Behavioral parity — expression + flags + test text + cheatsheet + Explain / Replace / List / Details all implemented; Details adds capture-group color cycling that the upstream lacks.
Theming — full SpikerSoft glassmorphism via @include glass-themed(); honors light/dark theme variables; no RegExr CSS pasted verbatim.
Cross-linked with #41 (Regexp People game — distinct product).
What landed
Core editor (parity items)
Tokenizing pattern bar — live syntax highlighting layered behind a transparent <input>; hover-sync with Explain panel via hoveredTokenIndex signal.
Flag toggles — g / i / m / s / u / y as click-to-toggle buttons (no need to type them in the slashes).
Test-text frame — transparent textarea over a highlight layer; six-color match cycle (--regex-group-N palette) so overlapping captures stay readable.
Tools tabs — Explain (RegExr-style nested-card layout that visualizes group/set nesting), Replace ($1-style preview), List (custom joiner), Details (range / value / capture-group table).
Solver — runs in a Web Worker, races a 250 ms timeout watchdog so a runaway regex never freezes the UI.
Curriculum / lessons (substantial expansion — original ticket scoped only "sandbox" parity)
12 chapters / ~40 lessons in the 40000–49999 lesson-number band (Lesson40100_LookaroundsTutorial etc.).
Two lesson kinds — tutorial (read-and-continue) and challenge (graded against a RegexPlan reference solution).
Backend wiring — RegexLessonStrategyBase + per-chapter strategy files, RegexLessonRegistry, MediatR GetLessonAttemptQueryHandler / CompleteTutorialCommandHandler. Browser-graded attempts are stashed in a long-lived IOfflineAttemptStore (Mongo) and the short-lived ILessonAttemptCache (Redis) so completion survives a Redis restart.
Idempotent tutorial completion — LessonsController.CompleteTutorial now returns 200 OK { JustCompleted: false } for stray re-clicks on already-finished tutorials instead of 410 Gone. Resolves the misleading console error reported during dogfooding.
Lesson pane — lib-regex-lesson-pane shows instructions, hints, expected-match preview, real-time grader feedback, gated Continue button (disabled while POST in flight, label flips to Saving… → Completed).
Catalog navigation — LessonCatalogService chapters → in-component Lessons menu (header dropdown) AND Lessons sidebar pane stay in lockstep via the shared activeLessonNumber() signal; selecting in either surface updates both.
UX scaffolding
Mode toggle — clear Sandbox ↔ Lesson switch in the menu bar (preserves sandbox state via sandboxStateSnapshot so users can scratch around mid-lesson without losing work).
Guided tour — RegExTourService implementing IntroTourProvider; data-tour="…" anchors on every notable surface (pattern bar, flag toggles, test text, tools tabs, lessons menu, both side panes, mode toggle, tour button itself). Step list is filtered against live DOM at start time so missing-element steps never explode the tour.
Three-column desktop layout — lessons-pane (left, 240px) | main pane (1fr) | cheatsheet-pane (right, 260px) by default. Each pane is independently togglable from the View menu (checkbox-style entries) AND has its own in-pane close button. Header shows a Show Cheatsheet button only when the pane is hidden — no duplicate label noise.
Pane swap — View → Swap panes flips lessons↔cheatsheet sides for users who prefer the curriculum on the right.
Responsive collapse — at ≤1280px the cheatsheet column drops out of the grid (still togglable); at ≤900px the layout collapses to a single column with panes stacking above the main pane.
File menu — Save to Browser / Download to Device / Load from Browser / Load from Device via shared SaveContentDialogComponent + LoadContentDialogComponent (parameterized to use SpikerSoftRegExStorage / savedRegex IndexedDB store, distinct from the JSON tool's). Persists pattern + flags + test text + replaceWith + listJoiner.
Persistence + migration
All editor state + pane preferences saved to localStorage under spikersoft.regex-tool.state.v1.
restoreState() reads two generations of legacy keys (sidebarMode string union, very-old cheatsheetOpen boolean) and migrates to the current cheatsheetVisible / lessonsVisible / panesSwapped booleans — covered by unit tests.
Quality bar
Frontend — nx test tools: 487 passed / 2 skipped (489 total) across 39 spec files. Includes targeted coverage for pane toggles, swap persistence, legacy-state migration (3 separate tests), in-pane close button DOM, header Show Cheatsheet rendering, lesson-mode auto-open w/ manual-hide tracking, idempotent tutorial completion gating, and the regex-curriculum reference-solution validator (verifies every RegexPlan.ExpectedMatches against the lesson's reference solution).
Backend — LessonsControllerTests: 31/31 passing, including new cases for the offline-store fallback path and the idempotent re-completion no-op. RegexCurriculumTests validates lesson-number ranges and reference-solution↔plan agreement for every lesson.
#19 — Development > Regular Expressions don't work (referenced; this port is what supersedes it).
#41 — Regexp People game native port (sister, distinct product).
Attribution
SpikerSoft port is a clean-room Angular re-implementation inspired by gskinner/regexr (GPL-3.0). Attribution + license link appear in the in-tool footer and in component-level doc comments.
## Closing — RegExr-style port shipped, evolved well past v1
The RegEx authoring tool has been live in `lib-reg-ex` for several sprints and has grown well beyond the original v1 acceptance bar. Closing this ticket as **done**; new work continues against discrete tickets.
### Acceptance checklist
- [x] **Tools route** — `/tools/(tools:regex)` hosts the ported tool. Lesson deep links via `?lessonId=NNNNN`.
- [x] **Behavioral parity** — expression + flags + test text + cheatsheet + **Explain / Replace / List / Details** all implemented; Details adds capture-group color cycling that the upstream lacks.
- [x] **Theming** — full SpikerSoft glassmorphism via `@include glass-themed()`; honors light/dark theme variables; **no** RegExr CSS pasted verbatim.
- [x] **License + credits** — GPL-3.0 attribution footer linking gskinner/regexr + license, NOTICE-style copy in component header doc.
- [x] **Cross-linked** with #41 (Regexp People game — distinct product).
### What landed
#### Core editor (parity items)
- **Tokenizing pattern bar** — live syntax highlighting layered behind a transparent `<input>`; hover-sync with Explain panel via `hoveredTokenIndex` signal.
- **Flag toggles** — `g / i / m / s / u / y` as click-to-toggle buttons (no need to type them in the slashes).
- **Test-text frame** — transparent textarea over a highlight layer; six-color match cycle (`--regex-group-N` palette) so overlapping captures stay readable.
- **Tools tabs** — Explain (RegExr-style nested-card layout that visualizes group/set nesting), Replace ($1-style preview), List (custom joiner), Details (range / value / capture-group table).
- **Solver** — runs in a Web Worker, races a 250 ms timeout watchdog so a runaway regex never freezes the UI.
#### Curriculum / lessons (substantial expansion — original ticket scoped only "sandbox" parity)
- **12 chapters / ~40 lessons** in the **`40000–49999`** lesson-number band (`Lesson40100_LookaroundsTutorial` etc.).
- **Two lesson kinds** — *tutorial* (read-and-continue) and *challenge* (graded against a `RegexPlan` reference solution).
- **Backend wiring** — `RegexLessonStrategyBase` + per-chapter strategy files, `RegexLessonRegistry`, MediatR `GetLessonAttemptQueryHandler` / `CompleteTutorialCommandHandler`. Browser-graded attempts are stashed in a long-lived `IOfflineAttemptStore` (Mongo) **and** the short-lived `ILessonAttemptCache` (Redis) so completion survives a Redis restart.
- **Idempotent tutorial completion** — `LessonsController.CompleteTutorial` now returns `200 OK { JustCompleted: false }` for stray re-clicks on already-finished tutorials instead of `410 Gone`. Resolves the misleading console error reported during dogfooding.
- **Lesson pane** — `lib-regex-lesson-pane` shows instructions, hints, expected-match preview, real-time grader feedback, gated `Continue` button (disabled while POST in flight, label flips to `Saving…` → `Completed`).
- **Catalog navigation** — `LessonCatalogService` chapters → in-component **Lessons menu** (header dropdown) AND **Lessons sidebar pane** stay in lockstep via the shared `activeLessonNumber()` signal; selecting in either surface updates both.
#### UX scaffolding
- **Mode toggle** — clear Sandbox ↔ Lesson switch in the menu bar (preserves sandbox state via `sandboxStateSnapshot` so users can scratch around mid-lesson without losing work).
- **Guided tour** — `RegExTourService` implementing `IntroTourProvider`; `data-tour="…"` anchors on every notable surface (pattern bar, flag toggles, test text, tools tabs, lessons menu, both side panes, mode toggle, tour button itself). Step list is filtered against live DOM at start time so missing-element steps never explode the tour.
- **Three-column desktop layout** — **lessons-pane (left, 240px) | main pane (1fr) | cheatsheet-pane (right, 260px)** by default. Each pane is independently togglable from the **View** menu (checkbox-style entries) AND has its own in-pane close button. Header shows a `Show Cheatsheet` button only when the pane is hidden — no duplicate label noise.
- **Pane swap** — *View → Swap panes* flips lessons↔cheatsheet sides for users who prefer the curriculum on the right.
- **Responsive collapse** — at ≤1280px the cheatsheet column drops out of the grid (still togglable); at ≤900px the layout collapses to a single column with panes stacking above the main pane.
- **File menu** — *Save to Browser / Download to Device / Load from Browser / Load from Device* via shared `SaveContentDialogComponent` + `LoadContentDialogComponent` (parameterized to use `SpikerSoftRegExStorage` / `savedRegex` IndexedDB store, distinct from the JSON tool's). Persists pattern + flags + test text + replaceWith + listJoiner.
#### Persistence + migration
- All editor state + pane preferences saved to `localStorage` under `spikersoft.regex-tool.state.v1`.
- `restoreState()` reads two generations of legacy keys (`sidebarMode` string union, very-old `cheatsheetOpen` boolean) and migrates to the current `cheatsheetVisible` / `lessonsVisible` / `panesSwapped` booleans — covered by unit tests.
### Quality bar
- **Frontend** — `nx test tools`: **487 passed / 2 skipped (489 total)** across 39 spec files. Includes targeted coverage for pane toggles, swap persistence, legacy-state migration (3 separate tests), in-pane close button DOM, header `Show Cheatsheet` rendering, lesson-mode auto-open w/ manual-hide tracking, idempotent tutorial completion gating, and the regex-curriculum reference-solution validator (verifies every `RegexPlan.ExpectedMatches` against the lesson's reference solution).
- **Backend** — `LessonsControllerTests`: **31/31 passing**, including new cases for the offline-store fallback path and the idempotent re-completion no-op. `RegexCurriculumTests` validates lesson-number ranges and reference-solution↔plan agreement for every lesson.
- **Build** — `nx build tools` clean; no lint errors (eslint / stylelint / angular-eslint template).
### Related tickets / follow-ups
- #19 — *Development > Regular Expressions don't work* (referenced; this port is what supersedes it).
- #41 — Regexp People **game** native port (sister, distinct product).
### Attribution
SpikerSoft port is a clean-room Angular re-implementation inspired by [gskinner/regexr](https://github.com/gskinner/regexr/) (GPL-3.0). Attribution + license link appear in the in-tool footer and in component-level doc comments.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Add a [new feature]: a native SpikerSoft Angular implementation of RegExr-style regex authoring — the interactive editor / cheatsheet / test surface (regexr.com UX: expression bar + flags, cheatsheet sidebar, Text/Tests area with match highlighting, Tools tabs such as Explain / Replace / List / Details). Not an iframe of regexr.com; not the separate “Regexp People–style regex game” — see #41 — regex game (sister ticket, also regex-themed but different product).
Route (target):
/tools/(tools:regex)under the tools area — clarify naming/docs so learners don’t confuse it with #41.Relationship to existing code
We already host a Regular Expression surface in
lib-reg-ex(toolslibrary →RegExComponentpath). Use it as the starting integration point, but evolve toward a full RegExr-parity tool ported into our ecosystem (standalone components/services, routing, theme). After the port landed, ongoing work tracks SpikerSoft — upstream is only the initial baseline / inspiration, not perpetual sync.Approach
gskinner/regexr[latest default branch] as the port reference snapshot — reimplement client-side behaviors we need inside Angular, SpikerSoft theme, and our component patterns.License
RegExr is GPL-3.0. Our codebase is public, which aligns with redistribution expectations — still file NOTICE / attribution to Grant Skinner & gskinner, link to upstream, and comply with GPLv3 obligations for this derivative feature (legal review if anything is unclear).
Acceptance (draft)
/tools/(tools:regex)(or documented equivalent) hosts the ported tool.Links
Closing — RegExr-style port shipped, evolved well past v1
The RegEx authoring tool has been live in
lib-reg-exfor several sprints and has grown well beyond the original v1 acceptance bar. Closing this ticket as done; new work continues against discrete tickets.Acceptance checklist
/tools/(tools:regex)hosts the ported tool. Lesson deep links via?lessonId=NNNNN.@include glass-themed(); honors light/dark theme variables; no RegExr CSS pasted verbatim.What landed
Core editor (parity items)
<input>; hover-sync with Explain panel viahoveredTokenIndexsignal.g / i / m / s / u / yas click-to-toggle buttons (no need to type them in the slashes).--regex-group-Npalette) so overlapping captures stay readable.Curriculum / lessons (substantial expansion — original ticket scoped only "sandbox" parity)
40000–49999lesson-number band (Lesson40100_LookaroundsTutorialetc.).RegexPlanreference solution).RegexLessonStrategyBase+ per-chapter strategy files,RegexLessonRegistry, MediatRGetLessonAttemptQueryHandler/CompleteTutorialCommandHandler. Browser-graded attempts are stashed in a long-livedIOfflineAttemptStore(Mongo) and the short-livedILessonAttemptCache(Redis) so completion survives a Redis restart.LessonsController.CompleteTutorialnow returns200 OK { JustCompleted: false }for stray re-clicks on already-finished tutorials instead of410 Gone. Resolves the misleading console error reported during dogfooding.lib-regex-lesson-paneshows instructions, hints, expected-match preview, real-time grader feedback, gatedContinuebutton (disabled while POST in flight, label flips toSaving…→Completed).LessonCatalogServicechapters → in-component Lessons menu (header dropdown) AND Lessons sidebar pane stay in lockstep via the sharedactiveLessonNumber()signal; selecting in either surface updates both.UX scaffolding
sandboxStateSnapshotso users can scratch around mid-lesson without losing work).RegExTourServiceimplementingIntroTourProvider;data-tour="…"anchors on every notable surface (pattern bar, flag toggles, test text, tools tabs, lessons menu, both side panes, mode toggle, tour button itself). Step list is filtered against live DOM at start time so missing-element steps never explode the tour.Show Cheatsheetbutton only when the pane is hidden — no duplicate label noise.SaveContentDialogComponent+LoadContentDialogComponent(parameterized to useSpikerSoftRegExStorage/savedRegexIndexedDB store, distinct from the JSON tool's). Persists pattern + flags + test text + replaceWith + listJoiner.Persistence + migration
localStorageunderspikersoft.regex-tool.state.v1.restoreState()reads two generations of legacy keys (sidebarModestring union, very-oldcheatsheetOpenboolean) and migrates to the currentcheatsheetVisible/lessonsVisible/panesSwappedbooleans — covered by unit tests.Quality bar
nx test tools: 487 passed / 2 skipped (489 total) across 39 spec files. Includes targeted coverage for pane toggles, swap persistence, legacy-state migration (3 separate tests), in-pane close button DOM, headerShow Cheatsheetrendering, lesson-mode auto-open w/ manual-hide tracking, idempotent tutorial completion gating, and the regex-curriculum reference-solution validator (verifies everyRegexPlan.ExpectedMatchesagainst the lesson's reference solution).LessonsControllerTests: 31/31 passing, including new cases for the offline-store fallback path and the idempotent re-completion no-op.RegexCurriculumTestsvalidates lesson-number ranges and reference-solution↔plan agreement for every lesson.nx build toolsclean; no lint errors (eslint / stylelint / angular-eslint template).Related tickets / follow-ups
Attribution
SpikerSoft port is a clean-room Angular re-implementation inspired by gskinner/regexr (GPL-3.0). Attribution + license link appear in the in-tool footer and in component-level doc comments.