that contains it
$(_getHTMLMenuItem(menuItemID)).parent().remove();
diff --git a/src/config.json b/src/config.json
index 0f67e9a58fb..e769d723bcd 100644
--- a/src/config.json
+++ b/src/config.json
@@ -23,8 +23,8 @@
"healthDataServerURL": "https://healthdev.brackets.io/healthDataLog"
},
"name": "Brackets",
- "version": "1.7.0-0",
- "apiVersion": "1.7.0",
+ "version": "1.8.0-0",
+ "apiVersion": "1.8.0",
"homepage": "http://brackets.io",
"issues": {
"url": "http://github.com/adobe/brackets/issues"
@@ -35,7 +35,13 @@
"branch": "",
"SHA": ""
},
+ "dependencies": {
+ "anymatch": "1.3.0",
+ "chokidar": "1.6.0",
+ "lodash": "4.15.0"
+ },
"devDependencies": {
+ "glob": "7.0.6",
"grunt": "0.4.5",
"jasmine-node": "1.11.0",
"grunt-jasmine-node": "0.1.0",
diff --git a/src/dependencies.js b/src/dependencies.js
index afea3d43a2e..9da47afebfb 100644
--- a/src/dependencies.js
+++ b/src/dependencies.js
@@ -21,9 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, evil:true */
-/*global window, document */
-
/**
* Check for missing dependencies
*/
@@ -48,6 +45,6 @@ window.setTimeout(function () {
"If you're still having problems, please contact us via one of the channels mentioned at the bottom of the README.
" +
"Reload Brackets
";
- document.write(str);
+ window.document.write(str);
}
}, 1000);
diff --git a/src/document/ChangedDocumentTracker.js b/src/document/ChangedDocumentTracker.js
index 36be7ea859d..ed36fd13a25 100644
--- a/src/document/ChangedDocumentTracker.js
+++ b/src/document/ChangedDocumentTracker.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, window */
-
/**
* Defines a ChangedDocumentTracker class to monitor changes to files in the current project.
*/
diff --git a/src/document/Document.js b/src/document/Document.js
index 433b2dec688..a2ae75f52dc 100644
--- a/src/document/Document.js
+++ b/src/document/Document.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define */
-
define(function (require, exports, module) {
"use strict";
diff --git a/src/document/DocumentCommandHandlers.js b/src/document/DocumentCommandHandlers.js
index 7d019e0ba2f..81ad7c55a4e 100644
--- a/src/document/DocumentCommandHandlers.js
+++ b/src/document/DocumentCommandHandlers.js
@@ -21,9 +21,7 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */
-/*global define, $, brackets, window, WebSocket */
+/*jslint regexp: true */
define(function (require, exports, module) {
"use strict";
@@ -1525,35 +1523,31 @@ define(function (require, exports, module) {
/** Delete file command handler **/
function handleFileDelete() {
var entry = ProjectManager.getSelectedItem();
- if (entry.isDirectory) {
- Dialogs.showModalDialog(
- DefaultDialogs.DIALOG_ID_EXT_DELETED,
- Strings.CONFIRM_FOLDER_DELETE_TITLE,
- StringUtils.format(
- Strings.CONFIRM_FOLDER_DELETE,
- StringUtils.breakableUrl(entry.name)
- ),
- [
- {
- className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
- id : Dialogs.DIALOG_BTN_CANCEL,
- text : Strings.CANCEL
- },
- {
- className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,
- id : Dialogs.DIALOG_BTN_OK,
- text : Strings.DELETE
- }
- ]
- )
- .done(function (id) {
- if (id === Dialogs.DIALOG_BTN_OK) {
- ProjectManager.deleteItem(entry);
- }
- });
- } else {
- ProjectManager.deleteItem(entry);
- }
+ Dialogs.showModalDialog(
+ DefaultDialogs.DIALOG_ID_EXT_DELETED,
+ Strings.CONFIRM_DELETE_TITLE,
+ StringUtils.format(
+ entry.isFile ? Strings.CONFIRM_FILE_DELETE : Strings.CONFIRM_FOLDER_DELETE,
+ StringUtils.breakableUrl(entry.name)
+ ),
+ [
+ {
+ className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
+ id : Dialogs.DIALOG_BTN_CANCEL,
+ text : Strings.CANCEL
+ },
+ {
+ className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,
+ id : Dialogs.DIALOG_BTN_OK,
+ text : Strings.DELETE
+ }
+ ]
+ )
+ .done(function (id) {
+ if (id === Dialogs.DIALOG_BTN_OK) {
+ ProjectManager.deleteItem(entry);
+ }
+ });
}
/** Show the selected sidebar (tree or workingset) item in Finder/Explorer */
diff --git a/src/document/DocumentManager.js b/src/document/DocumentManager.js
index 94c20a6cd86..5f1958999db 100644
--- a/src/document/DocumentManager.js
+++ b/src/document/DocumentManager.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $ */
-
/**
* DocumentManager maintains a list of currently 'open' Documents. The DocumentManager is responsible
* for coordinating document operations and dispatching certain document events.
diff --git a/src/document/InMemoryFile.js b/src/document/InMemoryFile.js
index babe149525d..4da2f23da34 100644
--- a/src/document/InMemoryFile.js
+++ b/src/document/InMemoryFile.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
-/*global define */
-
/**
* Represents a file that will never exist on disk - a placeholder backing file for untitled Documents. NO ONE
* other than DocumentManager should create instances of InMemoryFile. It is valid to test for one (`instanceof
diff --git a/src/document/TextRange.js b/src/document/TextRange.js
index fadd5a8691d..7eb5d9aa7e2 100644
--- a/src/document/TextRange.js
+++ b/src/document/TextRange.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define */
-
/**
*/
define(function (require, exports, module) {
diff --git a/src/editor/CSSInlineEditor.js b/src/editor/CSSInlineEditor.js
index ec4f68edeab..363f722ed9c 100644
--- a/src/editor/CSSInlineEditor.js
+++ b/src/editor/CSSInlineEditor.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint regexp: true, vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $ */
-
define(function (require, exports, module) {
"use strict";
diff --git a/src/editor/CodeHintList.js b/src/editor/CodeHintList.js
index dc73d8aadf6..0af254dafd7 100644
--- a/src/editor/CodeHintList.js
+++ b/src/editor/CodeHintList.js
@@ -21,9 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, window */
-
define(function (require, exports, module) {
"use strict";
@@ -307,14 +304,21 @@ define(function (require, exports, module) {
};
/**
- * Check whether keyCode is one of the keys that we handle or not.
+ * Check whether Event is one of the keys that we handle or not.
*
- * @param {number} keyCode
+ * @param {KeyBoardEvent|keyBoardEvent.keyCode} keyEvent
*/
- CodeHintList.prototype.isHandlingKeyCode = function (keyCode) {
+ CodeHintList.prototype.isHandlingKeyCode = function (keyCodeOrEvent) {
+ var keyCode = typeof keyCodeOrEvent === "object" ? keyCodeOrEvent.keyCode : keyCodeOrEvent;
+ var ctrlKey = typeof keyCodeOrEvent === "object" ? keyCodeOrEvent.ctrlKey : false;
+
+
return (keyCode === KeyEvent.DOM_VK_UP || keyCode === KeyEvent.DOM_VK_DOWN ||
keyCode === KeyEvent.DOM_VK_PAGE_UP || keyCode === KeyEvent.DOM_VK_PAGE_DOWN ||
keyCode === KeyEvent.DOM_VK_RETURN ||
+ keyCode === KeyEvent.DOM_VK_CONTROL ||
+ keyCode === KeyEvent.DOM_VK_ESCAPE ||
+ (ctrlKey && keyCode === KeyEvent.DOM_VK_SPACE) ||
(keyCode === KeyEvent.DOM_VK_TAB && this.insertHintOnTab));
};
@@ -385,21 +389,26 @@ define(function (require, exports, module) {
}
// (page) up, (page) down, enter and tab key are handled by the list
- if (event.type === "keydown" && this.isHandlingKeyCode(event.keyCode)) {
+ if (event.type === "keydown" && this.isHandlingKeyCode(event)) {
keyCode = event.keyCode;
- if (event.shiftKey &&
+ if (event.keyCode === KeyEvent.DOM_VK_ESCAPE) {
+ event.stopImmediatePropagation();
+ this.handleClose();
+
+ return false;
+ } else if (event.shiftKey &&
(event.keyCode === KeyEvent.DOM_VK_UP ||
event.keyCode === KeyEvent.DOM_VK_DOWN ||
event.keyCode === KeyEvent.DOM_VK_PAGE_UP ||
event.keyCode === KeyEvent.DOM_VK_PAGE_DOWN)) {
this.handleClose();
-
// Let the event bubble.
return false;
} else if (keyCode === KeyEvent.DOM_VK_UP) {
_rotateSelection.call(this, -1);
- } else if (keyCode === KeyEvent.DOM_VK_DOWN) {
+ } else if (keyCode === KeyEvent.DOM_VK_DOWN ||
+ (event.ctrlKey && keyCode === KeyEvent.DOM_VK_SPACE)) {
_rotateSelection.call(this, 1);
} else if (keyCode === KeyEvent.DOM_VK_PAGE_UP) {
_rotateSelection.call(this, -_itemsPerPage());
@@ -481,8 +490,6 @@ define(function (require, exports, module) {
.css({"left": hintPos.left, "top": hintPos.top, "width": hintPos.width + "px"});
this.opened = true;
- PopUpManager.addPopUp(this.$hintMenu, this.handleClose, true);
-
KeyBindingManager.addGlobalKeydownHook(this._keydownHook);
}
};
@@ -504,7 +511,16 @@ define(function (require, exports, module) {
"width": hintPos.width + "px"});
}
};
-
+ /**
+ * Calls the move up keybind to move hint suggestion selector
+ *
+ * @param {KeyBoardEvent} keyEvent
+ */
+ CodeHintList.prototype.callMoveUp = function (event) {
+ delete event.type;
+ event.type = "keydown";
+ this._keydownHook(event);
+ };
/**
* Closes the hint list
*/
diff --git a/src/editor/CodeHintManager.js b/src/editor/CodeHintManager.js
index c12cf27cabf..19d307aab81 100644
--- a/src/editor/CodeHintManager.js
+++ b/src/editor/CodeHintManager.js
@@ -21,9 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define */
-
/*
* __CodeHintManager Overview:__
*
@@ -249,7 +246,8 @@ define(function (require, exports, module) {
hintList = null,
deferredHints = null,
keyDownEditor = null,
- codeHintsEnabled = true;
+ codeHintsEnabled = true,
+ codeHintOpened = false;
PreferencesManager.definePreference("showCodeHints", "boolean", true, {
@@ -379,6 +377,7 @@ define(function (require, exports, module) {
}
hintList.close();
hintList = null;
+ codeHintOpened = false;
keyDownEditor = null;
sessionProvider = null;
sessionEditor = null;
@@ -410,19 +409,25 @@ define(function (require, exports, module) {
}
return false;
}
-
/**
* From an active hinting session, get hints from the current provider and
* render the hint list window.
*
* Assumes that it is called when a session is active (i.e. sessionProvider is not null).
*/
- function _updateHintList() {
+ function _updateHintList(callMoveUpEvent) {
+
+ callMoveUpEvent = typeof callMoveUpEvent === "undefined" ? false : callMoveUpEvent;
+
if (deferredHints) {
deferredHints.reject();
deferredHints = null;
}
+ if (callMoveUpEvent) {
+ return hintList.callMoveUp(callMoveUpEvent);
+ }
+
var response = sessionProvider.getHints(lastChar);
lastChar = null;
@@ -433,6 +438,7 @@ define(function (require, exports, module) {
// if the response is true, end the session and begin another
if (response === true) {
var previousEditor = sessionEditor;
+
_endSession();
_beginSession(previousEditor);
} else if (response.hasOwnProperty("hints")) { // a synchronous response
@@ -469,6 +475,7 @@ define(function (require, exports, module) {
* @param {Editor} editor
*/
_beginSession = function (editor) {
+
if (!codeHintsEnabled) {
return;
}
@@ -500,7 +507,6 @@ define(function (require, exports, module) {
}
sessionEditor = editor;
-
hintList = new CodeHintList(sessionEditor, insertHintOnTab, maxCodeHints);
hintList.onSelect(function (hint) {
var restart = sessionProvider.insertHint(hint),
@@ -518,26 +524,6 @@ define(function (require, exports, module) {
}
};
- /**
- * Explicitly start a new session. If we have an existing session,
- * then close the current one and restart a new one.
- * @param {Editor} editor
- */
- function _startNewSession(editor) {
- if (!editor) {
- editor = EditorManager.getFocusedEditor();
- }
-
- if (editor) {
- lastChar = null;
- if (_inSession(editor)) {
- _endSession();
- }
- // Begin a new explicit session
- _beginSession(editor);
- }
- }
-
/**
* Handles keys related to displaying, searching, and navigating the hint list.
* This gets called before handleChange.
@@ -574,7 +560,8 @@ define(function (require, exports, module) {
function _handleKeyupEvent(jqEvent, editor, event) {
keyDownEditor = editor;
if (_inSession(editor)) {
- if (event.keyCode === KeyEvent.DOM_VK_HOME || event.keyCode === KeyEvent.DOM_VK_END) {
+ if (event.keyCode === KeyEvent.DOM_VK_HOME ||
+ event.keyCode === KeyEvent.DOM_VK_END) {
_endSession();
} else if (event.keyCode === KeyEvent.DOM_VK_LEFT ||
event.keyCode === KeyEvent.DOM_VK_RIGHT ||
@@ -583,6 +570,8 @@ define(function (require, exports, module) {
// We do this in "keyup" because we want the cursor position to be updated before
// we redraw the list.
_updateHintList();
+ } else if (event.ctrlKey && event.keyCode === KeyEvent.DOM_VK_SPACE) {
+ _updateHintList(event);
}
}
}
@@ -667,6 +656,30 @@ define(function (require, exports, module) {
return (hintList && hintList.isOpen());
}
+ /**
+ * Explicitly start a new session. If we have an existing session,
+ * then close the current one and restart a new one.
+ * @param {Editor} editor
+ */
+ function _startNewSession(editor) {
+ if (isOpen()) {
+ return;
+ }
+
+ if (!editor) {
+ editor = EditorManager.getFocusedEditor();
+ }
+ if (editor) {
+ lastChar = null;
+ if (_inSession(editor)) {
+ _endSession();
+ }
+
+ // Begin a new explicit session
+ _beginSession(editor);
+ }
+ }
+
/**
* Expose CodeHintList for unit testing
*/
@@ -696,12 +709,16 @@ define(function (require, exports, module) {
activeEditorChangeHandler(null, EditorManager.getActiveEditor(), null);
EditorManager.on("activeEditorChange", activeEditorChangeHandler);
-
- // Dismiss code hints before executing any command since the command
+
+ // Dismiss code hints before executing any command other than showing code hints since the command
// may make the current hinting session irrevalent after execution.
// For example, when the user hits Ctrl+K to open Quick Doc, it is
- // pointless to keep the hint list since the user wants to view the Quick Doc.
- CommandManager.on("beforeExecuteCommand", _endSession);
+ // pointless to keep the hint list since the user wants to view the Quick Doc
+ CommandManager.on("beforeExecuteCommand", function (event, commandId) {
+ if (commandId !== Commands.SHOW_CODE_HINTS) {
+ _endSession();
+ }
+ });
CommandManager.register(Strings.CMD_SHOW_CODE_HINTS, Commands.SHOW_CODE_HINTS, _startNewSession);
diff --git a/src/editor/Editor.js b/src/editor/Editor.js
index 7cf92d98beb..99203dc8341 100644
--- a/src/editor/Editor.js
+++ b/src/editor/Editor.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, window */
-
/**
* Editor is a 1-to-1 wrapper for a CodeMirror editor instance. It layers on Brackets-specific
* functionality and provides APIs that cleanly pass through the bits of CodeMirror that the rest
@@ -88,6 +84,7 @@ define(function (require, exports, module) {
CLOSE_TAGS = "closeTags",
DRAG_DROP = "dragDropText",
HIGHLIGHT_MATCHES = "highlightMatches",
+ LINEWISE_COPY_CUT = "lineWiseCopyCut",
SCROLL_PAST_END = "scrollPastEnd",
SHOW_CURSOR_SELECT = "showCursorWhenSelecting",
SHOW_LINE_NUMBERS = "showLineNumbers",
@@ -120,6 +117,7 @@ define(function (require, exports, module) {
cmOptions[CLOSE_TAGS] = "autoCloseTags";
cmOptions[DRAG_DROP] = "dragDrop";
cmOptions[HIGHLIGHT_MATCHES] = "highlightSelectionMatches";
+ cmOptions[LINEWISE_COPY_CUT] = "lineWiseCopyCut";
cmOptions[SCROLL_PAST_END] = "scrollPastEnd";
cmOptions[SHOW_CURSOR_SELECT] = "showCursorWhenSelecting";
cmOptions[SHOW_LINE_NUMBERS] = "lineNumbers";
@@ -174,6 +172,9 @@ define(function (require, exports, module) {
}
}
});
+ PreferencesManager.definePreference(LINEWISE_COPY_CUT, "boolean", true, {
+ description: Strings.DESCRIPTION_LINEWISE_COPY_CUT
+ });
PreferencesManager.definePreference(SCROLL_PAST_END, "boolean", false, {
description: Strings.DESCRIPTION_SCROLL_PAST_END
});
@@ -401,6 +402,7 @@ define(function (require, exports, module) {
indentWithTabs : currentOptions[USE_TAB_CHAR],
inputStyle : "textarea", // the "contenteditable" mode used on mobiles could cause issues
lineNumbers : currentOptions[SHOW_LINE_NUMBERS],
+ lineWiseCopyCut : currentOptions[LINEWISE_COPY_CUT],
lineWrapping : currentOptions[WORD_WRAP],
matchBrackets : { maxScanLineLength: 50000, maxScanLines: 1000 },
matchTags : { bothTags: true },
@@ -1032,10 +1034,10 @@ define(function (require, exports, module) {
});
// For word wrap. Code adapted from https://codemirror.net/demo/indentwrap.html#
this._codeMirror.on("renderLine", function (cm, line, elt) {
- var charWidth = self._codeMirror.defaultCharWidth(), basePadding = 4;
+ var charWidth = self._codeMirror.defaultCharWidth();
var off = CodeMirror.countColumn(line.text, null, cm.getOption("tabSize")) * charWidth;
elt.style.textIndent = "-" + off + "px";
- elt.style.paddingLeft = (basePadding + off) + "px";
+ elt.style.paddingLeft = off + "px";
});
};
@@ -1045,6 +1047,12 @@ define(function (require, exports, module) {
* @param {!string} text
*/
Editor.prototype._resetText = function (text) {
+ var currentText = this._codeMirror.getValue();
+ if (text === currentText) {
+ // there's nothing to reset
+ return;
+ }
+
var perfTimerName = PerfUtils.markStart("Editor._resetText()\t" + (!this.document || this.document.file.fullPath));
var cursorPos = this.getCursorPos(),
diff --git a/src/editor/EditorCommandHandlers.js b/src/editor/EditorCommandHandlers.js
index c3aa73859bb..3a0dcf7c457 100644
--- a/src/editor/EditorCommandHandlers.js
+++ b/src/editor/EditorCommandHandlers.js
@@ -21,10 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $ */
-
-
/**
* Text-editing commands that apply to whichever Editor is currently focused
*/
@@ -210,7 +206,7 @@ define(function (require, exports, module) {
line = doc.getLine(startLine);
var originalCursorPosition = line.search(/\S|$/);
- var firstCharPosition,cursorPosition = originalCursorPosition;
+ var firstCharPosition, cursorPosition = originalCursorPosition;
for (i = startLine; i <= endLine; i++) {
//check if preference for indent line comment is available otherwise go back to default indentation
@@ -227,7 +223,7 @@ define(function (require, exports, module) {
cursorPosition = originalCursorPosition;
}
- editGroup.push({text: prefixes[0], start: {line: i, ch: cursorPosition}});
+ editGroup.push({text: prefixes[0], start: {line: i, ch: cursorPosition}});
} else {
editGroup.push({text: prefixes[0], start: {line: i, ch: 0}});
}
@@ -1117,17 +1113,7 @@ define(function (require, exports, module) {
return handleUndoRedo("redo");
}
- /**
- * Special command handler that just ignores the command. This is used for Cut, Copy, and Paste.
- * These menu items are handled natively, but need to be registered in our JavaScript code so the
- * menu items can be created.
- */
- function ignoreCommand() {
- // Do nothing. The shell will call the native handler for the command.
- return (new $.Deferred()).reject().promise();
- }
-
- function _handleSelectAll() {
+ function _handleSelectAll() {
var result = new $.Deferred(),
editor = EditorManager.getFocusedEditor();
@@ -1141,6 +1127,19 @@ define(function (require, exports, module) {
return result.promise();
}
+ function _execCommand(cmd) {
+ window.document.execCommand(cmd);
+ }
+ function _execCommandCut() {
+ _execCommand("cut");
+ }
+ function _execCommandCopy() {
+ _execCommand("copy");
+ }
+ function _execCommandPaste() {
+ _execCommand("paste");
+ }
+
// Register commands
CommandManager.register(Strings.CMD_INDENT, Commands.EDIT_INDENT, indentText);
CommandManager.register(Strings.CMD_UNINDENT, Commands.EDIT_UNINDENT, unindentText);
@@ -1159,8 +1158,8 @@ define(function (require, exports, module) {
CommandManager.register(Strings.CMD_UNDO, Commands.EDIT_UNDO, handleUndo);
CommandManager.register(Strings.CMD_REDO, Commands.EDIT_REDO, handleRedo);
- CommandManager.register(Strings.CMD_CUT, Commands.EDIT_CUT, ignoreCommand);
- CommandManager.register(Strings.CMD_COPY, Commands.EDIT_COPY, ignoreCommand);
- CommandManager.register(Strings.CMD_PASTE, Commands.EDIT_PASTE, ignoreCommand);
+ CommandManager.register(Strings.CMD_CUT, Commands.EDIT_CUT, _execCommandCut);
+ CommandManager.register(Strings.CMD_COPY, Commands.EDIT_COPY, _execCommandCopy);
+ CommandManager.register(Strings.CMD_PASTE, Commands.EDIT_PASTE, _execCommandPaste);
CommandManager.register(Strings.CMD_SELECT_ALL, Commands.EDIT_SELECT_ALL, _handleSelectAll);
});
diff --git a/src/editor/EditorManager.js b/src/editor/EditorManager.js
index 2b1f4d53f39..026713a36a6 100644
--- a/src/editor/EditorManager.js
+++ b/src/editor/EditorManager.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, window */
-
/**
* EditorManager owns the UI for the editor area. This essentially mirrors the 'current document'
* property maintained by DocumentManager's model.
diff --git a/src/editor/EditorOptionHandlers.js b/src/editor/EditorOptionHandlers.js
index 46152921f8e..216e9e2467f 100644
--- a/src/editor/EditorOptionHandlers.js
+++ b/src/editor/EditorOptionHandlers.js
@@ -21,9 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define */
-
define(function (require, exports, module) {
"use strict";
diff --git a/src/editor/EditorStatusBar.js b/src/editor/EditorStatusBar.js
index 7baf9e407ec..9cec5fddaef 100644
--- a/src/editor/EditorStatusBar.js
+++ b/src/editor/EditorStatusBar.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, window */
-
/**
* Manages parts of the status bar related to the current editor's state.
*/
diff --git a/src/editor/ImageViewer.js b/src/editor/ImageViewer.js
index 250e09831c6..ba24847b739 100644
--- a/src/editor/ImageViewer.js
+++ b/src/editor/ImageViewer.js
@@ -21,9 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, window */
-
define(function (require, exports, module) {
"use strict";
diff --git a/src/editor/InlineTextEditor.js b/src/editor/InlineTextEditor.js
index fd70e1439f4..62dfd36b121 100644
--- a/src/editor/InlineTextEditor.js
+++ b/src/editor/InlineTextEditor.js
@@ -23,8 +23,6 @@
// FUTURE: Merge part (or all) of this class with MultiRangeInlineEditor
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, window */
define(function (require, exports, module) {
"use strict";
diff --git a/src/editor/InlineWidget.js b/src/editor/InlineWidget.js
index 2e7688934d3..0b00c50755b 100644
--- a/src/editor/InlineWidget.js
+++ b/src/editor/InlineWidget.js
@@ -21,10 +21,6 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, window */
-
define(function (require, exports, module) {
"use strict";
diff --git a/src/editor/MultiRangeInlineEditor.js b/src/editor/MultiRangeInlineEditor.js
index 17154137ff5..1c055b0f2c3 100644
--- a/src/editor/MultiRangeInlineEditor.js
+++ b/src/editor/MultiRangeInlineEditor.js
@@ -23,9 +23,6 @@
// FUTURE: Merge part (or all) of this class with InlineTextEditor
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, window */
-
/**
* An inline editor for displaying and editing multiple text ranges. Each range corresponds to a
* contiguous set of lines in a file.
diff --git a/src/extensibility/ExtensionManager.js b/src/extensibility/ExtensionManager.js
index 47ffb9f5ee8..b6cc2d8ef01 100644
--- a/src/extensibility/ExtensionManager.js
+++ b/src/extensibility/ExtensionManager.js
@@ -21,8 +21,7 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
-/*global define, $, brackets */
+/*jslint regexp: true */
/*unittests: ExtensionManager*/
/**
diff --git a/src/extensibility/ExtensionManagerDialog.js b/src/extensibility/ExtensionManagerDialog.js
index c692372923c..acfd61873fb 100644
--- a/src/extensibility/ExtensionManagerDialog.js
+++ b/src/extensibility/ExtensionManagerDialog.js
@@ -21,9 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global brackets, define, $ */
-
define(function (require, exports, module) {
"use strict";
@@ -255,7 +252,7 @@ define(function (require, exports, module) {
// new install or an update.
Package.validate(path, { requirePackageJSON: true }).done(function (info) {
if (info.errors.length) {
- result.reject(Package.formatError(info.errors));
+ result.reject(info.errors.map(Package.formatError).join(" "));
return;
}
@@ -312,6 +309,7 @@ define(function (require, exports, module) {
views = [],
$search,
$searchClear,
+ $modalDlg,
context = { Strings: Strings, showRegistry: !!brackets.config.extension_registry },
models = [];
@@ -338,6 +336,7 @@ define(function (require, exports, module) {
$search.val("");
views.forEach(function (view, index) {
view.filter("");
+ $modalDlg.scrollTop(0);
});
if (!updateSearchDisabled()) {
@@ -363,14 +362,15 @@ define(function (require, exports, module) {
$dlg = dialog.getElement();
$search = $(".search", $dlg);
$searchClear = $(".search-clear", $dlg);
+ $modalDlg = $(".modal-body", $dlg);
function setActiveTab($tab) {
if (models[_activeTabIndex]) {
- models[_activeTabIndex].scrollPos = $(".modal-body", $dlg).scrollTop();
+ models[_activeTabIndex].scrollPos = $modalDlg.scrollTop();
}
$tab.tab("show");
if (models[_activeTabIndex]) {
- $(".modal-body", $dlg).scrollTop(models[_activeTabIndex].scrollPos || 0);
+ $modalDlg.scrollTop(models[_activeTabIndex].scrollPos || 0);
clearSearch();
}
}
@@ -437,7 +437,7 @@ define(function (require, exports, module) {
$(".spinner", $dlg).remove();
views.forEach(function (view) {
- view.$el.appendTo($(".modal-body", $dlg));
+ view.$el.appendTo($modalDlg);
});
// Update search UI before new tab is shown
@@ -457,6 +457,7 @@ define(function (require, exports, module) {
var query = $(this).val();
views.forEach(function (view) {
view.filter(query);
+ $modalDlg.scrollTop(0);
});
}).on("click", ".search-clear", clearSearch);
diff --git a/src/extensibility/ExtensionManagerView.js b/src/extensibility/ExtensionManagerView.js
index 8afe722964a..0bac5cdde1a 100644
--- a/src/extensibility/ExtensionManagerView.js
+++ b/src/extensibility/ExtensionManagerView.js
@@ -21,8 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */
-/*global define, $, brackets, Mustache, PathUtils */
/*unittests: ExtensionManager*/
define(function (require, exports, module) {
@@ -44,7 +42,7 @@ define(function (require, exports, module) {
/**
* Create a detached link element, so that we can use it later to extract url details like 'protocol'
*/
- var _tmpLink = document.createElement('a');
+ var _tmpLink = window.document.createElement('a');
/**
* Creates a view enabling the user to install and manage extensions. Must be initialized
diff --git a/src/extensibility/ExtensionManagerViewModel.js b/src/extensibility/ExtensionManagerViewModel.js
index a95b7cd3a65..90d30fe512e 100644
--- a/src/extensibility/ExtensionManagerViewModel.js
+++ b/src/extensibility/ExtensionManagerViewModel.js
@@ -21,8 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */
-/*global define, $ */
/*unittests: ExtensionManager*/
define(function (require, exports, module) {
diff --git a/src/extensibility/InstallExtensionDialog.js b/src/extensibility/InstallExtensionDialog.js
index 631c78f2267..e11cace4324 100644
--- a/src/extensibility/InstallExtensionDialog.js
+++ b/src/extensibility/InstallExtensionDialog.js
@@ -21,8 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, window, $, brackets, document */
/*unittests: Install Extension Dialog*/
define(function (require, exports, module) {
@@ -260,7 +258,7 @@ define(function (require, exports, module) {
break;
case STATE_CLOSED:
- $(document.body).off(".installDialog");
+ $(window.document.body).off(".installDialog");
// Only resolve as successful if we actually installed something.
Dialogs.cancelModalDialogIfOpen("install-extension-dialog");
diff --git a/src/extensibility/Package.js b/src/extensibility/Package.js
index f75453eb05b..1119f6779b2 100644
--- a/src/extensibility/Package.js
+++ b/src/extensibility/Package.js
@@ -21,10 +21,7 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, regexp: true,
-indent: 4, maxerr: 50 */
-/*global define, $, brackets */
+/*jslint regexp: true */
/**
* Functions for working with extension packages
diff --git a/src/extensibility/node/ExtensionManagerDomain.js b/src/extensibility/node/ExtensionManagerDomain.js
index 6fa70e12ce8..3ebf219175d 100644
--- a/src/extensibility/node/ExtensionManagerDomain.js
+++ b/src/extensibility/node/ExtensionManagerDomain.js
@@ -21,9 +21,8 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, node: true, nomen: true,
-indent: 4, maxerr: 50 */
+/*eslint-env node */
+/*jslint node: true */
"use strict";
diff --git a/src/extensibility/node/package-validator.js b/src/extensibility/node/package-validator.js
index 3d086152224..b2b65458994 100644
--- a/src/extensibility/node/package-validator.js
+++ b/src/extensibility/node/package-validator.js
@@ -21,9 +21,8 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, node: true, nomen: true,
-indent: 4, maxerr: 50, regexp: true */
+/*eslint-env node */
+/*jslint node: true, regexp: true */
"use strict";
diff --git a/src/extensibility/node/spec/Installation.spec.js b/src/extensibility/node/spec/Installation.spec.js
index 7fad313a125..d86d71251da 100644
--- a/src/extensibility/node/spec/Installation.spec.js
+++ b/src/extensibility/node/spec/Installation.spec.js
@@ -21,9 +21,8 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, node: true, nomen: true,
-indent: 4, maxerr: 50 */
+/*eslint-env node */
+/*jslint node: true */
/*global expect, describe, it, beforeEach, afterEach */
"use strict";
diff --git a/src/extensibility/node/spec/Validation.spec.js b/src/extensibility/node/spec/Validation.spec.js
index ef85e5860e4..ab90688d012 100644
--- a/src/extensibility/node/spec/Validation.spec.js
+++ b/src/extensibility/node/spec/Validation.spec.js
@@ -21,9 +21,8 @@
*
*/
-
-/*jslint vars: true, plusplus: true, devel: true, node: true, nomen: true,
-indent: 4, maxerr: 50 */
+/*eslint-env node */
+/*jslint node: true */
/*global expect, describe, it, afterEach */
"use strict";
diff --git a/src/extensibility/registry_utils.js b/src/extensibility/registry_utils.js
index 365ef38935b..57be44c6e29 100644
--- a/src/extensibility/registry_utils.js
+++ b/src/extensibility/registry_utils.js
@@ -29,9 +29,6 @@
* In the future, we should have a better mechanism for sharing code between the two.
*/
-/*jslint vars: true, plusplus: true, nomen: true, indent: 4, maxerr: 50 */
-/*global brackets, define*/
-
define(function (require, exports, module) {
"use strict";
diff --git a/src/extensions/default/CSSCodeHints/CSSProperties.json b/src/extensions/default/CSSCodeHints/CSSProperties.json
index 21c4c96e810..253729a1153 100644
--- a/src/extensions/default/CSSCodeHints/CSSProperties.json
+++ b/src/extensions/default/CSSCodeHints/CSSProperties.json
@@ -95,6 +95,7 @@
"flow-into": {"values": ["none"], "type": "named-flow"},
"flow-from": {"values": ["none", "inherit"], "type": "named-flow"},
"font": {"values": []},
+ "font-display": {"values": ["auto", "block", "swap", "fallback", "optional"]},
"font-family": {"values": ["cursive", "fantasy", "inherit", "monospace", "sans-serif", "serif"]},
"font-feature-settings": {"values": ["normal"]},
"font-kerning": {"values": ["auto", "none", "normal"]},
@@ -112,6 +113,23 @@
"font-variant-numeric": {"values": ["normal"]},
"font-variant-position": {"values": ["normal", "sub", "super"]},
"font-weight": {"values": ["bold", "bolder", "lighter", "normal", "100", "200", "300", "400", "500", "600", "700", "800", "900", "inherit"]},
+ "grid": {"values": []},
+ "grid-area": {"values": []},
+ "grid-auto-columns": {"values": []},
+ "grid-auto-flow": {"values": ["row", "column", "dense"]},
+ "grid-auto-rows": {"values": []},
+ "grid-column": {"values": ["auto"]},
+ "grid-column-end": {"values": []},
+ "grid-column-gap": {"values": []},
+ "grid-column-start": {"values": []},
+ "grid-gap": {"values": []},
+ "grid-row": {"values": ["auto"]},
+ "grid-row-end": {"values": []},
+ "grid-row-start": {"values": []},
+ "grid-row-gap": {"values": []},
+ "grid-template-areas": {"values": []},
+ "grid-template-columns": {"values": ["auto"]},
+ "grid-template-rows": {"values": ["auto"]},
"height": {"values": ["auto", "inherit"]},
"hyphens": {"values": ["auto", "manual", "none"]},
"image-orientation": {"values": []},
@@ -120,7 +138,7 @@
"left": {"values": ["auto", "inherit"]},
"letter-spacing": {"values": ["normal", "inherit"]},
"line-height": {"values": ["normal", "inherit"]},
- "list-style": {"values": ["armenian", "circle", "decimal", "decimal-leading-zero", "disc", "georgian", "inherit", "inside", "lower-alpha", "lower-greek", "lower-latin", "lower-roman", "none", "outside", "square", "upper-alpha", "upper-latin", "upper-roman", "url()"]},
+ "list-style": {"values": ["none", "inherit", "initial", "unset", "url()", "armenian", "circle", "decimal", "decimal-leading-zero", "disc", "georgian", "inside", "lower-alpha", "lower-greek", "lower-latin", "lower-roman", "outside", "square", "upper-alpha", "upper-latin", "upper-roman"]},
"list-style-image": {"values": ["none", "url()", "inherit"]},
"list-style-position": {"values": ["inside", "outside", "inherit"]},
"list-style-type": {"values": ["armenian", "circle", "decimal", "decimal-leading-zero", "disc", "georgian", "lower-alpha", "lower-greek", "lower-latin", "lower-roman", "none", "square", "upper-alpha", "upper-latin", "upper-roman", "inherit"]},
diff --git a/src/extensions/default/CSSCodeHints/main.js b/src/extensions/default/CSSCodeHints/main.js
index 94a61213f3f..4006d837b2f 100644
--- a/src/extensions/default/CSSCodeHints/main.js
+++ b/src/extensions/default/CSSCodeHints/main.js
@@ -21,8 +21,7 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */
-/*global define, brackets, $ */
+/*jslint regexp: true */
define(function (require, exports, module) {
"use strict";
@@ -334,6 +333,12 @@ define(function (require, exports, module) {
selectInitial = true;
}
+ if (lastContext === CSSUtils.PROP_VALUE) {
+ // close the session if we're coming from a property value
+ // see https://github.com/adobe/brackets/issues/9496
+ return null;
+ }
+
lastContext = CSSUtils.PROP_NAME;
needle = needle.substr(0, this.info.offset);
diff --git a/src/extensions/default/CSSCodeHints/unittests.js b/src/extensions/default/CSSCodeHints/unittests.js
index 715e2b752b2..e3d5febfeb9 100644
--- a/src/extensions/default/CSSCodeHints/unittests.js
+++ b/src/extensions/default/CSSCodeHints/unittests.js
@@ -21,8 +21,7 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, describe, it, xit, expect, beforeEach, afterEach, $, brackets */
+/*global describe, it, xit, expect, beforeEach, afterEach */
define(function (require, exports, module) {
"use strict";
diff --git a/src/extensions/default/CloseOthers/main.js b/src/extensions/default/CloseOthers/main.js
index f9122b60068..50947782cbf 100644
--- a/src/extensions/default/CloseOthers/main.js
+++ b/src/extensions/default/CloseOthers/main.js
@@ -21,9 +21,6 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
-/*global define, brackets */
-
define(function (require, exports, module) {
"use strict";
diff --git a/src/extensions/default/CloseOthers/unittests.js b/src/extensions/default/CloseOthers/unittests.js
index 3dc411955d2..01e288af1a5 100644
--- a/src/extensions/default/CloseOthers/unittests.js
+++ b/src/extensions/default/CloseOthers/unittests.js
@@ -21,8 +21,7 @@
*
*/
-/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, describe, it, expect, beforeEach, afterEach, runs, brackets, waitsForDone, spyOn */
+/*global describe, it, expect, beforeEach, afterEach, runs, waitsForDone, spyOn */
define(function (require, exports, module) {
"use strict";
diff --git a/src/extensions/default/CodeFolding/Prefs.js b/src/extensions/default/CodeFolding/Prefs.js
index 9903198c3da..8f498584ed8 100644
--- a/src/extensions/default/CodeFolding/Prefs.js
+++ b/src/extensions/default/CodeFolding/Prefs.js
@@ -4,8 +4,7 @@
* @author Patrick Oladimeji
* @date 3/22/14 20:39:53 PM
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, brackets*/
+
define(function (require, exports, module) {
"use strict";
diff --git a/src/extensions/default/CodeFolding/foldhelpers/foldSelected.js b/src/extensions/default/CodeFolding/foldhelpers/foldSelected.js
index ec22aa59f4a..f8d3da83e05 100644
--- a/src/extensions/default/CodeFolding/foldhelpers/foldSelected.js
+++ b/src/extensions/default/CodeFolding/foldhelpers/foldSelected.js
@@ -3,7 +3,7 @@
* @author Patrick Oladimeji
* @date 31/07/2015 00:11:53
*/
-/*global define*/
+
define(function (require, exports, module) {
"use strict";
diff --git a/src/extensions/default/CodeFolding/foldhelpers/foldcode.js b/src/extensions/default/CodeFolding/foldhelpers/foldcode.js
index bd90228de08..5d188f3df67 100644
--- a/src/extensions/default/CodeFolding/foldhelpers/foldcode.js
+++ b/src/extensions/default/CodeFolding/foldhelpers/foldcode.js
@@ -2,8 +2,7 @@
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Based on http://codemirror.net/addon/fold/foldcode.js
// Modified by Patrick Oladimeji for Brackets
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, brackets, document*/
+
define(function (require, exports, module) {
"use strict";
var CodeMirror = brackets.getModule("thirdparty/CodeMirror/lib/codemirror"),
@@ -36,7 +35,7 @@ define(function (require, exports, module) {
lastMark,
foldMarks;
for (i = 0; i < marks.length; ++i) {
- if (marks[i].__isFold && force !== "fold") {
+ if (marks[i].__isFold) {
if (!allowFolded) {
return null;
}
@@ -60,7 +59,7 @@ define(function (require, exports, module) {
}
function makeWidget() {
- var widget = document.createElement("span");
+ var widget = window.document.createElement("span");
widget.className = "CodeMirror-foldmarker";
return widget;
}
@@ -90,18 +89,25 @@ define(function (require, exports, module) {
});
textRange.on("clear", function (from, to) {
- delete cm._lineFolds[pos.line];
- CodeMirror.signal(cm, "unfold", cm, from, to, pos.line);
+ delete cm._lineFolds[from.line];
+ CodeMirror.signal(cm, "unfold", cm, from, to);
});
if (force === "fold") {
delete range.cleared;
- cm._lineFolds[pos.line] = range;
+ // In some cases such as in xml style files, the start of line folds can span multiple lines.
+ // For instance the attributes of an element can span multiple lines. In these cases when folding
+ // we want to render a gutter marker for both the beginning and end of the opening xml tag.
+ if (pos.line < range.from.line) {
+ cm._lineFolds[range.from.line] = range;
+ } else {
+ cm._lineFolds[pos.line] = range;
+ }
} else {
delete cm._lineFolds[pos.line];
}
- CodeMirror.signal(cm, force, cm, range.from, range.to, pos.line);
+ CodeMirror.signal(cm, force, cm, range.from, range.to);
return range;
}
diff --git a/src/extensions/default/CodeFolding/foldhelpers/foldgutter.js b/src/extensions/default/CodeFolding/foldhelpers/foldgutter.js
index c8476ffa188..7aa319e59c0 100644
--- a/src/extensions/default/CodeFolding/foldhelpers/foldgutter.js
+++ b/src/extensions/default/CodeFolding/foldhelpers/foldgutter.js
@@ -2,8 +2,7 @@
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Based on http://codemirror.net/addon/fold/foldgutter.js
// Modified by Patrick Oladimeji for Brackets
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, brackets, document, window, $*/
+
define(function (require, exports, module) {
"use strict";
var CodeMirror = brackets.getModule("thirdparty/CodeMirror/lib/codemirror"),
@@ -28,7 +27,7 @@ define(function (require, exports, module) {
* @return {HTMLElement} a htmlelement representing the fold marker
*/
function marker(spec) {
- var elt = document.createElement("div");
+ var elt = window.document.createElement("div");
elt.className = spec;
return elt;
}
@@ -100,6 +99,7 @@ define(function (require, exports, module) {
i = sr.to.line + 1;
} else {
range = cm._lineFolds[i] || (func && func(cm, pos));
+
if (!fade || (fade && $gutter.is(":hover"))) {
if (cm.isFolded(i)) {
// expand fold if invalid
@@ -355,14 +355,10 @@ define(function (require, exports, module) {
* @param {!CodeMirror} cm the CodeMirror instance for the active editor
* @param {!Object} from the ch and line position that designates the start of the region
* @param {!Object} to the ch and line position that designates the end of the region
- * @param {?Number} gutterLineNumber the gutter line number that was clicked to signal the fold event
*/
- function onFold(cm, from, to, gutterLineNumber) {
- var state = cm.state.foldGutter,
- line = isNaN(gutterLineNumber) ? from.line : gutterLineNumber;
- if (line >= state.from && line < state.to) {
- updateFoldInfo(cm, line, line + 1);
- }
+ function onFold(cm, from, to) {
+ var state = cm.state.foldGutter;
+ updateFoldInfo(cm, from.line, from.line + 1);
}
/**
@@ -370,15 +366,12 @@ define(function (require, exports, module) {
* @param {!CodeMirror} cm the CodeMirror instance for the active editor
* @param {!{line:number, ch:number}} from the ch and line position that designates the start of the region
* @param {!{line:number, ch:number}} to the ch and line position that designates the end of the region
- * @param {?Number} gutterLineNumber the gutter line number that was clicked to signal the fold event
*/
- function onUnFold(cm, from, to, gutterLineNumber) {
- var state = cm.state.foldGutter,
- line = isNaN(gutterLineNumber) ? from.line : gutterLineNumber;
+ function onUnFold(cm, from, to) {
+ var state = cm.state.foldGutter;
var vp = cm.getViewport();
- if (line >= state.from && line < state.to) {
- updateFoldInfo(cm, line, Math.min(vp.to, to.line));
- }
+ delete cm._lineFolds[from.line];
+ updateFoldInfo(cm, from.line, to.line || vp.to);
}
/**
diff --git a/src/extensions/default/CodeFolding/foldhelpers/handlebarsFold.js b/src/extensions/default/CodeFolding/foldhelpers/handlebarsFold.js
new file mode 100644
index 00000000000..96213f186fe
--- /dev/null
+++ b/src/extensions/default/CodeFolding/foldhelpers/handlebarsFold.js
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2016 - present Adobe Systems Incorporated. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/**
+ * Fold range finder for handlebars/mustache template type files.
+ * @author Patrick Oladimeji
+ * @date 14/08/2016 22:04:21
+ */
+
+define(function (require, exports, module) {
+ "use strict";
+ var CodeMirror = brackets.getModule("thirdparty/CodeMirror/lib/codemirror"),
+ _ = brackets.getModule("thirdparty/lodash"),
+ StringUtils = brackets.getModule("utils/StringUtils");
+
+ /**
+ * Utility function for scanning the text in a document until a certain condition is met
+ * @param {object} cm The code mirror object representing the document
+ * @param {string} startCh The start character position for the scan operation
+ * @param {number} startLine The start line position for the scan operation
+ * @param {function (string): boolean} condition A predicate function that takes in the text seen so far and returns true if the scanning process should be halted
+ * @returns {{from:CodeMirror.Pos, to: CodeMirror.Pos, string: string}} An object representing the range of text scanned.
+ */
+ function scanTextUntil(cm, startCh, startLine, condition) {
+ var line = cm.getLine(startLine),
+ seen = "",
+ characterIndex = startCh,
+ currentLine = startLine,
+ range;
+ while (currentLine <= cm.lastLine()) {
+ if (line.length === 0) {
+ characterIndex = 0;
+ line = cm.getLine(++currentLine);
+ } else {
+ seen = seen.concat(line[characterIndex] || "");
+ if (condition(seen)) {
+ range = {
+ from: {ch: startCh, line: startLine},
+ to: {ch: characterIndex, line: currentLine},
+ string: seen
+ };
+ return range;
+ } else if (characterIndex >= line.length) {
+ seen = seen.concat(cm.lineSeparator());
+ if (condition(seen)) {
+ range = {
+ from: {ch: startCh, line: startLine},
+ to: {ch: characterIndex, line: currentLine},
+ string: seen
+ };
+ return range;
+ }
+ characterIndex = 0;
+ line = cm.getLine(++currentLine);
+ } else {
+ ++characterIndex;
+ }
+ }
+ }
+ }
+
+ /**
+ * Utility function used to detect the end of a helper name when scanning a series of text.
+ * The end of a helper name is signalled by a space character or the `}`
+ * @param {string} seen The string seen so far
+ * @returns {boolean} True when the end of a helper name has been detected.
+ */
+ function endHelperName(seen) {
+ return (/\s$/).test(seen) || StringUtils.endsWith(seen, "}");
+ }
+
+ /**
+ * Returns a predicate function that returns true when a specific character is found
+ * @param {string} character the character to use in the match function
+ * @returns {function} A function that checks if the last character of the parameter string matches the parameter character
+ */
+ function readUntil(character) {
+ return function (seen) {
+ return seen[seen.length - 1] === character;
+ };
+ }
+
+ function getRange(cm, start) {
+ var currentLine = start.line,
+ text = cm.getLine(currentLine) || "",
+ i = 0,
+ tagStack = [],
+ braceStack = [],
+ found,
+ openTag,
+ openPos,
+ currentCharacter,
+ openTagIndex = text.indexOf("{{"),
+ range;
+
+ if (openTagIndex < 0 || text[openTagIndex + 2] === "/") {
+ return;
+ }
+
+ found = scanTextUntil(cm, openTagIndex + 2, currentLine, endHelperName);
+ if (!found) {
+ return;
+ }
+
+ openPos = {
+ from: {line: currentLine, ch: openTagIndex},
+ to: found.to
+ };
+ openTag = found.string.substring(0, found.string.length - 1);
+ if (openTag[0] === "#" || openTag[0] === "~" || openTag[0] === "^") {
+ found = scanTextUntil(cm, openPos.to.ch, openPos.to.line, function (seen) {
+ return seen.length > 1 && seen.substr(-2) === "}}";
+ });
+ if (found) {
+ openPos.to = {line: found.to.line, ch: found.to.ch + 1};
+ }
+ tagStack.push(openTag.substr(1));
+ } else {
+ braceStack.push("{{");
+ }
+
+ i = found.to.ch;
+ currentLine = found.to.line;
+
+ while (currentLine <= cm.lastLine()) {
+ text = cm.getLine(currentLine);
+ currentCharacter = (text && text[i]) || "";
+ switch (currentCharacter) {
+ case "{":
+ if (text[i + 1] === "{") {
+ found = scanTextUntil(cm, i + 2, currentLine, endHelperName);
+ if (found) {
+ var tag = found.string.substring(0, found.string.length - 1);
+ if (tag[0] === "#" || tag[0] === "~" || tag[0] === "^") {
+ tagStack.push(tag.substr(1));
+ } else if (tag[0] === "/" &&
+ (_.last(tagStack) === tag.substr(1) || _.last(tagStack) === "*" + tag.substr(1))) {
+ tagStack.pop();
+ if (tagStack.length === 0 && braceStack.length === 0) {
+ range = {
+ from: openPos.to,
+ to: {ch: i, line: currentLine}
+ };
+ return range;
+ }
+ } else {
+ braceStack.push("{{");
+ }
+ }
+ }
+ break;
+ case "}":
+ if (text[i + 1] === "}") {
+ braceStack.pop();
+ if (braceStack.length === 0 && tagStack.length === 0) {
+ range = {
+ from: openPos.to,
+ to: {ch: i, line: currentLine}
+ };
+ return range;
+ }
+ }
+ break;
+ case "\"":
+ case "'":
+ found = scanTextUntil(cm, i + 1, currentLine, readUntil(text[i]));
+ if (found) {
+ i = found.to.ch;
+ currentLine = found.to.line;
+ }
+ break;
+ default:
+ break;
+ }
+
+ ++i;
+ if (i >= text.length) {
+ ++currentLine;
+ i = 0;
+ }
+ }
+ }
+
+ module.exports = getRange;
+});
diff --git a/src/extensions/default/CodeFolding/foldhelpers/indentFold.js b/src/extensions/default/CodeFolding/foldhelpers/indentFold.js
index 736a9df94ae..d2fa6f63cee 100644
--- a/src/extensions/default/CodeFolding/foldhelpers/indentFold.js
+++ b/src/extensions/default/CodeFolding/foldhelpers/indentFold.js
@@ -3,8 +3,6 @@
* @author Patrick Oladimeji
* @date 12/27/13 21:54:41 PM
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, brackets*/
define(function (require, exports, module) {
"use strict";
diff --git a/src/extensions/default/CodeFolding/main.js b/src/extensions/default/CodeFolding/main.js
index 3eb80dd8c32..bc224b32fe1 100644
--- a/src/extensions/default/CodeFolding/main.js
+++ b/src/extensions/default/CodeFolding/main.js
@@ -25,8 +25,7 @@
* @author Patrick Oladimeji
* @date 10/24/13 9:35:26 AM
*/
-/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, brackets*/
+
define(function (require, exports, module) {
"use strict";
@@ -69,6 +68,7 @@ define(function (require, exports, module) {
var foldGutter = require("foldhelpers/foldgutter"),
foldCode = require("foldhelpers/foldcode"),
indentFold = require("foldhelpers/indentFold"),
+ handlebarsFold = require("foldhelpers/handlebarsFold"),
selectionFold = require("foldhelpers/foldSelected");
@@ -394,8 +394,9 @@ define(function (require, exports, module) {
return prefs.getSetting("alwaysUseIndentFold");
}, indentFold);
- CodeMirror.registerHelper("fold", "django", CodeMirror.helpers.fold.brace);
- CodeMirror.registerHelper("fold", "tornado", CodeMirror.helpers.fold.brace);
+ CodeMirror.registerHelper("fold", "handlebars", handlebarsFold);
+ CodeMirror.registerHelper("fold", "htmlhandlebars", handlebarsFold);
+ CodeMirror.registerHelper("fold", "htmlmixed", handlebarsFold);
EditorManager.on("activeEditorChange.CodeFolding", onActiveEditorChanged);
DocumentManager.on("documentRefreshed.CodeFolding", function (event, doc) {
diff --git a/src/extensions/default/CodeFolding/unittest-files/test.hbs b/src/extensions/default/CodeFolding/unittest-files/test.hbs
new file mode 100644
index 00000000000..17181463dbf
--- /dev/null
+++ b/src/extensions/default/CodeFolding/unittest-files/test.hbs
@@ -0,0 +1,47 @@
+{{!--
+ comments
+ go
+ here
+--}}
+
+{{#test}}
+
+
+{{/test}}
+
+Comments
+
+
diff --git a/src/extensions/default/CodeFolding/unittest-files/test.html b/src/extensions/default/CodeFolding/unittest-files/test.html
new file mode 100644
index 00000000000..25f9d4232f1
--- /dev/null
+++ b/src/extensions/default/CodeFolding/unittest-files/test.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/extensions/default/CodeFolding/unittest-files/test.js b/src/extensions/default/CodeFolding/unittest-files/test.js
index f5e4bb4665c..e921abe57c0 100644
--- a/src/extensions/default/CodeFolding/unittest-files/test.js
+++ b/src/extensions/default/CodeFolding/unittest-files/test.js
@@ -1,33 +1,36 @@
/**
- * Synchronises the code folding states in the CM doc to cm._lineFolds cache.
- * When an undo operation is done, if folded code fragments are restored, then
- * we need to update cm._lineFolds with the fragments
- * @param {Object} cm cm the CodeMirror instance for the active editor
- * @param {Object} from starting position in the doc to sync the fold states from
- * @param {[[Type]]} lineAdded a number to show how many lines where added to the document
- */
- function syncDocToFoldsCache(cm, from, lineAdded) {
- var minFoldSize = prefs.getSetting("minFoldSize") || 2;
- var opts = cm.state.foldGutter.options || {};
- var rf = opts.rangeFinder || CodeMirror.fold.auto;
- var i, pos, folds, fold, range;
- if (lineAdded <= 0) {
- return;
- }
+ * Synchronises the code folding states in the CM doc to cm._lineFolds cache.
+ * When an undo operation is done, if folded code fragments are restored, then
+ * we need to update cm._lineFolds with the fragments
+ * @param {Object} cm cm the CodeMirror instance for the active editor
+ * @param {Object} from starting position in the doc to sync the fold states from
+ * @param {[[Type]]} lineAdded a number to show how many lines where added to the document
+*/
+/*global define, brackets, document, window, $, CodeMirror, isFold, prefs*/
+
+function syncDocToFoldsCache(cm, from, lineAdded) {
+ "use strict";
+ var minFoldSize = prefs.getSetting("minFoldSize") || 2;
+ var opts = cm.state.foldGutter.options || {};
+ var rf = opts.rangeFinder || CodeMirror.fold.auto;
+ var i, pos, folds, fold, range;
+ if (lineAdded <= 0) {
+ return;
+ }
- for (i = from; i <= from + lineAdded; i = i + 1) {
- pos = CodeMirror.Pos(i);
- folds = cm.doc.findMarksAt(pos).filter(isFold);
- fold = folds.length ? fold = folds[0] : undefined;
- if (fold) {
- range = rf(cm, CodeMirror.Pos(i));
- if (range && range.to.line - range.from.line >= minFoldSize) {
- cm._lineFolds[i] = range;
- i = range.to.line;
- } else {
- delete cm._lineFolds[i];
- }
+ for (i = from; i <= from + lineAdded; i = i + 1) {
+ pos = CodeMirror.Pos(i);
+ folds = cm.doc.findMarksAt(pos).filter(isFold);
+ fold = folds.length ? fold = folds[0] : undefined;
+ if (fold) {
+ range = rf(cm, CodeMirror.Pos(i));
+ if (range && range.to.line - range.from.line >= minFoldSize) {
+ cm._lineFolds[i] = range;
+ i = range.to.line;
+ } else {
+ delete cm._lineFolds[i];
}
}
-
}
+
+}
diff --git a/src/extensions/default/CodeFolding/unittests.js b/src/extensions/default/CodeFolding/unittests.js
index 6cddfe37b86..36b76713376 100644
--- a/src/extensions/default/CodeFolding/unittests.js
+++ b/src/extensions/default/CodeFolding/unittests.js
@@ -3,7 +3,9 @@
* @author Patrick Oladimeji
* @date 01/08/2015 18:34
*/
-/*global define, brackets, describe, beforeEach, afterEach, it, expect, runs, waitsForDone, waitsFor*/
+
+/*global describe, beforeEach, afterEach, it, expect, runs, waitsForDone, waitsFor*/
+
define(function (require, exports, module) {
"use strict";
var SpecRunnerUtils = brackets.getModule("spec/SpecRunnerUtils"),
@@ -22,10 +24,34 @@ define(function (require, exports, module) {
foldMarkerOpen = gutterName + "-open",
foldMarkerClosed = gutterName + "-folded";
var extensionPath = FileUtils.getNativeModuleDirectoryPath(module),
- testDocPath = extensionPath + "/unittest-files/",
- testFilePath = testDocPath + "test.js";
-
- var open = "open", folded = "folded";
+ testDocumentDirectory = extensionPath + "/unittest-files/",
+ // The line numbers referenced below are dependent on the files in /unittest-files directory.
+ // Remember to update the numbers if the files change.
+ testFilesSpec = {
+ js: {
+ filePath: testDocumentDirectory + "test.js",
+ foldableLines: [1, 11, 17, 21, 25, 27, 30],
+ sameLevelFoldableLines: [17, 21],
+ firstSelection: {start: {line: 2, ch: 0}, end: {line: 10, ch: 0}},
+ secondSelection: {start: {line: 5, ch: 0}, end: {line: 8, ch: 4}}
+ },
+ html: {
+ filePath: testDocumentDirectory + "test.html",
+ foldableLines: [1, 2, 5, 7, 8, 12, 13, 14, 18, 19, 24, 27],
+ sameLevelFoldableLines: [8, 24],
+ firstSelection: {start: {line: 3, ch: 0}, end: {line: 10, ch: 0}},
+ secondSelection: {start: {line: 6, ch: 0}, end: {line: 17, ch: 4}}
+ },
+ hbs: {
+ filePath: testDocumentDirectory + "test.hbs",
+ foldableLines: [1, 7, 14, 16, 17, 21, 26, 28, 29, 32, 33, 38, 41],
+ sameLevelFoldableLines: [1, 7, 14],
+ firstSelection: {start: {line: 2, ch: 0}, end: {line: 10, ch: 0}},
+ secondSelection: {start: {line: 5, ch: 0}, end: {line: 8, ch: 4}}
+ }
+ },
+ open = "open",
+ folded = "folded";
/**
* Utility to temporarily set preference values in the session scope
@@ -69,7 +95,7 @@ define(function (require, exports, module) {
runs(function () {
//setPreference("saveFoldStates", false);
- SpecRunnerUtils.loadProjectInTestWindow(testDocPath);
+ SpecRunnerUtils.loadProjectInTestWindow(testDocumentDirectory);
});
}
@@ -94,7 +120,7 @@ define(function (require, exports, module) {
* @param {Number} line The line number to fold
*/
function foldCodeOnLine(line) {
- cm.setCursor(line);
+ cm.setCursor(line - 1);
var promise = runCommand("codefolding.collapse");
waitsForDone(promise, "Collapse code", 2000);
}
@@ -104,7 +130,7 @@ define(function (require, exports, module) {
* @param {Number} line The line number to fold
*/
function expandCodeOnLine(line) {
- cm.setCursor(line);
+ cm.setCursor(line - 1);
var promise = runCommand("codefolding.expand");
waitsForDone(promise, "Expand code", 2000);
}
@@ -129,6 +155,9 @@ define(function (require, exports, module) {
* @returns {Object} an object with line and type property
*/
function gutterMarkState(lineInfo) {
+ if (!lineInfo || !lineInfo.gutterMarkers) {
+ return;
+ }
var classes = lineInfo.gutterMarkers[gutterName].classList;
if (classes && classes.contains(foldMarkerClosed)) {
return {line: lineInfo.line, type: folded};
@@ -141,7 +170,7 @@ define(function (require, exports, module) {
/**
* Helper function to return the fold markers on the current codeMirror instance
*
- * @returns {[[Type]]} [[Description]]
+ * @returns {Array
{{title}}
+