Skip to content

Instantly share code, notes, and snippets.

@Schascha
Last active May 3, 2024 07:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • 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

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

Clone to new directory

git clone <url> <name>

List all existing branches

git branch -av

Checkout last branch

git checkout -

Create and checkout a new branch

git checkout -b <branch>

Delete branch

Delete local branch:

git branch -d <branch>

Delete remote branch:

git push origin :<branch>

Rename branch

git branch -m <old> <new>

Show last tag

git describe --tags

Rename tag

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

Reset to last commit

git clean -df && git checkout -- .

Reset to origin branch

git reset --hard origin/<branch>

Force push to origin

git push -f origin <branch>

Clean up local branches

git fetch -p

Automatically prune on every fetch request:

git config --global fetch.prune true

Change remote URL

git remote set-url origin <new>

Automatically rebase

git config --global pull.rebase true

.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