Skip to content

Instantly share code, notes, and snippets.

@ezhlobo
Last active August 29, 2015 14:20
Show Gist options
  • Save ezhlobo/8d85c5783dbb3762db28 to your computer and use it in GitHub Desktop.
Save ezhlobo/8d85c5783dbb3762db28 to your computer and use it in GitHub Desktop.
Styleguides
{
"excludeFiles": ["node_modules/**", "dist/**"],
"disallowDanglingUnderscores": true,
"disallowEmptyBlocks": true,
"disallowFunctionDeclarations": true,
"disallowImplicitTypeConversion": ["numeric", "boolean", "binary", "string"],
"disallowKeywordsOnNewLine": ["else"],
"disallowMixedSpacesAndTabs": true,
"disallowMultipleLineBreaks": true,
"disallowMultipleSpaces": true,
"disallowNamedUnassignedFunctions": true,
"disallowNewlineBeforeBlockStatements": true,
"disallowOperatorBeforeLineBreak": ["+", "."],
"disallowQuotedKeysInObjects": "allButReserved",
"disallowSpaceAfterObjectKeys": true,
"disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
"disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
"disallowSpacesInCallExpression": true,
"disallowSpacesInFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInsideBrackets": true,
"disallowSpacesInsideParentheses": true,
"disallowTrailingComma": true,
"disallowTrailingWhitespace": true,
"requireAnonymousFunctions": true,
"requireBlocksOnNewline": true,
"requireCamelCaseOrUpperCaseIdentifiers": true,
"requireCapitalizedComments": true,
"requireCapitalizedConstructors": true,
"requireCommaBeforeLineBreak": true,
"requireCurlyBraces": [
"if",
"else",
"for",
"while",
"do",
"try",
"catch",
"case",
"default"
],
"requireDollarBeforejQueryAssignment": true,
"requireDotNotation": "except_snake_case",
"requireLineBreakAfterVariableAssignment": true,
"requireLineFeedAtFileEnd": true,
"requireMultipleVarDecl": "onevar",
"requirePaddingNewLineAfterVariableDeclaration": true,
"requirePaddingNewLinesAfterBlocks": {
"allExcept": ["inCallExpressions", "inArrayExpressions", "inProperties"]
},
"requirePaddingNewLinesAfterUseStrict": true,
"requirePaddingNewLinesBeforeExport": true,
"requirePaddingNewlinesBeforeKeywords": [
"do",
"for",
"if",
"switch",
"try",
"while",
"with",
"return"
],
"requirePaddingNewLinesBeforeLineComments": { "allExcept": "firstAfterCurly" },
"requirePaddingNewLinesInObjects": true,
"requireParenthesesAroundIIFE": true,
"requireSemicolons": true,
"requireSpaceAfterBinaryOperators": [
"=",
",",
"+",
"-",
"/",
"*",
"==",
"===",
"!=",
"!=="
],
"requireSpaceAfterKeywords": [
"do",
"for",
"if",
"else",
"switch",
"case",
"try",
"catch",
"void",
"while",
"with",
"return",
"typeof"
],
"requireSpaceAfterLineComment": true,
"requireSpaceBeforeBinaryOperators": [
"=",
"+",
"-",
"/",
"*",
"==",
"===",
"!=",
"!=="
],
"requireSpaceBeforeBlockStatements": 1,
"requireSpaceBeforeKeywords": [
"do",
"else",
"while",
"catch",
"catch"
],
"requireSpaceBeforeObjectValues": true,
"requireSpaceBetweenArguments": true,
"requireSpacesInConditionalExpression": true,
"requireSpacesInForStatement": true,
"requireSpacesInFunctionDeclaration": {
"beforeOpeningCurlyBrace": true
},
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true
},
"requireSpacesInFunction": {
"beforeOpeningCurlyBrace": true
},
"requireSpacesInsideObjectBrackets": "all",
"safeContextKeyword": ["that"],
"validateParameterSeparator": ", ",
"validateQuoteMarks": "'",
"requirePaddingNewLinesAfterBlocks": true
}
scss_files: 'app/**/*.scss'
linters:
ColorVariable:
enabled: false
ElsePlacement:
style: new_line
Indentation:
character: space
width: 4
LeadingZero:
style: include_zero
MergeableSelector:
force_nesting: false
NameFormat:
# Temporary
enabled: false
# user-friendly: ^\.?[A-Za-z]+(-[A-Za-z]+)*(_{SelectorFormat})?$
# convention: '^\.?[A-Za-z]+(-[A-Za-z]+)*(_(js)?-?[a-z]([A-Za-z\d]+(-[a-z][a-z\d]*)*)((--|__)[a-z]([a-z\d]*(-[a-z][a-z\d]*)*))*)?$'
NestingDepth:
max_depth: 3
PlaceholderInExtend:
enabled: false
SelectorDepth:
max_depth: 3
SelectorFormat:
convention: '^[a-z]+(-[a-z]+)*(_{2}[a-z]+(-[a-z]+)*)*(-{2}[a-z]+(-[a-z]+)*)*$|^-[a-z]+(-[a-z]+)*$'
ignored_types: ['element']
SingleLinePerProperty:
allow_single_line_rule_sets: false
QualifyingElement:
enabled: false
PropertySortOrder:
order:
# Dimensions
- width
- min-width
- max-width
- height
- min-height
- max-height
- padding
- padding-top
- padding-right
- padding-bottom
- padding-left
- margin
- margin-top
- margin-right
- margin-bottom
- margin-left
- top
- right
- bottom
- left
- position
- display
# Block
- float
- clear
- box-sizing
- border
- border-top
- border-right
- border-bottom
- border-left
- border-width
- border-top-width
- border-right-width
- border-bottom-width
- border-left-width
- border-style
- border-top-style
- border-right-style
- border-bottom-style
- border-left-style
- border-radius
- border-top-left-radius
- border-top-right-radius
- border-bottom-left-radius
- border-bottom-right-radius
- border-color
- border-top-color
- border-right-color
- border-bottom-color
- border-left-color
- background
- background-color
- background-image
- background-repeat
- background-position
- background-size
- box-shadow
- opacity
- visibility
- transform
# Text
- line-height
- font
- font-family
- font-size
- font-style
- font-variant
- font-weight
- font-smoothing
- color
- text-align
- text-decoration
- text-indent
- text-overflow
- text-rendering
- text-shadow
- text-transform
- text-wrap
- letter-spacing
- word-spacing
- white-space

