JavaScript Tips | 文字列ユーティリティ:整形 - ケバブケース化

JavaScript JavaScript
スポンサーリンク

ケバブケースってそもそも何か

まず言葉の整理からいきましょう。
「ケバブケース(kebab-case)」は、単語をハイフン - でつなぎ、全部小文字で書くスタイルです。

"userName""user-name"
"UserID""user-id"
"createdAt""created-at"

HTML のクラス名や、CSS のプロパティ名、
一部の設定ファイル(YAML など)では、ケバブケースがよく使われます。

JavaScript の世界では userName(キャメルケース)が主流ですが、
「外に出すときは user-name にしたい」という場面が結構あります。
そのギャップを埋めるのが「ケバブケース化ユーティリティ」です。


何を「ケバブケース」に変換したいのか

業務でよくあるのは、次のような状況です。

JavaScript の変数名・プロパティ名は userName で書いている。
CSS のクラス名や data 属性は user-name にしたい。
設定ファイルや API のパラメータ名がケバブケースで決まっている。

つまり、内部ではキャメルケースやパスカルケース、
外部の世界ではケバブケース、という構造です。

このとき、
「内部の名前 → ケバブケースの文字列」
に変換する小さな関数があると、とても楽になります。


ケバブケース化の基本的な考え方

キャメルケース(userNameId)をケバブケース(user-name-id)にする流れを分解すると、こうなります。

大文字の手前にハイフン - を挿入する。
全体を小文字にする。

例えば userNameId なら、

userNameId
user-Name-Id(大文字の前に - を入れるイメージ)
user-name-id(全部小文字にする)

という変換です。

UserID のように先頭が大文字、かつ大文字が連続するケースもあります。
この場合は、連続する大文字の「切れ目」にハイフンを入れる、という一工夫が必要です。


シンプルなケバブケース化ユーティリティ

実装例

初心者でも追いやすい形で書いてみます。

function toKebabCase(value) {
  if (value == null) return "";

  const str = String(value).trim();

  if (str === "") return "";

  const withHyphen = str
    // 小文字 or 数字の直後に大文字が来たら、その間にハイフンを入れる
    .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
    // 連続する大文字にも対応(UserID → User-ID)
    .replace(/([A-Z])([A-Z][a-z])/g, "$1-$2");

  return withHyphen
    .replace(/[\s_]+/g, "-") // 空白やアンダースコアもハイフンに
    .toLowerCase();
}
JavaScript

やっていることを順番に噛み砕きます。

value == null(null / undefined)のときは空文字を返す。
String(value).trim() で文字列化し、前後の空白を削る。
([a-z0-9])([A-Z]) で「小文字 or 数字の直後の大文字」を見つけて、その間に - を挟む。
([A-Z])([A-Z][a-z]) で「連続する大文字の切れ目」に - を挟む(UserIDUser-ID)。
空白やアンダースコアは - にまとめる。
最後に toLowerCase() で全部小文字にする。

これで、キャメルケース・パスカルケース・スネークケース・スペース区切りなど、
よくあるパターンはだいたいケバブケースに変換できます。


具体例で動きを確認する

キャメルケースからケバブケースへ

toKebabCase("userName");        // "user-name"
toKebabCase("userNameId");      // "user-name-id"
toKebabCase("createdAt");       // "created-at"
JavaScript

JavaScript のプロパティ名を、そのまま CSS クラス名っぽくできます。

パスカルケースからケバブケースへ

toKebabCase("UserName");        // "user-name"
toKebabCase("UserID");          // "user-id"
toKebabCase("HTTPRequest");     // "http-request"
JavaScript

先頭が大文字でも、連続する大文字があっても、
それなりに自然なケバブケースになります。

スネークケース・スペース区切りからケバブケースへ

toKebabCase("user_name");       // "user-name"
toKebabCase("user name");       // "user-name"
toKebabCase("  user  name  ");  // "user-name"
JavaScript

設定ファイルやラベルからキー名を作るときにも、そのまま使えます。


業務での実用的な使いどころ

CSS クラス名や data 属性の生成

例えば、コンポーネント名や状態名から CSS クラス名を作りたいとします。

const componentName = "UserCard";
const state = "isActive";

const baseClass = toKebabCase(componentName); // "user-card"
const stateClass = toKebabCase(state);        // "is-active";

const className = `${baseClass} ${baseClass}--${stateClass}`;
// "user-card user-card--is-active"
JavaScript

内部ではキャメル/パスカルで扱い、
HTML に出すときだけケバブケースにする、という分離ができます。

設定ファイルや API パラメータ名とのマッピング

外部仕様で「パラメータ名はケバブケース」と決まっていることもあります。

const options = {
  maxItems: 10,
  showHeader: true,
};

function buildQuery(params) {
  const query = new URLSearchParams();

  for (const key in params) {
    const kebabKey = toKebabCase(key);
    query.set(kebabKey, String(params[key]));
  }

  return query.toString();
}

buildQuery(options);
// "max-items=10&show-header=true"
JavaScript

内部では maxItems / showHeader で統一しつつ、
外に出すときだけケバブケースに変換できます。


設計として大事なポイント

「内部表現」と「外部表現」を分ける

一番大事なのは、
「内部ではキャメルケースで統一する」と決めてしまうことです。

そのうえで、

外部に出ていくとき(HTML クラス名、data 属性、クエリパラメータなど)はケバブケース化する。
外部から入ってくるとき(設定ファイルなど)がケバブケースなら、入口でキャメルケース化する。

というふうに、「入口」と「出口」で変換する設計にします。

これをやっておくと、

「この名前は userName だっけ? user-name だっけ?」
「CSS と JS で名前が微妙に違ってバグる」

といった混乱が一気に減ります。

変換をその場その場でやらない

悪いパターンは、使うたびにバラバラに変換することです。

toKebabCase("userName");
toKebabCase("userName");
toKebabCase("userName");
JavaScript

どこで何が変換されているのか分からなくなります。

良いパターンは、

「外に出す直前」に一度だけケバブケース化する
それ以外の場所ではキャメルケースだけを使う

という流れにすることです。


小さな練習で感覚をつかむ

コンソールで、いくつか試してみてください。

toKebabCase("userName");
toKebabCase("UserName");
toKebabCase("userNameId");
toKebabCase("UserID");
toKebabCase("user_name");
toKebabCase("  user name id  ");
JavaScript

どういうルールでハイフンが入って、
最終的に全部小文字になっているかを目で確認すると、
「ケバブケース化」の感覚がかなりつかめます。

そのうえで、自分のプロジェクトに

export function toKebabCase(value) { ... }
JavaScript

を一つ置いて、
「HTML や外部仕様で“ケバブケース指定”のところは必ずここを通す」
というルールにしてみてください。

それができた瞬間、あなたのコードは
「命名規則の違いに振り回される側」から
「自分たちのルールに正規化してから外と話す側」に、一段レベルアップします。

タイトルとURLをコピーしました