Skip to content

Instantly share code, notes, and snippets.

@Schascha
Last active July 26, 2024 07:12
Show Gist options
  • Save Schascha/6f8eec61aa90b58c0948e7a05af7246e to your computer and use it in GitHub Desktop.
Save Schascha/6f8eec61aa90b58c0948e7a05af7246e to your computer and use it in GitHub Desktop.
Just a few things I like to remember

SVG Sprite

Demo

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>SVG Sprite Symbol</title>
		<style>
			body {
				-webkit-font-smoothing: antialiased;
				-moz-osx-font-smoothing: grayscale;
				--color-text: #333;
				--color-icons: #f5f5f5;
				--color-link: #cbf3ee;
				color: var(--color-text);
			}

			html {
				box-sizing: border-box;
			}

			*,
			*::before,
			*::after {
				box-sizing: inherit;
			}

			.hidden {
				position: absolute;
				overflow: hidden;
				width: 0;
				height: 0;
				pointer-events: none;
			}

			.icon {
				display: inline-block;
				fill: currentColor;
				width: 3rem;
				height: 3rem;
			}

			.icons {
				display: flex;
				align-items: flex-start;
				list-style: none;
				flex-wrap: wrap;
				margin: 0;
				padding: 0;
			}

			.icons > li {
				transition: background .3s ease;
				background: var(--color-icons);
				margin: 10px;
				padding: 10px;
				text-align: center;
				flex: 0;
			}

			.icons > li:hover {
				background-color: var(--color-link);
			}
		</style>
	</head>

	<body>
		<svg class="hidden">
			<symbol id="icon-facebook" viewBox="0 0 512 512">
				<path d="M188.1,99.1v70.4h-51.6v86.1h51.6v255.9h106V255.7h71.1c0,0,6.7-41.3,9.9-86.5h-80.6v-58.9c0-8.8,11.6-20.6,23-20.6h57.8V0h-78.5C185.5,0,188.1,86.2,188.1,99.1"/>
			</symbol>
			<symbol id="icon-google-plus" viewBox="0 0 512 512">
				<path d="M447.5,223v-55.4H408V223h-56.9v39.6H408v57h39.5v-57h55.3V223H447.5L447.5,223L447.5,223zM159.7,219.8v63.4c0,0,61.4-0.1,86.3-0.1c-13.5,41.1-34.6,63.4-86.3,63.4c-52.4,0-93.3-42.6-93.3-95s40.9-95,93.3-95c27.7,0,45.6,9.8,62,23.4c13.1-13.2,12-15,45.5-46.7c-28.4-25.9-66.1-41.6-107.5-41.6C71.5,91.5,0,163.1,0,251.5c0,88.4,71.5,160,159.7,160c131.8,0,164.1-115,153.4-191.7H159.7L159.7,219.8L159.7,219.8z"/>
			</symbol>
			<symbol id="icon-twitter" viewBox="0 0 512 512">
				<path d="M512,94.7c-18.8,8.5-39.1,14.2-60.3,16.7c21.7-13.2,38.3-34,46.2-58.8c-20.3,12.2-42.8,21-66.7,25.8c-19.2-20.7-46.5-33.6-76.7-33.6c-58,0-105,47.6-105,106.3c0,8.3,0.9,16.4,2.7,24.2C164.9,171,87.5,128.7,35.6,64.4c-9,15.7-14.2,34-14.2,53.4c0,36.9,18.5,69.4,46.7,88.5c-17.2-0.6-33.4-5.3-47.6-13.3c0,0.4,0,0.9,0,1.3c0,51.5,36.2,94.5,84.3,104.2c-8.8,2.4-18.1,3.7-27.7,3.7c-6.8,0-13.3-0.7-19.8-1.9c13.4,42.2,52.2,73,98.1,73.8c-35.9,28.5-81.2,45.5-130.5,45.5c-8.5,0-16.8-0.5-25.1-1.5c46.5,30.2,101.7,47.8,161,47.8c193.2,0,298.9-162,298.9-302.4c0-4.6-0.1-9.2-0.3-13.8C480.1,134.8,497.9,116.1,512,94.7"/>
			</symbol>
		</svg>

    <!-- Example 1: SVG use tag -->
    
		<ul class="icons">
			<li>
				<svg class="icon">
					<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-facebook"></use>
				</svg>
			</li>
			<li>
				<svg class="icon">
					<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-google-plus"></use>
				</svg>
			</li>
			<li>
				<svg class="icon">
					<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-twitter"></use>
				</svg>
			</li>
		</ul>
    
    <!-- Example 2: JS rewrite -->

		<ul class="icons">
			<li>
				<i class="icon icon-facebook"></i>
			</li>
			<li>
				<i class="icon icon-google-plus"></i>
			</li>
			<li>
				<i class="icon icon-twitter"></i>
			</li>
		</ul>

		<script>
			document.querySelectorAll('i').forEach(function(el) {
				var
					classname = el.className,
					icon = classname.match(/icon[-\w]+/),
					svg,
					use
				;

				if (icon) {
					svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
					svg.setAttribute('class', classname);

					use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
					use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#' + icon);
					svg.appendChild(use);

					el.parentNode.replaceChild(svg, el);
				}
			});
		</script>
	</body>
</html>

Find and replace Sass Compass mixins

A useful find and replace command to delete old Compass Mixins.

Find

@include (align-content|align-items|align-self|appearance|animation|background|border-radius|box-shadow|box-sizing|flex|flex-basis|flex-direction|flex-flow|flex-grow|flex-wrap|justify-content|justify-self|opacity|order|text-shadow|transform|transform-origin|transition|transition-timing-function|user-select)\((.*?)\);

Replace

$1: $2;

Automatically publish to npm using GitHub Actions

Something I like to achieve with GitHub workflows is to automatically publish new tags. The goal:

  • Use .nvmrc and keep it updated
  • Only publish tags
  • Add a nice version badge
  • Don't get a headache about the configuration

Configure the secret

First of all we need to setup a node auth token in the GitHub Repository as Repository secret.

We can probably generate an Automation token on npm https://www.npmjs.com/settings/<user>/tokens and add it to the repository settings https://github.com/<user>/<repository>/settings/secrets/actions.

I use NODE_AUTH_TOKEN as the name of the secret.

Once you have done that you will be able to add the secret and use it in your GitHub Actions.

Setup node

In the root of the project we add a .nvmrc file and set the latest LTS node version as default:

lts/*

In the workflows we can now reference this file in the setup action:

- name: Setup 🔌
  uses: actions/setup-node@v3
  with:
    node-version-file: '.nvmrc'
    registry-url: https://registry.npmjs.org/

Note to use node-version-file instead of node-version so that the node version only needs to be defined in one place. It is also important to add registry-url, otherwise there may be problems with the authentication.

Publish

Now we can setup the publish task. This task should only run if a new tag is created:

- name: Publish 🚀
  if: startsWith(github.ref, 'refs/tags/')
  run: npm publish --access public
  env:
    NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}

Badge

As a little icing on the cake we can add a npm version badge to the README file:

[![npm](https://img.shields.io/npm/v/<package>)](https://www.npmjs.com/package/<package>)

Conclusion

Keeping it all togehter the worklow could look like this:

name: Build

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v3
        with:
          persist-credentials: false

      - name: Setup 🔌
        uses: actions/setup-node@v3
        with:
          node-version-file: '.nvmrc'
          registry-url: https://registry.npmjs.org/

      - name: Install dependencies 👨🏻‍💻
        run: npm ci

      - name: Run tests 🧪
        run: npm test

      - name: Build 🔧
        run: npm run build

      - name: Publish 🚀
        if: startsWith(github.ref, 'refs/tags/')
        run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}

That's all. Now we can sit back and watch the GitHub Actions auto-publish the release.

Daily automatically fetch and commit with GitHub Actions

For some reasons it may be useful to run GitHub Actions as a scheduled task, called cron jobs, e.g. to regularly fetch data from an API and save it as a file.

A cron job is a task that runs periodically on a given schedule, defined by the Cron expression * * * * *. In our example it will be daily at 00:00 with 0 0 * * *. Other options would be every 5 minutes */5 * * * * or every hour 0 * * * *. Keep in mind that there is a monthly spending limit in minutes to run tasks with Github Actions. For more information about the syntax, see https://crontab.guru/.

