Skip to content

Instantly share code, notes, and snippets.

@sachin-hg
Created January 20, 2023 08:53
Show Gist options
  • Save sachin-hg/32a0a161b045bfd01beaaa1b55f850aa to your computer and use it in GitHub Desktop.
Save sachin-hg/32a0a161b045bfd01beaaa1b55f850aa to your computer and use it in GitHub Desktop.
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