Skip to content

Replace line halo with dotted-end connector style - #128

Merged
mkpoli merged 8 commits into
masterfrom
feat/dotted-end-replace-halo
May 31, 2026
Merged

mkpoli merged 8 commits into
masterfrom
feat/dotted-end-replace-halo

Conversation

@mkpoli

@mkpoli mkpoli commented May 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Drop the line-halo (background-stroke crossing mask) — it looked muddy in practice and clashed with the colour-coded connector aesthetic.
  • Replace it with a dotted-end style: connectors are dotted near each endpoint and solid through the middle, calling out the word being linked while keeping the central line crisp.
  • Rename lineHalo / lineHaloWidth (two knobs) → dottedEnd (single boolean) in Parameters, +page, persisted-params, and i18n-svelte. en.json swaps params_line_halo[_on] for params_dotted_end[_on]; other locales had no halo translation yet so there's nothing to remove.

Rendering technique

Two-pass SVG overlay per connector path, using pathLength="100" normalisation:

  1. First pass — full-length dotted stroke (stroke-dasharray="lineWidth lineWidth*2", stroke-linecap="round") renders the dotted ends.
  2. Second pass — solid middle (stroke-dasharray="50 100", stroke-dashoffset="-25") overlays positions 25–75 of the normalised path.

Net visual: ⋯⋯───solid───⋯⋯ — regardless of path length or curvature.

Test plan

  • Toggle the new "Dotted Ends" checkbox under Options; lines render dotted near words, solid in the middle.
  • Verify it stacks with lineStyle (solid / dashed / dotted) — when dottedEnd is off, behaviour matches main.
  • Refresh — dottedEnd persists via persisted-params snapshot.
  • Export PNG / SVG / PDF preserves the two-pass rendering.

Summary by CodeRabbit

  • New Features

    • Replaced the prior line "halo" option with a new "dotted endpoint radius" control to render filled dots at connector endpoints and adjust their size.
  • Localization

    • Added translations for the dotted endpoint radius label across 26+ locales to surface the new control in many languages.

Drop the line-halo (background-coloured stroke for crossing legibility) —
in practice it looked muddled and conflicted with the colour-coded
connector aesthetic. Replace it with a dotted-end style: connectors are
dotted near each endpoint and solid through the middle, which both calls
out the word being linked and keeps the central line visually crisp.

Implementation uses an SVG two-pass overlay with pathLength=100
normalisation, so the solid middle covers the 25%–75% range of every
path regardless of its actual length.

UI/state: rename lineHalo/lineHaloWidth → dottedEnd (single boolean) in
Parameters, +page, persisted-params, i18n-svelte. en.json swaps
params_line_halo[_on] for params_dotted_end[_on]; other locales had no
halo translation yet so nothing to remove.
@vercel

vercel Bot commented May 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
word-order Ready Ready Preview, Comment May 31, 2026 10:08am

Request Review

@coderabbitai

coderabbitai Bot commented May 27, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Replaces the line halo connector-rendering option with a new dottedEndRadius parameter: adds localization keys, updates persisted params and i18n mapping, implements deduplicated endpoint-circle rendering in Output.svelte, updates Parameters UI to a slider, and wires state persistence and prop binding in +page.svelte.

Changes

Dotted Endpoint Radius Feature