I use Git Auto Commit to create and push a commit message. To use this GitHub Action, give the default GITHUB_TOKEN write permissions.

Last but not least, the action that is to be carried out is missing. In this example, npm run fetch triggers a node script.

name: Fetch

on:
  schedule:
    - cron: '0 0 * * *'

permissions:
  contents: write

jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v4

      - name: Setup 🔌
        uses: actions/setup-node@v3

      - name: Install dependencies 👨🏻‍💻
        run: npm ci

      - name: Fetch 🔎
        run: npm run fetch

      - name: Commit
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: Auto fetch

CSS SVG background with Data URIs

One simple and quick solution for SVG background images, like the chevron for select fields:

select {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M1.55021 4.86891C1.83949 4.5992 2.3085 4.5992 2.59778 4.86891L7.99992 9.85571L13.4021 4.86891C13.6913 4.5992 14.1604 4.5992 14.4496 4.86891C14.7389 5.13863 14.7389 5.57593 14.4496 5.84565L8.88911 10.9801C8.77576 11.0901 8.64002 11.178 8.48978 11.2387C8.33515 11.3011 8.16843 11.3333 7.99992 11.3333C7.83141 11.3333 7.66469 11.3011 7.51005 11.2387C7.35982 11.178 7.22409 11.0901 7.11074 10.9801L1.55021 5.84565C1.26093 5.57593 1.26093 5.13863 1.55021 4.86891Z" fill="rgb(153 153 153)"/></svg>');
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 1rem;
}

The syntax is data:image/svg+xml;utf8,<svg ... > ... </svg>. The entire SVG can be inserted as a one-liner, after data:image/svg+xml;utf8,. Watch out by color fills. The # in HEX colors must be escaped as %23, e.g. fill="%23999999". Or use RGB colors instead fill="rgb(153 153 153)".

Git Cheat Sheet

Graph

To visualize the commit history in a graph format, use the following command:

git log --all --decorate --oneline --graph

Clone

Clone to new directory

To clone a repository to a new directory, use the following command:

git clone <url> <name>

Branch

List branches

List existing branches

To list all existing branches, including remote branches, use the following command:

git branch -av

List merged branches

To list branches that have been merged into the current branch, use the following command:

git branch --merged

Delete branch

To delete a branch, use the following commands:

Delete local branch

git branch -d <branch>

Delete remote branch

git push origin :<branch>

Rename branch

To rename a branch, use the following command:

git branch -m <old> <new>

Checkout

Checkout last branch

To switch to the previously checked out branch, use the following command:

git checkout -

Create and checkout a new branch

To create and switch to a new branch, use the following command:

git checkout -b <branch>

Tag

Show last tag

To display the last tag in the repository, use the following command:

git describe --tags

Rename tag

To rename a tag, use the following commands:

git tag <new> <old>
git tag -d <old>
git push origin :<old>
git push --tags

Reset

Reset to last commit

To reset the working directory to the last commit, use the following command:

git clean -df && git checkout -- .

Reset to origin branch

To reset the current branch to the state of the remote origin branch, use the following command:

git reset --hard origin/<branch>

Fetch/Pull/Push

Force push to origin

To forcefully push changes to the remote origin branch, use the following command:

git push -f origin <branch>

Clean up local branches

To clean up local branches that have been deleted on the remote repository, use the following command:

git fetch -p

Automatically prune on every fetch request

To automatically prune deleted branches on every fetch request, use the following command:

git config --global fetch.prune true

Automatically rebase

To automatically rebase when pulling changes from a remote branch, use the following command:

git config --global pull.rebase true

Change remote URL

To change the URL of the remote repository, use the following command:

git remote set-url origin <new>

.htaccess Cheat Sheet

Rewrite rules for www and HTTPS

RewriteEngine On

RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Ignore development environment

RewriteCond %{HTTP_HOST} !^localhost [NC]
RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1$

Redirect non-existing pages

RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

Remove .html extension

RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^([^\.]+)$ $1.html [NC,L]

npm Cheat Sheet

Shorthands

Installing a package:

npm install <package> or npm i <package>

Installing a package globally:

npm i --global <package> or npm i -g <package>

Installing a package and save it as a dependency:

npm i --save <package> or npm i -S <package>

Installing a package and save it as a devDependency:

npm i --save-dev <package> or npm i -D <package>

Running tests:

npm test or npm t

Create a default package.json

npm init -y

List installed packages

npm ls --depth 0

List globally installed packages:

npm ls -g --depth 0

List package dependencies:

npm ls <package>

Running locally installed executables

./node_modules/.bin/<command>

Find your package on the internet

npm repo, npm home or npm docs

Find an other package:

npm home <package>

Bump package version

npm version with major, minor or patch

Remove tag prefix

npm config set tag-version-prefix ''

Use production environment

export NODE_ENV=production

Publishing scoped public packages

npm publish --access public

Terminal Cheat Sheet

Change directory

Go to home directory:

cd

Return to last directory:

cd -

Open current terminal directory

open .

Use working directory as variable

${PWD##*/}

Kill task

kill <PID>

Use ps or ps -ax | grep <name> to find running process IDs.

Django Template Snippets

Prevent duplicate symbols

{% if color|slice:'1' != '#' %}#{% endif %}{{ color|lower }}
{{ price }}{% if price|slice:'-1:' != '€' %}{% endif %}

Regroup and sort lists case insensitive

{% regroup list|dictsort:'name.lower' by name %}

Example: Alphabetical List

{% regroup children|dictsort:'get_menu_title.lower' by get_menu_title.0|title as letter_list %}

<ul>
  {% for letter in letter_list %}
    <li>
      <h3>{{ letter.grouper }}</h3>
      <ul>
        {% for child in letter.list %}
          <li>
            <a href="{{ child.attr.redirect_url|default:child.get_absolute_url }}" title="{{ child.get_menu_title }}">
              {{ child.get_menu_title }}
            </a>
          </li>
        {% endfor %}
      </ul>
    <li>
  {% endfor %}
</ul>

Self-referencing canonical tag

<link rel="canonical" href="{{ request.is_secure|yesno:'https,http'|add:'://'|add:request.get_host|add:request.path }}" />

Numeric for loop

{% for i in 'x'|ljust:'3' %}
    {{ forloop.counter }}
{% endfor %}

JavaScript Snippets

Disable all Links

[...document.querySelectorAll('a')].forEach((el) => {el.addEventListener('click', (e) => {e.preventDefault()});});

Download images

[...document.querySelectorAll('img')].forEach(({src}) => {
    const link = document.createElement('a');
    link.download = src;
    link.href = src
    link.click();
});

Reading time

Math.ceil([...document.querySelectorAll('h1, h2, h3, h4, h5, h6, p, li')].map(({innerText}) => innerText).join(' ').trim().split(/\s+/).length / 250);

Promise: Wait for variable

function waitForCondition(variable) {
  function waitFor(result) {
    if (result) {
      return result;
    }
    return new Promise((resolve) => setTimeout(resolve, 100))
      .then(() => Promise.resolve(window[variable])) 
      .then((res) => waitFor(res));
  }
  return waitFor();
}

window.myVar = null;
waitForCondition('myVar').then((res) => console.log(res));

Aspect ratio

function gcd(a, b) {
    return !b ? a : gcd(b, a % b);
}

function ratio(a, b) {
  return `${a / gcd(a, b)}:${b / gcd(a, b)}`;
}

console.log(ratio(1024, 768))  // '4:3'

Get UTM parameter

export function getUTM() {
	const
		params = new URLSearchParams(window.location.search),
		utm = []
	;

	params.forEach((value, key) => {
		if (key.startsWith('utm_')) {
			utm.push(`${key}=${value}`);
		}
	});

	return utm.join('&');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment