diff --git a/spec/theme-manager-spec.coffee b/spec/theme-manager-spec.coffee index 70a01c213..d99633d57 100644 --- a/spec/theme-manager-spec.coffee +++ b/spec/theme-manager-spec.coffee @@ -70,7 +70,7 @@ describe "ThemeManager", -> describe "when the core.themes config value changes", -> it "add/removes stylesheets to reflect the new config value", -> themeManager.onDidReloadAll reloadHandler = jasmine.createSpy() - spyOn(themeManager, 'getUserStylesheetPath').andCallFake -> null + spyOn(atom.styles, 'getUserStyleSheetPath').andCallFake -> null waitsForPromise -> themeManager.activateThemes() @@ -268,7 +268,7 @@ describe "ThemeManager", -> [stylesheetRemovedHandler, stylesheetAddedHandler, stylesheetsChangedHandler] = [] userStylesheetPath = path.join(temp.mkdirSync("atom"), 'styles.less') fs.writeFileSync(userStylesheetPath, 'body {border-style: dotted !important;}') - spyOn(themeManager, 'getUserStylesheetPath').andReturn userStylesheetPath + spyOn(atom.styles, 'getUserStyleSheetPath').andReturn userStylesheetPath waitsForPromise -> themeManager.activateThemes() diff --git a/src/atom.coffee b/src/atom.coffee index be23d1cf6..b3796ddae 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -137,6 +137,9 @@ class Atom extends Model # Public: A {ThemeManager} instance themes: null + # Public: A {StyleManager} instance + styles: null + # Public: A {DeserializerManager} instance deserializers: null diff --git a/src/style-manager.coffee b/src/style-manager.coffee index 7b9a786c7..f9d6aa373 100644 --- a/src/style-manager.coffee +++ b/src/style-manager.coffee @@ -1,5 +1,12 @@ +fs = require 'fs-plus' +path = require 'path' {Emitter, Disposable} = require 'event-kit' +# Extended: A singleton instance of this class available via `atom.styles`, +# which you can use to globally query and observe the set of active style +# sheets. The `StyleManager` doesn't add any style elements to the DOM on its +# own, but is instead subscribed to by individual `` elements, +# which clone and attach style elements in different contexts. module.exports = class StyleManager constructor: -> @@ -7,19 +14,78 @@ class StyleManager @styleElements = [] @styleElementsBySourcePath = {} + ### + Section: Event Subscription + ### + + # Extended: Invoke `callback` for all current and future style elements. + # + # * `callback` {Function} that is called with style elements. + # * `styleElement` An `HTMLStyleElement` instance. The `.sheet` property + # will be null because this element isn't attached to the DOM. If you want + # to attach this element to the DOM, be sure to clone it first by calling + # `.cloneNode(true)` on it. The style element will also have the following + # non-standard properties: + # * `sourcePath` A {String} containing the path from which the style + # element was loaded. + # * `context` A {String} indicating the target context of the style + # element. + # + # Returns a {Disposable} on which `.dispose()` can be called to cancel the + # subscription. observeStyleElements: (callback) -> callback(styleElement) for styleElement in @getStyleElements() @onDidAddStyleElement(callback) + # Extended: Invoke `callback` when a style element is added. + # + # * `callback` {Function} that is called with style elements. + # * `styleElement` An `HTMLStyleElement` instance. The `.sheet` property + # will be null because this element isn't attached to the DOM. If you want + # to attach this element to the DOM, be sure to clone it first by calling + # `.cloneNode(true)` on it. The style element will also have the following + # non-standard properties: + # * `sourcePath` A {String} containing the path from which the style + # element was loaded. + # * `context` A {String} indicating the target context of the style + # element. + # + # Returns a {Disposable} on which `.dispose()` can be called to cancel the + # subscription. onDidAddStyleElement: (callback) -> @emitter.on 'did-add-style-element', callback + # Extended: Invoke `callback` when a style element is removed. + # + # * `callback` {Function} that is called with style elements. + # * `styleElement` An `HTMLStyleElement` instance. + # + # Returns a {Disposable} on which `.dispose()` can be called to cancel the + # subscription. onDidRemoveStyleElement: (callback) -> @emitter.on 'did-remove-style-element', callback + # Extended: Invoke `callback` when an existing style element is updated. + # + # * `callback` {Function} that is called with style elements. + # * `styleElement` An `HTMLStyleElement` instance. The `.sheet` property + # will be null because this element isn't attached to the DOM. The style + # element will also have the following non-standard properties: + # * `sourcePath` A {String} containing the path from which the style + # element was loaded. + # * `context` A {String} indicating the target context of the style + # element. + # + # Returns a {Disposable} on which `.dispose()` can be called to cancel the + # subscription. onDidUpdateStyleElement: (callback) -> @emitter.on 'did-update-style-element', callback + ### + Section: Reading Style Elements + ### + + # Extended: Get all loaded style elements. getStyleElements: -> @styleElements.slice() @@ -85,3 +151,17 @@ class StyleManager existingStyleElements = @getStyleElements() for styleElement in styleElementsToRestore @addStyleElement(styleElement) unless styleElement in existingStyleElements + + ### + Section: Paths + ### + + # Extended: Get the path of the user style sheet in `~/.atom`. + # + # Returns a {String}. + getUserStyleSheetPath: -> + stylesheetPath = fs.resolve(path.join(atom.getConfigDirPath(), 'styles'), ['css', 'less']) + if fs.isFileSync(stylesheetPath) + stylesheetPath + else + path.join(atom.getConfigDirPath(), 'styles.less') diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index e87028ae3..3bdb15573 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -6,7 +6,7 @@ EmitterMixin = require('emissary').Emitter {File} = require 'pathwatcher' fs = require 'fs-plus' Q = require 'q' -{deprecate} = require 'grim' +Grim = require 'grim' Package = require './package' @@ -57,61 +57,66 @@ class ThemeManager Section: Event Subscription ### - # Essential: Invoke `callback` when all styles have been reloaded. + # Essential: Invoke `callback` when style sheet changes associated with + # updating the list of active themes have completed. # # * `callback` {Function} onDidReloadAll: (callback) -> @emitter.on 'did-reload-all', callback - # Essential: Invoke `callback` when a stylesheet has been added to the dom. + # Deprecated: Invoke `callback` when a stylesheet has been added to the dom. # # * `callback` {Function} # * `stylesheet` {StyleSheet} the style node # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidAddStylesheet: (callback) -> + Grim.deprecate("Use atom.styles.onDidAddStyleElement instead") @emitter.on 'did-add-stylesheet', callback - # Essential: Invoke `callback` when a stylesheet has been removed from the dom. + # Deprecated: Invoke `callback` when a stylesheet has been removed from the dom. # # * `callback` {Function} # * `stylesheet` {StyleSheet} the style node # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidRemoveStylesheet: (callback) -> + Grim.deprecate("Use atom.styles.onDidRemoveStyleElement instead") @emitter.on 'did-remove-stylesheet', callback - # Essential: Invoke `callback` when a stylesheet has been updated. + # Deprecated: Invoke `callback` when a stylesheet has been updated. # # * `callback` {Function} # * `stylesheet` {StyleSheet} the style node # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidUpdateStylesheet: (callback) -> + Grim.deprecate("Use atom.styles.onDidUpdateStyleElement instead") @emitter.on 'did-update-stylesheet', callback - # Essential: Invoke `callback` when any stylesheet has been updated, added, or removed. + # Deprecated: Invoke `callback` when any stylesheet has been updated, added, or removed. # # * `callback` {Function} # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidChangeStylesheets: (callback) -> + Grim.deprecate("Use atom.styles.onDidAdd/RemoveStyleElement instead") @emitter.on 'did-change-stylesheets', callback on: (eventName) -> switch eventName when 'reloaded' - deprecate 'Use ThemeManager::onDidReloadAll instead' + Grim.deprecate 'Use ThemeManager::onDidReloadAll instead' when 'stylesheet-added' - deprecate 'Use ThemeManager::onDidAddStylesheet instead' + Grim.deprecate 'Use ThemeManager::onDidAddStylesheet instead' when 'stylesheet-removed' - deprecate 'Use ThemeManager::onDidRemoveStylesheet instead' + Grim.deprecate 'Use ThemeManager::onDidRemoveStylesheet instead' when 'stylesheet-updated' - deprecate 'Use ThemeManager::onDidUpdateStylesheet instead' + Grim.deprecate 'Use ThemeManager::onDidUpdateStylesheet instead' when 'stylesheets-changed' - deprecate 'Use ThemeManager::onDidChangeStylesheets instead' + Grim.deprecate 'Use ThemeManager::onDidChangeStylesheets instead' else - deprecate 'ThemeManager::on is deprecated. Use event subscription methods instead.' + Grim.deprecate 'ThemeManager::on is deprecated. Use event subscription methods instead.' EmitterMixin::on.apply(this, arguments) ### @@ -197,18 +202,15 @@ class ThemeManager atom.config.set('core.themes', enabledThemeNames) ### - Section: Managing Stylesheets + Section: Private ### - # Public: Returns the {String} path to the user's stylesheet under ~/.atom + # Returns the {String} path to the user's stylesheet under ~/.atom getUserStylesheetPath: -> - stylesheetPath = fs.resolve(path.join(@configDirPath, 'styles'), ['css', 'less']) - if fs.isFileSync(stylesheetPath) - stylesheetPath - else - path.join(@configDirPath, 'styles.less') + Grim.deprecate("Call atom.styles.getUserStyleSheetPath() instead") + atom.styles.getUserStyleSheetPath() - # Public: Resolve and apply the stylesheet specified by the path. + # Resolve and apply the stylesheet specified by the path. # # This supports both CSS and Less stylsheets. # @@ -231,7 +233,7 @@ class ThemeManager loadUserStylesheet: -> @unwatchUserStylesheet() - userStylesheetPath = @getUserStylesheetPath() + userStylesheetPath = atom.styles.getUserStyleSheetPath() return unless fs.isFileSync(userStylesheetPath) @userStylesheetPath = userStylesheetPath @@ -292,10 +294,6 @@ class ThemeManager applyStylesheet: (path, text, type='bundled') -> @styleSheetDisposablesBySourcePath[path] = atom.styles.addStyleSheet(text, sourcePath: path, group: type) - ### - Section: Private - ### - stringToId: (string) -> string.replace(/\\/g, '/') diff --git a/src/workspace.coffee b/src/workspace.coffee index 843827d59..20b46a4d5 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -61,7 +61,7 @@ class Workspace extends Model @addOpener (filePath) => switch filePath when 'atom://.atom/stylesheet' - @open(atom.themes.getUserStylesheetPath()) + @open(atom.styles.getUserStyleSheetPath()) when 'atom://.atom/keymap' @open(atom.keymaps.getUserKeymapPath()) when 'atom://.atom/config'