196 |
197 |
198 | **[[⬆]](#TOC)**
199 |
200 |
201 | ### Type Names
202 |
203 | All ColdFusion type names in arguments, return types and the like should all be in lower case when they are native ColdFusion types. If they are components they should be the EXACT name of the component. This is extremely important if for some reason the code executes in a case-sensitive system, then the code will not work. ALWAYS have the exact case of components and definitions. If no type is defined, then it is assumed it is uses the **any** type.
204 |
205 |
206 |
207 |
208 |
209 | ✅ DO THIS
210 |
211 |
212 | ❌ NOT THIS
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 | function test( array paths, model.users.User user ){}
221 | boolean function isDone(){}
222 | SecurityService function getSecurityService();
223 |
238 |
239 | **[[⬆]](#TOC)**
240 |
241 |
242 | ### CFML Tags, Custom Tags and Attributes
243 |
244 | All CFML and custom tags should be writing in lower case form, just like HTML tags. Attributes for CFML tags should follow the same behavior as arguments and variables as seen below. If attributes can all be placed in one line, then do that. However, if they will span and cause breaks, consider breaking the attributes into multiple lines and aligning them to the first attribute. Usually, you can do 2 or 3 in one line, else break. Same goes for method calls.
245 |
246 |
247 |
291 |
292 |
293 | **[[⬆]](#TOC)**
294 |
295 |
296 | ### Arguments and Variables
297 |
298 | They should be descriptive lowercase single words, acronyms or abbreviations. If multiple words are necessary they should follow camel case with first letter lowercase. Examples:
299 |
300 |
301 |
302 |
303 |
304 | ✅ DO THIS
305 |
306 |
307 | ❌ NOT THIS
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 | niceLocation = "Miami";
316 |
317 |
318 |
319 |
320 |
321 | NICELOCATION = "Miami";
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 | results = "";
332 |
333 |
334 |
335 |
336 |
337 | Results = "";
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 | avgSalary = "323";
348 |
349 |
350 |
351 |
352 |
353 | average-salary = "323";
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 | **[[⬆]](#TOC)**
363 |
364 |
365 | ### Constants or Static Variables
366 |
367 | They should all be in upper case separated by underscores "\_". Examples:
368 |
369 |
370 |
371 |
372 |
373 | ✅ DO THIS
374 |
375 |
376 | ❌ NOT THIS
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 | INTERCEPTOR_POINTS = "";
385 |
386 |
387 |
388 |
389 |
390 | interceptor-points = "";
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 | LINE_SEP = "-";
401 |
402 |
403 |
404 |
405 |
406 | line_sep = "-";
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 | MAX = "123";
417 |
418 |
419 |
420 |
421 |
422 | max = "123";
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 | **[[⬆]](#TOC)**
432 |
433 |
434 | ## Whitespaces
435 |
436 | This is more of a convenience for readability and preference, but these are the standards we set forward for consistency and for making code reviews easier to scan with the eyes.
437 |
438 |
439 | **[[⬆]](#TOC)**
440 |
441 | ### Code Blocks
442 |
443 | Code blocks should start in one line and end in another.
444 |
445 |
446 |
509 |
510 |
511 |
512 | **[[⬆]](#TOC)**
513 |
514 | ### Multi-Argument Declarations
515 |
516 | When declaring 4 arguments or more go into multi-line layout
517 |
518 |
519 |
520 |
521 |
522 | ✅ DO THIS
523 |
524 |
525 | ❌ NOT THIS
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 | function testThis(
534 | required name,
535 | required any target,
536 | boolean isHappy="true",
537 | any results
538 | ){
539 |
540 | ... function here
541 |
542 | }
543 |
544 |
545 |
546 |
547 |
548 | function testThis(required name, required any target, boolean isHappy="true", any results){
549 | }
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 | **[[⬆]](#TOC)**
565 |
566 | ### Multi-Argument Function Calls
567 |
568 | When calling a function with 4 arguments or more go into multi-line layout:
569 |
570 |
571 |
670 |
671 | **[[⬆]](#TOC)**
672 |
673 |
674 | ### Method Chaining
675 |
676 | When using method chaining and libraries that encourage this, remember that they do it for convenience and also readability. Do not chain for up to 1000 levels, use 2 or 3 and then break.
677 |
678 |
679 |
767 |
768 |
769 | > However, please note that this conventions are only if you are writing libraries. If you are within an ecosystem that provides WireBox Dependency Injection, then **always** prefer WireBox.
770 |
771 |
772 | **[[⬆]](#TOC)**
773 |
774 | ## End of Line on Files
775 |
776 | Do not add extra lines to files when ending them:
777 |
778 | ``` coldfusion
779 | // dont this
780 | component{
781 | .....
782 | }
783 | ```
784 |
785 |
786 | **[[⬆]](#TOC)**
787 |
788 |
789 |
790 | ## Components
791 |
792 | ### Documentation
793 |
794 | Yes, you will need to document **ALL** of your code, from classes to property definitions to code blocks to arguments. Our preference is to write all logic in script and **not** in tags unless we are targeting a specific CFML Engine. We leverage [DocBox](https://github.com/Ortus-Solutions/DocBox) for reading, parsing and creating documentation out of all CFCs in an application. Please also refer to the [Custom Anotations](https://github.com/Ortus-Solutions/DocBox/wiki/List-of-Custom-Annotations) that DocBox applies so you can extend the metadata in a CFC. The DockBlockr plugin is magnificent for this.
795 |
796 |
797 | ``` js
798 | /**
799 | * @author Luis Majano
800 | *
801 | * My component documentation
802 | * goes here in multiple lines if needed
803 | * You can add links and valid HTML if needed
804 | *
805 | * Copyright or License Information goes here
806 | */
807 | component accessors="true"{
808 |
809 | /**
810 | * First name of the user
811 | */
812 | property name="firstName";
813 |
814 | /**
815 | * Last name of the user
816 | */
817 | property name="lastName";
818 |
819 | /**
820 | * Constructor
821 | */
822 | function init(){
823 | return this;
824 | }
825 |
826 | /**
827 | * Submit an order
828 | *
829 | * @product The product object
830 | * @coupon The Coupon code needed
831 | * @results The results object
832 | *
833 | * @throws InvalidArgumentException - When an invalid product is sent
834 | * @throws InvalidCouponCode - When an invalid coupon is sent
835 | *
836 | * @return An Order object
837 | */
838 | Order function submitOrder( required product, coupon="", boolean results=true ){
839 | }
840 |
841 | }
842 | ```
843 |
844 | **[[⬆]](#TOC)**
845 |
846 | ### Scopes
847 |
848 |
849 | Components can have instance data that can be placed in two different visibility scopes: **private** and **public**. Private variables are declared in the `variables` scope and public variables in the `this` scope. This means that the variables in the `this` scope will be available for modification from the outside world, while the `variables` scope is not accessible from the outside world directly.
850 |
851 | The only way to manipulate these private variables would be through methods that your object will expose to the outside world. This is called data-hiding or encapsulation.
852 |
853 |
854 | #### Use Accessors
855 |
856 | Leverage implicit getters and setters in all component declarations instead of creating getters and setters manually, unless you need to add behavior to them:
857 |
858 | ``` js
859 | component accessors="true"{
860 |
861 | property name="firstName";
862 | property name="lastName";
863 | }
864 | ```
865 |
866 |
867 | Be very careful of when to make internal properties public as you will be violating encapsulation (look at next point). One of the best reasons for making variables public is if they do not change and can act like static constants. If your variable does not meet this criteria, then DO NOT expose it as public.
868 |
869 | ``` coldfusion
870 |
871 |
872 |
873 | ```
874 |
875 |
876 | > Even though you are treating these variables like final static variables they CAN still be modified as ColdFusion does not support *final or static* variables (Lucee does in 5+). It is more of a convention and agreement to use this approach.
877 |
878 | **[[⬆]](#TOC)**
879 |
880 | ### Encapsulation
881 |
882 | Encapsulation provides the basis for modularity by hiding information from unwanted outside access and attaching that information to only methods that need access to it. This binds data and operations tightly together and separates them from external access that may corrupt/change them intentionally or unintentionally. Encapsulation is achieved by declaring variables as private in a CFC (`variables` scope).
883 |
884 | This gives access to data to only public/package member functions of the CFC. You can then create their mutators (setters) and accessors (getters) via public methods. Some benefits of encapsulation are:
885 |
886 | - You can keep the exposed API the same while changing how your CFC works internally without breaking any code that uses your CFC
887 | - Prevents the developer from getting in trouble by violating your internal assumptions about how the instance data works
888 | - It hides your implementation from the outside world
889 |
890 |
891 |
892 |
893 |
922 |
923 | **[[⬆]](#TOC)**
924 |
925 | ### Constructors
926 |
927 | Always have an `init()` method that acts as your constructor and returns `this` (unless you are building a web services/flash remoting facade). Even if the method has a simple return statement, it is always best practice that every object have a constructor method.
928 |
929 | ```js
930 | component{
931 | function init(){
932 | return this;
933 | }
934 | }
935 | ```
936 |
937 | If you are using inheritance then you must call the parent constructor by accessing the `super` scope.
938 |
939 | ```js
940 | component extends="BaseConverter"{
941 | function init(){
942 | super.init();
943 | return this;
944 | }
945 | }
946 | ```
947 |
948 | **[[⬆]](#TOC)**
949 |
950 | ### Var Scoping
951 |
952 |
953 | Always, always, always use `var` or the `local` scope for local variables inside your methods, including ALL loop counters, temporary variables, queries, etc. This is called **var scoping**. If you do not do this, your component will not be thread-safe.
954 |
955 | This means that if somebody persists (stores) this component in memory, subsequent calls can and will override variables and create all sorts of memory problems. There is an open source project called [http://www.schierberl.com/cfblog/index.cfm/2006/7/20/varScoper-10-release varscoper] that can check all of your components for var scoping issues, even if they are using cfscript. Var scoping applies to methods inside components and also to UDF's/Closures in order to comply with best practices.
956 |
957 |
958 |
959 |
960 |
961 | ✅ DO THIS
962 |
963 |
964 | ❌ NOT THIS
965 |
966 |
967 |
968 |
969 |
970 |
971 |
972 | <cffunction name="myFunction" access="public" returntype="void" output="false" hint="This methods does nothing">
973 | <cfset var i = 0>
974 | <cfset var qGet = "">
975 | <cfquery name="qGet">
976 | </cfquery>
977 | <cfloop from="1" to ="20" index="i">
978 | </cfloop>
979 | </cffunction>
980 |
999 |
1000 | **[[⬆]](#TOC)**
1001 | ### Output From CFCs
1002 |
1003 | Always (*with rare exceptions*) use `output="false"` in your function and components. Do not output directly to the buffer inside a CFC method; instead return a string from the method. The main reason is that you don't want to break encapsulation. By outputting directly to the output stream you assume knowledge of the external environment of the CFC. However, if you return a string then you get the exact same behavior when you do `#myCFC.someHTMLGeneratingMethod()#` but you gain the advantage of not assuming that's how your method will be used. For instance, what if the method that returns the string is used inside of a big `cfscript` block where someone is building a string via concatenation? Everything will break.
1004 |
1005 | ```js
1006 |
1007 |
1008 |
1009 |
1010 |
1011 | ```
1012 |
1013 | **[[⬆]](#TOC)**
1014 | ### Return Types & Duck Typing
1015 |
1016 |
1017 | Use the `returnType` attribute of the functions and the `type` attribute of the argument add documentation and runtime type checking. Also remember that `void` is the return type when your method call does not return anything.
1018 |
1019 | Duck Typing is when you use the return type or type of `any`. This is a useful technique when dealing with a dynamic language such as ColdFusion. This means that the argument or object returned can be ANYTHING, which then your caller needs to determine what to do with it and what it is based on pre-determined conventions. Usually you will need to document this in a `@return ` annotation within your function call to document the possibilities.
1020 |
1021 | A side effect of not using a strong type is a speed enhancement, since ColdFusion does not check the validity of the types. This side effect should not be used to get more performance, unless absolutely necessary.
1022 | This dynamic nature of arguments and return types brings forth great power in a dynamic language, but it also opens holes for runtime exceptions. However, thanks to unit testing, these runtime exceptions should be minimized. So as a followup guideline to duck typing is that you must have unit tests for these components.
1023 |
1024 | **[[⬆]](#TOC)**
1025 | ### Referencing External Scopes
1026 |
1027 | Do not directly reference external scopes, i.e.: session/application/client/server/request variables, inside a CFC. If you reference external scopes you will be breaking the encapsulation and cohesiveness of the component at hand. You have now binded the component to an external scope that must exist in order for this component to work. This also provides difficulties when unit testing.
1028 |
1029 | However, the one exception to referencing external scopes is when building **facades**, especially for web services/flash remoting, in which case ALL references to shared scope variables should be encapsulated within the facade. This means, for instance, passing in the dsn instead of referring to application.dsn when doing database queries. If you do not know what a facade is, then please search for facade pattern to learn more about it. It basically encapsulates a shared scope such as application,session, etc into a CFC.
1030 |
1031 | **[[⬆]](#TOC)**
1032 | ### Default Arguments
1033 |
1034 | In general, non-required arguments of a CFC method should have a default value specified, unless you will be programmatically checking for existence using `structKeyExists(arguments, "key")`, which sometimes is useful.
1035 |
1036 | ```js
1037 |
1038 |
1039 | ```
1040 |
1041 | **[[⬆]](#TOC)**
1042 |
1043 | ### Inheritance & Composition
1044 |
1045 | Use inheritance only when describing an **is-a** relationship, not for a **has-a** relationship (composition) or for code reuse only. For a nice summary, visit http://cnx.rice.edu/content/m11709/latest/
1046 |
1047 | Do not use a component as a huge glorified set of methods and call that code reuse. Components are synonymous to objects, they should have an identity upon themselves. Put in practice your [Ontology](http://en.wikipedia.org/wiki/Ontology) skills and define what the CFC will do for you and what is their identity.
1048 |
1049 | Always prefer object composition over inheritance. This is where another component is created or injected as a property of the object at hand. There are several reasons of why to choose composition over inheritance in order to make your designs more flexible and not coupled at compile time, which inheritance does. Composition brings in functionality at runtime as you can switch implementations, etc. Some resources are:
1050 |
1051 | * https://en.wikipedia.org/wiki/Composition_over_inheritance
1052 | * http://www.artima.com/lejava/articles/designprinciples4.html
1053 | * http://web.archive.org/web/20090225065341/http://guidewiredevelopment.wordpress.com/2008/02/05/favoring-composition-over-inheritance/
1054 |
1055 | **[[⬆]](#TOC)**
1056 |
1057 | ## General Best Practices
1058 |
1059 | * Avoid using `Application.cfm` and move to `Application.cfc`. Not only will you get more functionality, but it is a standard. Also, **always** have an `Application.cfc` for your application. If not, CF will search for one and use it's settings and you do not want that.
1060 | * Only create Application listener methods that you will use, do not create them as empty functions unecessarily.
1061 |
1062 | **[[⬆]](#TOC)**
1063 |
1064 | ### Session Scope Usage
1065 | Be very careful when using `session` scoped variables in your applications, especially if used under heavy load or high traffic. Remember that `session` variables are per user and consume memory. If they are misused or you issue `session` variables randomly, your RAM usage will increase exponentially. Consider always having low timeouts for your `session` scopes and always disallowing bots to have `session` variables. Do not pre-set `session` scoped variables if not necessary. Usually, when somebody logs in, then give memory away.
1066 |
1067 |
1068 | **[[⬆]](#TOC)**
1069 |
1070 | ### Use `cflock` On Shared Resources
1071 | Use `cflock` whenever you need to make your code thread safe. This applies to variables in shared scopes such as: `server and application` scope. You sometimes want to even lock `session,request` scope if you are working with framesets, but usually locking `session,request` scope is not necessary anymore. Also remember to use `cflock` whenever you are accessing shared resources, such as file operations, cache operations, etc.
1072 | * Always use a `timeout` and `throwOnTimeout` attributes on the `cflock` tag.
1073 | * If you use **exclusive** locks on a resource, make sure that you also provide **readonly** locks when trying to read from such resources.
1074 | * Use named locks for locking resources that do not apply to scopes such as `server, application, session, request`. However, please understand that the name of the lock is on a **per server** basis. So make sure the name is unique enough so other applications running on the same server do not collide with it. If they do, you will be providing unecesarry bottlenecks as named locks are global.
1075 | * Good locking article: http://www.adobe.com/devnet/server_archive/articles/cf_locking_best_practices.html
1076 | * Do not overinflate the code within lock tags. Locking code should only occur on small bits of code and when you are acessing the shared resource. Of course, there are special ocassions to do more than just saving in shared scope, but use it as a rule of thumb.
1077 |
1078 |
1079 |
1132 |
1133 | **[[⬆]](#TOC)**
1134 |
1135 | ### Race Conditions
1136 | There will be cases where you need to do a double tests in order to avoid race conditions on shared resources. This strategy can be applied when you need to test, for example, if a resource is created, an object is configured, etc. What this strategy does is provide two if statement criterias that can verify behavior on the resource, squished between a `cflock` tag. This prevents threads that have already entered the locking stage and are waiting execution, to re-execute the locked code.
1137 |
1138 |
1139 |
1178 |
1179 |
1180 | As you can see from the previous code snippet, if you do not have the double if statements, then code that is waiting on the lock, will re-execute the creation of the controller object. Therefore, since we can test the resource state, we can provide a multi-thread safety net.
1181 |
1182 | ### Do Not Abuse Pound Signs
1183 | Pound signs are most often used to output variables to their set values or evaluate them. There are many places where you DO NOT need to place hash signs. This only delays the evaluation and is not best practice. Most likely you will only need to use pound signs when using ''cfoutput'' or when dealing with certain tag attributes that require the evaluation of a variable.
1184 |
1185 |
1186 |
1217 |
1218 | **[[⬆]](#TOC)**
1219 |
1220 | ### More General Recommendations
1221 |
1222 | * Components are supposed to be objects and have an identity. Always ask yourself what this component's responsibilities are and how will it interact with its surroundings.
1223 | * Variables pass in and out of components by **reference** or by value based on the same rules as the rest of CFML. For instance, strings, arrays, numbers, and dates all pass by value, but structures, queries, and all other "complex" objects (including CFC instances) pass by reference.
1224 | * Arrays in ColdFusion pass by value in Adobe ColdFusion, so beware of this behavior as it is not the same as in Java or other CFML engines.
1225 | * `Duplicate()` and CFWDDX do not work on CFC instances (ColdFusion 7 and below). CFC’s can only be serialized in ColdFusion 8 and with several restrictions. Be careful when serializing objects as the entire object graphs have the potential of being serialized. ColdFusion 9 presents mechanisms to restrict component serializations which helps incredibly.
1226 | * When extending a component outside the base component's package, the sub-component does not inherit `package` permissions -- thus, you cannot call `package` methods on other CFCs in the package of the base component from the sub-component.
1227 | * You can have a method that has a `returnType` or an argument that has a `type` of a base component and return any component that extends that base component. For example, if `methodA` takes an argument `foo` of type `motorVehicle` and you pass `foo` as an instance of `car`, which extends `motorVehicle` then `methodA` will honor that `car` is a `motorVehicle` when doing type checking on the argument `foo`.
1228 | * The previous concept applies to interfaces and inheritance.
1229 | * Use interfaces when you want to provide clear API definitions that need to be implemented. They can be good documentation tools and provide compile time checks on your code.
1230 | * Use `structKeyExists` instead of `isDefined` when checking for existence.
1231 |
1232 |
1233 |
1262 |
1263 | * Use `cfswitch` instead of `cfif` if you have a specific expression that you can evaluate against and if you will have more than 2 `cfelseif` clauses. Not only does it provide more readability, but your code will make more sense.
1264 | * Avoid usage of `iif` if at all possible as it is documented to be slower. However, sometimes it can prove handy.
1265 | * Avoid usage of `evaluate()` expressions. They have to be evaluated by the ColdFusion engine and will always run slower. There are times when you will have to use them, especially when doing dynamic concatenations, but try to avoid them at all possible.
1266 |
1267 |
1268 |
1269 |
1270 |
1271 | ✅ DO THIS
1272 |
1273 |
1274 | ❌ NOT THIS
1275 |
1276 |
1277 |
1278 |
1279 |
1280 |
1281 |
1282 | <cfset value = form[ "field#i#" ]>
1283 |
1284 |
1285 |
1286 |
1287 |
1288 | <cfset value = evaluate("form.field#i#")>
1289 |
1332 |
1333 | * When you are creating view templates, try to always surround it with `cfoutput` tag, instead of nesting them all over the place.
1334 |
1335 |
1336 |
1385 |
1386 | * Code for portability. Avoid at all costs on hardcoding paths, urls, file locations, etc. If you are using a framework, which you should, they usually provide a way to setup application global variables. If not within a framework context, try to set global variables in a shared scope such as `application` scope once when your application loads and then just grab settings from it. Always believe that your application locations can change.
1387 |
1388 | * Prefer double quotation marks for denoting strings.
1389 |
1390 | ``` js
1391 | function getFullName( string firstname = "", string lastname = "" ){
1392 | return "#arguments.lastname#, #arguments.firstname#";
1393 | }
1394 | ```
1395 |
1396 | **[[⬆]](#TOC)**
1397 |
1398 | ## ColdBox Specific Best Practices
1399 |
1400 | * Leverage the `rc and prc` scopes directly instead of referencing the `event` object unless you need default values
1401 | * Leverage `var` or `local` scope in the event handlers if those variables will NOT be used in layouts/views
1402 | * Leverage the `prc` for data set/read safely within your application. Incoming data through the `rc` is NEVER to be trusted. This should remain as what a client sent into a request.
1403 | * Do not mix `local` scope usage and `var` scope declared variables in your handlers. PICK ONE approach.
1404 | * Do not create dual performing actions that respond to different HTTP verbs. Like a `list()` action that lists and saves to the database in a post. Create two actions, two concerns.
1405 | * Always always always leverage injection via WireBox
1406 | * Remember that all event handlers are singletons
1407 |
1408 | **[[⬆]](#TOC)**
1409 |
--------------------------------------------------------------------------------
/guides/css-sass.md:
--------------------------------------------------------------------------------
1 | # Airbnb CSS / Sass Styleguide
2 |
3 | *A mostly reasonable approach to CSS and Sass*
4 |
5 | ## Table of Contents
6 |
7 | 1. [Terminology](#terminology)
8 | - [Rule Declaration](#rule-declaration)
9 | - [Selectors](#selectors)
10 | - [Properties](#properties)
11 | 1. [CSS](#css)
12 | - [Formatting](#formatting)
13 | - [Comments](#comments)
14 | - [OOCSS and BEM](#oocss-and-bem)
15 | - [ID Selectors](#id-selectors)
16 | - [JavaScript hooks](#javascript-hooks)
17 | - [Border](#border)
18 | 1. [Sass](#sass)
19 | - [Syntax](#syntax)
20 | - [Ordering](#ordering-of-property-declarations)
21 | - [Variables](#variables)
22 | - [Mixins](#mixins)
23 | - [Extend directive](#extend-directive)
24 | - [Nested selectors](#nested-selectors)
25 | 1. [Translation](#translation)
26 | 1. [License](#license)
27 |
28 | ## Terminology
29 |
30 | ### Rule declaration
31 |
32 | A “rule declaration” is the name given to a selector (or a group of selectors) with an accompanying group of properties. Here's an example:
33 |
34 | ```css
35 | .listing {
36 | font-size: 18px;
37 | line-height: 1.2;
38 | }
39 | ```
40 |
41 | ### Selectors
42 |
43 | In a rule declaration, “selectors” are the bits that determine which elements in the DOM tree will be styled by the defined properties. Selectors can match HTML elements, as well as an element's class, ID, or any of its attributes. Here are some examples of selectors:
44 |
45 | ```css
46 | .my-element-class {
47 | /* ... */
48 | }
49 | [aria-hidden] {
50 | /* ... */
51 | }
52 | ```
53 |
54 | ### Properties
55 |
56 | Finally, properties are what give the selected elements of a rule declaration their style. Properties are key-value pairs, and a rule declaration can contain one or more property declarations. Property declarations look like this:
57 |
58 | ```css
59 | /* some selector */ {
60 | background: #f1f1f1;
61 | color: #333;
62 | }
63 | ```
64 |
65 | **[⬆ back to top](#table-of-contents)**
66 |
67 | ## CSS
68 |
69 | ### Formatting
70 |
71 | * Use tabs for indentation.
72 | * Prefer dashes over camelCasing in class names.
73 | - Underscores and PascalCasing are okay if you are using BEM (see [OOCSS and BEM](#oocss-and-bem) below).
74 | * Avoid ID selectors if at all possible.
75 | * When using multiple selectors in a rule declaration, give each selector its own line.
76 | * Put a space before the opening brace `{` in rule declarations.
77 | * In properties, put a space after, but not before, the `:` character.
78 | * Put closing braces `}` of rule declarations on a new line.
79 | * Put blank lines between rule declarations.
80 |
81 | **Bad**
82 |
83 | ```css
84 | .avatar{
85 | border-radius:50%;
86 | border:2px solid white; }
87 | .no, .nope, .not_good {
88 | // ...
89 | }
90 | #lol-no {
91 | // ...
92 | }
93 | ```
94 |
95 | **Good**
96 |
97 | ```css
98 | .avatar {
99 | border-radius: 50%;
100 | border: 2px solid white;
101 | }
102 | .one,
103 | .selector,
104 | .per-line {
105 | // ...
106 | }
107 | ```
108 |
109 | ### Comments
110 |
111 | * Prefer line comments (`//` in Sass-land) to block comments.
112 | * Prefer comments on their own line. Avoid end-of-line comments.
113 | * Write detailed comments for code that isn't self-documenting:
114 | - Uses of z-index
115 | - Compatibility or browser-specific hacks
116 |
117 | ### OOCSS and BEM
118 |
119 | We encourage some combination of OOCSS and BEM for these reasons:
120 |
121 | * It helps create clear, strict relationships between CSS and HTML
122 | * It helps us create reusable, composable components
123 | * It allows for less nesting and lower specificity
124 | * It helps in building scalable stylesheets
125 |
126 | **OOCSS**, or “Object Oriented CSS”, is an approach for writing CSS that encourages you to think about your stylesheets as a collection of “objects”: reusable, repeatable snippets that can be used independently throughout a website.
127 |
128 | * Nicole Sullivan's [OOCSS wiki](https://github.com/stubbornella/oocss/wiki)
129 | * Smashing Magazine's [Introduction to OOCSS](http://www.smashingmagazine.com/2011/12/12/an-introduction-to-object-oriented-css-oocss/)
130 |
131 | **BEM**, or “Block-Element-Modifier”, is a _naming convention_ for classes in HTML and CSS. It was originally developed by Yandex with large codebases and scalability in mind, and can serve as a solid set of guidelines for implementing OOCSS.
132 |
133 | * CSS Trick's [BEM 101](https://css-tricks.com/bem-101/)
134 | * Harry Roberts' [introduction to BEM](http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/)
135 |
136 | We recommend a variant of BEM with PascalCased “blocks”, which works particularly well when combined with components (e.g. React). Underscores and dashes are still used for modifiers and children.
137 |
138 | **Example**
139 |
140 | ```jsx
141 | // ListingCard.jsx
142 | function ListingCard() {
143 | return (
144 |
145 |
Adorable 2BR in the sunny Mission
146 |
147 |
Vestibulum id ligula porta felis euismod semper.
148 |
149 |
150 | );
151 | }
152 | ```
153 |
154 | ```css
155 | /* ListingCard.css */
156 | .ListingCard { }
157 | .ListingCard--featured { }
158 | .ListingCard__title { }
159 | .ListingCard__content { }
160 | ```
161 |
162 | * `.ListingCard` is the “block” and represents the higher-level component
163 | * `.ListingCard__title` is an “element” and represents a descendant of `.ListingCard` that helps compose the block as a whole.
164 | * `.ListingCard--featured` is a “modifier” and represents a different state or variation on the `.ListingCard` block.
165 |
166 | ### ID selectors
167 |
168 | While it is possible to select elements by ID in CSS, it should generally be considered an anti-pattern. ID selectors introduce an unnecessarily high level of [specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) to your rule declarations, and they are not reusable.
169 |
170 | For more on this subject, read [CSS Wizardry's article](http://csswizardry.com/2014/07/hacks-for-dealing-with-specificity/) on dealing with specificity.
171 |
172 | ### JavaScript hooks
173 |
174 | Avoid binding to the same class in both your CSS and JavaScript. Conflating the two often leads to, at a minimum, time wasted during refactoring when a developer must cross-reference each class they are changing, and at its worst, developers being afraid to make changes for fear of breaking functionality.
175 |
176 | We recommend creating JavaScript-specific classes to bind to, prefixed with `.js-`:
177 |
178 | ```html
179 |
180 | ```
181 |
182 | ### Border
183 |
184 | Use `0` instead of `none` to specify that a style has no border.
185 |
186 | **Bad**
187 |
188 | ```css
189 | .foo {
190 | border: none;
191 | }
192 | ```
193 |
194 | **Good**
195 |
196 | ```css
197 | .foo {
198 | border: 0;
199 | }
200 | ```
201 | **[⬆ back to top](#table-of-contents)**
202 |
203 | ## Sass
204 |
205 | ### Syntax
206 |
207 | * Order your regular CSS and `@include` declarations logically (see below)
208 |
209 | ### Ordering of property declarations
210 |
211 | 1. Property declarations
212 |
213 | List all standard property declarations, anything that isn't an `@include` or a nested selector.
214 |
215 | ```scss
216 | .btn-green {
217 | background: green;
218 | font-weight: bold;
219 | // ...
220 | }
221 | ```
222 |
223 | 2. `@include` declarations
224 |
225 | Grouping `@include`s at the end makes it easier to read the entire selector.
226 |
227 | ```scss
228 | .btn-green {
229 | background: green;
230 | font-weight: bold;
231 | @include transition(background 0.5s ease);
232 | // ...
233 | }
234 | ```
235 |
236 | 3. Nested selectors
237 |
238 | Nested selectors, _if necessary_, go last, and nothing goes after them. Add whitespace between your rule declarations and nested selectors, as well as between adjacent nested selectors. Apply the same guidelines as above to your nested selectors.
239 |
240 | ```scss
241 | .btn {
242 | background: green;
243 | font-weight: bold;
244 | @include transition(background 0.5s ease);
245 | .icon {
246 | margin-right: 10px;
247 | }
248 | }
249 | ```
250 |
251 | ### Variables
252 |
253 | Prefer dash-cased variable names (e.g. `$my-variable`) over camelCased or snake_cased variable names. It is acceptable to prefix variable names that are intended to be used only within the same file with an underscore (e.g. `$_my-variable`).
254 |
255 | ### Mixins
256 |
257 | Mixins should be used to DRY up your code, add clarity, or abstract complexity--in much the same way as well-named functions. Mixins that accept no arguments can be useful for this, but note that if you are not compressing your payload (e.g. gzip), this may contribute to unnecessary code duplication in the resulting styles.
258 |
259 | ### Extend directive
260 |
261 | `@extend` should be avoided because it has unintuitive and potentially dangerous behavior, especially when used with nested selectors. Even extending top-level placeholder selectors can cause problems if the order of selectors ends up changing later (e.g. if they are in other files and the order the files are loaded shifts). Gzipping should handle most of the savings you would have gained by using `@extend`, and you can DRY up your stylesheets nicely with mixins.
262 |
263 | ### Nested selectors
264 |
265 | **Do not nest selectors more than three levels deep!**
266 |
267 | ```scss
268 | .page-container {
269 | .content {
270 | .profile {
271 | // STOP!
272 | }
273 | }
274 | }
275 | ```
276 |
277 | When selectors become this long, you're likely writing CSS that is:
278 |
279 | * Strongly coupled to the HTML (fragile) *—OR—*
280 | * Overly specific (powerful) *—OR—*
281 | * Not reusable
282 |
283 |
284 | Again: **never nest ID selectors!**
285 |
286 | If you must use an ID selector in the first place (and you should really try not to), they should never be nested. If you find yourself doing this, you need to revisit your markup, or figure out why such strong specificity is needed. If you are writing well formed HTML and CSS, you should **never** need to do this.
287 |
288 | **[⬆ back to top](#table-of-contents)**
289 |
290 | ## Translation
291 |
292 | This style guide is also available in other languages:
293 |
294 | -  **Bahasa Indonesia**: [mazipan/css-style-guide](https://github.com/mazipan/css-style-guide)
295 | -  **Chinese (Traditional)**: [ArvinH/css-style-guide](https://github.com/ArvinH/css-style-guide)
296 | -  **Chinese (Simplified)**: [Zhangjd/css-style-guide](https://github.com/Zhangjd/css-style-guide)
297 | -  **French**: [mat-u/css-style-guide](https://github.com/mat-u/css-style-guide)
298 | -  **Georgian**: [DavidKadaria/css-style-guide](https://github.com/davidkadaria/css-style-guide)
299 | -  **Japanese**: [nao215/css-style-guide](https://github.com/nao215/css-style-guide)
300 | -  **Korean**: [CodeMakeBros/css-style-guide](https://github.com/CodeMakeBros/css-style-guide)
301 | -  **Portuguese (Brazil)**: [felipevolpatto/css-style-guide](https://github.com/felipevolpatto/css-style-guide)
302 | -  **Portuguese (Portugal)**: [SandroMiguel/airbnb-css-style-guide](https://github.com/SandroMiguel/airbnb-css-style-guide)
303 | -  **Russian**: [rtplv/airbnb-css-ru](https://github.com/rtplv/airbnb-css-ru)
304 | -  **Spanish**: [ismamz/guia-de-estilo-css](https://github.com/ismamz/guia-de-estilo-css)
305 | -  **Vietnamese**: [trungk18/css-style-guide](https://github.com/trungk18/css-style-guide)
306 | -  **Italian**: [antoniofull/linee-guida-css](https://github.com/antoniofull/linee-guida-css)
307 | -  **German**: [tderflinger/css-styleguide](https://github.com/tderflinger/css-styleguide)
308 |
309 | **[⬆ back to top](#table-of-contents)**
310 |
311 | ## License
312 |
313 | (The MIT License)
314 |
315 | Copyright (c) 2015 Airbnb
316 |
317 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
318 |
319 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
320 |
321 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
322 |
323 | **[⬆ back to top](#table-of-contents)**
--------------------------------------------------------------------------------
/guides/database.md:
--------------------------------------------------------------------------------
1 | # Ortus Database Naming Conventions
2 |
3 |
4 | A naming convention is important when working with databases in order to provide a clear structure and format; especially in team environments. By using these conventions the database can be understood by anyone applying these conventions; thus increasing maintainability.
5 |
6 | At Ortus, our preference is to levarage Hibernate ORM with additional SQL additions.
7 |
8 | ## Table of Contents
9 |
10 | 1. [General Conventions](#general)
11 | 1. [Table Conventions](#tables)
12 | 1. [Column Conventions](#columns)
13 | 1. [Index Conventions](#indexes)
14 | 1. [View Conventions](#views)
15 |
16 |
17 | ## General Conventions
18 |
19 | - All names should be in camelcase with the first letter in lower case and should match their respective ORM objects.
20 |
21 | ```
22 | -- DO THIS --
23 | user
24 | permision
25 | userPermission
26 |
27 | -- NOT THIS --
28 | User
29 | Permission
30 | User_Permission
31 | user_permission
32 | ```
33 |
34 | - Separate name parts by using camel case and NOT underscores or spaces. This provides better readibility and you will not have to use quotes when doing SQL statements. Look at example in the previous point.
35 | - Prefixes or namespaces are the ONLY parts of names that should be separated by underscores. This defines a clear separation between names and areas.
36 |
37 | ```
38 | -- DO THIS --
39 | blog_user
40 | blog_userPermission
41 |
42 | -- NOT THIS --
43 | BlogUser
44 | BlogUserPermission
45 | Blog_UserPermission
46 | ```
47 |
48 | - Do not use numbers in names. This is poor design, indicating divided table structures.
49 | - Do not use dot (`.`) separator between names, remember use camel casing. This way you will avoid problems when doing SQL statements as fields are accessed using dot notation.
50 | - It goes without saying, do not use reserved database words in any name.
51 | - Always try to use names that make sense and are descriptive of their purpose.
52 | - Avoid abbreviations whenever possible. ONLY use abbreviations that are well known and documented.
53 | - Avoid acronyms whenever possible. Only use acronyms that are well known and documented. Also, they should all be in uppercase if used.
54 |
55 | ```
56 | -- DO THIS --
57 | HTTPRequests
58 | savedURL
59 |
60 | -- NOT THIS --
61 | http_requests
62 | httprequests
63 | savedurl
64 | saved_url
65 | ```
66 |
67 |
68 | **[[⬆]](#TOC)**
69 |
70 | ## Table Conventions
71 |
72 | - Tables are usually entities you are modeling for persistence. So make sure the names are in proper English and carry natural meanings. These names should make sense and should be descriptive.
73 | - Avoid acronyms and abbreviations if at all possible. If acronyms are used, then make sure to capitalize them. Abbreviations used should be well known abbreviations and should be camel cased.
74 | - Avoid using plural names for tables, use singular forms. This will avoid errors due to pluralization of words and also when moving table design to objects or entities. The name should map to the entity it is modeling.
75 |
76 | ```
77 | -- DO THIS --
78 | blog_user
79 | blog_page
80 | person
81 | box
82 | activity
83 |
84 | -- NOT THIS --
85 | blog_users
86 | blog_pages
87 | people
88 | boxes
89 | activities
90 | ```
91 |
92 | - Use namespaces for tables whenever grouping is needed. This grouping is a clear separation when working with the tables and can also provide a good basis for security, as you could secure via the namespace. Namespaces should be separated by anunderscore and then the name should be camel cased.
93 |
94 | ```
95 | -- DO THIS --
96 | lookups_country
97 | lookups_state
98 | lookups_regionalOffice
99 | hr_employee
100 | hr_salary
101 | is_employee
102 | is_vacationDay
103 |
104 | -- NOT THIS --
105 | LookupsCountry
106 | lookupsState
107 | LOOKUPS_RegionalOffice
108 | HREmployee
109 | ISEmployee
110 | ISVacationDay
111 | ```
112 |
113 | * Do not use prefixes like `tbl,db` as they are EXTREMELY redundant and useless.
114 | * All tables should have at least ONE primary key.
115 |
116 |
117 | **[[⬆]](#TOC)**
118 |
119 | ## Column Conventions
120 |
121 | * Columns are usually attributes of an entity you are modeling via a table. So make sure the names are in proper English and carry natural meanings. These names should make sense and should be descriptive.
122 | * Avoid acronyms and abbreviations if at all possible. If acronyms are used, then make sure to capitalize them. Abbreviations used should be well known abbreviations and should be camel cased.
123 | * Get used to naming primary or foreign keys with an `ID` identifier suffix. DO NOT use the column name `id` to identify a primary key. Be more descriptive, usually looking at the table name.
124 |
125 | ```
126 | -- DO THIS --
127 | userID
128 | userPermissionID
129 |
130 | -- NOT THIS --
131 | id
132 | userid
133 | upid
134 | ```
135 |
136 | * Foreign keys should be prefixed with a capitalized `FK_` in order to visually denote relationships and also to avoid ambigous table selects. After the `FK_` the name of the column must comply with our naming conventions.
137 | ```
138 | -- DO THIS --
139 | FK_userID
140 |
141 | -- NOT THIS --
142 | fkuserid
143 | userID
144 | ```
145 |
146 | * Boolean columns should use the `is` prefix.
147 | ```
148 | -- DO THIS --
149 | isActive
150 | isSold
151 |
152 | -- NOT THIS --
153 | active
154 | sold
155 | ```
156 |
157 | * Date columns should be suffixed in camel case with the word `Date`.
158 | ```
159 | -- DO THIS --
160 | createdDate
161 | updatedDate
162 |
163 | -- NOT THIS --
164 | date_created
165 | date_updated
166 | ```
167 |
168 |
169 | **[[⬆]](#TOC)**
170 |
171 | ## Index Conventions
172 |
173 | * Always prefix all index names with `idx_` to distinguish it as an index.
174 | * The names of the index should at least convey the columns it reaches or at least the purpose of the index.
175 |
176 | **[[⬆]](#TOC)**
177 |
178 | ## Views Conventions
179 |
180 | * Always try to use names that make sense and are descriptive for the views. Avoid acronyms and abbreviations if at all possible. If acronyms are used, then make sure to capitalize them. Abbreviations used should be well known abbreviations and should be camel cased.
181 | * All views should be prefixed with `vw_` in order to distinguish them in SQL statements from regular database tables.
182 |
183 | **[[⬆]](#TOC)**
184 |
--------------------------------------------------------------------------------
/guides/do-this-not-this-table.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ✅ DO THIS
5 |
6 |
7 | ❌ NOT THIS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/guides/security.md:
--------------------------------------------------------------------------------
1 | # Ortus Security Guidelines
2 |
3 |
4 | This guide delineates some best practices when dealing with SQL injection attempts or just plain old URL/FORM variable manipulations, when building ColdFusion web applications.
5 |
6 | ## Table of Contents
7 |
8 | 1. [HTTP Methods](#http_methods)
9 | 1. [Protecting Your Code](#protecting_code)
10 |
11 | ## Golden Rule of Web Applications
12 | > Never ever ever trust the incoming data. It is YOUR responsibility to protect your code.
13 |
14 | ## Understanding The HTTP Methods
15 |
16 | First of all, you also need to understand what a POST, GET, DELETE, PUT are used for. The method attribute of the `FORM` element specifies the HTTP method used to send the form to the processing agent. This attribute may take the following values:
17 |
18 | * `GET` : With the HTTP `GET` method, the form data set is appended to the URI specified by the action attribute (with a question-mark (`?`) as separator) and this new URI is sent to the processing agent.
19 | * `POST,PUT,DELETE` : The form data set is included in the body of the form and sent to the processing agent, with expectations of either a save, update or delete.
20 |
21 | The `GET` method should be used when the form is **idempotent** (i.e., causes no side-effects). Many database searches have no visible side effects and make ideal applications for the `GET` method. If the service associated with the processing of a form causes side effects (for example, if the form modifies a database or subscription to a service), the `POST,PUT, or DELETE` method should be used.
22 |
23 | The most important fact is that the `GET` method should be used for idempotent transactions. Here is the definition for idempotent:
24 |
25 |
26 | "Idempotent operation means that it can be repeated without causing any errors or inconsistencies if the operation is carried out once or many times".
27 |
28 |
29 | Thanks to Roger Benningfield:
30 |
31 |
32 | "Allowing GET requests to change the state of server resources can be a very dangerous game, without so much as a whiff of malicious behavior. An app that allows clients to change or delete data just by fetching a URI is asking for trouble in 2020."
33 |
34 |
35 |
36 | There is a time for using `GET` and a time for using `POST,PUT,DELETE` and **NONE OF THEM should trust the client data**.
37 |
38 | **[[⬆]](#TOC)**
39 |
40 | ## Protecting Your Code
41 |
42 | As for security, FORM variables are just as easy to modify as URL variables. However, there are several ways to protect from attacks, SQL injection or plain mischief:
43 |
44 | * `` tag with strict data-type and scaling will prevent URL and FORM variable abuse. This tag binds incoming FORM or URL variables to specific types and even create default values for them.
45 | * Use of `` is the most common form of stopping URL/FORM variable abuse with direct SQL and it makes your queries faster as well (If your db supports it). Use this tag to protect any part of your SQL statements that come from an external source, even `ORDER BY` or `GROUP BY` statements.
46 | * Get into the habit of adding the `maxlength` attribute to `cfqueryparam`, to limit the number of characters/digits to bind a column with.
47 | * Use of Stored Procedures will prevent SQL injection as all variables are binded by the use of ``.
48 | * Try to always use a custom error page that cannot display to the user the entire error message. This will hide your internal information and encapsulate your errors.
49 | * It is the role of the developer to protect the database and its contents, no matter if you are using a POST or a GET.
50 | * Do not trust the client on the incoming data; always do data type checking and authorization/authentication checking on the server-side.
51 |
52 | **[[⬆]](#TOC)**
53 |
--------------------------------------------------------------------------------
/linters/.cflintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rule": [],
3 | "includes": [
4 | { "code": "AVOID_USING_CFINCLUDE_TAG" },
5 | { "code": "AVOID_USING_CFABORT_TAG" },
6 | { "code": "AVOID_USING_CFEXECUTE_TAG" },
7 | { "code": "AVOID_USING_DEBUG_ATTR" },
8 | { "code": "AVOID_USING_ABORT" },
9 | { "code": "AVOID_USING_ISDATE" },
10 | { "code": "AVOID_USING_ISDEBUGMODE" },
11 | { "code": "AVOID_USING_CFINSERT_TAG" },
12 | { "code": "AVOID_USING_CFUPDATE_TAG" },
13 | { "code": "ARG_VAR_CONFLICT" },
14 | { "code": "ARG_HINT_MISSING" },
15 | { "code": "ARG_HINT_MISSING_SCRIPT" },
16 | { "code" : "ARGUMENT_INVALID_NAME" },
17 | { "code" : "ARGUMENT_ALLCAPS_NAME" },
18 | { "code" : "ARGUMENT_TOO_WORDY" },
19 | { "code" : "ARGUMENT_IS_TEMPORARY" },
20 | { "code": "CFQUERYPARAM_REQ" },
21 | { "code": "COMPARE_INSTEAD_OF_ASSIGN" },
22 | { "code": "COMPONENT_HINT_MISSING" },
23 | { "code" : "COMPONENT_INVALID_NAME" },
24 | { "code" : "COMPONENT_ALLCAPS_NAME" },
25 | { "code" : "COMPONENT_TOO_SHORT" },
26 | { "code" : "COMPONENT_TOO_LONG" },
27 | { "code" : "COMPONENT_TOO_WORDY" },
28 | { "code" : "COMPONENT_IS_TEMPORARY" },
29 | { "code" : "COMPONENT_HAS_PREFIX_OR_POSTFIX" },
30 | { "code": "COMPLEX_BOOLEAN_CHECK" },
31 | { "code": "EXCESSIVE_ARGUMENTS" },
32 | { "code": "EXCESSIVE_FUNCTIONS" },
33 | { "code": "EXPLICIT_BOOLEAN_CHECK" },
34 | { "code": "FUNCTION_TOO_COMPLEX" },
35 | { "code": "FUNCTION_HINT_MISSING" },
36 | { "code": "FILE_SHOULD_START_WITH_LOWERCASE" },
37 | { "code": "LOCAL_LITERAL_VALUE_USED_TOO_OFTEN" },
38 | { "code": "GLOBAL_LITERAL_VALUE_USED_TOO_OFTEN" },
39 | { "code": "MISSING_VAR" },
40 | { "code" : "METHOD_INVALID_NAME" },
41 | { "code" : "METHOD_ALLCAPS_NAME" },
42 | { "code" : "METHOD_IS_TEMPORARY" },
43 | { "code": "NESTED_CFOUTPUT" },
44 | { "code": "NEVER_USE_QUERY_IN_CFM" },
45 | { "code": "OUTPUT_ATTR" },
46 | { "code" : "QUERYPARAM_REQ" },
47 | { "code": "UNUSED_LOCAL_VARIABLE" },
48 | { "code": "UNUSED_METHOD_ARGUMENT" },
49 | { "code": "SQL_SELECT_STAR" },
50 | { "code": "SCOPE_ALLCAPS_NAME" },
51 | { "code": "VAR_ALLCAPS_NAME" },
52 | { "code": "VAR_INVALID_NAME" },
53 | { "code": "VAR_TOO_WORDY" }
54 | ],
55 | "inheritParent": false,
56 | "parameters": {
57 | "TooManyFunctionsChecker.maximum" : 50
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/linters/.cflintrc-handlers:
--------------------------------------------------------------------------------
1 | {
2 | "rule": [],
3 | "includes": [
4 | { "code": "AVOID_USING_STRUCTNEW" },
5 | { "code": "AVOID_USING_ARRAYNEW" },
6 | { "code": "AVOID_USING_CFINCLUDE_TAG" },
7 | { "code": "AVOID_USING_CFABORT_TAG" },
8 | { "code": "AVOID_USING_CFEXECUTE_TAG" },
9 | { "code": "AVOID_USING_DEBUG_ATTR" },
10 | { "code": "AVOID_USING_CREATEOBJECT" },
11 | { "code": "AVOID_USING_ABORT" },
12 | { "code": "AVOID_USING_ISDATE" },
13 | { "code": "AVOID_USING_ISDEBUGMODE" },
14 | { "code": "AVOID_USING_CFINSERT_TAG" },
15 | { "code": "AVOID_USING_CFUPDATE_TAG" },
16 | { "code": "ARG_VAR_CONFLICT" },
17 | { "code": "ARG_VAR_MIXED" },
18 | { "code" : "ARGUMENT_INVALID_NAME" },
19 | { "code" : "ARGUMENT_TOO_WORDY" },
20 | { "code" : "ARGUMENT_IS_TEMPORARY" },
21 | { "code": "CFQUERYPARAM_REQ" },
22 | { "code": "COMPARE_INSTEAD_OF_ASSIGN" },
23 | { "code": "COMPONENT_HINT_MISSING" },
24 | { "code" : "COMPONENT_INVALID_NAME" },
25 | { "code" : "COMPONENT_ALLCAPS_NAME" },
26 | { "code" : "COMPONENT_TOO_SHORT" },
27 | { "code" : "COMPONENT_TOO_LONG" },
28 | { "code" : "COMPONENT_TOO_WORDY" },
29 | { "code" : "COMPONENT_IS_TEMPORARY" },
30 | { "code" : "COMPONENT_HAS_PREFIX_OR_POSTFIX" },
31 | { "code": "COMPLEX_BOOLEAN_CHECK" },
32 | { "code": "EXCESSIVE_FUNCTION_LENGTH" },
33 | { "code": "EXCESSIVE_COMPONENT_LENGTH" },
34 | { "code": "EXCESSIVE_ARGUMENTS" },
35 | { "code": "EXCESSIVE_FUNCTIONS" },
36 | { "code": "EXPLICIT_BOOLEAN_CHECK" },
37 | { "code": "FUNCTION_TOO_COMPLEX" },
38 | { "code": "FUNCTION_HINT_MISSING" },
39 | { "code": "FILE_SHOULD_START_WITH_LOWERCASE" },
40 | { "code": "MISSING_VAR" },
41 | { "code" : "METHOD_ALLCAPS_NAME" },
42 | { "code" : "METHOD_IS_TEMPORARY" },
43 | { "code": "NESTED_CFOUTPUT" },
44 | { "code": "NEVER_USE_QUERY_IN_CFM" },
45 | { "code": "OUTPUT_ATTR" },
46 | { "code" : "QUERYPARAM_REQ" },
47 | { "code": "UNUSED_LOCAL_VARIABLE" },
48 | { "code": "SQL_SELECT_STAR" },
49 | { "code": "SCOPE_ALLCAPS_NAME" },
50 | { "code": "VAR_ALLCAPS_NAME" },
51 | { "code": "VAR_TOO_WORDY" },
52 | { "code": "VAR_IS_TEMPORARY" }
53 | ],
54 | "inheritParent": false,
55 | "parameters": {
56 | "TooManyFunctionsChecker.maximum" : 20
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/linters/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = false
10 | indent_style = tab
11 | indent_size = 4
12 | tab_width = 4
13 |
14 | [*.yml]
15 | indent_style = space
16 | indent_size = 2
17 |
18 | [*.{md,markdown}]
19 | trim_trailing_whitespace = false
20 | insert_final_newline = false
--------------------------------------------------------------------------------
/linters/.eslintrc.json:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 |
4 | parserOptions: {
5 | parser: "babel-eslint",
6 | sourceType: "module"
7 | },
8 |
9 | env: {
10 | "browser": true,
11 | "es6" : true
12 | },
13 |
14 | extends: [
15 | "prettier",
16 | // Uncomment any of the lines below to choose desired strictness,
17 | // but leave only one uncommented!
18 | // See https://eslint.vuejs.org/rules/#available-rules
19 | // "plugin:vue/essential" // Priority A: Essential (Error Prevention)
20 | "plugin:vue/strongly-recommended" // Priority B: Strongly Recommended (Improving Readability)
21 | // "plugin:vue/recommended" // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
22 | ],
23 |
24 | // required to lint *.vue files
25 | plugins: [
26 | "vue"
27 | ],
28 |
29 | globals: {
30 | "ga": true, // Google Analytics
31 | "cordova": true,
32 | "__statics": true,
33 | "process": true,
34 | "Capacitor": true,
35 | "chrome": true
36 | },
37 |
38 | // add your custom rules here
39 | rules: {
40 | "array-bracket-spacing": ["error", "always", {
41 | "singleValue": true,
42 | "arraysInArrays": true,
43 | "objectsInArrays": true
44 | }],
45 | "array-bracket-newline" : [ "error", {
46 | "multiline" : true
47 | } ],
48 | "array-element-newline" : [ "error",
49 | { "multiline": true, "minItems": 2 }
50 | ],
51 | "camelcase" : [ "error" , {
52 | "properties" : "always"
53 | }],
54 | "indent": ["error", "tab", {
55 | ignoredNodes: ["TemplateLiteral"]
56 | }],
57 | "keyword-spacing": ["error", { "after": true, "before": true }],
58 | "key-spacing": ["error", {
59 | "singleLine": {
60 | "beforeColon": false,
61 | "afterColon": true
62 | },
63 | "multiLine": {
64 | "beforeColon": true,
65 | "afterColon": true,
66 | "align": "colon"
67 | }
68 | }],
69 | "no-trailing-spaces": ["error", {
70 | "skipBlankLines": false,
71 | "ignoreComments": false
72 | }],
73 | "no-fallthrough" : "error",
74 | // allow debugger during development only
75 | "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
76 | "object-curly-newline" : [ "error", { "multiline" : true } ],
77 | "object-curly-spacing": ["error", "always", {
78 | "objectsInObjects": true,
79 | "arraysInObjects": true
80 | }],
81 | "object-property-newline" : [ "error", { "allowAllPropertiesOnSameLine" : true } ],
82 | "prefer-promise-reject-errors": "off",
83 | "quotes" : [ "error", "double" ],
84 | "semi": ["error", "always"],
85 | "space-in-parens": ["error", "always"],
86 | "space-before-function-paren": ["error", {
87 | "anonymous": "never",
88 | "named": "never",
89 | "asyncArrow": "never"
90 | }],
91 | "vue/html-indent": ["error", "tab"],
92 | "vue/html-self-closing": [ "error", {
93 | "html": {
94 | "void": "any",
95 | "normal": "always",
96 | "component": "always"
97 | }
98 | } ]
99 | }
100 | }
--------------------------------------------------------------------------------
/linters/.jsbeautifyrc:
--------------------------------------------------------------------------------
1 | {
2 | "beautify.language": {
3 | "js": ["js","json","cfc"],
4 | "css": ["css", "scss"],
5 | "html": ["htm", "html", "cfml", "cfm"]
6 | },
7 | "brace_style": "collapse",
8 | "indent_with_tabs": true,
9 | "indent_size": 4,
10 | "indent_level": 0,
11 | "preserve_newlines": true,
12 | "max_preserve_newlines": 5,
13 | "html": {
14 | "allowed_file_extensions": ["htm", "html", "xhtml", "shtml", "xml", "svg", "cfm", "cfml"],
15 | "indent_scripts": "keep",
16 | "indent_inner_html": true,
17 | "indent_body_inner_html": true,
18 | "indent_handlebars": true,
19 | "unformatted": ["code", "pre"],
20 | "content_unformatted": ["pre", "code"],
21 | "wrap_line_length": 0
22 | },
23 | "css": {
24 | "selector_separator_newline": true
25 | },
26 | "js": {
27 | "break_chained_methods": true,
28 | "comma_first": false,
29 | "e4x": false,
30 | "jslint_happy": true,
31 | "keep_function_indentation": true,
32 | "keep_array_indentation": true,
33 | "space_after_anon_function": false,
34 | "spaceBeforeConditional": true,
35 | "space_in_paren": true,
36 | "space_in_empty_paren": false,
37 | "space_before_conditional": true,
38 | "operator_position": "before-newline",
39 | "unescape_strings": false,
40 | "wrap_line_length": 0
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/linters/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise": true,
3 | "curly": true,
4 | "eqeqeq": true,
5 | "eqnull": true,
6 | "browser": true,
7 | "devel": true,
8 | "sub": true,
9 | "noarg": true,
10 | "node": true,
11 | "latedef": true,
12 | "unused": true,
13 | "esversion": 6,
14 | "globals": {
15 | "jQuery": true,
16 | "$": true,
17 | "module": true,
18 | "angular": true
19 | }
20 | }
--------------------------------------------------------------------------------
/linters/.sass-lint.yml:
--------------------------------------------------------------------------------
1 | severity: error
2 |
3 | linters:
4 |
5 | BorderZero:
6 | enabled: true
7 | convention: zero
8 |
9 | BemDepth:
10 | enabled: true
11 |
12 | DeclarationOrder:
13 | enabled: false
14 |
15 | ExtendDirective:
16 | enabled: true
17 |
18 | LeadingZero:
19 | enabled: false
20 |
21 | NameFormat:
22 | enabled: true
23 |
24 | PrivateNamingConvention:
25 | enabled: true
26 | prefix: _
27 |
28 | PropertySortOrder:
29 | enabled: false
30 |
31 | QualifyingElement:
32 | enabled: false
33 |
34 | SelectorFormat:
35 | enabled: true
36 | convention: hyphenated_BEM
37 | class_convention: ^(?!js-).*
38 | class_convention_explanation: should not be written in the form js-*
39 |
40 | SingleLinePerProperty:
41 | enabled: true
42 | allow_single_line_rule_sets: false
43 |
44 | StringQuotes:
45 | enabled: true
46 | style: double_quotes
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Ortus Coding Style Guides
2 |
3 |
4 |
5 | This repository includes all of the Ortus coding style guides, linter and formatting configurations. Read, collaborate and enjoy.
6 |
7 | ## Guides
8 |
9 | * [ColdFusion](guides/coldfusion.md)
10 | * [CSS-SASS](guides/css-sass.md)
11 | * [Database](guides/database.md)
12 | * [JavaScript](guides/javascript.md)
13 | * [Security](guides/security.md)
14 |
15 |
16 | ## Linters
17 |
18 | * [CFlint](linters/.cflintrc) - Leverages the cflint project (`box install commandbox-cflint`)
19 | * [CFlint ColdBox Handlers](linters/.cflintrc-handlers) - Specific linting of ColdBox Handlers
20 | * [Editorconfig](linters/.editorconfig) - Leverages the EditorConfig Plugins for your IDE
21 | * [ESLint](linters/.eslintrc.json) - ESLinting of JavaScript and Vue files.
22 | * [JSBeautify](linters/.jsbeautifyrc)
23 | * [JSHint](linters/.jshintrc)
24 | * [SASS](linters/.sass-lint.yml)
25 |
26 | ## Formatters
27 |
28 | * [ColdFusion - CFFormat](formatters/.cfformat.json)
29 | * [ColdFusion - Submlime](formatters/cfml_format.sublime-settings)
30 | * [Java - Eclipse/VSCode](formatters/ortus-java-style.xml)
31 |
32 |
33 | ## IDE Automatic Coding Standards
34 |
35 | We also provide ways to apply our formatting rules automatically via modern IDEs.
36 |
37 | ### CommandBox Formatting
38 |
39 | Start off by installing the cfformat CommandBox package: `box install commandbox-cfformat`. Then in the root of your application if you have a `box.json` open it. If you don't, then initialize your application as a CommandBox package: `box init`. Then open the file and look for a `scripts` section, if you don't have one, then add it. We will create three scripts to format your source code:
40 |
41 | * `format` : Format all the files/directories you want
42 | * `format:watch` : Start a watcher for all the files/directories you want and if a save is detected, automatically format the changed files.
43 | * `format:check` : Verifies if the watched files/directories adhere to your style guides.
44 |
45 | ```js
46 | scripts : {
47 | "format" : "cfformat run handlers/,interceptors/,models/,test-harness/tests/specs,ModuleConfig.cfc --overwrite",
48 | "format:watch" : "cfformat watch handlers/,interceptors/,models/,test-harness/tests/specs,ModuleConfig.cfc ./.cfformat.json",
49 | "format:check" : "cfformat check handlers/,interceptors/,models/,test-harness/tests/specs,ModuleConfig.cfc",
50 | }
51 | ```
52 |
53 | Then you can run a watcher: `box run-script format:watch` and everytime you save a change in the files being watched, the formatter will automatically format the CFML code.
54 |
55 |
56 | ### VSCode ESLint
57 |
58 | We are using ESLint as our standards for formatting and linting for JavaScript and Vue files. You can follow this guide to setup your VSCode editor for formatting and linting: [Setup VSCode](https://www.digitalocean.com/community/tutorials/linting-and-formatting-with-eslint-in-vs-code)
59 |
60 |
61 | ### Sublime
62 |
63 | If you use Sublime as your IDE, you can install the `CFML` package and use the built-in formatter to help you format CFML files according to our standards. Just open the **Format Settings** and paste in the [Sublime Settings](formatters/cfml_format.sublime-settings) contents. Then you can use the shortcut for it according to OS to execute it. You can read it here: https://github.com/jcberquist/sublimetext-cfml#code-formatting
64 |
65 | 
66 |
67 | The CFML Format operation is a manual command in Sublime by default. To make it automatic, install the "Hooks" (https://packagecontrol.io/packages/Hooks) plugin for Sublime and then add the following hook to your Syntax specific settings for CFML. To get to the Syntax specific settings, open a CFM or CFC file in Sublime then select the menu item Sublime Text > Preferences > Syntax - Specific Settings
68 |
69 | ```json
70 | // These settings override both User and Default settings for the cfml
71 | syntax
72 | {
73 | "on_pre_save_language": [
74 | {
75 | "command": "cfml_format",
76 | "args": {
77 | "current_method": false
78 | }, }
79 | ] }
80 | ```
81 |
82 |
83 | ---
84 |
85 | **Copyright Ortus Solutions Corp**
86 |
87 | If otherwise noted, this content is property of Ortus Solutions, Corp.
88 |
89 | > Soli Deo Gloria
90 |
--------------------------------------------------------------------------------
/resources/ortus-spaceman.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ortus-Solutions/coding-standards/f73c446f917264598c80531c89499df8573fc90a/resources/ortus-spaceman.jpg
--------------------------------------------------------------------------------
/resources/sublime-format-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ortus-Solutions/coding-standards/f73c446f917264598c80531c89499df8573fc90a/resources/sublime-format-settings.png
--------------------------------------------------------------------------------
/resources/vscode-beautify-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ortus-Solutions/coding-standards/f73c446f917264598c80531c89499df8573fc90a/resources/vscode-beautify-settings.png
--------------------------------------------------------------------------------