<!-- Source: https://diff.svelte.page/examples/line-diff -->

# Line Diff

> Edit before and after text to compare line and raw character diff output.

**Source:** [https://diff.svelte.page/examples/line-diff](https://diff.svelte.page/examples/line-diff)

**Markdown mirror:** [https://diff.svelte.page/examples/line-diff.md](https://diff.svelte.page/examples/line-diff.md)

---

This mirror preserves the prose, implementation notes, and runnable Svelte source behind the live example page.

## FIG-001: compare lines.

Line tokens include their original LF, CRLF, or lone-CR endings, blank lines, and an unterminated final line. JSON and configuration are plain text: nothing is parsed, sorted, or normalized. Cleanup applies only to character mode.

**Metadata:** tag: `READABILITY` | modes: `2` | input: `identical`

### Source

#### LineDiff.svelte

Source file: [src/lib/examples/line-diff/demos/LineDiff.svelte](https://github.com/humanspeak/svelte-diff/blob/main/docs/src/lib/examples/line-diff/demos/LineDiff.svelte)

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

    const initialOriginal = 'count=10\nkeep=true\n'
    const initialModified = 'count=20\nkeep=true\n'
    let originalText = $state(initialOriginal)
    let modifiedText = $state(initialModified)
    const reset = () => {
        originalText = initialOriginal
        modifiedText = initialModified
    }
</script>

<div class="editor">
    <div class="inputs">
        <label>Before<textarea bind:value={originalText} spellcheck="false"></textarea></label>
        <label>After<textarea bind:value={modifiedText} spellcheck="false"></textarea></label>
    </div>
    <div class="controls"><button type="button" onclick={reset}>Reset</button><button type="button" onclick={() => {
            originalText = 'count=10\n\nkeep=true'
            modifiedText = 'count=20\n\nkeep=true\n'
        }}>Blank lines / final newline</button></div>
    <p>Line tokens include their original LF, CRLF, or lone-CR endings, blank lines, and an unterminated final line. JSON and configuration are plain text: nothing is parsed, sorted, or normalized. Both cleanup props are ignored in line mode. The raw character pane disables cleanup.</p>
    <div class="panes">
        <section>
            <h2>Raw character mode</h2>
            <!-- svelte-ignore a11y_no_noninteractive_tabindex (Scrollable results must be keyboard focusable.) -->
            <div class="diff-output" role="region" aria-label="Raw character result" tabindex="0">
                <SvelteDiff {originalText} {modifiedText} cleanupEfficiency={0}>
                    {#snippet remove(text)}<del class="diff-remove">{text}</del>{/snippet}
                    {#snippet insert(text)}<ins class="diff-insert">{text}</ins>{/snippet}
                </SvelteDiff>
            </div>
            <footer>Character · cleanup off</footer>
        </section>
        <section>
            <h2>Line mode</h2>
            <!-- svelte-ignore a11y_no_noninteractive_tabindex (Scrollable results must be keyboard focusable.) -->
            <div class="diff-output" role="region" aria-label="Line result" tabindex="0">
                <SvelteDiff {originalText} {modifiedText} diffMode="line">
                    {#snippet remove(text)}<del class="diff-remove">{text}</del>{/snippet}
                    {#snippet insert(text)}<ins class="diff-insert">{text}</ins>{/snippet}
                </SvelteDiff>
            </div>
            <footer>Line · cleanup skipped</footer>
        </section>
    </div>
</div>

<style>
    .editor { min-width: 0; }
    .inputs, .panes { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    label { display: grid; gap: 0.5rem; padding: 1rem; min-width: 0; font: 0.75rem var(--font-mono); }
    textarea { width: 100%; box-sizing: border-box; min-height: 8rem; resize: vertical; border: 1px solid var(--brut-rule); background: var(--brut-bg); color: var(--brut-ink); padding: 0.85rem; font: 0.8rem/1.6 var(--font-mono); }
    .controls { display: flex; flex-wrap: wrap; gap: 1rem; padding: 1rem; }
    button { border: 1px solid var(--brut-rule); padding: 0.4rem 0.7rem; background: var(--brut-bg); color: var(--brut-ink); cursor: pointer; }
    p { padding: 1rem; }
    section { display: grid; grid-template-rows: auto 1fr auto; min-width: 0; border: 1px solid var(--brut-rule); }
    h2, footer { padding: 0.75rem 1rem; margin: 0; font: 0.75rem var(--font-mono); }
    footer { border-top: 1px solid var(--brut-rule); }
    .diff-output { min-height: 8rem; max-height: 24rem; overflow: auto; overflow-wrap: anywhere; white-space: pre-wrap; padding: 1rem; }
    .diff-output:focus-visible { outline: 2px solid var(--brut-accent); outline-offset: -2px; }
    @media (max-width: 700px) { .inputs, .panes { grid-template-columns: minmax(0, 1fr); } }
</style>
```
