diff --git a/spec/fixtures/Bad.tmTheme b/spec/fixtures/Bad.tmTheme new file mode 100644 index 000000000..11e4f3c89 --- /dev/null +++ b/spec/fixtures/Bad.tmTheme @@ -0,0 +1,422 @@ + + + + + comment + Dawn + name + Dawn + settings + + + settings + + background + #F5F5F5 + caret + #000000 + foreground + #080808 + invisibles + #4B4B7E80 + selection + #7496CF4D + + + + name + Comment + scope + comment + settings + + fontStyle + italic + foreground + #5A525F + + + + name + Constant + scope + constant + settings + + fontStyle + bold + foreground + #811F24 + + + + name + Entity + scope + entity + settings + + fontStyle + + foreground + #BF4F24 + + + + name + Keyword + scope + keyword + settings + + fontStyle + + foreground + #794938 + + + + name + Storage + scope + storage + settings + + fontStyle + italic + foreground + #A71D5D + + + + name + String + scope + string | punctuation.definition.string + settings + + fontStyle + + foreground + #0B6125 + + + + name + Support + scope + support + settings + + fontStyle + + foreground + #691C97 + + + + name + Variable + scope + variable + settings + + fontStyle + + foreground + #234A97 + + + + name + Invalid – Deprecated + scope + invalid.deprecated + settings + + fontStyle + bold italic underline + foreground + #B52A1D + + + + name + Invalid – Illegal + scope + invalid.illegal + settings + + background + #B52A1D + fontStyle + italic underline + foreground + #F8F8F8 + + + + name + String embedded-source + scope + string source + settings + + background + #6F8BBA26 + fontStyle + + foreground + #080808 + + + + name + String constant + scope + string constant + settings + + fontStyle + bold + foreground + #696969 + + + + name + String variable + scope + string variable + settings + + fontStyle + + foreground + #234A97 + + + + name + String.regexp + scope + string.regexp + settings + + fontStyle + + foreground + #CF5628 + + + + name + String.regexp.«special» + scope + string.regexp.character-class, string.regexp constant.character.escaped, string.regexp source.ruby.embedded, string.regexp string.regexp.arbitrary-repitition + settings + + fontStyle + bold italic + foreground + #CF5628 + + + + name + String.regexp constant.character.escape + scope + string.regexp constant.character.escape + settings + + fontStyle + bold + foreground + #811F24 + + + + name + Embedded Source + scope + text source + settings + + background + #6F8BBA26 + + + + name + Support.function + scope + support.function + settings + + fontStyle + + foreground + #693A17 + + + + name + Support.constant + scope + support.constant + settings + + fontStyle + + foreground + #B4371F + + + + name + Support.variable + scope + support.variable + settings + + foreground + #234A97 + + + + name + Markup.list + scope + markup.list + settings + + foreground + #693A17 + + + + name + Markup.heading + scope + markup.heading | markup.heading entity.name + settings + + fontStyle + bold + foreground + #19356D + + + + name + Markup.quote + scope + markup.quote + settings + + background + #BBBBBB30 + fontStyle + italic + foreground + #0B6125 + + + + name + Markup.italic + scope + markup.italic + settings + + fontStyle + italic + foreground + #080808 + + + + name + Markup.bold + scope + markup.bold + settings + + fontStyle + bold + foreground + #080808 + + + + name + Markup.underline + scope + markup.underline + settings + + fontStyle + underline + foreground + #080808 + + + + name + Markup.link + scope + markup.link + settings + + fontStyle + italic underline + foreground + #234A97 + + + + name + Markup.raw + scope + markup.raw + settings + + background + #BBBBBB30 + fontStyle + + foreground + #234A97 + + + + name + Markup.deleted + scope + markup.deleted + settings + + foreground + #B52A1D + + + + name + Meta.seperator + scope + meta.separator + settings + + background + #DCDCDC + fontStyle + bold + foreground + #19356D + + + + uuid + E7E82498-F9EA-49A6-A0D8-12327EA46B01 + + diff --git a/spec/init-spec.coffee b/spec/init-spec.coffee index 4ac4749c5..479d5d791 100644 --- a/spec/init-spec.coffee +++ b/spec/init-spec.coffee @@ -8,7 +8,7 @@ describe "apm init", -> [packagePath, themePath] = [] beforeEach -> - # silenceOutput() + silenceOutput() spyOnToken() currentDir = temp.mkdirSync('apm-init-') @@ -112,3 +112,14 @@ describe "apm init", -> expect(fs.existsSync(path.join(themePath, 'README.md'))).toBeTruthy() expect(fs.existsSync(path.join(themePath, 'package.json'))).toBeTruthy() expect(fs.existsSync(path.join(themePath, 'LICENSE.md'))).toBeFalsy() + + it "logs an error if it doesn't have all the required color settings", -> + callback = jasmine.createSpy('callback') + textMateThemePath = path.join(__dirname, 'fixtures', 'Bad.tmTheme') + apm.run(['init', '--theme', 'fake-theme', '--convert', textMateThemePath], callback) + + waitsFor 'waiting for init to complete', -> + callback.callCount is 1 + + runs -> + expect(callback.argsForCall[0][0].message.length).toBeGreaterThan 0 diff --git a/src/text-mate-theme.coffee b/src/text-mate-theme.coffee index 835440110..bdc99457b 100644 --- a/src/text-mate-theme.coffee +++ b/src/text-mate-theme.coffee @@ -9,10 +9,36 @@ class TextMateTheme @buildRulesets() buildRulesets: -> - {settings} = plist.parseStringSync(@contents) - @buildSyntaxVariables(settings[0]) - @buildGlobalSettingsRulesets(settings[0]) - @buildScopeSelectorRulesets(settings[1..]) + {settings} = plist.parseStringSync(@contents) ? {} + settings ?= [] + + for setting in settings + {scope, name} = setting.settings + continue if scope or name + + # Require all of these or invalid LESS will be generated if any required + # variable value is missing + {background, foreground, caret, selection, invisibles, lineHighlight} = setting.settings + if background and foreground and caret and selection and lineHighlight and invisibles + variableSettings = setting.settings + break + + unless variableSettings? + throw new Error """ + Could not find the required color settings in the theme. + + The theme being converted must contain a settings array with all of the following keys: + * background + * caret + * foreground + * invisibles + * lineHighlight + * selection + """ + + @buildSyntaxVariables(variableSettings) + @buildGlobalSettingsRulesets(variableSettings) + @buildScopeSelectorRulesets(settings) getStylesheet: -> lines = [ @@ -29,16 +55,14 @@ class TextMateTheme getSyntaxVariables: -> @syntaxVariables - buildSyntaxVariables: ({settings}) -> + buildSyntaxVariables: (settings) -> @syntaxVariables = SyntaxVariablesTemplate for key, value of settings replaceRegex = new RegExp("\\{\\{#{key}\\}\\}", 'g') @syntaxVariables = @syntaxVariables.replace(replaceRegex, @translateColor(value)) @syntaxVariables - buildGlobalSettingsRulesets: ({settings}) -> - {background, foreground, caret, selection, lineHighlight} = settings - + buildGlobalSettingsRulesets: (settings) -> @rulesets.push selector: '.editor' properties: @@ -101,7 +125,7 @@ class TextMateTheme @rulesets.push selector: '.editor.is-focused .line-number.cursor-line-no-selection, .editor.is-focused .line.cursor-line' properties: - 'background-color': @translateColor(lineHighlight) + 'background-color': @translateColor(settings.lineHighlight) buildScopeSelectorRulesets: (scopeSelectorSettings) -> for {name, scope, settings} in scopeSelectorSettings diff --git a/src/theme-converter.coffee b/src/theme-converter.coffee index 826ca2937..75e960c71 100644 --- a/src/theme-converter.coffee +++ b/src/theme-converter.coffee @@ -33,7 +33,11 @@ class ThemeConverter @readTheme (error, themeContents) => return callback(error) if error? - theme = new TextMateTheme(themeContents) + try + theme = new TextMateTheme(themeContents) + catch error + return callback(error) + fs.writeFileSync(path.join(@destinationPath, 'stylesheets', 'base.less'), theme.getStylesheet()) fs.writeFileSync(path.join(@destinationPath, 'stylesheets', 'syntax-variables.less'), theme.getSyntaxVariables()) callback()