Layer / File(s) Summary
Type contracts and localization infrastructure
src/lib/persisted-params.ts, src/i18n/i18n-svelte.ts, project.inlang/messages/*, .claude/worktrees/svelte5-migrate
ParamsSnapshot adds dottedEndRadius?: number and removes lineHalo/lineHaloWidth; createLL() maps params.dottedEndRadius to m.params_dotted_end_radius; params_dotted_end_radius key added across message files; worktree pointer advanced.
Connector endpoint rendering
src/lib/Output.svelte
Props replace lineHalo/lineHaloWidth with dottedEndRadius (default 0); uniqueEndpoints(lines) deduplicates endpoints by quantizing (x,y)+color; halo SVG pass removed; when dottedEndRadius > 0 filled <circle> elements are rendered at deduped endpoints.
Parameter slider UI
src/lib/Parameters.svelte
Props interface removes halo props and adds dottedEndRadius ($bindable(0)); UI replaces halo checkbox+disabled range with RangeSlider bound to dottedEndRadius; .halo-row CSS removed.
State management and wiring
src/routes/+page.svelte
Reactive dottedEndRadius state added; onMount() restores it from loadParams() and autosave persists it with saveParams(); <Output> and <Parameters> are wired to use dottedEndRadius.

Sequence Diagram (high-level):

sequenceDiagram
  participant Parameters as Parameters.svelte
  participant Page as +page.svelte
  participant Output as Output.svelte
  participant Dedup as uniqueEndpoints()
  participant SVG as SVG rendering
  Parameters->>Page: bind dottedEndRadius
  Page->>Output: pass dottedEndRadius prop
  Output->>Dedup: extract endpoints from lines
  Dedup->>Dedup: quantize (x,y)+color to dedupe
  Dedup-->>SVG: unique endpoint list
  SVG->>SVG: render connector paths
  SVG->>SVG: render filled circles at endpoints (dottedEndRadius > 0)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I swapped the halos for little dots,
Each line end gleams like playful spots;
Params slid smooth, persistence kept,
Endpoints tidy, no stacks left wept;
A tiny rabbit hops — the UI hops!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Replace line halo with dotted-end connector style' accurately summarizes the main change: removing the line halo feature and replacing it with a new dotted-end connector rendering approach. It is concise, specific, and clearly reflects the primary objective of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dotted-end-replace-halo

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

User feedback: "I mean a dot at the end, similar to what our og image".
The og-image draws a solid connector with a filled coloured circle at
each endpoint — that's the visual we want, not a two-pass dotted-then-
solid overlay on the line itself.

Replace the previous pathLength-overlay trick with a clean second pass:
the original connector renders normally (respecting the user's line
style), then for each unique endpoint we draw a filled circle of the
connector colour. Endpoints are deduped by quantised (x,y,color) so the
short straight-segment fragments drawLines emits when straightLength > 0
don't stack three coincident dots.

Dot radius scales with lineWidth (max with a small floor) so it stays
visible at thin line widths and proportional at thick ones.
Replace the dottedEnd on/off checkbox with a 0-10px radius slider.
dottedEnd:boolean becomes dottedEndRadius:number across Parameters,
Output, +page and the persisted-params snapshot; endpoint circles now
render with r={dottedEndRadius}, drawn only when the radius is > 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the dotted-end control to its sibling parameters: use the shared
<RangeSlider> with a " px" suffix instead of a bare <input type="range">, so
it looks and behaves like Line Width / Space Width etc.

i18n: the control had only an en-only orphan pair (params_dotted_end +
params_dotted_end_on, the latter unused since the checkbox was removed).
Replace them with a single accurate params_dotted_end_radius ("Dot radius")
and translate it into every locale, grounded in each locale's vocab
(ja 点の半径, ja-Hira てんの おおきさ, ko 점 반지름, ko-Kore 點 반지름,
zh-HanS 圆点半径, ain Noka poro hi, …). Drop the dottedEnd/dottedEndOn
accessors and wire dottedEndRadius in i18n-svelte.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The dotted-end RangeSlider had no step (defaulting to 1), so it jumped a whole
pixel at a time. Match the fine-grained siblings (line-width, letter-spacing,
curvature) with step={0.1} for smooth dragging.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/routes/+page.svelte (1)

252-257: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clamp restored dottedEndRadius to the slider range.

loadParams() reads user-controlled localStorage, and this new field is only type-checked before being passed through to SVG rendering. A corrupted/manual edit can restore negative or oversized radii here, unlike the UI path which constrains the value to 0..10.

🛡️ Suggested fix
-		if (typeof stored.dottedEndRadius === 'number') dottedEndRadius = stored.dottedEndRadius;
+		if (typeof stored.dottedEndRadius === 'number') {
+			dottedEndRadius = Math.max(0, Math.min(10, stored.dottedEndRadius));
+		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/`+page.svelte around lines 252 - 257, The loadParams() restore
logic allows an out-of-range dottedEndRadius from localStorage; clamp the
restored value to the same slider bounds used in the UI (0..10) before assigning
dottedEndRadius. Locate the loadParams() function and replace the unconditional
assignment guarded only by typeof stored.dottedEndRadius === 'number' with a
clamp operation (e.g., Math.min(Math.max(stored.dottedEndRadius, 0), 10)) so
dottedEndRadius is always within 0..10 when restored.
src/lib/Output.svelte (1)

194-198: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Only render dots for the outer connector endpoints.

When straightLength > 0, drawLines() turns one logical connector into three segments, but uniqueEndpoints(lines) collects endpoints from all of them. That also emits circles at the stub/curve junctions, so this feature draws extra dots in the middle of a connector whenever straight stubs are enabled.

💡 Suggested direction
+	type EndpointDot = { x: number; y: number; color: string };
+
-	function drawLines(
+	function drawLines(
 		word_spans: HTMLSpanElement[][],
 		equivalency: number[][][],
 		verticalGap: number,
 		lineGap: number,
 		straightLength: number,
 		endpointCorrection: number
-	): Line[] {
+	): { lines: Line[]; endpointDots: EndpointDot[] } {
 		if (!output) return [];
 		const rectOutput = output.getBoundingClientRect();

 		const lines: Line[] = [];
+		const endpointDots: EndpointDot[] = [];
@@
 						const color = colors[i];
+						endpointDots.push({ x: x1, y: y1, color }, { x: x2, y: y2, color });
 						lines.push([x1, y1 + straightLength, x2, y2 - straightLength, color]);
@@
-		return lines;
+		return { lines, endpointDots };
 	}

Then dedupe/render endpointDots instead of re-deriving them from the segmented lines array.

Also applies to: 214-223, 954-965

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/Output.svelte` around lines 194 - 198, uniqueEndpoints(lines) is
currently collecting endpoints from every sub-segment created by drawLines()
(which splits a logical connector into 3 segments when straightLength > 0),
causing dots to be rendered at stub/curve junctions; instead, compute and dedupe
the outer connector endpoints once (use the already-derived endpointDots or
build it from the original connector endpoints before segmentation) and render
those deduped endpointDots rather than re-deriving from the segmented lines
array. Update drawLines()/any code that pushes into lines and the call-site that
uses uniqueEndpoints(lines) to use the precomputed outer endpoints (deduped) for
circle rendering; apply the same change to the other occurrences with the
segmented push logic (the other drawLines-like blocks referenced in the review)
so only outer endpoints are emitted.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/Output.svelte`:
- Around line 71-74: The docstring for the prop dottedEndRadius is out of date
(it describes a dotted-stroke approach) — update the comment above
dottedEndRadius in Output.svelte to describe the current behavior: it controls
the radius of the filled endpoint circles rendered at connector ends (units,
e.g. pixels), how it affects visual appearance (size of the filled caps) and any
interaction/spacing implications; replace references to "dotted" or "halo" with
"filled endpoint circles" and note default value/units and that the connector
stroke itself is solid in the middle.

---

Outside diff comments:
In `@src/lib/Output.svelte`:
- Around line 194-198: uniqueEndpoints(lines) is currently collecting endpoints
from every sub-segment created by drawLines() (which splits a logical connector
into 3 segments when straightLength > 0), causing dots to be rendered at
stub/curve junctions; instead, compute and dedupe the outer connector endpoints
once (use the already-derived endpointDots or build it from the original
connector endpoints before segmentation) and render those deduped endpointDots
rather than re-deriving from the segmented lines array. Update drawLines()/any
code that pushes into lines and the call-site that uses uniqueEndpoints(lines)
to use the precomputed outer endpoints (deduped) for circle rendering; apply the
same change to the other occurrences with the segmented push logic (the other
drawLines-like blocks referenced in the review) so only outer endpoints are
emitted.

In `@src/routes/`+page.svelte:
- Around line 252-257: The loadParams() restore logic allows an out-of-range
dottedEndRadius from localStorage; clamp the restored value to the same slider
bounds used in the UI (0..10) before assigning dottedEndRadius. Locate the
loadParams() function and replace the unconditional assignment guarded only by
typeof stored.dottedEndRadius === 'number' with a clamp operation (e.g.,
Math.min(Math.max(stored.dottedEndRadius, 0), 10)) so dottedEndRadius is always
within 0..10 when restored.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5e6f7a28-d3bc-43fb-8bdd-6c1f456b3981

📥 Commits

Reviewing files that changed from the base of the PR and between 63950f0 and 673a268.

📒 Files selected for processing (37)
  • project.inlang/messages/ain.json
  • project.inlang/messages/ar.json
  • project.inlang/messages/bg.json
  • project.inlang/messages/bn.json
  • project.inlang/messages/de.json
  • project.inlang/messages/en.json
  • project.inlang/messages/eo.json
  • project.inlang/messages/es.json
  • project.inlang/messages/fa.json
  • project.inlang/messages/fi.json
  • project.inlang/messages/fr.json
  • project.inlang/messages/grc.json
  • project.inlang/messages/hi.json
  • project.inlang/messages/ia.json
  • project.inlang/messages/id.json
  • project.inlang/messages/it.json
  • project.inlang/messages/ja-Hira.json
  • project.inlang/messages/ja.json
  • project.inlang/messages/ko-Kore.json
  • project.inlang/messages/ko.json
  • project.inlang/messages/la.json
  • project.inlang/messages/nl.json
  • project.inlang/messages/pl.json
  • project.inlang/messages/pt.json
  • project.inlang/messages/ru.json
  • project.inlang/messages/th.json
  • project.inlang/messages/tok.json
  • project.inlang/messages/tr.json
  • project.inlang/messages/uk.json
  • project.inlang/messages/vi.json
  • project.inlang/messages/zh-HanS.json
  • project.inlang/messages/zh-HanT.json
  • src/i18n/i18n-svelte.ts
  • src/lib/Output.svelte
  • src/lib/Parameters.svelte
  • src/lib/persisted-params.ts
  • src/routes/+page.svelte

Comment thread src/lib/Output.svelte Outdated
mkpoli and others added 2 commits May 31, 2026 16:30
…e render

The comment still described the old dotted-stroke / halo approach. Update it to
describe current behavior: radius (px) of the filled endpoint circles at each
connector end; stroke stays solid in the middle; 0 (default) hides the dots.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lace-halo

# Conflicts:
#	project.inlang/messages/ain.json
#	project.inlang/messages/ar.json
#	project.inlang/messages/bg.json
#	project.inlang/messages/bn.json
#	project.inlang/messages/de.json
#	project.inlang/messages/eo.json
#	project.inlang/messages/es.json
#	project.inlang/messages/fa.json
#	project.inlang/messages/fi.json
#	project.inlang/messages/fr.json
#	project.inlang/messages/grc.json
#	project.inlang/messages/hi.json
#	project.inlang/messages/ia.json
#	project.inlang/messages/id.json
#	project.inlang/messages/it.json
#	project.inlang/messages/ja-Hira.json
#	project.inlang/messages/ja.json
#	project.inlang/messages/ko-Kore.json
#	project.inlang/messages/ko.json
#	project.inlang/messages/la.json
#	project.inlang/messages/nl.json
#	project.inlang/messages/pl.json
#	project.inlang/messages/pt.json
#	project.inlang/messages/ru.json
#	project.inlang/messages/th.json
#	project.inlang/messages/tok.json
#	project.inlang/messages/tr.json
#	project.inlang/messages/uk.json
#	project.inlang/messages/vi.json
#	project.inlang/messages/zh-HanS.json
#	project.inlang/messages/zh-HanT.json
Per request, render the dot as ain "sinkop" → "Sinkop poro hi" (dot size)
instead of the generic "Noka" (image).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
project.inlang/messages/bn.json (1)

170-170: ⚡ Quick win

Group translation keys by semantic category for consistency.

The params_dotted_end_radius key is placed at the end of the file, separated from other params_* keys grouped at lines 6-39. For maintainability, place this key near related line-style parameters (after params_line_style_dotted around line 13).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@project.inlang/messages/bn.json` at line 170, Move the translation key
"params_dotted_end_radius" next to the other params_* keys (specifically after
"params_line_style_dotted") so all line-style/params keys are grouped together;
update the JSON ordering by cutting the "params_dotted_end_radius" entry from
its current end-of-file location and inserting it immediately after
"params_line_style_dotted" to keep semantic grouping and consistency.
project.inlang/messages/de.json (1)

170-170: ⚡ Quick win

Group translation keys by semantic category for consistency.

The params_dotted_end_radius key is placed at the end of the file, separated from other params_* keys grouped at lines 6-47. For maintainability, place this key near related line-style parameters (after params_line_style_dotted around line 13).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@project.inlang/messages/de.json` at line 170, Move the
"params_dotted_end_radius" translation key so it is grouped with other
line-style parameters: locate "params_line_style_dotted" and insert
"params_dotted_end_radius": "Punktradius" directly after it (or within that
contiguous params_* block) to keep all line-style keys together and maintain
consistency.
project.inlang/messages/ar.json (1)

170-170: ⚡ Quick win

Group translation keys by semantic category for consistency.

The params_dotted_end_radius key is placed at the end of the file, separated from other params_* keys grouped at lines 6-47. For maintainability, place this key near related line-style parameters (after params_line_style_dotted around line 13).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@project.inlang/messages/ar.json` at line 170, Move the
"params_dotted_end_radius" key so it sits with the other params_* line-style
keys (near "params_line_style_dotted" and related entries) instead of at the end
of the file; locate the "params_dotted_end_radius" entry and cut/paste it into
the block containing "params_line_style_dotted" (and other params_ keys) to keep
semantic grouping consistent.
project.inlang/messages/ain.json (1)

167-167: ⚡ Quick win

Group translation keys by semantic category for consistency.

The params_dotted_end_radius key is placed at the end of the file (line 167), separated from other params_* keys that are grouped together (lines 6-46). In contrast, en.json places this key at line 14, near related line-style parameters.

For maintainability, place this key in the params section alongside other connector-line parameters (after params_line_style_dotted around line 13).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@project.inlang/messages/ain.json` at line 167, Move the
"params_dotted_end_radius" entry from its current trailing position into the
params group near other connector-line keys: locate "params_line_style_dotted"
and insert "params_dotted_end_radius" directly after that key (so it sits with
other params_* keys), ensuring JSON ordering and commas remain valid and no
duplicate keys are introduced; update surrounding commas if needed and keep the
translation string unchanged.
project.inlang/messages/es.json (1)

170-170: ⚡ Quick win

Group translation keys by semantic category for consistency.

The params_dotted_end_radius key is placed at the end of the file, separated from other params_* keys grouped at lines 6-39. For maintainability, place this key near related line-style parameters (after params_line_style_dotted around line 13), matching the placement in en.json.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@project.inlang/messages/es.json` at line 170, Move the
"params_dotted_end_radius" translation so it is grouped with other params_* keys
(specifically place it after "params_line_style_dotted") instead of at the file
end; locate the key "params_dotted_end_radius" in
project.inlang/messages/es.json and cut/paste it into the block where the other
params_* entries (e.g., "params_line_style_dotted") are defined, matching the
order used in en.json for consistency.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/worktrees/svelte5-migrate:
- Line 1: Remove the accidental Claude worktree pointer and lock from the PR and
add them to .gitignore: delete the tracked artifact(s) by staging a removal from
Git's index (e.g., git rm --cached .claude/worktrees/svelte5-migrate and git rm
--cached .claude/scheduled_tasks.lock) and commit that removal; then update
.gitignore to include either ".claude/" (preferred) or at minimum
".claude/worktrees/" and ".claude/scheduled_tasks.lock" and commit the
.gitignore change so future CLAUDE artifacts are ignored.

---

Nitpick comments:
In `@project.inlang/messages/ain.json`:
- Line 167: Move the "params_dotted_end_radius" entry from its current trailing
position into the params group near other connector-line keys: locate
"params_line_style_dotted" and insert "params_dotted_end_radius" directly after
that key (so it sits with other params_* keys), ensuring JSON ordering and
commas remain valid and no duplicate keys are introduced; update surrounding
commas if needed and keep the translation string unchanged.

In `@project.inlang/messages/ar.json`:
- Line 170: Move the "params_dotted_end_radius" key so it sits with the other
params_* line-style keys (near "params_line_style_dotted" and related entries)
instead of at the end of the file; locate the "params_dotted_end_radius" entry
and cut/paste it into the block containing "params_line_style_dotted" (and other
params_ keys) to keep semantic grouping consistent.

In `@project.inlang/messages/bn.json`:
- Line 170: Move the translation key "params_dotted_end_radius" next to the
other params_* keys (specifically after "params_line_style_dotted") so all
line-style/params keys are grouped together; update the JSON ordering by cutting
the "params_dotted_end_radius" entry from its current end-of-file location and
inserting it immediately after "params_line_style_dotted" to keep semantic
grouping and consistency.

In `@project.inlang/messages/de.json`:
- Line 170: Move the "params_dotted_end_radius" translation key so it is grouped
with other line-style parameters: locate "params_line_style_dotted" and insert
"params_dotted_end_radius": "Punktradius" directly after it (or within that
contiguous params_* block) to keep all line-style keys together and maintain
consistency.

In `@project.inlang/messages/es.json`:
- Line 170: Move the "params_dotted_end_radius" translation so it is grouped
with other params_* keys (specifically place it after
"params_line_style_dotted") instead of at the file end; locate the key
"params_dotted_end_radius" in project.inlang/messages/es.json and cut/paste it
into the block where the other params_* entries (e.g.,
"params_line_style_dotted") are defined, matching the order used in en.json for
consistency.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9aa1dfb4-71d2-43e0-8bd9-194f14946a9c

📥 Commits

Reviewing files that changed from the base of the PR and between 673a268 and 20ef9ba.

⛔ Files ignored due to path filters (1)
  • .claude/scheduled_tasks.lock is excluded by !**/*.lock
