diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c465ab7c1..94c957ba3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,9 @@ propose changes to this document in a pull request. ## Submitting Issues +* Check the [debugging guide](https://atom.io/docs/latest/debugging) for tips + on debugging. You might be able to find the cause of the problem and fix + things yourself. * Include the version of Atom you are using and the OS. * Include screenshots and animated GIFs whenever possible; they are immensely helpful. diff --git a/build/tasks/build-task.coffee b/build/tasks/build-task.coffee index e4ff2578c..1484b6a07 100644 --- a/build/tasks/build-task.coffee +++ b/build/tasks/build-task.coffee @@ -1,5 +1,6 @@ fs = require 'fs' path = require 'path' +_ = require 'underscore-plus' module.exports = (grunt) -> {cp, isAtomPackage, mkdir, rm} = require('./task-helpers')(grunt) @@ -48,16 +49,22 @@ module.exports = (grunt) -> path.join('bootstrap', 'docs') path.join('bootstrap', 'examples') path.join('pegjs', 'examples') - # Add .* to avoid matching hunspell_dictionaries. - path.join('spellchecker', 'vendor', 'hunspell', '.*') + path.join('plist', 'tests') path.join('xmldom', 'test') path.join('jasmine-reporters', 'ext') path.join('build', 'Release', 'obj.target') + path.join('build', 'Release', 'obj') path.join('build', 'Release', '.deps') path.join('vendor', 'apm') path.join('resources', 'mac') path.join('resources', 'win') ] + ignoredPaths = ignoredPaths.map (ignoredPath) -> _.escapeRegExp(ignoredPath) + + # Add .* to avoid matching hunspell_dictionaries. + ignoredPaths.push "#{_.escapeRegExp(path.join('spellchecker', 'vendor', 'hunspell') + path.sep)}.*" + ignoredPaths.push "#{_.escapeRegExp(path.join('build', 'Release') + path.sep)}.*\\.pdb" + # Hunspell dictionaries are only not needed on OS X. if process.platform is 'darwin' ignoredPaths.push path.join('spellchecker', 'vendor', 'hunspell_dictionaries') diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index 0707a2c66..5c1c5abc8 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -8,11 +8,17 @@ GitHub = require 'github-releases' request = require 'request' grunt = null -maxReleases = 10 -assets = [ - {assetName: 'atom-mac.zip', sourceName: 'Atom.app'} - {assetName: 'atom-mac-symbols.zip', sourceName: 'Atom.breakpad.syms'} -] + +if process.platform is 'darwin' + assets = [ + {assetName: 'atom-mac.zip', sourceName: 'Atom.app'} + {assetName: 'atom-mac-symbols.zip', sourceName: 'Atom.breakpad.syms'} + ] +else + assets = [ + {assetName: 'atom-windows.zip', sourceName: 'Atom'} + ] + commitSha = process.env.JANKY_SHA1 token = process.env.ATOM_ACCESS_TOKEN defaultHeaders = @@ -23,7 +29,6 @@ module.exports = (gruntObject) -> grunt = gruntObject grunt.registerTask 'publish-build', 'Publish the built app', -> - return unless process.platform is 'darwin' return if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH isnt 'master' done = @async() @@ -45,10 +50,13 @@ logError = (message, error, details) -> zipApps = (buildDir, assets, callback) -> zip = (directory, sourceName, assetName, callback) -> + if process.platform is 'win32' + zipCommand = "C:/psmodules/7z.exe a -r #{assetName} #{sourceName}" + else + zipCommand = "zip -r --symlinks #{assetName} #{sourceName}" options = {cwd: directory, maxBuffer: Infinity} - child_process.exec "zip -r --symlinks #{assetName} #{sourceName}", options, (error, stdout, stderr) -> - if error? - logError("Zipping #{sourceName} failed", error, stderr) + child_process.exec zipCommand, options, (error, stdout, stderr) -> + logError("Zipping #{sourceName} failed", error, stderr) if error? callback(error) tasks = [] diff --git a/docs/build-instructions/linux.md b/docs/build-instructions/linux.md index 68f0374de..16f135b11 100644 --- a/docs/build-instructions/linux.md +++ b/docs/build-instructions/linux.md @@ -7,6 +7,7 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. * OS with 64-bit or 32-bit architecture * C++ toolchain * on Ubuntu/Debian: `sudo apt-get install build-essential` + * on Fedora: `sudo yum --assumeyes install make gcc gcc-c++ glibc-devel` * [node.js](http://nodejs.org/download/) v0.10.x * [Ubuntu/Debian/Mint instructions](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os) * [Fedora instructions](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#fedora) @@ -20,6 +21,9 @@ Ubuntu LTS 12.04 64-bit is the recommended platform. * `npm config set python /usr/bin/python2 -g` to ensure that gyp uses Python 2 * This command may require `sudo` depending on how you have [configured npm](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os). + * Git + * on Ubuntu/Debian: `sudo apt-get install git` + * on Fedora: `sudo yum install git-core` ## Instructions diff --git a/docs/build-instructions/windows.md b/docs/build-instructions/windows.md index f60cbea7a..41b9b12dc 100644 --- a/docs/build-instructions/windows.md +++ b/docs/build-instructions/windows.md @@ -51,5 +51,13 @@ fix this, you probably need to fiddle with your system PATH. * Try moving the repository to `C:\atom`. Most likely, the path is too long. See [issue #2200](https://github.com/atom/atom/issues/2200). +* `error MSB4025: The project file could not be loaded. Invalid character in the given encoding.` + + * These can occur because your home directory (`%USERPROFILE%`) has non-ASCII + characters in it. This is a bug in [gyp](https://code.google.com/p/gyp/) + which is used to build native node modules and there is no known workaround. + * https://github.com/TooTallNate/node-gyp/issues/297 + * https://code.google.com/p/gyp/issues/detail?id=393 + ### Windows build error reports in atom/atom * Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Awindows&type=Issues) to get a list of reports about build errors on Windows. diff --git a/docs/debugging.md b/docs/debugging.md index 2b81acd20..0070de61d 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -1,6 +1,13 @@ # Debugging -Atom provides several tools to help you understand unexpected behavior and debug problems. This guide describes some of those tools and a few approaches to help you debug and provide more helpful information when [submitting issues]. +Atom provides several tools to help you understand unexpected behavior and debug problems. This guide describes some of those tools and a few approaches to help you debug and provide more helpful information when [submitting issues]: + +* [Update to the latest version](#update-to-the-latest-version) +* [Check Atom and package settings](#check-atom-and-package-settings) +* [Check the keybindings](#check-the-keybindings) +* [Check if the problem shows up in safe mode](#check-if-the-problem-shows-up-in-safe-mode) +* [Check your config files](#check-your-config-files) +* [Check for errors in the developer tools](#check-for-errors-in-the-developer-tools) ## Update to the latest version diff --git a/menus/darwin.cson b/menus/darwin.cson index 0f8b3ad10..647f20d6a 100644 --- a/menus/darwin.cson +++ b/menus/darwin.cson @@ -109,6 +109,7 @@ submenu: [ { label: 'Add Selection Above', command: 'editor:add-selection-above' } { label: 'Add Selection Below', command: 'editor:add-selection-below' } + { label: 'Single Selection', command: 'editor:consolidate-selections'} { label: 'Split into Lines', command: 'editor:split-selections-into-lines'} { type: 'separator' } { label: 'Select to Top', command: 'core:select-to-top' } diff --git a/menus/linux.cson b/menus/linux.cson index abdebf11c..850b25d91 100644 --- a/menus/linux.cson +++ b/menus/linux.cson @@ -108,6 +108,7 @@ { label: 'Add Selection &Above', command: 'editor:add-selection-above' } { label: 'Add Selection &Below', command: 'editor:add-selection-below' } { label: 'S&plit into Lines', command: 'editor:split-selections-into-lines'} + { label: 'Single Selection', command: 'editor:consolidate-selections'} { type: 'separator' } { label: 'Select to &Top', command: 'core:select-to-top' } { label: 'Select to Botto&m', command: 'core:select-to-bottom' } diff --git a/menus/win32.cson b/menus/win32.cson index d8a343a6c..6f43528bf 100644 --- a/menus/win32.cson +++ b/menus/win32.cson @@ -127,6 +127,7 @@ { label: 'Add Selection &Above', command: 'editor:add-selection-above' } { label: 'Add Selection &Below', command: 'editor:add-selection-below' } { label: 'S&plit into Lines', command: 'editor:split-selections-into-lines'} + { label: 'Single Selection', command: 'editor:consolidate-selections'} { type: 'separator' } { label: 'Select to &Top', command: 'core:select-to-top' } { label: 'Select to Botto&m', command: 'core:select-to-bottom' } diff --git a/package.json b/package.json index e823ee917..cc6c78a3c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "0.104.0", + "version": "0.105.0", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { @@ -17,7 +17,7 @@ "url": "http://github.com/atom/atom/raw/master/LICENSE.md" } ], - "atomShellVersion": "0.13.0", + "atomShellVersion": "0.13.1", "dependencies": { "async": "0.2.6", "atom-keymap": "^0.27.0", @@ -48,14 +48,14 @@ "react-atom-fork": "^0.10.0", "reactionary-atom-fork": "^0.9.0", "runas": "^0.5", - "scandal": "0.15.2", + "scandal": "0.15.3", "scoped-property-store": "^0.9.0", "scrollbar-style": "^0.4.0", "season": "^1.0.2", "semver": "1.1.4", "serializable": "^1", "space-pen": "3.2.0", - "temp": "0.5.0", + "temp": "0.7.0", "text-buffer": "^2.3.0", "theorist": "^1", "underscore-plus": "^1.4.1", @@ -74,8 +74,8 @@ "autoflow": "0.17.0", "autosave": "0.14.0", "background-tips": "0.14.0", - "bookmarks": "0.24.0", - "bracket-matcher": "0.45.0", + "bookmarks": "0.25.0", + "bracket-matcher": "0.47.0", "command-palette": "0.22.0", "deprecation-cop": "0.7.0", "dev-live-reload": "0.31.0", @@ -89,25 +89,25 @@ "image-view": "0.35.0", "keybinding-resolver": "0.18.0", "link": "0.22.0", - "markdown-preview": "0.76.0", + "markdown-preview": "0.82.0", "metrics": "0.32.0", "open-on-github": "0.28.0", - "package-generator": "0.30.0", + "package-generator": "0.31.0", "release-notes": "0.32.0", - "settings-view": "0.121.0", + "settings-view": "0.127.0", "snippets": "0.45.0", "spell-check": "0.37.0", "status-bar": "0.40.0", "styleguide": "0.29.0", - "symbols-view": "0.55.0", + "symbols-view": "0.56.0", "tabs": "0.41.0", "timecop": "0.19.0", - "tree-view": "0.100.0", + "tree-view": "0.103.0", "update-package-dependencies": "0.6.0", "welcome": "0.16.0", "whitespace": "0.22.0", "wrap-guide": "0.18.0", - "language-c": "0.17.0", + "language-c": "0.18.0", "language-coffee-script": "0.22.0", "language-css": "0.17.0", "language-gfm": "0.39.0", @@ -125,7 +125,7 @@ "language-php": "0.15.0", "language-property-list": "0.7.0", "language-python": "0.18.0", - "language-ruby": "0.27.0", + "language-ruby": "0.29.0", "language-ruby-on-rails": "0.14.0", "language-sass": "0.13.0", "language-shellscript": "0.8.0", @@ -135,7 +135,7 @@ "language-todo": "0.10.0", "language-toml": "0.12.0", "language-xml": "0.14.0", - "language-yaml": "0.6.0" + "language-yaml": "0.7.0" }, "private": true, "scripts": { diff --git a/script/bootstrap b/script/bootstrap index 89890bc18..250041b53 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -10,6 +10,8 @@ function executeCommands(commands, done, index) { index = (index == undefined ? 0 : index); if (index < commands.length) { var command = commands[index]; + if (command.message) + console.log(command.message); var options = null; if (typeof command !== 'string') { options = command.options; @@ -36,12 +38,10 @@ function bootstrap() { var npmFlags = ' --userconfig=' + path.resolve('.npmrc') + ' '; var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'season', 'grim']; - var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo'; var commands = [ - {command: initialNpmCommand + npmFlags + 'install --quiet', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}}, - {command: npmPath + npmFlags + 'install --quiet', options: {cwd: apmInstallPath, ignoreStdout: true}}, - echoNewLine, + {command: initialNpmCommand + npmFlags + 'install --quiet', message: 'Installing build modules...', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}}, + {command: npmPath + npmFlags + 'install --quiet', message: 'Installing apm...', options: {cwd: apmInstallPath, ignoreStdout: true}}, apmPath + ' clean ' + apmFlags, apmPath + ' install --quiet ' + apmFlags, apmPath + ' dedupe --quiet ' + apmFlags + ' ' + packagesToDedupe.join(' '), diff --git a/script/cibuild b/script/cibuild index c5347df45..6e76d8831 100755 --- a/script/cibuild +++ b/script/cibuild @@ -19,12 +19,18 @@ function loadEnvironmentVariables(filePath) { var value = parts[1].trim().substr(1, parts[1].length - 2); process.env[key] = value; } - } catch(error) { } + } catch(error) { + console.error("Failed to load environment variables: " + filePath, error.code); + } } function readEnvironmentVariables() { - loadEnvironmentVariables('/var/lib/jenkins/config/atomcredentials') - loadEnvironmentVariables('/var/lib/jenkins/config/xcodekeychain') + if (process.platform === 'win32') + loadEnvironmentVariables(path.resolve('/jenkins/config/atomcredentials')); + else { + loadEnvironmentVariables('/var/lib/jenkins/config/atomcredentials'); + loadEnvironmentVariables('/var/lib/jenkins/config/xcodekeychain'); + } } readEnvironmentVariables(); diff --git a/spec/atom-reporter.coffee b/spec/atom-reporter.coffee index ac1c9b98c..0497f35a3 100644 --- a/spec/atom-reporter.coffee +++ b/spec/atom-reporter.coffee @@ -2,6 +2,7 @@ path = require 'path' _ = require 'underscore-plus' {convertStackTrace} = require 'coffeestack' {View, $, $$} = require '../src/space-pen-extensions' +grim = require 'grim' sourceMaps = {} formatStackTrace = (spec, message='', stackTrace) -> @@ -52,6 +53,11 @@ class AtomReporter extends View @div outlet: "message", class: 'message' @div outlet: "results", class: 'results' + @div outlet: "deprecations", class: 'status alert alert-warning', style: 'display: none', => + @span outlet: 'deprecationStatus', '0 deprecations' + @div class: 'deprecation-toggle' + @div outlet: 'deprecationList', class: 'deprecation-list' + startedAt: null runningSpecCount: 0 completeSpecCount: 0 @@ -59,6 +65,7 @@ class AtomReporter extends View failedCount: 0 skippedCount: 0 totalSpecCount: 0 + deprecationCount: 0 @timeoutId: 0 reportRunnerStarting: (runner) -> @@ -88,6 +95,29 @@ class AtomReporter extends View reportSpecStarting: (spec) -> @specStarted(spec) + addDeprecations: (spec) -> + deprecations = grim.getDeprecations() + @deprecationCount += deprecations.length + @deprecations.show() if @deprecationCount > 0 + if @deprecationCount is 1 + @deprecationStatus.text("1 deprecation") + else + @deprecationStatus.text("#{@deprecationCount} deprecations") + + for deprecation in deprecations + @deprecationList.append $$ -> + @div class: 'padded', => + @div class: 'result-message fail deprecation-message', deprecation.message + + for stack in deprecation.stacks + fullStack = stack.map ({functionName, location}) -> + if functionName is '' + " at #{location}" + else + " at #{functionName} (#{location})" + @pre class: 'stack-trace padded', formatStackTrace(spec, deprecation.message, fullStack.join('\n')) + grim.clearDeprecations() + handleEvents: -> $(document).on "click", ".spec-toggle", ({currentTarget}) => element = $(currentTarget) @@ -96,6 +126,13 @@ class AtomReporter extends View element.toggleClass('folded') false + $(document).on "click", ".deprecation-toggle", ({currentTarget}) => + element = $(currentTarget) + deprecationList = $(document).find('.deprecation-list') + deprecationList.toggle() + element.toggleClass('folded') + false + updateSpecCounts: -> if @skippedCount specCount = "#{@completeSpecCount - @skippedCount}/#{@totalSpecCount - @skippedCount} (#{@skippedCount} skipped)" @@ -175,6 +212,7 @@ class AtomReporter extends View specView = new SpecResultView(spec) specView.attach() @failedCount++ + @addDeprecations(spec) class SuiteResultView extends View @content: -> diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index 7a5d4ced0..c0cb73e74 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -1199,28 +1199,31 @@ describe "EditorComponent", -> beforeEach -> inputNode = node.querySelector('.hidden-input') + buildTextInputEvent = ({data, target}) -> + event = new Event('textInput') + event.data = data + Object.defineProperty(event, 'target', get: -> target) + event + it "inserts the newest character in the input's value into the buffer", -> - inputNode.value = 'x' - inputNode.dispatchEvent(new Event('input')) + node.dispatchEvent(buildTextInputEvent(data: 'x', target: inputNode)) expect(editor.lineForBufferRow(0)).toBe 'xvar quicksort = function () {' - inputNode.value = 'xy' - inputNode.dispatchEvent(new Event('input')) + node.dispatchEvent(buildTextInputEvent(data: 'y', target: inputNode)) expect(editor.lineForBufferRow(0)).toBe 'xyvar quicksort = function () {' it "replaces the last character if the length of the input's value doesn't increase, as occurs with the accented character menu", -> - inputNode.value = 'u' - inputNode.dispatchEvent(new Event('input')) + node.dispatchEvent(buildTextInputEvent(data: 'u', target: inputNode)) expect(editor.lineForBufferRow(0)).toBe 'uvar quicksort = function () {' - inputNode.value = 'ü' - inputNode.dispatchEvent(new Event('input')) + # simulate the accented character suggestion's selection of the previous character + inputNode.setSelectionRange(0, 1) + node.dispatchEvent(buildTextInputEvent(data: 'ü', target: inputNode)) expect(editor.lineForBufferRow(0)).toBe 'üvar quicksort = function () {' it "does not handle input events when input is disabled", -> component.setInputEnabled(false) - inputNode.value = 'x' - inputNode.dispatchEvent(new Event('input')) + node.dispatchEvent(buildTextInputEvent(data: 'x', target: inputNode)) expect(editor.lineForBufferRow(0)).toBe 'var quicksort = function () {' describe "commands", -> diff --git a/src/cursor.coffee b/src/cursor.coffee index df9e5e06b..08e8f7e94 100644 --- a/src/cursor.coffee +++ b/src/cursor.coffee @@ -114,9 +114,10 @@ class Cursor extends Model # Public: Get the RegExp used by the cursor to determine what a "word" is. # - # options: An {Object} with the following keys: + # options: An optional {Object} with the following keys: # :includeNonWordCharacters - A {Boolean} indicating whether to include # non-word characters in the regex. + # (default: true) # # Returns a {RegExp}. wordRegExp: ({includeNonWordCharacters}={})-> diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 64b94aa82..0fe763a06 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -84,7 +84,6 @@ EditorComponent = React.createClass ref: 'input' className: 'hidden-input' style: hiddenInputStyle - onInput: @onInput onFocus: @onInputFocused onBlur: @onInputBlurred @@ -268,6 +267,7 @@ EditorComponent = React.createClass node = @getDOMNode() node.addEventListener 'mousewheel', @onMouseWheel node.addEventListener 'focus', @onFocus # For some reason, React's built in focus events seem to bubble + node.addEventListener 'textInput', @onTextInput scrollViewNode = @refs.scrollView.getDOMNode() scrollViewNode.addEventListener 'scroll', @onScrollViewScroll @@ -393,6 +393,26 @@ EditorComponent = React.createClass onFocus: -> @refs.input.focus() + onTextInput: (event) -> + return unless @isInputEnabled() + + {editor} = @props + inputNode = event.target + + # Work around of the accented character suggestion feature in OS X. + # Text input fires before a character is inserted, and if the browser is + # replacing the previous un-accented character with an accented variant, it + # will select backward over it. + selectedLength = inputNode.selectionEnd - inputNode.selectionStart + editor.selectLeft() if selectedLength is 1 + + editor.insertText(event.data) + inputNode.value = event.data + + # If we prevent the insertion of a space character, then the browser + # interprets the spacebar keypress as a page-down command. + event.preventDefault() unless event.data is ' ' + onInputFocused: -> @setState(focused: true) @@ -453,19 +473,9 @@ EditorComponent = React.createClass scrollViewNode.scrollTop = 0 scrollViewNode.scrollLeft = 0 - onInput: (char, replaceLastCharacter) -> - return unless @inputEnabled - - {editor} = @props - - if replaceLastCharacter - editor.transact -> - editor.selectLeft() - editor.insertText(char) - else - editor.insertText(char) - onMouseDown: (event) -> + return unless event.button is 0 # only handle the left mouse button + {editor} = @props {detail, shiftKey, metaKey} = event screenPosition = @screenPositionForMouseEvent(event) diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 53b05ab56..7d05b229c 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -368,6 +368,8 @@ class EditorView extends View false if @isFocused @overlayer.on 'mousedown', (e) => + return unless e.which is 1 # only handle the left mouse button + @overlayer.hide() clickedElement = document.elementFromPoint(e.pageX, e.pageY) @overlayer.show() @@ -567,7 +569,7 @@ class EditorView extends View @scrollTop(scrollTop) @subscribe @editor, 'scroll-left-changed', (scrollLeft) => - @scrollLeft(scrollLeft) + @scrollView.scrollLeft(scrollLeft) @subscribe @editor, 'soft-wrap-changed', (softWrap) => @setSoftWrap(softWrap) diff --git a/src/input-component.coffee b/src/input-component.coffee index 372bccf9c..230c4be37 100644 --- a/src/input-component.coffee +++ b/src/input-component.coffee @@ -1,4 +1,3 @@ -punycode = require 'punycode' {last, isEqual} = require 'underscore-plus' React = require 'react-atom-fork' {input} = require 'reactionary-atom-fork' @@ -17,7 +16,6 @@ InputComponent = React.createClass componentDidMount: -> @getDOMNode().addEventListener 'paste', @onPaste - @getDOMNode().addEventListener 'input', @onInput @getDOMNode().addEventListener 'compositionupdate', @onCompositionUpdate # Don't let text accumulate in the input forever, but avoid excessive reflows @@ -36,15 +34,6 @@ InputComponent = React.createClass onPaste: (e) -> e.preventDefault() - onInput: (e) -> - e.stopPropagation() - valueCharCodes = punycode.ucs2.decode(@getDOMNode().value) - valueLength = valueCharCodes.length - replaceLastChar = valueLength is @lastValueLength - @lastValueLength = valueLength - lastChar = String.fromCharCode(last(valueCharCodes)) - @props.onInput?(lastChar, replaceLastChar) - onFocus: -> @props.onFocus?() diff --git a/static/jasmine.less b/static/jasmine.less index 9207dff7c..23efbf15c 100644 --- a/static/jasmine.less +++ b/static/jasmine.less @@ -135,6 +135,10 @@ body { padding: 5px 0 5px 0; } + .result-message.deprecation-message { + color: #f0ad4e; + } + .stack-trace { font-size: 12px; margin: 5px 0 0 0; @@ -174,4 +178,24 @@ body { // overflow: hidden; } } + + .deprecation-toggle { + .octicon(fold); + float: right; + cursor: pointer; + opacity: 0; + color: #999; + + &.folded { + .octicon(unfold); + } + } + + .deprecation-toggle:hover { + color: #333; + } + + &:hover .deprecation-toggle { + opacity: 1; + } }