Created
March 10, 2019 21:06
-
-
Save thecere/02a9c047f089b916b41e62905b47ae62 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// derived from https://github.com/scniro/react-codemirror2/blob/master/src/index.tsx | |
import React from 'react' | |
const SERVER_RENDERED = process.env.UIX_ENV == 'express' | |
let CodeMirror | |
if (!SERVER_RENDERED) { | |
CodeMirror = require('codemirror') | |
} | |
export class DiffView extends React.Component { | |
constructor(props) { | |
super(props) | |
this.ref = null | |
this.mergeview = null | |
this.leftEditor = null | |
this.editor = null | |
this.rightEditor = null | |
this.mounted = false | |
} | |
componentWillMount() { | |
if (SERVER_RENDERED) return | |
if (this.props.editorWillMount) { | |
this.props.editorWillMount() | |
} | |
} | |
createMergeView(options) { | |
// this kills the old ones | |
this.ref.innerHTML = '' | |
// ok, we play some games with text initializiation | |
// if we initialize with the real text contents, we get glitches in the "blue diff indicators" | |
// so we init with empty strings and use a additional setValue call on the subeditors later | |
let {value, origLeft, origRight, ...nonTextOptions} = options | |
if (origLeft !== undefined) { | |
nonTextOptions.origLeft = '' | |
} | |
if (origRight !== undefined) { | |
nonTextOptions.origRight = '' | |
} | |
this.mergeview = CodeMirror.MergeView(this.ref, {...nonTextOptions, value: ''}) | |
// optional left or right | |
this.leftEditor = this.mergeview.leftOriginal() | |
this.rightEditor = this.mergeview.rightOriginal() | |
// center editor (can be writable) | |
this.editor = this.mergeview.editor() | |
this.editor.on('change', (cm, data) => { | |
if (!this.mounted) { | |
return | |
} | |
if (this.props.onChange) { | |
this.props.onChange(this.editor, data, this.editor.getValue()) | |
} | |
}) | |
this.hackCSS(this.props.height) | |
// ok, apply the init hack | |
if (value) { | |
this.editor.setValue(value) | |
} | |
if (this.leftEditor && origLeft) { | |
this.leftEditor.setValue(origLeft) | |
} | |
if (this.rightEditor && origRight) { | |
this.rightEditor.setValue(origRight) | |
} | |
if (this.props.editorDidMount) { | |
this.props.editorDidMount(this.editor, this.leftEditor, this.rightEditor) | |
} | |
this.mergeview.setShowDifferences(options.highlightDifferences) | |
} | |
componentDidMount() { | |
if (SERVER_RENDERED) return | |
this.createMergeView(this.props.options) | |
this.mounted = true | |
} | |
componentWillReceiveProps(nextProps) { | |
if (SERVER_RENDERED) return | |
if (this.props.height != nextProps.height || this.props.width != nextProps.width) { | |
this.hackCSS(nextProps.height) | |
} | |
let prevOpts = this.props.options | |
let nextOpts = nextProps.options | |
let resetOptions = ['collapseIdentical', 'lineWrapping', 'connect', 'ignoreWhitespace'] | |
let reset = resetOptions.some(name => prevOpts[name] !== nextOpts[name]) | |
if (reset) { | |
// full reset | |
this.createMergeView(nextOpts) | |
} else { | |
if (prevOpts.highlightDifferences != nextOpts.highlightDifferences) { | |
this.mergeview.setShowDifferences(nextOpts.highlightDifferences) | |
} | |
// XXX: handle all option changes with a reset? | |
if (prevOpts.origLeft != nextOpts.origLeft) { | |
this.leftEditor.setValue(nextOpts.origLeft) | |
//~ this.createMergeView(nextOpts) | |
} | |
if (prevOpts.value != nextOpts.value) { | |
this.editor.setValue(nextOpts.value) | |
//~ this.createMergeView(nextProps.options) | |
} | |
//~ let self = this.mergeview | |
//~ this.editor.operation(function() { | |
//~ merge.collapseIdenticalStretches(self, true); | |
//~ }); | |
//~ this.mergeview.setOption('collapseIdentical', true) | |
} | |
} | |
componentWillUnmount() { | |
if (SERVER_RENDERED) return | |
this.mergeview = null | |
this.leftEditor = null | |
this.rightEditor = null | |
} | |
shouldComponentUpdate(nextProps, nextState) { | |
if (SERVER_RENDERED) return false | |
return true | |
} | |
hackCSS = height => { | |
if (!this.ref || SERVER_RENDERED) return | |
for (let e of this.ref.querySelectorAll('.codemirror-merge .CodeMirror')) { | |
e.style.height = `${height}px` | |
} | |
// http://dwwebs.com/notes-common/codemirror/doc/manual.html#refresh | |
for (let e of [this.editor, this.leftEditor, this.rightEditor]) { | |
if (e) { | |
e.refresh() | |
} | |
} | |
} | |
render() { | |
if (SERVER_RENDERED) return null | |
let {width, height} = this.props | |
let className = this.props.className | |
? `codemirror-merge ${this.props.className}` | |
: 'codemirror-merge' | |
return ( | |
<div | |
className={className} | |
ref={self => (this.ref = self)} | |
style={{width, height, overflow: 'hidden'}} | |
/> | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment