Made indentation 2 spaces instead of 4

Made indentation 2 spaces instead of 4

--- grammars/latex.cson
+++ grammars/latex.cson
@@ -9,773 +9,773 @@
 # Rules to be implemented. Please add to repository and link to a 'meta' to include.
 # The following rules correspond to the ten special latex characters
 patterns: [
-    {
-        include: '#controlMeta'
-    }
-    {
-        include: '#percentMeta'
-    }
-    {
-        include: '#dollarMeta'
-    }
-    {
-        include: '#tildeMeta'
-    }
-    {
-        include: '#ampersandMeta'
-    }
-    {
-        include: '#openCurlyBracketMeta'
-    }
-    {
-        include: '#closeCurlyBracketMeta'
-    }
-    {
-        include: '#underscoreMeta'
-    }
-    {
-        include: '#caretMeta'
-    }
-    {
-        include: '#hashtagMeta'
-    }
+  {
+    include: '#controlMeta'
+  }
+  {
+    include: '#percentMeta'
+  }
+  {
+    include: '#dollarMeta'
+  }
+  {
+    include: '#tildeMeta'
+  }
+  {
+    include: '#ampersandMeta'
+  }
+  {
+    include: '#openCurlyBracketMeta'
+  }
+  {
+    include: '#closeCurlyBracketMeta'
+  }
+  {
+    include: '#underscoreMeta'
+  }
+  {
+    include: '#caretMeta'
+  }
+  {
+    include: '#hashtagMeta'
+  }
 ]

 # List of available rules. Must 'include' a rule to patterns for it to be implemented.
 # Thinking of moving pure TeX commands to a separate file and linking it in here (like the preexisting package).
 repository:
 # Meta Commands
