Better md example & hide deleted text
This commit is contained in:
parent
3894e7e401
commit
5eac6bb012
3 changed files with 108 additions and 53 deletions
|
|
@ -99,7 +99,11 @@
|
|||
|
||||
<main>
|
||||
<section class="tokenizer-selector">
|
||||
<div class="radio-group" role="radiogroup" aria-label="Tokenization strategy">
|
||||
<div
|
||||
class="radio-group"
|
||||
role="radiogroup"
|
||||
aria-label="Tokenization strategy"
|
||||
>
|
||||
<label class="radio-option">
|
||||
<input
|
||||
type="radio"
|
||||
|
|
@ -137,7 +141,7 @@
|
|||
<span class="radio-custom" aria-hidden="true"></span>
|
||||
<div class="radio-content">
|
||||
<span class="radio-label">Markdown</span>
|
||||
<span class="radio-description">Preserve formatting</span>
|
||||
<span class="radio-description">Keep Markdown markers with words</span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -175,31 +179,37 @@
|
|||
</div>
|
||||
|
||||
<div class="text-area-card diamond-result">
|
||||
<label
|
||||
id="merged-label"
|
||||
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"
|
||||
<div class="result-header">
|
||||
<label
|
||||
id="merged-label"
|
||||
title="The automatically merged result - edit the boxes above to see changes in real-time."
|
||||
>
|
||||
<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>
|
||||
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>
|
||||
<label class="history-toggle" for="show-deletions">
|
||||
<input type="checkbox" id="show-deletions" aria-controls="merged" />
|
||||
Show deleted text
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
id="merged"
|
||||
role="textbox"
|
||||
|
|
|
|||
|
|
@ -6,16 +6,27 @@ const originalTextArea = document.getElementById('original') as HTMLTextAreaElem
|
|||
const leftTextArea = document.getElementById('left') as HTMLTextAreaElement;
|
||||
const rightTextArea = document.getElementById('right') as HTMLTextAreaElement;
|
||||
const mergedTextArea = document.getElementById('merged') as HTMLDivElement;
|
||||
const showDeletions = document.getElementById('show-deletions') as HTMLInputElement;
|
||||
const tokenizerRadios = document.querySelectorAll(
|
||||
'input[name="tokenizer"]'
|
||||
) as NodeListOf<HTMLInputElement>;
|
||||
|
||||
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<void> {
|
|||
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<void> {
|
|||
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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue