reconcile/examples/website/index.html

224 lines
8.5 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
/>
<meta
name="description"
content="3-way text merging that automatically resolves conflicts. No more Git conflict markers — just clean, merged results."
/>
<meta property="og:title" content="3-Way Text Merge" />
<meta
property="og:description"
content="3-way text merging that automatically resolves conflicts. No more Git conflict markers — just clean, merged results."
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://schmelczer.dev/reconcile" />
<meta property="og:image" content="/favicon.ico" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<title>Reconcile: conflict-free text merging</title>
<link inline inline-asset="index.css" inline-asset-delete />
</head>
<body>
<div class="background"></div>
<div class="scroll-container">
<div class="page-wrapper">
<header>
<h1>Reconcile: conflict-free 3-way text merging</h1>
<p>
Think
<a
href="https://www.gnu.org/software/diffutils/manual/html_node/Invoking-diff3.html"
target="_blank"
rel="noopener noreferrer"
>diff3</a
>
or <code>git merge</code>, but with intelligent conflict resolution that
requires no user intervention. The
<a
href="https://github.com/schmelczer/reconcile"
target="_blank"
rel="noopener noreferrer"
>Reconcile</a
>
library tackles a fundamental challenge in collaborative editing: what happens
when multiple users edit the same text simultaneously, but the conflict
resolver only has access to the final results, not the intermediate steps?
</p>
<p>
Where traditional merge tools leave you with conflict markers to resolve
manually, Reconcile automatically weaves changes together. The
<code>reconcile(parent, left, right)</code> function takes conflicting edits
and produces clean, unified results using an algorithm inspired by Operational
Transformation. No more <code>&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code> markers
cluttering your text.
</p>
<p>
The process starts with your chosen tokenisation strategy, then applies Myers'
diff algorithm to compare the original with both modified versions. These
diffs are optimised and transformed to preserve meaningful changes, before a
final merge strategy combines all modifications without losing any edits.
</p>
<p>
Ready to dive deeper? Check out the
<a
href="https://github.com/schmelczer/reconcile"
target="_blank"
rel="noopener noreferrer"
>documentation</a
>
or try editing the text boxes below to see Reconcile in action.
</p>
<p>
Use the tokenisation options below to experiment with different approaches —
the library also supports custom tokenisers.
</p>
</header>
<main>
<section class="tokenizer-selector">
<div class="radio-group" role="radiogroup" aria-label="Tokenization strategy">
<label class="radio-option">
<input
type="radio"
name="tokenizer"
value="Character"
id="tokenizer-character"
/>
<span class="radio-custom" aria-hidden="true"></span>
<div class="radio-content">
<span class="radio-label">Character</span>
<span class="radio-description"
>Fine-grained character-level merging</span
>
</div>
</label>
<label class="radio-option">
<input
type="radio"
name="tokenizer"
value="Word"
id="tokenizer-word"
checked
/>
<span class="radio-custom" aria-hidden="true"></span>
<div class="radio-content">
<span class="radio-label">Word</span>
<span class="radio-description">Retain full words (default)</span>
</div>
</label>
<label class="radio-option">
<input type="radio" name="tokenizer" value="Line" id="tokenizer-line" />
<span class="radio-custom" aria-hidden="true"></span>
<div class="radio-content">
<span class="radio-label">Line</span>
<span class="radio-description"
>Line-by-line like <code>git merge</code></span
>
</div>
</label>
</div>
</section>
<div class="text-area-card diamond-parent">
<label
for="original"
title="The original text before any concurrent edits were made."
>Original</label
>
<textarea id="original" name="original"></textarea>
</div>
<div class="text-area-card diamond-left">
<label
for="left"
title="First user's edits — changes from this box appear in green in the result."
>
First user's edits
<div class="box Left"></div>
</label>
<textarea id="left" name="left"></textarea>
</div>
<div class="text-area-card diamond-right">
<label
for="right"
title="Second user's edits — changes from this box appear in blue in the result."
>
Second user's edits
<div class="box Right"></div>
</label>
<textarea id="right" name="right"></textarea>
</div>
<div class="text-area-card diamond-result">
<label
for="merged"
title="The automatically merged result — edit the boxes above to see changes in real-time."
>
Merged result
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path
d="M10 10l-6 6v4h4l6 -6m1.99 -1.99l2.504 -2.504a2.828 2.828 0 1 0 -4 -4l-2.5 2.5"
></path>
<path d="M13.5 6.5l4 4"></path>
<path d="M3 3l18 18"></path>
</svg>
</label>
<div id="merged" role="textbox" aria-readonly="true" aria-live="polite"></div>
</div>
</main>
<footer>
<p>2025 Andras Schmelczer</p>
<a
href="https://github.com/schmelczer/reconcile"
class="github-link"
aria-label="GitHub repository"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5"
/>
</svg>
</a>
</footer>
</div>
</div>
<noscript>JavaScript is required for this website to function properly.</noscript>
<script inline inline-asset="index.js" inline-asset-delete></script>
</body>
</html>