このファイルは、このリポジトリで作業する Claude Code (claude.ai/code) 向けのガイドです。
- 日本向けのライブラリなので、ユーザーとのやり取り・ドキュメント(README、CLAUDE.md など)・コードコメント・XML ドキュメントコメント・コミットメッセージ・PR の説明はすべて日本語で書く。
- コミット・push・PR 作成は頼まれたときだけ行う。master で作業せず、ブランチを切ってから PR にする(依存する変更が続くときは、頼まれたら stacked PR にする)。
- PR のマージはユーザーが行う。「マージした」と言われたら master を pull し、マージ済みのブランチを削除する。
- ライブラリは 3 つ(SDK スタイル)。ビルドは
dotnet build ZipConvertCustomerBarCode.sln。ZipConvertCustomerBarCode: コア。netstandard2.0とnet8.0。外部依存を追加しない(描画ライブラリに依存させないのが分割の目的。System.Memoryも入れない)。Span<T>などは#if NET8_0_OR_GREATERの中だけで使い、#elseにnetstandard2.0用の処理を書く。#ifは小さな範囲(メソッドや構造体の中)に閉じ込め、共通にできる部分は共通のメソッドにする。Spanを使うのは計測で効果があった箇所のみ(住所照合の正規化、CSV の読み込み)。Spanを使わなくても両方で速くできる場合は、#ifを使わず共通のコードにする。
ZipConvertCustomerBarCode.Drawing: System.Drawing.Common による描画(Windows のみ)。ZipConvertCustomerBarCode.SkiaSharp: SkiaSharp による描画。名前空間はSkiaSharpとの衝突を避けるためZipConvertCustomerBarCode.Skia。
ZipConvertCustomerBarCode.Demo: デモサイト(Blazor WebAssembly、net10.0、パッケージにはしない)。コアのBarCode.CreateとToSvg/ToPrintSvgだけを使い、郵便番号データは使わない(12万件あり、ブラウザーで読み込むには重い)。InvariantGlobalizationで ICU を省いている(コアはカルチャに依存しない)。ソリューションに含めているので、CI の test でビルドされる。README の画面のスクリーンショットはdocs/demo.png(NuGet のパッケージページでも表示されるよう、README からは raw.githubusercontent.com の絶対 URL で参照する)。- ローカルでは
dotnet run --project ZipConvertCustomerBarCode.Demoで起動する。Razor では@codeが予約語なので、変数名にcodeを使わない。
- ローカルでは
netstandard2.0の既定 C# は 7.3。#if NET8_0_OR_GREATERの外ではrecordや null 許容参照型など新しい構文は使わない。- バージョン・著作権表示・パッケージ情報は
Directory.Build.propsにまとめている。パッケージアイコンicon.png(128×128)は、このライブラリで作ったバーコードの先頭4シンボル(スタート + 郵便番号3桁)を縦に伸ばし、紺地に白で描いたもの。dotnet run tools/GenerateIcon.cs -- icon.pngで生成する(色・拡大率・余白もこのスクリプトにある)。デモサイトのファビコンZipConvertCustomerBarCode.Demo/wwwroot/icon.pngも同じ画像なので、作り直したらコピーする。 - 公開メンバーには XML ドキュメントコメントを付ける(
GenerateDocumentationFile有効のため、ないと警告になる)。CI(GITHUB_ACTIONS)ではTreatWarningsAsErrorsで警告をエラーにしている(依存パッケージの脆弱性の警告 NU1900〜NU1904 は除く)。ローカルで CI と同じ確認をするときはdotnet build -p:TreatWarningsAsErrors=trueのように付ける。 .csファイルは UTF-8(BOM 付き、.editorconfigにも記載)。新規ファイルにも BOM を付ける(.claude/settings.jsonのフックが Write / Edit 後に自動で補う)。CI のformatジョブがdotnet format --verify-no-changesで.editorconfigに従っているか確認するので、崩れたらdotnet format ZipConvertCustomerBarCode.slnで直す。改行はcore.autocrlf=trueに従う(Windows の作業ツリーでは CRLF、リポジトリ内は LF)。
dotnet testで実行(xUnit v3、net10.0)。global.jsonで Microsoft.Testing.Platform を指定しているため、Microsoft.NET.Test.Sdkやxunit.runner.visualstudioは追加しない。- コアは
#ifで処理が分かれるため、変更したら両方のビルドでテストする:dotnet test(net8.0 版)とdotnet test -p:CoreTargetFramework=netstandard2.0。TargetFrameworkTestsが、指定したビルドが実際に使われていることを確認する。 TestData/cases.tsvとv1-*.pngは 1.x(.NET Framework 版)の出力で、シンボル列と画像がこれとピクセル単位で一致することを確認している。1.x がマニュアルと異なっていたケース(補足ルール対象など)は除いてあり、それらはSupplementaryRuleTestsでマニュアルの「バーコード・データ」を期待値にしている。出力が変わる修正をした場合は、マニュアルに照らして意図した変更か確認してから期待値を更新する。cases.tsvはタブ区切り(郵便番号・住所・シンボル列・画像ファイル名)。住所が空の行があるので、シェルで加工するときは連続するタブがまとめられないよう注意する。- System.Drawing のテストは Windows 以外ではスキップされる。
TestData/ken_all_sample.csvは utf_ken_all.csv の形式で手書きしたテスト用データ(実データの抜粋ではない)。実際の郵便番号データ(約12万件)はリポジトリに含めない。TestData/jigyosyo_sample.csvは JIGYOSYO.CSV の形式で手書きしたテスト用データで、実データと同じく Shift_JIS・CRLF。編集するときは UTF-8 で書いてiconv -f UTF-8 -t CP932で変換する(.gitattributesで binary 指定)。- テストプロジェクトの
SkiaSharp.NativeAssets.Linux.NoDependenciesは CI(Linux)用。ライブラリ本体には追加しない。
.github/workflows/build.yml: push・PR で Ubuntu と Windows × コアの両方のビルドをテストし、パッケージを作る。- リリースは
v2.0.0のようなタグを push すると、タグのバージョンで3パッケージを nuget.org に公開する(Trusted Publishing。ワークフローのファイル名build.ymlと Environment 名releaseを nuget.org に登録しているので、どちらも名前を変えない)。nuget.org 側のポリシーは「新しいバージョンの追加のみ」なので、公開済みのバージョンは出し直せない(修正は次のバージョンで出す)。公開後にgithub-releaseジョブがタグの GitHub Release を作る(リリースノートはマージした PR から自動生成、-を含むタグはプレリリース)。公開ジョブはactions/attestでパッケージの出所を証明し、github-releaseはそのパッケージを Release に添付する(nuget.org は公開時にリポジトリ署名を付けてファイルが変わるため、gh attestation verifyで確認できるのは Release に添付したもの)。 - 公開ジョブは GitHub の
releaseEnvironment で動く(v*タグのみ、cssho の承認後に実行。SecretNUGET_USERもこの Environment にある)。Directory.Build.propsのVersionPrefixはローカルと CI のプレリリース版(2.0.0-ci.N)用で、公開時はタグのバージョンが優先される。VersionPrefixはPackageValidationBaselineVersion以上にしておく(低いとアセンブリのバージョンが基準より低くなり CP0003 エラー)。 - ワークフローのアクションは
.github/workflows/actions.lock(gh actions-lock)でコミットに固定している。uses:を追加・変更したらgh actions-lockでロックし直し、gh actions-lock --verifyで確認してから、ロックファイルとワークフローを一緒にコミットする(ワークフローを編集すると、フックが--verify-localで漏れを知らせる)。JSON 出力は--json=valid,findingsのように=でつなぐ(空白区切りだとパスとして解釈される)。 .github/workflows/pages.yml: master への push(コア・デモ・ビルド設定の変更時)と手動実行で、デモサイトを GitHub Pages(https://cssho.github.io/ZipConvertCustomerBarCode/)に配置する。リポジトリ名のパスで公開されるため、配置時にindex.htmlの<base href>を書き換え、.nojekyllを置いている。index.htmlの OGP タグとsitemap.xmlは公開 URL を絶対 URL で書いている(robots.txtはドメインの直下にしか置けないため置いていない)。- CI の
verify-lockfile.ymlが PR・push・週1回でロックファイルを検証する。アクションの更新は Dependabot(.github/dependabot.yml、既定の cooldown でリリースから3日待つ)が、ロックファイルの作り直しも含めて PR にする。 - パッケージ作成時の検証(
EnablePackageValidation)で、net8.0 版から netstandard2.0 版の公開 API が欠けているとエラー(CP0002)になる(net8.0 版にだけ API を足すのは検出しない)。 - あわせて、公開済みのバージョン(
Directory.Build.propsのPackageValidationBaselineVersion)と比べて公開 API を削除・変更していないかも確認する。新しいバージョンを公開したら、この基準も公開したバージョンに上げる。破壊的変更をするメジャーバージョンアップでは、この基準を外すか更新する。 - NuGet パッケージの更新も Dependabot が PR にする。
SkiaSharpとテスト用のSkiaSharp.NativeAssets.Linux.NoDependenciesはバージョンを揃える必要があるので、グループにまとめて一緒に更新する。デモのMicrosoft.AspNetCore.Components.WebAssemblyと...DevServerも同様にグループにしている。 build.ymlは、ドキュメントなどビルドに関係しないファイル(*.md・LICENSE・docs/・.claude/・.github/dependabot.yml)だけの変更では test と pack をスキップする(changesジョブで判定)。paths-ignoreを使うと必須チェックが報告されず PR をマージできなくなるので使わない。- master はルールセットで保護している(PR 経由のみ、
build-result(test・format・pack の結果をまとめるジョブ)と verify-lockfile のverifyの成功が必須)。CI のジョブ名を変えるとマージできなくなるので、ルールセットの必須チェックも合わせて変更する。
- 住所の変換(
BarCode.cs)は日本郵便のバーコードマニュアル(https://www.post.japanpost.jp/zipcode/zipmanual/p19.html)に従う。コード中の番号付きコメント(1.〜6.、補足ルール1〜5)はマニュアルの手順番号に対応している。 - マニュアルでは住所を「住所A(町域名まで)」と「住所B(町域名以降)」に分け、住所Bだけから抜き出す。
Create(郵便番号, 住所)は住所全体を住所Bとして扱うため、町域名に特定文字の前の漢数字を含む住所(一番町、八丁堀など)では誤る。これは既知の制限で、Create(郵便番号, 住所A, 住所B)かZipCodeDictionaryを渡すCreateを推奨している。 - バーコードは常に 23 シンボル: スタート + 郵便番号 7 桁 + 住所表示番号 13 枠(不足分は
CC4で埋める)+ チェックデジット + ストップ。 - バーの形は
CustomerBarCode.csのBarPatternDicで定義(1 シンボル = 幅 12px に 3 本、x=0/4/8、幅 2px、上・中・下段 各 4px)。この表は旧バージョンの GIF 画像とピクセル単位で一致することを確認済みなので、変更するときは既存出力と比較する。 - 描画パッケージは
GetBars()の矩形を白地に黒で塗るだけにし、バーコードのロジックはコアに置く。
ZipCodeDictionaryは利用者が渡す utf_ken_all.csv(UTF-8)と JIGYOSYO.CSV(Shift_JIS)を読む。Shift_JIS は .NET Core 以降では利用者がCodePagesEncodingProviderを登録する必要がある(コアに依存を足さないため、ライブラリ側では登録しない)。読み込み時の都道府県名の検証で、文字コードの取り違えを検出している。- 住所照合(
AddressMatcher、ZipCodeDictionaryの検索)は呼び出し回数が多く、LINQ やToUpperInvariantだけで目に見えて遅くなったことがある。変更したら実データで計測する(英字の大文字化は ASCII のみを手で変換している)。 - 事業所名での検索は、名前の完全一致を優先する。部分一致は誤検出が多かったため、番地なども一致する場合だけ採用する。