laurentpayot / minidenticons

Super lightweight SVG identicon (pixelated avatar) generator
https://laurentpayot.github.io/minidenticons
MIT License
408 stars 19 forks source link

Cannot run in CommonJS mode? #9

Closed Pengap closed 3 months ago

Pengap commented 3 months ago

When I specify the item in tsconfig.json as "module": "CommonJS" the startup error is

module.exports = require("minidenticons");
                 ^
Error [ERR_REQUIRE_ESM]: require() of ES Module .../node_modules/.pnpm/minidenticons@4.2.0/node_modules/minidenticons/minidenticons.js from .../nestjs-backend/dist/index.js not supported.
Instead change the require of minidenticons.js in .../nestjs-backend/dist/index.js to a dynamic import() which is available in all CommonJS modules.

import sth. like this

import { minidenticon } from 'minidenticons';

Using it this way

const svgAvatar = minidenticon('xxx');
laurentpayot commented 3 months ago

Hi @Pengap,

Yes minidenticon is ESM only because ESM landed in 2015 and we’re in 2024 :wink:

CommonJS can import ESM, but it has to be async:

const { minidenticon } = await import('minidenticon')

If that’s an issue with your CommonJS Node backend, your can also simply copy the source code in your own module file and export minidenticon the CommonJS way:

const COLORS_NB = 9
const DEFAULT_SATURATION = 95
const DEFAULT_LIGHTNESS = 45

const MAGIC_NUMBER = 5

function simpleHash(str) {
    return str.split('')
        .reduce((hash, char) => (hash ^ char.charCodeAt(0)) * -MAGIC_NUMBER, MAGIC_NUMBER)
        >>> 2
}

module.exports.minidenticon = function(seed="", saturation=DEFAULT_SATURATION, lightness=DEFAULT_LIGHTNESS, hashFn=simpleHash) {
    const hash = hashFn(seed)
    const hue = (hash % COLORS_NB) * (360 / COLORS_NB)
    return [...Array(seed ? 25 : 0)].reduce((acc, e, i) =>
        hash & (1 << (i % 15)) ?
            acc + `<rect x="${i > 14 ? 7 - ~~(i / 5) : ~~(i / 5)}" y="${i % 5}" width="1" height="1"/>`
        : acc,
        `<svg viewBox="-1.5 -1.5 8 8" xmlns="http://www.w3.org/2000/svg" fill="hsl(${hue} ${saturation}% ${lightness}%)">`
    )
    + '</svg>'
}

I hope it helps you. Good luck, because using old CommonJS along with newer ESM is a PITA…