-
-
+ Merged result
+
+
+
+
;
-const sampleText = `The reconcile-text library is embedded on this page as a WASM module and powers these text boxes. Experiment with changing the "Original", "First user's edit", and "Second user's edit" text boxes to see competing changes get merged in real-time within the "Merged result" box.
+const sampleText = `## Draft release
+## Release plan
-Here, you will see color-coded tokens marking the origin of each token, including ones that got deleted. The result depends on the tokenisation strategy selected above:
-- Character-based
-- Word-based (default)
-- Markdown-based`;
+Build steps:
+- Prototype
+- Publish
+
+Review checklist:
+- [ ] Draft
+- [ ] Review
+
+Announcement:
+> Internal
+> Ready
+
+Use color-coded changes to compare tokenisers.`;
let pendingUpdate: number | null = null;
function scheduleUpdate(): void {
@@ -31,6 +42,9 @@ async function main(): Promise {
originalTextArea.addEventListener('input', scheduleUpdate);
leftTextArea.addEventListener('input', scheduleUpdate);
rightTextArea.addEventListener('input', scheduleUpdate);
+ showDeletions.addEventListener('change', () => {
+ mergedTextArea.classList.toggle('show-deletions', showDeletions.checked);
+ });
document.addEventListener('selectionchange', () => {
if (
@@ -51,15 +65,21 @@ async function main(): Promise {
updateMergedText();
}
-// Edit the instructions to generate example edits
+// Deleting obsolete lines while reformatting their neighbours leaves orphaned
+// markers with Word, but Markdown keeps each marker attached to its line's first word.
function loadSample(): void {
originalTextArea.value = sampleText;
- leftTextArea.value =
- sampleText.replace('color', 'colour') +
- "\n\nCheck out what's the most complex conflict you can come up with!";
+ leftTextArea.value = sampleText
+ .replace('## Draft release\n', '')
+ .replace('- Prototype\n', '')
+ .replace('- [ ] Draft\n', '')
+ .replace('> Internal\n', '')
+ .replace('color', 'colour');
rightTextArea.value = sampleText
- .replace('Experiment with changing', 'Try editing')
- .replace('WASM', 'WebAssembly');
+ .replace('## Release plan', '# Release plan')
+ .replace('- Publish', '1. Publish')
+ .replace('- [ ] Review', '- [x] Review')
+ .replace('> Ready', 'Ready');
}
function updateMergedText(): void {
diff --git a/examples/website/src/style.scss b/examples/website/src/style.scss
index 7ef66d2..f2a3374 100644
--- a/examples/website/src/style.scss
+++ b/examples/website/src/style.scss
@@ -68,7 +68,7 @@ header {
padding: 32px 32px 0 32px;
}
-header > h1 {
+header>h1 {
font-size: 2.5rem;
font-weight: 700;
color: $primary-blue;
@@ -93,13 +93,13 @@ code {
font-weight: 500;
}
-header > p {
+header>p {
color: $text-secondary;
font-size: 1.1rem;
margin-bottom: 0;
}
-header > p:not(:first-of-type) {
+header>p:not(:first-of-type) {
margin-top: 16px;
}
@@ -234,6 +234,20 @@ main {
align-items: center;
}
+.result-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 8px 16px;
+}
+
+.history-toggle {
+ gap: 6px;
+ font-size: 0.85rem;
+ cursor: pointer;
+}
+
.diamond-result svg {
width: 20px;
height: 20px;
@@ -277,17 +291,26 @@ textarea {
resize: none;
outline: none;
margin-bottom: 0;
- field-sizing: content; /* Doesn't work in Safari yet */
+ field-sizing: content;
+ /* Doesn't work in Safari yet */
}
#merged {
width: 100%;
user-select: text;
- > * {
+ >* {
position: relative;
white-space: pre-wrap;
}
+
+ &:not(.show-deletions) {
+
+ .RemovedFromLeft,
+ .RemovedFromRight {
+ display: none;
+ }
+ }
}
.Unchanged {
@@ -348,12 +371,12 @@ $DOT_RADIUS: 4;
background: caret-colour($light-blue);
}
- > * {
+ >* {
position: absolute;
background-color: inherit;
}
- > .stick {
+ >.stick {
left: 0;
top: 0;
transform: translateX(-50%);
@@ -364,7 +387,7 @@ $DOT_RADIUS: 4;
animation: blink-stick 1s steps(1) infinite;
}
- > .dot {
+ >.dot {
border-radius: 50%;
width: #{$DOT_RADIUS * 2}px;
height: #{$DOT_RADIUS * 2}px;
@@ -386,11 +409,11 @@ $DOT_RADIUS: 4;
}
}
- &:hover > .dot {
+ &:hover>.dot {
opacity: 0;
}
- > .info {
+ >.info {
top: -1.3em;
left: calc(-#{$CARET_WIDTH} / 2 * 1px);
font-size: 0.9em;
@@ -403,16 +426,18 @@ $DOT_RADIUS: 4;
border-radius: 3px 3px 3px 0;
}
- &:hover > .info {
+ &:hover>.info {
opacity: 1;
}
}
@keyframes blink-stick {
+
0%,
100% {
opacity: 1;
}
+
50% {
opacity: 0;
}
@@ -423,11 +448,11 @@ $DOT_RADIUS: 4;
padding: 32px 18px 0 18px;
}
- header > h1 {
+ header>h1 {
margin-bottom: 18px;
}
- header > p {
+ header>p {
font-size: 1rem;
}
@@ -494,14 +519,14 @@ footer {
gap: 16px;
}
-.footer-links > a > svg {
+.footer-links>a>svg {
color: $text-secondary;
width: 28px;
height: 28px;
transition: transform 0.2s;
}
-.footer-links > a > svg:hover {
+.footer-links>a>svg:hover {
cursor: pointer;
transform: scale(1.15);
-}
+}
\ No newline at end of file