Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Today I learned

A collection of useful code snippets for a faster development.
Reading time < 5 mins

Filter by:
#19

Add items to an array in Nunjucks

To add items in Nunjucks, use the.push() function.

{%set arr=[1,2]%}
{%set arr=(arr.push(3), arr)%}

Final array:

arr = [1,2,3]

Unfortunately, I did not found any references in the officialNunjucks documentation for this useful function 🤷🏻‍♀️

{%set animals=['cat 🐱','dog 🐶','lion 🦁']%}
{%set domesticAnimals=[]%}
{%for animalin animals%}
{%if animal!=='lion'%}
{%set domesticAnimals=(domesticAnimals.push(animal), domesticAnimals)%}
{%endif%}
{%endfor%}

Final array:

domesticAnimals = ['cat 🐱', 'dog 🐶']

🧨!important

If you use{% set .... %} inside a for-loop block, pay attention to have defined itoutside before entering the loop.
I wrote a post about it:📒 Nunjucks scoped variable declarations


📚More info

Docs aboutTwig 'push' filter. Note that this filter is not present into the officialTwig documentation 🤷🏻‍♀️

#18

Git flow initialize

To inizializegit flow with default branches configuration, run

git flow init-d

It will create a git flow structure to your project

Initialized empty Git repositoryin /Users/giulia/Sites/giulia/test/.git/
Using default branch names.
No branches exist yet. Base branches must be created now.
Branch namefor production releases:[main]
Branch namefor"next release" development:[develop]
.git/hooks/post-commit: line8: git-stats:command not found

How to name your supporting branch prefixes?
Feature branches?[feature/]
Bugfix branches?[bugfix/]
Release branches?[release/]
Hotfix branches?[hotfix/]
Support branches?[support/]
Version tag prefix?[]
Hooks and filters directory?[/Users/giulia/Sites/giulia/test/.git/hooks]

📚 More info

#17

Add multiple classes in pug

Pug, formerly known asJade, is a template engine thas uses a JavaScript render engine. Sometimes we have to add a class conditionally based on a variable, here I go with some tricky solutions I found.

One condition to check#

The easiest way to check a class inpug is using theternary operator

-var cond1=true
.c-component(class=cond1?'cond1-TRUE':'cond1-FALSE')

HTML output

<divclass="c-component cond1-true"></div>

But there are other two ways to write the same exact condition in pug:

-var cond1=true

//- (1)
.c-component(class={'cond1-true': cond1===true})

//- (2)
.c-component(class={cond1True: cond1===true})

Important#

🧨!important
(1) kebab-case classcond1-true must be wrapped in quotes
(2) camelCase classcond1True can skip wrapper quotes

HTML output

<divclass="c-component cond1-true"></div>
<divclass="c-component cond1True"></div>

More than one condition to check#

If we have to checktwo condintions, we can go also in this case with the ternary operator to choose which classes we want.

We can write the conditionals in three ways:

  1. using twoclass attributes separated by space
(class=cond1 ? 'cond1-TRUE' : 'cond1-FALSE' class=cond2 ? 'cond2-TRUE' : 'cond2-FALSE')
  1. using twoclass attributes separated by comma
(class=cond1 ? 'cond1-TRUE' : 'cond1-FALSE', class=cond2 ? 'cond2-TRUE' : 'cond2-FALSE')
  1. using twoclass attributes, one for each parentesis
(class=cond1 ? 'cond1-TRUE' : 'cond1-FALSE')(class=cond2 ? 'cond2-TRUE' : 'cond2-FALSE')

All three:

pug

-var cond1=true
-var cond2=false

.c-component(class=cond1?'cond1-TRUE':'cond1-FALSE'class=cond2?'cond2-TRUE':'cond2-FALSE')

.c-component(class=cond1?'cond1-TRUE':'cond1-FALSE',class=cond2?'cond2-TRUE':'cond2-FALSE')

.c-component(class=cond1?'cond1-TRUE':'cond1-FALSE')(class=cond2?'cond2-TRUE':'cond2-FALSE')

HTML output

<divclass="c-component cond1-TRUE cond2-FALSE"></div>

<divclass="c-component cond1-TRUE cond2-FALSE"></div>

