Snippets in JavaScript: Converting PascalCase to kebab-case // Integrating with ShadowDOM
Have you ever wanted to convert a string written in either PascalCase
or camelCase
to a hyphenated kebab-case
? Of course you have; we all have. I get asked how to do this maybe 42 times per day, so here’s how you do it.
A Regular Expression
In JavaScript:
How about in PHP?
What about C#?
How does it work?
The regular expression looks for a lowercase alphanumeric character [a-z0–9]
followed by an uppercase alpha character [A-Z]
, both in a capture group (xyz)
. We use $1
and $2
because we want to retain the characters, but put something in between them.
If you were to replace it with $1.$2
, you’d end up with a result like: my.paragraph.element
When would you use this?
This could be used for automatically inferring class names like converting MyParagraph
to my-paragraph
which is handy for autoloading ShadowDOM elements (or similar in PHP).
Example: https://jsfiddle.net/tbkhczd7/1/
Let’s look at two files: index.html
and a main.js
.
In the HTML below, you can see that we have two custom tags being utilized named my-paragraph
and labeled-input
.
They are defined using HTML’s template tag. Read more on MDN to better understand their capabilities and how to use <slot>
if you’re unfamiliar.
These templates are one half of what defines our ShadowDOM elements. They provide the structure, allow customization, and utilize scoped <style>
tags for visual representation.
The other half required is JavaScript to define and initialize the elements. There’s a fair amount of code here, but the gist is:
- Extend
HTMLElement
to abstract common functionality - Derive specific classes from the aforementioned
- Associate our classes to our templates
Note that you could extend any element you want, not just HTMLElement
; if you wanted to beef up a button, you could do something like this:
class MyButton extends HTMLButtonElement { ... }
Below, you’ll see in the static attach(...)
method, we use our PascalCase
converter mentioned earlier in this article.
Read through the code and we’ll catch up down below.
The functionality provided within LabeledInputElement
and MyParagraphElement
are just demonstrative to illustrate how they have the ability to scope events/logic.
In our static attach(template) { ... }
method, you can see there’s a null check against template
at which point it attempts to convert our class name into what the expected HTML tag would be. There’s additional logic you could add here to ensure the element exists, but for the sake of example we’re assuming that our coupled templates should exist.
At the bottom, the uncommented example iterates through all available <template>
tags and reverses kebab-case
to PascalCase
in an attempt to find the defined class. Again, you should add logic here to ensure what you’re looking for actually exists, but this is a demo.
By using our two string conversions, we’re able to easily create and autoload custom ShadowDOM elements just by using basic definitions; two steps:
- Create a
<template>
with a uniquekebab-case
identifier - Create a class with a similar
PascalCase
identifier
Now you can cleanly create classes + templates and autoload them without the hassle of maintaining coupled definitions.