diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..96eea09
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,39 @@
+# エディターの基本設定(Visual Studio・VS Code・Rider など)
+# 改行コードは Git の core.autocrlf に任せるため、end_of_line は指定しない
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+# .cs は UTF-8(BOM 付き)
+[*.cs]
+charset = utf-8-bom
+
+[*.{csproj,props,targets,xml,yml,yaml,json,mjs,js}]
+indent_size = 2
+
+[*.sln]
+indent_style = tab
+
+# Markdown は行末の空白2つが改行の意味になるため、削除しない
+[*.md]
+trim_trailing_whitespace = false
+
+# gh actions-lock が生成するロックファイル(YAML)は、手で整形しない
+[.github/workflows/actions.lock]
+charset = unset
+indent_style = unset
+indent_size = unset
+insert_final_newline = unset
+trim_trailing_whitespace = unset
+
+# テストデータは 1.x の出力や実データの形式に合わせているので、エディターで変更しない
+[**/TestData/**]
+charset = unset
+indent_style = unset
+indent_size = unset
+insert_final_newline = unset
+trim_trailing_whitespace = unset
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0b4b6e0..d35d445 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -136,3 +136,26 @@ jobs:
- name: nuget.org に公開
# .snupkg(シンボルパッケージ)は同じフォルダーにあれば一緒に公開される
run: dotnet nuget push "artifacts/*.nupkg" --api-key ${{ steps.login.outputs.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
+
+ # nuget.org に公開したあと、タグの GitHub Release を作る(リリースノートはマージした PR から自動生成)
+ # 書き込み権限は、Trusted Publishing を扱う publish ジョブとは分けてこのジョブだけに付ける
+ github-release:
+ needs: publish
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: GitHub Release の作成
+ env:
+ GH_TOKEN: ${{ github.token }}
+ shell: bash
+ run: |
+ # v2.1.0-beta.1 のような - を含むタグはプレリリースにする
+ prerelease=()
+ if [[ "$GITHUB_REF_NAME" == *-* ]]; then prerelease=(--prerelease); fi
+ # 手で先に作った場合や、ジョブを再実行した場合は、作成済みの Release をそのまま使う
+ if gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" > /dev/null 2>&1; then
+ echo "Release $GITHUB_REF_NAME は作成済みのため、スキップする"
+ exit 0
+ fi
+ gh release create "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --verify-tag --generate-notes --title "$GITHUB_REF_NAME" "${prerelease[@]}"
diff --git a/.gitignore b/.gitignore
index 57a1574..6aa4433 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,13 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
+##
+## Get latest from `dotnet new gitignore`
+
+# dotenv files
+.env
# User-specific files
+*.rsuser
*.suo
*.user
*.userosscache
@@ -10,6 +16,9 @@
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
+# Mono auto generated files
+mono_crash.*
+
# Build results
[Dd]ebug/
[Dd]ebugPublic/
@@ -17,45 +26,79 @@
[Rr]eleases/
x64/
x86/
-build/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
+[Ll]og/
+[Ll]ogs/
-# Visual Studo 2015 cache/options directory
+# Visual Studio 2015/2017 cache/options directory
.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
-# NUNIT
+# NUnit
*.VisualState.xml
TestResult.xml
+nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
*_i.c
*_p.c
-*_i.h
+*_h.h
*.ilk
*.meta
*.obj
+*.iobj
*.pch
*.pdb
+*.ipdb
*.pgc
*.pgd
*.rsp
+# but not Directory.Build.rsp, as it configures directory-level build defaults
+!Directory.Build.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
+*_wpftmp.csproj
*.log
+*.tlog
*.vspscc
*.vssscc
.builds
@@ -70,14 +113,21 @@ _Chutzpah*
ipch/
*.aps
*.ncb
+*.opendb
*.opensdf
*.sdf
*.cachefile
+*.VC.db
+*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
# TFS 2012 Local Workspace
$tf/
@@ -90,18 +140,29 @@ _ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
-# JustCode is a .NET coding addin-in
-.JustCode
-
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
# NCrunch
_NCrunch_*
.*crunch*.local.xml
+nCrunchTemp_*
# MightyMoose
*.mm.*
@@ -129,39 +190,71 @@ publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
-# TODO: Comment the next line if you want to checkin your web deploy settings
+# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
# NuGet Packages
*.nupkg
+# NuGet Symbol Packages
+*.snupkg
# The packages folder can be ignored because of Package Restore
-**/packages/*
+**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
-!**/packages/build/
+!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
-#!**/packages/repositories.config
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
-# Windows Azure Build Output
+# Microsoft Azure Build Output
csx/
*.build.csdef
-# Windows Store app package directory
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
# Others
-*.[Cc]ache
ClientBin/
-[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
+*.jfm
*.pfx
*.publishsettings
-node_modules/
-bower_components/
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
# RIA/Silverlight projects
Generated_Code/
@@ -173,24 +266,233 @@ _UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
+*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
+node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+.idea/
+
+##
+## Visual studio for Mac
+##
+
+
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# content below from: https://github.com/github/gitignore/blob/main/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/main/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# Vim temporary swap files
+*.swp
+
+## ZipConvertCustomerBarCode
+
+# Claude Code のフック(.claude/hooks/*.mjs)に npm の依存を足した場合
+node_modules/
+
+# Claude Code の個人用設定(共有する設定は .claude/settings.json)
+.claude/settings.local.json
+
+# 実際の郵便番号データ(約12万件)はリポジトリに含めない。テストでは TestData の手書きサンプルを使う
+utf_ken_all.csv
+KEN_ALL.CSV
+JIGYOSYO.CSV
+ken_all.zip
+utf_ken_all.zip
+jigyosyo.zip
diff --git a/CLAUDE.md b/CLAUDE.md
index 9a9a887..ce2e0aa 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -20,9 +20,9 @@
- `ZipConvertCustomerBarCode.Drawing`: System.Drawing.Common による描画(Windows のみ)。
- `ZipConvertCustomerBarCode.SkiaSharp`: SkiaSharp による描画。名前空間は `SkiaSharp` との衝突を避けるため `ZipConvertCustomerBarCode.Skia`。
- `netstandard2.0` の既定 C# は 7.3。`#if NET8_0_OR_GREATER` の外では `record` や null 許容参照型など新しい構文は使わない。
-- バージョン・著作権表示・パッケージ情報は `Directory.Build.props` にまとめている。
-- 公開メンバーには XML ドキュメントコメントを付ける(`GenerateDocumentationFile` 有効のため、ないと警告になる)。
-- `.cs` ファイルは UTF-8(BOM 付き)。新規ファイルにも BOM を付ける(`.claude/settings.json` のフックが Write / Edit 後に自動で補う)。改行は `core.autocrlf=true` に従う(Windows の作業ツリーでは CRLF、リポジトリ内は LF)。
+- バージョン・著作権表示・パッケージ情報は `Directory.Build.props` にまとめている。パッケージアイコン `icon.png`(128×128)は、このライブラリで作ったバーコードの先頭4シンボル(スタート + 郵便番号3桁)を縦に伸ばし、紺地に白で描いたもの。`dotnet run tools/GenerateIcon.cs -- 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 後に自動で補う)。改行は `core.autocrlf=true` に従う(Windows の作業ツリーでは CRLF、リポジトリ内は LF)。
## テスト
@@ -38,7 +38,7 @@
## CI・リリース
- `.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 側のポリシーは「新しいバージョンの追加のみ」なので、公開済みのバージョンは出し直せない(修正は次のバージョンで出す)。
+- リリースは `v2.0.0` のようなタグを push すると、タグのバージョンで3パッケージを nuget.org に公開する(Trusted Publishing。ワークフローのファイル名 `build.yml` と Environment 名 `release` を nuget.org に登録しているので、どちらも名前を変えない)。nuget.org 側のポリシーは「新しいバージョンの追加のみ」なので、公開済みのバージョンは出し直せない(修正は次のバージョンで出す)。公開後に `github-release` ジョブがタグの GitHub Release を作る(リリースノートはマージした PR から自動生成、`-` を含むタグはプレリリース)。
- 公開ジョブは GitHub の `release` Environment で動く(`v*` タグのみ、cssho の承認後に実行。Secret `NUGET_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` のように `=` でつなぐ(空白区切りだとパスとして解釈される)。
- CI の `verify-lockfile.yml` が PR・push・週1回でロックファイルを検証する。アクションの更新は Dependabot(`.github/dependabot.yml`、既定の cooldown でリリースから3日待つ)が、ロックファイルの作り直しも含めて PR にする。
diff --git a/Directory.Build.props b/Directory.Build.props
index 7eaff55..cd8a21a 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -20,6 +20,8 @@
git
customer-barcode;barcode;japan-post;postal-code;zipcode;カスタマバーコード;郵便番号
README.md
+
+ icon.png
true
snupkg
+ true
+ $(WarningsNotAsErrors);NU1900;NU1901;NU1902;NU1903;NU1904
+
diff --git a/icon.png b/icon.png
new file mode 100644
index 0000000..e79e5d4
Binary files /dev/null and b/icon.png differ
diff --git a/tools/GenerateIcon.cs b/tools/GenerateIcon.cs
new file mode 100644
index 0000000..39032e7
--- /dev/null
+++ b/tools/GenerateIcon.cs
@@ -0,0 +1,42 @@
+// パッケージアイコン icon.png(128x128)を生成する。
+// 実行: dotnet run tools/GenerateIcon.cs -- icon.png
+//
+// このライブラリでカスタマバーコードを作り、先頭4シンボル(スタート + 郵便番号3桁)のバー配置(GetBars)を
+// 横2倍・縦7倍に伸ばして、紺の角丸の背景に白で描く(ライブラリの出力は白地に黒だが、アイコンでは色を反転している)。
+// バーのある範囲を上下左右の中央に置く。
+#:project ../ZipConvertCustomerBarCode.SkiaSharp/ZipConvertCustomerBarCode.SkiaSharp.csproj
+using SkiaSharp;
+using ZipConvertCustomerBarCode;
+
+const int Size = 128;
+const int ScaleX = 2;
+const int ScaleY = 7;
+const int Symbols = 4;
+const int CellWidth = 12;
+var background = new SKColor(0x1F, 0x3A, 0x5F);
+
+var code = BarCode.Create("2630023", "千葉市稲毛区緑町3丁目30-8 郵便ビル403号");
+var bars = code.GetBars().Where(b => b.X < Symbols * CellWidth).ToList();
+
+// バーのある範囲(スタート記号の先頭は空き枠なので、シンボルの枠ではなくバーで測る)
+var left = bars.Min(b => b.X) * ScaleX;
+var right = bars.Max(b => b.X + b.Width) * ScaleX;
+var top = bars.Min(b => b.Y) * ScaleY;
+var bottom = bars.Max(b => b.Y + b.Height) * ScaleY;
+var offsetX = (Size - (right - left)) / 2 - left;
+var offsetY = (Size - (bottom - top)) / 2 - top;
+
+using var bitmap = new SKBitmap(Size, Size);
+using var canvas = new SKCanvas(bitmap);
+canvas.Clear(SKColors.Transparent);
+using var backgroundPaint = new SKPaint { Color = background, IsAntialias = true };
+canvas.DrawRoundRect(new SKRect(0, 0, Size, Size), 20, 20, backgroundPaint);
+using var barPaint = new SKPaint { Color = SKColors.White };
+foreach (var bar in bars)
+{
+ canvas.DrawRect(offsetX + bar.X * ScaleX, offsetY + bar.Y * ScaleY, bar.Width * ScaleX, bar.Height * ScaleY, barPaint);
+}
+
+using var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
+File.WriteAllBytes(args.Length > 0 ? args[0] : "icon.png", data.ToArray());
+Console.WriteLine($"バーの範囲: x={offsetX + left}〜{offsetX + right - 1}, y={offsetY + top}〜{offsetY + bottom - 1}");