NodeJS SVG to Animated Gif

Needed an to take an SVG and individually grab frames of the same SVG and place them into an animated gif. This lib simplifies it to await gif.addFrame(svgString, delay).

img-min--1--1

The SvgGif util below simplified the use of gif-encoder, convert-svg-to-png, and png-js.

const fs = require('fs');
const GifEncoder = require('gif-encoder');
const { convert } = require('convert-svg-to-png');
const Png = require('png-js');

function decode(data) {
    return new Promise((resolve) => {
        new Png(data).decode((pixels) => {
            resolve(pixels);
        });
    });
}

class SvgGif {
    constructor({ width, height, fileName = 'img.gif', repeat = 0 }) {
        // Create GIF
        this.gif = new GifEncoder(width, height);
        this.gif.setRepeat(0);
        this.gif.on('error', (err) => console.log(err));

        // Collect output
        const file = fs.createWriteStream('img.gif');
        this.gif.pipe(file);
        this.gif.writeHeader();
    }

    async addFrame(svg, delay = 1000) {
        this.gif.setDelay(delay);
        const data = await convert(svg);
        const pixels = await decode(data);
        this.gif.addFrame(pixels);
    }

    finish() {
        this.gif.finish();
    }
}

module.exports = SvgGif;

Example usage:

const SvgGif = require('./SvgGif');

const width = 1280;
const height = 720;

var svg = `
    ... place full svg file contents here ...
`;

(async () => {

    const gif = new SvgGif({
        width,
        height,
        fileName: 'img.gif'
    });

    console.log(`Generating...`);
    
    // Render 1 frame for 1 second
    await gif.addFrame(svg, 1000);
    
    // Modify SVG here and render frame
    await gif.addFrame(svg, 1000);
    
    // Done
    gif.finish();
    console.log(`Done.`);
})();

LWC and GitHub Actions / Pages

Sharing what you create with lwc.dev can be as easy as adding a GitHub Action to deploy to GitHub Pages.

  • GitHub Pages are static pages hosted at user.github.io/
  • These static files live in your github.com/user/user.github.io repo.
    • Create a blank repo with this name if it doesn't exist.
  • GitHub Actions are .yml files in the .github/workflow/file.yml directory of your project. These can subscribe to events, like a user pushing to the master branch, and then spin up a docker container to do anything.

The script below is going to do a few things.

  • Checkout your projects files
  • npm install
  • npm run build (build LWC application to /dist)
  • Clone our user.github.io repo.
  • Copy /dist/* to a folder in the user.github.io/ folder.
  • (optional, we need non-absolute paths in index.html, so remove / at the start of urls)
  • Git Add + Commit + Push to user.github.io.

The script will also need a few secrets added. Once a secret is set in the repo settings tab it becomes readonly.

  • GIT_USER - Your username or bot account
  • GIT_TOKEN - Personal Token (treat this like a password!)
  • GIT_EMAIL - Used for commit.
  • GIT_NAME - Your name or a "Bot"

Secrets are also removed from logs. For instance if you don't want your email or name in the logs, save them as secrets!
You can use any user as long as they have write access to the repository.

name: CD

on:
  push:
    branches:
    - master

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    - name: Checkout
      uses: actions/setup-node@v1
      with:
        node-version: 10.x
    - name: npm install, build, and deploy
      run: |
        npm install
        npm run build
        git clone https://${{ secrets.GIT_USER }}:${{ secrets.GIT_TOKEN }}@github.com/Templarian/templarian.github.io
        cp -rf dist/. templarian.github.io/lwc-ui/
        cd templarian.github.io
        git config --global user.email "${{ secrets.GIT_EMAIL }}"
        git config --global user.name "${{ secrets.GIT_NAME }}"
        sed -i 's/"\//"/g' lwc-ui/index.html
        git add .
        git commit -m "Deploy lwc-ui"
        git push

In the above script replace templarian with the name of your user. The secret GIT_USER could be used here, but it's important to illustrate that another user with access could be used. Such as a bot account.

Similar GitHub Actions can be used to sync files between repositories. You can also parse the commit message and only build when a certain word is found.

Debug LWC Jest Tests with VS Code

It's as easy as adding a launch.json in the .vscode folder.

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
      {
        "type": "node",
        "request": "launch",
        "name": "Jest Tests",
        "program": "${workspaceRoot}/node_modules/.bin/jest",
        "cwd": "${workspaceRoot}",
        "args": ["-i", "--runInBand", "${relativeFile}", "--no-cache"]
      }
    ]
  }
  

On the left select the debug menu, and the play while viewing the .spec.js file you wish to debug. Be sure to place a breakpoint first.

MDI Light v0.2.63

Around 2 years ago I got the idea of making an alternative to MDI that favored a slightly lighter style with the same consistent design. Unfortunately it always sat second to all of my other open source efforts (mainly MDI).

MDI Light Preview

Now with the effort of the MDI contributor team we're working to make MDI Light a first class icon set! This will mean regular updates and improvements from the community.

The only real difference is that for an icon to exist in MDI Light it must first exist in MDI. The team views this as a way to ensure MDI gets icons first and that we can perfectly map codepoints in the font between the two.

NPM

  • npm i @mdi/light-font | NPM | GitHub
  • npm i @mdi/light-svg | NPM GitHub |
  • npm i @mdi/light-js | NPM | GitHub
  • npm i @mdi/react - Same react library works great for MDI Light.

Future

MDI Light is a side project for our team, but over the next year we're going to quickly add icons to ensure it's a great alternative for everyone.

Everything will live under the @mdi organization on NPM.