Today I learned

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

#26

How to add generic styles in Vue Styleguidist

At work, recently we worked on a styleguide project using vue Styleguidist, the Vue little brother of react-styleguidist, and we would like to organize components styles in this way:

  • component specific styles would be inside the [ComponentName].vue file
  • while all generic styles (colors, typography, and so on) would be inside a generic styles.scss file.

The first (bad) idea #

If we hadn't been in a Styleguidist app, but in a "normal" Vue app instead, we could have add a sass @import with all our generic styles at the highiest component, the App.vue:

// App.vue

<template>
<div id="app">
...
</div>
</template>

<script>
export default {
name: 'App',
}
</script>

<style lang="scss">
// generic styles
@import 'styles/styles.scss'
</style>

In this way, all components will have inherited our generic styles.

But in a Styleguidist project we have not such an high-level Vue component ๐Ÿ˜ฉ

If we would want to import a generic file in that way, we would have to add it into all our components, like this:

// components/MyComponent.vue

<template>
...
</template>

<script>
export default {
name: 'MyComponent',
}
</script>

<style lang="scss">
// generic styles
@import 'styles/styles.scss'

// my components custom styles
.c-my-component
{
background: red;
}

...
</style>

Not such a great idea! ๐Ÿง

The second (I think good?) idea #

Probably there is a better way to do it, but for the moment we'll go with this! ๐Ÿ˜…

Adding a vue.conifg.js file to the Styleguidist project, we can tell to Styleguidist sass-loader which style content it has to prepend before the actual component <style> content. This can be achieved using sass-loader additionalData option

// vue.config.js

module.exports = {
css: {
sourceMap: true,
loaderOptions: {
scss: {
additionalData: `
@import "assets/styles/styles.scss";
`
,
},
},
},
}

๐Ÿงจ !important

In these examples I have assumed that we are using SASS (.scss) files and not simple CSS files.
The sass-loader node package I mentioned before is already installed in our project because we wrote styles in SASS using the <style lang="scss"> syntax.

โšก๏ธ Bonus tip #

Since we have just added the vue.config.js file, we also added my postcss configuration there:

const postcssNormalize = require('postcss-normalize')
const postcssPresetEnv = require('postcss-preset-env')

module.exports = {
css: {
sourceMap: true,
loaderOptions: {
scss: {
additionalData: `
@import "assets/styles/styles.scss";
`
,
},
postcss: {
plugins: () => [
postcssPresetEnv({
features: {
'logical-properties-and-values': {
dir: 'ltr',
},
},
}),
postcssNormalize(),
],
},
},
},
}

Et voilร ! ๐Ÿ‡ซ๐Ÿ‡ท

With this configuration:

  • component specific styles are inside the [ComponentName].vue file
  • while all generic styles are inside a generic styles.scss file

Please let me know if you found a better way to import general styles in Vue Styleguidist components! ๐Ÿ˜‡

#25

Find element in array and move it to the first position

Surely there are several way to do it, this is just one of them. Let me know if you know a better way to do it ๐Ÿ’ช๐Ÿป

To find an element into an array and move to be the first, you have to:

๐Ÿ“š The findIndex() method returns the index of the first element in the array that satisfies the provided testing function.

const arr = [1, 2, 3, '๐Ÿฑ', 4, 5, 6, 7, 8, 9 , 10]
const itemToFind = '๐Ÿฑ'

const foundIdx = arr.findIndex(el => el == itemToFind) // -> foundIdx = 3
  • remove the item in that specific position using splice()

๐Ÿ“š The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place.

arr.splice(foundIdx, 1)

// splice(start[, deleteCount[, item1[, item2[, ...]]]])
// start = foundIdx
// deleteCount = 1 = number of elements in the array to remove from start
  • add the item to the 1st position using unshift()

๐Ÿ“š The unshift() method adds one or more elements to the beginning of an array and returns the new length of the array.

arr.unshift(itemToFind)

Output

console.log(arr)

// (11) ["๐Ÿฑ", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

To sum up:

const arr = [1, 2, 3, '๐Ÿฑ', 4, 5, 6, 7, 8, 9 , 10]
const itemToFind = '๐Ÿฑ'

const foundIdx = arr.findIndex(el => el == itemToFind)
arr.splice(foundIdx, 1)
arr.unshift(itemToFind)

๐Ÿ“š More info

Moving Element In An Array From Index To Another

js
#24