<divclass="c-component cond1-TRUE cond2-FALSE"></div>

If we have a ternary option with the second operandempty, we could simplify the pug syntax:

-var cond1=true
-var cond2=false

.c-component(class=cond1&&'cond1-TRUE'class=cond2&&'cond2-TRUE')
//- or more explicit
.c-component(class=cond1?'cond1-TRUE':''class=cond2?'cond2-TRUE':'')

HTML output

<divclass="c-component cond1-TRUE"></div>

🖥 Codepen example.

📚 More info

#16

Remove duplicates in object arrays

We have an object with multiple arrays inside it, and we need to remove duplicates between these arrays.

const obj={
arr1:['a','b','c'],
arr2:['a','b','d','e','f'],
}
  • First of all, we have to get the two arrays and merge their items with theArray.prototype.concat() method. As the documentation says, we can use this function on arrays only, not on objects!

  • We use this trick: we call an empty array[] and then we apply theconcat() method to it

const allItems=[].concat(obj.arr1, obj.arr2)

that will return

console.log(allItems)
// (8) ["a", "b", "c", "a", "b", "d", "e", "f"]

Remove duplicates from an array#

Method 1: filter()#

Let's filter our array with all items inside, just to be without duplicates.

Array.prototype.filter() method use this condition: "for every item I loop through, I will check if the current index (pos) is the same as theindexOf(item), and it this condition is true I will return the item.".

Array.prototype.indexOf() methodreturns the first index at which a given element can be found in the array, or -1 if it is not present, so the filter condition is satisfied only for the first time the item pass the loop because loopindex andindexOf are the same.

To be more clear let's make a table of the loop:

ItemLoop indexindexOf*ConditionSaved into unique array
'a'00ok, 0 == 0 so this will returntrueyes
'b'11ok, 1 == 1 so this will returntrueyes
'c'22ok, 2 == 2 so this will returntrueyes
'a'30whoa, 3 != 0 so this will returnfalsenope!
'b'41whoa, 4 != 1 so this will returnfalsenope!
'd'55ok, 5 == 5 so this will returntrueyes
'e'66ok, 6 == 6 so this will returntrueyes
'f'77ok, 7 == 7 so this will returntrueyes

*indexOf = first position the item is present

const unique= allItems.filter((item, pos)=> allItems.indexOf(item)=== pos)
console.log(unique)
// (6) ["a", "b", "c", "d", "e", "f"]

Method 2: Set()#

Set() is an object lets you store unique values of any type.

  • create a newSet() to return the unique values
  • spread... its items inside theSet object
  • wrap all in square brackets to return an array[object]
const unique=[...newSet(allItems)]

or we can use this syntax (I prefer this one! It seems more clear to me that we are manipulating something that will become an array using theArray.from() method)

  • create a newSet() to return the unique values
  • convert the Set object to an array usingArray.from()
const unique= Array.from(newSet(allItems))

and the result is exactly the same as above usingfilter().

console.log(unique)
// (6) ["a", "b", "c", "d", "e", "f"]

To sum up#

/* ==========================================================================
OBJECT ARRAYS, REMOVE DUPLICATES
========================================================================== */


const obj={
arr1:['a','b','c'],
arr2:['a','b','d','e','f'],
}

const allItems=[].concat(obj.arr1, obj.arr2)

// using filter()
const unique_filter= allItems.filter((item, pos)=> allItems.indexOf(item)=== pos)

// using Set()
const unique_set1=[...newSet(allItems)]
const unique_set2= Array.from(newSet(allItems))

console.log(allItems)// (8) ["a", "b", "c", "a", "b", "d", "e", "f"]

console.log(unique_filter)// (6) ["a", "b", "c", "d", "e", "f"]
console.log(unique_set1)// (6) ["a", "b", "c", "d", "e", "f"]
console.log(unique_set2)// (6) ["a", "b", "c", "d", "e", "f"]

📚 More info

How to Remove Array Duplicates in ES6

#15

Add HTML classes to 11ty markdown content

11ty comes with some useful plugins for markdown manipulation, one of these ismarkdown-it-attrs.

This plugin should be used combined with its big brother, the markdown parsermarkdown-it, which is already added in 11ty basic installation.

markdown-it-attrs usesmarkdown-it and adds the possibility to add attributes to HTML nodes generated from markdown.

To use it, add this plugin to the.eleventy configuration file:

  • requiremarkdown-it
const markdownIt=require('markdown-it')
  • requiremarkdown-it-attrs
const markdownItAttrs=require('markdown-it-attrs')
  • define basicmarkdown-it configuration options
const markdownItOptions={
html:true,
breaks:true,
linkify:true
}
  • setmarkdown-it-attrs asmarkdown-it usage options
const markdownLib=markdownIt(markdownItOptions).use(markdownItAttrs)
  • set as eleventy configuration the new markdown configuration
eleventyConfig.setLibrary('md', markdownLib)

To sum up:

// .eleventy.js

const markdownIt=require('markdown-it')
const markdownItAttrs=require('markdown-it-attrs')

const markdownItOptions={
html:true,
breaks:true,
linkify:true
}

const markdownLib=markdownIt(markdownItOptions).use(markdownItAttrs)
eleventyConfig.setLibrary('md', markdownLib)

Example of usage#

# This is a title {.c-article-section__title}
This is a paragraph with data-state {data-state=important}

Another text with attributes {.c-article-section__disclaimer #articleId attr=value attr2="spaced value"}

![Alt text](image.jpg){.u-shadow}

[Link in a new tab](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a){target="_blank" rel="noopener"}

will output

<h1class="c-article-section__title">This is a title</h1>
<pdata-state=important>This is a paragraph with data-state</p>
<pclass="c-article-section__disclaimer"id="articleId"attr=valueattr2="spaced value">Another text with attributes</p>

<imgclass="u-shadow"src="image.jpg"alt="Alt text">
<ahref="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a"target="_blank"rel="noopener">Link in a new tab</a>

🧨!important

Note the last line where I added thetarget="_blank" attribute to the link to open it in a new browser tab. It's ok open a link in a new tab, but for security reasons it has to have also therel="noopener" attribute.

Side note: unfortunately, I did not find a way to add attributes to markdowntables andblockquotes 😢

📚 More info

#14

Start an npm project

To start an npm project, you have just to runnpm init and npm will start asking you a lot of questions about how to call the project, who's the author and so on. If you are like me and have complete trust on your tools and its choices, just add-y at the end. It stands foryes and npm will complete the boring burocrazy for you. 😏

npm init-y
#13

Force include classes in critical CSS

Critical CSS build byAddy Osmani is a useful library that extracts and inlines critical-path CSS in HTML pages.

In the documentation page, there are a lot of configurations availablebut they are not the only ones! 😏

Critical CSS uses as its enginepenthouse which has in turn a lot of configuration options. One of them, isforceInclude.

forceInclude: [...] description from docs 📚:

Array of css selectors to keep in critical css, even if not appearing in critical viewport. Strings or regex (f.e. ['.keepMeEvenIfNotSeenInDom', /^.button/])

For instance, if we want to add a cta class injected via JS and not available in DOM nodes when the critical path is generated, we have to configure our critical CSS options like this:

critical.generate({
base:'./',
src:'template-homepage.html',
css:['production/css/style-1.css','production/css/style-2.css'],
....
penthouse:{
forceInclude:['OPTIONAL-CLASS-HERE'],
},
})
#12

Nunjucks scoped variable declarations

We have to pay attention where we set Nunjucks variables because they arescoped

{%set animals=['🐱','🐶','🐺']%}

{%for itemin animals%}
{%set animal= item%}
{%endfor%}

{{ animal}}
{# animal -> ERROR #}
{# animal declared INSIDE the loop is NOT available #}
{%set animals=['🐱','🐶','🐺']%}

{# note this declaration #}
{%set animal=''%}

{%for itemin animals%}
{%set animal= item%}
{%endfor%}

{{ animal}}
{# animal declared OUTSIDE the loop is available #}
{# animal -> 🐺 (last array item) #}

📚 More info

Twig docs - set variables

#11

Nunjucks advanced loops

Nunjucks is a powerful template engine that allows to loop through arrays and also objects 😏

Loop though an array#

{%set animals=['🐱','🐶','🐺']%}

{%for itemin animals%}
Value:{{ item}}
{%endfor%}
Value: 🐱
Value: 🐶
Value: 🐺

Loop though an object#

{%set animal={
name:'cat',
emoji:'🐱'
}%}


{%for key, valuein animal%}
{{ key}}:{{ value}}
{%endfor%}

Note that we have to declare the two parameters of the loopkey, value.

name: cat
emoji: 🐱

Theiterable property#

InTwig exists an intresting property,iterable that checks if a variable can be iterable in a for loop:

Loop through an array:

{%set animals=['🐱','🐶','🐺']%}

{%if animalsis iterable%}
{%for itemin animals%}
Value:{{ item}}
{%endfor%}
{%else%}
Not iterable:{{ animal}}
{%endif%}
Value: 🐱
Value: 🐶
Value: 🐺

Loop through an object:

{%set animals={
name:'cat',
emoji:'🐱'
}%}


{%if animalsis iterable%}
{%for itemin animals%}
Value:{{ item}}
{%endfor%}
{%else%}
Not iterable:{{ animal}}
{%endif%}
Value: cat
Value: 🐱

🧨!important

Please note thatiterable is aTwig property and can have unexpected results in Nunjucks template engine.

InTwig astring isnot iterable:

{%set animal='cat'%}

{%if animalis iterable%}
Iterable!
{%for itemin animal%}
Value:{{ item}}
{%endfor%}
{%else%}
Not iterable!
{{ animal}}
{%endif%}

Twig output

Not iterable!
cat

but if we run the same code inNunjucks, we discover that astring is iterable 🤯

Nunjucks output

Iterable!
Value: c
Value: a
Value: t

Accessing the parent loop#

Nunjucks provides in its loops theloop property.

From thedocs theloop.index is

the current iteration of the loop (1 indexed)

But what if we have two nested loops and we want to access to the parent loop?

Workaround: save the loop index as row number! 😏

In this example we have a matrix content: two rows and each row has one ore more cells. If we want to print all cells content and position, we have to:

  • loop (parent loop) through the rows

  • loop (child loop) through the columns

  • get the content inside each cell

    {%set animals=[
    ['🐱','🐶','🐺'],
    ['🐍']
    ]%}


    <table>
    {%for rowin animals%}
    {# new row #}
    <tr>
    {%set rowloop= loop%}
    {%for cellin row%}
    <td>
    row (rowloop.index):{{ rowloop.index}}
    column (loop.index):{{ loop.index}}
    cell:{{ cell}}
    </td>
    {%endfor%}
    </tr>
    {%endfor%}
    </table>

HTML output


<table>
{# new row #}
<tr>
<td>
row (rowloop.index):1
column (loop.index): 1
cell: 🐱
</td>
<td>
row (rowloop.index):1
column (loop.index): 2
cell: 🐶
</td>
<td>
row (rowloop.index):1
column (loop.index): 3
cell: 🐺
</td>
</tr>
{# new row #}
<tr>
<td>
row (rowloop.index):2
column (loop.index): 1
cell: 🐍
</td>
</tr>
</table>

📚 More info

#10

Shell cheatsheet

Few commands I found very useful during development.

CommandDescription
man lsshow manual for command 'ls'
wc <file>words count
rm <file>remove/delete file
rm -i <file>remove/delete file (interactive, ask confirm)
rmdir <directory>remove/delete directory
rm -R <directory>remove/delete directory and subdirectory
rm -iR <directory>remove/delete directory (interactive)
cp <current location> <destination>copy files
chmod -R 755 <folder>add writing permission to folder
pwdpresent working directory / print working directory
cdchange directory
mkdirmake directory
lslist files
ls -llist files (long form)
ls -lahlist files (long form, all also hidden, human readable)
touch [filename]create file
chownchange owner
cat <file>show file
<cmd> > <file>direct the output of "cmd" into "file"
grep -rl "<text>" <dir>search for all files containing<text> inside<dir>
lnsymbolic link
aliasshow available alias on shell
cd -go to the previous current directory
ctrl +radvanced search (search any word in bash history)

[8]ページ先頭

©2009-2025 Movatter.jp