📒 Files selected for processing (38)
  • .claude/worktrees/svelte5-migrate
  • project.inlang/messages/ain.json
  • project.inlang/messages/ar.json
  • project.inlang/messages/bg.json
  • project.inlang/messages/bn.json
  • project.inlang/messages/de.json
  • project.inlang/messages/en.json
  • project.inlang/messages/eo.json
  • project.inlang/messages/es.json
  • project.inlang/messages/fa.json
  • project.inlang/messages/fi.json
  • project.inlang/messages/fr.json
  • project.inlang/messages/grc.json
  • project.inlang/messages/hi.json
  • project.inlang/messages/ia.json
  • project.inlang/messages/id.json
  • project.inlang/messages/it.json
  • project.inlang/messages/ja-Hira.json
  • project.inlang/messages/ja.json
  • project.inlang/messages/ko-Kore.json
  • project.inlang/messages/ko.json
  • project.inlang/messages/la.json
  • project.inlang/messages/nl.json
  • project.inlang/messages/pl.json
  • project.inlang/messages/pt.json
  • project.inlang/messages/ru.json
  • project.inlang/messages/th.json
  • project.inlang/messages/tok.json
  • project.inlang/messages/tr.json
  • project.inlang/messages/uk.json
  • project.inlang/messages/vi.json
  • project.inlang/messages/zh-HanS.json
  • project.inlang/messages/zh-HanT.json
  • src/i18n/i18n-svelte.ts
  • src/lib/Output.svelte
  • src/lib/Parameters.svelte
  • src/lib/persisted-params.ts
  • src/routes/+page.svelte