How to add Google Fonts in Vue Styleguidist

Few days ago I worked on a vue-styleguidist project and I had to use a Google Font.

Side note: vue-styleguidist is the "Vue version" of the more famous react-styleguidist, a component development environment with hot reloaded dev server and a living style guide.

In a static page, I would add the font in a classic way using a <link> tag:

<html>
<head>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Raleway:100,400,800">

<style>
h1 {
font-family: 'Raleway', sans-serif;
font-size: 48px;
}
</style>
</head>
<body>
<h1>Whoa! I'm in Raleway ๐Ÿ“</h1>
</body>
</html>

But hey, in Styleguidist we are writing components into the "Styleguidist box" ๐Ÿ“ฆ!

Styleguidist takes care of creating the fancy and functional box around our components, while we only have to write what is strictly necessary for the component (its structure, its styles, and its logic)

To add a <head> property to the "Styleguidist box" we have to use the react-styleguidist template property which lets us change the HTML of the Styleguidist application.

To find out template supported properties, I deep dive into mini-html-webpack-template-plugin extended options. There I found that it is possible to add an head property with an array of links... awesome! ๐Ÿ˜ผ

Name Type Default Description
head.links {Array} undefined Array of objects with key + value pairs

So, to add Raleway Google Font in our project we have to add to the styleguide.config.js file a template object:

// styleguide.config.js

module.exports = {
title: 'My awesome styleguide',
components: 'components/**/[A-Z]*.vue',
...
template: {
head: {
links: [{
key: 'stylesheet',
value: 'https://fonts.googleapis.com/css?family=Raleway:100,400,800',
}, ],
},
},
}

that turns out in

<head>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Raleway:100,400,800">

</head>

Now, in our components files we can use the Google Font ๐Ÿ˜

// My component.vue

<template>
<h1>My awesome title</h1>
</template>

<script>
export default {
name: 'MyComponent',
}
</script>

<style>
h1 {
font-family: 'Raleway', sans-serif;
font-size: 48px;
}
</style>
#23

Add a class in Nunjucks using a conditional statement

In Nunjucks we can use a conditional statement in two ways:

  1. explicit using the {% if %} keyword,
  2. or implicit using the {{ }} expression.

Note: I did not find any reference about these names โ€“ implicit/explicit โ€“ in the Nunjucks official documentation ๐Ÿ“š, I just named to easily distinguish the two syntax in this tutorial ๐Ÿ˜‡.

Syntax n.1: explicit #

Using an explicit {% if %} keyword, Nunjucks checks if the condition is met

{% set arr = ['๐Ÿฑ', '๐Ÿถ', '๐Ÿบ'] %}

<p>{% if '๐Ÿถ' in arr %}{% endif %}</p>

HTML output

<p>true</p>

Using this method, we can add an HTML class when a specific condition is met

{% set arr = ['๐Ÿฑ', '๐Ÿถ', '๐Ÿบ'] %}

<div class="c-animals {% if '๐Ÿถ' in arr %}has-dog{% endif %}">...</div>

HTML output

<div class="c-animals has-dog">...</div>

Syntax n.2: implicit #

Using double curly braces, Nunjucks evalued its content:

{% set arr = ['๐Ÿฑ', '๐Ÿถ', '๐Ÿบ'] %}

<p>{{ if '๐Ÿถ' in arr }}</p>

HTML output

<p>true</p>

Using this method, we can add an HTML class when a specific condition is met

{% set arr = ['๐Ÿฑ', '๐Ÿถ', '๐Ÿบ'] %}

<div class="c-animals {{ 'has-dog' if '๐Ÿถ' in arr }}">...</div>

HTML output

<div class="c-animals has-dog">...</div>

Note that the HTML output is exactly the same! ๐Ÿš€

To sum up #

{% set arr = ['๐Ÿฑ', '๐Ÿถ', '๐Ÿบ'] %}