-    controlMeta: {
-        comment: 'This is (ideally) called when a backslash is found.'
-        patterns: [
-            {
-                include: '#doubleBackslash'
-            }
-            {
-                include: '#escapedCharacter'
-            }
-            {
-                include: '#accents'
-            }
-            {
-                include: '#documentclass'
-            }
-            {
-                include: '#usepackage'
-            }
-            {
-                include: '#inputFile'
-            }
-            {
-                include: '#documentEnvironment'
-            }
-            {
-                include: '#figureEnvironment'
-            }
-            {
-                include: '#mathEnvironmentMeta'
-            }
-            {
-                include: '#genericEnvironment'
-            }
-            {
-                include: '#sectioning'
-            }
-            {
-                include: '#hypersetup'
-            }
-            {
-                include: '#makeatsomething'
-            }
-            {
-                include: '#genericMacro'
-            }
-        ]
-    }
-    percentMeta: {
-        comment: 'This is called when there is a lone percent sign (escaped covered by controlMeta).'
-        patterns: [
-            {
-                comment: 'Should work so long it is the end of any comment; eg. % other% TEX = ...'
-                include: '#magicComment'
-            }
-            {
-                include: '#lineComment'
-            }
-        ]
-    }
-    dollarMeta: {
-        comment: 'Called when $ sign found'
-        patterns: [
-            {
-                include: '#displayMathMode'
-            }
-            {
-                include: '#inlineMathMode'
-            }
-        ]
-    }
-    tildeMeta: {
-        comment: 'This is only an unbreaking space (when alone).'
-        name: 'punctuation.space.latex'
-        match: '~'
-    }
-    ampersandMeta: {
-        comment: 'The ampersand normally represents alignment (catcode 4).'
-        comment: 'Probably not useful (or legal) outside of align or table environment. However, it must be left this way to let users implement custom environments.'
-        name: 'punctuation.alignment.latex'
-        match: '&'
-    }
-    openCurlyBracketMeta: {
-        contentName: 'variable.parameter.argument.latex'
-        begin: '{'
-        beginCaptures:
-            0:
-                name: 'punctuation.definition.argument.latex'
-        end: '}'
-        endCaptures:
-            0:
-                name: 'punctuation.definition.argument.latex'
-        patterns: [
-            comment: 'Optimisation good to implement here. Rework commentMeta to be a more general check for escaped characters and comments'
-            {
-                include: '#escapedCharacter'
-            }
-            {
-                include: '#lineComment'
-            }
-            {
-                include: '$base'
-            }
-        ]
-    }
-    closeCurlyBracketMeta: {
-        comment: 'To reach this means unbalanced brackets: THIS IS AN ERROR.'
+  controlMeta: {
+    comment: 'This is (ideally) called when a backslash is found.'
+    patterns: [
+      {
+        include: '#doubleBackslash'
+      }
+      {
+        include: '#escapedCharacter'
+      }
+      {
+        include: '#accents'
+      }
+      {
+        include: '#documentclass'
+      }
+      {
+        include: '#usepackage'
+      }
+      {
+        include: '#inputFile'
+      }
+      {
+        include: '#documentEnvironment'
+      }
+      {
+        include: '#figureEnvironment'
+      }
+      {
+        include: '#mathEnvironmentMeta'
+      }
+      {
+        include: '#genericEnvironment'
+      }
+      {
+        include: '#sectioning'
+      }
+      {
+        include: '#hypersetup'
+      }
+      {
+        include: '#makeatsomething'
+      }
+      {
+        include: '#genericMacro'
+      }
+    ]
+  }
+  percentMeta: {
+    comment: 'This is called when there is a lone percent sign (escaped covered by controlMeta).'
+    patterns: [
+      {
+        comment: 'Should work so long it is the end of any comment; eg. % other% TEX = ...'
+        include: '#magicComment'
+      }
+      {
+        include: '#lineComment'
+      }
+    ]
+  }
+  dollarMeta: {
+    comment: 'Called when $ sign found'
+    patterns: [
+      {
+        include: '#displayMathMode'
+      }
+      {
+        include: '#inlineMathMode'
+      }
+    ]
+  }
+  tildeMeta: {
+    comment: 'This is only an unbreaking space (when alone).'
+    name: 'punctuation.space.latex'
+    match: '~'
+  }
+  ampersandMeta: {
+    comment: 'The ampersand normally represents alignment (catcode 4).'
+    comment: 'Probably not useful (or legal) outside of align or table environment. However, it must be left this way to let users implement custom environments.'
+    name: 'punctuation.alignment.latex'
+    match: '&'
+  }
+  openCurlyBracketMeta: {
+    contentName: 'variable.parameter.argument.latex'
+    begin: '{'
+    beginCaptures:
+      0:
+        name: 'punctuation.definition.argument.latex'
+    end: '}'
+    endCaptures:
+      0:
+        name: 'punctuation.definition.argument.latex'
+    patterns: [
+      comment: 'Optimisation good to implement here. Rework commentMeta to be a more general check for escaped characters and comments'
+      {
+        include: '#escapedCharacter'
+      }
+      {
+        include: '#lineComment'
+      }
+      {
+        include: '$base'
+      }
+    ]
+  }
+  closeCurlyBracketMeta: {
+    comment: 'To reach this means unbalanced brackets: THIS IS AN ERROR.'
+    name: 'invalid.illegal.latex'
+    match: '}'
+  }
+  underscoreMeta: {
+    comment: 'Underscore means subscript. It will take an argument in brackets if possible. If not, just the single next character.'
+    comment: 'Only valid when within mathmode. Will address this later.'
+    patterns: [
+      {
+        include: '#underscoreWithArgument'
+      }
+      {
+        include: '#underscoreNoArgument'
+      }
+    ]
+  }
+  underscoreWithArgument: {
+    comment: 'Matches an underscore and between curly brackets'
+    name: 'punctuation.subscript.latex'
+    begin: '_\\s*(?={)'
+    end: '(?<=\\})'
+    patterns: [
+      {
+        include: '#argumentScope'
+      }
+    ]
+  }
+  underscoreNoArgument: {
+    comment: 'Matches an underscore and next character or macro'
+    comment: 'Considering making this give a warning, as brackets is best practice'
+    name: 'punctuation.subscript.latex'
+    match: '_\\s*(\\\\[a-zA-Z]+|\\\\[.]|.)?'
+  }
+  caretMeta: {
+    comment: 'Like underscore, but superscript'
+    patterns: [
+      {
+        include: '#caretWithArgument'
+      }
+      {
+        include: '#caretNoArgument'
+      }
+    ]
+  }
+  caretWithArgument: {
+    comment: 'Matches a caret and between curly brackets'
+    name: 'punctuation.superscript.latex'
+    begin: '\\^\\s*(?={)'
+    end: '(?<=\\})'
+    patterns: [
+      {
+        include: '#argumentScope'
+      }
+    ]
+  }
+  caretNoArgument: {
+    comment: 'Matches a caret and next character or macro'
+    comment: 'Considering making this give a warning, as brackets is best practice'
+    name: 'punctuation.superscript.latex'
+    match: '\\^\\s*(\\\\[a-zA-Z]+|\\\\[.]|.)?'
+  }
+  hashtagMeta: {
+    comment: 'I dont like calling this the pound symbol. Catcode says it is a parameter identifier.'
+    match: '(\\#{3,}[0-9]+)|(\\#{2}[0-9]+)|(\\#[0-9]+)'
+    captures:
+      1:
+        name: 'variable.parameter.hashtag.3.latex'
+      2:
+        name: 'variable.parameter.hashtag.2.latex'
+      3:
+        name: 'variable.parameter.hashtag.1.latex'
+  }
+# Other
+  escapedCharacter: {
+    comment: 'Finds escaped characters like \$ and \%. Uses this regex so unique capture groups can be used.'
+    name: 'constant.character.latex'
+    match: '(\\\\)(\\&|\\%|\\$|\\#|\\_|\\{|\\}|(textascii(tilde|circum)|textbackslash)(?=[^a-zA-Z@]))'
+  }
+  accents: {
+    comment: 'For standard latex accent macros such as \^ or \`'
+    name: 'constant.character.accent.latex'
+    match: '''(\\\\)([\\`\\'\\^\\"\\~\\=\\.](\\w|\\{\\w?\\})|[Hcklbdruv]\\{\\w?\\})'''
+  }
+  hypersetup: {
+    comment: 'Recongnises hypersetup environment. Can be extended to be a general key-option scoper, but this (potentially) allows custom colours for known keys.'
+    name: 'meta.preamble.latex'
+    begin: '(\\\\)hypersetup(?=[^a-zA-Z@])'
+    beginCaptures:
+      0:
+        name: 'keyword.control.preamble.hypersetup.latex'
+      1:
+        name: 'punctuation.definition.function.latex'
+    end: '(?<=\\})|(^\\s*$)'
+    endCaptures:
+      1:
         name: 'invalid.illegal.latex'
-        match: '}'
-    }
-    underscoreMeta: {
-        comment: 'Underscore means subscript. It will take an argument in brackets if possible. If not, just the single next character.'
-        comment: 'Only valid when within mathmode. Will address this later.'
-        patterns: [
-            {
-                include: '#underscoreWithArgument'
-            }
-            {
-                include: '#underscoreNoArgument'
-            }
-        ]
-    }
-    underscoreWithArgument: {
-        comment: 'Matches an underscore and between curly brackets'
-        name: 'punctuation.subscript.latex'
-        begin: '_\\s*(?={)'
-        end: '(?<=\\})'
-        patterns: [
-            {
-                include: '#argumentScope'
-            }
-        ]
-    }
-    underscoreNoArgument: {
-        comment: 'Matches an underscore and next character or macro'
-        comment: 'Considering making this give a warning, as brackets is best practice'
-        name: 'punctuation.subscript.latex'
-        match: '_\\s*(\\\\[a-zA-Z]+|\\\\[.]|.)?'
-    }
-    caretMeta: {
-        comment: 'Like underscore, but superscript'
-        patterns: [
-            {
-                include: '#caretWithArgument'
-            }
-            {
-                include: '#caretNoArgument'
-            }
-        ]
-    }
-    caretWithArgument: {
-        comment: 'Matches a caret and between curly brackets'
-        name: 'punctuation.superscript.latex'
-        begin: '\\^\\s*(?={)'
-        end: '(?<=\\})'
-        patterns: [
-            {
-                include: '#argumentScope'
-            }
-        ]
-    }
-    caretNoArgument: {
-        comment: 'Matches a caret and next character or macro'
-        comment: 'Considering making this give a warning, as brackets is best practice'
-        name: 'punctuation.superscript.latex'
-        match: '\\^\\s*(\\\\[a-zA-Z]+|\\\\[.]|.)?'
-    }
-    hashtagMeta: {
-        comment: 'I dont like calling this the pound symbol. Catcode says it is a parameter identifier.'
-        match: '(\\#{3,}[0-9]+)|(\\#{2}[0-9]+)|(\\#[0-9]+)'
-        captures:
-            1:
-                name: 'variable.parameter.hashtag.3.latex'
-            2:
-                name: 'variable.parameter.hashtag.2.latex'
-            3:
-                name: 'variable.parameter.hashtag.1.latex'
-    }
-# Other
-    escapedCharacter: {
-        comment: 'Finds escaped characters like \$ and \%. Uses this regex so unique capture groups can be used.'
+    patterns: [
+      {
+        include: '#argumentScope'
+      }
+    ]
+  }
+  lineComment: {
+    comment: 'Line comment. This will find an available % sign and match it to just before another % (where it looks for a magic comment) or the end.'
+    name: 'comment.line.percentage.latex'
+    begin: '%'
+    end: '(?=%)|$'
+  }
+  escapedPercent: {
+    comment: 'Escaped % sign. Possible deprecated by escapedCharacter.'
+    name: 'constant.character.latex'
+    match: '\\\\%'
+  }
+  escapedCurlyBracket: {
+    comment: 'Escaped }. Possible deprecated by escapedCharacter.'
+    name: 'constant.character.latex'
+    match: '\\\\}|\\\\{'
+  }
+  usepackage: {
+    comment: 'Package finder. Similar to documentclass, but allows custom colours. A macro name is only valid with letters (exceptions apply--eg. makeatletter). This checks to see if the name is purely "usepackage" and the following character is not a legal part of the macro name.'
+    name: 'meta.preamble.latex'
+    begin: '(\\\\)usepackage(?=[^a-zA-Z@])'
+    beginCaptures:
+      0:
+        name: 'keyword.control.preamble.latex'
+      1:
+        name: 'punctuation.definition.function.latex'
+    end: '(?<=\\})|(^\\s*$)'
+    endCaptures:
+      1:
+        name: 'invalid.illegal.latex'
+    patterns:[
+      {
+        include: '#awaitingArgumentBrackets'
+      }
+      {
+        comment: 'Only this one necessary because escaped characters will be picked up by awaitingArgumentBrackets.'
+        include: '#lineComment'
+      }
+      {
+        comment: 'Will try and find optional arguments first.'
+        include: '#optionalArgumentScope'
+      }
+      {
+        include: '#argumentScope'
+      }
+    ]
+  }
+  sectioning: {
+    comment: 'Covers all sectioning commands such as section, subsection, subparagraph, etc.'
+    name: 'support.function.section.latex'
+    begin: '(\\\\)((sub){0,2}section|(sub){0,1}paragraph|part|chapter)(\\*)?(?=[^a-zA-Z@])'
+    beginCaptures:
+      0:
+        name: 'keyword.control.section.latex'
+      1:
+        name: 'punctuation.definition.function.latex'
+    end: '(?<=\\})|(^\\s*$)'
+    endCaptures:
+      1:
+        name: 'invalid.illegal.latex'
+    patterns: [
+      {
+        include: '#awaitingArgumentBrackets'
+      }
+      {
+        comment: 'Only this one necessary because escaped characters will be picked up by awaitingArgumentBrackets.'
+        include: '#lineComment'
+      }
+      {
+        comment: 'Will try and find optional arguments first.'
+        include: '#optionalArgumentScope'
+      }
+      {
+        include: '#argumentScope'
+      }
+    ]
+  }
+  doubleBackslash: {
+    match: '\\\\\\\\'
+    name: 'punctuation.break.latex'
+  }
+  commentMeta: {
+    comment: 'Main purpose is to distinguish escaped % from comments. Deprecated.'
+    patterns: [
+      {
+        include: '#doubleBackslash'
+      }
+      {
+        include: '#escapedPercent'
+      }
+      {
+        include: '#magicComment'
+      }
+      {
+        include: '#lineComment'
+      }
+    ]
+  }
+  genericMacro: {
+    comment: 'A catch all for latex macros that have not already been identified.'
+    name: 'support.function.general.latex'
+    match: '\\\\[a-zA-Z]+'
+  }
+  magicComment: {
+    comment: 'Magic commands work in first 20 lines. Can be improved to change color depending if the command matches a known string'
+    name: 'keyword.control.magic.latex'
+    match: '''(?x)  # Allow comments like this
+           ((        # Capture groups 1 & 2
+             (%)     # Capture percent sign
+             (\\ !(?>TEX|BIB)\\ )  # Exact match required
+             (\\S+)    # A word (this is required as far as I know)
+             )       # End capture group 2
+             (\\ = \\ )  # Match = with space (required)
+           )         # End capture group 1
+           .*$       # To end; some options have spaces
+         '''
+  }
+  documentclass: {
+    comment: 'Documentclass finder.'
+    name: 'meta.preamble.latex'
+    begin: '(\\\\)documentclass(?=[^a-zA-Z@])'
+    beginCaptures:
+      0:
+        name: 'keyword.control.preamble.latex'
+      1:
+        name: 'punctuation.definition.function.latex'
+    end: '(?<=\\})|(^\\s*$)'
+    endCaptures:
+      1:
+        name: 'invalid.illegal.latex'
+    patterns:[
+      {
+        include: '#awaitingArgumentBrackets'
+      }
+      {
+        include: '#lineComment'
+      }
+      {
+        include: '#optionalArgumentScope'
+      }
+      {
+        include: '#argumentScope'
+      }
+    ]
+  }
+  awaitingArgumentBrackets: {
+    comment: 'Anything not whitespace, opening bracket or comment will be flagged as invalid.illegal. Should take priority over other matches (even comments, as comments have the escaped % exception).'
+    match: '[^{\\[\\s%]+'
+    name: 'invalid.illegal.latex'
+  }
+  optionalArgumentScope: {
+    comment: 'Matches options brackets and everything inside them.'
+    contentName: 'variable.parameter.optional.latex'
+    begin: '\\['
+    beginCaptures:
+      0:
+        name: 'punctuation.definition.optional.begin.latex'
+    end: '\\]'
+    endCaptures:
+      0:
+        name: 'punctuation.definition.optional.end.latex'
+    patterns: [
+      {
+        comment: 'AFAIK, the optional parameters never have nested brackets. Will come back to this after a while or if I find they do.'
+        include: '#commentMeta'
+      }
+      {
+        include: '#escapedCurlyBracket'
+      }
+      {
+        include: '#openCurlyBracketMeta'
+      }
+    ]
+  }
+  argumentScope: {
+    comment: 'Matches arguments brackets (the outmost of nested brackets). Specifically for commands like usepackage.'
+    contentName: 'variable.parameter.argument.latex'
+    begin: '\\{'
+    beginCaptures:
+      0:
+        name: 'punctuation.definition.argument.begin.latex'
+    end: '\\}'
+    endCaptures:
+      0:
+        name: 'punctuation.definition.argument.end.latex'
+    patterns: [
+      {
+        include: '#commentMeta'
+      }
+      {
+        include: '#escapedCurlyBracket'
+      }
+      {
+        include: '#openCurlyBracketMeta'
+      }
+    ]
+  }
+  nestedSquareBrackets: {
+    contentName: 'variable.parameter.optional.latex'
+    begin: '\\['
+    beginCaptures:
+      0:
+        name: 'punctuation.definition.optional.begin.latex'
+    end: '\\]'
+    endCaptures:
+      0:
+        name: 'punctuation.definition.optional.end.latex'
+    patterns: [
+      comment: 'Optimisation good to implement here. Rework commentMeta to be a more general check for escaped characters and comments'
+      {
+        include: '#commentMeta'
+      }
+      {
+        include: '#escapedCloseSquareBracket'
+      }
+      {
+        include: '#nestedSquareBrackets'
+      }
+    ]
+  }
+  endArgumentsMeta: {
+    patterns: [
+      {
+        include: '#doubleBackslash'
+      }
+      {
+        include: '#escapedCurlyBracket'
+      }
+    ]
+  }
+  texKeywords: {
+    comment: 'Official TeX keywords that can be used in certain situations. Done AFAIK.'
+    name: 'support.constant.keyword.latex'
+    match: '''(?x)
+         at | by | bp | cc | cm | dd | depth | em | ex | fil | fill | filll | height | in | minus | mm | mu | pc | plus | pt | sp | spread | to | true | width
+         '''
+  }
+  texPrimitives: {
+    comment: 'Primitives (no smaller definitions) can be confirmed using \show\<cm>. This list is obviously not finished.'
+    match: '''(?x)
+         (\\\\)(
+         above | badness | relax | show
+         )
+         '''
+  }
+  inlineMathMode: {
+    comment: 'This can be triggered using $ or \( \). Both can be used in the same pair.'
+    contentName: 'string.other.math.inline.latex'
+    begin: '(\\$)|(\\\\\\()'
+    beginCaptures:
+      0:
+        name: 'string.other.math.inline.begin.latex'
+    end: '(\\$)|(\\\\\\))'
+    endCaptures:
+      0:
+        name: 'string.other.math.inline.end.latex'
+    patterns: [
+      {
+        include: '#commentMeta'
+      }
+      {
+        comment: 'Mathmode special characters are different to text; eg. textbackslash is not allowed'
         name: 'constant.character.latex'
-        match: '(\\\\)(\\&|\\%|\\$|\\#|\\_|\\{|\\}|(textascii(tilde|circum)|textbackslash)(?=[^a-zA-Z@]))'
-    }
-    accents: {
-        comment: 'For standard latex accent macros such as \^ or \`'
-        name: 'constant.character.accent.latex'
-        match: '''(\\\\)([\\`\\'\\^\\"\\~\\=\\.](\\w|\\{\\w?\\})|[Hcklbdruv]\\{\\w?\\})'''
-    }
-    hypersetup: {
-        comment: 'Recongnises hypersetup environment. Can be extended to be a general key-option scoper, but this (potentially) allows custom colours for known keys.'
-        name: 'meta.preamble.latex'
-        begin: '(\\\\)hypersetup(?=[^a-zA-Z@])'
-        beginCaptures:
-            0:
-                name: 'keyword.control.preamble.hypersetup.latex'
-            1:
-                name: 'punctuation.definition.function.latex'
-        end: '(?<=\\})|(^\\s*$)'
-        endCaptures:
-            1:
-                name: 'invalid.illegal.latex'
-        patterns: [
-            {
-                include: '#argumentScope'
-            }
-        ]
-    }
-    lineComment: {
-        comment: 'Line comment. This will find an available % sign and match it to just before another % (where it looks for a magic comment) or the end.'
-        name: 'comment.line.percentage.latex'
-        begin: '%'
-        end: '(?=%)|$'
-    }
-    escapedPercent: {
-                comment: 'Escaped % sign. Possible deprecated by escapedCharacter.'
+        match: '\\\\\\$'
+      }
+      {
+        comment: 'When in inline math, the exit can only be $ or \)'
+        name: 'invalid.illegal.latex'
+        match: '(\\\\(\\[|\\(|\\)))'
+      }
+      {
+        include: '$base'
+      }
+    ]
+  }
+  displayMathMode: {
+    comment: 'This can be triggered using $$ or \[ \]. Both can be used in the same pair.'
+    contentName: 'string.other.math.display.latex'
+    begin: '(\\$\\$)|(\\\\\\[)'
+    beginCaptures:
+      0:
+        name: 'string.other.math.display.begin.latex'
+      1:
+        name: 'invalid.deprecated.latex'
+    end: '(\\$\\$)|(\\\\\\])'
+    endCaptures:
+      0:
+        name: 'string.other.math.display.end.latex'
+      1:
+        name: 'invalid.deprecated.latex'
+    patterns: [
+      {
+        include: '#commentMeta'
+      }
+      {
+        comment: 'Mathmode special characters are different to text; eg. textbackslash is not allowed'
         name: 'constant.character.latex'
-        match: '\\\\%'
-    }
-    escapedCurlyBracket: {
-        comment: 'Escaped }. Possible deprecated by escapedCharacter.'
-        name: 'constant.character.latex'
-        match: '\\\\}|\\\\{'
-    }
-    usepackage: {
-        comment: 'Package finder. Similar to documentclass, but allows custom colours. A macro name is only valid with letters (exceptions apply--eg. makeatletter). This checks to see if the name is purely "usepackage" and the following character is not a legal part of the macro name.'
-        name: 'meta.preamble.latex'
-        begin: '(\\\\)usepackage(?=[^a-zA-Z@])'
-        beginCaptures:
-            0:
-                name: 'keyword.control.preamble.latex'
-            1:
-                name: 'punctuation.definition.function.latex'
-        end: '(?<=\\})|(^\\s*$)'
-        endCaptures:
-            1:
-                name: 'invalid.illegal.latex'
-        patterns:[
-            {
-                include: '#awaitingArgumentBrackets'
-            }
-            {
-                comment: 'Only this one necessary because escaped characters will be picked up by awaitingArgumentBrackets.'
-                include: '#lineComment'
-            }
-            {
-                comment: 'Will try and find optional arguments first.'
-                include: '#optionalArgumentScope'
-            }
-            {
-                include: '#argumentScope'
-            }
-        ]
-    }
-    sectioning: {
-        comment: 'Covers all sectioning commands such as section, subsection, subparagraph, etc.'
-        name: 'support.function.section.latex'
-        begin: '(\\\\)((sub){0,2}section|(sub){0,1}paragraph|part|chapter)(\\*)?(?=[^a-zA-Z@])'
-        beginCaptures:
-            0:
-                name: 'keyword.control.section.latex'
-            1:
-                name: 'punctuation.definition.function.latex'
-        end: '(?<=\\})|(^\\s*$)'
-        endCaptures:
-            1:
-                name: 'invalid.illegal.latex'
-        patterns: [
-            {
-                include: '#awaitingArgumentBrackets'
-            }
-            {
-                comment: 'Only this one necessary because escaped characters will be picked up by awaitingArgumentBrackets.'
-                include: '#lineComment'
-            }
-            {
-                comment: 'Will try and find optional arguments first.'
-                include: '#optionalArgumentScope'
-            }
-            {
-                include: '#argumentScope'
-            }
-        ]
-    }
-    doubleBackslash: {
-        match: '\\\\\\\\'
-        name: 'punctuation.break.latex'
-    }
-    commentMeta: {
-        comment: 'Main purpose is to distinguish escaped % from comments. Deprecated.'
-        patterns: [
-            {
-                include: '#doubleBackslash'
-            }
-            {
-                include: '#escapedPercent'
-            }
-            {
-                include: '#magicComment'
-            }
-            {
-                include: '#lineComment'
-            }
-        ]
-    }
-    genericMacro: {
-        comment: 'A catch all for latex macros that have not already been identified.'
-        name: 'support.function.general.latex'
-        match: '\\\\[a-zA-Z]+'
-    }
-    magicComment: {
-        comment: 'Magic commands work in first 20 lines. Can be improved to change color depending if the command matches a known string'
-        name: 'keyword.control.magic.latex'
-        match: '''(?x)    # Allow comments like this
-            ((              # Capture groups 1 & 2
-                (%)         # Capture percent sign
-                (\\ !(?>TEX|BIB)\\ )    # Exact match required
-                (\\S+)      # A word (this is required as far as I know)
-                )           # End capture group 2
-                (\\ = \\ )  # Match = with space (required)
-            )               # End capture group 1
-            .*$             # To end; some options have spaces
-        '''
-    }
-    documentclass: {
-        comment: 'Documentclass finder.'
-        name: 'meta.preamble.latex'
-        begin: '(\\\\)documentclass(?=[^a-zA-Z@])'
-        beginCaptures:
-            0:
-                name: 'keyword.control.preamble.latex'
-            1:
-                name: 'punctuation.definition.function.latex'
-        end: '(?<=\\})|(^\\s*$)'
-        endCaptures:
-            1:
-                name: 'invalid.illegal.latex'
-        patterns:[
-            {
-                include: '#awaitingArgumentBrackets'
-            }
-            {
-                include: '#lineComment'
-            }
-            {
-                include: '#optionalArgumentScope'
-            }
-            {
-                include: '#argumentScope'
-            }
-        ]
-    }
-    awaitingArgumentBrackets: {
-        comment: 'Anything not whitespace, opening bracket or comment will be flagged as invalid.illegal. Should take priority over other matches (even comments, as comments have the escaped % exception).'
-        match: '[^{\\[\\s%]+'
+        match: '\\\\\\$'
+      }
+      {
+        comment: 'When in display math, the exit can only be $$ or \]'
         name: 'invalid.illegal.latex'
-    }
-    optionalArgumentScope: {
-        comment: 'Matches options brackets and everything inside them.'
-        contentName: 'variable.parameter.optional.latex'
-        begin: '\\['
-        beginCaptures:
-            0:
-                name: 'punctuation.definition.optional.begin.latex'
-        end: '\\]'
-        endCaptures:
-            0:
-                name: 'punctuation.definition.optional.end.latex'
-        patterns: [
-            {
-                comment: 'AFAIK, the optional parameters never have nested brackets. Will come back to this after a while or if I find they do.'
-                include: '#commentMeta'
-            }
-            {
-                include: '#escapedCurlyBracket'
-            }
-            {
-                include: '#openCurlyBracketMeta'
-            }
-        ]
-    }
-    argumentScope: {
-        comment: 'Matches arguments brackets (the outmost of nested brackets). Specifically for commands like usepackage.'
-        contentName: 'variable.parameter.argument.latex'
-        begin: '\\{'
-        beginCaptures:
-            0:
-                name: 'punctuation.definition.argument.begin.latex'
-        end: '\\}'
-        endCaptures:
-            0:
-                name: 'punctuation.definition.argument.end.latex'
-        patterns: [
-            {
-                include: '#commentMeta'
-            }
-            {
-                include: '#escapedCurlyBracket'
-            }
-            {
-                include: '#openCurlyBracketMeta'
-            }
-        ]
-    }
-    nestedSquareBrackets: {
-        contentName: 'variable.parameter.optional.latex'
-        begin: '\\['
-        beginCaptures:
-            0:
-                name: 'punctuation.definition.optional.begin.latex'
-        end: '\\]'
-        endCaptures:
-            0:
-                name: 'punctuation.definition.optional.end.latex'
-        patterns: [
-            comment: 'Optimisation good to implement here. Rework commentMeta to be a more general check for escaped characters and comments'
-            {
-                include: '#commentMeta'
-            }
-            {
-                include: '#escapedCloseSquareBracket'
-            }
-            {
-                include: '#nestedSquareBrackets'
-            }
-        ]
-    }
-    endArgumentsMeta: {
-        patterns: [
-            {
-                include: '#doubleBackslash'
-            }
-            {
-                include: '#escapedCurlyBracket'
-            }
-        ]
-    }
-    texKeywords: {
-        comment: 'Official TeX keywords that can be used in certain situations. Done AFAIK.'
-        name: 'support.constant.keyword.latex'
-        match: '''(?x)
-        at | by | bp | cc | cm | dd | depth | em | ex | fil | fill | filll | height | in | minus | mm | mu | pc | plus | pt | sp | spread | to | true | width
-        '''
-    }
-    texPrimitives: {
-        comment: 'Primitives (no smaller definitions) can be confirmed using \show\<cm>. This list is obviously not finished.'
-        match: '''(?x)
-        (\\\\)(
-        above | badness | relax | show
-        )
-        '''
-    }
-    inlineMathMode: {
-        comment: 'This can be triggered using $ or \( \). Both can be used in the same pair.'
-        contentName: 'string.other.math.inline.latex'
-        begin: '(\\$)|(\\\\\\()'
-        beginCaptures:
-            0:
-                name: 'string.other.math.inline.begin.latex'
-        end: '(\\$)|(\\\\\\))'
-        endCaptures:
-            0:
-                name: 'string.other.math.inline.end.latex'
-        patterns: [
-            {
-                include: '#commentMeta'
-            }
-            {
-                comment: 'Mathmode special characters are different to text; eg. textbackslash is not allowed'
-                name: 'constant.character.latex'
-                match: '\\\\\\$'
-            }
-            {
-                comment: 'When in inline math, the exit can only be $ or \)'
-                name: 'invalid.illegal.latex'
-                match: '(\\\\(\\[|\\(|\\)))'
-            }
-            {
-                include: '$base'
-            }
-        ]
-    }
-    displayMathMode: {
-        comment: 'This can be triggered using $$ or \[ \]. Both can be used in the same pair.'
-        contentName: 'string.other.math.display.latex'
-        begin: '(\\$\\$)|(\\\\\\[)'
-        beginCaptures:
-            0:
-                name: 'string.other.math.display.begin.latex'
-            1:
-                name: 'invalid.deprecated.latex'
-        end: '(\\$\\$)|(\\\\\\])'
-        endCaptures:
-            0:
-                name: 'string.other.math.display.end.latex'
-            1:
-                name: 'invalid.deprecated.latex'
-        patterns: [
-            {
-                include: '#commentMeta'
-            }
-            {
-                comment: 'Mathmode special characters are different to text; eg. textbackslash is not allowed'
-                name: 'constant.character.latex'
-                match: '\\\\\\$'
-            }
-            {
-                comment: 'When in display math, the exit can only be $$ or \]'
-                name: 'invalid.illegal.latex'
-                match: '(?<=[^\\\\])(\\$)(?=[^\\$])|(\\\\(\\[|\\(|\\)))'
-            }
-            {
-                include: '$base'
-            }
-        ]
-    }
-    genericEnvironment: {
-        comment: 'Matches environments not recognised by other rules. Less lenient with random formatting here, it is expected to all be on one line.'
-        contentName: 'support.environment.latex'
-        begin: '(\\\\)(begin)(\\{)([\\w \\*]*)(\\})'
-        beginCaptures:
-            1:
-                name: 'punctuation.definition.function.latex'
-            2:
-                name: 'support.function.environment.begin.latex'
-            3:
-                name: 'punctuation.definition.argument.begin.latex'
-            4:
-                name: 'variable.parameter.argument.latex'
-            5:
-                name: 'punctuation.definition.argument.end.latex'
-        end: '(\\\\)(end)(\\{)(\\4)(\\})'
-        endCaptures:
-            1:
-                name: 'punctuation.definition.function.latex'
-            2:
-                name: 'support.function.environment.end.latex'
-            3:
-                name: 'punctuation.definition.argument.begin.latex'
-            4:
-                name: 'variable.parameter.argument.latex'
-            5:
-                name: 'punctuation.definition.argument.end.latex'
-        patterns: [
-            {
-                include: '$base'
-            }
-        ]
-    }
-    documentEnvironment: {
-        comment: 'To stop the entire contents of the document environment being labelled. Its useless anyway, as I split up my work and just include it into the main file.'
-        begin: '(\\\\)(begin)(\\{)(document)(\\})'
-        beginCaptures:
-            1:
-                name: 'punctuation.definition.function.latex'
-            2:
-                name: 'support.function.environment.begin.latex'
-            3:
-                name: 'punctuation.definition.argument.begin.latex'
-            4:
-                name: 'variable.parameter.argument.latex'
-            5:
-                name: 'punctuation.definition.argument.end.latex'
-        end: '(\\\\)(end)(\\{)(document)(\\})'
-        endCaptures:
-            1:
-                name: 'punctuation.definition.function.latex'
-            2:
-                name: 'support.function.environment.end.latex'
-            3:
-                name: 'punctuation.definition.argument.begin.latex'
-            4:
-                name: 'variable.parameter.argument.latex'
-            5:
-                name: 'punctuation.definition.argument.end.latex'
-        patterns: [
-            {
-                include: '$base'
-            }
-        ]
-    }
-    figureEnvironment: {
-        comment: 'Matches the common figure environment'
-        contentName: 'support.environment.figure.latex'
-        begin: '(\\\\)(begin)(\\{)(figure)(\\})((\\[)(\\w*)(\\]))?'
-        beginCaptures:
-            1:
-                name: 'punctuation.definition.function.latex'
-            2:
-                name: 'support.function.environment.begin.latex'
-            3:
-                name: 'punctuation.definition.argument.begin.latex'
-            4:
-                name: 'variable.parameter.argument.latex'
-            5:
-                name: 'punctuation.definition.argument.end.latex'
-            7:
-                name: 'punctuation.definition.optional.begin.latex'
-            8:
-                name: 'variable.parameter.optional.latex'
-            9:
-                name: 'punctuation.definition.optional.end.latex'
-        end: '(\\\\)(end)(\\{)(\\4)(\\})'
-        endCaptures:
-            1:
-                name: 'punctuation.definition.function.latex'
-            2:
-                name: 'support.function.environment.end.latex'
-            3:
-                name: 'punctuation.definition.argument.begin.latex'
-            4:
-                name: 'variable.parameter.argument.latex'
-            5:
-                name: 'punctuation.definition.argument.end.latex'
-        patterns: [
-            {
-                include: '$base'
-            }
-        ]
-    }
-    mathEnvironmentMeta: {
-        comment: 'Matches math environments'
-        patterns: [
-            {
-                include: '#alignMathEnvironment'
-            }
-        ]
-    }
-    alignMathEnvironment: {
-        comment: 'Matches align environment'
-        contentName: 'support.environment.math.align.latex'
-        begin: '(\\\\)(begin)(\\{)(align(\\*)?)(\\})'
-        beginCaptures:
-            1:
-                name: 'punctuation.definition.function.latex'
-            2:
-                name: 'support.function.environment.begin.latex'
-            3:
-                name: 'punctuation.definition.argument.begin.latex'
-            4:
-                name: 'variable.parameter.argument.latex'
-            6:
-                name: 'punctuation.definition.argument.end.latex'
-        end: '(\\\\)(end)(\\{)(\\4)(\\})'
-        endCaptures:
-            1:
-                name: 'punctuation.definition.function.latex'
-            2:
-                name: 'support.function.environment.end.latex'
-            3:
-                name: 'punctuation.definition.argument.begin.latex'
-            4:
-                name: 'variable.parameter.argument.latex'
-            5:
-                name: 'punctuation.definition.argument.end.latex'
-        patterns: [
-            {
-                include: '$base'
-            }
-        ]
-    }
-    makeatsomething: {
-        comment: 'Matches the makeat(letter|other) commands so that they get custom highlighting (because @ is now a character)'
-        name: 'support.function.makeat.latex'
-        begin: '(\\\\)makeatletter\\b'
-        end: '(\\\\)makeatother\\b'
-        patterns: [
-            {
-                include: '#commentMeta'
-            }
-        ]
-    }
-    inputFile: {
-        comment: 'Matches the input/include command and allows custom path colours.'
-        begin: '(\\\\)input(?=[^a-zA-Z@])'
-        beginCaptures:
-            0:
-                name: 'keyword.control.input.latex'
-            1:
-                name: 'punctuation.definition.function.latex'
-        end: '(?<=\\})|(^\\s*$)'
-        endCaptures:
-            1:
-                name: 'invalid.illegal.latex'
-        patterns:[
-            {
-                include: '#awaitingArgumentBrackets'
-            }
-            {
-                comment: 'Only this one necessary because escaped characters will be picked up by awaitingArgumentBrackets.'
-                include: '#lineComment'
-            }
-            {
-                include: '#filePathScope'
-            }
-        ]
-    }
-    filePathScope: {
-        comment: 'Matches a file path (UNIX only, add Windows yourself reader).'
-        contentName: 'variable.parameter.argument.latex'
-        begin: '\\{'
-        beginCaptures:
-            0:
-                name: 'punctuation.definition.argument.begin.latex'
-        end: '\\}'
-        endCaptures:
-            0:
-                name: 'punctuation.definition.argument.end.latex'
-        patterns: [
-            {
-                name: 'support.filepath.back.latex'
-                match: '\\.{2}\\/'
-            }
-            {
-                name: 'support.filepath.home.latex'
-                match: '\\.\\/'
-            }
-            {
-                name: 'support.filepath.root.latex'
-                match: '(?<=\\{)\\/'
-            }
-            {
-                name: 'support.filepath.directory.latex'
-                match: '[^(\\.{1,2}\\/)].*?\\/'
-            }
-            {
-                name: 'support.filepath.file.latex'
-                match: '[^}]*'
-            }
-        ]
-    }
-    verbatim: {
-        comment: 'Finds an inline verbatim string of the format \verb+...+'
-        name: 'string.function.verbatim'
-    }
+        match: '(?<=[^\\\\])(\\$)(?=[^\\$])|(\\\\(\\[|\\(|\\)))'
+      }
+      {
+        include: '$base'
+      }
+    ]
+  }
+  genericEnvironment: {
+    comment: 'Matches environments not recognised by other rules. Less lenient with random formatting here, it is expected to all be on one line.'
+    contentName: 'support.environment.latex'
+    begin: '(\\\\)(begin)(\\{)([\\w \\*]*)(\\})'
+    beginCaptures:
+      1:
+        name: 'punctuation.definition.function.latex'
+      2:
+        name: 'support.function.environment.begin.latex'
+      3:
+        name: 'punctuation.definition.argument.begin.latex'
+      4:
+        name: 'variable.parameter.argument.latex'
+      5:
+        name: 'punctuation.definition.argument.end.latex'
+    end: '(\\\\)(end)(\\{)(\\4)(\\})'
+    endCaptures:
+      1:
+        name: 'punctuation.definition.function.latex'
+      2:
+        name: 'support.function.environment.end.latex'
+      3:
+        name: 'punctuation.definition.argument.begin.latex'
+      4:
+        name: 'variable.parameter.argument.latex'
+      5:
+        name: 'punctuation.definition.argument.end.latex'
+    patterns: [
+      {
+        include: '$base'
+      }
+    ]
+  }
+  documentEnvironment: {
+    comment: 'To stop the entire contents of the document environment being labelled. Its useless anyway, as I split up my work and just include it into the main file.'
+    begin: '(\\\\)(begin)(\\{)(document)(\\})'
+    beginCaptures:
+      1:
+        name: 'punctuation.definition.function.latex'
+      2:
+        name: 'support.function.environment.begin.latex'
+      3:
+        name: 'punctuation.definition.argument.begin.latex'
+      4:
+        name: 'variable.parameter.argument.latex'
+      5:
+        name: 'punctuation.definition.argument.end.latex'
+    end: '(\\\\)(end)(\\{)(document)(\\})'
+    endCaptures:
+      1:
+        name: 'punctuation.definition.function.latex'
+      2:
+        name: 'support.function.environment.end.latex'
+      3:
+        name: 'punctuation.definition.argument.begin.latex'
+      4:
+        name: 'variable.parameter.argument.latex'
+      5:
+        name: 'punctuation.definition.argument.end.latex'
+    patterns: [
+      {
+        include: '$base'
+      }
+    ]
+  }
+  figureEnvironment: {
+    comment: 'Matches the common figure environment'
+    contentName: 'support.environment.figure.latex'
+    begin: '(\\\\)(begin)(\\{)(figure)(\\})((\\[)(\\w*)(\\]))?'
+    beginCaptures:
+      1:
+        name: 'punctuation.definition.function.latex'
+      2:
+        name: 'support.function.environment.begin.latex'
+      3:
+        name: 'punctuation.definition.argument.begin.latex'
+      4:
+        name: 'variable.parameter.argument.latex'
+      5:
+        name: 'punctuation.definition.argument.end.latex'
+      7:
+        name: 'punctuation.definition.optional.begin.latex'
+      8:
+        name: 'variable.parameter.optional.latex'
+      9:
+        name: 'punctuation.definition.optional.end.latex'
+    end: '(\\\\)(end)(\\{)(\\4)(\\})'
+    endCaptures:
+      1:
+        name: 'punctuation.definition.function.latex'
+      2:
+        name: 'support.function.environment.end.latex'
+      3:
+        name: 'punctuation.definition.argument.begin.latex'
+      4:
+        name: 'variable.parameter.argument.latex'
+      5:
+        name: 'punctuation.definition.argument.end.latex'
+    patterns: [
+      {
+        include: '$base'
+      }
+    ]
+  }
+  mathEnvironmentMeta: {
+    comment: 'Matches math environments'
+    patterns: [
+      {
+        include: '#alignMathEnvironment'
+      }
+    ]
+  }
+  alignMathEnvironment: {
+    comment: 'Matches align environment'
+    contentName: 'support.environment.math.align.latex'
+    begin: '(\\\\)(begin)(\\{)(align(\\*)?)(\\})'
+    beginCaptures:
+      1:
+        name: 'punctuation.definition.function.latex'
+      2:
+        name: 'support.function.environment.begin.latex'
+      3:
+        name: 'punctuation.definition.argument.begin.latex'
+      4:
+        name: 'variable.parameter.argument.latex'
+      6:
+        name: 'punctuation.definition.argument.end.latex'
+    end: '(\\\\)(end)(\\{)(\\4)(\\})'
+    endCaptures:
+      1:
+        name: 'punctuation.definition.function.latex'
+      2:
+        name: 'support.function.environment.end.latex'
+      3:
+        name: 'punctuation.definition.argument.begin.latex'
+      4:
+        name: 'variable.parameter.argument.latex'
+      5:
+        name: 'punctuation.definition.argument.end.latex'
+    patterns: [
+      {
+        include: '$base'
+      }
+    ]
+  }
+  makeatsomething: {
+    comment: 'Matches the makeat(letter|other) commands so that they get custom highlighting (because @ is now a character)'
+    name: 'support.function.makeat.latex'
+    begin: '(\\\\)makeatletter\\b'
+    end: '(\\\\)makeatother\\b'
+    patterns: [
+      {
+        include: '#commentMeta'
+      }
+    ]
+  }
+  inputFile: {
+    comment: 'Matches the input/include command and allows custom path colours.'
+    begin: '(\\\\)input(?=[^a-zA-Z@])'
+    beginCaptures:
+      0:
+        name: 'keyword.control.input.latex'
+      1:
+        name: 'punctuation.definition.function.latex'
+    end: '(?<=\\})|(^\\s*$)'
+    endCaptures:
+      1:
+        name: 'invalid.illegal.latex'
+    patterns:[
+      {
+        include: '#awaitingArgumentBrackets'
+      }
+      {
+        comment: 'Only this one necessary because escaped characters will be picked up by awaitingArgumentBrackets.'
+        include: '#lineComment'
+      }
+      {
+        include: '#filePathScope'
+      }
+    ]
+  }
+  filePathScope: {
+    comment: 'Matches a file path (UNIX only, add Windows yourself reader).'
+    contentName: 'variable.parameter.argument.latex'
+    begin: '\\{'
+    beginCaptures:
+      0:
+        name: 'punctuation.definition.argument.begin.latex'
+    end: '\\}'
+    endCaptures:
+      0:
+        name: 'punctuation.definition.argument.end.latex'
+    patterns: [
+      {
+        name: 'support.filepath.back.latex'
+        match: '\\.{2}\\/'
+      }
+      {
+        name: 'support.filepath.home.latex'
+        match: '\\.\\/'
+      }
+      {
+        name: 'support.filepath.root.latex'
+        match: '(?<=\\{)\\/'
+      }
+      {
+        name: 'support.filepath.directory.latex'
+        match: '[^(\\.{1,2}\\/)].*?\\/'
+      }
+      {
+        name: 'support.filepath.file.latex'
+        match: '[^}]*'
+      }
+    ]
+  }
+  verbatim: {
+    comment: 'Finds an inline verbatim string of the format \verb+...+'
+    name: 'string.function.verbatim'
+  }


Fix typo with runOnUserLoad

Fix typo with runOnUserLoad

--- app/sync.coffee
+++ app/sync.coffee
@@ -238,7 +238,7 @@
       # Load user
       @userIsLoaded = true
       fn() for fn in @runOnUserLoad
-      @userIsLoaded = []
+      @runOnUserLoad = []
       deferred.resolve user
     return deferred.promise


Add uglfiy task

Add uglfiy task

--- grunt/uglify.coffee
+++ grunt/uglify.coffee
@@ -1,3 +1,4 @@
-module.exports = {}
-  #production:
-  #  files: uglifyLibObject+module.exports =
+  production:
+    files:
+      'build/production/all.js': 'build/production/all.js'


partial fix search field, not working yet

--- test/dummy/app/assets/javascripts/myapp.js.coffee
+++ test/dummy/app/assets/javascripts/myapp.js.coffee
@@ -2,7 +2,7 @@
   $('table tfoot th').each  (idx) ->
     unless $(this).hasClass("nosearch")
       title = $('table thead th').eq( $(this).index() ).text()
-      $(this).html( '<input type="text" placeholder="search") %>" name="idx'+idx+'" />' )
+      $(this).html( '<input type="text" placeholder="search" name="idx'+idx+'" />' )

   # --- simple datatable ---
   xtable = $('table[role="xdatatable"]' ).DataTable(


Remove bad test

Remove bad test

We're not doing what we say we are here anymore.

--- test/javascripts/integration/store_test.js.coffee
+++ test/javascripts/integration/store_test.js.coffee
@@ -1,20 +0,0 @@
-module 'Integration: Store',
-  teardown: -> ETahi.reset()
-  setup: ->
-    setupApp(integration: true)
-
-test 'when creating a record, if event stream puts it in the store first, delete it in favor of the newly saved record', ->
-  store = ETahi.__container__.lookup "store:main"
-
-  server.respondWith 'POST', "/tasks", [
-    200, {"Content-Type": "application/json"}, JSON.stringify {task: {id: 1, body: "FOO"}}
-  ]
-
-  Ember.run ->
-    newRecord = store.createRecord('task', {body: "FOO"})
-    store.push('task', {id: 1, body: "BAR"}) # simulate event stream
-    store.push('task', {id: 2, body: "SAVEME"})
-
-    newRecord.save().then (record) ->
-      equal(record.get('body'), "FOO", "the record should have the newly saved body, not the one from the existing record.")
-      ok(store.find('task', 2),  "the other record should still exist")


Forgot in latest commit

Forgot in latest commit

--- app/views/temperature-view.coffee
+++ app/views/temperature-view.coffee
@@ -12,12 +12,14 @@
         this.model.fetch()

     render : =>
-        super
-        canvas = @$el.find(".canvas").get(0)
-        p = new Processing(canvas, @sketchProc);
-        p.width = @$el.width()
+
+        if(!@p)
+            super
+            canvas = @$el.find(".canvas").get(0)
+            @p = new Processing(canvas, @sketchProc);
+        @p.width = @$el.width()
        # console.log "Div width: " + @$el.find("div.col-lg-3").width()
-        p.temperatureEnd= Math.round(@model.get("data").value)
+        @p.temperatureEnd= Math.round(@model.get("data").value)

         #p.temperature = @model.get("value")


Fix for GenerateTerrainModal

Fix for GenerateTerrainModal

--- app/views/editor/level/modals/GenerateTerrainModal.coffee
+++ app/views/editor/level/modals/GenerateTerrainModal.coffee
@@ -343,6 +343,11 @@

   events:
     'click .choose-option': 'onGenerate'
+
+  constructor: (options) ->
+    super options
+    @presets = presets
+    @presetSizes = presetSizes

   onRevertModel: (e) ->
     id = $(e.target).val()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/controllable.coffee
+++ test/controllable.coffee
@@ -44,7 +44,7 @@
   equals player.I.x, 12

 test "should move player up while key is pressed", ->
-  ;
+

 test "should move player down while key is pressed", ->
   ;


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/controllable.coffee
+++ test/controllable.coffee
@@ -15,5 +15,7 @@

   equals player.I.x, 9

+  player.
+

 module()


test fetched docs as well

test fetched docs as well

--- test/environments.coffee
+++ test/environments.coffee
@@ -17,6 +17,17 @@
         primary_model.close ->
           expect(secondary_model.scope(scope).get('foo')).to.equal(undefined)
           secondary_model.subscribe scope, ->
+            expect(secondary_model.scope(scope).get('foo')).to.equal('bar')
+            secondary_model.close(done)
+    it 'syncs a fetched document', (done)->
+      primary_model = @store.createModel()
+      secondary_model = @store.createModel()
+      scope = 'collection.id'
+      primary_model.fetch scope, ->
+        primary_model.scope(scope).set('foo', 'bar')
+        primary_model.close ->
+          expect(secondary_model.scope(scope).get('foo')).to.equal(undefined)
+          secondary_model.fetch scope, ->
             expect(secondary_model.scope(scope).get('foo')).to.equal('bar')
             secondary_model.close(done)


Remove hardcoded auth server URL from XHR tests.

--- test/src/xhr_test.coffee
+++ test/src/xhr_test.coffee
@@ -515,8 +515,11 @@
       expect(@xhr.preflight).to.equal true

   describe '#send', ->
+    beforeEach ->
+      client = new Dropbox.Client testKeys
+      @url = client.urls.requestToken
+
     it 'reports errors correctly', (done) ->
-      @url = 'https://api.dropbox.com/1/oauth/request_token'
       @xhr = new Dropbox.Xhr 'POST', @url
       @xhr.prepare().send (error, data) =>
         expect(data).to.equal undefined
@@ -539,7 +542,6 @@
         done()

     it 'reports errors correctly when onError is set', (done) ->
-      @url = 'https://api.dropbox.com/1/oauth/request_token'
       @xhr = new Dropbox.Xhr 'POST', @url
       listenerError = null
       xhrCallbackCalled = false
@@ -577,8 +579,7 @@
         done()

     it 'processes data correctly', (done) ->
-      xhr = new Dropbox.Xhr 'POST',
-                            'https://api.dropbox.com/1/oauth/request_token',
+      xhr = new Dropbox.Xhr 'POST', @url
       xhr.addOauthParams @oauth
       xhr.prepare().send (error, data) ->
         expect(error).to.not.be.ok
@@ -587,8 +588,7 @@
         done()

     it 'processes data correctly when using setCallback', (done) ->
-      xhr = new Dropbox.Xhr 'POST',
-                            'https://api.dropbox.com/1/oauth/request_token',
+      xhr = new Dropbox.Xhr 'POST', @url
       xhr.addOauthParams @oauth
       xhr.setCallback (error, data) ->
         expect(error).to.not.be.ok
@@ -598,8 +598,7 @@
       xhr.prepare().send()

     it 'processes data and headers correctly', (done) ->
-      xhr = new Dropbox.Xhr 'POST',
-                            'https://api.dropbox.com/1/oauth/request_token',
+      xhr = new Dropbox.Xhr 'POST', @url
       xhr.addOauthParams @oauth
       xhr.reportResponseHeaders()
       xhr.prepare().send (error, data, metadata, headers) ->
@@ -614,8 +613,7 @@
     it 'sends Authorize headers correctly', (done) ->
       return done() if Dropbox.Xhr.ieXdr  # IE's XDR doesn't set headers.

-      xhr = new Dropbox.Xhr 'POST',
-                            'https://api.dropbox.com/1/oauth/request_token',
+      xhr = new Dropbox.Xhr 'POST', @url
       xhr.addOauthHeader @oauth
       xhr.prepare().send (error, data) ->
         expect(error).to.equal null


Updated Regex Test

Updated Regex Test

--- test/streams/load.coffee
+++ test/streams/load.coffee
@@ -11,8 +11,8 @@

 describe 'LoadMulti()', ->
   stub_files    = [
-    path.join stubsdir, 'nodeps', 'main.coffee'
-    path.join stubsdir, 'nodeps', 'manifest.json'
+    path.join stubsdir, 'commonjs', 'main.js'
+    path.join stubsdir, 'commonjs', 'required.js'
   ]
   LoadMulti    = null
   before -> {LoadMulti} = require '../../lib/streams/load'
@@ -23,36 +23,9 @@
     s = new LoadMulti stub_files
     s.on 'data', (chunk) -> d += chunk
     s.on 'end', ->
-      d.should.equal expected
-      return done()
-
-    expected = """
-    #
-    # # Test Stub
-    #
-
-
-
-    do ->
-      new KDNotificationView
-        title: 'Stub'
-    {
-      "name": "Stub",
-      "path": ".",
-      "source": {
-        "blocks": {
-          "app": {
-            "files": [
-              "./main.coffee"
-             ]
-          }
-        }
-      }
-    }
-
-
-    """
-
+      d.match(/required to pass/g).length.should.eql 2,
+        'The required matches werre not all found'
+      done()

   describe '#transforms()', ->


Adds resizer helper methods

Adds resizer helper methods

--- models/mixins/image_sizes.coffee
+++ models/mixins/image_sizes.coffee
@@ -1,5 +1,6 @@
 _ = require 'underscore'
 sd = require('sharify').data
+resizer = require '../../components/resizer/index.coffee'

 # requires the image mixin
 module.exports =
@@ -69,4 +70,14 @@
       return @imageUrl(size) if _.contains(sizes, size)
     null

-  aspectRatio: -> @get('aspect_ratio')
+  resizeUrlFor: ->
+    resizer.resize @imageUrlForMaxSize(), arguments...
+
+  cropUrlFor: ->
+    resizer.crop @imageUrlForMaxSize(), arguments...
+
+  fillUrlFor: ->
+    resizer.fill @imageUrlForMaxSize(), arguments...
+
+  aspectRatio: ->
+    @get('aspect_ratio')


Test help menu link

Test help menu link

--- test/components/course-listing.spec.coffee
+++ test/components/course-listing.spec.coffee
@@ -36,6 +36,22 @@
       # no refresh button when load succeeds
       expect(state.div.querySelector(".refresh-button")).to.be.null

+  it 'renders course appropriate help', ->
+    CourseListingActions.loaded(MASTER_COURSES_LIST)
+    renderListing().then (state) ->
+      # no courses are CC, so link should be tutor
+      expect(state.div.querySelector('.-help-link a').getAttribute('href'))
+        .equal('https://openstaxtutor.zendesk.com')
+
+    courses = _.clone(MASTER_COURSES_LIST)
+    courses[0] = _.clone(MASTER_COURSES_LIST[0])
+    courses[0].is_concept_coach = true
+    CourseListingActions.loaded(courses)
+    renderListing().then (state) ->
+      # has at least one CC course, so link should be to CC
+      expect(state.div.querySelector('.-help-link a').getAttribute('href'))
+        .equal('https://openstaxcc.zendesk.com/hc/en-us')
+
   it 'displays refresh button when loading fails', ->
     CourseListingActions.FAILED()
     expect(CourseListingStore.isFailed()).to.be.true


Ripple: animate through mounts, color mapping

--- ripple/index.coffee
+++ ripple/index.coffee
@@ -8,36 +8,53 @@
   require './index.styl'

 module.exports = class Ripple
-  ripple: ({$$el, color, isCenter, mouseX, mouseY}) ->
-    {width, height, top, left} = $$el.getBoundingClientRect()
+  constructor: ->
+    @state = z.state
+      waves: []

-    if isCenter
-      x = width / 2
-      y = height / 2
-    else
-      x = mouseX - left
-      y = mouseY - top
+  beforeUnmount: =>
+    {waves} = @state.getValue()
+    now = Date.now()

-    $$wave = document.createElement 'div'
-    $$wave.className = 'wave'
-    $$wave.style.top = "#{y}px"
-    $$wave.style.left = "#{x}px"
-    $$wave.style.background = "#{color}"
-
-    $$el.appendChild $$wave
-
-    setTimeout ->
-      $$el.removeChild $$wave
-    , 1400
+    # remove waves which have already started their animation
+    @state.set
+      waves: _.filter waves, ({startTime}) ->
+        startTime + 100 > now

   render: ({color, isCircle, isCenter}) =>
+    {waves} = @state.getValue()
+    color ?= 'blue'
+    if colors["$#{color}500"]?
+      color = colors["$#{color}500"]
+
     z '.zp-ripple',
       className: z.classKebab {isCircle}
       onmousedown: (e) =>
-        @ripple {
-          $$el: e.currentTarget
-          color
-          isCenter
-          mouseX: e.clientX
-          mouseY: e.clientY
+        {width, height, top, left} = e.currentTarget.getBoundingClientRect()
+
+        if isCenter
+          x = width / 2
+          y = height / 2
+        else
+          x = e.clientX - left
+          y = e.clientY - top
+
+        wave = {
+          startTime: Date.now()
+          $: z '.wave',
+            key: "#{x}_#{y}"
+            style:
+              top: "#{y}px"
+              left: "#{x}px"
+              background: "#{color}"
         }
+
+        @state.set
+          waves: waves.concat [wave]
+
+        setTimeout =>
+          {waves} = @state.getValue()
+          @state.set
+            waves: _.without waves, wave
+        , 1400
+      _.map waves, '$'


Add resetpassword route, fix alert box always being shown on reset password page

--- routes/index.coffee
+++ routes/index.coffee
@@ -1,5 +1,19 @@
 express = require 'express'
 router = express.Router()
+
+
+router.get '/resetPassword', (req, res) ->
+  if !req.user or !req.user.data.needsReset
+    return res.redirect "/"
+  res.render 'resetpassword',
+    error: req.flash 'error'
+    username: req.user.data.username
+
+router.use (req, res, next) ->
+  if req.user and req.user.data.needsReset
+    res.redirect '/resetPassword'
+  else
+    next()

 router.get '/admin', (req, res) ->
   if req.user


Separate option properties.

Separate option properties.

--- js/flight.coffee
+++ js/flight.coffee
@@ -1,11 +1,13 @@
 class Flight
   version: '0.0.1'
   isTransitioning: false
-  # defaults
+  currentPanel: ''
+  targetPanel: ''
+
+  # options
   transitionAnimation: true
   fadeAnimation: true
-  currentPanel: ''
-  targetPanel: ''
+
   speed: '0.4s'

   constructor: (options) ->


Tweak 'guides' types regex

Tweak 'guides' types regex

--- assets/javascripts/collections/types.coffee
+++ assets/javascripts/collections/types.coffee
@@ -7,7 +7,7 @@
       (result[@_groupFor(type)] ||= []).push(type)
     result.filter (e) -> e.length > 0

-  GUIDES_RGX = /guide|tutorial|reference|getting\ started/i
+  GUIDES_RGX = /(^|[\s\(])(guide|tutorial|reference|getting\ started)/i

   _groupFor: (type) ->
     if GUIDES_RGX.test(type.name)


Simplify completion_search.coffee

Simplify completion_search.coffee

--- background_scripts/completion_search.coffee
+++ background_scripts/completion_search.coffee
@@ -21,11 +21,8 @@
       queryTerms = [ terms.split(" ")..., queryTerms... ]
       prefix = "#{terms} "

-      @postprocessSuggestions =
-        (suggestions) ->
-          for suggestion in suggestions
-            continue unless suggestion.startsWith prefix
-            suggestion[prefix.length..]
+      @postprocessSuggestions = (suggestions) ->
+        suggestions.filter((s) => s.startsWith(prefix)).map((s) => s[prefix.length..])

     @engine.getUrl queryTerms

@@ -64,7 +61,8 @@
     else
       for engine in CompletionEngines
         engine = new engine()
-        return @engineCache.set searchUrl, engine if engine.match searchUrl
+        if engine.match searchUrl
+          return @engineCache.set searchUrl, engine

   # True if we have a completion engine for this search URL, false otherwise.
   haveCompletionEngine: (searchUrl) ->
@@ -88,15 +86,18 @@
     callback ?= (suggestions) -> suggestions

     # We don't complete queries which are too short: the results are usually useless.
-    return callback [] unless 3 < query.length
+    return callback [] unless query.length >= 3

     # We don't complete regular URLs or Javascript URLs.
-    return callback [] if 1 == queryTerms.length and Utils.isUrl query
-    return callback [] if Utils.hasJavascriptPrefix query
+    if queryTerms.length == 1 and Utils.isUrl query
+      return callback []
+    if Utils.hasJavascriptPrefix query
+      return callback []

     completionCacheKey = JSON.stringify [ searchUrl, queryTerms ]
     if @completionCache.has completionCacheKey
-      console.log "hit", completionCacheKey if @debug
+      if @debug
+        console.log "hit", completionCacheKey
       return callback @completionCache.get completionCacheKey

     # If the user appears to be typing a continuation of the characters of the most recent query, then we can
@@ -111,7 +112,7 @@
           # previous queries with no suggestions suppress subsequent no-hope HTTP requests as the user continues
           # to type.
           for suggestion in @mostRecentSuggestions
-            return false unless 0 <= suggestion.indexOf query
+            return false unless suggestion.includes(query)
           # Ok. Re-use the suggestion.
           true

@@ -125,41 +126,46 @@

     # We pause in case the user is still typing.
     Utils.setTimeout @delay, handler = @mostRecentHandler = =>
-      if handler == @mostRecentHandler
-        @mostRecentHandler = null
+      return unless handler == @mostRecentHandler
+      @mostRecentHandler = null

-        # Elide duplicate requests. First fetch the suggestions...
-        @inTransit[completionCacheKey] ?= new AsyncDataFetcher (callback) =>
-          engine = new EnginePrefixWrapper searchUrl, @lookupEngine searchUrl
-          url = engine.getUrl queryTerms
+      # Elide duplicate requests. First fetch the suggestions...
+      @inTransit[completionCacheKey] ?= new AsyncDataFetcher (callback) =>
+        engine = new EnginePrefixWrapper searchUrl, @lookupEngine searchUrl
+        url = engine.getUrl queryTerms

-          @get searchUrl, url, (xhr = null) =>
-            # Parsing the response may fail if we receive an unexpected or an unexpectedly-formatted response.
-            # In all cases, we fall back to the catch clause, below.  Therefore, we "fail safe" in the case of
-            # incorrect or out-of-date completion engines.
-            try
-              suggestions = engine.parse xhr
-              # Make all suggestions lower case.  It looks odd when suggestions from one completion engine are
-              # upper case, and those from another are lower case.
-              suggestions = (suggestion.toLowerCase() for suggestion in suggestions)
-              # Filter out the query itself. It's not adding anything.
-              suggestions = (suggestion for suggestion in suggestions when suggestion != query)
-              console.log "GET", url if @debug
-            catch
-              suggestions = []
-              # We allow failures to be cached too, but remove them after just thirty seconds.
-              Utils.setTimeout 30 * 1000, => @completionCache.set completionCacheKey, null
-              console.log "fail", url if @debug
+        # TODO(philc): Do we need to return the result of this.get here, or can we remove this return statement?
+        @get searchUrl, url, (xhr = null) =>
+          # Parsing the response may fail if we receive an unexpected or an unexpectedly-formatted response.
+          # In all cases, we fall back to the catch clause, below.  Therefore, we "fail safe" in the case of
+          # incorrect or out-of-date completion engines.
+          try
+            suggestions = engine.parse(xhr)
+            # Make all suggestions lower case.  It looks odd when suggestions from one completion engine are
+            # upper case, and those from another are lower case.
+            .map((s) => s.toLowerCase())
+            # suggestions = (suggestion.toLowerCase() for suggestion in suggestions)
+            # Filter out the query itself. It's not adding anything.
+            .filter((s) => s != query)
+            # suggestions = (suggestion for suggestion in suggestions when suggestion != query)
+            console.log "GET", url if @debug
+          catch
+            suggestions = []
+            # We allow failures to be cached too, but remove them after just thirty seconds.
+            Utils.setTimeout 30 * 1000, => @completionCache.set completionCacheKey, null
+            console.log "fail", url if @debug

-            callback suggestions
-            delete @inTransit[completionCacheKey]
+          callback suggestions
+          delete @inTransit[completionCacheKey]

-        # ... then use the suggestions.
-        @inTransit[completionCacheKey].use (suggestions) =>
-          @mostRecentSearchUrl = searchUrl
-          @mostRecentQuery = query
-          @mostRecentSuggestions = suggestions
-          callback @completionCache.set completionCacheKey, suggestions
+      # ... then use the suggestions.
+      @inTransit[completionCacheKey].use (suggestions) =>
+        @mostRecentSearchUrl = searchUrl
+        @mostRecentQuery = query
+        @mostRecentSuggestions = suggestions
+        callback @completionCache.set completionCacheKey, suggestions
+      return
+    return

   # Cancel any pending (ie. blocked on @delay) queries.  Does not cancel in-flight queries.  This is called
   # whenever the user is typing.


Add Option To Show Value Stats Per Book

Add Option To Show Value Stats Per Book

#18


Added revokeLookup for route cert

Added revokeLookup for route cert

--- src/middleware/router.coffee
+++ src/middleware/router.coffee
@@ -25,6 +25,7 @@
 #MyEdit
 pem = require 'pem'
 keystore = require '../api/keystore'
+RevokedCert = require('../model/revokedcerts').RevokedCert
 #

 isRouteEnabled = (route) -> not route.status? or route.status is 'enabled'
@@ -103,6 +104,64 @@
   logger.error "#{err.stack}" if err.stack

+###
+#
+###
+revokedLookup = (cert) ->
+  logger.debug "Looking up client linked in revocation list"
+  deferred = Q.defer()
+  pem.readCertificateInfo cert, (err, match) ->
+    if err
+      logger.error 'Error in pem: ' + err
+      deferred.reject err
+    else
+      logger.info "fp: " + match.fingerprint + " issuer: " + match.issuer.commonName
+      RevokedCert.findOne {fingerprint: match.fingerprint, issuerDN: match.issuer.commonName}, (err, result) ->
+        deferred.reject err if err
+
+        if result?
+          # found a match
+          logger.error "Revoked cert of mediator"
+          return deferred.reject "Revoked cert of mediator"
+        else if config.tlsClientLookup.type is 'strict'
+          logger.info "strict type: not in revocation list. OK"
+          deferred.resolve "strict type: not in revocation list. OK"
+
+        if config.tlsClientLookup.type is 'in-chain'
+          # walk further up and cert chain and check
+          utils.getKeystore (err, keystore) ->
+            deferred.reject err if err
+            missedMatches = 0
+            # find the isser cert
+            if not keystore.ca? || keystore.ca.length < 1
+              logger.info "Issuer cn=#{issuerCN} for cn=#{subjectCN} not found in keystore."
+              deferred.reject "Route cert's issuer cert not found in keystore."
+            else
+              for cert in keystore.ca
+                do (cert) ->
+                  pem.readCertificateInfo cert.data, (err, info) ->
+                    if err
+                      return deferred.reject err
+
+                    if info.commonName is issuerCN
+                      promise = revokedLookup cert.fingerprint, info.commonName, info.issuer.commonName
+                      promise.then (result) -> deferred.resolve result
+                    else
+                      missedMatches++
+
+                    if missedMatches is keystore.ca.length
+                      logger.info "Issuer cn=#{issuerCN} for cn=#{subjectCN} not found in keystore."
+                      deferred.reject "Route cert's issuer cert not found in keystore."
+        else
+          if config.tlsClientLookup.type isnt 'strict'
+            logger.warn "tlsClientLookup.type config option does not contain a known value, defaulting to 'strict'. Available options are 'strict' and 'in-chain'."
+          #deferred.reject "Not chained and cert not found in list"
+
+
+  return deferred.promise
+###
+#
+###
 sendRequestToRoutes = (ctx, routes, next) ->
   promises = []
   promise = {}
@@ -146,6 +205,18 @@

         if route.cert?
           options.ca = keystore.ca.id(route.cert).data
+          promises_rev = revokedLookup(options.ca)
+          .then (response) ->
+            if response == null
+              logger.info "Outgoing transaction ok: cert ok"
+          .fail (reason) ->
+            if reason instanceof Error
+              handleServerError ctx, reason
+            handleServerError ctx, new Error reason
+            next()
+
+          promises.push promises_rev
+

         if ctx.request.querystring
           options.path += '?' + ctx.request.querystring


Added spec for custom helpers failing within collections, thanks @ewollesen, closes #27

--- test/integration/custom_helper.spec.coffee
+++ test/integration/custom_helper.spec.coffee
@@ -129,3 +129,16 @@
       '''
       expect(@body).to.have.element('div > form > div#jonas')
       expect(@body).to.have.element('div > form > div#peter')
+
+    it "doesn't fail when called from a collection", ->
+      Serenade.Helpers.test = ->
+        @document.createElement("span")
+      model =
+        col: [1, 2]
+      @render '''
+        div
+          - collection @col
+            - test
+      ''', model
+      expect(@body).to.have.element('div > span')
+


JSListView update

JSListView update

--- JSKit/04_JSListView.coffee
+++ JSKit/04_JSListView.coffee
@@ -11,6 +11,7 @@
 		@_dblclickaction = null
 		@_style = "JSListStyleStandard"
 		@_textSize = 12
+		@_select = -1

 	setFrame:(frame)->
 		super(frame)
@@ -51,20 +52,20 @@
 				if (@_style=="JSListStyleStandard")
 					$(@_viewSelector+"_select").click (e) =>
 						e.stopPropagation()
-						select = $(@_viewSelector+"_select option:selected").val()
-						if (@_clickaction? && select?)
-							@_clickaction(select)
+						@_select = $(@_viewSelector+"_select option:selected").val()
+						if (@_clickaction? && @_select?)
+							@_clickaction(@_select)
 					$(@_viewSelector+"_select").dblclick (e) =>
 						e.stopPropagation()
-						select = $(@_viewSelector+"_select option:selected").val()
-						if (@_dblclickaction? && select?)
-							@_dblclickaction(select)
+						@_select = $(@_viewSelector+"_select option:selected").val()
+						if (@_dblclickaction? && @_select?)
+							@_dblclickaction(@_select)
 				else
 					$(@_viewSelector+"_select").change (e) =>
 						e.stopPropagation()
-						select = $(@_viewSelector+"_select option:selected").val()
-						if (@_clickaction? && select?)
-							@_clickaction(select)
+						@_select = $(@_viewSelector+"_select option:selected").val()
+						if (@_clickaction? && @_select?)
+							@_clickaction(@_select)

 			when "JSListStyleSortable"
 				@_tag = "<table style='width:100%;'><tbody id='"+@_objectID+"_select'>"
@@ -105,6 +106,9 @@
 		num = @_listData.indexOf(target)
 		return num

+	getSelect:->
+		return @_select
+
 	setSelect:(select)->
 		$(@_viewSelector+"_select").val(select)


Slugifable: fix updateSlug

Slugifable: fix updateSlug

--- workers/social/lib/social/traits/slugifiable.coffee
+++ workers/social/lib/social/traits/slugifiable.coffee
@@ -199,7 +199,7 @@
   updateSlug:(callback)->
     @createSlug (err, slug)=>
       if err then callback err
-      else @update $set:{slug, slug_:slug}, (err)->
+      else @update $set:{slug:slug.slug, slug_:slug.slug}, (err)->
         callback err, unless err then slug

   createSlug:(callback)->


move fetching proxy rules to domain model

--- client/landing/app/Applications/Environments.kdapplication/views/FirewallMapperView.coffee
+++ client/landing/app/Applications/Environments.kdapplication/views/FirewallMapperView.coffee
@@ -38,11 +38,12 @@

       @filterListController.instantiateListItems filters

-    KD.remote.api.JProxyRestriction.fetchRestrictionByDomain domain.domain, (err, restriction)=>
-      if restriction
-        for rule in restriction.ruleList
+    domain.fetchProxyRules (err, ruleList)=>
+      return console.log err if err
+      if ruleList
+        for rule in ruleList
           rule.domainName = domain.domain
-        @ruleListController.instantiateListItems restriction.ruleList
+        @ruleListController.instantiateListItems ruleList

     @fwRuleFormView = new FirewallFilterFormView delegate:@filterListController.getListView(), {domain}