1604281120
The shorthand techniques of any programming language help you to write more clean and optimized code. Shorthand techniques improve readability of your code and you can achieve your goal with less coding. Let’s discuss some of the shorthand techniques of JavaScript one by one.
//Longhand
let x; let y = 20;
//Shorthand
let x, y = 20;
We can assign values to multiple variables in one line with array destructuring.
//Longhand
let a, b, c;
a = 5;
b = 8;
c = 12;
//Shorthand
let [a, b, c] = [5, 8, 12];
We can save 5 lines of code here with ternary (conditional) operator.
//Longhand
let number = 26;
let isEven;
if(number % 2){
isEven = true;
}else{
isEven = false;
}
//Shorthand
let isEven = number % 2 ? true : false;
We can use OR(||)
short circuit evaluation to assign a default value to a variable in case the expected value found empty.
//Longhand
let imagePath;
let path = getImagePath();
if(path !== null && path !== undefined && path !== '') {
imagePath = path;
} else {
imagePath = 'default.jpg';
}
//Shorthand
let imagePath = getImagePath() || 'default.jpg';
If you are calling a function only if a variable is true, then using AND(&&)
short circuit you can do it in a single line.
//Longhand
if (isLoggedin) {
goToHomepage();
}
//Shorthand
isLoggedin && goToHomepage();
Here in shorthand technique, if isLoggedin
returns true, then only goToHomepage()
will execute.
To swap two variables, we often use a third variable. We can swap two variables easily with array destructuring assignment.
let x = 'Hello', y = 55;
//Longhand
const temp = x;
x = y;
y = temp;
//Shorthand
[x, y] = [y, x];
//Longhand
function add(num1, num2) {
return num1 + num2;
}
//Shorthand
const add = (num1, num2) => num1 + num2;
We normally use + operator to concatenate string values with variables. With ES6 template literals we can do it in a more simple way.
//Longhand
console.log('You got a missed call from ' + number + ' at ' + time);
//Shorthand
console.log(`You got a missed call from ${number} at ${time}`);
For multiline string we normally use + operator with a new line escape sequence (\n). We can do it in an easier way by using backticks (`).
//Longhand
console.log('JavaScript, often abbreviated as JS, is a\n' + 'programming language that conforms to the \n' +
'ECMAScript specification. JavaScript is high-level,\n' +
'often just-in-time compiled, and multi-paradigm.' );
//Shorthand
console.log(`JavaScript, often abbreviated as JS, is a programming language that conforms to the ECMAScript specification. JavaScript is high-level, often just-in-time compiled, and multi-paradigm.`);
For multiple value matching, we can put all values in array and use indexOf()
method.
//Longhand
if (value === 1 || value === 'one' || value === 2 || value === 'two') {
// Execute some code
}
// Shorthand
if ([1, 'one', 2, 'two'].indexOf(value) >= 0) {
// Execute some code
}
If the variable name and object key name is same then we can just mention variable name in object literals instead of both key and value. JavaScript will automatically set the key same as variable name and assign the value as variable value.
let firstname = 'Amitav';
let lastname = 'Mishra';
//Longhand
let obj = {firstname: firstname, lastname: lastname};
//Shorthand
let obj = {firstname, lastname};
There are built in methods like parseInt
and parseFloat
available to convert a string to number. We can also do this by simply providing a unary operator (+) in front of string value.
//Longhand
let total = parseInt('453');
let average = parseFloat('42.6');
//Shorthand
let total = +'453';
let average = +'42.6';
To repeat a string for a specified number of time you can use a for
loop. But using the repeat()
method we can do it in a single line.
//Longhand
let str = '';
for(let i = 0; i < 5; i ++) {
str += 'Hello ';
}
console.log(str); // Hello Hello Hello Hello Hello
// Shorthand
'Hello '.repeat(5);
Tip: Want to apologize to someone by sending 100 times “sorry”? Try it with
_repeat()_
method. If you want to repeat each string in a new line, then add_\n_
to the string.
'sorry\n'.repeat(100);
We can use Math.pow()
method to find the power of a number. There is a shorter syntax to do it with double asterik (**).
//Longhand
const power = Math.pow(4, 3); // 64
// Shorthand
const power = 4**3; // 64
The double NOT bitwise operator is a substitute for Math.floor()
method.
//Longhand
const floor = Math.floor(6.8); // 6
// Shorthand
const floor = ~~6.8; // 6
We can use for loop to loop through each value of array and find the max or min value. We can also use the Array.reduce() method to find the max and min number in array.But using spread operator we can do it in a single line.
// Shorthand
const arr = [2, 8, 15, 4];
Math.max(...arr); // 15
Math.min(...arr); // 2
To loop through an array we normally use the traditional for
loop. We can make use of the for...of
loop to iterate through arrays. To access the index of each value we can use for...in
loop.
let arr = [10, 20, 30, 40];
//Longhand
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
//Shorthand
//for of loop
for (const val of arr) {
console.log(val);
}
//for in loop
for (const index in arr) {
console.log(arr[index]);
}
We can also loop through object properties using for...in
loop.
let obj = {x: 20, y: 50};
for (const key in obj) {
console.log(obj[key]);
}
let arr1 = [20, 30];
//Longhand
let arr2 = arr1.concat([60, 80]);
// [20, 30, 60, 80]
//Shorthand
let arr2 = [...arr1, 60, 80];
// [20, 30, 60, 80]
To deep clone a multi-level object, we can iterate through each property and check if the current property contains an object. If yes, then do a recursive call to the same function by passing the current property value (i.e. the nested object).We can also do it by using JSON.stringify()
and JSON.parse()
in a single line.
let obj = {x: 20, y: {z: 30}};
//Longhand
const makeDeepClone = (obj) => {
let newObject = {};
Object.keys(obj).map(key => {
if(typeof obj[key] === 'object'){
newObject[key] = makeDeepClone(obj[key]);
} else {
newObject[key] = obj[key];
}
});
return newObject;
}
const cloneObj = makeDeepClone(obj);
//Shorthand
const cloneObj = JSON.parse(JSON.stringify(obj));
let str = 'jscurious.com';
//Longhand
str.charAt(2); // c
//Shorthand
str[2]; // c
Thanks for reading!
This article was originally published on medium.com
You may also like: ☞ Top 35 JavaScript Shorthands for Beginners
#web-design #web-development #javascript #javascript-tips
1650154380
Serverless Env Generator Plugin
THIS FORK SUPPORTS ONLY SERVERLESS V2
This is a fork of serverless-env-generator with more advanced YAML anchor supporting. See extended description for Commands and YAML File Structure and see Key features of this fork.
This plugin automatically creates a .env file during deployment by merging environment variables from one or more YAML files. During runtime these variables can then be loaded into process.env using dotenv.
For a brief introduction, read our blogpost about introducing serverless-env-generator.
Please note that the uploaded .env file contains secrets in cleartext. Therefore we recommend to use Serverless Crypt for critical secrets. This tool aims to strike a balance between storing secrets in plaintext in Lambda environment variables and having to decrypt them at runtime using KMS.
Furthermore the tool does not support environment variables generated by Serverless. We recommend to set these variables directly in each functions configuration in serverless.yml.
When used with serverless-local-dev-server your environment variables are directly loaded into process.env. No .env file is created to make sure that your local development and deployment tasks do not interfere :-)
This package requires node >= 8.0. Due to the reliance on KMS, encryption is only supported for AWS.
The .env.local
file in the project root is here only for the tests.
Table of Contents
Requirements
Getting Started
npm install dotenv --save
npm install @redtea/serverless-env-generator --save-dev
See: https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html
Please make sure to create the KMS key in the same region as your deployment.
For aliases we recommend to use the service name, for administration privileges no user (your AWS account has full permissions by default) and for usage privileges "serverless-admin" to link access permissions to deployment permissions.
serverless.yml configuration example:
provider:
name: aws
runtime: nodejs14.x
functions:
hello:
handler: handler.hello
# Add @redtea/serverless-env-generator to your plugins:
plugins:
- '@redtea/serverless-env-generator'
# Plugin config goes into custom:
custom:
envFiles: #YAML files used to create .env file
- environment.yml
envEncryptionKeyId: #KMS Key used for encrypting values
dev: ${env:AWS_KMS_KEYID} #Key used for development-stage
As the generated .env file contains the secrets in cleartext, make sure that it will never be checked into git!
.gitignore code example:
.env
Command example:
serverless env --attribute name --value "This is not a secret"
serverless env --attribute secret_name --value "This is a secret" --encrypt
Note that the .env file is automatically created when you deploy your function, so you can just load those variables with dotenv 🎉
Code example:
require('dotenv').config() // Load variables from .env file
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: process.env.secret_name,
input: event
})
}
callback(null, response)
}
Command example:
serverless deploy
serverless invoke -f $FUNCTION_NAME
Result example:
{
"body": "{\"input\": {}, \"message\": \"This is a secret\"}",
"statusCode": 200
}
Commands
You can use these commands to modify your YAML environment files.
If no stage is specified the default one as specified in serverless.yml is used.
Use the following commands to read and decrypt variables from your YAML environment files:
serverless env
serverless env --stage $STAGE
serverless env --attribute $NAME
serverless env --attribute $NAME --stage $STAGE
#shorthand:
sls env -a $NAME
sls env -a $NAME -s $STAGE
serverless env --decrypt
serverless env --attribute $NAME --decrypt
serverless env --attribute $NAME --stage $STAGE --decrypt
#shorthand:
sls env -a $NAME --decrypt
sls env -a $NAME -s $STAGE -d
Use the following commands to store and encrypt variables in your YAML environment files:
Note that variables are stored to the first file listed in envFiles.
serverless env --attribute $NAME --value $PLAINTEXT
serverless env --attribute $NAME --value $PLAINTEXT --stage $STAGE
#shorthand:
sls env -a $NAME -v $PLAINTEXT
sls env -a $NAME -v $PLAINTEXT -s $STAGE
serverless env --attribute $NAME --value $PLAINTEXT --encrypt
serverless env --attribute $NAME --value $PLAINTEXT --stage $STAGE --encrypt
#shorthand:
sls env -a $NAME -v $PLAINTEXT -e
sls env -a $NAME -v $PLAINTEXT -s $STAGE -e
serverless env --anchor $NAME --attribute $NAME --value $PLAINTEXT
#shorthand:
sls env -c $NAME -a $NAME -v $PLAINTEXT
serverless env --anchor $NAME --attribute $NAME --value $PLAINTEXT --encrypt
#shorthand:
sls env -c $NAME -a $NAME -v $PLAINTEXT -e
YAML File Structure
Environment variables are stored in stage-agnostic YAML files, which are then merged into a .env file on deployment.
File example:
common: &common
commonFoo: foo
dev: #stage
<<: *common
foo: bar #cleartext variable
bla: crypted:bc89hwnch8hncoaiwjnd... #encrypted variable
production:
<<: *common
foo: baz
bla: crypted:ncibinv0iwokncoiao3d...
You can create additional YAML environment files, for example to include variables that are dynamically generated. Just add them to the envFiles in your serverless.yml.
Usage with the serverless-plugin-webpack
In case you are also using the serverless-plugin-webpack
there are some caveats:
You have to place @redtea/serverless-env-generator
before the serverless-plugin-webpack
in the serverless.yml
# serverless.yml
plugins:
- '@redtea/serverless-env-generator'
- serverless-plugin-webpack
dotenv-webpack
You need to have the dotenv-webpack
plugin installed:
npm install dotenv-webpack --save-dev
and configured:
// webpack.config.js
const Dotenv = require('dotenv-webpack')
module.exports = {
// ...
plugins: [
// ...
new Dotenv()
]
}
Contribute
Anyone is more than welcome to contribute to the @redtea/serverless-env-generator plugin. Here just a few things to consider when doing so:
Author: Org-redtea
Source Code: https://github.com/org-redtea/serverless-env-generator
License: MIT License
1604281120
The shorthand techniques of any programming language help you to write more clean and optimized code. Shorthand techniques improve readability of your code and you can achieve your goal with less coding. Let’s discuss some of the shorthand techniques of JavaScript one by one.
//Longhand
let x; let y = 20;
//Shorthand
let x, y = 20;
We can assign values to multiple variables in one line with array destructuring.
//Longhand
let a, b, c;
a = 5;
b = 8;
c = 12;
//Shorthand
let [a, b, c] = [5, 8, 12];
We can save 5 lines of code here with ternary (conditional) operator.
//Longhand
let number = 26;
let isEven;
if(number % 2){
isEven = true;
}else{
isEven = false;
}
//Shorthand
let isEven = number % 2 ? true : false;
We can use OR(||)
short circuit evaluation to assign a default value to a variable in case the expected value found empty.
//Longhand
let imagePath;
let path = getImagePath();
if(path !== null && path !== undefined && path !== '') {
imagePath = path;
} else {
imagePath = 'default.jpg';
}
//Shorthand
let imagePath = getImagePath() || 'default.jpg';
If you are calling a function only if a variable is true, then using AND(&&)
short circuit you can do it in a single line.
//Longhand
if (isLoggedin) {
goToHomepage();
}
//Shorthand
isLoggedin && goToHomepage();
Here in shorthand technique, if isLoggedin
returns true, then only goToHomepage()
will execute.
To swap two variables, we often use a third variable. We can swap two variables easily with array destructuring assignment.
let x = 'Hello', y = 55;
//Longhand
const temp = x;
x = y;
y = temp;
//Shorthand
[x, y] = [y, x];
//Longhand
function add(num1, num2) {
return num1 + num2;
}
//Shorthand
const add = (num1, num2) => num1 + num2;
We normally use + operator to concatenate string values with variables. With ES6 template literals we can do it in a more simple way.
//Longhand
console.log('You got a missed call from ' + number + ' at ' + time);
//Shorthand
console.log(`You got a missed call from ${number} at ${time}`);
For multiline string we normally use + operator with a new line escape sequence (\n). We can do it in an easier way by using backticks (`).
//Longhand
console.log('JavaScript, often abbreviated as JS, is a\n' + 'programming language that conforms to the \n' +
'ECMAScript specification. JavaScript is high-level,\n' +
'often just-in-time compiled, and multi-paradigm.' );
//Shorthand
console.log(`JavaScript, often abbreviated as JS, is a programming language that conforms to the ECMAScript specification. JavaScript is high-level, often just-in-time compiled, and multi-paradigm.`);
For multiple value matching, we can put all values in array and use indexOf()
method.
//Longhand
if (value === 1 || value === 'one' || value === 2 || value === 'two') {
// Execute some code
}
// Shorthand
if ([1, 'one', 2, 'two'].indexOf(value) >= 0) {
// Execute some code
}
If the variable name and object key name is same then we can just mention variable name in object literals instead of both key and value. JavaScript will automatically set the key same as variable name and assign the value as variable value.
let firstname = 'Amitav';
let lastname = 'Mishra';
//Longhand
let obj = {firstname: firstname, lastname: lastname};
//Shorthand
let obj = {firstname, lastname};
There are built in methods like parseInt
and parseFloat
available to convert a string to number. We can also do this by simply providing a unary operator (+) in front of string value.
//Longhand
let total = parseInt('453');
let average = parseFloat('42.6');
//Shorthand
let total = +'453';
let average = +'42.6';
To repeat a string for a specified number of time you can use a for
loop. But using the repeat()
method we can do it in a single line.
//Longhand
let str = '';
for(let i = 0; i < 5; i ++) {
str += 'Hello ';
}
console.log(str); // Hello Hello Hello Hello Hello
// Shorthand
'Hello '.repeat(5);
Tip: Want to apologize to someone by sending 100 times “sorry”? Try it with
_repeat()_
method. If you want to repeat each string in a new line, then add_\n_
to the string.
'sorry\n'.repeat(100);
We can use Math.pow()
method to find the power of a number. There is a shorter syntax to do it with double asterik (**).
//Longhand
const power = Math.pow(4, 3); // 64
// Shorthand
const power = 4**3; // 64
The double NOT bitwise operator is a substitute for Math.floor()
method.
//Longhand
const floor = Math.floor(6.8); // 6
// Shorthand
const floor = ~~6.8; // 6
We can use for loop to loop through each value of array and find the max or min value. We can also use the Array.reduce() method to find the max and min number in array.But using spread operator we can do it in a single line.
// Shorthand
const arr = [2, 8, 15, 4];
Math.max(...arr); // 15
Math.min(...arr); // 2
To loop through an array we normally use the traditional for
loop. We can make use of the for...of
loop to iterate through arrays. To access the index of each value we can use for...in
loop.
let arr = [10, 20, 30, 40];
//Longhand
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
//Shorthand
//for of loop
for (const val of arr) {
console.log(val);
}
//for in loop
for (const index in arr) {
console.log(arr[index]);
}
We can also loop through object properties using for...in
loop.
let obj = {x: 20, y: 50};
for (const key in obj) {
console.log(obj[key]);
}
let arr1 = [20, 30];
//Longhand
let arr2 = arr1.concat([60, 80]);
// [20, 30, 60, 80]
//Shorthand
let arr2 = [...arr1, 60, 80];
// [20, 30, 60, 80]
To deep clone a multi-level object, we can iterate through each property and check if the current property contains an object. If yes, then do a recursive call to the same function by passing the current property value (i.e. the nested object).We can also do it by using JSON.stringify()
and JSON.parse()
in a single line.
let obj = {x: 20, y: {z: 30}};
//Longhand
const makeDeepClone = (obj) => {
let newObject = {};
Object.keys(obj).map(key => {
if(typeof obj[key] === 'object'){
newObject[key] = makeDeepClone(obj[key]);
} else {
newObject[key] = obj[key];
}
});
return newObject;
}
const cloneObj = makeDeepClone(obj);
//Shorthand
const cloneObj = JSON.parse(JSON.stringify(obj));
let str = 'jscurious.com';
//Longhand
str.charAt(2); // c
//Shorthand
str[2]; // c
Thanks for reading!
This article was originally published on medium.com
You may also like: ☞ Top 35 JavaScript Shorthands for Beginners
#web-design #web-development #javascript #javascript-tips
1619571780
March 25, 2021 Deepak@321 0 Comments
Welcome to my blog, In this article, we will learn the top 20 most useful python modules or packages and these modules every Python developer should know.
Hello everybody and welcome back so in this article I’m going to be sharing with you 20 Python modules you need to know. Now I’ve split these python modules into four different categories to make little bit easier for us and the categories are:
Near the end of the article, I also share my personal favorite Python module so make sure you stay tuned to see what that is also make sure to share with me in the comments down below your favorite Python module.
#python #packages or libraries #python 20 modules #python 20 most usefull modules #python intersting modules #top 20 python libraries #top 20 python modules #top 20 python packages
1604313328
let x;
let y = 20;
//Shorthand
let x, y = 20;
We can assign values to multiple variables in one line with array destructuring.
let a, b, c;
a = 5;
b = 8;
c = 12;
//Shorthand
let [a, b, c] = [5, 8, 12];
We can save 5 lines of code here with ternary (conditional) operator.
let marks = 26;
let result;
if(marks >= 30){
result = 'Pass';
}else{
result = 'Fail';
}
//Shorthand
let result = marks >= 30 ? 'Pass' : 'Fail';
We can use OR(||) short circuit evaluation to assign a default value to a variable in case the expected value found empty.
let imagePath;
let path = getImagePath();
if(path !== null && path !== undefined && path !== '') {
imagePath = path;
} else {
imagePath = 'default.jpg';
}
//Shorthand
let imagePath = getImagePath() || 'default.jpg';
If you are calling a function only if a variable is true, then using AND(&&) short circuit you can do it in a single line.
if (isLoggedin) {
goToHomepage();
}
//Shorthand
isLoggedin && goToHomepage();
Here in shorthand technique, if isLoggedin returns true, then only goToHomepage() will execute.
Read the original post in jscurious.com
#javascript #shorthand #web-development #typescript
1653075360
HAML-Lint
haml-lint
is a tool to help keep your HAML files clean and readable. In addition to HAML-specific style and lint checks, it integrates with RuboCop to bring its powerful static analysis tools to your HAML documents.
You can run haml-lint
manually from the command line, or integrate it into your SCM hooks.
gem install haml_lint
If you'd rather install haml-lint
using bundler
, don't require
it in your Gemfile
:
gem 'haml_lint', require: false
Then you can still use haml-lint
from the command line, but its source code won't be auto-loaded inside your application.
Run haml-lint
from the command line by passing in a directory (or multiple directories) to recursively scan:
haml-lint app/views/
You can also specify a list of files explicitly:
haml-lint app/**/*.html.haml
haml-lint
will output any problems with your HAML, including the offending filename and line number.
haml-lint
assumes all files are encoded in UTF-8.
Command Line Flag | Description |
---|---|
--auto-gen-config | Generate a configuration file acting as a TODO list |
--auto-gen-exclude-limit | Number of failures to allow in the TODO list before the entire rule is excluded |
-c /--config | Specify which configuration file to use |
-e /--exclude | Exclude one or more files from being linted |
-i /--include-linter | Specify which linters you specifically want to run |
-x /--exclude-linter | Specify which linters you don't want to run |
-r /--reporter | Specify which reporter you want to use to generate the output |
-p /--parallel | Run linters in parallel using available CPUs |
--fail-fast | Specify whether to fail after the first file with lint |
--fail-level | Specify the minimum severity (warning or error) for which the lint should fail |
--[no-]color | Whether to output in color |
--[no-]summary | Whether to output a summary in the default reporter |
--show-linters | Show all registered linters |
--show-reporters | Display available reporters |
-h /--help | Show command line flag documentation |
-v /--version | Show haml-lint version |
-V /--verbose-version | Show haml-lint , haml , and ruby version information |
haml-lint
will automatically recognize and load any file with the name .haml-lint.yml
as a configuration file. It loads the configuration based on the directory haml-lint
is being run from, ascending until a configuration file is found. Any configuration loaded is automatically merged with the default configuration (see config/default.yml
).
Here's an example configuration file:
linters:
ImplicitDiv:
enabled: false
severity: error
LineLength:
max: 100
All linters have an enabled
option which can be true
or false
, which controls whether the linter is run, along with linter-specific options. The defaults are defined in config/default.yml
.
Option | Description |
---|---|
enabled | If false , this linter will never be run. This takes precedence over any other option. |
include | List of files or glob patterns to scope this linter to. This narrows down any files specified via the command line. |
exclude | List of files or glob patterns to exclude from this linter. This excludes any files specified via the command line or already filtered via the include option. |
severity | The severity of the linter. External tools consuming haml-lint output can use this to determine whether to warn or error based on the lints reported. |
The exclude
global configuration option allows you to specify a list of files or glob patterns to exclude from all linters. This is useful for ignoring third-party code that you don't maintain or care to lint. You can specify a single string or a list of strings for this option.
Some static blog generators such as Jekyll include leading frontmatter to the template for their own tracking purposes. haml-lint
allows you to ignore these headers by specifying the skip_frontmatter
option in your .haml-lint.yml
configuration:
skip_frontmatter: true
The inherits_from
global configuration option allows you to specify an inheritance chain for a configuration file. It accepts either a scalar value of a single file name or a vector of multiple files to inherit from. The inherited files are resolved in a first in, first out order and with "last one wins" precedence. For example:
inherits_from:
- .shared_haml-lint.yml
- .personal_haml-lint.yml
First, the default configuration is loaded. Then the .shared_haml-lint.yml
configuration is loaded, followed by .personal_haml-lint.yml
. Each of these overwrite each other in the event of a collision in configuration value. Once the inheritance chain is resolved, the base configuration is loaded and applies its rules to overwrite any in the intermediate configuration.
Lastly, in order to match your RuboCop configuration style, you can also use the inherit_from
directive, which is an alias for inherits_from
.
haml-lint
is an opinionated tool that helps you enforce a consistent style in your HAML files. As an opinionated tool, we've had to make calls about what we think are the "best" style conventions, even when there are often reasonable arguments for more than one possible style. While all of our choices have a rational basis, we think that the opinions themselves are less important than the fact that haml-lint
provides us with an automated and low-cost means of enforcing consistency.
Add the following to your configuration file:
require:
- './relative/path/to/my_first_linter.rb'
- 'absolute/path/to/my_second_linter.rb'
The files that are referenced by this config should have the following structure:
module HamlLint
# MyFirstLinter is the name of the linter in this example, but it can be anything
class Linter::MyFirstLinter < Linter
include LinterRegistry
def visit_tag
return unless node.tag_name == 'div'
record_lint(node, "You're not allowed divs!")
end
end
end
For more information on the different types on HAML node, please look through the HAML parser code: https://github.com/haml/haml/blob/master/lib/haml/parser.rb
Keep in mind that by default your linter will be disabled by default. So you will need to enable it in your configuration file to have it run.
One or more individual linters can be disabled locally in a file by adding a directive comment. These comments look like the following:
-# haml-lint:disable AltText, LineLength
[...]
-# haml-lint:enable AltText, LineLength
You can disable all linters for a section with the following:
-# haml-lint:disable all
A directive will disable the given linters for the scope of the block. This scope is inherited by child elements and sibling elements that come after the comment. For example:
-# haml-lint:disable AltText
#content
%img#will-not-show-lint-1{ src: "will-not-show-lint-1.png" }
-# haml-lint:enable AltText
%img#will-show-lint-1{ src: "will-show-lint-1.png" }
.sidebar
%img#will-show-lint-2{ src: "will-show-lint-2.png" }
%img#will-not-show-lint-2{ src: "will-not-show-lint-2.png" }
The #will-not-show-lint-1
image on line 2 will not raise an AltText
lint because of the directive on line 1. Since that directive is at the top level of the tree, it applies everywhere.
However, on line 4, the directive enables the AltText
linter for the remainder of the #content
element's content. This means that the #will-show-lint-1
image on line 5 will raise an AltText
lint because it is a sibling of the enabling directive that appears later in the #content
element. Likewise, the #will-show-lint-2
image on line 7 will raise an AltText
lint because it is a child of a sibling of the enabling directive.
Lastly, the #will-not-show-lint-2
image on line 8 will not raise an AltText
lint because the enabling directive on line 4 exists in a separate element and is not a sibling of the it.
If there are multiple directives for the same linter in an element, the last directive wins. For example:
-# haml-lint:enable AltText
%p Hello, world!
-# haml-lint:disable AltText
%img#will-not-show-lint{ src: "will-not-show-lint.png" }
There are two conflicting directives for the AltText
linter. The first one enables it, but the second one disables it. Since the disable directive came later, the #will-not-show-lint
element will not raise an AltText
lint.
You can use this functionality to selectively enable directives within a file by first using the haml-lint:disable all
directive to disable all linters in the file, then selectively using haml-lint:enable
to enable linters one at a time.
Adding a new linter into a project that wasn't previously using one can be a daunting task. To help ease the pain of starting to use Haml-Lint, you can generate a configuration file that will exclude all linters from reporting lint in files that currently have lint. This gives you something similar to a to-do list where the violations that you had when you started using Haml-Lint are listed for you to whittle away, but ensuring that any views you create going forward are properly linted.
To use this functionality, call Haml-Lint like:
haml-lint --auto-gen-config
This will generate a .haml-lint_todo.yml
file that contains all existing lint as exclusions. You can then add inherits_from: .haml-lint_todo.yml
to your .haml-lint.yml
configuration file to ensure these exclusions are used whenever you call haml-lint
.
By default, any rules with more than 15 violations will be disabled in the todo-file. You can increase this limit with the auto-gen-exclude-limit
option:
haml-lint --auto-gen-config --auto-gen-exclude-limit 100
If you use vim
, you can have haml-lint
automatically run against your HAML files after saving by using the Syntastic plugin. If you already have the plugin, just add let g:syntastic_haml_checkers = ['haml_lint']
to your .vimrc
.
If you use vim
8+ or Neovim
, you can have haml-lint
automatically run against your HAML files as you type by using the Asynchronous Lint Engine (ALE) plugin. ALE will automatically lint your HAML files if it detects haml-lint
in your PATH
.
If you use SublimeLinter 3
with Sublime Text 3
you can install the SublimeLinter-haml-lint plugin using Package Control.
If you use atom
, you can install the linter-haml plugin.
If you use TextMate 2
, you can install the Haml-Lint.tmbundle bundle.
If you use Visual Studio Code
, you can install the Haml Lint extension
If you'd like to integrate haml-lint
into your Git workflow, check out our Git hook manager, overcommit.
To execute haml-lint
via a Rake task, make sure you have rake
included in your gem path (e.g. via Gemfile
) add the following to your Rakefile
:
require 'haml_lint/rake_task'
HamlLint::RakeTask.new
By default, when you execute rake haml_lint
, the above configuration is equivalent to running haml-lint .
, which will lint all .haml
files in the current directory and its descendants.
You can customize your task by writing:
require 'haml_lint/rake_task'
HamlLint::RakeTask.new do |t|
t.config = 'custom/config.yml'
t.files = ['app/views', 'custom/*.haml']
t.quiet = true # Don't display output from haml-lint to STDOUT
end
You can also use this custom configuration with a set of files specified via the command line:
# Single quotes prevent shell glob expansion
rake 'haml_lint[app/views, custom/*.haml]'
Files specified in this manner take precedence over the task's files
attribute.
Code documentation is generated with YARD and hosted by RubyDoc.info.
We love getting feedback with or without pull requests. If you do add a new feature, please add tests so that we can avoid breaking it in the future.
Speaking of tests, we use Appraisal to test against both HAML 4 and 5. We use rspec
to write our tests. To run the test suite, execute the following from the root directory of the repository:
appraisal bundle install
appraisal bundle exec rspec
All major discussion surrounding HAML-Lint happens on the GitHub issues page.
If you're interested in seeing the changes and bug fixes between each version of haml-lint
, read the HAML-Lint Changelog.
Author: sds
Source Code: https://github.com/sds/haml-lint
License: MIT license