{# 1. explicit #}
<div class="c-animals {% if '๐Ÿถ' in arr %}has-dog{% endif %}">...</div>

{# 2. implicit #}
<div class="c-animals {{ 'has-dog' if '๐Ÿถ' in arr }}">...</div>

Personally, I use both syntaxes in my Nunjucks files, and to choose which one to use I go with this logic:

  • if there is just one condition to met and it is quite simple, I use the implicit syntax
  • else I use the explicit one ๐Ÿค“
#22

Nodejs cheatsheet

Few commands I found very useful during development.

Command Description
npm list show a tree of every package found in the current folder
npm list -g same as above ^^, but search also in global packages
npm list -g --depth=0 same as above ^^, but do not show every packageโ€™s dependencies
npm list [package name] show a tree of every instance found in the current folder of that specific package
npm install install all packages in package.json
npm install [package name] install a package
npm install [package name] --save install a package as dependency
npm install [package name] --save-dev install a package as dev dependency
npm uninstall [package name] uninstall a package
npm install --save username/repo#branch-name-or-commit-or-tag install package from GitHub repository

Alias #

Alias Command
npm i npm install
npm i [package name] -D npm install [package name] --save-dev

โšก๏ธ Bonus tip #

npm-check is a useful tool to check for outdated, incorrect, and unused dependencies

๐Ÿ“š More info

#21

Git cheatsheet

Few commands I found very useful during development.

Command Description
git commit -am "message" add and commit all trakced files
git fetch --all --prune fetch all remotes, delete remote branches which are dead
git reset --merge abort merge, reset as before (also if there are local commit not pushed yet)
git merge --strategy-option theirs [branch] merge branch into current branch, keeping their work in conflicts
git branch --unset-upstream remove upstream branch
git reset myfile.js remove from staging area
git commit --amend --no-edit amend without edit message
git commit --amend --no-edit --patch amend without edit message + choose interactively which changes to commit
git checkout - switch to previous branch
git checkout [branch] -- path/to/file.scss get file from another branch and copy to current branch
git stash -u stash all files (also untracked ones)
git reset --soft A remove files, but still available in staging area
git reset --mixed A git reset A (default) remove files also in staging area
git reset --hard remove files as they never existed
git stash clear delete all stashes
git fetch origin; git reset --hard origin/main restore as remote main branch
git log --tags --simplify-by-decoration --pretty="format:%ci %d" show tags details
git log --graph --abbrev-commit --decorate show commits with decorative branches
git log --decorate --oneline --graph --date-order master@{"4 days ago"}..master show commits of the last 4 days in a compact graph
git diff --name-only | uniq | xargs $EDITOR open all modified files
git push origin :feature/branchname delete remote branch
git push origin --delete feature/branchname delete remote branch
git push origin --all push all local branches
git fetch --prune --prune-tags remove local tags, align tags to remotes
git ls-remote --tags origin list all remote tags

โšก๏ธ Bonus tip #

If there is a command you use often, you can save it as a global git alias.

git config --global alias.fixup 'commit --amend --no-edit'

and then using it

git fixup

Thanks to DarkWiiPlayer for pointing that out. ๐Ÿ˜Ž

Rename a git tag #

git tag [new] [old]
git tag -d [old]
git push origin :refs/tags/[old]
git push --tags

When you fetch remote tags, be sure you have the updated tags

git pull --prune --tags

GitLab branch compare #

  • Open the left sidebar
  • Click on Repository > Compare
https://github.com/giuliachiola/super-blog-11ty/compare/[source]...[target]

Example:

https://github.com/giuliachiola/super-blog-11ty/compare/main...develop
git
#20

Fix developer path after upgrade to MacOS Catalina

After MacOS system upgrade to Catalina, on my computer git did not work anymore. If you happened the same, the following steps resolve it for me!

Running any of git commands, you would probably got this error

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

To fix it, you had to run

xcode-select --install

The "xcode-select" command requires the command line developer tools.

A prompt will appear asking you to install it now.

xcode-prompt

When installation is completed, git should work as expected! ๐Ÿ˜Ž

๐Ÿ“š More info

Invalid active developer path

#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 official Nunjucks documentation for this useful function ๐Ÿคท๐Ÿปโ€โ™€๏ธ

{% set animals = ['cat ๐Ÿฑ', 'dog ๐Ÿถ', 'lion ๐Ÿฆ'] %}
{% set domesticAnimals = [] %}
{% for animal in 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 it outside before entering the loop.
I wrote a post about it: ๐Ÿ“’ Nunjucks scoped variable declarations

#18

Git flow initialize

To inizialize git flow with default branches configuration, run

git flow init -d

It will create a git flow structure to your project

Initialized empty Git repository in /Users/giulia/Sites/giulia/test/.git/
Using default branch names.
No branches exist yet. Base branches must be created now.
Branch name for production releases: [main]
Branch name for "next release" development: [develop]
.git/hooks/post-commit: line 8: 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