├── CONTRIBUTING.md ├── README.md ├── blog ├── README.md └── patterns.md ├── coding └── README.md ├── css └── README.md ├── design └── deliverables │ ├── README.md │ └── images │ ├── elementcollage-cloudfour.jpg │ └── moodboard-cloudfour.png ├── git ├── README.md ├── commit_template.txt └── pull_request_template.md ├── javascript ├── README.md └── vue │ └── README.md ├── learning └── javascript │ └── README.md ├── npm └── README.md ├── opensource └── README.md ├── package-json-script-names.md ├── rituals ├── README.md └── postmortems.md ├── testing └── README.md └── til ├── README.md ├── css └── filters-and-transitions.md ├── git └── README.md ├── js └── README.md └── lyza └── README.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Guides 2 | 3 | ## Just do it on `master`... 4 | 5 | * Adding a whole new section 6 | * Adding a TIL 7 | * Trivial modifications 8 | * When it just feels right and makes sense 9 | 10 | ## Branch/PR 11 | 12 | * Ongoing substantial changes to existing sections 13 | * Adding or modifying something that warrants discussion 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Guides 2 | 3 | Conventions, processes and notes about how we do things. 4 | 5 | - **[General Coding Conventions](./coding/)** 6 | - **[CSS Guide](./css/)** 7 | - **[JavaScript Guide](./javascript/)** 8 | - [Vue Guide](./javascript/vue) 9 | - **[Design Guide](./design/)** 10 | - **[Blog Guide](./blog)** 11 | - **[Git Guide](./git/)** 12 | - **[npm Guide](./npm)** 13 | - **[Open Source Guide](./opensource)** 14 | - **[Rituals Guide](./rituals)** 15 | - **[Today I Learned](./til/)** 16 | - **[Automated Testing](./testing)** -------------------------------------------------------------------------------- /blog/README.md: -------------------------------------------------------------------------------- 1 | # Cloud Four Blog Guide 2 | 3 |

Captain America sitting on a backwards chair

4 | 5 | So you've decided to write for the Cloud Four blog… Congratulations! There are a few things you may want to know about how our blog works: 6 | 7 | ## Post Excerpt Field 8 | 9 | Don't miss the "Excerpt" field at the bottom of the post editing UI. By crafting a short excerpt here, it will be displayed on the post listing pages and used for social media posts. If you don't set one explicitly, one will be created using the first few sentences of your post. 10 | 11 |

WordPress Editor Screen Options Dialogue

12 | 13 | Note you may need to open the "Screen Options" dialogue at the top of the page to make the "Excerpt" field visible. 14 | 15 | ## Featured Image Field 16 | 17 | Similarly, don't forget the "Featured Image" field in the sidebar. If you set an image here, it will be used for social media. This image is not displayed in the post content, however, so if you want to use it as a big image at the top of your post, you'll have to do that AND set the featured image. 18 | 19 | ## Categories and Tags 20 | 21 | Wordpress has a couple tools for organizing your posts: categories and tags. In the current iteration of cloudfour.com, we primarily use categories, and rarely use tags. Here's some background context from Tyler: 22 | 23 | >In past versions of the site, a large amount of tags proved tricky to navigate. So currently, we only expose categories (though we call them "Topics") in the front-end. Sometimes we use tags as an organizational tool behind the scenes, like flagging "featured" articles for the homepage. 24 | 25 | 26 | ## WordPress Shortcodes & Classes 27 | 28 | We have a small collection of [useful shortcodes and classes](patterns.md) to apply design patterns from our [pattern library](https://cloudfour-patterns.netlify.com/patterns/utilities.html). 29 | 30 | ## Previewing 31 | 32 | Note that our blog has two preview features. The "Preview" button only works for authenticated users. The "Enable Public Preview" checkbox will give you a public URL to share with unauthenticated users. 33 | 34 | Sometimes the public preview can get stuck or cached. To reset, just uncheck the preview box and check it again. 35 | 36 | ## Publication Time 37 | 38 | Jason's favorite time is 8:30 AM Pacific Time. Before lunch on East Coast, but late enough to be what people on West Coast see it first thing when they arrive in office. 39 | 40 | ## Comments & Pingbacks 41 | 42 | We don’t have a formal policy on comment approval, but here’s Jason's general guideline: 43 | 44 | - Let the author approve comments so they have the opportunity to process and respond if they want to. 45 | - Replying to comments is up to the author. If they contribute to understanding and there is nothing else to add, don’t feel compelled to respond. 46 | - Delete comments that are spam, troll, or jerk-like behavior. 47 | 48 | ### Advice from Jason: 49 | 50 | > Despite the fact that we ask people to be kind, courteous and constructive when they submit comments on our site, when articles reach a larger audience, we will inevitably end up some with comments that start to inch into an unkind territory. It can be hard to tell how to respond. If they are blatant jerks, I’ll simply delete their comment—you don’t get to come into our house and tear the place up. Sometimes with an obviously snarky comment, I’ll ignore the sarcasm and respond to the question as if it was asked in earnest. 51 | 52 | ### Pingbacks 53 | 54 | Don't approve pingbacks. We keep the feature enabled so we can see if websites link to us, but there's not very much review in displaying them on the site, and we don't optimize for them in our design. 55 | 56 | ## Translation Requests 57 | 58 | We have received requests to translate our articles in the past, but don't have a set answer. We'll considering saying "yes," if we still get credit, a link back to our site is clearly included, and they have a demonstrable track record of respectful translations. 59 | 60 | ## Writing Advice 61 | 62 | - [Don't Feel Like an Expert? Share Anyway.](https://medium.com/@sara_ann_marie/dont-feel-like-an-expert-share-anyway-661f2f8cd038) 63 | 64 | > Too many of the most interesting voices in tech and design talk themselves out of writing or speaking about their work—because they don’t think they have enough experience. But you don’t have to wait for “enough“ (whatever that means). Here’s how to find what’s special about your perspective right now—wherever you are in your career. 65 | 66 | - [Advice for Technical Writing](https://css-tricks.com/advice-for-technical-writing/) 67 | 68 | > In advance of a recent podcast with the incredible technical writer and Smashing Magazine editor-in-chief Rachel Andrew, I gathered up a bunch of thoughts and references on the subject of technical writing. So many smart people have said a lot of smart things over the years that I thought I'd round up some of my favorite advice and sprinkle in my own experiences, as someone who has also done his fair share of technical writing and editing. 69 | 70 | - [Avoid the Word "Just"](https://bradfrost.com/blog/post/just/) 71 | 72 | > “Just” makes me feel like an idiot. “Just” presumes I come from a specific background, studied certain courses in university, am fluent in certain technologies, and have read all the right books, articles, and resources. “Just” is a dangerous word. 73 | 74 | - [Words To Avoid in Educational Writing](https://css-tricks.com/words-avoid-educational-writing/) 75 | 76 | > I'm no English major, but as a writer and consumer of loads of educational (mostly tech) writing, I've come to notice a number of words and phrases that come up fairly often and don't add anything to the writing. In fact, they might detract from it. 77 | 78 | > Obviously; Basically; Simply; Of course; Clearly; Just; Everyone knows; However; So; Easy; 79 | 80 | - [Plain Language Is for Everyone, Even Experts](https://www.nngroup.com/articles/plain-language-experts/) 81 | 82 | > Professionals want clear, concise information devoid of unnecessary jargon or complex terms. Plain language benefits both consumers and organizations. 83 | 84 | - [Keep Code Samples Short & Relevant](https://twitter.com/sarah_edo/status/1106631555693187073) 85 | 86 | > When writing technical blog posts, please take care that the code samples in the article aren't long. In my opinion, the post shouldn't be the full repo. Highlight the specific parts of interest, and peel away boilerplate so people can read less and learn more. Then, if needed, link to a more complete code example on [CodePen](https://codepen.io/), [JSBin](https://jsbin.com/), or something similar. 87 | 88 | - [Write a Hulk Summary](https://chriscoyier.net/2020/01/23/the-hulk-summary/) 89 | 90 | > Channel your inner Hulk voice and use it to describe whatever you need to get writing on. Hammer down that shift key (caps lock is a cop-out) and type max 4 words for each bullet to capture the core sentiment of what you’re arguing. 91 | 92 | > WRITING IS HARD; YOU THINK TOO MUCH! WE HAVE A SOLUTION; THE HULK SUMMARY! 93 | -------------------------------------------------------------------------------- /blog/patterns.md: -------------------------------------------------------------------------------- 1 | # WordPress Shortcodes & Classes 2 | 3 | In addition to [Markdown](https://en.support.wordpress.com/markdown-quick-reference/), we have a small collection of useful shortcodes and classes to apply design patterns: 4 | 5 | Note that you'll need to disable the visual editor to use Markdown. Click on your name in the top right, and then check the "Disable the visual editor when writing" option. 6 | 7 | ## Box Shortcode 8 | 9 |

Box Example

10 | 11 | The Box shortcode will create a [Post Intro](https://cloudfour-patterns.netlify.com/patterns/combos/blog.html#post-intro). It will strip any line breaks from the text. 12 | 13 | ```html 14 | [c4box] 15 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 16 | [/c4box] 17 | ``` 18 | 19 | #### Grow Modifier 20 | 21 |

Box Grow Example

22 | 23 | The Grow modifier will add a [`u-textGrowX` class](https://cloudfour-patterns.netlify.com/patterns/utilities.html#text) using whatever size you pass in. 24 | 25 | ```html 26 | [c4box grow=2] 27 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 28 | [/c4box] 29 | ``` 30 | 31 | You can use `grow=0` to keep the text the same size as the rest of the post, which is useful for a sort of alert box. 32 | 33 | ## Footnotes 34 | 35 |

Footnotes Example

36 | 37 | This is actually a feature of WordPress's version of [Markdown Extra](https://en.support.wordpress.com/markdown-quick-reference/). 38 | 39 | ```md 40 | I have more [^1] to say up here. 41 | 42 | (other post content) 43 | 44 | [^1]: To say down here. 45 | ``` 46 | 47 | Footnotes marked up this way will be added to the bottom of the post with a link back to the original reference. 48 | 49 | ## Figure Shortcode 50 | 51 |

Figure Example

52 | 53 | The Figure shortcode will create a [Figure](https://cloudfour-patterns.netlify.com/patterns/components/figure.html), with an optional caption and class. 54 | 55 | ```html 56 | [c4figure caption="Our offline notification banner." class="example"] 57 | 58 | [/c4figure] 59 | ``` 60 | 61 | Note the optional use of the `u-borderSm` utility class to add a light border to the image. Images with a white background may benefit from a border. 62 | 63 | ## Code Samples 64 | 65 | The WordPress Markdown editor understands both inline code using backticks — `` `code` `` — and "fenced" code blocks, using triple backticks: 66 | 67 | ````markdown 68 | ```css 69 | a { 70 | color: red; 71 | } 72 | ``` 73 | ```` 74 | 75 | Note that you can trigger syntax highlighting by indicating what type of code you're writing: `` ```css ``, `` ```html ``, and `` ```js ``, for example. 76 | 77 | #### Combining with Figure 78 | 79 | You can also wrap your code sample in a `c4figure` to add a caption, but because Markdown doesn't work inside WordPress shortcodes, you'll need to add the `pre` and `code` elements by hand, like so: 80 | 81 | ```html 82 | [c4figure caption="testing"] 83 |

 84 | a {
 85 |   color: red;
 86 | }
 87 | 
88 | [/c4figure] 89 | ``` 90 | 91 | ## FlexEmbed Shortcode 92 | 93 |

Flex Embed Example

94 | 95 | The FlexEmbed shortcode create a [Flex Embed](https://cloudfour-patterns.netlify.com/patterns/components/flex-embed.html), used to make an embed resize responsively while retaining its aspect ratio.. 96 | 97 | ```html 98 | [c4flexembed] 99 | 100 | [/c4flexembed] 101 | ``` 102 | 103 | #### Ratio Modifier 104 | 105 | You can manually choose the aspect ratio of the embed by setting the `ratio` attribute to either `1by1`, `2by1`, `3by1`, or `4by3`. You don't need to specify `16by9`, as that's the default. 106 | 107 | ```html 108 | [c4flexembed ratio="1by1"] 109 | 110 | [/c4flexembed] 111 | ``` 112 | 113 | #### No Wrap Modifier 114 | 115 | Passing the `nowrap` modifier will prevent the embedded content from being wrapped in `
`. It's useful if you're manually adding the class to your embed. 116 | 117 | ```html 118 | [c4flexembed nowrap=true] 119 | 120 | [/c4flexembed] 121 | ``` 122 | 123 | #### Combining with Figure 124 | 125 |

Flex Embed with Caption Example

126 | 127 | You can use `c4flexembed` inside `c4figure` to add a caption to your embedded content. 128 | 129 | ```html 130 | [c4figure caption="Val Head's animation talk from Responsive Field Day"] 131 | [c4flexembed] 132 | 133 | [/c4flexembed] 134 | [/c4figure] 135 | ``` 136 | 137 | ## Image Alignment 138 | 139 | ### Featured Image 140 | 141 |

Featured Image Example

142 | 143 | A featured image is pulled outside the content column, but isn't quite full-bleed. We accomplish this using [`u-pullSidesX` utility classes](https://cloudfour-patterns.netlify.com/patterns/utilities.html#space). 144 | 145 | ```html 146 |
147 | [c4figure] 148 | Wally Wood’s 22 Panels That Always Work 149 | [/c4figure] 150 |
151 | ``` 152 | 153 | Here, the combination of `u-pullSides1 u-md-pullSides6` will pull the image just outside the content container on small screens, and quite a bit more on medium and larger screens. 154 | 155 | ### Full-Bleed Image 156 | 157 |

Full-Bleed Image Example

158 | 159 | If you have an image you really want to showcase, try using the `u-release` class to make it full-bleed. Be aware this works best with images that are much wider than they are tall, otherwise users with very wide browsers may find the image fills the entire screen. 160 | 161 | ```html 162 |
163 | [c4figure caption="My book was conference SWAG! It was handed out along with t-shirts and water bottles as attendees entered the conference."] 164 | 165 | [/c4figure] 166 |
167 | ``` 168 | 169 | ### Float Left/Right Image 170 | 171 |

Floated Image Example

172 | 173 | Use a combination of [sizing utility classes](https://cloudfour-patterns.netlify.com/patterns/utilities.html#size) and [layout utility classes](https://cloudfour-patterns.netlify.com/patterns/utilities.html#layout) to scale and image and float it left or right. 174 | 175 | ```html 176 |
177 | [c4figure] 178 | The cover for Daredevil issue 5, with a caption promoting art by Wally Wood. 179 | [/c4figure] 180 |
181 | ``` 182 | 183 | Here, `u-sm-size1of2` will keep the image sized to 50% of the content column, `u-sm-floatRight` will float the image to the right on small screens and larger (but not very small screens). `u-sm-spaceLeft1` ensures there's margin on the image so text doesn't run up against it, and `u-md-pullRight6` will pull the floated image slightly outside the content container on medium and larger screens. 184 | -------------------------------------------------------------------------------- /coding/README.md: -------------------------------------------------------------------------------- 1 | ## Editors 2 | 3 | We enforce consistency in editor defaults using an **[`.editorconfig`](http://editorconfig.org/)**. The contents of our preferred editorconfig settings are: 4 | 5 | ``` 6 | root = true 7 | 8 | [*] 9 | indent_style = tab 10 | indent_size = 2 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | 18 | # YAML files cannot have tabs 19 | # @see https://yaml.org/faq.html 20 | [*.yml] 21 | indent_style = space 22 | ``` 23 | 24 | ### Enforcing editor defaults 25 | 26 | Automated enforcement of `.editorconfig` is enabled for you by default in boxen if you use Atom or Sublime Text. 27 | 28 | Everyone (unless you're an exception, and you'll know if that is the case) has an available `.editorconfig` in their user directory for consumption by editors. 29 | 30 | If you use a different editor, check to see if your editor has support for, or a package/plugin that supports, editorconfig and install/enable it. 31 | 32 | It is known that BBEdit, for some inexplicable reason, does not support editorconfig. It's probably possible to replicate the editorconfig settings by adjusting preferences. Shrug. 33 | -------------------------------------------------------------------------------- /css/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [ARIA Role, State, and Property Quick Reference]: https://www.w3.org/TR/html-aria/#aria-table 4 | [About HTML Semantics and Front-end Architecture]: http://nicolasgallagher.com/about-html-semantics-front-end-architecture 5 | [Atom]: http://atom.io 6 | [Atomic CSS and Lobotomized Owls]: http://alistapart.com/article/axiomatic-css-and-lobotomized-owls 7 | [Autoprefixer]: https://github.com/postcss/autoprefixer 8 | [CSS Dig]: https://css-tricks.com/starting-a-refactor-with-css-dig/ 9 | [CSS Guidelines: Architectural Principles]: http://cssguidelin.es/#architectural-principles 10 | [CSS Guidelines: JavaScript Hooks]: http://cssguidelin.es/#javascript-hooks 11 | [CSS Guidelines]: http://cssguidelin.es 12 | [CSS Property Order]: http://markdotto.com/2011/11/29/css-property-order/ 13 | [CSS Reset]: http://meyerweb.com/eric/tools/css/reset/ 14 | [CSScomb config]: http:// 15 | [CSScomb]: http://csscomb.com 16 | [Code Guide by @mdo]: http://codeguide.co/#css 17 | [KSS]: https://github.com/kss-node/kss-node 18 | [Modular CSS BEM/OOCSS Naming]: http://benfrain.com/modular-css-bem-oocss-naming/ 19 | [Naming CSS Stuff Is Really Hard]:http://seesparkbox.com/foundry/naming_css_stuff_is_really_hard 20 | [normalize.css]: http://necolas.github.io/normalize.css/ 21 | [Outside In]: http://webdesign.tutsplus.com/articles/outside-in-ordering-css-properties-by-importance--cms-21685 22 | [PostCSS]: https://github.com/postcss/postcss 23 | [Rework]: https://github.com/reworkcss/rework 24 | [SUIT CSS Linter]: https://github.com/necolas/postcss-bem-linter 25 | [SUIT CSS Naming Conventions]: https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md 26 | [SUIT CSS Utils]: https://github.com/suitcss/utils 27 | [Sass Guidelines: The 7-1 Pattern]: http://sass-guidelin.es/#the-7-1-pattern 28 | [stylelint]: https://stylelint.io/ 29 | [stylefmt]: https://github.com/morishitter/stylefmt 30 | [Sublime Text]: http://sublimetext.com 31 | [The CSS Specificity Graph]: http://csswizardry.com/2014/10/the-specificity-graph/ 32 | 33 | # CSS Guide 34 | 35 | Clean, consistent and understandable CSS is paramount to a successful project. It sets the tone, both visually and architecturally, for the entire front-end. These are our collected (and evolving) best practices for writing styles with some _style_. 😎 36 | 37 | - [Organization](#organization) 38 | - [Directory Structure](#directory-structure) 39 | - [Base Styles](#base-styles) 40 | - [Components](#components) 41 | - [Utilities](#utilities) 42 | - [Conventions](#conventions) 43 | - [General Rules](#general-rules) 44 | - [Property Sorting](#property-sorting) 45 | - [Selectors](#selectors) 46 | - [Class Naming](#class-naming) 47 | - [Comments](#comments) 48 | - [Architecture](#architecture) 49 | - [Dryness](#dryness) 50 | - [Encapsulation](#encapsulation) 51 | - [Composition](#composition) 52 | - [Compatibility](#compatibility) 53 | - [Tools](#tools) 54 | - [Processors](#processors) 55 | - [Formatters](#formatters) 56 | - [Validators](#validators) 57 | - [Analyzers](#analyzers) 58 | 59 | ## Organization 60 | 61 | ### Directory Structure 62 | 63 | This structure is an adaptation of [Sass Guidelines: The 7-1 Pattern]. It represents the organization of different types of style sheets, and the order they should follow. Unless specific project requirements dictate otherwise, the directory structure should look _something_ like this: 64 | 65 |
 66 | ├── base/
 67 | │   ├── forms.css
 68 | │   ├── typography.css
 69 | │   └── variables.css
 70 | ├── components/
 71 | │   ├── alert.css
 72 | │   ├── button.css
 73 | │   └── grid.css
 74 | ├── utils/
 75 | │   ├── display.css
 76 | │   ├── position.css
 77 | │   └── text.css
 78 | ├── vendor/
 79 | │   └── ...
 80 | └── main.css
 81 | 
82 | 83 | ### Base Styles 84 | 85 | The `base/` directory should contain foundational styles and other global dependencies. There should be few (if any) class definitions within this directory. In addition to common variables, this would also be an appropriate place to put mixins or functions if a preprocessor is in use. 86 | 87 | - Variables, mixins and functions should be organized in their own separate files. 88 | 89 | ```css 90 | /* base/variables.css */ 91 | 92 | :root { 93 | --font-family-sans: popular-sans, "Helvetica Neue", sans-serif; 94 | --font-size-base: 22px; 95 | --transition-duration: 360ms; 96 | } 97 | 98 | @custom-media --width-min-md screen and (min-width: 30em); 99 | @custom-media --width-min-lg screen and (min-width: 60em); 100 | ``` 101 | 102 | - Each file should only be responsible for providing base styles for a designated group of related elements. 103 | 104 | ```css 105 | /* base/scaffolding.css */ 106 | 107 | * {/*...*/} 108 | 109 | html {/*...*/} 110 | 111 | body {/*...*/} 112 | ``` 113 | 114 | ```css 115 | /* base/forms.css */ 116 | 117 | label {/*...*/} 118 | 119 | input {/*...*/} 120 | 121 | button {/*...*/} 122 | ``` 123 | 124 | ```css 125 | /* base/typography.css */ 126 | 127 | h1, 128 | h2, 129 | h3 {/*...*/} 130 | 131 | pre, 132 | code {/*...*/} 133 | ``` 134 | 135 | ### Components 136 | 137 | The `components/` directory should have the largest number of files, because most of the CSS should be written as small, reusable components. 138 | 139 | - Each file should contain only one component and, if possible, only class selectors with a common namespace for that component: 140 | 141 | ```css 142 | /* components/alert.css */ 143 | 144 | .Alert {/*...*/} 145 | 146 | .Alert--fixed {/*...*/} 147 | 148 | .Alert-header {/*...*/} 149 | 150 | .Alert-closeButton {/*...*/} 151 | ``` 152 | 153 | ```css 154 | /* components/button.css */ 155 | 156 | .Button {/*...*/} 157 | 158 | .Button--large {/*...*/} 159 | 160 | .Button--small {/*...*/} 161 | ``` 162 | 163 | ### Utilities 164 | 165 | The `utilities/` directory is where definitions for utility classes (or "helpers") should occur. Unlike components, there may be many of these class definitions per file. Their organization should be according to what kind of properties they affect. See [SUIT CSS Utils] for a nice example of this organization. 166 | 167 | - Each file should contain only classes prefixed with `u-` to identity them as utilities. 168 | 169 | ```css 170 | /* utilities/margin.css */ 171 | 172 | .u-marginAbove { 173 | margin-top: var(--vspace) !important; 174 | } 175 | 176 | .u-marginBelow { 177 | margin-bottom: var(--vspace) !important; 178 | } 179 | ``` 180 | 181 | - To ensure dominance over conflicting declarations, **utilities should come last after all other styles** in `main.css`. 182 | 183 | ```css 184 | /* main.css */ 185 | 186 | @import "base"; 187 | @import "components"; 188 | @import "sections"; 189 | @import "utils"; 190 | ``` 191 | 192 | [⇧ top](#css-guide) 193 | 194 | 195 | ## Conventions 196 | 197 | ### General Rules 198 | 199 | These rules were adapted from [CSS Guidelines]. This is an example of how declaration block syntax should be formatted (Sass syntax used to illustrate nesting): 200 | 201 | ```sass 202 | .Selector-1, 203 | .Selector-2 { /* 1 */ 204 | @include some-mixin(); /* 2 */ 205 | 206 | display: block; /* 3 */ 207 | background-color: rgba(0, 0, 0, 0.1); /* 4 */ 208 | background-image: url("image.png"); /* 5 */ 209 | opacity: 0.8; /* 6 */ 210 | padding: 0; /* 7 */ 211 | transition-duration: 0.3s; /* 8 */ 212 | 213 | &:hover, 214 | &:focus { /* 9 */ 215 | color: green; 216 | } 217 | 218 | &.is-disabled, 219 | &[disabled] { /* 10 */ 220 | pointer-events: none; 221 | } 222 | 223 | @media (min-width: 40em) { /* 11 */ 224 | width: auto; 225 | } 226 | 227 | &::before { /* 12 */ 228 | content: "Foo"; 229 | } 230 | } /* 13 */ 231 | /* 14 */ 232 | ``` 233 | 234 | 1. Combined selectors should be on separate lines, and the opening brace should be on the same line as the last selector. 235 | 2. Variables and preprocessor cruft should come before any properties, separated with blank line below. 236 | 3. One space should be after each colon, and each line should end with a semicolon. 237 | 4. Comma-delimited numbers inside of values with parenthesis (e.g. `rgb(0, 0, 0)`) should have spaces between them. 238 | 5. Strings within values should use double quotes. 239 | 6. Decimal values should include a leading `0`. 240 | 7. Values of zero should be unit-less. 241 | 8. Time values should be represented with the second (`s`) unit. This is easier for humans to parse, and encourages shorter values that divide evenly within an ideal 60 frames-per-second animation speed. 242 | 9. Nested pseudo class blocks should come after all property declarations. 243 | 10. Nested class or attribute blocks should come after all pseudo class blocks. 244 | 11. Nested media queries should come after all combined class or attribute blocks. 245 | 12. Nested pseudo element blocks should come after all media queries. 246 | 13. Closing braces should be on a new line. 247 | 14. A blank line should come after each declaration block. 248 | 249 | ### Order of Nested Selectors 250 | 251 | We use a standard order for nested selectors in Sass. By following this order, our code becomes more standardized and easier to understand. 252 | 253 | When in doubt, remember that the goal is to first define any **included** styles, followed by **regular** styles, followed by **modifiers**, followed by **children** (whose code would follow this same order). 254 | 255 | 256 | 1. #### Included Code 257 | 258 | 1. Local `$variables` 259 | * Local variables should really only be declared for mixins or functions. Most variables should be kept in the main variables partial, since variables in Sass are global. 260 | * However, if you have a set of variables that will only be used in a certain partial, declare them at the top of that file and prefix their names to avoid confusion in the global namespace. e.g., `$m_module_name_height`. 261 | 262 | 1. `@extend` statements 263 | * Avoid extends in favor of mixins. Extends offer no benefits over mixins, and can cause [specificity problems](http://csswizardry.com/2016/02/mixins-better-for-performance/). 264 | 265 | 1. `@include` statements 266 | * Knowing right off the bat that this class inherits another whole set of rules from elsewhere is good. Another benefit is that overriding styles for that inherited set of rules becomes much easier. 267 | 268 | 2. #### Alphabetized Regular Styles 269 | 1. Adding regular styles after the `@extend` and `@include` statements allows us to override those properties, if needed. Be sure to leave a comment if a declaration's only purpose is to override included styles. 270 | 271 | 1. Alphabetizing is helpful for a large team because it standardizes location of properties (See "Property Sorting" below). 272 | 273 | 3. #### Modifiers 274 | 1. Pseudo-classes (`:hover`), attribute selectors (`&[type="input"]`), and state classes (`&.is-active`) 275 | * These directly modify the parent selector so we declare them before other nested selectors. 276 | * Most BEM modifier classes don't need to be nested. However, some generic state class names like `is-active` that would otherwise be too non-specific to live in the global namespace, should be nested here. 277 | 278 | 1. Nested media queries 279 | * These come after regular styles, pseudo-classes, etc., so they can override them. 280 | 281 | 1. Parent modifier classes (`.parent__modifier &`) 282 | * Modifiers on parents can affect children. They should be nested like media queries. 283 | 284 | 4. #### Child Selectors 285 | 286 | 1. Pseudo-elements (`::before`) 287 | * Pseudo-elements are actually generated children, and so should be treated like any other nested selector. 288 | 289 | 2. Nested selectors 290 | * As a rule, **if a selector will work without it being nested then do not nest it.** 291 | * There shouldn’t be many nested selectors. Our naming convention means that we don’t need to nest selectors for namespacing. Before you nest a selector, consider if it would be better as a child class or modifier class. 292 | * Any nested selectors could contain their own nested pseudo-classes, pseudo-elements and media queries, following the rules above. 293 | 294 | ```sass 295 | .foo { 296 | @include font_ui(2.0); // 1.iii 297 | line-height: 1; // override font_ui line-height, 2.i 298 | width: 100%; // 2.ii 299 | 300 | &:hover { // 3.i - modifier: pseudo-class 301 | color: red; 302 | } 303 | 304 | // state classes usually have `is-` or `has-` class names that need to be nested. 305 | &.has-error { // 3.i - modifier: state class 306 | color: red; 307 | } 308 | 309 | @media only screen and (min-width: $screen_medium) { // 3.ii - modifier: media query 310 | width: 100%; 311 | } 312 | 313 | @media only screen and (min-width: $screen_large) { // 3.ii - modifier: media query 314 | width: 50%; 315 | } 316 | 317 | &::before { // 4.i - child: pseudo-element 318 | content: "!"; 319 | } 320 | 321 | // this should really be a non-nested BEM child class! 322 | h2 { // 4.ii - child: nested selector 323 | font-size: 2em; 324 | } 325 | } 326 | 327 | // modifier with proper BEM name 328 | // note the nested selectors follow the same order. 329 | .foo--bar { 330 | color: red; 331 | 332 | &:hover { 333 | color: orange; 334 | } 335 | 336 | @media only screen and (min-width: $screen_large) { 337 | display: none; 338 | } 339 | } 340 | 341 | 342 | // child element with proper BEM name 343 | .foo__icon { 344 | width: 1em; 345 | 346 | // nested modifier makes it easier to understand 347 | .foo--bar & { 348 | width: 2em; 349 | } 350 | } 351 | ``` 352 | 353 | ### Property Sorting 354 | 355 | Until recently, we followed Guy Routledge's [Outside In] method of property sorting. Over time, we discovered most property sorting methodologies require maintenance as new properties (for example, `flex-*` or `grid-*`) are introduced. This makes them inherently fragile and difficult to enforce. 356 | 357 | We now recommend properties are sorted alphabetically. This technique will scale to accommodate any new properties, and requires no learning curve for new project contributors. 358 | 359 | * You can quickly alphabetize declarations in Sublime Text by selecting several lines of code and pressing F5. 360 | * You can quickly alphabetize declarations in VS Code by selecting several lines of code and using the "Sort Lines Ascending" command. This has no keyboard shortcut by default, so you can either use the command pallete (CMD+SHIFT+P) or assign a keyboard shortcut. 361 | 362 | ```css 363 | /* Do */ 364 | 365 | selector { 366 | display: flex; 367 | font-size: 2em; 368 | left: 0; 369 | position: absolute; 370 | top: 0; 371 | } 372 | ``` 373 | 374 | ```css 375 | /* Don't */ 376 | 377 | selector { 378 | position: absolute; 379 | top: 0; 380 | left: 0; 381 | display: flex; 382 | font-size: 2em; 383 | } 384 | ``` 385 | 386 | It is recommended to use tools like [stylelint] to enforce these sorts of rules, which can be combined with the `--fix` option or a complementary tool like [stylefmt] to organize CSS properties from text editors like [Atom] and [Sublime Text]. 387 | 388 | ### Selectors 389 | 390 | - ID selectors should be avoided 391 | 392 | ```css 393 | /* Don't */ 394 | 395 | #some-id {} 396 | ``` 397 | 398 | ```css 399 | /* Don't even */ 400 | 401 | element#some-id {} 402 | ``` 403 | 404 | - Element selectors should be avoided outside of defining base styles 405 | 406 | ```css 407 | /* Don't */ 408 | 409 | .Component ul {} 410 | ``` 411 | 412 | ```css 413 | /* Don't */ 414 | 415 | .Component > span {} 416 | ``` 417 | 418 | ```css 419 | /* Don't */ 420 | 421 | li.Component-item {} 422 | ``` 423 | 424 | - Nesting should be avoided unless the resulting specificity is actually needed 425 | 426 | ```css 427 | /* Do */ 428 | 429 | .Component {} 430 | 431 | .Component-element {} 432 | ``` 433 | 434 | ```css 435 | /* Don't */ 436 | 437 | .Component {} 438 | 439 | .Component .Component-element {} 440 | ``` 441 | 442 | **Note:** It is also acceptable to "nest" pseudo classes and pseudo elements when using a preprocessor, since doing this has no unintentional effect on specificity. 443 | 444 | - Nested selectors may only be two levels deep and must consist of a modifier class followed by an element class 445 | 446 | ```css 447 | .Component--modifier .Component-element {} 448 | ``` 449 | 450 | - Unrelated selectors should not be combined 451 | 452 | ```css 453 | /* Do */ 454 | 455 | h1, 456 | h2, 457 | h3 { 458 | font-weight: bold; 459 | letter-spacing: -0.1em; 460 | } 461 | ``` 462 | 463 | ```css 464 | /* Don't */ 465 | 466 | .Component-header, 467 | .OtherComponent-header, 468 | .AnotherComponent--extended { 469 | margin-top: 0; 470 | } 471 | ``` 472 | 473 | **Note:** If using a preprocessor like Sass, the `@extend` feature should be used with great care to avoid the unintentional combining of unrelated selectors. 474 | 475 | ### Class Naming 476 | 477 | Naming stuff can be hilariously difficult. To minimize future confusion, try to pick names that are less likely to change (or become inaccurate). For example, a component name of `.FormGroup` might be better than `.RegistrationShipping`, since it describes a _function_ rather than a _context_. See [Naming CSS Stuff Is Really Hard] for more examples. 478 | 479 | The following conventions were adapted from the [SUIT CSS Naming Conventions]. 480 | 481 | #### Utility Classes 482 | 483 | Syntax: `u-[sm|md|lg-]` 484 | 485 | ```css 486 | .u-floatLeft { 487 | float: left !important; 488 | } 489 | 490 | @media (--sm) { 491 | .u-sm-floatLeft { 492 | float: left !important; 493 | } 494 | } 495 | ``` 496 | 497 | #### Component Classes 498 | 499 | Syntax: `[--modifierName|-descendentName` 500 | 501 | ```css 502 | /* Component Name */ 503 | .Alert {} 504 | 505 | /* Modifier */ 506 | .Alert--dismissable {} 507 | 508 | /* Descendent */ 509 | .Alert-closeButton {} 510 | 511 | /* Modifying descendants */ 512 | .Alert--dismissable .Alert-closeButton {} 513 | ``` 514 | 515 | Avoid nesting descendents: 516 | 517 | ```css 518 | /* Do */ 519 | 520 | .Nav-subnavButton {} 521 | 522 | /* Don't */ 523 | 524 | .Nav-subnav-button {} 525 | ``` 526 | 527 | If you find yourself wanting complex parent-child relationships within a single component, you may benefit from breaking it into into multiple independent components: 528 | 529 | ```css 530 | .Nav {} 531 | 532 | .Subnav {} 533 | ``` 534 | 535 | #### States 536 | 537 | Syntax: `.is-stateOfComponent` 538 | 539 | State classes should reflect changes to a component's state. As such, it's important to resist the temptation to apply direct styles to these classes. Scoping states to associated component classes insures the use of consistent cross-component terminology. 540 | 541 | ```css 542 | /* Component Name */ 543 | .Tweet {} 544 | 545 | /* State of component */ 546 | .Tweet.is-expanded {} 547 | ``` 548 | 549 | It's also acceptable (and in some cases preferred) to manage state via built-in browser properties: 550 | 551 | ```css 552 | .Toggle:checked {} 553 | 554 | .Input:disabled {} 555 | 556 | .Tweet[aria-expanded="true"] {} 557 | ``` 558 | 559 | #### Micro-semantics 560 | 561 | When deciding how to construct complex class names with multiple delimited pieces, look at existing HTML specifications for inspiration before deciding on something arbitrary. 562 | 563 | The [ARIA Role, State, and Property Quick Reference] is a good resource for common element and state names. 564 | 565 | ```css 566 | /* Elements */ 567 | 568 | .Component-body {} 569 | .Component-header {} 570 | .Component-button {} 571 | .Component-dialog {} 572 | .Component-img {} 573 | ``` 574 | 575 | ```css 576 | /* Modifiers */ 577 | 578 | .Component--labelled {} 579 | .Component--hasPopop {} 580 | ``` 581 | 582 | ```css 583 | /* States */ 584 | 585 | .Component.is-busy {} 586 | .Component.is-expanded {} 587 | .Component.is-checked {} 588 | .Component.is-selected {} 589 | ``` 590 | 591 | #### JavaScript Hooks 592 | 593 | See [CSS Guidelines: JavaScript Hooks] 594 | 595 | ### Comments 596 | 597 | Comments are a good idea. There is no standardized CSS documentation tool ([KSS] for example) currently in use. For comments that explain declarations, this formatting is nice: 598 | 599 | From https://github.com/suitcss/components-arrange/blob/master/lib/arrange.css 600 | 601 | ```css 602 | /** 603 | * 1. Protect against the component expanding beyond the confines of its 604 | * container if properties affecting the box-model are applied to the 605 | * component. Mainly necessary because of (5). 606 | * 2. Rely on table layout. 607 | * 3. Zero out the default spacing that might be on an element (e.g., `ul`). 608 | * 4. Make sure the component fills at least the full width of its parent. 609 | * 5. Reset the table-layout algorithm in case a component is nested. 610 | */ 611 | 612 | .Arrange { 613 | box-sizing: border-box; /* 1 */ 614 | display: table; /* 2 */ 615 | margin: 0; /* 3 */ 616 | min-width: 100%; /* 4 */ 617 | padding: 0; /* 3 */ 618 | table-layout: auto; /* 5 */ 619 | } 620 | ``` 621 | 622 | Avoid simply restating what the property already tells us. Try to provide useful clarification of _why_ a rule was chosen. 623 | 624 | ```css 625 | /* Don't */ 626 | 627 | /** 628 | * 1. Use relative positioning. 629 | */ 630 | 631 | .Nav { 632 | position: relative; /* 1 */ 633 | } 634 | 635 | /* Do */ 636 | 637 | /** 638 | * 1. Allow child elements like the logo to position themselves relative 639 | to this container. 640 | */ 641 | 642 | .Nav { 643 | position: relative; /* 1 */ 644 | } 645 | ``` 646 | 647 | [⇧ top](#css-guide) 648 | 649 | 650 | ## Architecture 651 | 652 | See [CSS Guidelines: Architectural Principles] 653 | 654 | ### Dryness 655 | 656 | Use the following properties with care. They should occur in reusable utilities most of the time, and not repeated across a wide variety of components. 657 | 658 | - `margin` 659 | - `float` 660 | - `width` 661 | - `height` 662 | - `font-*` 663 | - `line-height` 664 | - `text-align` 665 | - `white-space` 666 | 667 | ### Encapsulation 668 | 669 | When writing base styles for a component, assume that the component is unaware of everything outside of its box. Add styles that depend on surrounding elements with care (or instead use more utility classes in your HTML.) 670 | 671 | ```css 672 | /* Do */ 673 | 674 | .Component { 675 | display: block; 676 | } 677 | 678 | .Component--withMargin { 679 | margin-top: 1em; 680 | } 681 | 682 | .Component--size1of2 { 683 | width: 50%; 684 | } 685 | ``` 686 | 687 | ```css 688 | /* Don't */ 689 | 690 | .Component { 691 | margin-top: 1em; 692 | display: block; 693 | width: 50%; 694 | } 695 | ``` 696 | 697 | ### Composition 698 | 699 | When combining components for specific overrides, do this in a context-specific style sheet: 700 | 701 | ```css 702 | /* sections/search.css */ 703 | 704 | .Section--search .Button {/*...*/} 705 | ``` 706 | 707 | If this combination reoccurs, consider creating a new component to abstract the needed pieces: 708 | 709 | ```css 710 | /* components/searchbar.css */ 711 | 712 | .SearchBar {/*...*/} 713 | 714 | .SearchBar-button {/*...*/} 715 | ``` 716 | 717 | ### Compatibility 718 | 719 | Vendor prefixes or other non-standard fallbacks make CSS difficult to read and maintain. Even mixins require documentation and maintenance. [Autoprefixer] will handle prefixes and other fallbacks based on your project's actual support requirements. This allows us to write styles in a standard and predictable way: 720 | 721 | ```scss 722 | /* Don't */ 723 | .Component { 724 | -webkit-transform: translateX(-50%); 725 | -ms-transform: translateX(-50%); 726 | transform: translateX(-50%); 727 | } 728 | 729 | /* Don't */ 730 | .Component { 731 | @include translateX(-50%); 732 | } 733 | 734 | /* Do */ 735 | .Component { 736 | transform: translateX(50%); 737 | } 738 | ``` 739 | 740 | [⇧ top](#css-guide) 741 | 742 | 743 | ## Tools 744 | 745 | ### Processors 746 | 747 | - **[PostCSS]** 748 | 749 | ### Validators 750 | 751 | - **[stylelint]** With this plugin, you can check the validity of stylesheets against a set of project-specific conventions. The plugin will throw an error if it finds CSS that violates these rules. 752 | 753 | ### Formatters 754 | 755 | - **[stylefmt]** Works alongside stylelint to help format your code. 756 | 757 | ### Analyzers 758 | 759 | - **[The CSS Specificity Graph]** A very simple model for diagrammatically assessing the overall health of your codebase in terms of specificity—a way of looking at an entire project’s CSS and highlighting any potentially troublesome areas of higher-than-ideal specificity. 760 | - **[CSS Dig]** A Chrome extension that summarizes selector and propery usage for any given page. Particularly useful for identifying areas of needless repetition (see [Dryness](#dryness)). 761 | 762 | [⇧ top](#css-guide) 763 | 764 | -------------------------------------------------------------------------------- /design/deliverables/README.md: -------------------------------------------------------------------------------- 1 | # Design Deliverables 2 | 3 | Our process retires or streamlines many traditional design steps to promote transparency between internal and external teams while also decreasing the distance between what we design and what the user actually experiences. 4 | 5 | The exact deliverables differ per project, but may include some or all of the following… 6 | 7 | - TODO: Prioritization Exercises 8 | - TODO: Personas 9 | - [Mood Boards](#mood-boards) 10 | - [Element Collages](#element-collages) 11 | - TODO: Collaborative Sketches 12 | - TODO: Wireframes 13 | - TODO: Prototypes 14 | 15 | ## Mood Boards 16 | 17 | A collage of images, textures, typography, colors or other materials, intended to evoke or visually summarize a particular style or concept. 18 | 19 | ![](./images/moodboard-cloudfour.png) 20 | 21 | Mood boards work best as part of the discovery phase of a project when brand characteristics are unknown, in flux or poorly applied to the web. They help internal and external teams get on the same page, establishing a shared frame of reference before we get in the weeds of more time-consuming, wholly original design tasks. 22 | 23 | - **After:** Prioritization exercises, personas 24 | - **Before:** Element collages 25 | - **Timeframe:** 1–3 days per revision 26 | - **Revisions:** Typically 1–3 27 | - **Collaborators:** 1–2 designers + anyone who'd like to contribute! 28 | 29 | ### Tips 30 | 31 | - Include materials you _know_ to be relevant as a starting point. This can include text notes summarizing priorities or characteristics, existing brand materials, or photographs of a physical location. 32 | - Share mood boards while they're still in progress. This promotes understanding of the board's malleable nature and the process for creating it. 33 | - Whenever possible, invite the client to collaborate on the mood board, either directly or by contributing comments/feedback. 34 | - Aside from color/gradient swatches, cropping or lighting adjustments to photographic imagery, avoid creating original work for mood boards. This takes more time, removes discussion from the design process and encourages feedback on specific design decisions over the board's _overall_ appropriateness. 35 | - Avoid presenting competing mood boards. While it's fine for a mood board to have complimentary sections to gauge interest in differing perspectives ("cool + modern," "bright + friendly"), simplifying a mood board review to "A versus B" can discourage discussion of the elements therein. 36 | 37 | ### Tools 38 | 39 | Mood boards are traditionally assembled in-person by cutting out pieces of magazines or other printed materials, then collaging them on matte board or some other surface. At Cloud Four we tend to use digital tools instead. This helps us collaborate more seamlessly with remote teams while also referencing more relevant digital imagery. 40 | 41 | - [InVision Boards](https://www.invisionapp.com/blog/boards-share-design-inspiration-assets/) 42 | - [Niice](https://niice.co/) 43 | 44 | ### Further Reading 45 | 46 | - [Cloud Four: Mood Boards (Neither Bored Nor Moody)](https://cloudfour.com/thinks/mood-boards/) 47 | 48 | ## Element Collages 49 | 50 | A collage of original but disparate design elements meant to demonstrate ideas without committing to a particular layout. As originator [Dan Mall](http://v3.danielmall.com/articles/rif-element-collages/) put it: 51 | 52 | > A full comp often requires ideas to be fully realized. An element collage allows me to document a thought at any state of realization and move on to the next. 53 | 54 | ![](./images/elementcollage-cloudfour.jpg) 55 | 56 | At the beginning of a project, element collages bridge the gap between explorational exercises like mood boards and more fleshed-out deliverables like in-browser mockups and prototypes. They're an ideal deliverable for figuring out foundational colors, typography, line weights and other design elements that can carry into the foundational CSS for in-browser mockups. 57 | 58 | Throughout a project, they may be used more informally to explore ideas and inform prototypes. 59 | 60 | - **After:** Mood boards 61 | - **Before:** Prototypes 62 | - **Timeframe:** 1–3 days per revision 63 | - **Revisions:** Typically 2–4 64 | - **Collaborators:** Ideally 2 or more designers work in parallel to create complimentary collages, eventually unifying their approach prior to prototyping. While prototyping, they can be created as simple one-off explorations (as needed). 65 | 66 | ### Tips 67 | 68 | - Don't try to design every possible pattern in your collage. Instead, focus on elements you have an instinct to explore that could inform future patterns. 69 | - Avoid composing elements of your collage in a manner that suggests a complete "page," which will disrupt the viewer's ability to critique the elements therein. If you find yourself unable to prevent this, it may be time to split your collage into separate images or artboards. 70 | - If you have an idea for animation or interaction, don't be afraid to use [blur](http://v3.danielmall.com/articles/rif-element-collages/rif-element-collage-sample.png), [gesture overlays](https://www.lukew.com/ff/entry.asp?1071) or other visual techniques to communicate that intent in an efficient way. 71 | - If working in parallel, freely steal borrow from your collaborators. Let every team member's work inform and strengthen the overall vision. Share your source files, messy layers and all. 72 | - If multiple designers end up pursuing very similar design directions, branch off by applying that direction to different elements. 73 | 74 | ### Tools 75 | 76 | We love designing in-browser, but it's usually a better idea to do looser explorations in a more free-form tool. Not having to worry about markup, box models or even responsive design considerations at this stage helps maintain a sense of play and inventiveness in our work. This helps us avoid designing [the same interface over and over](http://www.novolume.co.uk/blog/all-websites-look-the-same/). 77 | 78 | - [Sketch](https://www.sketchapp.com/) 79 | - [Adobe XD](http://www.adobe.com/products/experience-design.html) 80 | - [Adobe Photoshop](http://www.adobe.com/products/photoshop.html) 81 | - [Figma](https://www.figma.com/) 82 | 83 | ### Further Reading 84 | 85 | - [Dan Mall: Element Collages](http://v3.danielmall.com/articles/rif-element-collages/) 86 | - [Cloud Four: Element Collages… are FUN!](https://cloudfour.com/thinks/element-collages-are-fun/) 87 | -------------------------------------------------------------------------------- /design/deliverables/images/elementcollage-cloudfour.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfour/guides/6ed34d0b282c3483e013aee776782c6ae064c8f8/design/deliverables/images/elementcollage-cloudfour.jpg -------------------------------------------------------------------------------- /design/deliverables/images/moodboard-cloudfour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloudfour/guides/6ed34d0b282c3483e013aee776782c6ae064c8f8/design/deliverables/images/moodboard-cloudfour.png -------------------------------------------------------------------------------- /git/README.md: -------------------------------------------------------------------------------- 1 | [pull request]: https://help.github.com/articles/using-pull-requests 2 | [pull request template]: https://help.github.com/articles/creating-a-pull-request-template-for-your-repository/ 3 | [name your feature branches by convention]: https://docs.microsoft.com/en-us/vsts/git/concepts/git-branching-guidance?view=vsts#name-your-feature-branches-by-convention 4 | 5 | Git Protocol 6 | ============ 7 | 8 | A guide for programming within version control. 9 | 10 | ## Table of Contents 11 | 12 | - [General Guidelines](#general-guidelines) 13 | - [Writing a Feature](#writing-a-feature) 14 | - [Reviewing Code](#reviewing-code) 15 | - [Merging in General](#merging-in-general) 16 | - [Pull Request Template](#pull-request-template) 17 | - [Write Useful Commit Messages](#write-useful-commit-messages) 18 | 19 | 20 | General Guidelines 21 | ------------------ 22 | 23 | * Avoid including files that are specific to your own environment. 24 | * Avoid committing directly to `main`. 25 | * Perform all work in a feature branch. 26 | * Rebase frequently to incorporate upstream changes. 27 | * Use a [pull request] for code reviews. 28 | * Delete your local and remote branches after merging. 29 | 30 | Writing a Feature 31 | ----------------- 32 | 33 | ### Create a local feature branch based off main 34 | 35 | ``` 36 | git checkout main 37 | git pull 38 | git checkout -b 39 | ``` 40 | 41 | Prefix the branch name with something meaningful, for example: 42 | 43 | - `users/username/description` 44 | - `users/username/workitem` 45 | - `feature/feature-name` 46 | - `feature/feature-area/feature-name` 47 | - `bugfix/description` 48 | - `hotfix/description` 49 | - `cleanup/description` 50 | - `chore/description` 51 | 52 | When you [name your feature branches by convention] using slashes, 53 | it provides a much nicer organization when viewing as directories 54 | as well as within any Git GUI apps. 55 | 56 | ### Rebase frequently to incorporate upstream changes 57 | 58 | ``` 59 | git fetch origin 60 | git rebase origin/main 61 | ``` 62 | 63 | Resolve conflicts. When feature is in a good state, stage the changes 64 | 65 | ``` 66 | git add --all 67 | ``` 68 | 69 | ### Commit your changes 70 | 71 | ``` 72 | git status 73 | git commit --verbose 74 | ``` 75 | 76 | Be sure to [write a good commit message](#write-useful-commit-messages). 77 | 78 | If you've created more than one commit, use a rebase to squash them into 79 | cohesive commits with good messages: 80 | 81 | ``` 82 | git rebase -i origin/main 83 | ``` 84 | 85 | ### Push your branch 86 | 87 | ``` 88 | git push origin 89 | ``` 90 | 91 | Submit a [pull request]. Ask for a code review. 92 | 93 | Reviewing Code 94 | -------------- 95 | 96 | ### Fellow team members review the pull request 97 | 98 | Your team members will follow code review guidelines to avoid miscommunication. 99 | They make comments and ask questions directly on lines of code. 100 | When satisfied, they'll approve your pull request and leave a comment: 101 | 102 | > This is some excellent work, Ross. :thumbsup: 103 | 104 | Merging in General 105 | ------------------ 106 | 107 | Once your PR has been approved, you are responsible for merging it. 108 | 109 | ### Rebasing 110 | 111 | To avoid a messy history, please rebase and squash low-value commits 112 | like "Fix whitespace" into one or a small number of valuable commit(s). 113 | Edit commit messages to reveal intent. Run tests. 114 | 115 | ``` 116 | git fetch origin 117 | git rebase -i origin/main 118 | ``` 119 | 120 | ### Force-Pushing 121 | 122 | This allows GitHub to automatically close your pull 123 | request and mark it as merged when your commit(s) are pushed to `main`. It also 124 | makes it possible to find the pull request that brought in your changes. 125 | 126 | ``` 127 | git push --force origin 128 | ``` 129 | 130 | ### The Big Green Button Method 131 | 132 | Force-pushing may not always be appropriate for every project, depending on 133 | other factors like hooks or continuous integration. Pull Requests may also be 134 | merged into `main` (or whatever their target branch is) by simply 135 | clicking the green "Merge Branch" button on the GitHub Pull Request page. 136 | 137 | Note that GitHub offers three merge options: a merge commit, rebase and merge, 138 | and squash and merge. All are good for different situations. For example, 139 | merge commits are good for merging feature branches with many developers or 140 | that other feature branches depend on. 141 | 142 | For short-lived, single-developer feature branches, we favor squashing to 143 | preserve a clean and easy-to-follow history. 144 | 145 | - [How and Why to Squash Merge your Pull Request](https://cloudfour.com/thinks/squashing-your-pull-requests/) 146 | 147 | ### Once merged, delete your branch 148 | 149 | Delete the remote branch. 150 | 151 | ``` 152 | git push origin --delete 153 | ``` 154 | 155 | Delete your local feature branch. 156 | 157 | ``` 158 | git branch --delete 159 | ``` 160 | 161 | ## Pull Request Template 162 | 163 | Please add a [Pull Request Template] to your repo, 164 | to ensure that all pull requests follow our guide: 165 | 166 | See our [Standard Pull Request Template](./pull_request_template.md) in this directory. 167 | 168 | ## Write Useful Commit Messages 169 | 170 | Please ensure that you follow commit message best practices: 171 | 172 | 1. Separate subject from body with a blank line 173 | 1. Limit the subject line to 50 characters 174 | 1. Capitalize the first word of the subject line 175 | 1. Do not end the subject line with a period 176 | 1. Use the imperative mood in the subject line 177 | (e.g. "Fix the bug" not "Fixed the bug") 178 | 1. Wrap the body at 72 characters 179 | 1. Use the body to explain what and why vs. how 180 | 181 | For example: 182 | 183 | ``` 184 | Present-tense summary under 50 characters 185 | 186 | * More information about commit (under 72 characters). 187 | * More information about commit (under 72 characters). 188 | 189 | http://project.management-system.com/ticket/123 190 | ``` 191 | 192 | ### Commit Message Best Practices 193 | - [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) 194 | - [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/) 195 | - [Commit Messages Guide](https://github.com/RomuloOliveira/commit-messages-guide) 196 | 197 | ### Commit Message Template 198 | 199 | See our [Standard Commit Message Template](./commit_template.txt) in this directory. 200 | 201 | To use the template, save it to your local machines and add it to your `.gitconfig`: 202 | 203 | ``` 204 | git config --global commit.template <.git-commit-template.txt file path> 205 | ``` 206 | 207 | For example, if you saved it to your home folder, try: 208 | 209 | ``` 210 | git config --global commit.template ~/.git-commit-template.txt 211 | ``` 212 | -------------------------------------------------------------------------------- /git/commit_template.txt: -------------------------------------------------------------------------------- 1 | # : Short subject line 2 | # |<---- Using a Maximum Of 50 Characters ---->| 3 | 4 | 5 | # Explain why this change is being made 6 | # |<---- Try To Limit Each Line to a Maximum Of 72 Characters ---->| 7 | 8 | # Provide links or keys to any relevant tickets, articles or other resources 9 | # e.g.: Fixes #23 10 | 11 | # --- COMMIT END --- 12 | # Type can be 13 | # feat (new feature) 14 | # fix (bug fix) 15 | # refactor (refactoring production code) 16 | # style (formatting, missing semi colons, etc; no code change) 17 | # docs (changes to documentation) 18 | # test (adding or refactoring tests; no production code change) 19 | # chore (updating grunt tasks etc; no production code change) 20 | # -------------------- 21 | # Remember to 22 | # Capitalize the subject line 23 | # Use the imperative mood in the subject line 24 | # Do not end the subject line with a period 25 | # Separate subject from body with a blank line 26 | # Use the body to explain what and why vs. how 27 | # Can use multiple lines with "-" for bullet points in body 28 | # -------------------- 29 | # For more information about this template, check out 30 | # https://gist.github.com/adeekshith/cd4c95a064977cdc6c50 31 | -------------------------------------------------------------------------------- /git/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | Please include a summary of the change and which issue is fixed. 4 | Please also include relevant motivation and context. 5 | List any dependencies that are required for this change. 6 | 7 | ## Screenshots 8 | 9 | Visual changes should include a screenshot. 10 | 11 | ## Testing 12 | 13 | 1. instructions for reviewers 14 | 1. to test your changes 15 | 16 | --- 17 | 18 | - Fixes # (issue) 19 | - or [TrelloCard/Issue/Story](LINK_TO_STORY) 20 | 21 | /CC @person 22 | -------------------------------------------------------------------------------- /javascript/README.md: -------------------------------------------------------------------------------- 1 | 2 | [Airbnb JavaScript Style Guide]: https://github.com/airbnb/javascript 3 | 4 | 5 | [Array Destructuring]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Array_destructuring 6 | [Array Literal Spread Syntax]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_array_literals 7 | [Array.from]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from 8 | [Array.prototype.push]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/push 9 | [Function Arguments Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments 10 | [Function Declaration]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function 11 | [Function Default Parameters]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters 12 | [Function Expression]: https://developer.mozilla.org/en-US/docs/web/JavaScript/Reference/Operators/function 13 | [No eval]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Do_not_ever_use_eval! 14 | [NodeList]: https://developer.mozilla.org/en-US/docs/Web/API/NodeList 15 | [Object.assign]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign 16 | [Object Destructuring]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring 17 | [Object Literal Spread Syntax]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals 18 | [Spread Syntax]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax 19 | [Template Literals]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals 20 | 21 | 22 | [Adding Array Items]: https://jsperf.com/adding-array-items 23 | [Arrays from Array-Like Objects]: https://jsperf.com/array-like-object-to-array 24 | [Array Destructuring vs Not]: https://jsperf.com/array-destructuring 25 | [Arrays From Iterables]: https://jsperf.com/arrays-from-iterables 26 | [Mapping Over Iterables]: https://jsperf.com/array-from-vs-spread-vs-array-from-map 27 | [Object Destructuring vs Not]: https://jsperf.com/destructure-vs-not 28 | [Shallow Copy Objects]: https://jsperf.com/shallow-copy-objects 29 | [Shallow Copy Arrays]: https://jsperf.com/shallow-copy-arrays 30 | [Spread Syntax for Variadic Functions]: https://jsperf.com/spread-syntax-for-variadic-functions 31 | 32 | 33 | [array-callback-return]: https://eslint.org/docs/rules/array-callback-return 34 | [function-paren-newline]: https://eslint.org/docs/rules/function-paren-newline 35 | [no-array-constructor]: https://eslint.org/docs/rules/no-array-constructor.html 36 | [no-const-assign]: https://eslint.org/docs/rules/no-const-assign.html 37 | [no-eval]: https://eslint.org/docs/rules/no-eval 38 | [no-new-func]: https://eslint.org/docs/rules/no-new-func 39 | [no-new-object]: https://eslint.org/docs/rules/no-new-object.html 40 | [no-param-reassign]: https://eslint.org/docs/rules/no-param-reassign.html 41 | [no-prototype-builtins]: https://eslint.org/docs/rules/no-prototype-builtins 42 | [no-var]: https://eslint.org/docs/rules/no-var.html 43 | [object-shorthand]: https://eslint.org/docs/rules/object-shorthand.html 44 | [prefer-const]: https://eslint.org/docs/rules/prefer-const.html 45 | [prefer-destructuring]: https://eslint.org/docs/rules/prefer-destructuring 46 | [prefer-object-spread]: https://eslint.org/docs/rules/prefer-object-spread 47 | [prefer-rest-params]: https://eslint.org/docs/rules/prefer-rest-params 48 | [prefer-spread]: https://eslint.org/docs/rules/prefer-spread 49 | [prefer-template]: https://eslint.org/docs/rules/prefer-template.html 50 | [quotes]: https://eslint.org/docs/rules/quotes.html 51 | [quote-props]: https://eslint.org/docs/rules/quote-props.html 52 | 53 | 54 | [@babel/plugin-transform-destructuring]: https://babeljs.io/docs/en/next/babel-plugin-transform-destructuring.html 55 | 56 | # JavaScript Guide 57 | 58 | *A mostly reasonable approach to JavaScript, inspired by the [Airbnb JavaScript Style Guide].* 59 | 60 | ## A note on performance vs readability 61 | 62 | The end-user experience always come first which means performance should always be top-of-mind. The JSPerf examples used in this guide do not use large datasets. If you find yourself working with large datasets and the suggested approach based on this guide performs slower, don't be afraid to push back on a per-project basis (see [Performance vs Readability](https://blog.usejournal.com/performance-vs-readability-2e9332730790)). 63 | 64 | ## Table of Contents 65 | 66 | 1. [Variables](#variables) 67 | 2. [Objects](#objects) 68 | 3. [Arrays](#arrays) 69 | 4. [Destructring](#destructuring) 70 | 5. [Strings](#strings) 71 | 6. [Functions](#functions) 72 | 73 | --- 74 | 75 | ## Variables 76 | 77 | ### 1.1 Prefer Constants 78 | 79 | Use `const` for all of your references; avoid using `var`. 80 | 81 | > Why? This ensures that you can’t reassign your references, which can lead to bugs and difficult to comprehend code. 82 | 83 | #### Examples 84 | 85 | 🚫 Nope. 🚫 86 | 87 | ```js 88 | var a = 1; 89 | var b = 2; 90 | ``` 91 | 92 | 🎉 Yep! 🎉 93 | 94 | ```js 95 | const a = 1; 96 | const b = 2; 97 | ``` 98 | 99 | #### Resources 100 | 101 | - ESLint: 102 | - [prefer-const] 103 | - [no-const-assign] 104 | 105 | ### 1.2 Reassigning References 106 | 107 | If you must reassign references, use `let` instead of `var`. 108 | 109 | > Why? `let` is block-scoped rather than function-scoped like `var`. Function-scoped variables are hoisted which can lead to bugs if you are not careful. Using block-scoped variables makes our code more predictable by giving the variable an explicit scope. 110 | 111 | #### Examples 112 | 113 | 🚫 Nope. 🚫 114 | 115 | ```js 116 | var count = 1; 117 | if (true) { 118 | count += 1; 119 | } 120 | ``` 121 | 122 | 🎉 Yep! 🎉 123 | 124 | ```js 125 | let count = 1; 126 | if (true) { 127 | count += 1; 128 | } 129 | ``` 130 | 131 | #### Resources 132 | 133 | - ESLint: [no-var] 134 | 135 | ### 1.3 Block Scope 136 | 137 | Note that both `let` and `const` are block-scoped. 138 | 139 | #### Examples 140 | 141 | ```js 142 | // Both `const` and `let` only exist in the blocks they are defined in. 143 | { 144 | let a = 1; 145 | const b = 1; 146 | } 147 | console.log(a); // ReferenceError: a is not defined 148 | console.log(b); // ReferenceError: b is not defined 149 | ``` 150 | 151 | [⇧ top](#javascript-guide) 152 | 153 | --- 154 | 155 | ## Objects 156 | 157 | ### 2.1 Object Creation 158 | 159 | Use the literal syntax for object creation. 160 | 161 | > Why? While there are no performance differences between the two approaches, the byte savings and conciseness of the object literal form is what has made it the de facto way of creating new objects. 162 | 163 | #### Examples 164 | 165 | 🚫 Nope. 🚫 166 | 167 | ```js 168 | const item = new Object(); 169 | ```` 170 | 171 | 🎉 Yep! 🎉 172 | 173 | ```js 174 | const item = {}; 175 | ``` 176 | 177 | #### Resources 178 | 179 | - ESLint: [no-new-object] 180 | 181 | ### 2.2 Object Shorthand Syntax 182 | 183 | Use object shorthand syntax for both methods and property values. 184 | 185 | > Why? ECMAScript 6 provides a concise form for defining object literal methods and properties. This syntax can make defining complex object literals much cleaner. 186 | 187 | #### Object Method 188 | 189 | 🚫 Nope. 🚫 190 | 191 | ```js 192 | const atom = { 193 | value: 1, 194 | addValue: function (value) { 195 | return atom.value + value; 196 | }, 197 | }; 198 | ``` 199 | 200 | 🎉 Yep! 🎉 201 | 202 | ```js 203 | const atom = { 204 | value: 1, 205 | addValue(value) { 206 | return atom.value + value; 207 | }, 208 | }; 209 | ``` 210 | 211 | #### Object Property 212 | 213 | 🚫 Nope. 🚫 214 | 215 | ```js 216 | const generalLeiaOrgana = 'General Leia Organa'; 217 | 218 | const obj = { 219 | generalLeiaOrgana: generalLeiaOrgana, 220 | }; 221 | ``` 222 | 223 | 🎉 Yep! 🎉 224 | 225 | ```js 226 | const generalLeiaOrgana = 'General Leia Organa'; 227 | 228 | const obj = { 229 | generalLeiaOrgana, 230 | }; 231 | ``` 232 | 233 | #### Resources 234 | 235 | - ESLint: [object-shorthand] 236 | 237 | ### 2.3 Object Quoted Properties 238 | 239 | Only quote properties that are invalid identifiers. 240 | 241 | > Why? In general we consider it subjectively easier to read. It improves syntax highlighting, and is also more easily optimized by many JS engines. 242 | 243 | #### Examples 244 | 245 | 🚫 Nope. 🚫 246 | 247 | ```js 248 | const obj = { 249 | 'foo': 3, 250 | 'bar': 4, 251 | 'data-blah': 5, 252 | }; 253 | ``` 254 | 255 | 🎉 Yep! 🎉 256 | 257 | ```js 258 | const obj = { 259 | foo: 3, 260 | bar: 4, 261 | 'data-blah': 5, 262 | }; 263 | ``` 264 | 265 | #### Resources 266 | 267 | - ESLint: [quote-props] 268 | 269 | ### 2.4 Object Prototype Methods 270 | 271 | Do not call `Object.prototype` methods directly, such as `hasOwnProperty`, `propertyIsEnumerable`, and `isPrototypeOf`. 272 | 273 | > Why? In ECMAScript 5.1, `Object.create` was added, which enables the creation of objects with a specified `[[Prototype]]`. `Object.create(null)` is a common pattern used to create objects that will be used as a Map. This can lead to errors when it is assumed that objects will have properties from `Object.prototype`. 274 | 275 | #### Examples 276 | 277 | 🚫 Nope. 🚫 278 | 279 | ```js 280 | console.log(object.hasOwnProperty(key)); 281 | ``` 282 | 283 | 🎉 Yep! 🎉 284 | 285 | ```js 286 | // Good 287 | console.log(Object.prototype.hasOwnProperty.call(object, key)); 288 | 289 | // Best 290 | const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope. 291 | console.log(has.call(object, key)); 292 | ``` 293 | 294 | #### Resources 295 | 296 | - ESLint: [no-prototype-builtins] 297 | 298 | ### 2.5 Object Shallow-Copy 299 | 300 | Prefer the [object spread][Object Literal Spread Syntax] operator over [`Object.assign`][Object.assign] to shallow-copy objects. Use the object rest operator to get a new object with certain properties omitted. 301 | 302 | > Why? Object spread is a declarative alternative which may perform better than the more dynamic, imperative Object.assign. 303 | 304 | #### Examples 305 | 306 | 🚫 Nope. 🚫 307 | 308 | ```js 309 | // This mutates `original` ಠ_ಠ 310 | const original = { a: 1, b: 2 }; 311 | const copy = Object.assign(original, { c: 3 }); 312 | delete copy.a; // So does this! 313 | 314 | // Works but not preferred 315 | const original = { a: 1, b: 2 }; 316 | const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 } 317 | ``` 318 | 319 | 🎉 Yep! 🎉 320 | 321 | ```js 322 | const original = { a: 1, b: 2 }; 323 | const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 } 324 | 325 | const { a, ...noA } = copy; // noA => { b: 2, c: 3 } 326 | ``` 327 | 328 | #### Resources 329 | 330 | - ESLint: [prefer-object-spread] 331 | - JSPerf: [Shallow Copy Objects] 332 | 333 | [⇧ top](#javascript-guide) 334 | 335 | --- 336 | 337 | ## Arrays 338 | 339 | ### 3.1 Array Creation 340 | 341 | Use the literal syntax for array creation. 342 | 343 | > Why? Use of the `Array` constructor to construct a new array is generally discouraged in favor of array literal notation because of the single-argument pitfall and because the `Array` global may be redefined. 344 | 345 | #### Examples 346 | 347 | 🚫 Nope. 🚫 348 | 349 | ```js 350 | const items = new Array(); 351 | ``` 352 | 353 | 🎉 Yep! 🎉 354 | 355 | ```js 356 | const items = []; 357 | ``` 358 | 359 | #### Resources 360 | 361 | - ESLint: [no-array-constructor] 362 | 363 | 364 | ### 3.2 Adding Items To Arrays 365 | 366 | Use [Array.prototype.push()][Array.prototype.push] instead of direct assignment to add items to an array. 367 | 368 | #### Examples 369 | 370 | 🚫 Nope. 🚫 371 | 372 | ```js 373 | const someStack = []; 374 | someStack[someStack.length] = 'abracadabra'; 375 | ``` 376 | 377 | 🎉 Yep! 🎉 378 | 379 | ```js 380 | const someStack = []; 381 | someStack.push('abracadabra'); 382 | ``` 383 | 384 | #### Resources 385 | 386 | - JSPerf: [Adding Array Items] 387 | 388 | ### 3.3 Array Shallow-Copy 389 | 390 | Use [array spread syntax][Array Literal Spread Syntax] `...` to shallow-copy arrays. 391 | 392 | > Why? Better overall performance. 393 | 394 | #### Examples 395 | 396 | 🚫 Nope. 🚫 397 | 398 | ```js 399 | // Too slow 400 | const animals = ['ant', 'bison', 'camel', 'duck', 'elephant']; 401 | const len = animals.length; 402 | const animalsCopy = []; 403 | let i; 404 | 405 | for (i = 0; i < len; i ++) { 406 | animalsCopy[i] = animals[i]; 407 | } 408 | 409 | // Works but is not preferred 410 | const animals = ['ant', 'bison', 'camel', 'duck', 'elephant']; 411 | const animalsCopy = animals.slice(); 412 | ``` 413 | 414 | 🎉 Yep! 🎉 415 | 416 | ```js 417 | const animals = ['ant', 'bison', 'camel', 'duck', 'elephant']; 418 | const animalsCopy = [...animals]; 419 | ``` 420 | 421 | #### Resources: 422 | 423 | - JSPerf: [Shallow Copy Arrays] 424 | 425 | ### 3.4 Arrays From Iterables 426 | 427 | To convert an iterable object (e.g. [NodeList]) to an array, use [array spread syntax][Array Literal Spread Syntax] `...` instead of [Array.from]. 428 | 429 | > Why? Better performance. 430 | 431 | #### Examples 432 | 433 | 🚫 Nope. 🚫 434 | 435 | ```js 436 | const paragraphs = document.querySelectorAll('p'); 437 | const nodes = Array.from(paragraphs); 438 | ``` 439 | 440 | 🎉 Yep! 🎉 441 | 442 | ```js 443 | const paragraphs = document.querySelectorAll('p'); 444 | const nodes = [...paragraphs]; 445 | ``` 446 | #### Note 447 | 448 | If using Babel with `@babel/preset-env` with option `loose:true`, and are transpiling to older targets in a `.browserlistrc`, you may need to add the following to your Babel config (e.g., `babel.config.js`): 449 | 450 | ```js 451 | plugins: [ 452 | ..., 453 | '@babel/plugin-transform-spread', 454 | ... 455 | ] 456 | ``` 457 | 458 | (The default option for this plugin is `loose:false`, which will override the global setting) 459 | 460 | #### Resources 461 | 462 | - ESLint: [prefer-spread] 463 | - JSPerf: [Arrays From Iterables] 464 | 465 | ### 3.5 Arrays from Array-Like Objects 466 | 467 | Use [`Array.from`][Array.from] for converting an array-like object to an array. 468 | 469 | > Why? Not only is it easier to read/type but it also performs better. 470 | 471 | #### Examples 472 | 473 | 🚫 Nope. 🚫 474 | 475 | ```js 476 | const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }; 477 | const arr = Array.prototype.slice.call(arrLike); 478 | ``` 479 | 480 | 🎉 Yep! 🎉 481 | 482 | ```js 483 | const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }; 484 | const arr = Array.from(arrLike); 485 | ``` 486 | 487 | #### Resources 488 | 489 | - JSPerf: [Arrays from Array-Like Objects] 490 | 491 | ### 3.6 Mapping Over Iterables 492 | 493 | Use [array spread syntax][Array Literal Spread Syntax] `...` instead of [`Array.from`][Array.from] for mapping over iterables. 494 | 495 | > Why? Overall better performance. 496 | 497 | #### Examples 498 | 499 | 🚫 Nope. 🚫 500 | 501 | ```js 502 | const iterable = 'Hello there!'; 503 | const upperCase = letter => letter.toUpperCase(); 504 | const upperCaseLetters = Array.from(iterable, upperCase); 505 | ``` 506 | 507 | 🎉 Yep! 🎉 508 | 509 | ```js 510 | const iterable = 'Hello there!'; 511 | const upperCase = letter => letter.toUpperCase(); 512 | const upperCaseLetters = [...iterable].map(upperCase); 513 | ``` 514 | 515 | #### Resources 516 | 517 | - JSPerf: [Mapping Over Iterables] 518 | 519 | ### 3.7 Array Callback Return 520 | 521 | Use `return` statements in array method callbacks. It’s okay to omit the `return` if the function body consists of a single statement returning an expression without side effects. 522 | 523 | 524 | #### Examples 525 | 526 | 🚫 Nope. 🚫 527 | 528 | ```js 529 | inbox.filter(msg => { 530 | const { subject, author } = msg; 531 | if (subject === 'Mockingbird') { 532 | return author === 'Harper Lee'; 533 | } else { 534 | return false; 535 | } 536 | }); 537 | ``` 538 | 539 | 🎉 Yep! 🎉 540 | 541 | ```js 542 | inbox.filter(msg => { 543 | const { subject, author } = msg; 544 | if (subject === 'Mockingbird') { 545 | return author === 'Harper Lee'; 546 | } 547 | 548 | return false; 549 | }); 550 | ``` 551 | 552 | 🎉 Also good! 🎉 553 | 554 | ```js 555 | [1, 2, 3].map((x) => { 556 | const y = x + 1; 557 | return x * y; 558 | }); 559 | 560 | // The return can be omitted here. 561 | [1, 2, 3].map(x => x + 1); 562 | ``` 563 | 564 | #### Resources 565 | 566 | - ESLint: [array-callback-return] 567 | 568 | [⇧ top](#javascript-guide) 569 | 570 | --- 571 | 572 | ## Destructuring 573 | 574 | ### 4.1 Object Destructuring 575 | 576 | Use [object destructuring][Object Destructuring] when accessing and using multiple properties of an object. 577 | 578 | > Why? Destructuring saves you from creating temporary references for those properties. 579 | 580 | #### Examples 581 | 582 | 🚫 Nope. 🚫 583 | 584 | ```js 585 | function getFullName(user) { 586 | const firstName = user.firstName; 587 | const lastName = user.lastName; 588 | 589 | return `${firstName} ${lastName}`; 590 | } 591 | ``` 592 | 593 | 🎉 Yep! 🎉 594 | 595 | ```js 596 | // Good 597 | function getFullName(user) { 598 | const { firstName, lastName } = user; 599 | return `${firstName} ${lastName}`; 600 | } 601 | 602 | // Best 603 | function getFullName({ firstName, lastName }) { 604 | return `${firstName} ${lastName}`; 605 | } 606 | ``` 607 | 608 | #### Resources 609 | 610 | - ESLint: [prefer-destructuring] 611 | - JSPerf: [Object Destructuring vs Not] 612 | - MDN Web Docs: [Object Destructuring] 613 | 614 | ### 4.2 Array Destructuring 615 | 616 | How you destructure an array depends on your situation. Below are a couple of ways to complete the same task. 617 | 618 | #### Examples 619 | 620 | ```js 621 | // This works! 622 | const arr = [1, 2, 3, 4]; 623 | const first = arr[0]; 624 | const second = arr[1]; 625 | const rest = arr.slice(2); 626 | 627 | console.log(first); // 1 628 | console.log(second); // 2 629 | console.log(rest); // [3, 4] 630 | 631 | // This works great also! 632 | const arr = [1, 2, 3, 4]; 633 | const [first, second, ...rest] = arr; 634 | 635 | console.log(first); // 1 636 | console.log(second); // 2 637 | console.log(rest); // [3, 4] 638 | ``` 639 | 640 | _**Note:** For performance reasons, strongly consider use of the [@babel/plugin-transform-destructuring] plugin when using [array destructuring][Array Destructuring]._ 641 | 642 | #### Resources 643 | 644 | - Babel Plugin: [@babel/plugin-transform-destructuring] 645 | - JSPerf: [Array Destructuring vs Not] 646 | - MDN Web Docs: [Array Destructuring] 647 | 648 | ### 4.3 Destructuring for Multiple Return Values 649 | 650 | Use [object destructuring][Object Destructuring] for multiple return values, not [array destructuring][Array Destructuring]. 651 | 652 | > Why? You can add new properties over time or change the order of things without breaking call sites. 653 | 654 | #### Examples 655 | 656 | 🚫 Nope. 🚫 657 | 658 | ```js 659 | function processInput(input) { 660 | return [left, right, top, bottom]; 661 | } 662 | 663 | // the caller needs to think about the order of return data 664 | const [left, __, top] = processInput(input); 665 | ``` 666 | 667 | 🎉 Yep! 🎉 668 | 669 | ```js 670 | function processInput(input) { 671 | return { left, right, top, bottom }; 672 | } 673 | 674 | // the caller selects only the data they need 675 | const { left, top } = processInput(input); 676 | ``` 677 | 678 | [⇧ top](#javascript-guide) 679 | 680 | --- 681 | 682 | ## Strings 683 | 684 | ### 5.1 Quotes 685 | 686 | Use single quotes `''` for strings. The exception is if a string includes a literal `'` single quote, use double quotes `"` instead. 687 | 688 | #### Examples 689 | 690 | 🚫 Nope. 🚫 691 | 692 | ```js 693 | // Should be single quote. 694 | const name = "Cloud Four"; 695 | 696 | // Template literals should contain interpolation or newlines. 697 | const name = `Cloud Four`; 698 | 699 | // This string has a literal single quote! 700 | const foo = 'What\'s for dinner?'; 701 | ``` 702 | 703 | 🎉 Yep! 🎉 704 | 705 | ```js 706 | const name = 'Cloud Four'; 707 | 708 | // It's okay to use double quotes here. 709 | const foo = "What's for dinner?"; 710 | ``` 711 | 712 | #### Resources 713 | 714 | - ESLint: [quotes] 715 | 716 | ### 5.2 Template Literals 717 | 718 | When programmatically building up strings, use [template literals][Template Literals] instead of concatenation. 719 | 720 | > Why? Template literals (template strings) give you a readable, concise syntax with proper newlines and string interpolation features. 721 | 722 | #### Examples 723 | 724 | 🚫 Nope. 🚫 725 | 726 | ```js 727 | function sayHi(name) { 728 | return 'How are you, ' + name + '?'; 729 | } 730 | 731 | function sayHi(name) { 732 | return ['How are you, ', name, '?'].join(); 733 | } 734 | ``` 735 | 736 | 🎉 Yep! 🎉 737 | 738 | ```js 739 | function sayHi(name) { 740 | return `How are you, ${name}?`; 741 | } 742 | ``` 743 | 744 | #### Resources 745 | 746 | - ESLint: [prefer-template] 747 | 748 | ### 5.3 Eval 749 | 750 | [Never use `eval()`][No eval] on a string, it opens too many vulnerabilities. 751 | 752 | #### Resources 753 | 754 | - ESLint: [no-eval] 755 | 756 | [⇧ top](#javascript-guide) 757 | 758 | --- 759 | 760 | ## Functions 761 | 762 | ### 6.1 Avoid Function Hoisting 763 | 764 | Although it is possible to call functions before they are defined via [hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting) we prefer to avoid this pattern in our code as it can be confusing. 765 | 766 | #### Examples 767 | 768 | Although this code works properly it may be more confusing and we generally avoid it: 769 | 770 | ```js 771 | logFoo(); 772 | 773 | function logFoo() { 774 | console.log("foo"); 775 | } 776 | ``` 777 | 778 | We would prefer one of the following patterns: 779 | 780 | ```js 781 | // Define the function before calling 782 | function logFoo() { 783 | console.log("foo"); 784 | } 785 | 786 | logFoo(); 787 | ``` 788 | 789 | ```js 790 | // Import the function 791 | import {logFoo} from './log-foo.js'; 792 | 793 | logFoo(); 794 | ``` 795 | 796 | In files that call a number of helper functions it can be helpful to move those functions to modules, or start the file with a main function that provides a summary of the steps taken in the file. For example: 797 | 798 | ```js 799 | // The `main` function contains an overview of the file's logic. 800 | // (`main` could be switched to a more meaningful name in context.) 801 | function main() { 802 | thing1(); 803 | thing2(); 804 | thing3(); 805 | thing4(); 806 | } 807 | 808 | function thing1() {} 809 | function thing2() {} 810 | function thing3() {} 811 | function thing4() {} 812 | 813 | main(); 814 | ``` 815 | 816 | Another option is to move helper functions to modules: 817 | 818 | ```js 819 | // Import helpers so they're defined up front 820 | import {thing1, thing2, thing3, thing4} from './helpers.js'; 821 | 822 | thing1(); 823 | thing2(); 824 | thing3(); 825 | thing4(); 826 | ``` 827 | 828 | ### 6.2 Function Arguments Parameter 829 | 830 | Never name a function parameter `arguments`. 831 | 832 | > Why? This will take precedence over the [`arguments` object][Function Arguments Object] that is given to every function scope. 833 | 834 | #### Examples 835 | 836 | 🚫 Nope. 🚫 837 | 838 | ```js 839 | function foo(name, options, arguments) { 840 | // ... 841 | } 842 | ``` 843 | 844 | 🎉 Yep! 🎉 845 | 846 | ```js 847 | function foo(name, options, args) { 848 | // ... 849 | } 850 | ``` 851 | 852 | #### Resources 853 | 854 | - MDN: [Function Arguments Object] 855 | 856 | ### 6.3 Use Rest Syntax for Function Arguments Object 857 | 858 | Use the rest syntax `...args` instead of the `arguments` object. 859 | 860 | > Why? Rest arguments are a real Array, and not merely Array-like as the `arguments` object is. 861 | 862 | #### Examples 863 | 864 | 🚫 Nope. 🚫 865 | 866 | ```js 867 | function concatenateAll() { 868 | const args = Array.prototype.slice.call(arguments); 869 | return args.join(''); 870 | } 871 | 872 | // Slow performance 873 | function concatenateAll() { 874 | const args = Array.from(arguments); 875 | return args.join(''); 876 | } 877 | ``` 878 | 879 | 🎉 Yep! 🎉 880 | 881 | ```js 882 | function concatenateAll(...args) { 883 | return args.join(''); 884 | } 885 | ``` 886 | 887 | #### Resources 888 | 889 | - ESLint: [prefer-rest-params] 890 | 891 | ### 6.4 Function Default Parameters 892 | 893 | Use [function default parameter syntax][Function Default Parameters] rather than mutating function arguments. 894 | 895 | #### Examples 896 | 897 | 🚫 Nope. 🚫 898 | 899 | ```js 900 | function doThings(opts) { 901 | // If opts is falsey it can introduce bugs. 902 | opts = opts || {}; 903 | // ... 904 | } 905 | 906 | function doThings(opts) { 907 | if (opts === undefined) { 908 | opts = {}; 909 | } 910 | // ... 911 | } 912 | ``` 913 | 914 | 🎉 Yep! 🎉 915 | 916 | ```js 917 | function doThings(opts = {}) { 918 | // ... 919 | } 920 | ``` 921 | 922 | #### Resources 923 | 924 | - MDN: [Function Default Parameters] 925 | 926 | ### 6.5 Function Default Parameter Side Effects 927 | 928 | Avoid side effects with [function default parameters][Function Default Parameters]. 929 | 930 | > Why? They are confusing to reason about. 931 | 932 | #### Examples 933 | 934 | 🚫 Nope. 🚫 935 | 936 | ```js 937 | let b = 1; 938 | 939 | // Eek! 940 | function count(a = b++) { 941 | console.log(a); 942 | } 943 | 944 | count(); // 1 945 | count(); // 2 946 | count(3); // 3 947 | count(); // 3 948 | ``` 949 | 950 | ### 6.6 Function Constructor 951 | 952 | Never use the `Function` constructor to create a new function. 953 | 954 | > Why? Creating a function in this way evaluates a string similarly to `eval()`, which [opens vulnerabilities](#53-eval). 955 | 956 | #### Examples 957 | 958 | 🚫 Nope. 🚫 959 | 960 | ```js 961 | var add = new Function('a', 'b', 'return a + b'); 962 | 963 | var subtract = Function('a', 'b', 'return a - b'); 964 | ``` 965 | 966 | 🎉 Yep! 🎉 967 | 968 | ```js 969 | var x = function (a, b) { 970 | return a + b; 971 | }; 972 | ``` 973 | 974 | #### Resources 975 | 976 | - ESLint: [no-new-func] 977 | 978 | ### 6.7 Mutating Function Parameters 979 | 980 | Never mutate function parameters. 981 | 982 | > Why? Manipulating objects passed in as parameters can cause unwanted variable side effects in the original caller. 983 | 984 | #### Examples 985 | 986 | 🚫 Nope. 🚫 987 | 988 | ```js 989 | function foo(bar) { 990 | bar = 13; 991 | } 992 | 993 | function foo(bar) { 994 | bar++; 995 | } 996 | ``` 997 | 998 | 🎉 Yep! 🎉 999 | 1000 | ```js 1001 | function foo(bar) { 1002 | var baz = bar; 1003 | } 1004 | ``` 1005 | 1006 | #### Resources 1007 | 1008 | - ESLint: [no-param-reassign] 1009 | 1010 | 1011 | ### 6.8 Spread Syntax for Variadic Functions 1012 | 1013 | Prefer the use of the [spread syntax operator `...`][Spread Syntax] to call variadic functions (a function that accepts a variable number of arguments). 1014 | 1015 | > Why? It’s cleaner, you don’t need to supply a context, and it's easier to compose `new` when compared to using `apply`. 1016 | 1017 | #### Examples 1018 | 1019 | 🚫 Nope. 🚫 1020 | 1021 | ```js 1022 | const args = [1, 2, 3, 4]; 1023 | Math.max.apply(Math, args); 1024 | 1025 | new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5])); 1026 | ``` 1027 | 1028 | 🎉 Yep! 🎉 1029 | 1030 | ```js 1031 | const args = [1, 2, 3, 4]; 1032 | Math.max(...args); 1033 | 1034 | new Date(...[2016, 8, 5]); 1035 | ``` 1036 | 1037 | #### Resources 1038 | 1039 | - ESLint: [prefer-spread] 1040 | - JSPerf: [Spread Syntax for Variadic Functions] 1041 | 1042 | [⇧ top](#javascript-guide) 1043 | 1044 | --- 1045 | 1046 | ## Arrow Functions 1047 | 1048 | TBD... 1049 | 1050 | [⇧ top](#javascript-guide) 1051 | 1052 | --- 1053 | 1054 | ## Classes & Constructors 1055 | 1056 | TBD... 1057 | 1058 | [⇧ top](#javascript-guide) 1059 | 1060 | --- 1061 | 1062 | ## Modules 1063 | 1064 | TBD... 1065 | 1066 | [⇧ top](#javascript-guide) 1067 | 1068 | --- 1069 | 1070 | ## Iterators and Generators 1071 | 1072 | TBD... 1073 | 1074 | [⇧ top](#javascript-guide) 1075 | 1076 | --- 1077 | 1078 | ## Properties 1079 | 1080 | TBD... 1081 | 1082 | [⇧ top](#javascript-guide) 1083 | 1084 | --- 1085 | 1086 | ## Variables 1087 | 1088 | TBD... 1089 | 1090 | [⇧ top](#javascript-guide) 1091 | 1092 | --- 1093 | 1094 | ## Hoisting 1095 | 1096 | TBD... 1097 | 1098 | [⇧ top](#javascript-guide) 1099 | 1100 | --- 1101 | 1102 | ## Comparison Operators & Equality 1103 | 1104 | TBD... 1105 | 1106 | [⇧ top](#javascript-guide) 1107 | 1108 | --- 1109 | 1110 | ## Blocks 1111 | 1112 | TBD... 1113 | 1114 | [⇧ top](#javascript-guide) 1115 | 1116 | --- 1117 | 1118 | ## Control Statements 1119 | 1120 | TBD... 1121 | 1122 | [⇧ top](#javascript-guide) 1123 | 1124 | --- 1125 | 1126 | ## Comments 1127 | 1128 | TBD... 1129 | 1130 | [⇧ top](#javascript-guide) 1131 | 1132 | --- 1133 | 1134 | ## Whitespace 1135 | 1136 | TBD... 1137 | 1138 | [⇧ top](#javascript-guide) 1139 | 1140 | --- 1141 | 1142 | ## Commas 1143 | 1144 | TBD... 1145 | 1146 | [⇧ top](#javascript-guide) 1147 | 1148 | --- 1149 | 1150 | ## Semicolons 1151 | 1152 | TBD... 1153 | 1154 | [⇧ top](#javascript-guide) 1155 | 1156 | --- 1157 | 1158 | ## Type Casting & Coercion 1159 | 1160 | TBD... 1161 | 1162 | [⇧ top](#javascript-guide) 1163 | 1164 | --- 1165 | 1166 | ## Naming Conventions 1167 | 1168 | TBD... 1169 | 1170 | [⇧ top](#javascript-guide) 1171 | 1172 | --- 1173 | 1174 | ## Accessors 1175 | 1176 | TBD... 1177 | 1178 | [⇧ top](#javascript-guide) 1179 | 1180 | --- 1181 | 1182 | ## Events 1183 | 1184 | TBD... 1185 | 1186 | [⇧ top](#javascript-guide) 1187 | 1188 | --- 1189 | 1190 | ## jQuery 1191 | 1192 | TBD... 1193 | 1194 | [⇧ top](#javascript-guide) 1195 | 1196 | --- 1197 | 1198 | ## ECMAScript 5 Compatibility 1199 | 1200 | TBD... 1201 | 1202 | [⇧ top](#javascript-guide) 1203 | 1204 | --- 1205 | 1206 | ## ECMAScript 6+ (ES 2015+) Styles 1207 | 1208 | TBD... 1209 | 1210 | [⇧ top](#javascript-guide) 1211 | 1212 | --- 1213 | 1214 | ## Standard Library 1215 | 1216 | TBD... 1217 | 1218 | [⇧ top](#javascript-guide) 1219 | 1220 | --- 1221 | 1222 | ## Testing 1223 | 1224 | TBD... 1225 | 1226 | [⇧ top](#javascript-guide) 1227 | 1228 | --- 1229 | 1230 | ## Performance 1231 | 1232 | TBD... 1233 | 1234 | [⇧ top](#javascript-guide) 1235 | 1236 | --- 1237 | 1238 | ## Resources 1239 | 1240 | TBD... 1241 | 1242 | [⇧ top](#javascript-guide) 1243 | 1244 | --- 1245 | 1246 | ## In the Wild 1247 | 1248 | TBD... 1249 | 1250 | [⇧ top](#javascript-guide) 1251 | 1252 | --- 1253 | 1254 | ## Translation 1255 | 1256 | TBD... 1257 | 1258 | [⇧ top](#javascript-guide) 1259 | 1260 | --- 1261 | 1262 | ## The JavaScript Style Guide Guide 1263 | 1264 | TBD... 1265 | 1266 | [⇧ top](#javascript-guide) 1267 | 1268 | --- 1269 | 1270 | ## Contributors 1271 | 1272 | TBD... 1273 | 1274 | [⇧ top](#javascript-guide) 1275 | 1276 | --- 1277 | 1278 | ## License 1279 | 1280 | TBD... 1281 | 1282 | [⇧ top](#javascript-guide) 1283 | -------------------------------------------------------------------------------- /javascript/vue/README.md: -------------------------------------------------------------------------------- 1 | # Vue Guide 2 | 3 | This styleguide is a work-in-progress, documenting how Cloud Four prefers to write Vue. As we continue to expand it, please refer to these guides for additional best practices: 4 | 5 | * [Official Vue Style Guide](https://vuejs.org/v2/style-guide/) 6 | * [Deverus Vue Style Guide](https://gist.github.com/brianboyko/91fdfb492071e743e389d84eee002342) 7 | * [Erik reviews the Deverus Style Guide](https://www.youtube.com/watch?v=38XnZ3EJqYQ) 8 | 9 | ## Destructuring in Templates 10 | 11 | Try to avoid destructuring in HTML templates, to make it obvious where a particular variable is coming from. Since HTML templates have access to props and local variables in `v-for` loops, clarity is favored over brevity in this case. 12 | 13 | ### Avoid This 14 | 15 | Notice that in this example with nested `v-for` loops, destructuring makes it unclear where certain variables are coming from, and some repeated variables like `title` need to be remapped. 16 | 17 | ```vue 18 |
19 |

{{ title }}

20 | 21 |
25 |

{{ subtitle }}

26 | 27 |
28 | {{ question }} 29 |
{{ answer }}
30 |
31 |
32 | 33 |
34 | {{ question }} 35 |
{{ answer }}
36 |
37 |
38 | ``` 39 | 40 | ### Prefer This 41 | 42 | By not destructuring, the nested `v-for` loops are much easier to understand. 43 | 44 | ```vue 45 |
46 |

{{ category.title }}

47 | 48 |
49 |

{{ subcategory.title }}

50 | 51 |
52 | {{ item.question }} 53 |
{{ item.answer }}
54 |
55 |
56 | 57 |
58 | {{ item.question }} 59 |
{{ item.answer }}
60 |
61 |
62 | ``` 63 | 64 | Note that while these examples with nested `v-for` loops are extreme, they highlight a possible problem with destructuring in HTML templates. As a team, we decided to favor consistency, and rather than have a rule like "always destructure except in loops," we've standardized on "avoid destructuring in templates." 65 | -------------------------------------------------------------------------------- /learning/javascript/README.md: -------------------------------------------------------------------------------- 1 | # Learning JavaScript 2 | 3 | *Note*: Right now this is just a catch-all place for some JavaScript learning resources and scribbly notes. I may continue to organize this more formally as we go. The sections will be based roughly on the excellent [_Eloquent JavaScript_](http://eloquentjavascript.net/) by Martijn Haverbeke. 4 | 5 | # JavaScript, Introduction 6 | 7 | Read the [Introduction chapter of _Eloquent JavaScript_](http://eloquentjavascript.net/00_intro.html). 8 | 9 | ## *What is JavaScript?* and Terminology 10 | 11 | ### ECMA 12 | 13 | The chapter makes mention of ECMA and ECMAScript. These are terms you’ll hear a lot. Developers often abbreviate “ECMAScript” to _ES_, as in _ES5_ and _ES6_ (both in written and spoken forms). 14 | 15 | ES6 (ECMAScript 6, also known as “Harmony”) is a big, hot topic right now. We’ll be talking more about that as we go. 16 | 17 | For now, most of what you’ll see is ES5, the flavor of JavaScript supported by [basically every browser](http://kangax.github.io/compat-table/es5/). 18 | 19 | ### Platforms and Engines 20 | 21 | JavaScript is a language, but it needs a place to be executed. There are several leading JavaScript *engines* ("virtual environments that interpret and execute JavaScript", thanks, Wikipedia!), including: 22 | 23 | * V8 (Chrome, node) 24 | * SpiderMonkey (first JS engine ever; now in Firefox) 25 | * Nitro (Safari) 26 | 27 | 28 | ## An Aside: Matters of Style and Opinion 29 | 30 | Toward the end of the introduction for _Eloquent JavaScript_ is a code block like this: 31 | 32 | ```javascript 33 | function fac(n) { 34 | if (n == 0) 35 | return 1; 36 | else 37 | return fac(n - 1) * n; 38 | } 39 | ``` 40 | 41 | Coding style is like writing style and punctuation: different people do it differently. At Cloud Four, we have our own set of conventions for writing JavaScript (and other things, like CSS!) that we try to stick to. In fact, this code block violates one of them. 42 | 43 | We define JavaScript coding conventions at Cloud Four using two tools, [JSHint](http://jshint.com/) and [JSCS](http://jscs.info/). 44 | 45 | JSHint conventions are tuned toward preventing you from making actual programming mistakes, while JSCS conventions are stylistic. 46 | 47 | Configuration files for both JSHint and JSCS are installed automatically on Cloud Four laptops using boxen, and the appropriate plugins/packages for enforcing them are installed for either Atom or SublimeText. In case you are curious, you can [find our current conventions here](https://github.com/cloudfour/cloudfour-boxen/tree/master/modules/cloudfour_potions/files/dotfiles) (`jscsrc` and `jshintrc`). 48 | 49 | ## Exercises 50 | 51 | These let you try out a couple of places that you can go to test JavaScript and inspect the state of the browser environment. 52 | 53 | ### Exercise 1: Web Inspector, the `window` object 54 | 55 | In Chrome, open the Web Inspector (`Option-Cmd-I` on a Mac) and go to the `console` tab. 56 | 57 | Type 58 | 59 | ```javascript 60 | window 61 | ``` 62 | 63 | and hit enter. 64 | 65 | What this does is display (print out) a representation of the value for the identifier `window`. `window` is a JavaScript `Object` that is made available by the `environment` in the browser (if "Object" and "environment" are mysterious concepts as of yet, don't fret, they'll come up later). 66 | 67 | Expand the `window` object and explore it a bit, especially the stuff under the `document` property (itself another object...it's objects all the way down!). The `document` object contains representations of a lot of stuff about the web document in the browser window and you may start seeing some items that look familiar here. 68 | 69 | ### Exercise 2: ScratchPad, `window` object redux 70 | 71 | In Firefox, go to `Tools -> Web Developer -> Scratchpad...`. You can [read more about it here](https://developer.mozilla.org/en-US/docs/Tools/Scratchpad) if you like. 72 | 73 | The console in Web Inspector or the Console in Firefox are useful for quick, one-line things (in the previous example, `window` gets evaluated as soon as you hit enter), but ScratchPad gives you the ability to run longer chunks of JavaScript code in the browser environment. 74 | 75 | Type 76 | 77 | ```javascript``` 78 | window 79 | ``` 80 | 81 | and hit enter. 82 | 83 | Now click the `Run` button. Nothing happens. That's because we're not _in_ the console, the way we were when we were in the Web Inspector console above. This isn't a console, so things aren't logging out (displaying their values). But what if we wanted to examine the `window` object? There are two options. One is to right-click the `window` text and choose `Inspect` from the pop-up menu (this lets you explore the current state of the `window` object on that line). 84 | 85 | #### Exercise Thinking Points 86 | 87 | * What happens if you modify the code in the ScratchPad to read: `console.log(window);` and click `Run`? Can you find the output? 88 | * What is the value of the `window.document.URL` property? What does it refer to? 89 | 90 | ## Questions for Thought 91 | 92 | * Is there a difference between JavaScript and ECMAScript? Why do both exist? 93 | * Explore: What's the relationship between JavaScript and node? 94 | -------------------------------------------------------------------------------- /npm/README.md: -------------------------------------------------------------------------------- 1 | # Setting up your computer to publish to npm (only necessary the first time) 2 | 3 | Prerequisites: [Node.js](https://github.com/creationix/nvm#installation) with npm version 5.7.0+ (required for `npm ci` to work) 4 | 5 | ## Setting up your npm account online 6 | 7 | - [Either confirm that you have an npm account or create one](https://www.npmjs.com/) (you'll need your username and password) 8 | - Confirm you have set up two-factor authentication on your npm account or set it up 9 | - Set up 2FA to protect `Authorization and Publishing` 10 | - Use a 2FA provider to complete your 2FA setup ([1Password](https://1password.com/) or [Authy](https://authy.com/) or [Google Authenticator](https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8)) 11 | - This app will now provide you with a One-Time Password (OTP), every time you do a task that requires 2FA 12 | - Login to the C4 npm account (see 1Password for details: `cloudfour-user`) 13 | - Go to the account settings for the `cloudfour` npm organization (not `cloudfour-user`) 14 | - Go to the `Members` tab and use `Invite Members` to invite yourself, using the npm username you had or just created 15 | - You may or may not need to logout and go to your account to accept the invite 16 | 17 | ## Signing in to npm locally 18 | 19 | - In the terminal, type `npm adduser `, and enter: 20 | - Your username 21 | - Your password 22 | - Your email address 23 | - A new OTP from your phone, once prompted 24 | 25 | Once you are signed in, you should be ready to publish (see individual repos for per-repo publishing instructions) 26 | -------------------------------------------------------------------------------- /opensource/README.md: -------------------------------------------------------------------------------- 1 | # Open Source at Cloud Four 2 | 3 | This guide is about how we manage our open-source work at Cloud Four. Given that this work happens across several Git repos that have been set up by various people over many years, it makes sense to have a guide that documents our current best thinking about how to operate them. 4 | 5 | ## NPM Package Setup 6 | 7 | !!! THIS IS A WORK-IN-PROGRESS !!! 8 | 9 | For open-source work that is published to npm, we need to do our due diligence. That includes ensuring that the package has tests, the build passes, there are no security vulnerabilities, and it stays up-to-date with dependencies. 10 | 11 | - [@cloudfour npm packages](https://www.npmjs.com/org/cloudfour) 12 | 13 | ### Checklist 14 | 15 | - [ ] one 16 | - [ ] two 17 | - [ ] three 18 | 19 | ### README file 20 | 21 | Add note about recommended README bits: 22 | 23 | - npm badge 24 | - build status badge 25 | - install instructions (from npm) 26 | - link to documentation 27 | - link to changelog 28 | 29 | ### CHANGELOG file 30 | 31 | Add note about the importance of maintaining a changelog. 32 | 33 | ### Release Process 34 | 35 | Add note about version bump and npm release process 36 | 37 | - [bump](https://github.com/fabiospampinato/bump) 38 | 39 | ### Tests & Linting 40 | 41 | Add note about testing and linting 42 | 43 | ### Continuous Integration 44 | 45 | Add note about Travis (and .com/.org) to run tests and lint 46 | 47 | ### Automated Dependency Updates 48 | 49 | Add note about Renovate 50 | 51 | - How to evaluate Renovate PRs 52 | 53 | ### Automated Security Checks 54 | 55 | Add note about Snyk 56 | 57 | - Added by Jason in April 2017. Company was started by a friend of his, and some good people work there. 58 | - How to evaluate Snyk security patches 59 | - Lifecycle of a Snyk security patch 60 | 61 | - [Snyk documentation](https://snyk.io/docs/) 62 | - [Using Snyk, NSP and Retire.JS to Identify and Fix Vulnerable Dependencies in your Node.js Applications](https://developers.redhat.com/blog/2017/04/12/using-snyk-nsp-and-retire-js-to-identify-and-fix-vulnerable-dependencies-in-your-node-js-applications/) 63 | - [NSP is shutting down](https://blog.npmjs.org/post/175511531085/the-node-security-platform-service-is-shutting) 64 | - [Introducing `npm audit`: Identify and fix insecure dependencies](https://blog.npmjs.org/post/173719309445/npm-audit-identify-and-fix-insecure) 65 | - [Difference between Snyk and NSP?](https://github.com/Snyk/snyk/issues/19) 66 | - [Audit CI](https://www.npmjs.com/package/audit-ci) 67 | - [Comparing NPM Audit with Synk](https://www.nearform.com/blog/comparing-npm-audit-with-snyk/) 68 | - [Snyk demo app](https://github.com/snyk/snyk-demo-app) 69 | - [Twitter thread about Snyk patches](https://twitter.com/spaceninja/status/1118179340871553024) 70 | -------------------------------------------------------------------------------- /package-json-script-names.md: -------------------------------------------------------------------------------- 1 | # `package.json` Script Names 2 | 3 | ## General 4 | 5 | - `npm run validate`: Runs all tests, type checks, linters, and formatters 6 | 7 | ## Testing 8 | 9 | - `npm run test`: Runs all test runners (Jest and/or Cypress) 10 | - `npm run test:watch`: Runs all test runners in watch mode 11 | - `npm run test:jest`: Runs Jest and exits 12 | - `npm run test:jest:watch`: Runs Jest in watch mode 13 | - `npm run test:cypress`: Runs Cypress and exits 14 | - `npm run test:cypress:open`: Open Cypress dashboard 15 | 16 | ## Linting 17 | 18 | - `npm run lint`: Runs all linters and formatters, and fixes any auto-fixable problems 19 | - `npm run lint:check`: Runs all linters and formatters, and reports problems even if they are auto-fixable 20 | - `npm run lint:js` 21 | - `npm run lint:js:check` 22 | - `npm run lint:css` 23 | - `npm run lint:css:check` 24 | 25 | ## Type Checking 26 | 27 | - `npm run type`: Runs typechecker 28 | - `npm run type:watch`: Runs the typechecker in watch mode 29 | -------------------------------------------------------------------------------- /rituals/README.md: -------------------------------------------------------------------------------- 1 | # Rituals 2 | 3 | This guide documents some common rituals we encourage in our work. 4 | 5 | These are not ironclad processes we should always follow. More like a helpful jumping-off point if you're on a project where they would be useful. 6 | 7 | ## [Postmortems](./postmortems.md) 8 | 9 | > “A postmortem is a written record of an incident, its impact, the actions taken to mitigate or resolve it, the root cause(s), and the follow-up actions to prevent the incident from recurring.” — Google's _Site Reliability Engineering_ 10 | 11 | This ritual is held when a serious incident happens, such as a site outage, and the team needs to understand what happened and how to avoid it in the future. 12 | -------------------------------------------------------------------------------- /rituals/postmortems.md: -------------------------------------------------------------------------------- 1 | # Incident Postmortems 2 | 3 | Postmortem documents are a ritual designed to examine serious incidents or outages. Google’s [book on Site Reliability Engineering](https://landing.google.com/sre/book.html) says: 4 | 5 | > A postmortem is a written record of an incident, its impact, the actions taken to mitigate or resolve it, the root cause(s), and the follow-up actions to prevent the incident from recurring. 6 | 7 | ## Purpose 8 | 9 | We practice postmortems to ensure we understand and address the root cause of severe incidents such as outages, data loss, or serious production bugs. 10 | 11 | > "Don't make the mistake of neglecting a post-mortem after an incident. Without a post-mortem you fail to recognize what you're doing right, where you could improve, and most importantly, how to avoid making the same exact mistakes next time around. A well-designed, blameless post-mortem allows teams to continuously learn, and serves as a way to iteratively improve your infrastructure and incident response process." — [PagerDuty](https://response.pagerduty.com/after/post_mortem_process/) 12 | 13 | ### What is a Postmortem? 14 | 15 | A postmortem is a document that examines an incident in detail, including: 16 | 17 | - An summary of what happened 18 | - The incident's impact 19 | - What caused the incident 20 | - How the incident was resolved 21 | - A detailed timeline 22 | - What could have prevented the incident 23 | 24 | ### Why Do We Do Postmortems? 25 | 26 | The goal of the postmortem is to gain a detailed understanding of the root causes of the incident to avoid it happening again in the future. A secondary goal can be to reassure the client, since the actions taken during an incident response may not be visible to them. 27 | 28 | For postmortems to be effective at reducing repeat incidents, the review process has to incentivize teams to honestly identify root causes and fix them. For this reason, we practice **blameless postmortems** (see below). 29 | 30 | ### When is a Postmortem Needed? 31 | 32 | It depends on the client or project. For applications or sites with an service-level agreement, postmortems are commonly carried out for high-severity incidents that violate the SLA. For client applications or site, a postmortem may only be called for following a major outage or quality-control problem. 33 | 34 | > "Incidents in your organization should have clear and measurable severity levels. These severity levels can be used to trigger the post-mortem process. For example, any incident Sev-1 or higher triggers the postmortem process, while the postmortem can be optional for less severe incidents." — [Atlassian](https://www.atlassian.com/blog/statuspage/incident-postmortem-writing-tips) 35 | 36 | The postmortem document should be produced within 24-48 hours of the incident's resolution, while it's still fresh in everyone's memory. 37 | 38 | > "Despite how painful an outage may have been, the worst thing you can do is to bury it and never properly close the incident in a clear and transparent way. Most humans come together in times of crisis and communication around outage post-mortems, in my experience, has always been met with positive energy, understanding comments, constructive suggestions and numerous offers to help." — [Daniel Doubrovkine says](https://artsy.github.io/blog/2014/11/19/how-to-write-great-outage-post-mortems/) 39 | 40 | ### Who Completes the Postmortem? 41 | 42 | In a small company like ours, the most senior engineer with direct knowledge should be writing an outage postmortem. It's their job and responsibility to acknowledge, understand and explain what happened. For particularly sensitive topics, it may make sense to escalate this responsibility to an engineering manager or founder. 43 | 44 | > "Focusing attention away from the individual contributors allows the team to learn from the mistakes and address the root causes in time without the unnecessary stress or pressure during a crisis." — [Daniel Doubrovkine](https://artsy.github.io/blog/2014/11/19/how-to-write-great-outage-post-mortems/) 45 | 46 | ### Who is the Postmortem For? 47 | 48 | The postmortem is intended for public consumption, especially by clients. It's a visible way to document not just the problem that happened, but how you addressed it and are ensuring it won't happen again. A properly written postmortem should increase your customer's faith in you. 49 | 50 | > "The postmortem audience includes customers, direct reports, peers, the company's executive team and often investors. The document may be published on your website, and otherwise goes to the entire team. It's critical to bcc everyone. This is the equivalent of a locked thread, avoiding washing the laundry in public: one of the worst possible things to see is when a senior manager replies back pointing an individual who made a mistake, definitely not an email you want accidentally sent to the entire company." — [Daniel Doubrovkine](https://artsy.github.io/blog/2014/11/19/how-to-write-great-outage-post-mortems/) 51 | 52 | ### Running a Postmortem Meeting 53 | 54 | Some teams hold a meeting after the postmortem document is produced. These meetings are generally short, only 15-30 minutes, and are intended to be a wrap-up of the postmortem process. We discuss what happened, what could have gone better, and any followup actions we need to take. The point of the meeting is to ensure there's no disagreement on the analysis, and spread a wider awareness of problems the team is facing. 55 | 56 | ## Blameless Postmortems 57 | 58 | Many teams have adopted “blameless” postmortems, which focus on systemic problems and root causes without naming individuals or casting blame onto people or teams. Here's John Allspaw, from [Blameless Postmortems and a Just Culture](https://codeascraft.com/2012/05/22/blameless-postmortems/) 59 | 60 | > Having a “blameless” Post-Mortem process means that engineers whose actions have contributed to an accident can give a detailed account of: 61 | 62 | > - what actions they took at what time, 63 | > - what effects they observed, 64 | > - expectations they had, 65 | > - assumptions they had made, 66 | > - and their understanding of timeline of events as they occurred. 67 | 68 | > …and that they can give this detailed account without fear of punishment or retribution. 69 | 70 | > Why shouldn’t they be punished or reprimanded? Because an engineer who thinks they’re going to be reprimanded are disincentivized to give the details necessary to get an understanding of the mechanism, pathology, and operation of the failure. This lack of understanding of how the accident occurred all but guarantees that it will repeat. If not with the original engineer, another one in the future. 71 | 72 | For a good example of why blameless postmortems matter, I strongly encourage you to watch [Who Destroyed Three Mile Island?](https://www.youtube.com/watch?v=hMk6rF4Tzsg), a talk by Nickolas Means from Lead Dev London 2018. 73 | 74 | ## Tips 75 | 76 | - Make sure the timeline is an accurate representation of events. 77 | - Use the [Five Whys](https://en.wikipedia.org/wiki/5_Whys) technique to traverse the causal chain until you find a good true root cause. 78 | - Don't change details or events to make things "look better". We need to be honest in our post-mortems, even to ourselves, otherwise they lose their effectiveness. 79 | - Don't name and shame someone. We keep our post-mortems blameless. If someone deployed a change that broke things, it's not their fault, it's our fault for having a system that allowed them to deploy a breaking change, etc. 80 | - Avoid the concept of "human error". This is related to the point above about "naming and shaming", but there's a subtle difference - very rarely is the mistake "rooted" in a human performing an action, there are often several contributing factors (the script the human ran didn't have rate limiting, the documentation was out of date, etc...) that can and should be addressed. 81 | 82 | ## Resources 83 | 84 | * [Postmortem Template](https://docs.google.com/document/d/12Prd33SDG1U0yE_gwXUgwa85Vn6dS_Qo5RdEWwFzFEo) document on Google Drive 85 | * [Postmortem Handbook from Atlassian](https://www.atlassian.com/incident-management/handbook/postmortems) 86 | * [Postmortem Process from PagerDuty](https://response.pagerduty.com/after/post_mortem_process/) 87 | * [Effective Postmortem Tips from PagerDuty](https://response.pagerduty.com/after/effective_post_mortems/) 88 | * [Blameless Postmortems and a Just Culture](https://codeascraft.com/2012/05/22/blameless-postmortems/) 89 | * [How to Write Great Outage Postmortems](https://artsy.github.io/blog/2014/11/19/how-to-write-great-outage-post-mortems/) 90 | -------------------------------------------------------------------------------- /testing/README.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | ## Philosophy 4 | * Test code is a first-class part of the deliverable, not an optional nice-to-have. 5 | * When scoping / estimating work: always factor in testing. 6 | * Testability is an attribute of good code. Code that cannot be tested is a problem. 7 | * Insufficient test coverage is better than no test coverage. 8 | * Prefer [Use Case Coverage over Code Coverage](https://kentcdodds.com/blog/how-to-know-what-to-test) (no need for 100% code coverage). 9 | * Additional history and guiding principles are in [this "manifesto" doc](https://docs.google.com/document/d/1XWx0GZLndtPF4-cwBeHii85osRj0ROPrflBF3DAVewA/edit) 10 | 11 | ## Best Practices & Standardization 12 | 13 | ### General 14 | * Organization of testing scripts in `package.json` ([more details](../package-json-script-names.md)) 15 | * `npm run test`: Runs all test runners (Jest and/or Cypress) 16 | * `npm run test:watch`: Runs all test runners in watch mode 17 | * `npm run test:jest`: Runs Jest and exits 18 | * `npm run test:jest:watch`: Runs Jest in watch mode 19 | * `npm run test:cypress`: Runs Cypress and exits 20 | * `npm run test:cypress:open`: Open Cypress dashboard 21 | 22 | * [Apply the AHA principle](https://kentcdodds.com/blog/avoid-nesting-when-youre-testing). Try to minimize nesting, coupling and over-abstraction. These make tests brittle and hard to maintain. 23 | 24 | ### Jest 25 | * Unit test files for components should be siblings in the same directory with a `.test.js` suffix. Placing test code close to application code is intended to encourage testing and make it harder to forget. 26 | * For the test name, prefer the `it('should do something')` syntax because it is more self-documenting and intuitive 27 | * Use `describe()` and `beforeEach` sparingly. They lead to nesting and coupling. 28 | 29 | ### Testing Library 30 | * Prefer the `getByRole` query over others because it typically best matches the user's experience. [1](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#not-using-byrole-most-of-the-time) 31 | * Avoid `getByTestId` because it _least_ matches the user's experience. 32 | * We encourage using the `screen` object exported by Testing Library because the resulting idioms will be more similar in React and Vanilla JS projects. [1](https://testing-library.com/docs/queries/about#screen), [2](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library#not-using-screen). 33 | 34 | ## Favorite Tools 35 | * Unit/integration testing: Jest + Testing Library 36 | * E2E testing: Cypress 37 | 38 | ## Resources 39 | * [Common Testing Library mistakes](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library) 40 | * [Avoid Nesting](https://kentcdodds.com/blog/avoid-nesting-when-youre-testing) 41 | -------------------------------------------------------------------------------- /til/README.md: -------------------------------------------------------------------------------- 1 | # TIL 2 | 3 | "Today I learned" or "thing I learned". Roughly-organized quick MD notes about stuff we encounter. 4 | -------------------------------------------------------------------------------- /til/css/filters-and-transitions.md: -------------------------------------------------------------------------------- 1 | Today I learned a bit about CSS `filter`, which is a *property* that allows you to do a bunch of annoying things, but I find that the `grayscale` filter value is not terrible. I played around in a [codepen](http://codepen.io/lyzadanger/pen/vEpxMy) and noted: 2 | 3 | * You can transition on `filter`, at least in some browsers 4 | * You can listen for `transitionend` just like with any transition 5 | * `grayscale` can take a percentage argument which operates something like the "opacity" of the filter, e.g. `grayscale(50%)` 6 | 7 | I do not however know the performance impacts of filters and those transitions and anticipate they could be significant issues. 8 | 9 | ## Events 10 | 11 | `transitionend` events are useful but supported inconsistently, no surprise there. [Bootstrap's transition.js](https://github.com/twbs/bootstrap/blob/master/js/transition.js) does a decent job of wrapping that up. I adapted a slightly boiled-down variant of this for my own use. Intriguingly the feature test involves checking for a `style` property on a given element. 12 | -------------------------------------------------------------------------------- /til/git/README.md: -------------------------------------------------------------------------------- 1 | ## Linking to Multiple Lines 2 | 3 | I learned today that you can link to a multiple-line selection, not just a single line, e.g. https://github.com/hexojs/hexo/blob/master/lib/plugins/console/generate.js#L89-L101 4 | 5 | Add `CONTRIBUTING.md` at the top of your repo and it will get linked to with a "read the guidelines for contributing..." automatically! 6 | 7 | ## --ours vs. --theirs 8 | 9 | Recently I learned about 10 | 11 | `git checkout --ours [file...]` 12 | 13 | and 14 | 15 | `git checkout --theirs [file...]` 16 | 17 | Which is a quick way to resolve a conflict on something in an intuitive way. Then commit the results. 18 | 19 | ## git rev-parse 20 | 21 | The [`git rev-parse` command](http://git-scm.com/docs/git-rev-parse) is a "porcelainish" interface to some lower-level git internals. 22 | 23 | Kinda handy: 24 | 25 | * `git rev-parse --is-inside-work-tree` returns a Boolean as to whether you are, well, currently inside of a working git tree 26 | * `git rev-parse --short HEAD` Gits you the short SHA hash for the most recent commit on HEAD 27 | * `git rev-parse --verify --short refs/stash` will return the short hash of the latest stash. Note that it will fail/exit 1 if there isn't a stash: `fatal: Needed a single revision` and thus needs to be handled appropriately if you're doing something meaningful with the response. 28 | 29 | 30 | ## git symbolic-ref 31 | 32 | `git symbolic-ref --quiet --short HEAD` is a programattic way to ask what your working branch is at the moment. 33 | 34 | ## Delete merged local branches 35 | 36 | ``` 37 | git checkout master 38 | git branch --merged | grep -v "\*" | xargs -n 1 git branch -d 39 | ``` 40 | 41 | [Via this gist](https://gist.github.com/JoshuaEstes/2627607#delete-all-branches-that-have-been-merged) 42 | -------------------------------------------------------------------------------- /til/js/README.md: -------------------------------------------------------------------------------- 1 | ## 2015-02-25 2 | 3 | Neat little trick that'll work in IE9+: 4 | 5 | ```javascript 6 | var print = console.log.bind(console, '>'); 7 | print('Hello, World'); // > Hello, World 8 | ``` 9 | -------------------------------------------------------------------------------- /til/lyza/README.md: -------------------------------------------------------------------------------- 1 | # Trivial Things I learned 2 | 3 | (Not worthy of putting in conceptual TIL files). 4 | 5 | * 2015-02-19: How to go to the last line of a file in `vi`. You may start your snickering now. `:$` 6 | --------------------------------------------------------------------------------