✅ Files skipped from review due to trivial changes (9)
  • project.inlang/messages/ko-Kore.json
  • project.inlang/messages/eo.json
  • project.inlang/messages/ja.json
  • project.inlang/messages/ja-Hira.json
  • project.inlang/messages/fi.json
  • project.inlang/messages/ia.json
  • project.inlang/messages/nl.json
  • project.inlang/messages/pl.json
  • project.inlang/messages/id.json
🚧 Files skipped from review as they are similar to previous changes (10)
  • project.inlang/messages/bg.json
  • project.inlang/messages/fa.json
  • project.inlang/messages/la.json
  • project.inlang/messages/hi.json
  • project.inlang/messages/zh-HanT.json
  • project.inlang/messages/pt.json
  • project.inlang/messages/th.json
  • src/lib/Parameters.svelte
  • src/routes/+page.svelte
  • src/lib/Output.svelte

@@ -0,0 +1 @@
Subproject commit c2c954a4248627977c35e61cde74fe85ebd50822

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check tracking status and gitignore coverage for the Claude worktree path.
git ls-files .claude | head -50
echo "--- gitignore entries mentioning .claude ---"
rg -n '\.claude' .gitignore 2>/dev/null || echo "no .claude entry in .gitignore"

Repository: mkpoli/word-order

Length of output: 200


🏁 Script executed:

#!/bin/bash
set -euo pipefail

commit="c2c954a4248627977c35e61cde74fe85ebd50822"

echo "=== git show (summary + changed files) for $commit ==="
git show --no-patch --pretty=format:'%h %s' --name-only "$commit" | sed -n '1,120p'

echo
echo "=== current .gitignore contents mentioning .claude ==="
if [ -f .gitignore ]; then
  rg -n '\.claude' .gitignore || echo "no .claude entry in .gitignore"
  echo "--- .gitignore (first 200 lines) ---"
  sed -n '1,200p' .gitignore
else
  echo ".gitignore not found at repo root"
fi

echo
echo "=== whether .claude/worktrees is ignored/covered ==="
git check-ignore -v .claude/worktrees/svelte5-migrate || true

Repository: mkpoli/word-order

Length of output: 260


🏁 Script executed:

#!/bin/bash
set -euo pipefail

commit="c2c954a4248627977c35e61cde74fe85ebd50822"

echo "=== git show (commit subject) ==="
git show -s --pretty=format:'%h %s' "$commit"

echo
echo "=== files changed in commit (name-only) ==="
git diff-tree --no-commit-id --name-only -r "$commit" | sed -n '1,200p'

echo
echo "=== is .claude tracked? ==="
git ls-files .claude | sed -n '1,200p'
echo
echo "=== specifically tracked: .claude/worktrees/svelte5-migrate ==="
git ls-files .claude/worktrees/svelte5-migrate || echo "not tracked"

echo
echo "=== whether .claude/worktrees is ignored/covered ==="
if [ -f .gitignore ]; then
  rg -n '\.claude' .gitignore || echo "no .claude entry in .gitignore"
  echo "--- .gitignore (first 200 lines) ---"
  sed -n '1,200p' .gitignore
else
  echo ".gitignore not found at repo root"
fi

echo
git check-ignore -v .claude/worktrees/svelte5-migrate || true

Repository: mkpoli/word-order

Length of output: 646


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== current content of .claude/worktrees/svelte5-migrate (first 200 lines) ==="
sed -n '1,200p' .claude/worktrees/svelte5-migrate

commit="c2c954a4248627977c35e61cde74fe85ebd50822"

echo
echo "=== how commit $commit affected .claude/worktrees/svelte5-migrate ==="
git show "$commit" -- .claude/worktrees/svelte5-migrate | sed -n '1,200p'

echo
echo "=== is any .claude file added/modified in commit $commit (limited to .claude paths) ==="
git diff-tree --no-commit-id -r --name-only "$commit" | rg '^\.claude/' || true

Repository: mkpoli/word-order

Length of output: 227


🏁 Script executed:

#!/bin/bash
set -euo pipefail

commit="c2c954a4248627977c35e61cde74fe85ebd50822"

echo "=== repo path type ==="
ls -ld .claude .claude/worktrees .claude/worktrees/svelte5-migrate || true

echo
echo "=== git ls-tree for that path at HEAD ==="
git ls-tree -r --name-only HEAD .claude/worktrees/svelte5-migrate || echo "none at HEAD"

echo
echo "=== git ls-files entry (mode/path) ==="
git ls-files -s .claude/worktrees/svelte5-migrate || echo "not listed as tracked file"

echo
echo "=== is it tracked as a directory? list tracked entries under it (limited) ==="
git ls-files .claude/worktrees/svelte5-migrate | head -50

echo
echo "=== show what the merge commit actually changed (stat + names, limited) ==="
git show --stat --oneline "$commit" | sed -n '1,120p'
echo
git show --name-only --pretty=format:'%h %s' "$commit" | sed -n '1,200p'

Repository: mkpoli/word-order

Length of output: 1875


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== git log for .claude/worktrees/svelte5-migrate (most recent) ==="
git log -n 5 --oneline -- .claude/worktrees/svelte5-migrate

echo
echo "=== git log for .claude/scheduled_tasks.lock (most recent) ==="
git log -n 5 --oneline -- .claude/scheduled_tasks.lock

echo
echo "=== show diff summary for the specific commit c2c954... affecting .claude paths ==="
commit="c2c954a4248627977c35e61cde74fe85ebd50822"
git show --name-status --pretty=format:'%h %s' "$commit" -- .claude 2>/dev/null || true

Repository: mkpoli/word-order

Length of output: 412


Likely accidental: committed Claude worktree artifact (.claude/worktrees/svelte5-migrate)

  • .claude/worktrees/svelte5-migrate is tracked and points to c2c954a (“Merge remote-tracking branch 'origin/master' into svelte5-migrate”), pulling in unrelated app changes (e.g., src/routes/+layout.svelte, src/routes/+page.svelte, src/lib/ui/RangeSlider.svelte, multiple src/lib/*.svelte).
  • .gitignore has no .claude entry, so these artifacts aren’t being ignored (also .claude/scheduled_tasks.lock is tracked).

Drop the .claude/ worktree pointer(s) from this PR and add .claude/ (or at least .claude/worktrees/ + .claude/scheduled_tasks.lock) to .gitignore.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/worktrees/svelte5-migrate at line 1, Remove the accidental Claude
worktree pointer and lock from the PR and add them to .gitignore: delete the
tracked artifact(s) by staging a removal from Git's index (e.g., git rm --cached
.claude/worktrees/svelte5-migrate and git rm --cached
.claude/scheduled_tasks.lock) and commit that removal; then update .gitignore to
include either ".claude/" (preferred) or at minimum ".claude/worktrees/" and
".claude/scheduled_tasks.lock" and commit the .gitignore change so future CLAUDE
artifacts are ignored.

@mkpoli
mkpoli merged commit 8544732 into master May 31, 2026
5 checks passed
mkpoli added a commit that referenced this pull request Jun 14, 2026
master replaced the line-halo connector style with dottedEndRadius (#128),
removing lineHalo/lineHaloWidth from ParamsSnapshot and Parameters' Props.
This branch's +page.svelte still wired those props, so svelte-check failed in
CI. Swap the stored-snapshot reads, the params object, and the Output/
Parameters bindings over to dottedEndRadius.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mkpoli added a commit that referenced this pull request Jun 14, 2026
…125)

* fix(export): fall back to raster PDF for non-Latin scripts

#109 routed every PDF through svg2pdf, which can only embed the 14
standard PDF fonts (Helvetica / Times / Courier). Those have no glyphs
for CJK / Cyrillic / Greek / Arabic / Devanagari / Hebrew, so non-Latin
diagrams came out as mojibake.

Add pdfNeedsRaster() that scans tokens, annotations, and displayName
overrides for any character outside the Latin / Latin-extended /
diacritic / general-punctuation whitelist. When detected, fall back
to the pre-#109 raster path (domToImage + addImage). Pure-Latin docs
keep the vector path — text stays selectable, lines stay crisp.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(lint): swap pdfNeedsRaster regex for codePointAt loop

The Unicode-range regex tripped no-control-regex /
no-misleading-character-class / no-irregular-whitespace under eslint.
Same logic via per-character codePointAt is clearer anyway and avoids
the linter rules entirely.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(export): include language label in raster fallback check

pdfNeedsRaster() only inspected s.displayName, but the exported header
falls back to getLanguageName(lang, locale) when displayName is unset.
A Latin-only sentence labelled "ja" still renders 日本語 in the header
under a Japanese UI locale, so the vector branch was producing mojibake
on those labels.

Compute the rendered label (displayName ?? getLanguageName(...)) and run
isLatinScript on that — picked up from CodeRabbit feedback on #125.

* fix(export): vector PDF with embedded fonts, drop raster fallback

Previously the PDF export fell back to a raster-PNG-in-PDF whenever the
diagram contained any non-Latin character, because jsPDF only ships the
14 standard PDF fonts and svg2pdf has no way to read @font-face from
the input SVG. That meant text wasn't selectable and the output lost
the vector crispness of the on-screen preview.

Replace that with an on-demand font-embedding pipeline:

- src/app.html pins the diagram's CSS font stack to Noto Sans / Serif /
  Mono + their CJK SC/JP/KR variants via Google Fonts, so the on-screen
  preview already loads the same families we'll embed.
- src/lib/Output.svelte's .serif / .sans-serif / .monospace / output
  font-family rules name the Noto variants explicitly.
- src/lib/pdf-fonts.ts walks the SVG produced by elementToSVG, detects
  the dominant script of each <text> run, fetches a Google Fonts
  ?text= subsetted woff2 (just the glyphs the diagram actually uses),
  decodes woff2 → TTF in-browser via wawoff2, and registers each subset
  with the jsPDF instance via addFileToVFS + addFont. The <text>
  font-family is rewritten to the specific Noto name so svg2pdf binds
  to the registered font directly.
- src/routes/+page.svelte's exportPdf calls registerSvgFonts before
  svg2pdf, and the isLatinScript / pdfNeedsRaster gate + dom-to-image
  raster branch are gone. Module-level cache means consecutive exports
  of the same diagram don't re-fetch.

Net result: CJK / Cyrillic / Greek / Arabic / etc. text in the PDF is
now real vector text (selectable, copy-pasteable, crisp at any zoom)
that renders with the exact same glyph outlines as the preview.

* fix(params): use dottedEndRadius after line-halo removal

master replaced the line-halo connector style with dottedEndRadius (#128),
removing lineHalo/lineHaloWidth from ParamsSnapshot and Parameters' Props.
This branch's +page.svelte still wired those props, so svelte-check failed in
CI. Swap the stored-snapshot reads, the params object, and the Output/
Parameters bindings over to dottedEndRadius.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
mkpoli added a commit that referenced this pull request Jun 27, 2026
Match the dotted-end control to its sibling parameters: use the shared
<RangeSlider> with a " px" suffix instead of a bare <input type="range">, so
it looks and behaves like Line Width / Space Width etc.

i18n: the control had only an en-only orphan pair (params_dotted_end +
params_dotted_end_on, the latter unused since the checkbox was removed).
Replace them with a single accurate params_dotted_end_radius ("Dot radius")
and translate it into every locale, grounded in each locale's vocab
(ja 点の半径, ja-Hira てんの おおきさ, ko 점 반지름, ko-Kore 點 반지름,
zh-HanS 圆点半径, ain Noka poro hi, …). Drop the dottedEnd/dottedEndOn
accessors and wire dottedEndRadius in i18n-svelte.
mkpoli added a commit that referenced this pull request Jun 27, 2026
The dotted-end RangeSlider had no step (defaulting to 1), so it jumped a whole
pixel at a time. Match the fine-grained siblings (line-width, letter-spacing,
curvature) with step={0.1} for smooth dragging.
mkpoli added a commit that referenced this pull request Jun 27, 2026
Per request, render the dot as ain "sinkop" → "Sinkop poro hi" (dot size)
instead of the generic "Noka" (image).
mkpoli added a commit that referenced this pull request Jun 27, 2026
master replaced the line-halo connector style with dottedEndRadius (#128),
removing lineHalo/lineHaloWidth from ParamsSnapshot and Parameters' Props.
This branch's +page.svelte still wired those props, so svelte-check failed in
CI. Swap the stored-snapshot reads, the params object, and the Output/
Parameters bindings over to dottedEndRadius.

This branch was successfully deployed

1 active deployment
Preview — 20ef9ba8 Deployed May 31, 2026 by vercel[bot]
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