diff --git a/build/resources/asar-ordering-hint.txt b/build/resources/asar-ordering-hint.txt
index fcf891f41..40c896989 100644
--- a/build/resources/asar-ordering-hint.txt
+++ b/build/resources/asar-ordering-hint.txt
@@ -3094,7 +3094,6 @@
2998273: node_modules/theorist/lib/sequence.js
3004878: node_modules/coffeestack/index.js
3010047: src/window-event-handler.js
-3033233: node_modules/space-pen/lib/space-pen.js
3054355: src/styles-element.js
1995661: src/flux/models/utils.js
3061775: src/flux/errors.js
@@ -4562,7 +4561,6 @@
2998273: node_modules/theorist/lib/sequence.js
3004878: node_modules/coffeestack/index.js
3010047: src/window-event-handler.js
-3033233: node_modules/space-pen/lib/space-pen.js
3054355: src/styles-element.js
1995661: src/flux/models/utils.js
3061775: src/flux/errors.js
diff --git a/build/tasks/docs-build-task.coffee b/build/tasks/docs-build-task.coffee
index 91efeb608..aa5305230 100644
--- a/build/tasks/docs-build-task.coffee
+++ b/build/tasks/docs-build-task.coffee
@@ -8,10 +8,6 @@ _ = require 'underscore'
donna = require 'donna'
tello = require 'tello'
-moduleBlacklist = [
- 'space-pen'
-]
-
module.exports = (grunt) ->
{cp, mkdir, rm} = require('./task-helpers')(grunt)
@@ -23,7 +19,6 @@ module.exports = (grunt) ->
return false if modulePath.match(/node_modules/g)
# Don't traverse blacklisted packages (that have docs, but we don't want to include)
- return false if path.basename(modulePath) in moduleBlacklist
return true unless path.basename(modulePath) is 'package.json'
return true unless fs.isFileSync(modulePath)
diff --git a/package.json b/package.json
index a048912fc..e43f577bd 100644
--- a/package.json
+++ b/package.json
@@ -67,7 +67,6 @@
"season": "^5.1",
"semver": "^4.2",
"source-map-support": "^0.3.2",
- "space-pen": "3.8.2",
"spellchecker": "3.2.3",
"temp": "^0.8",
"underscore": "^1.8",
diff --git a/spec/jasmine-helper.coffee b/spec/jasmine-helper.coffee
index 9612c154e..97c397f9b 100644
--- a/spec/jasmine-helper.coffee
+++ b/spec/jasmine-helper.coffee
@@ -2,8 +2,6 @@ fs = require 'fs'
{remote} = require 'electron'
module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
- {$, $$} = require '../src/space-pen-extensions'
-
window[key] = value for key, value of require './jasmine'
{TerminalReporter} = require 'jasmine-tagged'
@@ -21,8 +19,7 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
remote.process.stdout.write(str)
if NylasEnv.getLoadSettings().showSpecsInWindow
- N1SpecReporter = require './n1-spec-reporter'
- reporter = new N1SpecReporter()
+ reporter = require './n1-spec-reporter'
else if NylasEnv.getLoadSettings().exitWhenDone
reporter = new TerminalReporter
color: true
@@ -38,8 +35,7 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
else
NylasEnv.exit(0)
else
- N1SpecReporter = require './n1-spec-reporter'
- reporter = new N1SpecReporter()
+ reporter = require './n1-spec-reporter'
NylasEnv.initialize()
@@ -50,7 +46,9 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
jasmineEnv.addReporter(timeReporter)
jasmineEnv.setIncludedTags([process.platform])
- $('body').append $$ -> @div id: 'jasmine-content'
+ div = document.createElement('div')
+ div.id = 'jasmine-content'
+ document.body.appendChild(div)
jasmineEnv.execute()
diff --git a/spec/jasmine-jquery.js b/spec/jasmine-jquery.js
deleted file mode 100644
index ef2731784..000000000
--- a/spec/jasmine-jquery.js
+++ /dev/null
@@ -1,181 +0,0 @@
-(function(jQuery) {
-
-jasmine.JQuery = function() {};
-
-jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
- return jQuery('
').append(html).html();
-};
-
-jasmine.JQuery.elementToString = function(element) {
- return jQuery('').append(element.clone()).html();
-};
-
-jasmine.JQuery.matchersClass = {};
-
-(function(namespace) {
- var data = {
- spiedEvents: {},
- handlers: []
- };
-
- namespace.events = {
- spyOn: function(selector, eventName) {
- var handler = function(e) {
- data.spiedEvents[[selector, eventName]] = e;
- };
- jQuery(selector).bind(eventName, handler);
- data.handlers.push(handler);
- },
-
- wasTriggered: function(selector, eventName) {
- return !!(data.spiedEvents[[selector, eventName]]);
- },
-
- cleanUp: function() {
- data.spiedEvents = {};
- data.handlers = [];
- }
- }
-})(jasmine.JQuery);
-
-(function(){
- var jQueryMatchers = {
- toHaveClass: function(className) {
- return this.actual.hasClass(className);
- },
-
- toBeVisible: function() {
- return this.actual.is(':visible');
- },
-
- toBeHidden: function() {
- return this.actual.is(':hidden');
- },
-
- toBeSelected: function() {
- return this.actual.is(':selected');
- },
-
- toBeChecked: function() {
- return this.actual.is(':checked');
- },
-
- toBeEmpty: function() {
- return this.actual.is(':empty');
- },
-
- toExist: function() {
- return this.actual.size() > 0;
- },
-
- toHaveAttr: function(attributeName, expectedAttributeValue) {
- return hasProperty(this.actual.attr(attributeName), expectedAttributeValue);
- },
-
- toHaveId: function(id) {
- return this.actual.attr('id') == id;
- },
-
- toHaveHtml: function(html) {
- return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html);
- },
-
- toHaveText: function(text) {
- if (text && jQuery.isFunction(text.test)) {
- return text.test(this.actual.text());
- } else {
- return this.actual.text() == text;
- }
- },
-
- toHaveValue: function(value) {
- return this.actual.val() == value;
- },
-
- toHaveData: function(key, expectedValue) {
- return hasProperty(this.actual.data(key), expectedValue);
- },
-
- toMatchSelector: function(selector) {
- return this.actual.is(selector);
- },
-
- toContain: function(selector) {
- return this.actual.find(selector).size() > 0;
- },
-
- toBeDisabled: function(selector){
- return this.actual.is(':disabled');
- },
-
- // tests the existence of a specific event binding
- toHandle: function(eventName) {
- var events = this.actual.data("events");
- return events && events[eventName].length > 0;
- },
-
- // tests the existence of a specific event binding + handler
- toHandleWith: function(eventName, eventHandler) {
- var stack = this.actual.data("events")[eventName];
- var i;
- for (i = 0; i < stack.length; i++) {
- if (stack[i].handler == eventHandler) {
- return true;
- }
- }
- return false;
- }
- };
-
- var hasProperty = function(actualValue, expectedValue) {
- if (expectedValue === undefined) {
- return actualValue !== undefined;
- }
- return actualValue == expectedValue;
- };
-
- var bindMatcher = function(methodName) {
- var builtInMatcher = jasmine.Matchers.prototype[methodName];
-
- jasmine.JQuery.matchersClass[methodName] = function() {
- if (this.actual instanceof HTMLElement) {
- this.actual = jQuery(this.actual);
- }
- if (this.actual && this.actual.jquery) {
- var result = jQueryMatchers[methodName].apply(this, arguments);
- this.actual = jasmine.JQuery.elementToString(this.actual);
- return result;
- }
-
- if (builtInMatcher) {
- return builtInMatcher.apply(this, arguments);
- }
-
- return false;
- };
- };
-
- for(var methodName in jQueryMatchers) {
- bindMatcher(methodName);
- }
-})();
-
-beforeEach(function() {
- this.addMatchers(jasmine.JQuery.matchersClass);
- this.addMatchers({
- toHaveBeenTriggeredOn: function(selector) {
- this.message = function() {
- return [
- "Expected event " + this.actual + " to have been triggered on" + selector,
- "Expected event " + this.actual + " not to have been triggered on" + selector
- ];
- };
- return jasmine.JQuery.events.wasTriggered(selector, this.actual);
- }
- })
-});
-
-afterEach(function() {
- jasmine.JQuery.events.cleanUp();
-});
-})(require('../src/space-pen-extensions').jQuery);
diff --git a/spec/n1-spec-reporter.cjsx b/spec/n1-spec-reporter.cjsx
new file mode 100644
index 000000000..b0a63b52f
--- /dev/null
+++ b/spec/n1-spec-reporter.cjsx
@@ -0,0 +1,315 @@
+path = require 'path'
+_ = require 'underscore'
+_str = require 'underscore.string'
+{convertStackTrace} = require 'coffeestack'
+React = require 'react'
+ReactDOM = require 'react-dom'
+grim = require 'grim'
+marked = require 'marked'
+
+sourceMaps = {}
+formatStackTrace = (spec, message='', stackTrace, indent="") ->
+ return stackTrace unless stackTrace
+
+ jasminePattern = /^\s*at\s+.*\(?.*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
+ firstJasmineLinePattern = /^\s*at [/\\].*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
+ convertedLines = []
+ for line in stackTrace.split('\n')
+ convertedLines.push(line) unless jasminePattern.test(line)
+ break if firstJasmineLinePattern.test(line)
+
+ stackTrace = convertStackTrace(convertedLines.join('\n'), sourceMaps)
+ lines = stackTrace.split('\n')
+
+ # Remove first line of stack when it is the same as the error message
+ errorMatch = lines[0]?.match(/^Error: (.*)/)
+ lines.shift() if message.trim() is errorMatch?[1]?.trim()
+
+ for line, index in lines
+ # Remove prefix of lines matching: at [object Object]. (path:1:2)
+ prefixMatch = line.match(/at \[object Object\]\. \(([^)]+)\)/)
+ line = "at #{prefixMatch[1]}" if prefixMatch
+
+ # Relativize locations to spec directory
+ lines[index] = line.replace("at #{spec.specDirectory}#{path.sep}", 'at ')
+
+ lines = lines.map (line) -> indent + line.trim()
+ lines.join('\n')
+
+
+indentationString: (suite, plus=0) ->
+ rootSuite = suite
+ indentLevel = 0 + plus
+ while rootSuite.parentSuite
+ rootSuite = rootSuite.parentSuite
+ indentLevel += 1
+ return [0...indentLevel].map(-> " ").join("")
+
+
+suiteString: (spec) ->
+ descriptions = [spec.suite.description]
+
+ rootSuite = spec.suite
+ while rootSuite.parentSuite
+ indent = indentationString(rootSuite)
+ descriptions.unshift(indent + rootSuite.description)
+ rootSuite = rootSuite.parentSuite
+
+ descriptions.join("\n")
+
+
+class N1SpecReporter extends React.Component
+ constructor: (@props) ->
+
+ render: ->
+
+
+
+
+
+
Core
+
{@_renderSpecsOfType('core')}
+
+
+
Bundled
+
{@_renderSpecsOfType('bundled')}
+
+
+
User
+
{@_renderSpecsOfType('user')}
+
+ {@_renderStatus()}
+
+ {@_renderFailures()}
+
+ {@_renderDeprecations()}
+
+ {@props.plainTextOutput}
+
+
+
+ _renderSpecsOfType: (type) =>
+ items = []
+ @props.specs.forEach (spec, idx) =>
+ return unless spec.specType is type
+ statusClass = "pending"
+ title = undefined
+ results = spec.results()
+ if results
+ if results.skipped
+ statusClass = "skipped"
+ else if results.failedCount > 0
+ statusClass = "failed"
+ title = spec.getFullName()
+ else if spec.endedAt
+ statusClass = "passed"
+
+ items.push
+
+ items
+
+ _renderFailures: =>
+ # We have an array of specs with `suite` and potentially N `parentSuite` from there.
+ # Create a tree instead.
+ topLevelSuites = []
+
+ failedSpecs = @props.specs.filter (spec) ->
+ spec.endedAt and spec.results().failedCount > 0
+
+ for spec in failedSpecs
+ suite = spec.suite
+ suite = suite.parentSuite while suite.parentSuite
+ if topLevelSuites.indexOf(suite) is -1
+ topLevelSuites.push(suite)
+
+ topLevelSuites.map (suite, idx) =>
+
+
+ _renderDeprecations: =>
+ return if @props.deprecations.length is 0
+
+ if @props.deprecations.length is 1
+ label = "1 deprecation"
+ else
+ label = "#{@props.deprecations.length} deprecations"
+
+
+
{label}
+
+
+ {@_renderDeprecationList()}
+
+
+
+
+ _renderDeprecationList: =>
+ @props.deprecations.map (deprecation) =>
+
+
+ {deprecation.message}
+ {
+ deprecation.getStacks().map (stack) =>
+ fullStack = stack.map ({functionName, location}) ->
+ if functionName is '
'
+ " at #{location}"
+ else
+ " at #{functionName} (#{location})"
+
+ {formatStackTrace(deprecation.spec, deprecation.message, fullStack.join('\n'))}
+
+ }
+
+
+
+ _renderStatus: =>
+ failedCount = 0
+ skippedCount = 0
+ completeCount = 0
+ for spec in @props.specs
+ results = spec.results()
+ continue unless spec.endedAt
+ failedCount += 1 if results.failedCount > 0
+ skippedCount += 1 if results.skipped
+ completeCount += 1 if results.passedCount > 0 and results.failedCount is 0
+
+ if failedCount is 1
+ message = "#{failedCount} failure"
+ else
+ message = "#{failedCount} failures"
+
+ if skippedCount
+ specCount = "#{completeCount - skippedCount}/#{@props.specs.length - skippedCount} (#{skippedCount} skipped)"
+ else
+ specCount = "#{completeCount}/#{@props.specs.length}"
+
+
+
+
{specCount}
+
{message}
+
+
+ onReloadSpecs: =>
+ require('electron').ipcRenderer.send('call-webcontents-method', 'reload')
+
+
+class SuiteResultView extends React.Component
+ @propTypes: ->
+ suite: React.PropTypes.object
+ allSpecs: React.PropTypes.array
+
+ render: ->
+ items = []
+ subsuites = []
+
+ @props.allSpecs.forEach (spec) =>
+ if spec.suite is @props.suite
+ items.push(spec)
+ else
+ suite = spec.suite
+ while suite.parentSuite
+ if suite.parentSuite is @props.suite
+ subsuites.push(suite)
+ return
+ suite = suite.parentSuite
+
+ items = items.map (spec, idx) =>
+
+
+ subsuites = subsuites.map (suite, idx) =>
+
+
+
+
{@props.suite.description}
+
+ {items}
+ {subsuites}
+
+
+
+class SpecResultView extends React.Component
+ @propTypes: ->
+ spec: React.PropTypes.object
+
+ render: ->
+ description = @props.spec.description
+ resultItems = @props.spec.results().getItems()
+ description = "it #{description}" if description.indexOf('it ') isnt 0
+
+ failures = []
+ for result, idx in resultItems
+ continue if result.passed()
+ stackTrace = formatStackTrace(@props.spec, result.message, result.trace.stack)
+ failures.push(
+
+
{result.message}
+
{stackTrace}
+
+ )
+
+
+
{description}
+
{failures}
+
+
+
+
+el = document.createElement('div')
+document.body.appendChild(el)
+
+startedAt = null
+specs = []
+deprecations = []
+plainTextOutput = ""
+
+update = =>
+ component =
+ ReactDOM.render(component, el)
+
+updateSoon = _.debounce(update, 125)
+
+module.exports =
+ reportRunnerStarting: (runner) ->
+ specs = runner.specs()
+ startedAt = Date.now()
+ updateSoon()
+
+ reportRunnerResults: (runner) ->
+ updateSoon()
+
+ reportSuiteResults: (suite) ->
+
+ reportSpecResults: (spec) ->
+ spec.endedAt = Date.now()
+ specDeprecations = grim.getDeprecations()
+ d.spec = spec for d in specDeprecations
+ deprecations = deprecations.concat(specDeprecations)
+ grim.clearDeprecations()
+ updateSoon()
+
+ reportPlainTextSpecResult: (spec) ->
+ str = ""
+ if spec.results().failedCount > 0
+ str += suiteString(spec) + "\n"
+ indent = indentationString(spec.suite, 1)
+ stackIndent = indentationString(spec.suite, 2)
+
+ description = spec.description
+ description = "it #{description}" if description.indexOf('it ') isnt 0
+ str += indent + description + "\n"
+
+ for result in spec.results().getItems()
+ continue if result.passed()
+ str += indent + result.message + "\n"
+ stackTrace = formatStackTrace(spec, result.message, result.trace.stack, stackIndent)
+ str += stackTrace + "\n"
+ str += "\n\n"
+
+ plainTextOutput = plainTextOutput + str
+ updateSoon()
+
+ reportSpecStarting: (spec) ->
+ updateSoon()
diff --git a/spec/n1-spec-reporter.coffee b/spec/n1-spec-reporter.coffee
deleted file mode 100644
index 8666de3af..000000000
--- a/spec/n1-spec-reporter.coffee
+++ /dev/null
@@ -1,317 +0,0 @@
-path = require 'path'
-_ = require 'underscore'
-_str = require 'underscore.string'
-{convertStackTrace} = require 'coffeestack'
-{View, $, $$} = require '../src/space-pen-extensions'
-grim = require 'grim'
-marked = require 'marked'
-
-sourceMaps = {}
-formatStackTrace = (spec, message='', stackTrace, indent="") ->
- return stackTrace unless stackTrace
-
- jasminePattern = /^\s*at\s+.*\(?.*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
- firstJasmineLinePattern = /^\s*at [/\\].*[/\\]jasmine(-[^/\\]*)?\.js:\d+:\d+\)?\s*$/
- convertedLines = []
- for line in stackTrace.split('\n')
- convertedLines.push(line) unless jasminePattern.test(line)
- break if firstJasmineLinePattern.test(line)
-
- stackTrace = convertStackTrace(convertedLines.join('\n'), sourceMaps)
- lines = stackTrace.split('\n')
-
- # Remove first line of stack when it is the same as the error message
- errorMatch = lines[0]?.match(/^Error: (.*)/)
- lines.shift() if message.trim() is errorMatch?[1]?.trim()
-
- for line, index in lines
- # Remove prefix of lines matching: at [object Object]. (path:1:2)
- prefixMatch = line.match(/at \[object Object\]\. \(([^)]+)\)/)
- line = "at #{prefixMatch[1]}" if prefixMatch
-
- # Relativize locations to spec directory
- lines[index] = line.replace("at #{spec.specDirectory}#{path.sep}", 'at ')
-
- lines = lines.map (line) -> indent + line.trim()
- lines.join('\n')
-
-module.exports =
-class N1SpecReporter extends View
- @content: ->
- @div class: 'spec-reporter', =>
- @div class: 'padded pull-right', =>
- @button outlet: 'reloadButton', class: 'btn reload-button', 'Reload Specs'
- @div outlet: 'coreArea', class: 'symbol-area', =>
- @div outlet: 'coreHeader', class: 'symbol-header'
- @ul outlet: 'coreSummary', class: 'symbol-summary list-unstyled'
- @div outlet: 'bundledArea', class: 'symbol-area', =>
- @div outlet: 'bundledHeader', class: 'symbol-header'
- @ul outlet: 'bundledSummary', class: 'symbol-summary list-unstyled'
- @div outlet: 'userArea', class: 'symbol-area', =>
- @div outlet: 'userHeader', class: 'symbol-header'
- @ul outlet: 'userSummary', class: 'symbol-summary list-unstyled'
- @div outlet: "status", class: 'status alert alert-info', =>
- @div outlet: "time", class: 'time'
- @div outlet: "specCount", class: 'spec-count'
- @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'
- @pre outlet: "plainTextOutput", class: 'plain-text-output'
-
- startedAt: null
- runningSpecCount: 0
- completeSpecCount: 0
- passedCount: 0
- failedCount: 0
- skippedCount: 0
- totalSpecCount: 0
- deprecationCount: 0
- @timeoutId: 0
-
- reportRunnerStarting: (runner) ->
- @handleEvents()
- @startedAt = Date.now()
- specs = runner.specs()
- @totalSpecCount = specs.length
- @addSpecs(specs)
- $(document.body).append this
-
- @on 'click', '.stack-trace', ->
- $(this).toggleClass('expanded')
-
- @reloadButton.on 'click', -> require('electron').ipcRenderer.send('call-webcontents-method', 'reload')
-
- reportRunnerResults: (runner) ->
- @updateSpecCounts()
- @status.addClass('alert-success').removeClass('alert-info') if @failedCount is 0
- if @failedCount is 1
- @message.text "#{@failedCount} failure"
- else
- @message.text "#{@failedCount} failures"
-
- @status.addClass("specs-complete")
-
- reportSuiteResults: (suite) ->
-
- reportSpecResults: (spec) ->
- @completeSpecCount++
- spec.endedAt = Date.now()
- @specComplete(spec)
- @updateStatusView(spec)
- @reportPlainTextSpecResult(spec)
-
- reportPlainTextSpecResult: (spec) ->
- str = ""
- if spec.results().failedCount > 0
- str += @suiteString(spec) + "\n"
- indent = @indentationString(spec.suite, 1)
- stackIndent = @indentationString(spec.suite, 2)
-
- description = spec.description
- description = "it #{description}" if description.indexOf('it ') isnt 0
- str += indent + description + "\n"
-
- for result in spec.results().getItems()
- continue if result.passed()
- str += indent + result.message + "\n"
- stackTrace = formatStackTrace(spec, result.message, result.trace.stack, stackIndent)
- str += stackTrace + "\n"
- str += "\n\n"
- @plainTextOutput.append(str)
-
- indentationString: (suite, plus=0) ->
- rootSuite = suite
- indentLevel = 0 + plus
- while rootSuite.parentSuite
- rootSuite = rootSuite.parentSuite
- indentLevel += 1
- return [0...indentLevel].map(-> " ").join("")
-
- suiteString: (spec) ->
- descriptions = [spec.suite.description]
-
- rootSuite = spec.suite
- while rootSuite.parentSuite
- indent = @indentationString(rootSuite)
- descriptions.unshift(indent + rootSuite.description)
- rootSuite = rootSuite.parentSuite
-
- descriptions.join("\n")
-
- 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', =>
- @raw marked(deprecation.message)
-
- for stack in deprecation.getStacks()
- 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)
- specFailures = element.parent().find('.spec-failures')
- specFailures.toggle()
- 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)"
- else
- specCount = "#{@completeSpecCount}/#{@totalSpecCount}"
- @specCount[0].textContent = specCount
-
- updateStatusView: (spec) ->
- if @failedCount > 0
- @status.addClass('alert-danger').removeClass('alert-info')
-
- @updateSpecCounts()
-
- rootSuite = spec.suite
- rootSuite = rootSuite.parentSuite while rootSuite.parentSuite
- @message.text rootSuite.description
-
- time = "#{Math.round((spec.endedAt - @startedAt) / 10)}"
- time = "0#{time}" if time.length < 3
- @time[0].textContent = "#{time[0...-2]}.#{time[-2..]}s"
-
- addSpecs: (specs) ->
- coreSpecs = 0
- bundledPackageSpecs = 0
- userPackageSpecs = 0
- for spec in specs
- symbol = $$ -> @li id: "spec-summary-#{spec.id}", class: "spec-summary pending"
- switch spec.specType
- when 'core'
- coreSpecs++
- @coreSummary.append symbol
- when 'bundled'
- bundledPackageSpecs++
- @bundledSummary.append symbol
- when 'user'
- userPackageSpecs++
- @userSummary.append symbol
-
- if coreSpecs > 0
- @coreHeader.text("Core Specs (#{coreSpecs})")
- else
- @coreArea.hide()
- if bundledPackageSpecs > 0
- @bundledHeader.text("Bundled Package Specs (#{bundledPackageSpecs})")
- else
- @bundledArea.hide()
- if userPackageSpecs > 0
- if coreSpecs is 0 and bundledPackageSpecs is 0
- # Package specs being run, show a more descriptive label
- {specDirectory} = specs[0]
- packageFolderName = path.basename(path.dirname(specDirectory))
- packageName = _str.humanize(packageFolderName)
- @userHeader.text("#{packageName} Specs")
- else
- @userHeader.text("User Package Specs (#{userPackageSpecs})")
- else
- @userArea.hide()
-
- specStarted: (spec) ->
- @runningSpecCount++
-
- specComplete: (spec) ->
- specSummaryElement = $("#spec-summary-#{spec.id}")
- specSummaryElement.removeClass('pending')
- specSummaryElement.attr('title', spec.getFullName())
-
- results = spec.results()
- if results.skipped
- specSummaryElement.addClass("skipped")
- @skippedCount++
- else if results.passed()
- specSummaryElement.addClass("passed")
- @passedCount++
- else
- specSummaryElement.addClass("failed")
-
- specView = new SpecResultView(spec)
- specView.attach()
- @failedCount++
- @addDeprecations(spec)
-
-class SuiteResultView extends View
- @content: ->
- @div class: 'suite', =>
- @div outlet: 'description', class: 'description'
-
- initialize: (@suite) ->
- @attr('id', "suite-view-#{@suite.id}")
- @description.text(@suite.description)
-
- attach: ->
- (@parentSuiteView() or $('.results')).append this
-
- parentSuiteView: ->
- return unless @suite.parentSuite
-
- if not suiteView = $("#suite-view-#{@suite.parentSuite.id}").view()
- suiteView = new SuiteResultView(@suite.parentSuite)
- suiteView.attach()
-
- suiteView
-
-class SpecResultView extends View
- @content: ->
- @div class: 'spec', =>
- @div class: 'spec-toggle'
- @div outlet: 'description', class: 'description'
- @div outlet: 'specFailures', class: 'spec-failures'
-
- initialize: (@spec) ->
- @addClass("spec-view-#{@spec.id}")
-
- description = @spec.description
- description = "it #{description}" if description.indexOf('it ') isnt 0
- @description.text(description)
-
- for result in @spec.results().getItems() when not result.passed()
- stackTrace = formatStackTrace(@spec, result.message, result.trace.stack)
- @specFailures.append $$ ->
- @div result.message, class: 'result-message fail'
- @pre stackTrace, class: 'stack-trace padded' if stackTrace
-
- attach: ->
- @parentSuiteView().append this
-
- parentSuiteView: ->
- if not suiteView = $("#suite-view-#{@spec.suite.id}").view()
- suiteView = new SuiteResultView(@spec.suite)
- suiteView.attach()
-
- suiteView
diff --git a/spec/package-manager-spec.coffee b/spec/package-manager-spec.coffee
index 3438edfb8..066cd6869 100644
--- a/spec/package-manager-spec.coffee
+++ b/spec/package-manager-spec.coffee
@@ -456,9 +456,9 @@ describe "PackageManager", ->
one = require.resolve("./fixtures/packages/package-with-style-sheets-manifest/styles/1.css")
two = require.resolve("./fixtures/packages/package-with-style-sheets-manifest/styles/2.less")
three = require.resolve("./fixtures/packages/package-with-style-sheets-manifest/styles/3.css")
- expect(NylasEnv.themes.stylesheetElementForId(one)).not.toExist()
- expect(NylasEnv.themes.stylesheetElementForId(two)).not.toExist()
- expect(NylasEnv.themes.stylesheetElementForId(three)).not.toExist()
+ expect(NylasEnv.themes.stylesheetElementForId(one)).toBe(null)
+ expect(NylasEnv.themes.stylesheetElementForId(two)).toBe(null)
+ expect(NylasEnv.themes.stylesheetElementForId(three)).toBe(null)
it "invokes ::onDidDeactivatePackage listeners with the deactivated package", ->
waitsForPromise ->
diff --git a/spec/package-spec.coffee b/spec/package-spec.coffee
index 333480721..952c0e09b 100644
--- a/spec/package-spec.coffee
+++ b/spec/package-spec.coffee
@@ -1,4 +1,3 @@
-{$} = require '../src/space-pen-extensions'
path = require 'path'
Package = require '../src/package'
ThemePackage = require '../src/theme-package'
@@ -41,51 +40,57 @@ describe "Package", ->
theme = null
beforeEach ->
- $("#jasmine-content").append $("")
+ @wrap = document.createElement('nylas-theme-wrap')
+ document.getElementById("jasmine-content").appendChild(@wrap)
afterEach ->
theme.deactivate() if theme?
describe "when the theme contains a single style file", ->
it "loads and applies css", ->
- expect($("nylas-theme-wrap").css("padding-bottom")).not.toBe "1234px"
+
+ expect(window.getComputedStyle(@wrap)['padding-bottom']).not.toBe "1234px"
themePath = resolveFixturePath('theme-with-index-css')
theme = new ThemePackage(themePath)
theme.activate()
- expect($("nylas-theme-wrap").css("padding-top")).toBe "1234px"
+ expect(window.getComputedStyle(@wrap)['padding-top']).toBe "1234px"
it "parses, loads and applies less", ->
- expect($("nylas-theme-wrap").css("padding-bottom")).not.toBe "1234px"
+ expect(window.getComputedStyle(@wrap)['padding-bottom']).not.toBe "1234px"
themePath = resolveFixturePath('theme-with-index-less')
theme = new ThemePackage(themePath)
theme.activate()
- expect($("nylas-theme-wrap").css("padding-top")).toBe "4321px"
+ expect(window.getComputedStyle(@wrap)['padding-top']).toBe "4321px"
describe "when the theme contains a package.json file", ->
it "loads and applies stylesheets from package.json in the correct order", ->
- expect($("nylas-theme-wrap").css("padding-top")).not.toBe("101px")
- expect($("nylas-theme-wrap").css("padding-right")).not.toBe("102px")
- expect($("nylas-theme-wrap").css("padding-bottom")).not.toBe("103px")
+ styles = window.getComputedStyle(@wrap)
+ expect(styles["padding-top"]).not.toBe("101px")
+ expect(styles["padding-right"]).not.toBe("102px")
+ expect(styles["padding-bottom"]).not.toBe("103px")
themePath = resolveFixturePath('theme-with-package-file')
theme = new ThemePackage(themePath)
theme.activate()
- expect($("nylas-theme-wrap").css("padding-top")).toBe("101px")
- expect($("nylas-theme-wrap").css("padding-right")).toBe("102px")
- expect($("nylas-theme-wrap").css("padding-bottom")).toBe("103px")
+ styles = window.getComputedStyle(@wrap)
+ expect(styles["padding-top"]).toBe("101px")
+ expect(styles["padding-right"]).toBe("102px")
+ expect(styles["padding-bottom"]).toBe("103px")
describe "when the theme does not contain a package.json file and is a directory", ->
it "loads all stylesheet files in the directory", ->
- expect($("nylas-theme-wrap").css("padding-top")).not.toBe "10px"
- expect($("nylas-theme-wrap").css("padding-right")).not.toBe "20px"
- expect($("nylas-theme-wrap").css("padding-bottom")).not.toBe "30px"
+ styles = window.getComputedStyle(@wrap)
+ expect(styles["padding-top"]).not.toBe("10px")
+ expect(styles["padding-right"]).not.toBe("20px")
+ expect(styles["padding-bottom"]).not.toBe("30px")
themePath = resolveFixturePath('theme-without-package-file')
theme = new ThemePackage(themePath)
theme.activate()
- expect($("nylas-theme-wrap").css("padding-top")).toBe "10px"
- expect($("nylas-theme-wrap").css("padding-right")).toBe "20px"
- expect($("nylas-theme-wrap").css("padding-bottom")).toBe "30px"
+ styles = window.getComputedStyle(@wrap)
+ expect(styles["padding-top"]).toBe("10px")
+ expect(styles["padding-right"]).toBe("20px")
+ expect(styles["padding-bottom"]).toBe("30px")
describe "reloading a theme", ->
beforeEach ->
diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee
index b33d38912..a04c47a1b 100644
--- a/spec/spec-helper.coffee
+++ b/spec/spec-helper.coffee
@@ -7,15 +7,11 @@ require '../src/window'
NylasEnv.restoreWindowDimensions()
require 'jasmine-json'
-require './jasmine-jquery'
Grim = require 'grim'
TimeOverride = require './time-override'
KeymapManager = require '../src/keymap-manager'
-# FIXME: Remove jquery from this
-{$} = require '../src/space-pen-extensions'
-
Config = require '../src/config'
pathwatcher = require 'pathwatcher'
{clipboard} = require 'electron'
@@ -40,7 +36,9 @@ window.addEventListener 'core:close', -> window.close()
window.addEventListener 'beforeunload', ->
NylasEnv.storeWindowDimensions()
NylasEnv.saveSync()
-$('html,body').css('overflow', 'auto')
+
+document.querySelector('html').style.overflow = 'initial'
+document.querySelector('body').style.overflow = 'initial'
# Allow document.title to be assigned in specs without screwing up spec window title
documentTitle = null
@@ -142,7 +140,6 @@ beforeEach ->
TaskQueue._completed = []
TaskQueue._onlineStatus = true
- $.fx.off = true
documentTitle = null
NylasEnv.styles.restoreSnapshot(styleElementsToRestore)
NylasEnv.workspaceViewParentSelector = '#jasmine-content'
@@ -243,8 +240,8 @@ afterEach ->
delete NylasEnv.state?.packageStates
- $('#jasmine-content').empty() unless window.debugContent
-
+ unless window.debugContent
+ document.getElementById('jasmine-content').innerHTML = ''
ReactTestUtils.unmountAll()
jasmine.unspy(NylasEnv, 'saveSync')
@@ -354,8 +351,8 @@ window.keydownEvent = (key, properties={}) ->
originalEventProperties.target = properties.target?[0] ? properties.target
originalEventProperties.which = properties.which
originalEvent = KeymapManager.keydownEvent(key, originalEventProperties)
- properties = $.extend({originalEvent}, properties)
- $.Event("keydown", properties)
+ properties = _.extend({originalEvent}, properties)
+ new CustomEvent('keydown', properties)
window.mouseEvent = (type, properties) ->
if properties.point
@@ -364,7 +361,7 @@ window.mouseEvent = (type, properties) ->
properties.pageX = left + 1
properties.pageY = top + 1
properties.originalEvent ?= {detail: 1}
- $.Event type, properties
+ new CustomEvent(type, properties)
window.clickEvent = (properties={}) ->
window.mouseEvent("click", properties)
diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee
index c213ee8cd..5d99a4d52 100644
--- a/spec/theme-manager-spec.coffee
+++ b/spec/theme-manager-spec.coffee
@@ -1,6 +1,5 @@
path = require 'path'
-{$, $$} = require '../src/space-pen-extensions'
fs = require 'fs-plus'
temp = require 'temp'
@@ -101,7 +100,7 @@ describe "ThemeManager", ->
runs ->
didChangeActiveThemesHandler.reset()
- expect($('style.theme')).toHaveLength 0
+ expect(document.querySelectorAll('style.theme')).toHaveLength 0
NylasEnv.config.set('core.themes', ['ui-dark'])
waitsFor ->
@@ -109,8 +108,9 @@ describe "ThemeManager", ->
runs ->
didChangeActiveThemesHandler.reset()
- expect($('style[priority=1]')).toHaveLength 1
- expect($('style[priority=1]:eq(0)').attr('source-path')).toMatch /ui-dark/
+ sheets = Array.from(document.querySelectorAll('style[priority="1"]'))
+ expect(sheets).toHaveLength 1
+ expect(sheets[0].getAttribute('source-path')).toMatch /ui-dark/
NylasEnv.config.set('core.themes', ['ui-light', 'ui-dark'])
waitsFor ->
@@ -118,9 +118,10 @@ describe "ThemeManager", ->
runs ->
didChangeActiveThemesHandler.reset()
- expect($('style[priority=1]')).toHaveLength 2
- expect($('style[priority=1]:eq(0)').attr('source-path')).toMatch /ui-dark/
- expect($('style[priority=1]:eq(1)').attr('source-path')).toMatch /ui-light/
+ sheets = Array.from(document.querySelectorAll('style[priority="1"]'))
+ expect(sheets).toHaveLength 2
+ expect(sheets[0].getAttribute('source-path')).toMatch /ui-dark/
+ expect(sheets[1].getAttribute('source-path')).toMatch /ui-light/
NylasEnv.config.set('core.themes', [])
waitsFor ->
@@ -128,7 +129,8 @@ describe "ThemeManager", ->
runs ->
didChangeActiveThemesHandler.reset()
- expect($('style[priority=1]')).toHaveLength(1)
+ sheets = Array.from(document.querySelectorAll('style[priority="1"]'))
+ expect(sheets).toHaveLength(1)
# ui-dark has an directory path, the syntax one doesn't
NylasEnv.config.set('core.themes', ['theme-with-index-less', 'ui-light'])
@@ -136,7 +138,8 @@ describe "ThemeManager", ->
didChangeActiveThemesHandler.callCount == 1
runs ->
- expect($('style[priority=1]')).toHaveLength 2
+ sheets = Array.from(document.querySelectorAll('style[priority="1"]'))
+ expect(sheets).toHaveLength 2
importPaths = themeManager.getImportPaths()
expect(importPaths.length).toBe 1
expect(importPaths[0]).toContain 'ui-light'
@@ -151,7 +154,7 @@ describe "ThemeManager", ->
themeManager.activateThemes()
runs ->
- expect(workspaceElement).toHaveClass 'theme-ui-light'
+ expect(workspaceElement.classList.contains('theme-ui-light')).toBe(true)
themeManager.onDidChangeActiveThemes didChangeActiveThemesHandler = jasmine.createSpy()
NylasEnv.config.set('core.themes', ['theme-with-ui-variables'])
@@ -161,8 +164,8 @@ describe "ThemeManager", ->
runs ->
# `theme-` twice as it prefixes the name with `theme-`
- expect(workspaceElement).toHaveClass 'theme-theme-with-ui-variables'
- expect(workspaceElement).not.toHaveClass 'theme-ui-dark'
+ expect(workspaceElement.classList.contains('theme-theme-with-ui-variables')).toBe(true)
+ expect(workspaceElement.classList.contains('theme-ui-dark')).toBe(false)
describe "when a theme fails to load", ->
it "logs a warning", ->
@@ -183,37 +186,37 @@ describe "ThemeManager", ->
themeManager.onDidAddStylesheet stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler")
cssPath = path.join(__dirname, 'fixtures', 'css.css')
- lengthBefore = $('head style').length
+ lengthBefore = document.querySelectorAll('head style').length
themeManager.requireStylesheet(cssPath)
- expect($('head style').length).toBe lengthBefore + 1
+ expect(document.querySelectorAll('head style').length).toBe lengthBefore + 1
expect(styleElementAddedHandler).toHaveBeenCalled()
expect(stylesheetAddedHandler).toHaveBeenCalled()
expect(stylesheetsChangedHandler).toHaveBeenCalled()
- element = $('head style[source-path*="css.css"]')
- expect(element.attr('source-path')).toBe themeManager.stringToId(cssPath)
- expect(element.text()).toBe fs.readFileSync(cssPath, 'utf8')
- expect(element[0].sheet).toBe stylesheetAddedHandler.argsForCall[0][0]
+ element = document.querySelector('head style[source-path*="css.css"]')
+ expect(element.getAttribute('source-path')).toBe themeManager.stringToId(cssPath)
+ expect(element.textContent).toBe fs.readFileSync(cssPath, 'utf8')
# doesn't append twice
styleElementAddedHandler.reset()
themeManager.requireStylesheet(cssPath)
- expect($('head style').length).toBe lengthBefore + 1
+ expect(document.querySelectorAll('head style').length).toBe lengthBefore + 1
expect(styleElementAddedHandler).not.toHaveBeenCalled()
- $('head style[id*="css.css"]').remove()
+ element .remove()
it "synchronously loads and parses less files at the given path and installs a style tag for it in the head", ->
lessPath = path.join(__dirname, 'fixtures', 'sample.less')
- lengthBefore = $('head style').length
+ lengthBefore = document.querySelectorAll('head style').length
themeManager.requireStylesheet(lessPath)
- expect($('head style').length).toBe lengthBefore + 1
+ lengthAfter = document.querySelectorAll('head style').length
+ expect(lengthAfter).toBe lengthBefore + 1
- element = $('head style[source-path*="sample.less"]')
- expect(element.attr('source-path')).toBe themeManager.stringToId(lessPath)
- expect(element.text()).toBe """
+ element = document.querySelector('head style[source-path*="sample.less"]')
+ expect(element.getAttribute('source-path')).toBe themeManager.stringToId(lessPath)
+ expect(element.textContent).toBe """
#header {
color: #4d926f;
}
@@ -225,24 +228,24 @@ describe "ThemeManager", ->
# doesn't append twice
themeManager.requireStylesheet(lessPath)
- expect($('head style').length).toBe lengthBefore + 1
- $('head style[id*="sample.less"]').remove()
+ expect(document.querySelectorAll('head style').length).toBe lengthBefore + 1
+ element.remove()
it "supports requiring css and less stylesheets without an explicit extension", ->
themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'css')
- expect($('head style[source-path*="css.css"]').attr('source-path')).toBe themeManager.stringToId(path.join(__dirname, 'fixtures', 'css.css'))
+ expect(document.querySelector('head style[source-path*="css.css"]').getAttribute('source-path')).toBe themeManager.stringToId(path.join(__dirname, 'fixtures', 'css.css'))
themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'sample')
- expect($('head style[source-path*="sample.less"]').attr('source-path')).toBe themeManager.stringToId(path.join(__dirname, 'fixtures', 'sample.less'))
+ expect(document.querySelector('head style[source-path*="sample.less"]').getAttribute('source-path')).toBe themeManager.stringToId(path.join(__dirname, 'fixtures', 'sample.less'))
- $('head style[id*="css.css"]').remove()
- $('head style[id*="sample.less"]').remove()
+ document.querySelector('head style[source-path*="css.css"]').remove()
+ document.querySelector('head style[source-path*="sample.less"]').remove()
it "returns a disposable allowing styles applied by the given path to be removed", ->
cssPath = require.resolve('./fixtures/css.css')
- expect($(document.body).css('font-weight')).not.toBe("bold")
+ expect(window.getComputedStyle(document.body)['font-weight']).not.toBe("bold")
disposable = themeManager.requireStylesheet(cssPath)
- expect($(document.body).css('font-weight')).toBe("bold")
+ expect(window.getComputedStyle(document.body)['font-weight']).toBe("bold")
NylasEnv.styles.onDidRemoveStyleElement styleElementRemovedHandler = jasmine.createSpy("styleElementRemovedHandler")
themeManager.onDidRemoveStylesheet stylesheetRemovedHandler = jasmine.createSpy("stylesheetRemovedHandler")
@@ -250,7 +253,7 @@ describe "ThemeManager", ->
disposable.dispose()
- expect($(document.body).css('font-weight')).not.toBe("bold")
+ expect(window.getComputedStyle(document.body)['font-weight']).not.toBe("bold")
expect(styleElementRemovedHandler).toHaveBeenCalled()
expect(stylesheetRemovedHandler).toHaveBeenCalled()
@@ -291,9 +294,11 @@ describe "ThemeManager", ->
expect(getComputedStyle(workspaceElement)["background-color"]).toBe "rgb(0, 0, 255)"
# a value that is not overridden in the theme
- expect($("nylas-theme-wrap").css("padding-top")).toBe "150px"
- expect($("nylas-theme-wrap").css("padding-right")).toBe "150px"
- expect($("nylas-theme-wrap").css("padding-bottom")).toBe "150px"
+ node = document.querySelector('nylas-theme-wrap')
+ nodeStyle = window.getComputedStyle(node)
+ expect(nodeStyle['padding-top']).toBe "150px"
+ expect(nodeStyle['padding-right']).toBe "150px"
+ expect(nodeStyle['padding-bottom']).toBe "150px"
describe "when there is a theme with incomplete variables", ->
it "loads the correct values from the fallback ui-variables", ->
@@ -304,8 +309,10 @@ describe "ThemeManager", ->
# an override loaded in the base css of theme-with-incomplete-ui-variables
expect(getComputedStyle(workspaceElement)["background-color"]).toBe "rgb(0, 0, 255)"
- # a value that is not overridden in the theme
- expect($("nylas-theme-wrap").css("background-color")).toBe "rgb(152, 123, 0)"
+ # a value that is not overridden in the theme
+ node = document.querySelector('nylas-theme-wrap')
+ nodeStyle = window.getComputedStyle(node)
+ expect(nodeStyle['background-color']).toBe "rgb(152, 123, 0)"
describe "user stylesheet", ->
userStylesheetPath = null
@@ -337,14 +344,16 @@ describe "ThemeManager", ->
themeManager.onDidAddStylesheet stylesheetAddedHandler = jasmine.createSpy("stylesheetAddedHandler")
spyOn(themeManager, 'loadUserStylesheet').andCallThrough()
- expect($(document.body).css('border-style')).toBe 'dotted'
+ bodyStyle = window.getComputedStyle(document.body)
+ expect(bodyStyle['border-style']).toBe "dotted"
fs.writeFileSync(userStylesheetPath, 'body {border-style: dashed}')
waitsFor ->
themeManager.loadUserStylesheet.callCount is 1
runs ->
- expect($(document.body).css('border-style')).toBe 'dashed'
+ bodyStyle = window.getComputedStyle(document.body)
+ expect(bodyStyle['border-style']).toBe "dashed"
expect(styleElementRemovedHandler).toHaveBeenCalled()
expect(styleElementRemovedHandler.argsForCall[0][0].textContent).toContain 'dotted'
@@ -382,7 +391,9 @@ describe "ThemeManager", ->
match = null
for rule in stylesheetRemovedHandler.argsForCall[0][0].cssRules
match = rule if rule.selectorText is 'body'
- match.style.border is 'dashed' and $(document.body).css('border-style') is 'none'
+
+ bodyStyle = window.getComputedStyle(document.body)
+ match.style.border is 'dashed' and bodyStyle['border-style'] is 'none'
runs ->
expect(stylesheetsChangedHandler).toHaveBeenCalled()
diff --git a/src/space-pen-extensions.coffee b/src/space-pen-extensions.coffee
deleted file mode 100644
index 0f2d5c0df..000000000
--- a/src/space-pen-extensions.coffee
+++ /dev/null
@@ -1,109 +0,0 @@
-_ = require 'underscore'
-_ = _.extend(_, require('./space-pen-utils'))
-SpacePen = require 'space-pen'
-{Subscriber} = require 'emissary'
-
-###
-Edgehill Note:
-
-I want this file goneāplan is to slowly delete stuff below as we clean spacepen
-and it's helpers out of the project.
-
-- Ben
-###
-
-
-Subscriber.includeInto(SpacePen.View)
-
-jQuery = SpacePen.jQuery
-JQueryCleanData = jQuery.cleanData
-jQuery.cleanData = (elements) ->
- jQuery(element).view()?.unsubscribe?() for element in elements
- JQueryCleanData(elements)
-
-SpacePenCallRemoveHooks = SpacePen.callRemoveHooks
-SpacePen.callRemoveHooks = (element) ->
- view.unsubscribe?() for view in SpacePen.viewsForElement(element)
- SpacePenCallRemoveHooks(element)
-
-NativeEventNames = new Set
-NativeEventNames.add(nativeEvent) for nativeEvent in ["blur", "focus", "focusin",
-"focusout", "load", "resize", "scroll", "unload", "click", "dblclick", "mousedown",
-"mouseup", "mousemove", "mouseover", "mouseout", "mouseenter", "mouseleave", "change",
-"select", "submit", "keydown", "keypress", "keyup", "error", "contextmenu", "textInput",
-"textinput", "beforeunload"]
-
-JQueryTrigger = jQuery.fn.trigger
-jQuery.fn.trigger = (eventName, data) ->
- if NativeEventNames.has(eventName) or typeof eventName is 'object'
- JQueryTrigger.call(this, eventName, data)
- else
- data ?= {}
- data.jQueryTrigger = true
-
- for element in this
- NylasEnv.commands.dispatch(eventName, data)
- this
-
-HandlersByOriginalHandler = new WeakMap
-CommandDisposablesByElement = new WeakMap
-
-AddEventListener = (element, type, listener) ->
- if NativeEventNames.has(type)
- element.addEventListener(type, listener)
- else
- disposable = NylasEnv.commands.add(element, type, listener)
-
- unless disposablesByType = CommandDisposablesByElement.get(element)
- disposablesByType = {}
- CommandDisposablesByElement.set(element, disposablesByType)
-
- unless disposablesByListener = disposablesByType[type]
- disposablesByListener = new WeakMap
- disposablesByType[type] = disposablesByListener
-
- disposablesByListener.set(listener, disposable)
-
-RemoveEventListener = (element, type, listener) ->
- if NativeEventNames.has(type)
- element.removeEventListener(type, listener)
- else
- CommandDisposablesByElement.get(element)?[type]?.get(listener)?.dispose()
-
-JQueryEventAdd = jQuery.event.add
-jQuery.event.add = (elem, types, originalHandler, data, selector) ->
- handler = (event) ->
- if arguments.length is 1 and event.originalEvent?.detail?
- {detail} = event.originalEvent
- if Array.isArray(detail)
- originalHandler.apply(this, [event].concat(detail))
- else
- originalHandler.call(this, event, detail)
- else
- originalHandler.apply(this, arguments)
-
- HandlersByOriginalHandler.set(originalHandler, handler)
-
- JQueryEventAdd.call(this, elem, types, handler, data, selector, AddEventListener if NylasEnv?.commands?)
-
-JQueryEventRemove = jQuery.event.remove
-jQuery.event.remove = (elem, types, originalHandler, selector, mappedTypes) ->
- if originalHandler?
- handler = HandlersByOriginalHandler.get(originalHandler) ? originalHandler
- JQueryEventRemove(elem, types, handler, selector, mappedTypes, RemoveEventListener if NylasEnv?.commands?)
-
-JQueryContains = jQuery.contains
-
-jQuery.contains = (a, b) ->
- shadowRoot = null
- currentNode = b
- while currentNode
- if currentNode instanceof ShadowRoot and a.contains(currentNode.host)
- return true
- currentNode = currentNode.parentNode
-
- JQueryContains.call(this, a, b)
-
-Object.defineProperty jQuery.fn, 'element', get: -> @[0]
-
-module.exports = SpacePen