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}");