Files
atom/src/app/syntax.coffee
Nathan Sobo 886995364f Start on syntax global. Use it to replace scoped config settings.
We'll store all syntax-related global state in the `syntax` global. For
now, this means that all scoped properties will be stored here, as well
as all grammars.
2012-12-23 12:50:58 -07:00

60 lines
1.8 KiB
CoffeeScript

_ = require 'underscore'
jQuery = require 'jquery'
Specificity = require 'specificity'
{$$} = require 'space-pen'
module.exports =
class Syntax
constructor: ->
@globalProperties = {}
@propertiesBySelector = {}
addProperties: (args...) ->
scopeSelector = args.shift() if args.length > 1
properties = args.shift()
if scopeSelector
@propertiesBySelector[scopeSelector] ?= {}
_.extend(@propertiesBySelector[scopeSelector], properties)
else
_.extend(@globalProperties, properties)
getProperty: (scope, keyPath) ->
for object in @propertiesForScope(scope)
value = _.valueForKeyPath(object, keyPath)
return value if value?
undefined
propertiesForScope: (scope) ->
matchingSelectors = []
element = @buildScopeElement(scope)
while element
matchingSelectors.push(@matchingSelectorsForElement(element)...)
element = element.parentNode
properties = matchingSelectors.map (selector) => @propertiesBySelector[selector]
properties.concat([@globalProperties])
matchingSelectorsForElement: (element) ->
matchingSelectors = []
for selector of @propertiesBySelector
matchingSelectors.push(selector) if jQuery.find.matchesSelector(element, selector)
matchingSelectors.sort (a, b) -> Specificity(b) - Specificity(a)
buildScopeElement: (scope) ->
scope = new Array(scope...)
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]