The main purpose of this document is to show documentation of independent parts which may be used to create your own modules properly and quickly.

Table of content:

Interface

We called our application world. Therefore interface of communication with application looks like this:

app.world.say('message_to_world', attachmentInMessage)

# `attachmentInMessage` may be anything

See Modules to understand how to listen this messages.

Advanced

You have the opportunity to listen to what the world says manually:

app.world.listen('what_messages_you_want_to_listen', listener)

listener = (attachmentInMessage) ->

# `attachmentInMessage` is something that has been attached to message

But this interface is not recommended. They stay global because it is used to listen messages properly by modules.

Modules

Basic module:

app.Module.create

  body: (app, $) ->
    constructor: ->

Use onDocumentReady method to initialize your module when DOM has completely loaded:

app.Module.create

  body: (app, $) ->
    constructor: ->
    
  onDocumentReady: true

Modules doesn't know about each other. But sometimes one module have to share some data with other module.

Let's look at an example. First module will wait user click and after it should say to second module: {clicked: 'a'}.

In our approach you can not say specific module. But you can say to the world and hope that some module will hear.

First module:

app.Modules.create
  
  body: (app, $) ->
    constructor: ->
      $.document.on('click', 'a', @_handler)
      
    _handler: (e) ->
      msg =
        content: 'clickable'
        attachment: 
          clicked: e.target.tagName
    
      app.world.say(msg.content, msg.attachment)
      
      e.preventDefault()

Second module:

app.Modules.create

  body: (app, $) ->
    constructor: ->
    
    handler_clickable: (attachment) ->
      attachment.clicked
      # {clicked: 'A'}
      
  export:
    clickable: 'handler_clickable'

Method export in second module telling to the world what this module can hear. In this example second module can hear messages named clickable and invoke method handler_clickable as soon as heard.

Utilities

Utilities uses if you need to make alias for frequently used functions or make API for complex structure.

There are written utilities:

Ajax

Send ajax request to route:

route =
  name: 'save_data'
  obj: {dest: 'text'}

# `ajaxData` is what you send to jQuery.ajax function
ajaxData =
  # type described in router
  data:
    content: 'test message to send it to `save_data` router with `dest: text`'

