diff --git a/airflow_code_editor/VERSION b/airflow_code_editor/VERSION index 831446c..ac14c3d 100644 --- a/airflow_code_editor/VERSION +++ b/airflow_code_editor/VERSION @@ -1 +1 @@ -5.1.0 +5.1.1 diff --git a/airflow_code_editor/static/addon/search/searchcursor.js b/airflow_code_editor/static/addon/search/searchcursor.js index d586957..230017b 100644 --- a/airflow_code_editor/static/addon/search/searchcursor.js +++ b/airflow_code_editor/static/addon/search/searchcursor.js @@ -202,6 +202,7 @@ function SearchCursor(doc, query, pos, options) { this.atOccurrence = false + this.afterEmptyMatch = false this.doc = doc pos = pos ? doc.clipPos(pos) : Pos(0, 0) this.pos = {from: pos, to: pos} @@ -237,21 +238,29 @@ findPrevious: function() {return this.find(true)}, find: function(reverse) { - var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to)) - - // Implements weird auto-growing behavior on null-matches for - // backwards-compatibility with the vim code (unfortunately) - while (result && CodeMirror.cmpPos(result.from, result.to) == 0) { + var head = this.doc.clipPos(reverse ? this.pos.from : this.pos.to); + if (this.afterEmptyMatch && this.atOccurrence) { + // do not return the same 0 width match twice + head = Pos(head.line, head.ch) if (reverse) { - if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1) - else if (result.from.line == this.doc.firstLine()) result = null - else result = this.matches(reverse, this.doc.clipPos(Pos(result.from.line - 1))) + head.ch--; + if (head.ch < 0) { + head.line--; + head.ch = (this.doc.getLine(head.line) || "").length; + } } else { - if (result.to.ch < this.doc.getLine(result.to.line).length) result.to = Pos(result.to.line, result.to.ch + 1) - else if (result.to.line == this.doc.lastLine()) result = null - else result = this.matches(reverse, Pos(result.to.line + 1, 0)) + head.ch++; + if (head.ch > (this.doc.getLine(head.line) || "").length) { + head.ch = 0; + head.line++; + } + } + if (CodeMirror.cmpPos(head, this.doc.clipPos(head)) != 0) { + return this.atOccurrence = false } } + var result = this.matches(reverse, head) + this.afterEmptyMatch = result && CodeMirror.cmpPos(result.from, result.to) == 0 if (result) { this.pos = result diff --git a/airflow_code_editor/static/codemirror.js b/airflow_code_editor/static/codemirror.js index a310c60..2f626b7 100644 --- a/airflow_code_editor/static/codemirror.js +++ b/airflow_code_editor/static/codemirror.js @@ -3174,7 +3174,9 @@ if (/\bcm-fat-cursor\b/.test(cm.getWrapperElement().className)) { var charPos = charCoords(cm, head, "div", null, null); - cursor.style.width = Math.max(0, charPos.right - charPos.left) + "px"; + if (charPos.right - charPos.left > 0) { + cursor.style.width = (charPos.right - charPos.left) + "px"; + } } if (pos.other) { @@ -3349,10 +3351,14 @@ function updateHeightsInViewport(cm) { var display = cm.display; var prevBottom = display.lineDiv.offsetTop; + var viewTop = Math.max(0, display.scroller.getBoundingClientRect().top); + var oldHeight = display.lineDiv.getBoundingClientRect().top; + var mustScroll = 0; for (var i = 0; i < display.view.length; i++) { var cur = display.view[i], wrapping = cm.options.lineWrapping; var height = (void 0), width = 0; if (cur.hidden) { continue } + oldHeight += cur.line.height; if (ie && ie_version < 8) { var bot = cur.node.offsetTop + cur.node.offsetHeight; height = bot - prevBottom; @@ -3367,6 +3373,7 @@ } var diff = cur.line.height - height; if (diff > .005 || diff < -.005) { + if (oldHeight < viewTop) { mustScroll -= diff; } updateLineHeight(cur.line, height); updateWidgetHeight(cur.line); if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) @@ -3381,6 +3388,7 @@ } } } + if (Math.abs(mustScroll) > 2) { display.scroller.scrollTop += mustScroll; } } // Read and store the height of line widgets associated with the @@ -4492,6 +4500,12 @@ function onScrollWheel(cm, e) { var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; + var pixelsPerUnit = wheelPixelsPerUnit; + if (e.deltaMode === 0) { + dx = e.deltaX; + dy = e.deltaY; + pixelsPerUnit = 1; + } var display = cm.display, scroll = display.scroller; // Quit if there's nothing to scroll here @@ -4520,10 +4534,10 @@ // estimated pixels/delta value, we just handle horizontal // scrolling entirely here. It'll be slightly off from native, but // better than glitching out. - if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { + if (dx && !gecko && !presto && pixelsPerUnit != null) { if (dy && canScrollY) - { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); } - setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit)); + { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * pixelsPerUnit)); } + setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * pixelsPerUnit)); // Only prevent default scrolling if vertical scrolling is // actually possible. Otherwise, it causes vertical scroll // jitter on OSX trackpads when deltaX is small and deltaY @@ -4536,15 +4550,15 @@ // 'Project' the visible viewport to cover the area that is being // scrolled into view (if we know enough to estimate it). - if (dy && wheelPixelsPerUnit != null) { - var pixels = dy * wheelPixelsPerUnit; + if (dy && pixelsPerUnit != null) { + var pixels = dy * pixelsPerUnit; var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; if (pixels < 0) { top = Math.max(0, top + pixels - 50); } else { bot = Math.min(cm.doc.height, bot + pixels + 50); } updateDisplaySimple(cm, {top: top, bottom: bot}); } - if (wheelSamples < 20) { + if (wheelSamples < 20 && e.deltaMode !== 0) { if (display.wheelStartX == null) { display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; display.wheelDX = dx; display.wheelDY = dy; @@ -8221,7 +8235,7 @@ } function hiddenTextarea() { - var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"); + var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; min-height: 1em; outline: none"); var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); // The textarea is kept positioned near the cursor to prevent the // fact that it'll be scrolled into view on input from scrolling @@ -8985,9 +8999,11 @@ ContentEditableInput.prototype.supportsTouch = function () { return true }; ContentEditableInput.prototype.receivedFocus = function () { + var this$1 = this; + var input = this; if (this.selectionInEditor()) - { this.pollSelection(); } + { setTimeout(function () { return this$1.pollSelection(); }, 20); } else { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); } @@ -9816,7 +9832,7 @@ addLegacyProps(CodeMirror); - CodeMirror.version = "5.62.3"; + CodeMirror.version = "5.63.3"; return CodeMirror; diff --git a/airflow_code_editor/static/css/theme/solarized.css b/airflow_code_editor/static/css/theme/solarized.css index 9c6b126..e978fec 100644 --- a/airflow_code_editor/static/css/theme/solarized.css +++ b/airflow_code_editor/static/css/theme/solarized.css @@ -35,12 +35,10 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png .cm-s-solarized.cm-s-dark { color: #839496; background-color: #002b36; - text-shadow: #002b36 0 1px; } .cm-s-solarized.cm-s-light { background-color: #fdf6e3; color: #657b83; - text-shadow: #eee8d5 0 1px; } .cm-s-solarized .CodeMirror-widget { @@ -126,7 +124,6 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png .cm-s-solarized.cm-s-dark .CodeMirror-linenumber { color: #586e75; - text-shadow: #021014 0 -1px; } /* Light */ diff --git a/airflow_code_editor/static/mode/nsis/nsis.js b/airflow_code_editor/static/mode/nsis/nsis.js index 636940f..2b1c5fb 100644 --- a/airflow_code_editor/static/mode/nsis/nsis.js +++ b/airflow_code_editor/static/mode/nsis/nsis.js @@ -24,14 +24,14 @@ CodeMirror.defineSimpleMode("nsis",{ { regex: /`(?:[^\\`]|\\.)*`?/, token: "string" }, // Compile Time Commands - {regex: /^\s*(?:\!(include|addincludedir|addplugindir|appendfile|cd|delfile|echo|error|execute|packhdr|pragma|finalize|getdllversion|gettlbversion|system|tempfile|warning|verbose|define|undef|insertmacro|macro|macroend|makensis|searchparse|searchreplace))\b/, token: "keyword"}, + {regex: /^\s*(?:\!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|error|execute|finalize|getdllversion|gettlbversion|include|insertmacro|macro|macroend|makensis|packhdr|pragma|searchparse|searchreplace|system|tempfile|undef|uninstfinalize|verbose|warning))\b/, token: "keyword"}, // Conditional Compilation {regex: /^\s*(?:\!(if(?:n?def)?|ifmacron?def|macro))\b/, token: "keyword", indent: true}, {regex: /^\s*(?:\!(else|endif|macroend))\b/, token: "keyword", dedent: true}, // Runtime Commands - {regex: /^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetKnownFolderPath|GetLabelAddress|GetTempFileName|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfRtlLanguage|IfShellVarContextAll|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|Int64Cmp|Int64CmpU|Int64Fmt|IntCmp|IntCmpU|IntFmt|IntOp|IntPtrCmp|IntPtrCmpU|IntPtrOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadAndSetImage|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestLongPathAware|ManifestMaxVersionTested|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|PEAddResource|PEDllCharacteristics|PERemoveResource|PESubsysVer|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\b/, token: "keyword"}, + {regex: /^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetKnownFolderPath|GetLabelAddress|GetTempFileName|GetWinVer|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfRtlLanguage|IfShellVarContextAll|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|Int64Cmp|Int64CmpU|Int64Fmt|IntCmp|IntCmpU|IntFmt|IntOp|IntPtrCmp|IntPtrCmpU|IntPtrOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadAndSetImage|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestLongPathAware|ManifestMaxVersionTested|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|PEAddResource|PEDllCharacteristics|PERemoveResource|PESubsysVer|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\b/, token: "keyword"}, {regex: /^\s*(?:Function|PageEx|Section(?:Group)?)\b/, token: "keyword", indent: true}, {regex: /^\s*(?:(Function|PageEx|Section(?:Group)?)End)\b/, token: "keyword", dedent: true}, diff --git a/airflow_code_editor/static/mode/xml/xml.js b/airflow_code_editor/static/mode/xml/xml.js index 46806ac..4e36106 100644 --- a/airflow_code_editor/static/mode/xml/xml.js +++ b/airflow_code_editor/static/mode/xml/xml.js @@ -187,6 +187,10 @@ CodeMirror.defineMode("xml", function(editorConf, config_) { }; } + function lower(tagName) { + return tagName && tagName.toLowerCase(); + } + function Context(state, tagName, startOfLine) { this.prev = state.context; this.tagName = tagName || ""; @@ -205,8 +209,8 @@ CodeMirror.defineMode("xml", function(editorConf, config_) { return; } parentTagName = state.context.tagName; - if (!config.contextGrabbers.hasOwnProperty(parentTagName) || - !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { + if (!config.contextGrabbers.hasOwnProperty(lower(parentTagName)) || + !config.contextGrabbers[lower(parentTagName)].hasOwnProperty(lower(nextTagName))) { return; } popContext(state); @@ -240,7 +244,7 @@ CodeMirror.defineMode("xml", function(editorConf, config_) { if (type == "word") { var tagName = stream.current(); if (state.context && state.context.tagName != tagName && - config.implicitlyClosed.hasOwnProperty(state.context.tagName)) + config.implicitlyClosed.hasOwnProperty(lower(state.context.tagName))) popContext(state); if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) { setStyle = "tag"; @@ -279,7 +283,7 @@ CodeMirror.defineMode("xml", function(editorConf, config_) { var tagName = state.tagName, tagStart = state.tagStart; state.tagName = state.tagStart = null; if (type == "selfcloseTag" || - config.autoSelfClosers.hasOwnProperty(tagName)) { + config.autoSelfClosers.hasOwnProperty(lower(tagName))) { maybePopContext(state, tagName); } else { maybePopContext(state, tagName); @@ -359,7 +363,7 @@ CodeMirror.defineMode("xml", function(editorConf, config_) { if (context.tagName == tagAfter[2]) { context = context.prev; break; - } else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) { + } else if (config.implicitlyClosed.hasOwnProperty(lower(context.tagName))) { context = context.prev; } else { break; @@ -367,8 +371,8 @@ CodeMirror.defineMode("xml", function(editorConf, config_) { } } else if (tagAfter) { // Opening tag spotted while (context) { - var grabbers = config.contextGrabbers[context.tagName]; - if (grabbers && grabbers.hasOwnProperty(tagAfter[2])) + var grabbers = config.contextGrabbers[lower(context.tagName)]; + if (grabbers && grabbers.hasOwnProperty(lower(tagAfter[2]))) context = context.prev; else break; diff --git a/airflow_code_editor/static/vim.js b/airflow_code_editor/static/vim.js index c5210c9..289d8d1 100644 --- a/airflow_code_editor/static/vim.js +++ b/airflow_code_editor/static/vim.js @@ -951,7 +951,12 @@ if (!keysMatcher) { clearInputState(cm); return false; } var context = vim.visualMode ? 'visual' : 'normal'; - var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); + var mainKey = keysMatcher[2] || keysMatcher[1]; + if (vim.inputState.operatorShortcut && vim.inputState.operatorShortcut.slice(-1) == mainKey) { + // multikey operators act linewise by repeating only the last character + mainKey = vim.inputState.operatorShortcut; + } + var match = commandDispatcher.matchCommand(mainKey, defaultKeymap, vim.inputState, context); if (match.type == 'none') { clearInputState(cm); return false; } else if (match.type == 'partial') { return true; } @@ -1311,6 +1316,9 @@ } inputState.operator = command.operator; inputState.operatorArgs = copyArgs(command.operatorArgs); + if (command.keys.length > 1) { + inputState.operatorShortcut = command.keys; + } if (command.exitVisualBlock) { vim.visualBlock = false; updateCmSelection(cm); @@ -4297,7 +4305,7 @@ ignoreCase = (/^[^A-Z]*$/).test(regexPart); } var regexp = new RegExp(regexPart, - (ignoreCase || forceIgnoreCase) ? 'i' : undefined); + (ignoreCase || forceIgnoreCase) ? 'im' : 'm'); return regexp; } @@ -4453,7 +4461,14 @@ var cursor = cm.getSearchCursor(query, pos); for (var i = 0; i < repeat; i++) { var found = cursor.find(prev); - if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); } + if (i == 0 && found && cursorEqual(cursor.from(), pos)) { + var lastEndPos = prev ? cursor.from() : cursor.to(); + found = cursor.find(prev); + if (found && !found[0] && cursorEqual(cursor.from(), lastEndPos)) { + if (cm.getLine(lastEndPos.line).length == lastEndPos.ch) + found = cursor.find(prev); + } + } if (!found) { // SearchCursor may have returned null because it hit EOF, wrap // around and try again. @@ -5106,12 +5121,6 @@ regexPart = new RegExp(regexPart).source; //normalize not escaped characters } replacePart = tokens[1]; - // If the pattern ends with $ (line boundary assertion), change $ to \n. - // Caveat: this workaround cannot match on the last line of the document. - if (/(^|[^\\])(\\\\)*\$$/.test(regexPart)) { - regexPart = regexPart.slice(0, -1) + '\\n'; - replacePart = (replacePart || '') + '\n'; - } if (replacePart !== undefined) { if (getOption('pcre')) { replacePart = unescapeRegexReplace(replacePart.replace(/([^\\])&/g,"$1$$&")); @@ -5301,10 +5310,18 @@ lineEnd += modifiedLineNumber - unmodifiedLineNumber; joined = modifiedLineNumber < unmodifiedLineNumber; } + function findNextValidMatch() { + var lastMatchTo = lastPos && copyCursor(searchCursor.to()); + var match = searchCursor.findNext(); + if (match && !match[0] && lastMatchTo && cursorEqual(searchCursor.from(), lastMatchTo)) { + match = searchCursor.findNext(); + } + return match; + } function next() { // The below only loops to skip over multiple occurrences on the same // line when 'global' is not true. - while(searchCursor.findNext() && + while(findNextValidMatch() && isInRange(searchCursor.from(), lineStart, lineEnd)) { if (!global && searchCursor.from().line == modifiedLineNumber && !joined) { continue; diff --git a/changelog.txt b/changelog.txt index 16e7eb0..5743290 100644 --- a/changelog.txt +++ b/changelog.txt @@ -277,3 +277,10 @@ ### Changed - Vue-Good-Table file list (sortable&searchable) + +## 5.1.1 + +2020-10-17 + +### Changed +- CodeMirror upgrade diff --git a/package.json b/package.json index 793d938..1296be6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "airflow-code-editor", - "version": "5.1.0", + "version": "5.1.1", "description": "A plugin for [Apache Airflow](https://github.com/apache/airflow) that allows you to edit DAGs in browser. It provides a file managing interface within specified directories and it can be used to edit and download your files. If git support is enabled, the DAGs are stored in a Git repository. You may use it to view Git history, review local changes and commit.", "private": true, "directories": {