From bfc6bdfae3aa3d978f0c48eb46ecd1d777bf1b8d Mon Sep 17 00:00:00 2001 From: Jamie Peabody Date: Fri, 31 Dec 2021 15:30:37 +0000 Subject: [PATCH] chore: change resize --- .gitignore | 1 + examples/app.js | 8 +- examples/full-page.html | 37 ++++++ examples/index.html | 9 ++ examples/size.html | 148 ++++++++------------- examples/styles.html | 278 ++++++++++++++++++++++++++++++++++++++++ src/diff-view.js | 181 +++++++++++++------------- src/mergely.css | 55 +++----- 8 files changed, 485 insertions(+), 232 deletions(-) create mode 100644 examples/full-page.html create mode 100755 examples/styles.html diff --git a/.gitignore b/.gitignore index 519d3c5..f671a36 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ mergely-*.tgz package-lock.json *.log +diff-view2.js diff --git a/examples/app.js b/examples/app.js index a61390a..f1fce34 100644 --- a/examples/app.js +++ b/examples/app.js @@ -29,14 +29,12 @@ document.onreadystatechange = function () { }, lhs: function(setValue) { setValue(macbeth.join('\n')); - // setValue(lhs); }, rhs: function(setValue) { setValue(macbeth.join('\n') - .replace(/love/g,'bleed') - .replace(/heart/g, 'penis')); - // setValue(rhs); + .replace(/love/g, 'hate') + .replace(/heart/g, 'head')); }, - _debug: 'change,scroll' + _debug: '' }); }; diff --git a/examples/full-page.html b/examples/full-page.html new file mode 100644 index 0000000..915aace --- /dev/null +++ b/examples/full-page.html @@ -0,0 +1,37 @@ + + + + + Mergely - Full page example + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/examples/index.html b/examples/index.html index 968af2a..dc4a185 100644 --- a/examples/index.html +++ b/examples/index.html @@ -19,6 +19,15 @@ This example demonstrates the minimum amount of code required to use Mergely.
  • ajax.html
  • +
  • + size.html +
  • +
  • + styles.html +
  • +
  • + full-page.html +
  • diff --git a/examples/size.html b/examples/size.html index d7435e5..d934251 100755 --- a/examples/size.html +++ b/examples/size.html @@ -1,5 +1,5 @@ @@ -7,107 +7,63 @@ This example demonstrates how to enable line wrapping Mergely - Simple Example - - + + - - - - + + + + - - - + + + - + +
    + Inserted and removed at start but not end +
    +
    +
    +
    +
    -
    -
    - - - - - - -
    - -
    - + diff --git a/examples/styles.html b/examples/styles.html new file mode 100755 index 0000000..b1d00b6 --- /dev/null +++ b/examples/styles.html @@ -0,0 +1,278 @@ + + + + + Mergely - Simple Example + + + + + + + + + + + + + + + + + + +
    + Inserted and removed at start but not end +
    +
    +
    +
    +
    +
    + +
    + Removed and added, not at the start or end +
    +
    +
    +
    +
    +
    + +
    + One document empty, one line +
    +
    +
    +
    +
    +
    + +
    + One document empty, multiple lines +
    +
    +
    +
    +
    +
    + +
    + Inserted and removed at the end +
    +
    +
    +
    +
    +
    + +
    + Changed lines +
    +
    +
    +
    +
    + +
    + Custom styles +
    +
    +
    +
    +
    + + + + diff --git a/src/diff-view.js b/src/diff-view.js index becd012..9b631ba 100644 --- a/src/diff-view.js +++ b/src/diff-view.js @@ -15,13 +15,20 @@ Added `.mergely-editor` to the DOM to scope all the CSS changes. CSS now prefixes `.mergely-editor`. Current active change gutter line number style changed from `.CodeMirror-linenumber` to `.CodeMirror-gutter-background`. Removed support for jquery-ui merge buttons. -API switched from jQuery style to object methods. +API switched from jQuery-style to object methods. +Removed `options.width` and `options.height` and mergely now fills the parent container. +Removed `options.resize`. +Removed `options.resized`. +Removed `options.autoresize`. +Remove styles `.mergely-resizer`, `.mergely-full-screen-0`, and `.mergely-full-screen-8`. +Default for `options.change_timeout` changed to 0. No longer necessary to separately require codemirror/addon/search/searchcursor No longer necessary to separately require codemirror/addon/selection/mark-selection FEATURE: Gutter click now scrolls to any line. File drop-target indicator. +Mergely now emits `resize` event on resize. FIX: Fixed issue where canvas markup was not rendered when `viewport` enabled. @@ -31,6 +38,20 @@ Fixed issue where init triggered an updated event when autoupdate is disabled. Fixed documentation issue where `merge` incorrectly stated: from the specified `side` to the opposite side Fixed performance issue scrolling (find #) Fixed issue where initial render scrolled to first change, showing it at the bottom, as opposed to middle + +TODO: +Disable the fade-in +Fix the intermittent render issue +For some reason ignore-whitespace will mark the "red" differently +When wrap_lines is false, the CM editor grows, screwing up the layout +Fix the overflow for the rendered diff view +Fix the margin colorization +Remove the jump to first diff (instead, make it example) +Fix the alignment of the diff visualization and hz lines +Calculate only once. +Margin indicators are broken for macbeth +Macbeth needs a resize to render correctly +Introduce an async render pipeline as it's currently blocking UI */ const NOTICES = [ @@ -54,7 +75,6 @@ function CodeMirrorDiffView(el, options, { CodeMirror }) { CodeMirrorDiffView.prototype.init = function(el, options = {}) { this.settings = { autoupdate: true, - autoresize: true, rhs_margin: 'right', wrap_lines: false, line_numbers: true, @@ -66,14 +86,14 @@ CodeMirrorDiffView.prototype.init = function(el, options = {}) { ignoreaccents: false, fadein: 'fast', resize_timeout: 500, - change_timeout: 150, + change_timeout: 0, fgcolor: { - a:'#4ba3fa', - c:'#a3a3a3', - d:'#ff7f7f', // color for differences (soft color) - ca:'#4b73ff', - cc:'#434343', - cd:'#ff4f4f' + a: '#4ba3fa', + c: '#a3a3a3', + d: '#ff7f7f', // color for differences (soft color) + ca: '#4b73ff', + cc: '#434343', + cd: '#ff4f4f' }, // color for currently active difference (bright color) bgcolor: '#eee', vpcolor: 'rgba(0, 0, 200, 0.5)', @@ -88,55 +108,7 @@ CodeMirrorDiffView.prototype.init = function(el, options = {}) { lhs: function(setValue) { }, rhs: function(setValue) { }, loaded: function() { }, - resize: (init) => { - const parent = el.parentNode; - const { settings } = this; - let width; - let height; - if (settings.width == 'auto') { - width = parent.offsetWidth; - } - else { - width = settings.width; - } - if (settings.height == 'auto') { - height = parent.offsetHeight - 2; - } - else { - height = settings.height; - } - const contentWidth = width / 2.0 - 2 * 8 - 8; - const contentHeight = height; - - const lhsEditor = this._queryElement(`#${this.id}-editor-lhs`); - lhsEditor.style.width = `${contentWidth}px`; - lhsEditor.style.height = `${contentHeight}px`; - const rhsEditor = this._queryElement(`#${this.id}-editor-rhs`); - rhsEditor.style.width = `${contentWidth}px`; - rhsEditor.style.height = `${contentHeight}px`; - - const lhsCM = this._queryElement(`#${this.id}-editor-lhs .cm-s-default`); - lhsCM.style.width = `${contentWidth}px`; - lhsCM.style.height = `${contentHeight}px`; - const rhsCM = this._queryElement(`#${this.id}-editor-rhs .cm-s-default`); - rhsCM.style.width = `${contentWidth}px`; - rhsCM.style.height = `${contentHeight}px`; - const lhsMargin = this._queryElement(`#${this.id}-lhs-margin`); - lhsMargin.style.height = `${contentHeight}px`; - lhsMargin.height = `${contentHeight}`; - const midCanvas = this._queryElement(`.mergely-canvas canvas`); - midCanvas.style.height = `${contentHeight}px`; - midCanvas.height = `${contentHeight}`; - const rhsMargin = this._queryElement(`#${this.id}-rhs-margin`); - rhsMargin.style.height = `${contentHeight}px`; - rhsMargin.height = `${contentHeight}`; - - if (settings.resized) { - settings.resized(); - } - }, _debug: '', //scroll,draw,calc,diff,markup,change,init - resized: function() { }, // user supplied options ...options }; @@ -144,6 +116,7 @@ CodeMirrorDiffView.prototype.init = function(el, options = {}) { this.el = el; this.lhs_cmsettings = { + viewportMargin: Infinity, ...this.settings.cmsettings, ...this.settings.lhs_cmsettings, // these override any user-defined CodeMirror settings @@ -286,8 +259,10 @@ CodeMirrorDiffView.prototype._setOptions = function(opts) { CodeMirrorDiffView.prototype.options = function(opts) { if (opts) { this._setOptions(opts); - if (this.settings.autoresize) this.resize(); - if (this.settings.autoupdate) this.update(); + this.resize(); + if (this.settings.autoupdate) { + this.update(); + } } else { return this.settings; @@ -379,9 +354,26 @@ CodeMirrorDiffView.prototype.search = function(side, query, direction) { }; CodeMirrorDiffView.prototype.resize = function() { + const parent = this.el.parentNode; + const { settings } = this; + let height; + const contentHeight = parent.offsetHeight - 2; + + const lhsMargin = this._queryElement(`#${this.id}-lhs-margin`); + lhsMargin.style.height = `${contentHeight}px`; + lhsMargin.height = `${contentHeight}`; + const midCanvas = this._queryElement(`.mergely-canvas canvas`); + midCanvas.style.height = `${contentHeight}px`; + midCanvas.height = `${contentHeight}`; + const rhsMargin = this._queryElement(`#${this.id}-rhs-margin`); + rhsMargin.style.height = `${contentHeight}px`; + rhsMargin.height = `${contentHeight}`; + + this.el.dispatchEvent(new Event('resize')); + // recalculate line height as it may be zoomed this.em_height = null; - this.settings.resize(); + // this.settings.resize(); this._changing(); this._set_top_offset('lhs'); }; @@ -399,8 +391,10 @@ CodeMirrorDiffView.prototype.bind = function(el) { const { CodeMirror } = this; this.trace('init', 'bind'); el.style.visibility = 'hidden'; - el.style.position = 'absolute'; + el.style.display = 'flex'; + el.style.flexGrow = '1'; el.style.opacity = '0'; + el.style.height = '100%'; this.id = el.id; const found = document.getElementById(this.id); if (!found) { @@ -476,7 +470,9 @@ CodeMirrorDiffView.prototype.bind = function(el) { left: (editor.offsetWidth - 300) / 2 })); editor.addEventListener('click', () => { - splash.style.cssText += 'visibility: hidden; opacity: 0; transition: visibility 0s 100ms, opacity 100ms linear;'; + splash.style.visibility = 'hidden'; + splash.style.opacity = '0'; + splash.style.transition = `visibility 0s 100ms, opacity 100ms linear`; setTimeout(() => splash.remove(), 110); }, { once: true }); el.append(splash); @@ -495,8 +491,8 @@ CodeMirrorDiffView.prototype.bind = function(el) { // get current diff border color from user-defined css const diffColor = htmlToElement('') - const body = this._queryElement('body'); - body.append(diffColor); + // const body = this._queryElement('body'); + this.el.append(diffColor); this.current_diff_color = window.getComputedStyle(diffColor).borderTopColor; // make a throttled render function @@ -531,34 +527,33 @@ CodeMirrorDiffView.prototype.bind = function(el) { this._scrolling({ side: 'rhs', id: this.rhsId }); }); - // resize - if (this.settings.autoresize) { - let resizeTimeout; - const resize = (init) => { - if (init) { - if (this.settings.fadein !== false) { - const duration = this.settings.fadein === 'fast' ? 200 : 750; - el.style.cssText += `visibility: visible; opacity: 1.0; transition: opacity ${duration}ms linear;`; - } - else { - el.style.visibility = 'visible'; - el.style.opacity = '1.0'; - } + // resize event handeler + let resizeTimeout; + const resize = (init) => { + if (init) { + if (this.settings.fadein !== false) { + const duration = this.settings.fadein === 'fast' ? 200 : 750; + el.style.visibility = 'visible'; + el.style.opacity = '1.0'; + el.style.transition = `opacity ${duration}ms linear`; } - if (this.settings.resize) this.settings.resize(init); - this.resize(); - this.editor.lhs.refresh(); - this.editor.rhs.refresh(); - }; - this._handleResize = () => { - if (resizeTimeout) { - clearTimeout(resizeTimeout); + else { + el.style.visibility = 'visible'; + el.style.opacity = '1.0'; } - resizeTimeout = setTimeout(resize, this.settings.resize_timeout); - }; - window.addEventListener('resize', this._handleResize); - resize(true); - } + } + this.resize(); + this.editor.lhs.refresh(); + this.editor.rhs.refresh(); + }; + this._handleResize = () => { + if (resizeTimeout) { + clearTimeout(resizeTimeout); + } + resizeTimeout = setTimeout(resize, this.settings.resize_timeout); + }; + window.addEventListener('resize', this._handleResize); + resize(true); // scrollToDiff() from gutter function gutterClicked(side, line, ev) { @@ -824,8 +819,8 @@ CodeMirrorDiffView.prototype._clearMarginMarkup = function() { const ex = this._draw_info(); const ctx = ex.dcanvas.getContext('2d'); ctx.beginPath(); - ctx.fillStyle = '#fff'; - ctx.fillRect(0, 0, this.draw_mid_width, ex.visible_page_height); + ctx.fillStyle = 'rgba(0,0,0,0)'; // transparent + ctx.clearRect(0, 0, this.draw_mid_width, ex.visible_page_height); }; CodeMirrorDiffView.prototype._diff = function() { @@ -1531,7 +1526,7 @@ function throttle(func, { delay }) { const now = Date.now(); if (now - lastTime >= delay) { - func.apply(this); + setImmediate(func.apply(this)); lastTime = now; } else { // call `func` if no other event after `delay` diff --git a/src/mergely.css b/src/mergely.css index bc6c1a0..43a6d18 100644 --- a/src/mergely.css +++ b/src/mergely.css @@ -1,19 +1,22 @@ .mergely-editor .CodeMirror { line-height: 18px; -} - -/* FIXME: needed? */ -.CodeMirror-scroll { height: 100%; - overflow: auto; + width: 100%; } +/* .mergely-editor .mergely-column, .mergely-editor .mergely-canvas, .mergely-editor .mergely-margin { position: relative; float: left; } +*/ + +.mergely-editor .mergely-column { + flex-grow: 1; + width: 100%; +} .mergely-editor .mergely-margin canvas { width: 8px; @@ -23,43 +26,19 @@ width: 28px; } -/* resizeable */ -/* FIXME: needed? */ -.mergely-resizer { - width: 100%; - height: 100%; -} - -/* FIXME: needed? */ -.mergely-full-screen-0 { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - overflow: hidden; -} - -/* FIXME: needed? */ -.mergely-full-screen-8 { - position: absolute; - top: 8px; - bottom: 8px; - left: 8px; - right: 8px; - overflow: hidden; -} - .mergely-editor .mergely.a.rhs.start { border-top-width: 1px; border-top-style: solid; } +.mergely-editor .mergely.a.lhs.start.end { + border-top-width: 0px; +} + .mergely-editor .mergely.a.lhs.start.end, .mergely-editor .mergely.a.rhs.end { border-bottom-width: 1px; border-bottom-style: solid; - border-top-width: 0px; } .mergely-editor .mergely.d.lhs.end, @@ -135,10 +114,9 @@ } .mergely-editor .merge-button { - opacity: 0.6; height: 18px; cursor: pointer; - width: 27px; + width: 26px; padding-left: 3px; } @@ -147,6 +125,7 @@ color: #717171; } .mergely-editor .mergely.current.CodeMirror-gutter-background { + /* FIXME: does this do anything? */ background-color: #777; } .mergely-editor .mergely.current .CodeMirror-linenumber { @@ -154,13 +133,11 @@ font-weight: bold; } .mergely-editor .merge-button { - background-color: #bfbfbf; - color: #eee; + color: #383838; } .mergely-editor .merge-button:hover { color: #fff; mix-blend-mode: darken; - opacity: 0.8; } .mergely-editor .mergely-column { border: 1px solid #ccc; @@ -180,10 +157,12 @@ .mergely-editor .mergely.c { border-color: #a3a3a3; } +/* .mergely-editor .mergely.c.lhs, .mergely-editor .mergely.c.rhs { background-color: #fafafa; } +*/ .mergely-editor .mergely.ch.d.lhs { text-decoration: line-through; color: #ff0000;