mirror of
https://github.com/atom/atom.git
synced 2026-01-22 21:38:10 -05:00
Merge pull request #1781 from atom/ns-property-selectors
Don't use the DOM to look up scoped properties
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
"grunt-shell": "~0.3.1",
|
||||
"harmony-collections": "~0.3.8",
|
||||
"json-front-matter": "~0.1.3",
|
||||
"legal-eagle": "~0.3.0",
|
||||
"legal-eagle": "~0.4.0",
|
||||
"minidump": "0.5.x",
|
||||
"rcedit": "~0.1.2",
|
||||
"request": "~2.27.0",
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
"git-utils": "^1.1.1",
|
||||
"guid": "0.0.10",
|
||||
"jasmine-tagged": ">=1.1.1 <2.0",
|
||||
"mkdirp": "0.3.5",
|
||||
"keytar": "1.x",
|
||||
"less-cache": "0.12.0",
|
||||
"mixto": "1.x",
|
||||
"mkdirp": "0.3.5",
|
||||
"nslog": "0.5.0",
|
||||
"oniguruma": "^1.0.4",
|
||||
"optimist": "0.4.0",
|
||||
@@ -42,6 +42,7 @@
|
||||
"random-words": "0.0.1",
|
||||
"runas": "0.5.x",
|
||||
"scandal": "0.15.2",
|
||||
"scoped-property-store": "^0.6.0",
|
||||
"scrollbar-style": "^0.1.0",
|
||||
"season": ">=1.0.2 <2.0",
|
||||
"semver": "1.1.4",
|
||||
|
||||
@@ -2,6 +2,8 @@ _ = require 'underscore-plus'
|
||||
{specificity} = require 'clear-cut'
|
||||
{Subscriber} = require 'emissary'
|
||||
{GrammarRegistry, ScopeSelector} = require 'first-mate'
|
||||
ScopedPropertyStore = require 'scoped-property-store'
|
||||
PropertyAccessors = require 'property-accessors'
|
||||
|
||||
{$, $$} = require './space-pen-extensions'
|
||||
Token = require './token'
|
||||
@@ -14,6 +16,7 @@ Token = require './token'
|
||||
# language-specific comment regexes.
|
||||
module.exports =
|
||||
class Syntax extends GrammarRegistry
|
||||
PropertyAccessors.includeInto(this)
|
||||
Subscriber.includeInto(this)
|
||||
atom.deserializers.add(this)
|
||||
|
||||
@@ -24,34 +27,28 @@ class Syntax extends GrammarRegistry
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
@scopedPropertiesIndex = 0
|
||||
@scopedProperties = []
|
||||
@propertyStore = new ScopedPropertyStore
|
||||
|
||||
serialize: ->
|
||||
{deserializer: @constructor.name, @grammarOverridesByPath}
|
||||
|
||||
createToken: (value, scopes) -> new Token({value, scopes})
|
||||
|
||||
# Deprecated: Used by settings-view to display snippets for packages
|
||||
@::accessor 'scopedProperties', -> @propertyStore.propertySets
|
||||
|
||||
addProperties: (args...) ->
|
||||
name = args.shift() if args.length > 2
|
||||
[selector, properties] = args
|
||||
|
||||
@scopedProperties.unshift(
|
||||
name: name
|
||||
selector: selector,
|
||||
properties: properties,
|
||||
specificity: specificity(selector),
|
||||
index: @scopedPropertiesIndex++
|
||||
)
|
||||
propertiesBySelector = {}
|
||||
propertiesBySelector[selector] = properties
|
||||
@propertyStore.addProperties(name, propertiesBySelector)
|
||||
|
||||
removeProperties: (name) ->
|
||||
for properties in @scopedProperties.filter((properties) -> properties.name is name)
|
||||
_.remove(@scopedProperties, properties)
|
||||
@propertyStore.removeProperties(name)
|
||||
|
||||
clearProperties: ->
|
||||
@scopedProperties = []
|
||||
@scopedPropertiesIndex = 0
|
||||
@propertyStore = new ScopedPropertyStore
|
||||
|
||||
# Public: Get a property for the given scope and key path.
|
||||
#
|
||||
@@ -66,48 +63,21 @@ class Syntax extends GrammarRegistry
|
||||
#
|
||||
# Returns a {String} property value or undefined.
|
||||
getProperty: (scope, keyPath) ->
|
||||
for object in @propertiesForScope(scope, keyPath)
|
||||
value = _.valueForKeyPath(object, keyPath)
|
||||
return value if value?
|
||||
undefined
|
||||
scopeChain = scope
|
||||
.map (scope) ->
|
||||
scope = ".#{scope}" unless scope.indexOf('.') is 0
|
||||
scope
|
||||
.join(' ')
|
||||
@propertyStore.getPropertyValue(scopeChain, keyPath)
|
||||
|
||||
propertiesForScope: (scope, keyPath) ->
|
||||
matchingProperties = []
|
||||
candidates = @scopedProperties.filter ({properties}) -> _.valueForKeyPath(properties, keyPath)?
|
||||
if candidates.length
|
||||
element = @buildScopeElement(scope)
|
||||
while element
|
||||
matchingProperties.push(@matchingPropertiesForElement(element, candidates)...)
|
||||
element = element.parentNode
|
||||
matchingProperties
|
||||
scopeChain = scope
|
||||
.map (scope) ->
|
||||
scope = ".#{scope}" unless scope.indexOf('.') is 0
|
||||
scope
|
||||
.join(' ')
|
||||
|
||||
matchingPropertiesForElement: (element, candidates) ->
|
||||
matchingScopedProperties = candidates.filter ({selector}) ->
|
||||
$.find.matchesSelector(element, selector)
|
||||
matchingScopedProperties.sort (a, b) ->
|
||||
if a.specificity == b.specificity
|
||||
b.index - a.index
|
||||
else
|
||||
b.specificity - a.specificity
|
||||
_.pluck matchingScopedProperties, 'properties'
|
||||
|
||||
buildScopeElement: (scope) ->
|
||||
scope = scope.slice()
|
||||
element = $$ ->
|
||||
elementsForRemainingScopes = =>
|
||||
classString = scope.shift()
|
||||
classes = classString.replace(/^\./, '').replace(/\./g, ' ')
|
||||
if scope.length
|
||||
@div class: classes, elementsForRemainingScopes
|
||||
else
|
||||
@div class: classes
|
||||
elementsForRemainingScopes()
|
||||
|
||||
deepestChild = element.find(":not(:has(*))")
|
||||
if deepestChild.length
|
||||
deepestChild[0]
|
||||
else
|
||||
element[0]
|
||||
@propertyStore.getProperties(scopeChain, keyPath)
|
||||
|
||||
cssSelectorFromScopeSelector: (scopeSelector) ->
|
||||
new ScopeSelector(scopeSelector).toCssSelector()
|
||||
|
||||
Reference in New Issue
Block a user