Last active
February 2, 2021 14:53
-
-
Save nbibler/666c06f678e64a746a4366c68e5827db to your computer and use it in GitHub Desktop.
CodeMirror as an ember-modifier
This file contains hidden or 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
import { action } from "@ember/object"; | |
import { bind } from "@ember/runloop"; | |
import codemirror from "codemirror"; | |
import Modifier from "ember-modifier"; | |
import "codemirror/addon/edit/matchbrackets"; | |
import "codemirror/addon/selection/active-line"; | |
import "codemirror/mode/clike/clike"; | |
import "codemirror/mode/go/go"; | |
import "codemirror/mode/javascript/javascript"; | |
import "codemirror/mode/python/python"; | |
const EXTENSION_REGEXP = /(?:\.([^.]+))?$/; | |
/** | |
* Maps file extensions to loaded, CodeMirror-compatible language modes. | |
* | |
* **Important:** These CodeMirror modes must be loaded to be useable. See | |
* the above imports which load the supported language modes. | |
*/ | |
const modeMap: Record<string, string> = { | |
go: "text/x-go", | |
java: "text/x-java", | |
js: "javascript", | |
py: "python", | |
}; | |
/** | |
* This is a magic CodeMirror mode string to indicate that no highlighting | |
* should be used. | |
* | |
* See https://codemirror.net/doc/manual.html#option_mode. | |
*/ | |
const DoNotHighlight = "null"; | |
interface Args { | |
named: { | |
content: string; | |
path: string; | |
readOnly: boolean; | |
onUpdate: (content: string) => void; | |
[key: string]: unknown; | |
}; | |
positional: never; | |
} | |
export default class CodeMirrorModifier extends Modifier<Args> { | |
didInstall() { | |
this._setup(); | |
} | |
didUpdateArguments() { | |
if (this._editor.getValue() !== this.args.named.content) { | |
this._editor.setValue(this.args.named.content); | |
} | |
this._editor.setOption("readOnly", this.args.named.readOnly); | |
this._editor.setOption("mode", this.mode); | |
} | |
private _editor!: CodeMirror.Editor; | |
/** | |
* Transforms the given path into an equivalent CodeMirror compatible | |
* language mode string by inspecting the extension. | |
* | |
* If no matching language modes are supported or the file extension cannot be | |
* determined, this will return the magic CodeMirror "null" string mode value. | |
* The value "null" indicates no highlighting should be applied. | |
*/ | |
get mode() { | |
if (!this.args.named.path) { | |
return DoNotHighlight; | |
} | |
const extension = EXTENSION_REGEXP.exec(this.args.named.path); | |
if (!extension || !extension[1]) { | |
return DoNotHighlight; | |
} | |
return modeMap[extension[1].toLowerCase()] || DoNotHighlight; | |
} | |
@action | |
private _onChange(editor: CodeMirror.Editor, _changeObject: CodeMirror.EditorChangeLinkedList) { | |
this.args.named.onUpdate(editor.getValue()); | |
} | |
private _setup() { | |
if (!this.element) { | |
throw new Error("CodeMirror modifier has no element"); | |
} | |
const editor: CodeMirror.Editor = codemirror(this.element as HTMLElement, { | |
lineNumbers: true, | |
matchBrackets: true, | |
mode: this.mode, | |
readOnly: this.args.named.readOnly, | |
styleActiveLine: true, | |
theme: "my-custom-theme", | |
value: this.args.named.content || "", | |
viewportMargin: Infinity, | |
}); | |
editor.on("change", bind(this, this._onChange)); | |
this._editor = editor; | |
} | |
} |
This file contains hidden or 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
module.exports = function (defaults) { | |
const app = new EmberApp(defaults, { | |
app.import("node_modules/codemirror/lib/codemirror.css"); | |
}) | |
}) |
This file contains hidden or 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
{ | |
"devDependencies": { | |
"@types/codemirror": "^0.0.106", | |
"codemirror": "^5.59.2", | |
"ember-modifier": "^2.1.1", | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment