Comparar commits
19 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 7ba57df6f7 | |||
| 5c2f4d939a | |||
| 6c9c7b6d92 | |||
| 210dd61d2a | |||
| aa302cb935 | |||
| 994e856ccd | |||
| 808f7e6ed3 | |||
| 22f7bc8f26 | |||
| ab0b2cf12e | |||
| 599a2ad021 | |||
| db649798ef | |||
| 4f8f8c43a4 | |||
| 4491a9302b | |||
| ce138b56c0 | |||
| 8f8c0cbf45 | |||
| 7e04d85e1e | |||
| 136836e615 | |||
| 82882624ce | |||
| c03e849089 |
@@ -9,6 +9,7 @@ pairs:
|
||||
gt: Garen Torikian; garen
|
||||
mc: Matt Colyer; mcolyer
|
||||
jr: Jason Rudolph; jasonrudolph
|
||||
jl: Jessica Lord; jlord
|
||||
email:
|
||||
domain: github.com
|
||||
#global: true
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
* Added: Terminal package now bundled by default, open with ctrl-`
|
||||
* Fixed: Fuzzy finder not showing results for files at a certain depth
|
||||
* Fixed: Atom > Preferences... menu not opening settings in focused window
|
||||
|
||||
* Fixed: Atom failing to launch if the theme being used was not found
|
||||
|
||||
* Improved: Theme changes now immediately take effect
|
||||
* Fixed: Wrap in quotes/parens now works in split panes
|
||||
* Improved: Autocomplete now includes CSS property names and values
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# :rotating_light: Contributing to Atom :rotating_light:
|
||||
|
||||
|
||||
## Issues
|
||||
* Include screenshots and animated GIFs whenever possible, they are immensely
|
||||
helpful
|
||||
@@ -26,3 +27,35 @@
|
||||
* Class methods (methods starting with a `@`)
|
||||
* Instance variables
|
||||
* Instance methods
|
||||
|
||||
## Philosophy
|
||||
|
||||
### Write Beautiful Code
|
||||
Once you get something working, take the time to consider whether you can achieve it in a more elegant way. We're planning on open-sourcing Atom, so let's put our best foot forward.
|
||||
|
||||
### When in doubt, pair-up
|
||||
Pairing can be an effective and fun way to pass on culture, knowledge, and taste. If you can find the time, we encourage you to work synchronously with other community members of all experience levels to help the knowledge-mulching process. It doesn't have to be all the time; a little pairing goes a long way.
|
||||
|
||||
### Write tests, and write them first
|
||||
The test suite keeps protects our codebase from the ravages of entropy, but it only works when we have thorough coverage. Before you write implementation code, write a failing test proving that it's needed.
|
||||
|
||||
### Leave the test suite better than you found it
|
||||
Consider how the specs you are adding fit into the spec-file as a whole. Is this the right place for your spec? Does the spec need to be reorganized now that you're adding this extra dimension? Specs are only as useful as the next person's ability to understand them.
|
||||
|
||||
### Solve today's problem
|
||||
Avoid adding flexibility that isn't needed *today*. Nothing is ever set in stone, and we can always go back and add flexibility later. Adding it early just means we have to pay for complexity that we might not end up using.
|
||||
|
||||
### Favor clarity over brevity or cleverness.
|
||||
Three lines that someone else can read are better than one line that's tricky.
|
||||
|
||||
### Don't be defensive
|
||||
Only catch exceptions that are truly exceptional. Assume that components we control will honor their contracts. If they don't, the solution is to find and fix the problem in code rather than cluttering the code with attempts to foresee all potential issues at runtime.
|
||||
|
||||
### Don't be afraid to add classes and methods
|
||||
Code rarely suffers from too many methods and classes, and often suffers from too few. Err on the side of numerous short, well-named methods. Pull out classes with well-defined roles.
|
||||
|
||||
### Rip shit out
|
||||
Don't be afraid to delete code. Don't be afraid to rewrite something that needs to be refreshed. If it's in version control, we can always resurrect it.
|
||||
|
||||
### Maintain a consistent level of abstraction
|
||||
Every line in a method should read at the same basic level of abstraction. If there's a section of a method that goes into a lot more detail than the rest of the method, consider extracting a new method and giving it a clear name.
|
||||
|
||||
+27
-11
@@ -1,5 +1,6 @@
|
||||
#!/bin/sh
|
||||
ATOM_PATH=/Applications/Atom.app
|
||||
ATOM_BINARY=$ATOM_PATH/Contents/MacOS/Atom
|
||||
|
||||
if [ ! -d $ATOM_PATH ]; then sleep 5; fi # Wait for Atom to reappear, Sparkle may be replacing it.
|
||||
|
||||
@@ -8,7 +9,32 @@ if [ ! -d $ATOM_PATH ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
open -a $ATOM_PATH -n --args --executed-from="$(pwd)" --pid=$$ $@
|
||||
while getopts ":whv-:" opt; do
|
||||
case "$opt" in
|
||||
-)
|
||||
case "${OPTARG}" in
|
||||
wait)
|
||||
WAIT=1
|
||||
;;
|
||||
help|version)
|
||||
EXPECT_OUTPUT=1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
w)
|
||||
WAIT=1
|
||||
;;
|
||||
h|v)
|
||||
EXPECT_OUTPUT=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
$ATOM_BINARY --executed-from="$(pwd)" --pid=$$ $@
|
||||
else
|
||||
open -a $ATOM_PATH -n --args --executed-from="$(pwd)" --pid=$$ $@
|
||||
fi
|
||||
|
||||
# Used to exit process when atom is used as $EDITOR
|
||||
on_die() {
|
||||
@@ -16,16 +42,6 @@ on_die() {
|
||||
}
|
||||
trap 'on_die' SIGQUIT SIGTERM
|
||||
|
||||
# Don't exit process if we were told to wait.
|
||||
while [ "$#" -gt "0" ]; do
|
||||
case $1 in
|
||||
-W|--wait)
|
||||
WAIT=1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ $WAIT ]; then
|
||||
while true; do
|
||||
sleep 1
|
||||
|
||||
+3
-1
@@ -35,7 +35,9 @@
|
||||
"semver": "1.1.4",
|
||||
"guid": "0.0.10",
|
||||
"tantamount": "0.3.0",
|
||||
"nslog": "0.1.0",
|
||||
"coffeestack": "0.4.0",
|
||||
"first-mate": "0.1.0",
|
||||
"c-tmbundle": "1.0.0",
|
||||
"coffee-script-tmbundle": "4.0.0",
|
||||
"css-tmbundle": "1.0.0",
|
||||
@@ -67,7 +69,7 @@
|
||||
"todo-tmbundle": "1.0.0",
|
||||
"xml-tmbundle": "1.0.0",
|
||||
"yaml-tmbundle": "1.0.0",
|
||||
"nslog": "0.1.0"
|
||||
"terminal": "0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"biscotto": "0.0.12",
|
||||
|
||||
@@ -23,3 +23,10 @@ describe "ThemeManager", ->
|
||||
|
||||
config.set('core.themes', [])
|
||||
expect($('style.userTheme').length).toBe 0
|
||||
|
||||
describe "when a theme fails to load", ->
|
||||
it "logs a warning", ->
|
||||
themeManager = new ThemeManager()
|
||||
spyOn(console, 'warn')
|
||||
themeManager.loadTheme('a-theme-that-will-not-be-found')
|
||||
expect(console.warn).toHaveBeenCalled()
|
||||
|
||||
+44
-13
@@ -21,10 +21,18 @@ class AtomReporter extends View
|
||||
@div id: 'HTMLReporter', class: 'jasmine_reporter', =>
|
||||
@div outlet: 'specPopup', class: "spec-popup"
|
||||
@div outlet: "suites"
|
||||
@div outlet: 'coreHeader', class: 'symbolHeader'
|
||||
@ul outlet: 'coreSummary', class: 'symbolSummary list-unstyled'
|
||||
@div outlet: 'packagesHeader', class: 'symbolHeader'
|
||||
@ul outlet: 'packagesSummary', class: 'symbolSummary list-unstyled'
|
||||
@div outlet: 'coreArea', =>
|
||||
@div outlet: 'coreHeader', class: 'symbolHeader'
|
||||
@ul outlet: 'coreSummary', class: 'symbolSummary list-unstyled'
|
||||
@div outlet: 'internalArea', =>
|
||||
@div outlet: 'internalHeader', class: 'symbolHeader'
|
||||
@ul outlet: 'internalSummary', class: 'symbolSummary list-unstyled'
|
||||
@div outlet: 'bundledArea', =>
|
||||
@div outlet: 'bundledHeader', class: 'symbolHeader'
|
||||
@ul outlet: 'bundledSummary', class: 'symbolSummary list-unstyled'
|
||||
@div outlet: 'userArea', =>
|
||||
@div outlet: 'userHeader', class: 'symbolHeader'
|
||||
@ul outlet: 'userSummary', class: 'symbolSummary list-unstyled'
|
||||
@div outlet: "status", class: 'status', =>
|
||||
@div outlet: "time", class: 'time'
|
||||
@div outlet: "specCount", class: 'spec-count'
|
||||
@@ -122,18 +130,41 @@ class AtomReporter extends View
|
||||
|
||||
addSpecs: (specs) ->
|
||||
coreSpecs = 0
|
||||
packageSpecs = 0
|
||||
internalPackageSpecs = 0
|
||||
bundledPackageSpecs = 0
|
||||
userPackageSpecs = 0
|
||||
for spec in specs
|
||||
symbol = $$ -> @li class: "spec-summary pending spec-summary-#{spec.id}"
|
||||
if spec.coreSpec
|
||||
coreSpecs++
|
||||
@coreSummary.append symbol
|
||||
else
|
||||
packageSpecs++
|
||||
@packagesSummary.append symbol
|
||||
switch spec.specType
|
||||
when 'core'
|
||||
coreSpecs++
|
||||
@coreSummary.append symbol
|
||||
when 'internal'
|
||||
internalPackageSpecs++
|
||||
@internalSummary.append symbol
|
||||
when 'bundled'
|
||||
bundledPackageSpecs++
|
||||
@bundledSummary.append symbol
|
||||
when 'user'
|
||||
userPackageSpecs++
|
||||
@userSummary.append symbol
|
||||
|
||||
@coreHeader.text("Core Specs (#{coreSpecs}):")
|
||||
@packagesHeader.text("Package Specs (#{packageSpecs}):")
|
||||
if coreSpecs > 0
|
||||
@coreHeader.text("Core Specs (#{coreSpecs}):")
|
||||
else
|
||||
@coreArea.hide()
|
||||
if internalPackageSpecs > 0
|
||||
@internalHeader.text("Internal Package Specs (#{internalPackageSpecs}):")
|
||||
else
|
||||
@internalArea.hide()
|
||||
if bundledPackageSpecs > 0
|
||||
@bundledHeader.text("Bundled Package Specs (#{bundledPackageSpecs}):")
|
||||
else
|
||||
@bundledArea.hide()
|
||||
if userPackageSpecs > 0
|
||||
@userHeader.text("User Package Specs (#{userPackageSpecs}):")
|
||||
else
|
||||
@userArea.hide()
|
||||
|
||||
specStarted: (spec) ->
|
||||
@runningSpecCount++
|
||||
|
||||
@@ -5,14 +5,23 @@ measure 'spec suite require time', ->
|
||||
path = require 'path'
|
||||
require 'spec-helper'
|
||||
|
||||
requireSpecs = (directoryPath, specType) ->
|
||||
for specPath in fsUtils.listTreeSync(path.join(directoryPath, 'spec')) when /-spec\.coffee$/.test specPath
|
||||
require specPath
|
||||
for spec in jasmine.getEnv().currentRunner().specs() when not spec.specType?
|
||||
spec.specType = specType
|
||||
|
||||
# Run core specs
|
||||
for specPath in fsUtils.listTreeSync(fsUtils.resolveOnLoadPath("spec")) when /-spec\.coffee$/.test specPath
|
||||
require specPath
|
||||
requireSpecs(window.resourcePath, 'core')
|
||||
|
||||
spec.coreSpec = true for spec in jasmine.getEnv().currentRunner().specs()
|
||||
# Run internal package specs
|
||||
for packagePath in fsUtils.listTreeSync(config.bundledPackagesDirPath)
|
||||
requireSpecs(packagePath, 'internal')
|
||||
|
||||
# Run extension specs
|
||||
for packageDirPath in config.packageDirPaths
|
||||
for packagePath in fsUtils.listSync(packageDirPath)
|
||||
for specPath in fsUtils.listTreeSync(path.join(packagePath, "spec")) when /-spec\.coffee$/.test specPath
|
||||
require specPath
|
||||
# Run bundled package specs
|
||||
for packagePath in fsUtils.listTreeSync(config.nodeModulesDirPath) when atom.isInternalPackage(packagePath)
|
||||
requireSpecs(packagePath, 'bundled')
|
||||
|
||||
# Run user package specs
|
||||
for packagePath in fsUtils.listTreeSync(config.userPackagesDirPath)
|
||||
requireSpecs(packagePath, 'user')
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
fsUtils = require 'fs-utils'
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
temp = require 'temp'
|
||||
|
||||
describe "fsUtils", ->
|
||||
describe ".read(path)", ->
|
||||
@@ -82,6 +83,14 @@ describe "fsUtils", ->
|
||||
|
||||
expect(symlinkPaths).toEqual(paths)
|
||||
|
||||
it "ignores missing symlinks", ->
|
||||
directory = temp.mkdirSync('symlink-in-here')
|
||||
paths = []
|
||||
onPath = (childPath) -> paths.push(childPath)
|
||||
fs.symlinkSync(path.join(directory, 'source'), path.join(directory, 'destination'))
|
||||
fsUtils.traverseTreeSync(directory, onPath)
|
||||
expect(paths.length).toBe 0
|
||||
|
||||
describe ".md5ForPath(path)", ->
|
||||
it "returns the MD5 hash of the file at the given path", ->
|
||||
expect(fsUtils.md5ForPath(require.resolve('fixtures/sample.js'))).toBe 'dd38087d0d7e3e4802a6d3f9b9745f2b'
|
||||
|
||||
@@ -24,6 +24,8 @@ class Config
|
||||
configDirPath: configDirPath
|
||||
themeDirPaths: [userThemesDirPath, bundledThemesDirPath]
|
||||
bundledPackageDirPaths: [bundledPackagesDirPath, nodeModulesDirPath]
|
||||
bundledPackagesDirPath: bundledPackagesDirPath
|
||||
nodeModulesDirPath: nodeModulesDirPath
|
||||
packageDirPaths: [userPackagesDirPath, bundledPackagesDirPath]
|
||||
userPackagesDirPath: userPackagesDirPath
|
||||
userStoragePath: userStoragePath
|
||||
|
||||
@@ -27,7 +27,11 @@ class ThemeManager
|
||||
@loadTheme(themeName) for themeName in themeNames
|
||||
@loadUserStylesheet()
|
||||
|
||||
loadTheme: (name) -> @loadedThemes.push(new Theme(name))
|
||||
loadTheme: (name) ->
|
||||
try
|
||||
@loadedThemes.push(new Theme(name))
|
||||
catch error
|
||||
console.warn("Failed to load theme #{name}", error.stack ? error)
|
||||
|
||||
getUserStylesheetPath: ->
|
||||
stylesheetPath = fsUtils.resolve(path.join(config.configDirPath, 'user'), ['css', 'less'])
|
||||
|
||||
@@ -96,7 +96,7 @@ class AtomApplication
|
||||
submenu: [
|
||||
{ label: 'About Atom', selector: 'orderFrontStandardAboutPanel:' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Preferences...', accelerator: 'Command+,', click: => console.error("preferences not setup yet") }
|
||||
{ label: 'Preferences...', accelerator: 'Command+,', click: => @sendCommand('window:open-settings') }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Hide Atom', accelerator: 'Command+H', selector: 'hide:' }
|
||||
{ label: 'Hide Others', accelerator: 'Command+Shift+H', selector: 'hideOtherApplications:' }
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ parseCommandLine = ->
|
||||
options.usage """
|
||||
Atom #{version}
|
||||
|
||||
Usage: atom [options] [file ..]
|
||||
Usage: atom [options] [file ...]
|
||||
"""
|
||||
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
|
||||
options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.')
|
||||
|
||||
@@ -98,13 +98,13 @@ class FuzzyFinderView extends SelectList
|
||||
confirmed : ({filePath}) ->
|
||||
return unless filePath
|
||||
|
||||
if fsUtils.isFileSync(filePath)
|
||||
if fsUtils.isDirectorySync(filePath)
|
||||
@setError('Selected path is a directory')
|
||||
setTimeout((=> @setError()), 2000)
|
||||
else
|
||||
lineNumber = @getLineNumber()
|
||||
@cancel()
|
||||
@openPath(filePath, lineNumber)
|
||||
else
|
||||
@setError('Selected path does not exist')
|
||||
setTimeout((=> @setError()), 2000)
|
||||
|
||||
toggleFileFinder: ->
|
||||
@finderMode = 'file'
|
||||
|
||||
@@ -109,12 +109,12 @@ describe 'FuzzyFinder', ->
|
||||
expect(editor2.getPath()).toBe expectedPath
|
||||
expect(editor2.isFocused).toBeTruthy()
|
||||
|
||||
describe "when the selected path isn't a file that exists", ->
|
||||
describe "when the selected path is a directory", ->
|
||||
it "leaves the the tree view open, doesn't open the path in the editor, and displays an error", ->
|
||||
rootView.attachToDom()
|
||||
editorPath = rootView.getActiveView().getPath()
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
finderView.confirmed({filePath: 'dir/this/is/not/a/file.txt'})
|
||||
finderView.confirmed({filePath: project.resolve('dir')})
|
||||
expect(finderView.hasParent()).toBeTruthy()
|
||||
expect(rootView.getActiveView().getPath()).toBe editorPath
|
||||
expect(finderView.error.text().length).toBeGreaterThan 0
|
||||
|
||||
@@ -25,6 +25,9 @@ class SettingsView extends ScrollView
|
||||
rootView.command 'settings-view:toggle', ->
|
||||
rootView.open(configUri)
|
||||
|
||||
$(window).on 'window:open-settings', ->
|
||||
rootView.open(configUri)
|
||||
|
||||
@deserialize: ({activePanelName}={}) ->
|
||||
new SettingsView(activePanelName)
|
||||
|
||||
|
||||
@@ -147,13 +147,16 @@ module.exports =
|
||||
makeTree: (directoryPath) ->
|
||||
mkdirp.sync(directoryPath) if directoryPath and not @exists(directoryPath)
|
||||
|
||||
traverseTreeSync: (rootPath, onFile, onDirectory) ->
|
||||
traverseTreeSync: (rootPath, onFile, onDirectory=onFile) ->
|
||||
return unless @isDirectorySync(rootPath)
|
||||
|
||||
traverse = (directoryPath, onFile, onDirectory) ->
|
||||
for file in fs.readdirSync(directoryPath)
|
||||
childPath = path.join(directoryPath, file)
|
||||
stats = fs.statSync(childPath)
|
||||
stats = fs.lstatSync(childPath)
|
||||
if stats.isSymbolicLink()
|
||||
try
|
||||
stats = fs.statSync(childPath)
|
||||
if stats.isDirectory()
|
||||
traverse(childPath, onFile, onDirectory) if onDirectory(childPath)
|
||||
else if stats.isFile()
|
||||
|
||||
@@ -12,7 +12,7 @@ module.exports = (candidates, query, options={}) ->
|
||||
score += stringScore(path.basename(string), query)
|
||||
|
||||
# Shallow files are scored higher
|
||||
depth = Math.min(1, 10 - string.split('/').length - 1)
|
||||
depth = Math.max(1, 10 - string.split('/').length - 1)
|
||||
score *= depth * 0.01
|
||||
|
||||
{ candidate, score }
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
path = require 'path'
|
||||
|
||||
_ = require 'underscore'
|
||||
plist = require 'plist'
|
||||
{ScopeSelector} = require 'first-mate'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
grunt.registerTask 'convert-theme', 'Convert a TextMate theme to an Atom theme', ->
|
||||
if textMateThemePath = grunt.option('path')
|
||||
textMateThemePath = path.resolve(textMateThemePath)
|
||||
if grunt.file.isFile(textMateThemePath)
|
||||
textMateTheme = new TextMateTheme(textMateThemePath)
|
||||
themeName = path.basename(textMateThemePath, path.extname(textMateThemePath))
|
||||
atomThemePath = path.join(path.dirname(textMateThemePath), "#{themeName.toLowerCase()}-syntax.css")
|
||||
grunt.file.write(atomThemePath, textMateTheme.getStylesheet())
|
||||
grunt.log.ok("Atom theme written to: #{atomThemePath}")
|
||||
else
|
||||
grunt.log.error("No theme file found at: #{textMateThemePath}")
|
||||
false
|
||||
else
|
||||
grunt.log.error('Must specify --path=<path to TextMate theme>')
|
||||
false
|
||||
|
||||
class TextMateTheme
|
||||
constructor: (@path) ->
|
||||
@rulesets = []
|
||||
@buildRulesets()
|
||||
|
||||
buildRulesets: ->
|
||||
{settings} = plist.parseFileSync(@path)
|
||||
@buildGlobalSettingsRulesets(settings[0])
|
||||
@buildScopeSelectorRulesets(settings[1..])
|
||||
|
||||
getStylesheet: ->
|
||||
lines = []
|
||||
for {selector, properties} in @getRulesets()
|
||||
lines.push("#{selector} {")
|
||||
lines.push " #{name}: #{value};" for name, value of properties
|
||||
lines.push("}\n")
|
||||
lines.join('\n')
|
||||
|
||||
getRulesets: -> @rulesets
|
||||
|
||||
buildGlobalSettingsRulesets: ({settings}) ->
|
||||
{ background, foreground, caret, selection, lineHighlight } = settings
|
||||
|
||||
@rulesets.push
|
||||
selector: '.editor, .editor .gutter'
|
||||
properties:
|
||||
'background-color': @translateColor(background)
|
||||
'color': @translateColor(foreground)
|
||||
|
||||
@rulesets.push
|
||||
selector: '.editor.is-focused .cursor'
|
||||
properties:
|
||||
'border-color': @translateColor(caret)
|
||||
|
||||
@rulesets.push
|
||||
selector: '.editor.is-focused .selection .region'
|
||||
properties:
|
||||
'background-color': @translateColor(selection)
|
||||
|
||||
@rulesets.push
|
||||
selector: '.editor.is-focused .line-number.cursor-line-no-selection, .editor.is-focused .line.cursor-line'
|
||||
properties:
|
||||
'background-color': @translateColor(lineHighlight)
|
||||
|
||||
buildScopeSelectorRulesets: (scopeSelectorSettings) ->
|
||||
for { name, scope, settings } in scopeSelectorSettings
|
||||
continue unless scope
|
||||
@rulesets.push
|
||||
comment: name
|
||||
selector: @translateScopeSelector(scope)
|
||||
properties: @translateScopeSelectorSettings(settings)
|
||||
|
||||
translateScopeSelector: (textmateScopeSelector) ->
|
||||
new ScopeSelector(textmateScopeSelector).toCssSelector()
|
||||
|
||||
translateScopeSelectorSettings: ({ foreground, background, fontStyle }) ->
|
||||
properties = {}
|
||||
|
||||
if fontStyle
|
||||
fontStyles = fontStyle.split(/\s+/)
|
||||
properties['font-weight'] = 'bold' if _.contains(fontStyles, 'bold')
|
||||
properties['font-style'] = 'italic' if _.contains(fontStyles, 'italic')
|
||||
properties['text-decoration'] = 'underline' if _.contains(fontStyles, 'underline')
|
||||
|
||||
properties['color'] = @translateColor(foreground) if foreground
|
||||
properties['background-color'] = @translateColor(background) if background
|
||||
properties
|
||||
|
||||
translateColor: (textmateColor) ->
|
||||
if textmateColor.length <= 7
|
||||
textmateColor
|
||||
else
|
||||
r = parseInt(textmateColor[1..2], 16)
|
||||
g = parseInt(textmateColor[3..4], 16)
|
||||
b = parseInt(textmateColor[5..6], 16)
|
||||
a = parseInt(textmateColor[7..8], 16)
|
||||
a = Math.round((a / 255.0) * 100) / 100
|
||||
|
||||
"rgba(#{r}, #{g}, #{b}, #{a})"
|
||||
Referência em uma Nova Issue
Bloquear um usuário