Skip to content

Instantly share code, notes, and snippets.

@nathansmith
Last active October 24, 2024 17:00
Show Gist options
  • Save nathansmith/a71df3d26fc0a5b9a2e2a20427cd974f to your computer and use it in GitHub Desktop.
Save nathansmith/a71df3d26fc0a5b9a2e2a20427cd974f to your computer and use it in GitHub Desktop.
Helper to reduce a large string to a smaller ID.
/*
=====
NOTE:
=====
➡️ Actually, if you just want a random ID that works
even outside of SSL (localhost) you can just do this.
*/
// ======================
// Helper: get random ID.
// ======================
const getRandomId = (): string => {
// Expose string.
return (
// Prefer real UUID.
window.crypto.randomUUID?.() ||
// Or use a fallback.
`${Date.now()}-${Math.random()}`.replaceAll('.', '')
);
};
// Export.
export { getRandomId };
// ==========
// Constants.
// ==========
const KEY_LIST: string[] = [
'a', // 0.
'b', // 1.
'c', // 2.
'd', // 3.
'e', // 4.
'f', // 5.
'g', // 6.
'h', // 7.
'i', // 8.
'j', // 9.
];
const SPACE = ' ';
const SPACE_REGEX = /\s+/g;
// ==================================
// Helper: convert ID to hash string.
// ==================================
const getHashId = (value: string): string => {
// Clean up.
const newValue = value.trim().replace(SPACE_REGEX, SPACE);
// Set later.
const keyCount: Record<string, number> = {};
// Loop through.
for (let i = 0; i < newValue.length; i++) {
// Update.
const numStr = newValue.charCodeAt(i).toString();
// Loop through.
for (const num of numStr) {
// Get key.
const key = KEY_LIST[parseFloat(num)];
// Update.
keyCount[key] |= 0;
keyCount[key]++;
}
}
// Loop through.
const hashList = Object.entries(keyCount).map(([key, count]) => `${key}${count}`);
// Expose string.
return hashList.join('');
};
// Export.
export { getHashId };

EXAMPLE USAGE

🔓 This is not crypographically strong, simply a way to generate a shorter unique string from a longer one.

It is potentially helpful when creating a unique id="…" to associate elements such as tab and tabpanel within a tablist.

I wanted something that is lighter than the NPM uuid package, and does not use async promises. That way, it can be called directly within a JS template without having to rely on await or then callback chains.

import { getHashId } from './getHashId';

const example1 = getHashId(
  'EXAMPLE_UNIQUE_HUMAN_READABLE_ID_THAT_HAS_LOTS_OF_CHARACTERS_CONTAINED_THEREIN'
);

const example2 = getHashId(
  'ANOTHER_SILLY_EXAMPLE_WITH_VERY_LONG_TEXT_TO_SHOW_THAT_HASH_IS_UNIQUE_AFTER_CONVERSION'
);

const example3 = getHashId(
  '🦊🐶 The quick brown fox jumps over the lazy dog.'
);

const example4 = getHashId(`
  😎👍

  Lorem ipsum odor amet, consectetuer adipiscing elit. Finibus
  et vitae maximus augue sollicitudin dignissim ultricies nibh
  eros. Morbi integer lobortis blandit molestie litora magnis.

  Maecenas mi nunc litora praesent elit scelerisque. Morbi
  pretium fermentum fringilla vel; sagittis tempus maecenas
  ullamcorper. Ac curae mus ad libero mauris ex integer cursus.

  Faucibus facilisis purus sapien tempus orci. Mattis scelerisque
  vulputate placerat ridiculus tincidunt iaculis odio. Porttitor
  fringilla suspendisse volutpat ligula natoque praesent scelerisque.
`);

// Logs: "g29j23i28f23h28a2d7b1c9e6"
console.log(example1);

// Logs: "g20f21h33i36j30e8c10d10a2b2"
console.log(example2);

// Logs: "f10d14i5g5h7b55e8c15a16j6"
console.log(example3);

// Logs: "f112d88h83g51i43e46j105c91b691a221"
console.log(example4);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment