# @humanspeak/svelte-diff — full reference > Concatenated dump of every doc page under https://diff.svelte.page/docs. > Each section is bounded by an HTML comment with the source URL, > so agents can extract individual pages or cite a specific section. --- ## Install ```bash npm install @humanspeak/svelte-diff ``` `@humanspeak/svelte-diff` is the Svelte 5 component package. It accepts `originalText` and `modifiedText`, computes a diff reactively, and renders removed, inserted, equal, and expected segments. Use this library when the desired result is a rendered text diff inside a Svelte application. Use a lower-level algorithm library when you need patch creation, patch application, non-UI diff data, or non-Svelte runtimes. ## Minimal example ```svelte ``` ## Important behavior - In character mode, `cleanupSemantic` improves readability and takes precedence over efficiency cleanup. - In character mode, `cleanupEfficiency` defaults to `4`; set it to `0` to skip efficiency cleanup. - Expected patterns use named capture groups such as `(?\\d{4})` inside `originalText`. - Child snippets override the corresponding `renderers` entry, which overrides built-in markup. - `onProcessing` receives timing, raw diff tuples, and optional expected-pattern captures. ## Comparison granularity `diffMode?: SvelteDiffMode` accepts `'character' | 'word' | 'line'`; character is the default. Word and line modes skip both cleanup passes. Word mode preserves Unicode letter/mark/number/underscore runs, whitespace, and punctuation with deterministic case-sensitive tokens; it is not locale-aware, CJK runs stay whole, and emoji grapheme clusters may split. Line mode preserves original LF/CRLF/lone-CR endings, blank lines, indentation, and final-newline differences. JSON is plain text; sentence and structural JSON modes are unsupported. Expected captures resolve before tokenization. Raw tuples reconstruct resolved/cleaned source and exact modified text. Display annotations and line-break renderers can split tokens; deleted captured values remain in replaced lines. Mode changes recompute; callback-only changes reuse tuple identity; initial output supports SSR. Token timing `main` includes preparation/encoding/diff/decoding; `cleanup` is zero. Timings exclude extraction and rendering. One best-effort timeout in seconds covers token work (0 unlimited). Expiry or more than 65,535 distinct tokens across both inputs may return a complete replacement. No workers or virtualization are provided. - [Diff modes](https://diff.svelte.page/docs/guides/diff-modes) - [Word example](https://diff.svelte.page/examples/word-diff) - [Line example](https://diff.svelte.page/examples/line-diff) --- # CodeDiff > Props, semantics, themes, and optional imports for CodeDiff. **Source:** [https://diff.svelte.page/docs/api/code-diff](https://diff.svelte.page/docs/api/code-diff) --- The optional Svelte entry exports the same component as default and named `CodeDiff`, plus the public `CodeDiffProps` type: ```typescript import CodeDiff, { CodeDiff as NamedCodeDiff, type CodeDiffProps } from '@humanspeak/svelte-diff/code' ``` Install `@tanstack/highlight@1.0.0` when using this entry. The ordinary package root does not re-export CodeDiff or load TanStack at runtime. | Prop | Type | Default | Behavior | | ------------------- | -------------------------------------- | -------------------- | ----------------------------------------------- | | `originalText` | `string` | required | Complete literal original source | | `modifiedText` | `string` | required | Complete literal modified source | | `highlighter` | `Pick` | required | Caller-created complete-source tokenizer | | `language` | `string` | `'plaintext'` | Registered language name or alias | | `diffMode` | `'character' \| 'word' \| 'line'` | `'word'` | Raw comparison unit | | `timeout` | `number` | `1` | Diff deadline in seconds; 0 unlimited | | `cleanupSemantic` | `boolean` | `false` | Character-mode semantic cleanup | | `cleanupEfficiency` | `number` | `0` | Character-mode efficiency edit cost; 0 disables | | `class` | `string` | `''` | Additional outer `pre` classes | | `ariaLabel` | `string` | `'Code differences'` | Accessible overflow-region name | | `rendererClasses` | `{ remove?: string; insert?: string }` | `{}` | Additional `del`/`ins` classes | ```svelte {themeCss} ``` `Highlighter` is imported as a type from `@tanstack/highlight/core`. Register individual languages yourself; no all-language root import is needed. Both complete sources are tokenized before diff composition. Removed runs use original tokens; equal and inserted runs use modified tokens. The single `pre.th-code.svelte-code-diff` contains `code`, operation wrappers with `data-diff="remove|insert|equal"`, and syntax spans with `th-*` classes. Text is natively escaped by Svelte. Change backgrounds default to translucent red/green through `--svelte-diff-remove-bg` / `--svelte-diff-insert-bg`. Syntax foreground belongs to caller theme CSS, and default changed text has no strike-through. The block uses `white-space: pre` and keyboard-accessible overflow. Expected patterns are always false and are not a prop. There are no callbacks, custom snippets, patch inputs, gutters, or headless API in this entry. Cleanup applies only to character mode. Work remains synchronous and preserves model source code units; browser SSR parsing can normalize CR/CRLF. See the [code diffs guide](/docs/guides/code-diffs) for caching, themes, and limits. # SvelteDiff API > Complete SvelteDiff component API including props, renderer precedence, callbacks, and defaults. **Source:** [https://diff.svelte.page/docs/api/svelte-diff](https://diff.svelte.page/docs/api/svelte-diff) --- The package exports the component as both the default export and a named export. ```svelte ``` ## Props | Prop | Type | Default | Purpose | |---|---|---:|---| | `originalText` | `string` | required | The before/source text | | `modifiedText` | `string` | required | The after/target text | | `diffMode` | `SvelteDiffMode` | `'character'` | `'character'`, `'word'`, or `'line'`; word/line skip cleanup | | `expectedPatterns` | `boolean` | `true` | Enable named capture templates; `false` compares exact literal source without parsing | | `timeout` | `number` | `1` | Maximum diff computation time in seconds; `0` is unlimited | | `cleanupSemantic` | `boolean` | `false` | Character only: optimize edit boundaries for human readability | | `cleanupEfficiency` | `number` | `4` | Character-only edit cost for efficiency cleanup; `0` disables it | | `compact` | `boolean` | `true` | Render unstyled equal text without wrapper spans; `false` restores legacy equal spans | | `onProcessing` | `function` | — | Receive timing, raw tuples, and optional captures | | `rendererClasses` | `RendererClasses` | `{}` | Classes for built-in segment spans | | `renderers` | `Partial` | `{}` | Snippet map for individual segment types | | `remove` | `Snippet<[string]>` | — | Direct child snippet for removed text | | `insert` | `Snippet<[string]>` | — | Direct child snippet for inserted text | | `equal` | `Snippet<[string]>` | — | Direct child snippet for unchanged text | | `expected` | `Snippet<[string, string]>` | — | Direct child snippet for expected values | | `lineBreak` | `Snippet<[]>` | — | Direct child snippet between lines | ## Cleanup precedence In character mode, the component computes a raw diff, then runs at most one cleanup pass: 1. If `cleanupSemantic` is `true`, semantic cleanup runs. 2. Otherwise, if `cleanupEfficiency > 0`, efficiency cleanup runs with that value as the edit cost. 3. Otherwise, the raw diff is rendered. ## Renderer precedence Resolution happens independently for every segment type: 1. A direct child snippet such as `{#snippet insert(text)}` 2. The matching property in `renderers` 3. The built-in fallback For unchanged text, the default compact fallback emits text directly when no equal class or renderer is configured. Set `compact={false}` to restore the legacy equal ``. Removed, inserted, expected, and customized equal segments retain their normal elements. That means you can override one type and leave all others on their defaults. ```svelte {#snippet insert(text: string)} + {text} {/snippet} ``` ## `onProcessing` The callback runs after computation and cleanup. ```svelte ``` Timing values are milliseconds measured with `performance.now()`. ## Literal source `expectedPatterns` defaults to `true` on the component. Set it to `false` when comparing source containing named regex groups: ```svelte ``` Literal mode bypasses parsing, substitution, mismatch placeholders, and capture tagging. Raw tuples reconstruct both exact input strings. Changing this prop recomputes the comparison and clears stale capture metadata. Initial literal markup is rendered during SSR; callbacks remain client-only. The synchronous `computeDiff` helper defaults to `expectedPatterns: false`. Its other defaults match the component. See [Types and Exports](/docs/api/types) for its options and result within a Svelte-aware toolchain. ## Expected patterns If `originalText` contains named capture groups, the component tries to match those regions in `modifiedText` and renders successful matches as `expected` instead of additions/removals. ```svelte v\\d+\\.\\d+\\.\\d+)'} modifiedText="Release v2.4.1" /> ``` The group name is passed to the expected snippet and its matched value appears in the callback's `captures` object. ## Deprecated aliases `SvelteDiffMatchPatch` and the `SvelteDiffMatchPatch*` type names remain available for compatibility. New code should use `SvelteDiff` and the shorter `SvelteDiff*` types. ## Mode and capture semantics `diffMode` defaults to `character`; `word` and `line` skip both cleanup passes regardless of their props. `timing.cleanup` is exactly zero in token modes. See [Diff Modes](/docs/guides/diff-modes) for token rules, Unicode limitations, and complete examples. Capture extraction still precedes tokenization. Raw callback tuples reconstruct the resolved source (or cleaned placeholders on mismatch), and the exact modified text. Capture tagging may split displayed tokens, and newline rendering may split a tuple across snippet calls. For `Release (?v\\d+)` and `Release v2 ready`, line mode removes `Release v2`, inserts the full actual line, and annotates `v2` on the target side. The deleted captured value remains visible. Mode changes recompute immediately; callback-only changes reuse the tuple array. Computation runs during SSR and callback delivery runs on the client. The token deadline includes preparation and decoding; timeout or more than 65,535 distinct tokens can return a full replacement. See [performance](/docs/guides/performance). # Types and Exports > Public components, callbacks, renderer maps, tuples, and expected-pattern types exported by @humanspeak/svelte-diff. **Source:** [https://diff.svelte.page/docs/api/types](https://diff.svelte.page/docs/api/types) --- # Types & Exports The text-diff API is exported from the package root. Optional syntax-highlighted code diffs use the separate `@humanspeak/svelte-diff/code` entry. ```typescript import SvelteDiff, { SvelteDiff as NamedSvelteDiff, computeDiff, type SvelteDiffComputeOptions, type SvelteDiffResult, type SvelteDiffProps, type SvelteDiffMode, type SvelteDiffTiming, type SvelteDiffTuple, type Renderers, type RendererClasses, type CaptureRange, type DisplayDiff, type PatternMatchResult } from '@humanspeak/svelte-diff' ``` ## Components | Export | Notes | | ---------------------- | ---------------------------------- | | `default` | The `SvelteDiff` component | | `SvelteDiff` | Named export of the same component | | `SvelteDiffMatchPatch` | Deprecated compatibility alias | ## Optional code entry ```typescript import CodeDiff, { CodeDiff as NamedCodeDiff, type CodeDiffProps } from '@humanspeak/svelte-diff/code' ``` The exported `CodeDiffProps` type has the following shape: ```typescript import type { SvelteDiffMode } from '@humanspeak/svelte-diff' import type { Highlighter } from '@tanstack/highlight/core' interface CodeDiffProps { originalText: string modifiedText: string highlighter: Pick language?: string diffMode?: SvelteDiffMode timeout?: number cleanupSemantic?: boolean cleanupEfficiency?: number class?: string ariaLabel?: string rendererClasses?: { remove?: string; insert?: string } } ``` CodeDiff defaults to word mode, plaintext, timeout 1, semantic cleanup false, and efficiency 0. `ariaLabel` defaults to Code differences. Source is always literal. The root does not re-export this component or load optional TanStack at runtime. See the [CodeDiff API](/docs/api/code-diff) and [guide](/docs/guides/code-diffs). ## `SvelteDiffMode` ```typescript type SvelteDiffMode = 'character' | 'word' | 'line' ``` `SvelteDiffProps.diffMode` is optional and defaults to `character`. Deprecated prop aliases inherit it. Sentence and JSON are not accepted. See [Diff Modes](/docs/guides/diff-modes). ## `computeDiff`, `SvelteDiffComputeOptions`, and `SvelteDiffResult` Use the helper through the Svelte-aware package root within a Svelte toolchain; the entry requires Svelte-aware module resolution and compilation. Each call owns its engine and returns synchronously without mounting a component. ```typescript interface SvelteDiffComputeOptions { diffMode?: SvelteDiffMode timeout?: number cleanupSemantic?: boolean cleanupEfficiency?: number expectedPatterns?: boolean } interface SvelteDiffResult { timing: SvelteDiffTiming diffs: SvelteDiffTuple[] displayDiffs: DisplayDiff[] captures?: Record } const result: SvelteDiffResult = computeDiff(before, after, { diffMode: 'line' }) ``` Helper defaults are character mode, timeout 1 second, semantic cleanup false, efficiency edit cost 4, and **expectedPatterns false**. The component defaults expectedPatterns to **true**. Explicit true uses the same template resolution, mismatch placeholders, and capture tagging as the component. False bypasses parsing entirely: omitting inserts reconstructs the exact original input; omitting removals reconstructs the exact modified input. Captures are undefined and display segments have no expected tags. Semantic cleanup takes priority over efficiency in character mode; word/line skip both. ## `SvelteDiffTiming` ```typescript type SvelteDiffTiming = { main: number cleanup: number total: number } ``` All values are milliseconds. For character mode, `main` measures the core algorithm and `cleanup` measures the selected cleanup pass. For word/line, `main` includes tokenization, encoding, diffing, and decoding; `cleanup` is exactly zero. `total` covers the timed computation, excluding expected-pattern preprocessing and DOM rendering. ## `SvelteDiffTuple` Tuples always contain original text, never encoded IDs. With expected patterns, the source projection is resolved/cleaned source. Capture annotations can split displayed tokens without changing raw tuples. An alias for `Diff` from `diff-match-patch-ts`. Each tuple is an operation and its text: ```typescript type SvelteDiffTuple = [operation: -1 | 0 | 1, text: string] ``` - `-1` — removed - `0` — equal - `1` — inserted ## `Renderers` ```typescript type Renderers = { remove?: Snippet<[string]> equal?: Snippet<[string]> insert?: Snippet<[string]> expected?: Snippet<[string, string]> lineBreak?: Snippet<[]> } ``` The expected renderer receives both the matched text and its named capture-group name. ## `RendererClasses` ```typescript type RendererClasses = { remove?: string equal?: string insert?: string expected?: string } ``` Classes only affect built-in fallbacks. When you replace a segment with a snippet, that snippet owns its own classes. ## Expected-pattern types `CaptureRange` describes a named match inside the modified string. `DisplayDiff` is an internal-rendering-shaped segment that may carry an `expected` group name. `PatternMatchResult` combines resolved template text, captured values, and capture ranges. ```typescript interface PatternMatchResult { resolvedText: string captures: Record captureRanges: CaptureRange[] } ``` These are exported for integrations that want to share the component's expected-region concepts without duplicating type definitions. # Getting Started > Install @humanspeak/svelte-diff and render a readable, reactive text diff in Svelte 5. **Source:** [https://diff.svelte.page/docs/getting-started](https://diff.svelte.page/docs/getting-started) --- `@humanspeak/svelte-diff` is a focused Svelte 5 component for comparing two strings. It runs the diff-match-patch algorithm, optionally cleans the result for readability, and renders each change as real Svelte markup. ## Installation ```bash npm install @humanspeak/svelte-diff ``` ```bash pnpm add @humanspeak/svelte-diff ``` ## Compare two strings in Svelte To build an inline Svelte diff viewer, pass the original and modified strings to `SvelteDiff`. Enable `cleanupSemantic` to make edits in prose easier to read: ```svelte

``` By default, removed text is red with a strike-through, inserted text is green, and unchanged text is unstyled. Unstyled unchanged text uses compact DOM without wrapper spans; pass `compact={false}` when migrating selectors or styles that require the legacy equal spans. Text is escaped by Svelte; the component does not inject an HTML string. Try the [live diff viewer](/#compare-two-strings) or the [basic diff example](/examples/basic-diff). For dates, versions, and generated IDs that are supposed to change, use [expected patterns](/docs/guides/expected-patterns) to label those values separately. ## Reactive inputs Both required props are reactive. If either string changes, the component recomputes the diff. ```svelte ``` ## Recommended readable defaults For prose and user-facing copy, semantic cleanup is usually the best starting point: ```svelte ``` For machine-like strings where every small edit matters, keep semantic cleanup off and use the default efficiency cleanup. ## Styling with classes Use `rendererClasses` when you want to keep the default `` markup: ```svelte ``` Use child snippets when you need different elements, attributes, icons, or animation. See [Custom Rendering](/docs/guides/custom-rendering). ## Choosing a diff tool - [Svelte Diff vs jsdiff](/compare/vs-jsdiff) — choose a rendered Svelte component or a JavaScript library that returns diff data, including word and line modes. - [Svelte Diff vs diff-match-patch](/compare/vs-diff-match-patch) — compare the underlying algorithm library with its reactive Svelte component integration. - [Svelte Diff vs diff2html](/compare/vs-diff2html) — choose inline string comparison or a git-patch viewer with side-by-side files. ## Next steps - [SvelteDiff API](/docs/api/svelte-diff) — every prop and precedence rule - [Expected Patterns](/docs/guides/expected-patterns) — separate intentional variation from real changes - [Cleanup Modes](/docs/guides/cleanup) — choose semantic, efficiency, or raw output - [Interactive Examples](/examples) — edit values and inspect real output - [Comparisons](/compare) — decide between this component and lower-level diff tools ## Choose a comparison unit Character is the default and retains the existing cleanup behavior. Use `diffMode="word"` for complete changed words or `diffMode="line"` for complete changed lines. Both token modes skip cleanup. ```svelte ``` Read the [mode guide](/docs/guides/diff-modes), edit the [word example](/examples/word-diff), or try the [line example](/examples/line-diff). JSON input remains plain text; sentence and structural JSON modes are unsupported. # Cleanup Modes > Choose semantic cleanup, efficiency cleanup, or raw diff output for the right balance of readability and fidelity. **Source:** [https://diff.svelte.page/docs/guides/cleanup](https://diff.svelte.page/docs/guides/cleanup) --- Cleanup options apply only to the default `diffMode="character"`. Word and line modes skip both passes and report zero cleanup time. Granularity chooses comparison units; cleanup reorganizes character edits. See [Diff Modes](/docs/guides/diff-modes). The core algorithm finds a valid sequence of edits. Cleanup passes reorganize that sequence without changing the final text. ## Semantic cleanup ```svelte ``` Semantic cleanup shifts edit boundaries toward natural-looking word and phrase boundaries. Use it for prose, review screens, changelogs, and other output read by people. It may produce a slightly larger edit than the mathematically smallest diff if that edit is easier to understand. ## Efficiency cleanup ```svelte ``` Efficiency cleanup removes operationally trivial equalities. The number becomes the algorithm's edit-cost setting. `4` is the component default. Higher values make small equal regions more likely to be absorbed into surrounding edits. Lower values preserve more fine-grained equalities. ## Raw output Disable both cleanup paths when exact algorithm output matters: ```svelte ``` ## Character-mode precedence Semantic cleanup wins when enabled. The component does not run semantic and efficiency cleanup in sequence. | Configuration | Cleanup pass | |---|---| | `cleanupSemantic={true}` | semantic | | `cleanupSemantic={false}`, `cleanupEfficiency={4}` | efficiency | | `cleanupSemantic={false}`, `cleanupEfficiency={0}` | none | ## Choosing character-mode cleanup - Use **semantic** for prose and human review. - Use **efficiency** for compact technical diffs and a balanced default. - Use **raw** when consuming the rendered segmentation as a debugging aid or comparing it with another diff implementation. Open the [cleanup modes example](/examples/cleanup-modes) to see all three render the same input side by side. # Code Diffs > Compare literal source with optional whole-source syntax highlighting. **Source:** [https://diff.svelte.page/docs/guides/code-diffs](https://diff.svelte.page/docs/guides/code-diffs) --- Install the optional syntax highlighter alongside the Svelte package: ```sh pnpm add @humanspeak/svelte-diff @tanstack/highlight@1.0.0 ``` Import `CodeDiff` from `@humanspeak/svelte-diff/code`. Ordinary text-diff consumers can keep importing the root without installing TanStack. Create your own highlighter using individual language entries; register only what you use. ```svelte {themeCss} ``` The theme helper supplies syntax colors. Its default dark selector is `.dark`; toggle that class on an ancestor. For multiple independently themed blocks, use scoped `lightSelector` / `darkSelector`, `includeBaseStyles: false`, and scope the `th-*` color rules as in the [editable example](/examples/code-diff). Theme generation belongs in the application, not the library component. ## Whole-source context Both complete sources are tokenized independently before their raw diff runs are composed. Deletions use original syntax; unchanged and inserted text use modified syntax. Editing the interior of a multiline comment or string therefore retains its classification. Repeated text is located using cumulative UTF-16 offsets, never substring searching. `CodeDiff` always compares literal source. Named regex groups such as `(?\d{4})` remain code, and HTML-like input is rendered as escaped text. It has no expected-pattern prop or capture parsing. Unknown or unregistered languages fall back to plain text with TanStack's default highlighter settings. ## Modes, styles, and access These examples explicitly use line mode to keep removed and inserted code lines together. The component default remains word; word and character modes are available for inline comparisons. Word mode is the default; character and line modes are also available. Character cleanup defaults to off, and word/line skip cleanup entirely. JSON is highlighted source, not parsed or compared structurally. Unicode offsets use UTF-16; emoji grapheme atomicity is not guaranteed. Read the [diff modes guide](/docs/guides/diff-modes) for comparison units and deadline fallbacks. The output is one focusable, named `pre`/`code` region with semantic `del` and `ins` wrappers. Native Svelte escaping preserves source text without HTML injection. Syntax spans use `th-*` classes. There is no default strike-through or library foreground color. Override `--svelte-diff-remove-bg` and `--svelte-diff-insert-bg` on the block or an ancestor for change backgrounds, or add `rendererClasses`. `ariaLabel` names the overflow region; operation attributes label changes without adding label text to the source body. Use keyboard arrow keys to scroll long lines. The model preserves tabs, CR, LF, CRLF, final newlines, and Unicode code units. The browser HTML parser may normalize CR/CRLF during SSR; DOM or clipboard round-tripping of raw line endings is not guaranteed. Inputs are never normalized before diffing or tokenization. ## Reactivity and limits Changing only the modified source reuses original tokens. Changing language or highlighter identity invalidates both token stages. Mode, timeout, and cleanup options invalidate only diff computation. Theme, class, and operation-class changes reuse both tokenizations and diff results. Caches belong to each instance. Computation and tokenization are synchronous. `timeout` governs the diff algorithm, not highlighting or DOM rendering. This viewer has no patch format, hunks, gutters, line numbers, side-by-side layout, folding, virtualization, workers, editor parsing, callbacks, or headless entry. See the [CodeDiff API](/docs/api/code-diff), [types](/docs/api/types), and [editable code example](/examples/code-diff) with copyable complete source. # Custom Rendering > Style SvelteDiff with semantic classes or replace individual diff segments with Svelte 5 snippets. **Source:** [https://diff.svelte.page/docs/guides/custom-rendering](https://diff.svelte.page/docs/guides/custom-rendering) --- SvelteDiff offers two customization levels. `rendererClasses` preserves the built-in markup and changes its classes. Snippets replace the markup itself. ## Class-based styling ```svelte ``` ```css :global(.change--removed) { background: #fee2e2; color: #991b1b; text-decoration: line-through; } :global(.change--inserted) { background: #dcfce7; color: #166534; } :global(.change--expected) { background: #dbeafe; border-bottom: 1px dashed #2563eb; } ``` The classes are applied only to the built-in `` for that segment. A missing class falls back to the component's inline default for removed, inserted, or expected text. ## Direct child snippets Use snippets when semantic HTML or richer UI matters: ```svelte {#snippet remove(text: string)} {text} {/snippet} {#snippet insert(text: string)} {text} {/snippet} {#snippet expected(text: string, groupName: string)} {text} {/snippet} {#snippet lineBreak()}
{/snippet}
``` ## Renderer maps Snippets can also be assembled into a `renderers` object. This is useful when a design system owns reusable diff renderers. ```svelte {#snippet removed(text: string)}{text}{/snippet} {#snippet inserted(text: string)}{text}{/snippet} ``` ## Mixing strategies Resolution is per type. A direct `insert` snippet can coexist with `renderers.remove`; equal text can still use the built-in fallback. ```svelte {#snippet insert(text: string)} {text} {/snippet} ``` The direct child snippet wins for `insert`. The renderer map is used for `remove`. Everything else falls back to built-in rendering. ## Line breaks The component splits multiline segments and calls `lineBreak` between lines. Override it when your output needs block separation, line numbers, or accessible separators. Keep `white-space: pre-wrap` on the surrounding output if preserving other whitespace matters. # Diff Modes > Choose character, word, or line comparison while preserving exact text, expected captures, and reactive Svelte rendering. **Source:** [https://diff.svelte.page/docs/guides/diff-modes](https://diff.svelte.page/docs/guides/diff-modes) --- `diffMode` chooses the comparison unit. The exported `SvelteDiffMode` type is `'character' | 'word' | 'line'`. Character remains the default. | Mode | Use case | Behavior | | --- | --- | --- | | `character` (default) | Fine-grained edits | Existing diff-match-patch algorithm and cleanup defaults | | `word` | Prose and identifiers | Whole word runs, separate whitespace and punctuation tokens | | `line` | Logs, configuration, source snapshots | Complete lines with their original terminators; no character refinement | ## Word comparison ```svelte ``` Raw tuples are `[[0, "The "], [-1, "cat"], [1, "car"], [0, " sleeps."]]`. Unlike raw character output, the changed word is removed and inserted whole. Word tokens are Unicode letter/mark/number/underscore runs, horizontal whitespace runs, CRLF pairs, lone CR or LF, and individual remaining punctuation/symbol code points. Spaces, tabs, NBSP, case, combining marks, and normalization form are preserved exactly. Apostrophes and hyphens separate runs. Comparison is case-sensitive and deterministic on the server and client; it does not use locale-aware segmentation. A continuous CJK letter run is one token. Emoji grapheme clusters are not guaranteed atomic. Lone surrogate code units are preserved. Try the editable [word example](/examples/word-diff). ## Line comparison ```svelte ``` Raw tuples are `[[-1, "count=10\n"], [1, "count=20\n"], [0, "keep=true\n"]]`. A line includes its LF, CRLF, or lone-CR terminator. Mixed endings, indentation, blank lines, and an unterminated final line are preserved. Adding or removing a final newline changes the affected line token. No secondary character refinement runs. JSON is plain source text: no parsing, key sorting, or canonicalization occurs. Sentence and structural JSON modes are deferred and unsupported. Try the [line example](/examples/line-diff), including its blank-line/final-newline preset. Line mode is a comparison unit, not a file/hunk or side-by-side renderer. ## Cleanup matrix | Mode | Cleanup behavior | | --- | --- | | Character with `cleanupSemantic={true}` | Semantic cleanup wins | | Character with semantic off and `cleanupEfficiency > 0` | Efficiency cleanup (default edit cost: 4) | | Character with semantic off and efficiency 0 | No cleanup | | Word or line, with any cleanup props | Both passes skipped; `timing.cleanup` is exactly 0 | Granularity and [cleanup](/docs/guides/cleanup) are separate choices. Semantic cleanup can make character output more readable, but does not promise whole-token boundaries. The public comparison panes disable character cleanup to show this difference clearly. ## Literal source and computation For source code, use `expectedPatterns={false}`. The component defaults to true; literal mode bypasses the parser and all template substitution and tagging. ```svelte ``` `computeDiff` defaults to expectedPatterns false and returns synchronously with raw `diffs`, tagged `displayDiffs`, optional `captures`, and millisecond `timing`. It uses the same modes, timeout, and cleanup defaults as the component and owns an engine per call. Use it within a Svelte-aware toolchain: the package root requires Svelte-aware module resolution and compilation. Set expectedPatterns true explicitly when computing templates. In literal mode, omit inserts to reconstruct the exact original input and omit removals to reconstruct the exact modified input, including all line endings, tabs, and Unicode code units. ## Expected patterns and renderers With expectedPatterns enabled, the pipeline remains extraction → resolved/cleaned source → diff → capture tagging. Tokenization sees the resolved source, not regex syntax. On mismatch, it sees the cleaned placeholders. Raw callback tuples reconstruct that source when inserts are omitted, and reconstruct the exact modified string when removals are omitted. ```svelte ``` Here the resolved source is `Release v2`. Raw tuples are `[[-1, "Release v2"], [1, "Release v2 ready"]]`, and captures contain `version: 'v2'`. The removed line still contains `v2`; its replacement also displays `v2` as expected. Removals are never silently suppressed. Whole-token guarantees apply to raw tuple boundaries. Expected annotations may split a displayed word or line at capture boundaries. The existing newline renderer can split multiline tuples into multiple snippet calls. Child snippets still override renderer-map entries, which override built-in rendering. Compact rendering and custom line breaks work in every mode. See [expected patterns](/docs/guides/expected-patterns) and the [component API](/docs/api/svelte-diff). ## Reactivity, SSR, timing, and limits Changing either text, `diffMode`, `expectedPatterns`, timeout, or cleanup options recomputes the diff. Changing only the callback reuses the same tuple array. Initial diff markup is computed during SSR; callback delivery happens on the client after computation. For token modes, `timing.main` includes tokenization, shared-dictionary encoding, diffing, and decoding; `cleanup` is zero and `total` covers the timed computation. Expected-pattern preprocessing and DOM rendering are outside these measurements. `timeout` is in seconds (default 1; 0 means unlimited). Token preparation, the engine, and decoding share one absolute deadline. Expiry can return a coarse full delete/insert, preserving both complete strings. The shared dictionary supports at most 65,535 distinct tokens across both inputs; exceeding this also returns a complete replacement. Equality and one-sided empty inputs keep their simple fast-path results. Fallback never switches to character granularity or truncates input. This is a best-effort algorithm deadline, not a hard cap on a large token allocation, regex extraction, or rendering. Work remains synchronous: token modes do not virtualize output, offload to workers, or debounce input. Read the [performance guide](/docs/guides/performance) before comparing large documents. # Expected Patterns > Mark intentional dynamic text such as dates, names, IDs, and versions as expected instead of noisy changes. **Source:** [https://diff.svelte.page/docs/guides/expected-patterns](https://diff.svelte.page/docs/guides/expected-patterns) --- Snapshots, generated files, invoices, and release notes often contain values that are supposed to change. Expected patterns let you label those regions separately instead of showing them as ordinary red/green edits. ## Named capture syntax Put JavaScript-style named capture groups directly in `originalText`: ```svelte v\\d+\\.\\d+\\.\\d+) on (?\\d{4}-\\d{2}-\\d{2})'} modifiedText="Release v2.4.1 on 2026-07-17" /> ``` The version and date render as `expected`. Their names and values are also available to rendering and callback code. Capture names must be globally unique across the entire template, including separate lines; duplicate names are rejected even when their values would be equal. ## Access captured values ```svelte { captures = nextCaptures ?? {} }} />
{JSON.stringify(captures, null, 2)}
``` ## Custom expected markup Built-in expected-region spans expose `data-capture-name` and `data-capture-value` alongside the hover `title`. Use `element.dataset.captureName` and `element.dataset.captureValue` for richer tooltips. Each fragment of a multiline capture carries the full captured value. Custom snippets own their markup; this example exposes their supplied text, while `onProcessing` provides full capture values. ```svelte {#snippet expected(text: string, groupName: string)} {text} {/snippet} ``` ## Flexible context matching Patterns are matched using literal text around each named group as context. Extra content between the context and capture is tolerated. This is useful when the actual text adds punctuation or labels that the template does not include. ```text Template: Copyright (?\d{4}) (?.+) Actual: Copyright (c) 2026 Humanspeak, Inc. ``` `2026` and `Humanspeak, Inc.` can still be identified as the expected values while `(c)` remains a real insertion. ## Failure behavior Invalid recognized regex bodies or duplicate capture names reject the whole template. SvelteDiff compares the original source literally, and `captures` is undefined. For example, `(?*)` stays `(?*)` in the compared source. If a valid parsed template does not match its target, SvelteDiff cleans it before computing the normal diff, and `captures` is undefined. Each named group becomes a readable placeholder: `Copyright (?\d{4}) MIT` compared with `different text` uses `Copyright MIT` as its source. If `originalText` contains no named groups, the component follows the ordinary diff path with no extra matching work. ## Pattern safety Named groups are discovered with an iterative parenthesis-counting parser rather than a backtracking regex. Escaped parentheses and nested non-named groups are supported. Nested named groups are rejected to keep group ownership unambiguous. The pattern body is still compiled as JavaScript regular expression syntax. Treat patterns as trusted configuration, not untrusted user input. The algorithm timeout does not bound regex extraction. ## Good uses - Timestamps in snapshots - Generated IDs and build numbers - Copyright years and holders - Package versions in release output - User names or environment-specific paths Expected patterns are not a general ignore system: successful values stay visible, receive their own styling, and remain available through `captures`. ## Word and line modes All [diff modes](/docs/guides/diff-modes) retain extraction → resolved/cleaned source → diff → tagging. Tokenization operates on resolved text for matched templates; valid unmatched templates use cleaned placeholders, while invalid or duplicate templates retain the original literal source. Raw callback tuples reconstruct that source and the original modified text exactly. Expected annotations can split displayed words or lines, so whole-token guarantees apply to raw tuples, not snippet invocations. Newline rendering can also split tuples. ```svelte ``` Resolved source is `Release v2`. Line mode returns `[[-1, "Release v2"], [1, "Release v2 ready"]]`. The deletion includes the captured value `v2`, while the target annotates `v2` as expected with group name `version`. Removals remain removals and are never hidden to avoid this duplication. Word/line skip both cleanup options. # Timing and Performance > Measure SvelteDiff computation and cleanup time, set timeouts, and avoid unnecessary work with large inputs. **Source:** [https://diff.svelte.page/docs/guides/performance](https://diff.svelte.page/docs/guides/performance) --- # Timing & Performance SvelteDiff computes whenever `originalText`, `modifiedText`, `diffMode`, `timeout`, or a cleanup option changes. The `onProcessing` callback exposes the cost of that work. ## Compact equal-text DOM `compact` defaults to `true`. Unstyled built-in equal segments render as text instead of wrapper spans, reducing DOM weight without changing text content or intrinsic line breaks when no selectors or styles depend on the legacy wrapper. Custom equal snippets, `renderers.equal`, and `rendererClasses.equal` retain their requested markup. Use the legacy DOM only when existing selectors or styles require equal spans: ```svelte ``` ## Measure a diff ```svelte (timing = nextTiming)} />
Core algorithm
{timing.main.toFixed(2)} ms
Cleanup
{timing.cleanup.toFixed(2)} ms
Total
{timing.total.toFixed(2)} ms
``` ## Timeout `timeout` is measured in seconds and maps to the underlying diff-match-patch timeout. ```svelte ``` The default is one second. Use `0` for no time limit. An unlimited timeout can be appropriate for controlled offline inputs, but is a poor default for arbitrary user content on the main thread. The algorithm returns the best diff it has when the deadline is reached; timeout is not reported as an exception. ## Reactive input guidance For large editor documents, debounce text input before updating the values passed to SvelteDiff. This keeps typing responsive and avoids recomputing intermediate states the reader never sees. ```typescript let timer: ReturnType const scheduleDiff = (value: string) => { clearTimeout(timer) timer = setTimeout(() => { modifiedText = value }, 200) } ``` ## Cleanup cost `timing.cleanup` includes whichever character-mode cleanup pass was selected; it is exactly zero for word/line. Semantic cleanup generally does more readability work than efficiency cleanup. Measure with representative data instead of assuming the faster choice. ## Scope The component compares characters (default), words, or lines and renders the result. It does not virtualize large output, move computation to a worker, or expose incremental diff computation. For extremely large documents, consider a specialized editor diff engine. Use the [timing example](/examples/timing) to edit inputs and watch the callback values update. ## Token work and deadlines For word/line, `main` includes lossless tokenization, encoding, diffing, and decoding. `total` covers the timed computation. Expected-pattern preprocessing and DOM rendering are excluded. One absolute deadline covers all token stages, checked periodically during preparation and decoding. Expiry may return a full delete/insert; more than 65,535 distinct tokens shared across the inputs uses the same coarse fallback. Neither fallback truncates text or switches to character boundaries. This seconds-based timeout is best effort, not a hard cap on regex execution, one large token allocation, or rendering. Token modes remain synchronous and do not offload, virtualize, or debounce work. SSR computes initial markup. Changing only `onProcessing` preserves the tuple array identity. See [Diff Modes](/docs/guides/diff-modes) for exact token rules. # Migration Guide > Migrate from the previous SvelteDiffMatchPatch name or a hand-built diff rendering loop to SvelteDiff. **Source:** [https://diff.svelte.page/docs/migration](https://diff.svelte.page/docs/migration) --- ## 0.3.x to 0.4.0: compact equal text by default Starting in 0.4.0, `compact` defaults to `true`. Unstyled built-in equal text no longer receives unstyled wrapper `` elements. Text content and intrinsic line breaks are unchanged when no selectors or styles depend on the legacy wrapper, and custom equal snippets, `renderers.equal`, and `rendererClasses.equal` keep their requested markup. If application CSS, tests, or DOM queries depend on the former equal spans, opt out while migrating: ```svelte ``` Remove the opt-out after replacing selectors and styles that depend on unstyled equal `` elements. ## From `SvelteDiffMatchPatch` The component was renamed to `SvelteDiff`. The old export remains as a deprecated alias, so migration can be incremental. ```diff - import { SvelteDiffMatchPatch } from '@humanspeak/svelte-diff' + import { SvelteDiff } from '@humanspeak/svelte-diff' - + ``` The default import already resolves to `SvelteDiff`: ```svelte ``` Rename deprecated types the same way: | Deprecated | Current | |---|---| | `SvelteDiffMatchPatchProps` | `SvelteDiffProps` | | `SvelteDiffMatchPatchTiming` | `SvelteDiffTiming` | | `SvelteDiffMatchPatchDiff` | `SvelteDiffTuple` | ## From a custom `diff-match-patch` loop A typical manual integration configures an instance, calls `diff_main`, runs cleanup, and maps operations to markup. SvelteDiff owns that wiring. ```svelte { console.log({ timing, diffs }) }} /> ``` Move your operation-specific markup into `remove`, `insert`, and `equal` snippets. If your old implementation needs fuzzy matching or patch application, keep the lower-level library for that work—SvelteDiff deliberately exposes only the rendered text-diff use case. ## Callback field names Current timing fields are `main`, `cleanup`, and `total`, all in milliseconds. Avoid older examples that refer to `computeTime` or `cleanupTime`. ## Expected patterns Expected patterns are opt-in. Existing plain strings behave exactly as before. Only `originalText` values containing valid named capture groups activate expected-region matching. ## Verify the migration 1. Confirm both strings update reactively. 2. Compare cleanup mode output on representative documents. 3. Check custom snippets per segment type. 4. Update callback code to the current timing fields. 5. Add expected patterns only where variation is genuinely intentional. --- # Comparisons Compare Svelte Diff with alternative libraries. - [jsdiff](https://diff.svelte.page/compare/vs-jsdiff.md): https://diff.svelte.page/compare/vs-jsdiff - [diff-match-patch](https://diff.svelte.page/compare/vs-diff-match-patch.md): https://diff.svelte.page/compare/vs-diff-match-patch - [diff2html](https://diff.svelte.page/compare/vs-diff2html.md): https://diff.svelte.page/compare/vs-diff2html # Svelte Diff vs diff-match-patch Algorithm Library vs Ready-to-Render Svelte 5 Component ## Overview Google's diff-match-patch is the canonical text-diffing algorithm — and it is exactly what @humanspeak/svelte-diff runs internally (via the TypeScript port diff-match-patch-ts). The difference is everything around the algorithm: reactivity, cleanup wiring, rendering, and types, packaged as a Svelte 5 component instead of an imperative API you integrate by hand. - **Svelte Diff site:** https://diff.svelte.page - **Svelte Diff npm:** https://www.npmjs.com/package/%40humanspeak%2Fsvelte-diff - **Svelte Diff slug:** svelte-diff - **Category:** Diff algorithm library (Google) - **Approach:** Imperative diff_main() API you wire into Svelte yourself - **Website:** https://github.com/google/diff-match-patch - **GitHub:** https://github.com/google/diff-match-patch - **npm:** https://www.npmjs.com/package/diff-match-patch ## Feature comparison | Feature | @humanspeak/svelte-diff | diff-match-patch | Notes | | --- | --- | --- | --- | | Diff algorithm | diff-match-patch (same core, TypeScript port) | diff-match-patch | | | Ready-to-use Svelte component | Svelte 5 component | No — algorithm library | diff-match-patch exposes imperative APIs; you build and wire the Svelte UI | | Semantic cleanup | cleanupSemantic prop | Manual diff_cleanupSemantic() call | | | Efficiency cleanup | cleanupEfficiency edit-cost prop (default 4) | Manual call + editCost tuning | | | Timeout guard | timeout prop | Diff_Timeout setting | | | Expected patterns (ignore dynamic regions) | Named regex capture groups | No | | | Rendering | Svelte snippets or CSS classes | diff_prettyHtml() — hard-coded inline styles, no rendering hooks | | | TypeScript | First-class | Via separate @types/diff-match-patch package | | | Actively maintained | Yes | No | Last npm release in 2020; Google archived the upstream repository | | Fuzzy match & patch APIs | No | Yes | | ## Svelte Diff strengths - Ready-to-use Svelte 5 component — pass two strings, get a rendered diff - Svelte 5 runes-native — reactive to prop changes, no manual recompute - Character-mode semantic and efficiency cleanup, plus whole-word and whole-line modes - Expected patterns — mark dynamic regions (dates, names, versions) as "expected" with named regex capture groups instead of showing them as diffs - Full rendering control via Svelte snippets (remove / insert / equal / expected / lineBreak) or plain CSS classes - TypeScript-first with typed props, timing stats, and diff results - Optional CodeDiff entry with full-source syntax highlighting and caller-selected TanStack languages - Configurable timeout guard for large text comparisons ## diff-match-patch strengths - The canonical diff algorithm, ported to many languages - Proven at scale (originally built for Google Docs) - Includes fuzzy match and patch application APIs - Tiny with zero dependencies ## Svelte Diff limitations - Smaller community (newer project) - Character, word, and line modes; no sentence or structural JSON comparison - A Svelte component — not for diffing data in Node scripts or CLIs ## diff-match-patch limitations - Unmaintained — last npm release in 2020, upstream repository archived - Imperative API: you own the compute-on-change wiring, cleanup calls, and rendering - diff_prettyHtml() uses hard-coded inline styles and provides no rendering hooks - No bundled TypeScript types ## Verdict If you were about to wire diff-match-patch into a Svelte component by hand — recomputing on prop changes, running cleanup, mapping operations to styled spans — that wrapper is literally what @humanspeak/svelte-diff is, built on a maintained TypeScript port. Reach for the raw library only when you need its fuzzy match / patch APIs or you are working outside Svelte. ## Keywords diff-match-patch svelte, google diff match patch, diff match patch component, svelte diff match patch, diff-match-patch alternative # Svelte Diff vs diff2html Git-Patch HTML Generator vs Reactive Svelte 5 Component ## Overview diff2html turns unified diff text — git patches — into polished, GitHub-style side-by-side or line-by-line HTML. It is the right tool for visualizing patches, and the wrong shape for comparing two strings inside a Svelte app: it needs pre-generated diff text as input and renders via an HTML string or imperative DOM wrapper plus a global stylesheet, rather than a Svelte component. - **Svelte Diff site:** https://diff.svelte.page - **Svelte Diff npm:** https://www.npmjs.com/package/%40humanspeak%2Fsvelte-diff - **Svelte Diff slug:** svelte-diff - **Category:** Git diff HTML renderer - **Approach:** Convert unified diff / patch text into pre-styled HTML - **Website:** https://diff2html.xyz - **GitHub:** https://github.com/rtfpessoa/diff2html - **npm:** https://www.npmjs.com/package/diff2html ## Feature comparison | Feature | @humanspeak/svelte-diff | diff2html | Notes | | --- | --- | --- | --- | | Input | Two plain strings | Unified diff / git patch text | To compare two strings with diff2html you must generate patch text first (e.g. jsdiff createPatch) | | Ready-to-use Svelte component | Svelte 5 component | No — HTML generator | diff2html generates or inserts HTML; it is not a Svelte component | | Inline character-level diff | Yes | Within changed lines | | | Side-by-side file view | No | Yes | | | Git patch awareness (files, hunks, headers) | No | Yes | | | Custom rendering | Svelte snippets | Template + CSS overrides | | | Output | Real DOM via Svelte; optional syntax-highlighted CodeDiff | HTML string or imperative DOM injection + stylesheet | | | Expected patterns (ignore dynamic regions) | Named regex capture groups | No | | | Semantic cleanup | cleanupSemantic prop | No | | | TypeScript support | Yes | Yes | | ## Svelte Diff strengths - Ready-to-use Svelte 5 component — pass two strings, get a rendered diff - Svelte 5 runes-native — reactive to prop changes, no manual recompute - Character-mode semantic and efficiency cleanup, plus whole-word and whole-line modes - Expected patterns — mark dynamic regions (dates, names, versions) as "expected" with named regex capture groups instead of showing them as diffs - Full rendering control via Svelte snippets (remove / insert / equal / expected / lineBreak) or plain CSS classes - TypeScript-first with typed props, timing stats, and diff results - Optional CodeDiff entry with full-source syntax highlighting and caller-selected TanStack languages - Configurable timeout guard for large text comparisons ## diff2html strengths - Polished GitHub-style diff UI out of the box - Side-by-side and line-by-line view modes - Understands real git patches — files, hunks, renames - Framework-agnostic and maintained, with less frequent releases ## Svelte Diff limitations - Smaller community (newer project) - Character, word, and line modes; no sentence or structural JSON comparison - A Svelte component — not for diffing data in Node scripts or CLIs - No side-by-side or per-file patch view ## diff2html limitations - Requires unified diff text as input — comparing two strings means generating a patch first - Renders via an HTML string or imperative DOM wrapper and a global stylesheet, not components - Customization is CSS overrides, not your own markup - Heavier payload than a single-purpose component ## Verdict Choose diff2html to display git patches — PR-style file views with side-by-side layout. Choose @humanspeak/svelte-diff to compare two strings inline in a Svelte app, without generating patch text as an intermediate step. ## Keywords diff2html svelte, svelte git diff view, diff2html vs svelte-diff, svelte diff viewer, svelte side by side diff # Svelte Diff vs jsdiff Algorithm Library vs Ready-to-Render Svelte 5 Component ## Overview jsdiff (the npm "diff" package) is the default answer for text diffing in JavaScript — and it is excellent at computing diffs. But it renders nothing: every Svelte project that uses it re-implements the same change-object-to-markup loop. @humanspeak/svelte-diff is that missing rendering layer as a Svelte 5 component. - **Svelte Diff site:** https://diff.svelte.page - **Svelte Diff npm:** https://www.npmjs.com/package/%40humanspeak%2Fsvelte-diff - **Svelte Diff slug:** svelte-diff - **Category:** Diff algorithm library - **Approach:** Compute change objects in JS, build your own rendering - **Website:** https://github.com/kpdecker/jsdiff - **GitHub:** https://github.com/kpdecker/jsdiff - **npm:** https://www.npmjs.com/package/diff ## Feature comparison | Feature | @humanspeak/svelte-diff | jsdiff | Notes | | --- | --- | --- | --- | | Computes text diffs | Yes | Yes | | | Ready-to-use Svelte component | Svelte 5 component | No — algorithm library | jsdiff returns change objects; you build and wire the Svelte UI | | Renders the diff for you | Yes | No | | | Custom rendering | Svelte snippets (remove / insert / equal / expected) | Build your own from change objects | | | Semantic cleanup | cleanupSemantic prop | No | jsdiff returns minimal diffs with no human-readability cleanup pass | | Word / line modes | Yes | Yes | Both support word and line comparison; tokenization contracts differ | | Sentence / structural JSON modes | No | Yes | jsdiff provides diffSentences and diffJson; our JSON inputs remain plain text | | Expected patterns (ignore dynamic regions) | Named regex capture groups | No | | | Reactive updates | Recomputes when props change | Manual recompute wiring | | | Timing statistics | onProcessing callback | No | | | Patch create / apply utilities | No | Yes | | | TypeScript support | Yes | Yes | | | Framework-agnostic | No | Yes | | ## Svelte Diff strengths - Ready-to-use Svelte 5 component — pass two strings, get a rendered diff - Svelte 5 runes-native — reactive to prop changes, no manual recompute - Character-mode semantic and efficiency cleanup, plus whole-word and whole-line modes - Expected patterns — mark dynamic regions (dates, names, versions) as "expected" with named regex capture groups instead of showing them as diffs - Full rendering control via Svelte snippets (remove / insert / equal / expected / lineBreak) or plain CSS classes - TypeScript-first with typed props, timing stats, and diff results - Optional CodeDiff entry with full-source syntax highlighting and caller-selected TanStack languages - Configurable timeout guard for large text comparisons ## jsdiff strengths - Ubiquitous and battle-tested — the de-facto JS diffing library - Framework-agnostic — works in Node, CLIs, workers, any frontend - Multiple granularities: characters, words, lines, sentences, JSON - Patch utilities (createPatch / applyPatch) for unified diff text - Zero dependencies and actively maintained ## Svelte Diff limitations - Smaller community (newer project) - Character, word, and line modes; no sentence or structural JSON comparison - A Svelte component — not for diffing data in Node scripts or CLIs ## jsdiff limitations - Renders nothing — every Svelte project re-implements the same {#each} rendering loop - No semantic cleanup, so character-level diffs can be noisy - No Svelte integration — reactivity and recompute wiring are on you - Styling, escaping, and edge cases are your responsibility ## Verdict Choose jsdiff when you need diff data — in Node, a CLI, or a fully custom UI you want to build from scratch. Choose @humanspeak/svelte-diff when the goal is a diff on screen in a Svelte app: it is the component you would otherwise hand-roll around a diff library, with cleanup, reactivity, and rendering already done. ## Keywords jsdiff svelte, svelte text diff, render diff in svelte, jsdiff vs svelte-diff, svelte diff component --- ## External links - [npm](https://www.npmjs.com/package/@humanspeak/svelte-diff) - [GitHub](https://github.com/humanspeak/svelte-diff) - [Issue tracker](https://github.com/humanspeak/svelte-diff/issues) - [Humanspeak](https://humanspeak.com)