* feat: v5 BREAKING CHANGE: Mergely is no longer a jQuery plugin. BREAKING CHANGE: Removed `options.autoresize` BREAKING CHANGE: Removed `options.editor_width` BREAKING CHANGE: Removed `options.editor_height` BREAKING CHANGE: Removed `options.fadein` BREAKING CHANGE: Removed `options.fgcolor` BREAKING CHANGE: Removed `options.resize` BREAKING CHANGE: Removed `options.width` BREAKING CHANGE: Removed `options.height` BREAKING CHANGE: Removed `options.loaded` callback BREAKING CHANGE: Removed `options.resized` callback BREAKING CHANGE: Removed styles `.mergely-resizer`, `.mergely-full-screen-0`, and `.mergely-full-screen-8` BREAKING CHANGE: Changed default for `options.change_timeout` changed from `150` to `50`. BREAKING CHANGE: No longer automatically scrolls to first change. feat: CodeMirror is now an explicit dependency. feat: No longer necessary to separately require codemirror/addon/search/searchcursor feat: No longer necessary to separately require codemirror/addon/selection/mark-selection feat: `mergely.js` is now unminimized, and added new minimized version `mergely.min.js` feat: Gutter click now scrolls to any line feat: Mergely now emits `resize` event on resize feat: The UI is now non-blocking as diff now runs in background feat: Added support to provide `options.lhs` and `options.rhs` as strings feat: #16 added titles to editor.mergely.com fix: #165 block of changes at end of file are now distinguishable fix: #140 fixed performance issue with large files fix: Fixed issue where canvas markup was not rendered when `viewport` enabled fix: Fixed timing issue where swap sides may not work as expected. fix: Fixed issue where unmarkup did not emit an updated event. fix: Fixed documentation issue where `merge` incorrectly stated: from the specified `side` to the opposite side. fix: Fixed performance issue scrolling fix: Fixed issue where initial render scrolled to first change, showing it at the bottom (as opposed to middle as expected) fix: Fixed issue where line-diffs failed to diff non-alphanumeric characters * chore: tweaked no-start/end styles * feat: dark mode * chore: updated examples * chore(ci): updated webpack * chore(ci): alpha, beta, next branches * chore(ci): test * chore(ci): package-lock.json * chore(ci): ignore alpha, beta, next on branch * fix: fixes firefox scroll-linked effect issue * fix: fixes firefox scroll-linked effect issue * chore: fix css * chore: debug
340 lines
11 KiB
HTML
340 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>Mergely - Example editor</title>
|
|
<meta http-equiv="X-UA-Compatible" content="chrome=1, IE=edge">
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
|
|
<meta name="description" content="" />
|
|
<meta name="keywords" content="mergely,diff,merge,compare" />
|
|
<meta name="author" content="Jamie Peabody" />
|
|
<meta name="color-scheme" content="dark light">
|
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
|
|
|
<!-- Bootstrap -->
|
|
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
|
|
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.0/font/bootstrap-icons.css">
|
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
|
|
|
|
<!-- jquery -->
|
|
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.slim.js"></script>
|
|
|
|
<!-- Mergely -->
|
|
<link type="text/css" rel="stylesheet" href="/lib/mergely.css" />
|
|
<script type="text/javascript" src="/lib/mergely.js"></script>
|
|
|
|
<style type="text/css">
|
|
html, body {
|
|
margin: 0;
|
|
}
|
|
body.dark-mode {
|
|
background-color: #000;
|
|
}
|
|
body.dark-mode .btn {
|
|
color: white;
|
|
}
|
|
body.dark-mode .text-black-50 {
|
|
color: #606060 !important;
|
|
}
|
|
.mergely-editor .CodeMirror {
|
|
/* adjust line height for bootstrap */
|
|
line-height: 21px;
|
|
}
|
|
#compare {
|
|
height: 300px;
|
|
visibility: hidden;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
|
<div class="container-fluid">
|
|
<a class="navbar-brand" href="/">Mergely</a>
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
|
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
|
|
aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
<span class="p-1">
|
|
<button class="btn btn-secondary" id="doc-new">
|
|
<span class="bi-file-earmark-text" />
|
|
New
|
|
</button>
|
|
</span>
|
|
<span class="p-1">
|
|
<button class="btn btn-secondary" id="doc-diff">
|
|
<span class="bi-file-diff" />
|
|
Download diff
|
|
</button>
|
|
</span>
|
|
<span class="p-1">
|
|
<button class="btn btn-secondary" id="prev-change" title="Go previous change">
|
|
<span class="bi-arrow-up-circle-fill" />
|
|
</button>
|
|
</span>
|
|
<span class="p-1">
|
|
<button class="btn btn-secondary" id="next-change" title="Go next change">
|
|
<span class="bi-arrow-down-circle-fill" />
|
|
</button>
|
|
</span>
|
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
|
<li class="nav-item dropdown">
|
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
|
|
data-bs-toggle="dropdown" aria-expanded="false">
|
|
Options
|
|
</a>
|
|
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
|
|
<li><b class="dropdown-item">Editor options</b></li>
|
|
<li>
|
|
<div class="dropdown-item">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="dark-mode">
|
|
<label class="form-check-label" for="dark-mode">
|
|
Dark mode
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<div class="dropdown-item">
|
|
<div class="form-check form-switch">
|
|
<input checked class="form-check-input" type="checkbox" role="switch"
|
|
id="view-sidebar">
|
|
<label class="form-check-label" for="view-sidebar">
|
|
View sidebars
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<div class="dropdown-item">
|
|
<div class="form-check form-switch">
|
|
<input checked class="form-check-input" type="checkbox" role="switch"
|
|
id="wrap-lines">
|
|
<label class="form-check-label" for="wrap-lines">
|
|
Wrap lines
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<div class="dropdown-item">
|
|
<div class="form-check form-switch">
|
|
<input checked class="form-check-input" type="checkbox" role="switch"
|
|
id="line-numbers">
|
|
<label class="form-check-label" for="line-numbers">
|
|
Line numbers
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<div class="dropdown-item">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" role="switch"
|
|
id="read-only">
|
|
<label class="form-check-label" for="read-only">
|
|
Read only
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<hr class="dropdown-divider">
|
|
</li>
|
|
<li><b class="dropdown-item">Diff options</b></li>
|
|
<li>
|
|
<div class="dropdown-item">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" role="switch"
|
|
id="ignore-whitespace">
|
|
<label class="form-check-label" for="ignore-whitespace">
|
|
Ignore whitespace
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<div class="dropdown-item">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="ignore-case">
|
|
<label class="form-check-label" for="ignore-case">
|
|
Ignore case
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<div class="dropdown-item">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" role="switch"
|
|
id="ignore-ignoreaccents">
|
|
<label class="form-check-label" for="ignore-ignoreaccents">
|
|
Ignore accent characters
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<form class="d-flex flex-nowrap">
|
|
<input id="search-text" class="form-control me-2" type="search" placeholder="Search"
|
|
aria-label="Search">
|
|
<div class="btn-group">
|
|
<button id="search" type="button" class="btn btn-danger">Search</button>
|
|
<button type="button" class="btn btn-danger dropdown-toggle dropdown-toggle-split"
|
|
data-bs-toggle="dropdown" aria-expanded="false">
|
|
<span class="visually-hidden">Toggle Dropdown</span>
|
|
</button>
|
|
<ul class="dropdown-menu dropdown-menu-end">
|
|
<li><a id="search-lhs" class="dropdown-item" href="#">
|
|
<span class="bi-check"></span>Search left editor</a>
|
|
</li>
|
|
<li><a id="search-rhs" class="dropdown-item" href="#">
|
|
<span class="bi-check" style="color:transparent"></span>Search right editor</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div id="compare"></div>
|
|
<div class="container-fluid" style="font-size:12px">
|
|
<div class="row">
|
|
<div class="col" id="lhs-info">
|
|
<button class="btn p-0" id="download-lhs">
|
|
<span class="bi-box-arrow-in-down" />
|
|
</button>
|
|
<span class="text-black-50" id="lhs-characters"></span>
|
|
<span class="text-black-50" id="lhs-changes"></span>
|
|
</div>
|
|
<div class="col" style="flex: 0 0 24px">
|
|
</div>
|
|
<div class="col" id="rhs-info">
|
|
<button class="btn p-0" id="download-rhs">
|
|
<span class="bi-box-arrow-in-down" />
|
|
</button>
|
|
<span class="text-black-50" id="rhs-characters"></span>
|
|
<span class="text-black-50" id="rhs-changes"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const mergely = new Mergely('#compare', {
|
|
license: 'lgpl',
|
|
wrap_lines: true
|
|
});
|
|
|
|
mergely.once('updated', () => {
|
|
mergely.lhs('the qúíck red FOX\njumped over the hairy dog');
|
|
mergely.rhs('\tThe quick brown fox\njumped over the lazy dog');
|
|
|
|
mergely.once('updated', () => {
|
|
document.getElementById('compare').style.visibility = 'visible';
|
|
});
|
|
|
|
jQuery('#ignore-whitespace').on('click', (ev) => {
|
|
mergely.options({ ignorews: ev.target.checked });
|
|
});
|
|
jQuery('#ignore-case').on('click', (ev) => {
|
|
mergely.options({ ignorecase: ev.target.checked });
|
|
});
|
|
jQuery('#ignore-ignoreaccents').on('click', (ev) => {
|
|
mergely.options({ ignoreaccents: ev.target.checked });
|
|
});
|
|
jQuery('#view-sidebar').on('click', (ev) => {
|
|
mergely.options({ sidebar: ev.target.checked });
|
|
});
|
|
jQuery('#wrap-lines').on('click', (ev) => {
|
|
mergely.options({ wrap_lines: ev.target.checked });
|
|
});
|
|
jQuery('#line-numbers').on('click', (ev) => {
|
|
mergely.options({ line_numbers: ev.target.checked });
|
|
});
|
|
jQuery('#read-only').on('click', (ev) => {
|
|
const lhsCm = mergely.cm('lhs');
|
|
lhsCm.setOption('readOnly', ev.target.checked);
|
|
const rhsCm = mergely.cm('rhs');
|
|
rhsCm.setOption('readOnly', ev.target.checked);
|
|
mergely.options({});
|
|
});
|
|
jQuery('#next-change').on('click', (ev) => {
|
|
mergely.scrollToDiff('next');
|
|
});
|
|
jQuery('#prev-change').on('click', (ev) => {
|
|
mergely.scrollToDiff('prev');
|
|
});
|
|
jQuery('#dark-mode').on('click', (ev) => {
|
|
document.body.classList.toggle('dark-mode');
|
|
document.querySelector('.mergely-editor').classList.toggle('dark-mode');
|
|
// basically a no-op to force colors to be recalculated
|
|
mergely.options({});
|
|
});
|
|
jQuery('#doc-new').on('click', () => {
|
|
mergely.lhs('');
|
|
mergely.rhs('');
|
|
});
|
|
jQuery('#doc-diff').on('click', () => downloadText(mergely.diff(), 'doc.diff'));
|
|
jQuery('#download-lhs').on('click', () => downloadText(mergely.get('lhs'), 'lhs.txt'));
|
|
jQuery('#download-rhs').on('click', () => downloadText(mergely.diff('rhs'), 'rhs.txt'));
|
|
let searchLhs = true;
|
|
jQuery('#search-lhs').on('click', (ev) => {
|
|
searchLhs = true;
|
|
const lhs = document.getElementById('search-lhs').children[0];
|
|
const rhs = document.getElementById('search-rhs').children[0];
|
|
lhs.style = 'color:initial';
|
|
rhs.style = 'color:transparent';
|
|
});
|
|
jQuery('#search-rhs').on('click', (ev) => {
|
|
searchLhs = false;
|
|
const lhs = document.getElementById('search-lhs').children[0];
|
|
const rhs = document.getElementById('search-rhs').children[0];
|
|
lhs.style = 'color:transparent';
|
|
rhs.style = 'color:initial';
|
|
});
|
|
jQuery('#search-text').on('keypress', (ev) => {
|
|
console.log(ev.which)
|
|
if (event.which === 13) {
|
|
ev.preventDefault();
|
|
jQuery('#search').click();
|
|
}
|
|
});
|
|
jQuery('#search').on('click', (ev) => {
|
|
ev.preventDefault();
|
|
const text = jQuery('#search-text').get(0).value;
|
|
const direction = searchLhs ? 'lhs' : 'rhs';
|
|
mergely.search(direction, text);
|
|
});
|
|
});
|
|
|
|
mergely.on('updated', () => {
|
|
const info = mergely.summary();
|
|
jQuery('#lhs-characters').text(`${info.lhsLength} characters`);
|
|
jQuery('#rhs-characters').text(`${info.rhsLength} characters`);
|
|
if (info.numChanges) {
|
|
jQuery('#lhs-changes').text('(changed)');
|
|
jQuery('#rhs-changes').text('(changed)');
|
|
} else {
|
|
jQuery('#lhs-changes').text('(no changes)');
|
|
jQuery('#rhs-changes').text('(no changes)');
|
|
}
|
|
});
|
|
|
|
function downloadText(text, filename) {
|
|
const b64 = btoa(text);
|
|
const link = document.createElement('a');
|
|
link.download = filename;
|
|
link.href = 'data:text/csv;charset=utf-8;base64,' + b64;
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|