Created
January 20, 2023 08:53
-
-
Save sachin-hg/32a0a161b045bfd01beaaa1b55f850aa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const {htmlTagNames} = require('html-tag-names') | |
// get a list of all known html tag names and convert it into a map example: | |
// {body: true, head: true, li: true, h1: true, p: true} and so on | |
const tags = htmlTagNames.reduce((res, tag) => { | |
res[tag] = true | |
return res | |
}, {}) | |
// incremental number to generate baseX | |
let val = 0 | |
// cache of already generated classnames | |
const map = {} | |
// possible list of characters in the generated classnames | |
let codeset = | |
' _0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' | |
function toBaseX (n) { | |
let base = codeset.length | |
let converted = '' | |
while (n > 0) { | |
converted = codeset[n % base] + converted | |
n = Math.floor(n / base) | |
} | |
return converted | |
} | |
// conditions | |
// 1. className must not start with a digit [0-9]: check: isNaN(parseInt(value, 10)) | |
// Reason: CSS Spec doesn't allow classnams to start with digits | |
// 2. className must not include a space. check: !value.includes(' '). | |
// Reason: CSS Spec doesn't allow classnames to start with space | |
// FAQ: why do we have a space character in 'codeset', well as a hack, because otherwise this logic wont generate valid classnames | |
// like _A, _C. basically the ones starting with underscore | |
// 3. generated className must not be present in the list of known htmlTagNames | |
// Reason: sometimes developers use silly declarations like: .h1{font-size: 12px} .img {opacity: 0} | |
// therefore we dont want our generated classnames to clash with them | |
// 4. Opinionated: generated classNames with length >= 3 must begin with an underscore or with a Uppercase character | |
// check: (value[0] === value[0].toUpperCase() || value.length < 3) | |
// Reason: in our codebase when developers write classNames they usually use camel-casing or snake-casing or hyphen-seperated classnaes | |
// like: iAmAClasName i_am_a_class_name i-am-a-class-name. | |
// But they never write a classname starting with an uppercase character like: IAmNotAValidDeveloperWrittenClassName | |
// and they "almost always" write atleast 3 character long classnames [not starting with an underscore] | |
// since we dont want our generated classnames to conflict with developer-written-classnames. Hence these checks | |
const getNextClassName = () => { | |
while (true) { | |
let value = ++val | |
value = x(value) | |
if ( | |
!value.includes(' ') && | |
isNaN(parseInt(value, 10)) && | |
!htmlTagNames[value] && | |
(value[0] === value[0].toUpperCase() || value.length < 3) | |
) { | |
return value | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment