logo svelte /diff v0.4.1

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

npm install @humanspeak/svelte-diff
npm install @humanspeak/svelte-diff
pnpm add @humanspeak/svelte-diff
pnpm add @humanspeak/svelte-diff

Your first diff

<script lang="ts">
    import SvelteDiff from '@humanspeak/svelte-diff'

    const before = 'Ship the small release on Tuesday.'
    const after = 'Ship the polished release on Thursday.'
</script>

<p class="diff-output">
    <SvelteDiff originalText={before} modifiedText={after} cleanupSemantic />
</p>
<script lang="ts">
    import SvelteDiff from '@humanspeak/svelte-diff'

    const before = 'Ship the small release on Tuesday.'
    const after = 'Ship the polished release on Thursday.'
</script>

<p class="diff-output">
    <SvelteDiff originalText={before} modifiedText={after} cleanupSemantic />
</p>

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.

Reactive inputs

Both required props are reactive. If either string changes, the component recomputes the diff.

<script lang="ts">
    import SvelteDiff from '@humanspeak/svelte-diff'

    let originalText = $state('Hello from Svelte.')
    let modifiedText = $state('Hello from Svelte 5.')
</script>

<textarea bind:value={originalText}></textarea>
<textarea bind:value={modifiedText}></textarea>

<SvelteDiff {originalText} {modifiedText} />
<script lang="ts">
    import SvelteDiff from '@humanspeak/svelte-diff'

    let originalText = $state('Hello from Svelte.')
    let modifiedText = $state('Hello from Svelte 5.')
</script>

<textarea bind:value={originalText}></textarea>
<textarea bind:value={modifiedText}></textarea>

<SvelteDiff {originalText} {modifiedText} />

Recommended readable defaults

For prose and user-facing copy, semantic cleanup is usually the best starting point:

<SvelteDiff
    {originalText}
    {modifiedText}
    cleanupSemantic={true}
    timeout={1}
/>
<SvelteDiff
    {originalText}
    {modifiedText}
    cleanupSemantic={true}
    timeout={1}
/>

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 <span> markup:

<SvelteDiff
    {originalText}
    {modifiedText}
    rendererClasses={{
        remove: 'diff-remove',
        insert: 'diff-insert',
        equal: 'diff-equal',
        expected: 'diff-expected'
    }}
/>
<SvelteDiff
    {originalText}
    {modifiedText}
    rendererClasses={{
        remove: 'diff-remove',
        insert: 'diff-insert',
        equal: 'diff-equal',
        expected: 'diff-expected'
    }}
/>

Use child snippets when you need different elements, attributes, icons, or animation. See Custom Rendering.

Next steps