diff --git a/services/web/app/coffee/Features/Blog/BlogController.coffee b/services/web/app/coffee/Features/Blog/BlogController.coffee index 186d11d348..8f726602c3 100644 --- a/services/web/app/coffee/Features/Blog/BlogController.coffee +++ b/services/web/app/coffee/Features/Blog/BlogController.coffee @@ -4,15 +4,13 @@ logger = require("logger-sharelatex") _ = require("underscore") ErrorController = require "../Errors/ErrorController" -extensionsToProxy = [".png", ".xml", ".jpeg", ".json", ".zip", ".eps"] - module.exports = BlogController = getPage: (req, res, next)-> url = req.url?.toLowerCase() blogUrl = "#{settings.apis.blog.url}#{url}" - extensionsToProxy = [".png", ".xml", ".jpeg", ".json", ".zip", ".eps"] + extensionsToProxy = [".png", ".xml", ".jpeg", ".json", ".zip", ".eps", ".gif"] shouldProxy = _.find extensionsToProxy, (extension)-> url.indexOf(extension) != -1 diff --git a/services/web/app/views/project/editor/editor.jade b/services/web/app/views/project/editor/editor.jade index 59399e2aae..f79f6e3c19 100644 --- a/services/web/app/views/project/editor/editor.jade +++ b/services/web/app/views/project/editor/editor.jade @@ -20,6 +20,7 @@ div.full-size( keybindings="settings.mode", font-size="settings.fontSize", auto-complete="settings.autoComplete", + spell-check="true", spell-check-language="project.spellCheckLanguage", highlights="onlineUserCursorHighlights[editor.open_doc_id]" show-print-margin="false", diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee index ba9d69be47..596f350812 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee @@ -18,7 +18,7 @@ define [ url = ace.config._moduleUrl(args...) + "?fingerprint=#{window.aceFingerprint}" return url - App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage) -> + App.directive "aceEditor", ($timeout, $compile, $rootScope, event_tracking, localStorage, $cacheFactory) -> monkeyPatchSearch($rootScope, $compile) return { @@ -29,6 +29,7 @@ define [ fontSize: "=" autoComplete: "=" sharejsDoc: "=" + spellCheck: "=" spellCheckLanguage: "=" highlights: "=" text: "=" @@ -55,7 +56,9 @@ define [ scope.name = attrs.aceEditor autoCompleteManager = new AutoCompleteManager(scope, editor, element) - spellCheckManager = new SpellCheckManager(scope, editor, element) + if scope.spellCheck # only enable spellcheck when explicitly required + spellCheckCache = $cacheFactory("spellCheck-#{scope.name}", {capacity: 1000}) + spellCheckManager = new SpellCheckManager(scope, editor, element, spellCheckCache) undoManager = new UndoManager(scope, editor, element) highlightsManager = new HighlightsManager(scope, editor, element) cursorPositionManager = new CursorPositionManager(scope, editor, element, localStorage) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee index 68d45ac6e8..95a6519d59 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee @@ -5,7 +5,7 @@ define [ Range = ace.require("ace/range").Range class SpellCheckManager - constructor: (@$scope, @editor, @element) -> + constructor: (@$scope, @editor, @element, @cache) -> $(document.body).append @element.find(".spell-check-menu") @updatedLines = [] @@ -102,6 +102,8 @@ define [ learnWord: (highlight) -> @apiRequest "/learn", word: highlight.word @highlightedWordManager.removeWord highlight.word + language = @$scope.spellCheckLanguage + @cache?.put("#{language}:#{highlight.word}", true) getHighlightedWordAtCursor: () -> cursor = @editor.getCursorPosition() @@ -143,24 +145,67 @@ define [ runSpellCheck: (linesToProcess) -> {words, positions} = @getWords(linesToProcess) language = @$scope.spellCheckLanguage - @apiRequest "/check", {language: language, words: words}, (error, result) => - if error? or !result? or !result.misspellings? - return null + highlights = [] + seen = {} + newWords = [] + newPositions = [] + + # iterate through all words, building up a list of + # newWords/newPositions not in the cache + for word, i in words + key = "#{language}:#{word}" + seen[key] ?= @cache.get(key) # avoid hitting the cache unnecessarily + cached = seen[key] + if not cached? + newWords.push words[i] + newPositions.push positions[i] + else if cached is true + # word is correct + else + highlights.push + column: positions[i].column + row: positions[i].row + word: word + suggestions: cached + words = newWords + positions = newPositions + + displayResult = (highlights) => if linesToProcess? for shouldProcess, row in linesToProcess @highlightedWordManager.clearRows(row, row) if shouldProcess else @highlightedWordManager.clearRows() + for highlight in highlights + @highlightedWordManager.addHighlight highlight - for misspelling in result.misspellings - word = words[misspelling.index] - position = positions[misspelling.index] - @highlightedWordManager.addHighlight - column: position.column - row: position.row - word: word - suggestions: misspelling.suggestions + if not words.length + displayResult highlights + else + @apiRequest "/check", {language: language, words: words}, (error, result) => + if error? or !result? or !result.misspellings? + return null + mispelled = [] + for misspelling in result.misspellings + word = words[misspelling.index] + position = positions[misspelling.index] + mispelled[misspelling.index] = true + highlights.push + column: position.column + row: position.row + word: word + suggestions: misspelling.suggestions + key = "#{language}:#{word}" + if not seen[key] + @cache.put key, misspelling.suggestions + seen[key] = true + for word, i in words when not mispelled[i] + key = "#{language}:#{word}" + if not seen[key] + @cache.put(key, true) + seen[key] = true + displayResult highlights getWords: (linesToProcess) -> lines = @editor.getValue().split("\n") diff --git a/services/web/public/stylesheets/app/editor.less b/services/web/public/stylesheets/app/editor.less index 26fbadf369..153ea19fca 100644 --- a/services/web/public/stylesheets/app/editor.less +++ b/services/web/public/stylesheets/app/editor.less @@ -252,6 +252,20 @@ margin-bottom:0px; } +.sl_references_search_hint { + position: absolute; + bottom: -22px; + left: -1px; + right: 0px; + text-align: center; + padding: 2px; + background: rgb(202, 214, 250); + border: 1px solid lightgray; + box-shadow: 3px 3px 5px rgba(0,0,0,.2); + span { + color: black; + } +} // -- References Search Modal -- .references-search-modal-backdrop { // don't grey out the editor when the @@ -320,6 +334,9 @@ .hit-year.small { color: white; } + .hit-journal.small { + color: white; + } } .hit-title { font-size: 1.3em;