CSS の -webkit-line-clamp プロパティについて2016年12月02日 15時07分

結論からいうと、CSS の -webkit-line-clamp プロパティは使わないほうがいい。現状および今後の Web ブラウザでのサポートが望めないからである。

-webkit-line-clamp CSS プロパティとは何か

複数行でも3点リーダーをきかせることができるというもの。

このプロパティはどうやって使うか

-webkit-line-clamp プロパティ単体では効果を持たず、他のプロパティと組み合わせて使う。

selector {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

このプロパティは何のために存在するのか

おそらくは Apple 製アプリケーションでの内部的な利用のため。このプロパティは、Safari CSS ReferenceAdditional Unsupported Properties の項に記載がある。

WebKit provides partial support for a number of properties that are not supported for developer use. This list may include:

  • Properties designed for Apple internal use, such as properties specific to the way Mail and other applications use WebKit.
  • Properties that are in a very early stage of development and are not really usable yet.
  • Properties that are used within WebKit itself and cannot be parsed in a CSS file.
  • Properties that are parsed for historical reasons, but that are not actually used.

適当に訳すと、

WebKit は、開発者の使用に対してはサポートされないプロパティを、いくつか部分的にサポートしている。このリストには以下を含む:

  • Apple の内部的な利用 (Mail など、WebKit を使うアプリケーションに固有のもの) のために設計されたプロパティ。
  • 開発のごく初期段階であり、まだ実用に耐えないプロパティ。
  • WebKit 内部で使われ、CSS ファイルからはパースできないプロパティ。
  • 歴史的な理由でパースはされるが、実際には使われないプロパティ。

このプロパティの開発状況はどうなっているか

このプロパティは -webkit-box、すなわち旧式の flexbox (flexible box) と組み合わせる必要がある。現 flexbox 仕様とは相いれない。このことから、このプロパティは旧 flexbox 時代に内部利用のため、もしくは実験的に実装され、そのまま放置されたものではないかと推測される。実際に上述の文書ではこのプロパティが「サポートされない」ものとして挙げられている。

このプロパティをベンダ接頭辞なしで書く必要があるか

ない。display: -webkit-box というのは旧 flexbox 仕様の値にベンダ接頭辞をつけたものであり、そこからベンダ接頭辞を外して display: box と書いたところで、どのブラウザもサポートしていない。現 flexbox 仕様では display: flex という全く別の値を使うようになっている。なので、

selector {
  display: -webkit-box;
  display: box;
  -webkit-box-orient: vertical;
  box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

のようにベンダ接頭辞付きのプロパティを併記するのは無意味である。後述するように、line-clamp というプロパティが制定されることもない。

このプロパティは標準化されるのか

line-clamp というプロパティ名では標準化されない。2014 年 6 月の W3C CSS WG のミーティングにおいて、-webkit-line-clamp プロパティのことが議題に上がっている。そこでの結論としては、最大行数の指定とブロックに対する省略記号の問題は別々に議論していこうというものである。

-webkit-line-clamp プロパティの持つ、

  • 最大行数の指定
  • 最大行数をはみ出した内容の扱い
  • 省略記号の表示

という機能は別々のプロパティや疑似要素として CSS Overflow Module で検討されていくことになると思われる。(該当 issue)

余談: ベンダ接頭辞について

開発者が -webkit- ベンダ接頭辞付きのプロパティ / 値しか書かないという状況が蔓延したため、ベンダ接頭辞は無意味なものとなった。今やモバイル向けブラウザの多くは (WebKit でなくとも) -webkit- ベンダ接頭辞付きのプロパティを解釈する。(そうしないとモバイル向け Web サイトがまともに機能しない)

挙句の果てには、――これは CSS ではなく DOM の話だが――webkit 接頭辞付きのメソッドがエイリアスとして仕様に取り込まれるという体たらくである。

これらの反省から、現在のブラウザ開発ベンダはベンダ接頭辞を使わず、開発版ブラウザを使っているときや、ユーザーが明示的にオプションを有効にしたときのみ仕様策定中の機能を有効にするという方針になっている。ベンダ接頭辞は、かつて試験的に実装されたプロパティにつけることはあっても、今後新規に実装されていくプロパティにつける必要はない。

ベンダ接頭辞をつけるにしても、手動でつけていくのではなく、Autoprefixerのようなツールを使って自動的につけていくのが確実である。


この記事は、はてなエンジニアアドベントカレンダー 2016 の 2 日目の記事として公開された。翌日の担当は id:wtatsuru である。

知られてそうで知られてない少し知られてるECMAScript 2015 (ES6)の新機能2016年05月12日 15時38分

Kyoto.js #10で「知られてそうで知られてない少し知られてるECMAScript 2015 (ES6)の新機能」というライトニングトークをしたので、そのスライドに当日しゃべった内容や補足を追記して以下に掲載します。


自己紹介

ECMAScript 2015 (ECMA-262 6th Edtition)

  • クラス構文
  • アロー関数
  • ブロックスコープ
  • Promise
  • etc...

2015年にECMAScriptが大幅に改定されました。クラス構文やアロー関数の追加はあちこちで取り上げられているので皆さんご存知でしょうが、ここではあまり取り上げられていない地味な新機能を紹介します。

Unicodeの符号位置

// 🍣

'\uD83C\uDF63';  // ES5
'\u{1F363}';     // ES6

String.fromCharCode(0xD83C, 0xDF63);  // ES5
String.fromCodePoint(0x1F363);        // ES6

JavaScriptの文字列はUTF-16符号化形式で表現されます。絵文字などBMP(基本多言語面)外の文字はサロゲートペアと呼ばれるふたつの符号単位の組み合わせで表現されるため、これまでエスケープシーケンスを使うときなどには符号単位(16ビット符号なし整数)ごとに指定する必要がありました。ES2015ではUnicodeの符号位置(U+0U+10FFFFまでの値)を直接指定できるようになります。

Unicode正規化

'㍿ 100パーセント'.normalize('NFKC');
// => '株式会社 100パーセント'

'神 森鷗外'.normalize('NFC')
// => '神 森鷗外'

Unicodeには結合文字などの表現形式をそろえる「正規化」という手順が定義されています。ES2015では文字列にnormalizeメソッドが追加され、NFCやNFKCといった複数種類の正規化を適用できるようになりました。

NFKCで文字列を正規化すると、組文字が個々の文字に展開されたり、全角英数字が半角に、半角カタカナが全角にそろえられたりします。正規化を行うことで「神」が「神」になるなど字体が変わってしまうこともあるので注意してください。

正規表現の/uフラグ(unicodeオプション)

/^..$/.test('🍣');  // => true
/^.$/u.test('🍣');  // => true

/\p/.test('p');   // => true
/\p/u.test('p');  // => SyntaxError

これまで正規表現は符号単位ごとにマッチしていましたが、/uフラグを指定することで符号位置ごとにマッチするようになります。

また、未定義のメタ文字があったとき、これまでは\が無視されていましたが、/uフラグ下では構文エラーになります。これにより、将来新たなメタ文字を導入しても、既存の正規表現パターンの挙動が変わってしまうということがなくなります。将来の拡張性確保のためには重要な変更です。

正規表現の/yフラグ(stickyオプション)

let re = /bar/y;

re.test('foobar');  // => false

re.lastIndex = 3;
re.test('foobar');  // => true

通常正規表現マッチは部分一致ですが、/yフラグを付けると前方一致になります。/bar/.test('foobar')はマッチ成功となりますが/bar/y.test('foobar')barが先頭にないのでマッチ失敗となります。

前方一致といいましたが、より正確に言うと正規表現オブジェクトのlastIndexプロパティで指定した位置からの一致になります。上の例ではlastIndex3を指定したので、fooの直後からマッチを試みることになり、マッチが成功しています。

これが役に立つ場面として字句解析があげられます。文字列からトークンを切り出した後、次のトークンを探すときには前回のトークンの終了位置直後から探索できると便利でしょう。

正規表現の挙動の上書き

let regExpLike = {
    [Symbol.match]()   { return 42; },
    [Symbol.replace]() { return 23; },
    [Symbol.search]()  { return 12; },
};
'foo'.match(regExpLike);           // => 42
'foo'.replace(regExpLike, 'bar');  // => 23
'foo'.search(regExpLike);          // => 12

文字列のmatchメソッドなどは、引数として渡されたオブジェクトに処理を委譲するようになりました。Symbol.matchメソッドを持つオブジェクトを引数に渡すことで、そのメソッドの返り値がそのまま文字列のmatchメソッドの返り値となります。

RegExpを継承するオブジェクトなら、execメソッドを上書きするだけでも大丈夫です。

class MyRegExp extends RegExp {
   exec(str) { return [42]; }
}
let re = new MyRegExp;
'foo'.match(re); // => [42]

この挙動の変更は、XRegExpのような正規表現を拡張するライブラリの作成に有用だと思われます。

数学関数の追加

Math.sinh(1);   // => 1.1752011936438014
Math.expm1(1);  // => 1.718281828459045

双曲線関数や常用対数・二進対数関数など、多くの数学関数が追加されています。

Math.expm1(x)Math.exp(x) - 1と同じですが、xが0に近い値のときにより精度の高い結果を返します。

数値に限定した判別関数

isNaN('foo');         // => true
Number.isNaN('foo');  // => false

isFinite('42');         // => true
Number.isFinite('42');  // => false

従来のグローバル関数isNaN / isFiniteは引数を数値に変換してから非数・有限値かどうかを判定していました。ES2015で追加されたNumber.isNaN / Number.isFiniteは引数が数値でなければその時点で偽を返します。

整数の扱い

Math.trunc(3.1);   // => 3
Math.trunc(-3.1);  // => -3

Math.imul(0xFFFFFFFF, 0xFFFFFFFF);  // => 1

Number.isInteger(Math.pow(2, 53));      // => true
Number.isSafeInteger(Math.pow(2, 53));  // => false

Number.MAX_SAFE_INTEGER;
// => 9007199254740991 (2 ** 53 - 1)
Number.MIN_SAFE_INTEGER;
// => -9007199254740991 (- (2 ** 53 - 1))

Math.truncは引数が正の数なら切り下げ(Math.floor)を、負の数なら切り上げ(Math.ceil)を行います。

Math.imulはふたつの32ビット符号なし整数値を乗算し、その結果の下位32ビットの値を返します。単に*演算子を使うと64ビット浮動小数点数の有効桁数を超えたときに不正確な値になってしまいます。

整数かどうかの判定メソッドNumber.isIntegerも追加されました。Number.isSafeIntegerは整数であるかどうかに加えて、64ビット浮動小数点数で一の位まで正確に表せる範囲内かどうかも見ます。新たな定数を使って言うと、Number.MIN_SAFE_INTEGER以上Number.MAX_SAFE_INTEGER以下の整数に対してNumber.isSafeIntegerは真を返します。

completion valueの変化

eval('42; if (true) {}');  // ES5 => 42
eval('42; if (true) {}');  // ES6 => undefined

ECMAScript仕様では、式や文の評価結果(返り値や制御フロー)を表すcompletion recordという値が定義されています。これは概念的なものであり、各JavaScriptエンジンがcompletion recordという値を実装しているとは限りません。completion recordに基づく文の評価結果、いわば「文の返り値」は通常触れることはできませんが、eval関数の結果としてその値を確かめられます。

ES2015ではif文やfor文といった制御構文におけるcompletion recordの扱いが少し変更されました。ES5までは制御構文の本体が空だったとき、プログラム全体の返り値はその制御構文の直前の文の返り値を引き継いでいました。ES2015からは制御構文の本体が空ならundefinedが返るようになります。

この変更は主にJavaScriptエンジンの実装の都合によるものです。これまでは制御構文の評価に移ってもそれ以前の文の返り値を保持しておく必要がありました。ES2015に沿った実装なら制御構文の評価に移った時点でそれ以前の文の返り値を破棄してもよく、実装に最適化の余地が生まれると考えられます。

HTMLのようなコメント (付属書B: Webブラウザのための追加機能)

<!--
doSomething();
-->

HTMLのscript要素内にJavaScriptを書くときなど、要素の内容全体を<!-- -->で囲むことがあります。このとき<!---->も単一行コメントとみなされますが、この挙動はECMAScriptで定義されたものではなく、あくまで各Webブラウザの独自拡張という扱いでした。

ES2015では(仕様本文ではなく)付属書において<!-- -->をコメントとして扱う構文を定義しています。ただし、あくまでWebブラウザが後方互換性を確保するために実装するものであり、ブラウザと直接関係ない実装(Node.jsなど)がこの構文に対応することは推奨されていません。プログラマもこうしたレガシーな機能を使うべきでないとされています。

flexbox レイアウトで内容がはみ出す理由2016年04月03日 02時23分

flex box layoutで中に長いテキストなどを含む幅可変要素のレイアウト - くらげだらけ」という記事が興味深いです。過去に「長い英単語を途中で折り返したいときの CSS の指定方法」にて、word-wrap: break-worddisplay: inline-block などの組み合わせには注意が必要 (word-wrap の指定が効かないように見えることがある) と述べたのですが、似たようなことが display: flex にも言えるようです。

この挙動は認識していなかったので CSS Flexible Box Layout Module Level 1 (flexbox 仕様草案、2016 年 4 月 2 日時点のもの) を見てみたところ、「4.5. Implied Minimum Size of Flex Items」(flex アイテムの暗黙的な最小サイズ) の項に記述がありました。

flex アイテム (display: flex または display: inline-flex を指定した要素の子要素) の最小幅 (flex アイテムが水平方向に並ぶ場合) は、(min-width プロパティで明示的に指定していなければ) flex アイテムの内容の最小幅または flex アイテムに width プロパティで明示的に指定された幅などのうち、最も小さいものになる (flex アイテムの幅がそれ以上縮むことはない) そうです。

ここで「内容の最小幅」を算出するときには word-wrap: break-word の影響を考慮できません (break-word は行ボックスの幅からあふれる単語に影響を与えるが、最小幅を算出しようという段階では行ボックスの幅も定まっていない)。なので、widthmin-width も明示的に指定していない flex アイテムの内容に長い英単語があると、その単語の幅まで flex アイテムの幅が拡張されるということのようです (そして min-width が明示的に指定されていればそのようなことは起こらない)。仕様の注意書きには以下のように書かれています。

文書中の主要な領域に flex を使うなら、min-width: 12em のように明示的に最小幅を指定したほうがよい。そうでないと巨大な表や画像があったときに内容がはみ出して読みづらくなることがある。

Note - 4.5. Implied Minimum Size of Flex Items - CSS Flexible Box Layout Module Level 1 より抄訳

ではなぜこのような仕様になっているのでしょうか? 最初はパフォーマンス上の理由かと思いましたがそうではなく (flex アイテムの内容が膨大なときには、むしろパフォーマンスに悪影響を及ぼしうる)、製作者の意図しない奇妙な表示結果を避けるためだそうです。fantasai (flexbox 仕様編集者の一人) による暗黙的な最小サイズの解説に、どんな場面でどんな挙動を想定しているかの例も載っていました。主には「複数のナビゲーション項目を flex で並べたいが、画面幅が狭くて収まりきらない場合」の救済措置を意図しているようです。

奇妙な表示結果を避けるための仕様が、ある場面では逆に制作者の意図しない「奇妙な表示結果」を生み出しているというのが面白いですね。

補足: CSS 仕様の導入の経緯の調べ方

この記事を書くにあたって特定の CSS 仕様が導入された経緯について調べたのですが、その具体的な手順は以下の通りです。

  1. 何はともあれまずは最新の仕様草案を確認する。
  2. flexbox 仕様草案を斜め読みしていく。
    • 4.5. Implied Minimum Size of Flex Items」で min-widthmin-height プロパティを再定義しているのを見つける。
    • 9. Flex Layout Algorithm」もざっと追おうとするが、分量も多く複雑なので断念。
    • 大元の記事に関する仕様草案の記述個所はわかったが、なぜそのような仕様になっているのかはわからない。
  3. その仕様がいつ導入されたのかを確認する。
  4. メーリングリストでの議論を追う。
    • 仕様草案の Status of this document から、W3C CSS メーリングリストのアーカイブページに移動。
      • 2012 年 3月、4 月、5 月のメール一覧ページ (by thread) を見る。
    • メール一覧ページを「css3-flexbox」でページ内検索し、関連しそうなスレッドがないか探すも見つからない
  5. 検索する。
  6. ミーティングでの議論を追う。
    • 仕様の方針決定は CSS ワーキンググループ (CSS WG) のミーティングでなされることも多いので、「CSS WG MTG」でググるもミーティング一覧が出てこない。
    • 「CSS WG F2F」(F2F は Face-to-Face の略、実際に顔を突き合わせてのミーティング) でググったらミーティング一覧ページが出てきた。
    • 時期的に近そうな 2012 年 5 月ハンブルグ F2F の議事録 (Part I) を見たところ、議題「Flexbox: Flex Property and Flex Sizing」の中に「Next Issue: Implied minimum size of flexbox items」という項目があった。
      • ここで flex アイテムの最小幅の問題について取り上げられている。

Windows 10 で Emacs キーバインディングを利用するための設定のメモ2016年01月31日 11時26分

Windows の操作全般および MS-IME で Emacs のようなキーバインディングを利用するための個人的なメモ。

Ctrl キーの位置調整

Change Key を利用。管理者として実行する。

  • CapsLock → Ctrl (左)
  • カタカナ/ひらがな → Shift (右)
  • 半角/全角 → Esc

XKeymacs の設定

XKeymacs のスナップショットバージョンを利用。Explorer を「管理者として実行」し、その上で C:\Program Files にフォルダをコピー。

dot.xkeymacs

以下の内容でファイル %APPDATA%\dot.xkeymacs (たいていは C:\Users\{user}\AppData\Roaming\dot.xkeymacs) を作成。

(fset 'browser-back [browser-back])
(fset 'browser-forward [browser-forward])
(fset 'find-next [f3])
(fset 'find-previous [?\S-f3])

プロパティの「基本」タブ

  • 「アクティブウィンドウから離れる」の C-z 及び M-F12 を無効化
    • C-z は素通しさせ、「元に戻す」として扱う。
  • 「消去、編集」の C-t 及び C-x C-t を無効化
    • C-t は screen でのメタキーとしてのみ用い、他の用途には使わない。
  • 「その他」の Esc 及び C-[ を無効化
    • メタキーには Alt のみ用い、Esc は Esc としてのみ用いる。
  • 「IME の切替え」の全項目を無効化
    • IME のオン / オフは変換 / 無変換キーで行う。
  • 「その他」の C-x h を無効化
  • 「移動」の C-l、「消去、編集」の C-k、「その他」の C-u を無効化
    • MS-IME に対して「XKeymacs を無効にする」としていても、Firefox など (IME で入力中の文字列を自前で描画するアプリケーション?) では MS-IME での入力中に XKeymacs の設定が適用されてしまうので、MS-IME のキー設定と干渉するものは無効化しておく。
  • 「その他」の C-0 ... C-9 を無効化
    • 誤爆しかしない。必要なコマンドの数を事前に算出し、正しい数値のキーを打つのは私には困難。

プロパティの「詳細」タブ

  • 「その他」の Esc に Ctrl + [ を割り当て
    • C-[ は Meta ではなく単なる Esc として用いる。
  • 「その他」の Temporarily Disable XKeymacs に Ctrl + ; を割り当て
    • C-; C-○ と打つことでネイティブのショートカットキーを利用できる。";" (セミコロン) はホームポジションなので打つのも簡単。
  • 「その他」の Select All に Ctrl + X H を割り当て
    • Firefox Nightly で C-x h が期待通り動作しないので、これをネイティブの「すべて選択」に置換する
  • 「その他」の newline に Ctrl + J を割り当て
  • 「オリジナルコマンド」の browser-back に Meta + , を、browser-forward に Meta + . を、find-next に Ctrl + . を、find-previous に Ctrl + , をそれぞれ割り当て
    • "," (カンマ) は "<" (小なり) すなわち「←」(戻る方向) を、"." (ピリオド) は ">" (大なり) すなわち「→」(進む方向) を、それぞれ表す。

MS-IME の設定

  • 「スペースの入力」を「常に半角」
  • 「Shift キー単独で英数モードに切り替える」を有効化
  • 英数字及び記号類を「常に半角に変換」、ただし「~」のみ「変換しない」

MS-IME のキー設定

インポート / エクスポート機能がなさそうなので、ひとつずつ設定しなおしている。

キー 入力/変換済み文字なし 入力文字のみ 変換済み 候補一覧表示中 文節長変更中 変換済み文節内入力文字 備考
無変換 IME-オフ 全消去 文節戻し 候補閉 文節戻し 全戻し 何もなければ IME オフ、ほかは Esc と同じ
Shift + 無変換 かな切替 かな切替 かな切替 かな切替 かな切替 かな切替
変換 IME-オン 何もなければ IME オン、ほかは変更なし
Ctrl + 変換 再変換 何もなければ再変換、ほかは変更なし
Ctrl + A 文字先頭 文節先頭 候補先頭 - 文字先頭 Home と大体同じ
Ctrl + B 文字左 文節左or文字左 文節左or文字左 文節左 文字左 「←」と同じ
Ctrl + C - - - - - 握りつぶす
Ctrl + D 1文字削除 1文字削除 候補閉 - 1文字削除 Delete と同じ
Ctrl + E 文字末尾 文節末尾 候補最後 - 文字末尾 End と大体同じ
Ctrl + F 文字右 文節右 文節右 文節右 文字右 「→」と同じ
Ctrl + G 全消去 文節戻し 候補閉 文節戻し 全戻し Esc と同じ
Ctrl + I 予測候補表示 - 候補表示切替 - - Tab と同じ
Ctrl + J 全確定 全確定 候補選択+確定 全確定 全確定 Enter と同じ
Ctrl + N 全変換 変換+次 変換+次 文節変換 全変換
Ctrl + P 全変換 前候補 前候補 文節変換 全変換
Ctrl + Q - - - - - 握りつぶす
Ctrl + R - - - - - 握りつぶす
Ctrl + S - - - - - 握りつぶす
Ctrl + U カタカナ カタカナ カタカナ カタカナ カタカナ
Ctrl + V - - - - - 握りつぶす
Ctrl + W - - - - - 握りつぶす
Ctrl + X - - - - - 握りつぶす

Ctrl + H/K/L/M/O/T/Y/Z は変更なし。

MS-IME のキー設定の「機能選択」には「-」という項目がふたつ存在するが、先頭のものは MS-IME を利用しているアプリケーション側にそのキーを伝え、末尾のものは MS-IME 内でそのキーを握りつぶす。

漢字にマッチする JavaScript の正規表現パターン2015年12月31日 23時03分

たまに漢字にマッチする正規表現パターンを書きたいときがあります。Perl の正規表現だと Unicode のスクリプト名を使って \p{Han} で漢字にマッチさせられるのですが、JavaScript ではそうはいきません。JavaScript の正規表現には以下のふたつの問題があります。

  1. Unicode スクリプト名の指定 (\p{...}) に対応していない。
  2. そもそも Unicode の符号位置に対してマッチさせられない (UTF-16 における符号単位に対するマッチになる)。

とはいえ、解決不能な問題というわけでもないので、Perl の \p{Han} を JavaScript に移植してみましょう。\p{Han} の範囲は以下のコマンドで参照できます。

perl -MUnicode::UCD -MData::Dumper -E 'say Dumper Unicode::UCD::charscript("Han");'

Perl 5.20.2 (Unicode 6.3.0) では以下の範囲が含まれるとわかりました。

  • U+2E80 - U+2E99
  • U+2E9B - U+2EF3
  • U+2F00 - U+2FD5
  • U+3005 - U+3005
  • U+3007 - U+3007
  • U+3021 - U+3029
  • U+3038 - U+303B
  • U+3400 - U+4DB5
  • U+4E00 - U+9FCC
  • U+F900 - U+FA6D
  • U+FA70 - U+FAD9
  • U+20000 - U+2A6D6 (\uD840\uDC00 - \uD869\uDED6)
  • U+2A700 - U+2B734 (\uD869\uDF00 - \uD86D\uDF34)
  • U+2B740 - U+2B81D (\uD86D\uDF40 - \uD86E\uDC1D)
  • U+2F800 - U+2FA1D (\uD87E\uDC00 - \uD87E\uDE1D)

サロゲートペアが [\uD800-\uDBFF][\uDC00-\uDFFF] であることを踏まえると、BMP 外の範囲はそれぞれ以下の部分的な範囲に展開できます。

  • \uD840\uDC00 - \uD869\uDED6
    • [\uD840-\uD868][\uDC00-\uDFFF]
    • \uD869[\uDC00-\uDED6]
  • \uD869\uDF00 - \uD86D\uDF34
    • \uD869[\uDF00-\uDFFF]
    • [\uD86A-\uD86C][\uDC00-\uDFFF]
    • \uD86D[\uDC00-\uDF34]
  • \uD86D\uDF40 - \uD86E\uDC1D
    • \uD86D[\uDF40-\uDFFF]
    • \uD86E[\uDC00-\uDC1D]
  • \uD87E\uDC00 - \uD87E\uDE1D
    • \uD87E[\uDC00-\uDE1D]

これらを整理して組み合わせると、最終的に以下のパターンが得られます。

/(?:[\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u3005\u3007\u3021-\u3029\u3038-\u303B\u3400-\u4DB5\u4E00-\u9FCC\uF900-\uFA6D\uFA70-\uFAD9]|[\uD840-\uD868][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|[\uD86A-\uD86C][\uDC00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D])/

というわけで「漢字 1 文字にマッチする JavaScript の正規表現パターン」でした。よいお年を。