app.utils.ajax route.name, route.obj, ajaxData
Advanced

If you don't want to send ajax request via router you can use ajax_plain utility.

ajaxData =
  type: 'post'
  data:
    content: 'test message to send it to /save_data/text'

app.utils.ajax_plain '/save_data/text', ajaxData

Hash

If you want to store some data in location.hash use hash utility:

orders_hash = app.utils.hash('orders')

orders_hash.add(52) # location.hash == '#&orders[52]'
orders_hash.add(54) # location.hash == '#&orders[52,54]'
orders_hash.remove(52) # location.hash == '#&orders[54]'

If you want to get array of data use .getArray():

orders_hash.getArray()
# [54]

If you want to store collection, use .setArray():

orders_hash.setArray([50, 51, 52])
# location.hash == '#&orders[50,51,52]'

You can setup separator of items in hash:

hash_options = 
  array_separator: '-'

orders_hash = app.utils.hash('orders', hash_options)

...and now your items in location.hash will be stored like #&orders[50-51-52].

Keys

Use human names if you will check keyCode of pressed key on the keyboard. For example:

app.utils.key.Enter # => 13

Usecase of it:

input_keyup = (e) ->
  if e.keyCode is app.utils.key.Enter
    e.preventDefault()

$.document.on('keyup', 'input', input_keyup)

Available names of keys: Enter, Esc, Space, ArrowLeft, ArrowTop, ArrowRight, ArrowDown.

Router

Router is not so popular in use. Most often used by internals parts of the framework.

For example in routes you write:

route_name: ['/route/url/:id', 'get']

Then you need to get the url string:

route =
  name: 'route_name'
  obj: {id: 10}

app.utils.router.url(route.name, route.obj)
# => '/route/url/10'

Or you need to get the route object:

route =
  name: 'route_name'
  obj: {id: 10}

app.utils.router.parse(route.name, route.obj)
# => ['/route/url/10', 'get']

Url

Used to redirect or open url in new tab.

For example in routes file you write:

route_name: ['/route/url/:id', 'get']

Then you need to open this route:

route =
  name: 'route_name'
  obj: 10

app.utils.url(route.name, route.obj).open()

If you want to open route in new tab:

app.utils.url(route.name, route.obj).open('_blank')

Patches

In case you need to update or change third-party libraries and frameworks use patches.

There are written patches:

Add ajax progress event

Add progress event for jQuery ajax method.

ajaxObject =
  type: 'put'
  progress: (e) ->
    if e.lengthComputable
      # Get percent of loading
      percent = (e.loaded / e.total) * 100
  success: successCallback

Add to cache jQuery wrappers for global nodes

$.document # jQuery wrapper for `document`
$.window   # jQuery wrapper for `window`

All equals symbols used for output variable should be on new line

/ Bad
.some-object = content

/ Good
.some-object 
  = content

Double quotes always

/ Bad
.some-object data-text='text'

/ Good
.some-object data-text="text"

Siblings should be divided by blank line

/ Bad
.element Element
.sibling Sibling

/ Good
.element Element

.sibling Sibling

Come to previous nesting level with blank line before

/ Bad
.element
  .children Element with children
.sibling Sibling

/ Good
.element
  .children Element with children
  
.sibling Sibling

Add class with dot symbol and id with number symbol

But string with insertion inside need to code like attribute.

/ Bad
.element class="class-name class-name--#{modifier}"
.element id="obj obj#{id}"

/ Good
.element.class-name class="class-name--#{modifier}"
.element#obj id="obj#{id}"

Add ID after CLASS

/ Bad
#id.class Text

/ Good
.class#id Text

Add id with number symbol

But string with insertion inside need to code like attribute.

/ Bad
.element class="class-name class-name--#{modifier}"

/ Good
.element.class-name class="class-name--#{modifier}"

Clear ruby hash without spaces on two sides inside braces

/ Bad
= link_to "Link", root_path, { class: "hello" }

/ Good
= link_to "Link", root_path, {class: "hello"}

Use new ruby syntax for hash

/ Bad
= link_to "Link", root_path, {"class" => "hello"}

/ Good
= link_to "Link", root_path, {class: "hello"}

Use lowercase characters for tag names

/ Bad
BODY
  P Paragraph

/ Good
body
  p Paragraph
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment