From cf2988b389a3d26d863d31fd82c5cab7afee4259 Mon Sep 17 00:00:00 2001 From: nsnail Date: Thu, 14 Dec 2023 15:03:07 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=202.0=20(#3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .commitlintrc.js | 72 ++++++ .editorconfig | 23 -- .github/workflows/ci.yml | 36 +++ .gitignore | 9 +- .template.config/template.json | 30 +++ .tgitconfig | 4 - CHANGELOG.md | 11 + Directory.Build.props | 22 +- LICENSE | 2 +- NSExt.sln | 82 +++++-- NSExt.sln.DotSettings | 60 +++-- logo.png => assets/logo.png | Bin .../README.md => assets/res/Statements.ln | 0 build.cake | 117 --------- .../code.quality.props | 12 +- build/copy.pkg.xml.comment.files.targets | 10 + build/minver.targets | 11 + build/prebuild.targets | 24 ++ .../stylecop.analyzers.ruleset | 0 code.cleanup.full.ps1 | 1 - docs/CONTRIBUTING.md | 182 ++++++++++++++ docs/SEMVER.md | 226 ++++++++++++++++++ dot.clean.cmd | 3 - dotnet-tools.json | 18 +- git.pr.ps1 | 26 -- global.json | 4 +- nuget.config | 4 +- packable.props | 18 -- package.json | 14 ++ publish.ps1 | 6 - scripts/clean.ln.csx | 26 ++ scripts/code.clean.csx | 44 ++++ scripts/code.clean.ps1 | 4 + scripts/gen.cs.tt | 77 ++++++ scripts/gen.ln.cmd | 2 + scripts/gen.resx.tt | 39 +++ scripts/git.pr.ps1 | 11 + git.rc.ps1 => scripts/git.rc.ps1 | 2 +- .../image.optimize.csx | 4 +- scripts/install.as.tpl.ps1 | 2 + scripts/rename.csx | 27 +++ scripts/resharper.full.ps1 | 1 + scripts/switcher.nsext.json | 17 ++ scripts/switcher.ps1 | 27 +++ scripts/sync.sln.files.csx | 63 +++++ src/NSExt.Tests/NSExt.Tests.csproj | 9 - src/NSExt.Tests/TestCase.cs | 36 --- src/NSExt/GlobalUsings.cs | 8 - src/NSExt/NSExt.csproj | 10 - src/backend/GlobalUsings.cs | 6 + src/backend/NSExt.Tests/NSExt.Tests.csproj | 14 ++ .../NSExt/Attributes/LocalizationAttribute.cs | 0 .../ResourceDescriptionAttribute.cs | 0 src/{ => backend}/NSExt/Constant/Regexes.cs | 0 .../NSExt/Extensions/ByteExtensions.cs | 0 .../NSExt/Extensions/CharExtensions.cs | 0 .../NSExt/Extensions/DateTimeExtensions.cs | 0 .../NSExt/Extensions/DbCommandExtensions.cs | 3 + .../NSExt/Extensions/DecimalExtensions.cs | 0 .../NSExt/Extensions/EnumExtensions.cs | 0 .../NSExt/Extensions/EnumerableExtensions.cs | 0 .../NSExt/Extensions/GenericExtensions.cs | 0 .../NSExt/Extensions/IntExtensions.cs | 0 .../NSExt/Extensions/LoggerExtensions.cs | 3 + .../NSExt/Extensions/LongExtensions.cs | 0 .../NSExt/Extensions/ObjectExtensions.cs | 0 .../NSExt/Extensions/StreamExtensions.cs | 0 .../NSExt/Extensions/StringExtensions.cs | 5 +- .../NSExt/Extensions/TypeExtensions.cs | 0 .../NSExt/Extensions/UriExtensions.cs | 0 src/backend/NSExt/NSExt.csproj | 32 +++ stylecop.json | 9 - sync.metafiles.csx | 20 -- 73 files changed, 1157 insertions(+), 371 deletions(-) create mode 100644 .commitlintrc.js create mode 100644 .github/workflows/ci.yml create mode 100644 .template.config/template.json delete mode 100644 .tgitconfig create mode 100644 CHANGELOG.md rename logo.png => assets/logo.png (100%) rename src/NSExt/README.md => assets/res/Statements.ln (100%) delete mode 100644 build.cake rename code.quality.props => build/code.quality.props (84%) create mode 100644 build/copy.pkg.xml.comment.files.targets create mode 100644 build/minver.targets create mode 100644 build/prebuild.targets rename stylecop.analyzers.ruleset => build/stylecop.analyzers.ruleset (100%) delete mode 100644 code.cleanup.full.ps1 create mode 100644 docs/CONTRIBUTING.md create mode 100644 docs/SEMVER.md delete mode 100644 dot.clean.cmd delete mode 100644 git.pr.ps1 delete mode 100644 packable.props create mode 100644 package.json delete mode 100644 publish.ps1 create mode 100644 scripts/clean.ln.csx create mode 100644 scripts/code.clean.csx create mode 100644 scripts/code.clean.ps1 create mode 100644 scripts/gen.cs.tt create mode 100644 scripts/gen.ln.cmd create mode 100644 scripts/gen.resx.tt create mode 100644 scripts/git.pr.ps1 rename git.rc.ps1 => scripts/git.rc.ps1 (68%) rename image.optimize.csx => scripts/image.optimize.csx (97%) create mode 100644 scripts/install.as.tpl.ps1 create mode 100644 scripts/rename.csx create mode 100644 scripts/resharper.full.ps1 create mode 100644 scripts/switcher.nsext.json create mode 100644 scripts/switcher.ps1 create mode 100644 scripts/sync.sln.files.csx delete mode 100644 src/NSExt.Tests/NSExt.Tests.csproj delete mode 100644 src/NSExt.Tests/TestCase.cs delete mode 100644 src/NSExt/GlobalUsings.cs delete mode 100644 src/NSExt/NSExt.csproj create mode 100644 src/backend/GlobalUsings.cs create mode 100644 src/backend/NSExt.Tests/NSExt.Tests.csproj rename src/{ => backend}/NSExt/Attributes/LocalizationAttribute.cs (100%) rename src/{ => backend}/NSExt/Attributes/ResourceDescriptionAttribute.cs (100%) rename src/{ => backend}/NSExt/Constant/Regexes.cs (100%) rename src/{ => backend}/NSExt/Extensions/ByteExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/CharExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/DateTimeExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/DbCommandExtensions.cs (97%) rename src/{ => backend}/NSExt/Extensions/DecimalExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/EnumExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/EnumerableExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/GenericExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/IntExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/LoggerExtensions.cs (98%) rename src/{ => backend}/NSExt/Extensions/LongExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/ObjectExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/StreamExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/StringExtensions.cs (99%) rename src/{ => backend}/NSExt/Extensions/TypeExtensions.cs (100%) rename src/{ => backend}/NSExt/Extensions/UriExtensions.cs (100%) create mode 100644 src/backend/NSExt/NSExt.csproj delete mode 100644 stylecop.json delete mode 100644 sync.metafiles.csx diff --git a/.commitlintrc.js b/.commitlintrc.js new file mode 100644 index 0000000..fb715c8 --- /dev/null +++ b/.commitlintrc.js @@ -0,0 +1,72 @@ +// .commitlintrc.js +/** @type {import('cz-git').UserConfig} */ +module.exports = { + rules: { + // @see: https://commitlint.js.org/#/reference-rules + }, + prompt: { + alias: { fd: 'docs: fix typos' }, + messages: { + type: '选择你要提交的类型 :', + scope: '选择一个提交范围(可选):', + customScope: '请输入自定义的提交范围 :', + subject: '填写简短精炼的变更描述 :\n', + body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n', + breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n', + footerPrefixesSelect: '选择关联issue前缀(可选):', + customFooterPrefix: '输入自定义issue前缀 :', + footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', + confirmCommit: '是否提交或修改commit ?' + }, + types: [ + { value: 'wip', name: 'wip: 开发之中 | In development ', emoji:'🧠' }, + { value: 'feat', name: 'feat: 新增功能 | A new feature', emoji:'✨' }, + { value: 'fix', name: 'fix: 修复缺陷 | A bug fix', emoji:'🐛' }, + { value: 'docs', name: 'docs: 文档更新 | Documentation only changes', emoji:'📝' }, + { value: 'style', name: 'style: 代码格式 | Changes that do not affect the meaning of the code', emoji:'💄' }, + { value: 'refactor', name: 'refactor: 代码重构 | A code change that neither fixes a bug nor adds a feature', emoji:'♻️' }, + { value: 'perf', name: 'perf: 性能提升 | A code change that improves performance', emoji:'⚡' }, + { value: 'test', name: 'test: 测试相关 | Adding missing tests or correcting existing tests', emoji:'✅' }, + { value: 'build', name: 'build: 构建相关 | Changes that affect the build system or external dependencies', emoji:'📦' }, + { value: 'ci', name: 'ci: 持续集成 | Changes to our CI configuration files and scripts', emoji:'🎡' }, + { value: 'revert', name: 'revert: 回退代码 | Revert to a commit', emoji:'⏪' }, + { value: 'chore', name: 'chore: 其他修改 | Other changes that do not modify src or test files', emoji:'🔨' }, + ], + useEmoji: true, + emojiAlign: 'center', + useAI: false, + aiNumber: 1, + themeColorCode: '', + scopes: [], + allowCustomScopes: true, + allowEmptyScopes: true, + customScopesAlign: 'bottom', + customScopesAlias: 'custom', + emptyScopesAlias: 'empty', + upperCaseSubject: false, + markBreakingChangeMode: false, + allowBreakingChanges: ['feat', 'fix'], + breaklineNumber: 100, + breaklineChar: '|', + skipQuestions: [], + issuePrefixes: [ + // 如果使用 gitee 作为开发管理 + { value: 'link', name: 'link: 链接 ISSUES 进行中' }, + { value: 'closed', name: 'closed: 标记 ISSUES 已完成' } + ], + customIssuePrefixAlign: 'top', + emptyIssuePrefixAlias: 'skip', + customIssuePrefixAlias: 'custom', + allowCustomIssuePrefix: true, + allowEmptyIssuePrefix: true, + confirmColorize: true, + maxHeaderLength: Infinity, + maxSubjectLength: Infinity, + minSubjectLength: 0, + scopeOverrides: undefined, + defaultBody: '', + defaultIssues: '', + defaultScope: '', + defaultSubject: '' + } +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig index 8f642da..b432966 100644 --- a/.editorconfig +++ b/.editorconfig @@ -15,28 +15,6 @@ indent_size = 2 [*.cs] dotnet_analyzer_diagnostic.severity = warning -dotnet_diagnostic.CA1200.severity = none -dotnet_diagnostic.CA1707.severity = none -dotnet_diagnostic.CA1716.severity = none -dotnet_diagnostic.IDE0005.severity = none -dotnet_diagnostic.IDE0008.severity = none -dotnet_diagnostic.IDE0010.severity = none -dotnet_diagnostic.IDE0055.severity = none -dotnet_diagnostic.IDE0160.severity = none -dotnet_diagnostic.IDE0270.severity = none -dotnet_diagnostic.RCS1141.severity = none -dotnet_diagnostic.RCS1142.severity = none -dotnet_diagnostic.RCS1181.severity = none -dotnet_diagnostic.RCS1186.severity = none -dotnet_diagnostic.S101.severity = none -dotnet_diagnostic.S1121.severity = none -dotnet_diagnostic.S1199.severity = none -dotnet_diagnostic.S125.severity = none -dotnet_diagnostic.S2094.severity = none -dotnet_diagnostic.S3925.severity = none -dotnet_diagnostic.S4663.severity = none -dotnet_diagnostic.SYSLIB1045.severity = none - # ReSharper properties resharper_align_linq_query = true @@ -73,7 +51,6 @@ resharper_wrap_before_eq = true resharper_wrap_chained_method_calls = chop_if_long resharper_wrap_switch_expression = chop_if_long - # Microsoft .NET properties csharp_indent_braces = false csharp_new_line_before_open_brace = local_functions, methods, types \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b157c3b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,36 @@ +name: CI +on: + push: + tags: + - v* +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + filter: tree:0 + - uses: actions/setup-dotnet@v3 + with: + dotnet-version: 8.0.x + - working-directory: ./src/backend/NSExt + run: dotnet build -c Release -f net6.0 + - working-directory: ./src/backend/NSExt + run: dotnet build -c Release -f net7.0 + - working-directory: ./src/backend/NSExt + run: dotnet build -c Release -f net8.0 + - working-directory: ./src/backend/NSExt + run: dotnet pack -c Release --no-build + - uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: false + prerelease: false + - id: get_version + run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v} + - run: dotnet nuget push ./dist/backend/NSExt/bin/Release/NSExt.${{ steps.get_version.outputs.VERSION }}.nupkg --skip-duplicate --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json + - run: dotnet nuget push ./dist/backend/NSExt/bin/Release/NSExt.${{ steps.get_version.outputs.VERSION }}.snupkg --skip-duplicate --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json \ No newline at end of file diff --git a/.gitignore b/.gitignore index acde096..d756a2e 100644 --- a/.gitignore +++ b/.gitignore @@ -55,7 +55,7 @@ nunit-*.xml dlldata.c # Benchmark Results -BenchmarkDotNet.Artifacts/ +BenchmarkNSExtNet.Artifacts/ # .NET Core project.lock.json @@ -130,12 +130,12 @@ $tf/ # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper -*.DotSettings.user +*.NSExtSettings.user # TeamCity is a build add-in _TeamCity* -# DotCover is a Code Coverage Tool +# NSExtCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool @@ -400,6 +400,7 @@ FodyWeavers.xsd # User Define dist/ -refs/ *.[Dd]esigner.cs *.db +cache +/assets/res/Ln.resx diff --git a/.template.config/template.json b/.template.config/template.json new file mode 100644 index 0000000..f709711 --- /dev/null +++ b/.template.config/template.json @@ -0,0 +1,30 @@ +{ + "author": "nsnail", //必须 + "classifications": [ + "Web/WebAPI" + ], //必须,这个对应模板的Tags + "name": "NSExt", //必须,这个对应模板的Templates + "identity": "NSExt", //可选,模板的唯一名称 + "shortName": "lop", //必须,这个对应模板的Short Name + "tags": { + "language": "C#", + "type": "project" + }, + "sourceName": "NSExt", // 可选,要替换的名字 + "preferNameDirectory": true, // 可选,添加目录 + "sources": [ + { + "modifiers": [ + { + "exclude": [ + "**/.vs/**", + "**/.idea/**", + "**/.git/**", + "**/dist/**", + "**/node_modules/**" + ] + } + ] + } + ], +} \ No newline at end of file diff --git a/.tgitconfig b/.tgitconfig deleted file mode 100644 index cea19aa..0000000 --- a/.tgitconfig +++ /dev/null @@ -1,4 +0,0 @@ -[hook "startcommit"] - cmdline = dot.clean.cmd - wait = true - show = true \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a9413ef --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +## 2.0.0 (2023-12-14) + + +### Features + +* ++ ([e41652d](https://github.com/nsnail/NSExt/commit/e41652d553beda7a2eb1600da4795e07f4260330)) +* 增加一些扩展方法 ([1f26d0f](https://github.com/nsnail/NSExt/commit/1f26d0f28098f7ee98a9a5482096aecd53b85e04)) diff --git a/Directory.Build.props b/Directory.Build.props index 6a86153..593c51c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,26 +1,36 @@ + - $(MSBuildThisFileDirectory) + + + + true nsnail - $(SolutionDir)/dist/$(MSBuildProjectName)/obj - $(SolutionDir)/dist/$(MSBuildProjectName)/bin + $(SolutionDir)/dist/backend/$(MSBuildProjectName)/obj + $(SolutionDir)/dist/backend/$(MSBuildProjectName)/bin © 2006-2023 nsnail - A .NET extension function library + The NSExt is a .NET extension function library false true enable + preview beta + v + CA1707;IDE0005;IDE0008;IDE0010;IDE0028;IDE0055;IDE0160;IDE0300;IDE0305;RCS1141;RCS1142;RCS1181;S101;S1121;S1135;S125;S2094;S3604;S4663;SYSLIB1045;SA1010;RCS1123;SA1407;IDE0048;S1075;S3928 NSExt git https://github.com/nsnail/NSExt.git - net7.0;net8.0 + net6.0;net7.0;net8.0 $(AssemblyName) - + all runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE index 7777560..25c689d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 nsnail +Copyright (c) 2023 nsnail Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/NSExt.sln b/NSExt.sln index 5897daf..171567a 100644 --- a/NSExt.sln +++ b/NSExt.sln @@ -3,38 +3,66 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C84EB5A0-37AD-4B17-A51E-E36888C4441E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "backend", "backend", "{4DAF9366-855F-46BB-AE4C-660C92FA0697}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{5198A03D-0CAC-4828-A807-34A693F73859}" ProjectSection(SolutionItems) = preProject + .commitlintrc.js = .commitlintrc.js .editorconfig = .editorconfig .gitattributes = .gitattributes .gitignore = .gitignore - .tgitconfig = .tgitconfig - build.cake = build.cake - code.cleanup.full.ps1 = code.cleanup.full.ps1 - code.quality.props = code.quality.props Directory.Build.props = Directory.Build.props - dot.clean.cmd = dot.clean.cmd dotnet-tools.json = dotnet-tools.json - git.pr.ps1 = git.pr.ps1 - git.rc.ps1 = git.rc.ps1 global.json = global.json - image.optimize.csx = image.optimize.csx key.snk = key.snk LICENSE = LICENSE - logo.png = logo.png NSExt.sln.DotSettings = NSExt.sln.DotSettings - nuget.config = nuget.config - packable.props = packable.props + NuGet.Config = NuGet.Config + package.json = package.json README.md = README.md README.zh-CN.md = README.zh-CN.md - stylecop.analyzers.ruleset = stylecop.analyzers.ruleset - stylecop.json = stylecop.json - sync.metafiles.csx = sync.metafiles.csx EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt.Tests", "src\NSExt.Tests\NSExt.Tests.csproj", "{557FBEF6-E6D5-4531-86DF-D772A10E2261}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{BB0B25C9-0901-4923-913F-00F9A6B352A5}" + ProjectSection(SolutionItems) = preProject + clean.ln.csx = scripts/clean.ln.csx + code.clean.csx = scripts/code.clean.csx + code.clean.ps1 = scripts/code.clean.ps1 + gen.cs.tt = scripts/gen.cs.tt + gen.ln.cmd = scripts/gen.ln.cmd + gen.resx.tt = scripts/gen.resx.tt + git.pr.ps1 = scripts/git.pr.ps1 + git.rc.ps1 = scripts/git.rc.ps1 + image.optimize.csx = scripts/image.optimize.csx + install.as.tpl.ps1 = scripts/install.as.tpl.ps1 + rename.csx = scripts/rename.csx + resharper.full.ps1 = scripts/resharper.full.ps1 + switcher.nsext.json = scripts/switcher.nsext.json + switcher.ps1 = scripts/switcher.ps1 + sync.sln.files.csx = scripts/sync.sln.files.csx + EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt", "src\NSExt\NSExt.csproj", "{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{1129FE25-466B-4F4F-85FC-3752664245E1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{3C6F049E-3EE8-4D66-9AFF-E8A369032487}" + ProjectSection(SolutionItems) = preProject + ci.yml = .github/workflows/ci.yml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{8E4C93BA-9493-4892-80C4-5E174C504829}" + ProjectSection(SolutionItems) = preProject + code.quality.props = build/code.quality.props + copy.pkg.xml.comment.files.targets = build/copy.pkg.xml.comment.files.targets + minver.targets = build/minver.targets + prebuild.targets = build/prebuild.targets + stylecop.analyzers.ruleset = build/stylecop.analyzers.ruleset + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt", "src\backend\NSExt\NSExt.csproj", "{1E62C322-EE42-4699-A6F1-791C53EFA62D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt.Tests", "src\backend\NSExt.Tests\NSExt.Tests.csproj", "{00604162-C444-478B-B773-3AB23C856CA7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -45,13 +73,19 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {557FBEF6-E6D5-4531-86DF-D772A10E2261}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {557FBEF6-E6D5-4531-86DF-D772A10E2261}.Debug|Any CPU.Build.0 = Debug|Any CPU - {557FBEF6-E6D5-4531-86DF-D772A10E2261}.Release|Any CPU.ActiveCfg = Release|Any CPU - {557FBEF6-E6D5-4531-86DF-D772A10E2261}.Release|Any CPU.Build.0 = Release|Any CPU - {BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Release|Any CPU.Build.0 = Release|Any CPU + {1E62C322-EE42-4699-A6F1-791C53EFA62D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E62C322-EE42-4699-A6F1-791C53EFA62D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E62C322-EE42-4699-A6F1-791C53EFA62D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E62C322-EE42-4699-A6F1-791C53EFA62D}.Release|Any CPU.Build.0 = Release|Any CPU + {00604162-C444-478B-B773-3AB23C856CA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00604162-C444-478B-B773-3AB23C856CA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00604162-C444-478B-B773-3AB23C856CA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00604162-C444-478B-B773-3AB23C856CA7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {4DAF9366-855F-46BB-AE4C-660C92FA0697} = {C84EB5A0-37AD-4B17-A51E-E36888C4441E} + {3C6F049E-3EE8-4D66-9AFF-E8A369032487} = {1129FE25-466B-4F4F-85FC-3752664245E1} + {1E62C322-EE42-4699-A6F1-791C53EFA62D} = {4DAF9366-855F-46BB-AE4C-660C92FA0697} + {00604162-C444-478B-B773-3AB23C856CA7} = {4DAF9366-855F-46BB-AE4C-660C92FA0697} EndGlobalSection EndGlobal \ No newline at end of file diff --git a/NSExt.sln.DotSettings b/NSExt.sln.DotSettings index 30a9cb5..ea9fc25 100644 --- a/NSExt.sln.DotSettings +++ b/NSExt.sln.DotSettings @@ -1,34 +1,57 @@ - + Inherit - True - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - NEVER - NEVER + True + True + DO_NOT_SHOW + HINT + DO_NOT_SHOW + DO_NOT_SHOW + NEVER + NEVER NEVER - NEVER + NEVER ID IOS IP - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /> + UI + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /> - True - True - True - True + True + True + True + True True 1 - 1 + 1 OFF - HINT + HINT Required - Required - Required + Required + Required Required <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> <Policy Inspect="True" Prefix="_" Suffix="" Style="AA_BB" /> - <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <?xml version="1.0" encoding="utf-16"?> <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> @@ -80,7 +103,6 @@ True True True - True True True True diff --git a/logo.png b/assets/logo.png similarity index 100% rename from logo.png rename to assets/logo.png diff --git a/src/NSExt/README.md b/assets/res/Statements.ln similarity index 100% rename from src/NSExt/README.md rename to assets/res/Statements.ln diff --git a/build.cake b/build.cake deleted file mode 100644 index 2fb6a2b..0000000 --- a/build.cake +++ /dev/null @@ -1,117 +0,0 @@ -var target = Argument("target", "Default"); -var configuration = Argument("configuration", "Release"); -var framework = Argument("framework", "net7.0"); - -//////////////////////////////////////////////////////////////// -// Tasks - -Task("Clean") - .Does(context => -{ - context.CleanDirectory("./dist"); -}); - -Task("Build") - .IsDependentOn("Clean") - .Does(context => -{ - DotNetPublish("./src/NSExt/NSExt.csproj", new DotNetPublishSettings { - Configuration = configuration, - Framework = framework, - }); -}); - - -// Task("Test") -// .IsDependentOn("Build") -// .Does(context => -// { -// DotNetTest("./test/Spectre.Console.Tests/Spectre.Console.Tests.csproj", new DotNetTestSettings { -// Configuration = configuration, -// NoRestore = true, -// NoBuild = true, -// }); -// -// DotNetTest("./test/Spectre.Console.Cli.Tests/Spectre.Console.Cli.Tests.csproj", new DotNetTestSettings { -// Configuration = configuration, -// NoRestore = true, -// NoBuild = true, -// }); -// -// DotNetTest("./test/Spectre.Console.Analyzer.Tests/Spectre.Console.Analyzer.Tests.csproj", new DotNetTestSettings { -// Configuration = configuration, -// NoRestore = true, -// NoBuild = true, -// }); -// }); - - -// Task("Publish-GitHub") -// .WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions") -// //.IsDependentOn("Package") -// .Does(context => -// { -// var apiKey = Argument("github-key", null); -// if(string.IsNullOrWhiteSpace(apiKey)) { -// throw new CakeException("No GitHub API key was provided."); -// } -// -// // Publish to GitHub Packages -// var exitCode = 0; -// foreach(var file in context.GetFiles("./.artifacts/*.nupkg")) -// { -// context.Information("Publishing {0}...", file.GetFilename().FullPath); -// exitCode += StartProcess("dotnet", -// new ProcessSettings { -// Arguments = new ProcessArgumentBuilder() -// .Append("gpr") -// .Append("push") -// .AppendQuoted(file.FullPath) -// .AppendSwitchSecret("-k", " ", apiKey) -// } -// ); -// } -// -// if(exitCode != 0) -// { -// throw new CakeException("Could not push GitHub packages."); -// } -// }); - -Task("Publish-NuGet") - //.WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions") - .IsDependentOn("Build") - .Does(context => -{ - var apiKey = Argument("nuget-key", null); - if(string.IsNullOrWhiteSpace(apiKey)) { - throw new CakeException("No NuGet API key was provided."); - } - - // Publish to GitHub Packages - foreach(var file in context.GetFiles("./dist/NSExt/bin/Release/*.*")) - { - context.Information("Publishing {0}...", file.GetFilename().FullPath); - DotNetNuGetPush(file.FullPath, new DotNetNuGetPushSettings - { - Source = "https://api.nuget.org/v3/index.json", - ApiKey = apiKey, - SkipDuplicate = true - }); - } -}); - -//////////////////////////////////////////////////////////////// -// Targets - -Task("Publish") -// .IsDependentOn("Publish-GitHub") - .IsDependentOn("Publish-NuGet"); - -Task("Default") - .IsDependentOn("Build"); - -//////////////////////////////////////////////////////////////// -// Execution - -RunTarget(target) \ No newline at end of file diff --git a/code.quality.props b/build/code.quality.props similarity index 84% rename from code.quality.props rename to build/code.quality.props index 7e4518a..facdab9 100644 --- a/code.quality.props +++ b/build/code.quality.props @@ -1,8 +1,8 @@ - $(SolutionDir)/stylecop.analyzers.ruleset + $(SolutionDir)/build/stylecop.analyzers.ruleset - + true true true @@ -15,11 +15,15 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/build/copy.pkg.xml.comment.files.targets b/build/copy.pkg.xml.comment.files.targets new file mode 100644 index 0000000..93db426 --- /dev/null +++ b/build/copy.pkg.xml.comment.files.targets @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/build/minver.targets b/build/minver.targets new file mode 100644 index 0000000..2a53ff9 --- /dev/null +++ b/build/minver.targets @@ -0,0 +1,11 @@ + + + + $(MinVerMajor).$(MinVerMinor).$(MinVerPatch) + $(MinVerMajor).$(MinVerMinor).$(MinVerPatch) + $(MinVerVersion) + $(MinVerVersion) + $(MinVerVersion) + + + \ No newline at end of file diff --git a/build/prebuild.targets b/build/prebuild.targets new file mode 100644 index 0000000..4270160 --- /dev/null +++ b/build/prebuild.targets @@ -0,0 +1,24 @@ + + + + + + + + + Languages/Statements.ln + + + Languages/Ln.resx + PublicResXFileCodeGenerator + + + Languages/Ln.Designer.cs + + + \ No newline at end of file diff --git a/stylecop.analyzers.ruleset b/build/stylecop.analyzers.ruleset similarity index 100% rename from stylecop.analyzers.ruleset rename to build/stylecop.analyzers.ruleset diff --git a/code.cleanup.full.ps1 b/code.cleanup.full.ps1 deleted file mode 100644 index 5b5c370..0000000 --- a/code.cleanup.full.ps1 +++ /dev/null @@ -1 +0,0 @@ -dotnet jb cleanupcode --no-build ./NSExt.sln \ No newline at end of file diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000..fccf379 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,182 @@ +# 约定式提交 1.0.0 + +## [](#概述)概述 + +约定式提交规范是一种基于提交信息的轻量级约定。 它提供了一组简单规则来创建清晰的提交历史; 这更有利于编写自动化工具。 通过在提交信息中描述功能、修复和破坏性变更, 使这种惯例与 [SemVer](http://semver.org/lang/zh-CN) 相互对应。 + +提交说明的结构如下所示: + +* * * + +原文: + + [optional scope]: + + [optional body] + + [optional footer(s)] + + +译文: + + <类型>[可选 范围]: <描述> + + [可选 正文] + + [可选 脚注] + + +* * * + +提交说明包含了下面的结构化元素,以向类库使用者表明其意图: + +1. **fix:** _类型_ 为 `fix` 的提交表示在代码库中修复了一个 bug(这和语义化版本中的 [`PATCH`](https://semver.org/lang/zh-CN/#%E6%91%98%E8%A6%81) 相对应)。 +2. **feat:** _类型_ 为 `feat` 的提交表示在代码库中新增了一个功能(这和语义化版本中的 [`MINOR`](https://semver.org/lang/zh-CN/#%E6%91%98%E8%A6%81) 相对应)。 +3. **BREAKING CHANGE:** 在脚注中包含 `BREAKING CHANGE:` 或 <类型>(范围) 后面有一个 `!` 的提交,表示引入了破坏性 API 变更(这和语义化版本中的 [`MAJOR`](https://semver.org/lang/zh-CN/#%E6%91%98%E8%A6%81) 相对应)。 破坏性变更可以是任意 _类型_ 提交的一部分。 +4. 除 `fix:` 和 `feat:` 之外,也可以使用其它提交 _类型_ ,例如 [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional)(基于 [Angular 约定](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines))中推荐的 `build:`、`chore:`、 `ci:`、`docs:`、`style:`、`refactor:`、`perf:`、`test:`,等等。 + * build: 用于修改项目构建系统,例如修改依赖库、外部接口或者升级 Node 版本等; + * chore: 用于对非业务性代码进行修改,例如修改构建流程或者工具配置等; + * ci: 用于修改持续集成流程,例如修改 Travis、Jenkins 等工作流配置; + * docs: 用于修改文档,例如修改 README 文件、API 文档等; + * style: 用于修改代码的样式,例如调整缩进、空格、空行等; + * refactor: 用于重构代码,例如修改代码结构、变量名、函数名等但不修改功能逻辑; + * perf: 用于优化性能,例如提升代码的性能、减少内存占用等; + * test: 用于修改测试用例,例如添加、删除、修改代码的测试用例等。 +5. 脚注中除了 `BREAKING CHANGE: ` ,其它条目应该采用类似 [git trailer format](https://git-scm.com/docs/git-interpret-trailers) 这样的惯例。 + +其它提交类型在约定式提交规范中并没有强制限制,并且在语义化版本中没有隐式影响(除非它们包含 BREAKING CHANGE)。 可以为提交类型添加一个围在圆括号内的范围,以为其提供额外的上下文信息。例如 `feat(parser): adds ability to parse arrays.`。 + +## [](#示例)示例 + +### [](#包含了描述并且脚注中有破坏性变更的提交说明)包含了描述并且脚注中有破坏性变更的提交说明 + + feat: allow provided config object to extend other configs + + BREAKING CHANGE: `extends` key in config file is now used for extending other config files + + +### [](#包含了--字符以提醒注意破坏性变更的提交说明)包含了 `!` 字符以提醒注意破坏性变更的提交说明 + + feat!: send an email to the customer when a product is shipped + + +### [](#包含了范围和破坏性变更--的提交說明)包含了范围和破坏性变更 `!` 的提交說明 + + feat(api)!: send an email to the customer when a product is shipped + + +### [](#包含了--和-breaking-change-脚注的提交说明)包含了 `!` 和 BREAKING CHANGE 脚注的提交说明 + + chore!: drop support for Node 6 + + BREAKING CHANGE: use JavaScript features not available in Node 6. + + +### [](#不包含正文的提交说明)不包含正文的提交说明 + + docs: correct spelling of CHANGELOG + + +### [](#包含范围的提交说明)包含范围的提交说明 + + feat(lang): add polish language + + +### [](#包含多行正文和多行脚注的提交说明)包含多行正文和多行脚注的提交说明 + + fix: prevent racing of requests + + Introduce a request id and a reference to latest request. Dismiss + incoming responses other than from latest request. + + Remove timeouts which were used to mitigate the racing issue but are + obsolete now. + + Reviewed-by: Z + Refs: #123 + + +## [](#约定式提交规范)约定式提交规范 + +本文中的关键词 “必须(MUST)”、“禁止(MUST NOT)”、“必要(REQUIRED)”、“应当(SHALL)”、“不应当(SHALL NOT)”、“应该(SHOULD)”、“不应该(SHOULD NOT)”、“推荐(RECOMMENDED)”、“可以(MAY)” 和 “可选(OPTIONAL)” ,其相关解释参考 [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) 。 + +1. 每个提交都**必须**使用类型字段前缀,它由一个名词构成,诸如 `feat` 或 `fix` , 其后接**可选的**范围字段,**可选的** `!`,以及**必要的**冒号(英文半角)和空格。 +2. 当一个提交为应用或类库实现了新功能时,**必须**使用 `feat` 类型。 +3. 当一个提交为应用修复了 bug 时,**必须**使用 `fix` 类型。 +4. 范围字段**可以**跟随在类型字段后面。范围**必须**是一个描述某部分代码的名词,并用圆括号包围,例如: `fix(parser):` +5. 描述字段**必须**直接跟在 <类型>(范围) 前缀的冒号和空格之后。 描述指的是对代码变更的简短总结,例如: _fix: array parsing issue when multiple spaces were contained in string_ 。 +6. 在简短描述之后,**可以**编写较长的提交正文,为代码变更提供额外的上下文信息。正文**必须**起始于描述字段结束的一个空行后。 +7. 提交的正文内容自由编写,并**可以**使用空行分隔不同段落。 +8. 在正文结束的一个空行之后,**可以**编写一行或多行脚注。每行脚注都**必须**包含 一个令牌(token),后面紧跟 `:` 或 `#` 作为分隔符,后面再紧跟令牌的值(受 [git trailer convention](https://git-scm.com/docs/git-interpret-trailers) 启发)。 +9. 脚注的令牌**必须**使用 `-` 作为连字符,比如 `Acked-by` (这样有助于 区分脚注和多行正文)。有一种例外情况就是 `BREAKING CHANGE`,它**可以**被认为是一个令牌。 +10. 脚注的值**可以**包含空格和换行,值的解析过程**必须**直到下一个脚注的令牌/分隔符出现为止。 +11. 破坏性变更**必须**在提交信息中标记出来,要么在 <类型>(范围) 前缀中标记,要么作为脚注的一项。 +12. 包含在脚注中时,破坏性变更**必须**包含大写的文本 `BREAKING CHANGE`,后面紧跟着冒号、空格,然后是描述,例如: _BREAKING CHANGE: environment variables now take precedence over config files_ 。 +13. 包含在 <类型>(范围) 前缀时,破坏性变更**必须**通过把 `!` 直接放在 `:` 前面标记出来。 如果使用了 `!`,那么脚注中**可以**不写 `BREAKING CHANGE:`, 同时提交信息的描述中**应该**用来描述破坏性变更。 +14. 在提交说明中,**可以**使用 `feat` 和 `fix` 之外的类型,比如:_docs: updated ref docs._ 。 +15. 工具的实现必须**不区分**大小写地解析构成约定式提交的信息单元,只有 `BREAKING CHANGE` **必须**是大写的。 +16. BREAKING-CHANGE 作为脚注的令牌时**必须**是 BREAKING CHANGE 的同义词。 + +## [](#为什么使用约定式提交)为什么使用约定式提交 + +* 自动化生成 CHANGELOG。 +* 基于提交的类型,自动决定语义化的版本变更。 +* 向同事、公众与其他利益关系者传达变化的性质。 +* 触发构建和部署流程。 +* 让人们探索一个更加结构化的提交历史,以便降低对你的项目做出贡献的难度。 + +## [](#faq)FAQ + +### [](#在初始开发阶段我该如何处理提交说明)在初始开发阶段我该如何处理提交说明? + +我们建议你按照假设你已发布了产品那样来处理。因为通常总 _有人_ 使用你的软件,即便那是你软件开发的同事们。他们会希望知道诸如修复了什么、哪里不兼容等信息。 + +### [](#提交标题中的类型是大写还是小写)提交标题中的类型是大写还是小写? + +大小写都可以,但最好是一致的。 + +### [](#如果提交符合多种类型我该如何操作)如果提交符合多种类型我该如何操作? + +回退并尽可能创建多次提交。约定式提交的好处之一是能够促使我们做出更有组织的提交和 PR。 + +### [](#这不会阻碍快速开发和迭代吗)这不会阻碍快速开发和迭代吗? + +它阻碍的是以杂乱无章的方式快速前进。它助你能在横跨多个项目以及和多个贡献者协作时长期地快速演进。 + +### [](#约定式提交会让开发者受限于提交的类型吗因为他们会想着已提供的类型)约定式提交会让开发者受限于提交的类型吗(因为他们会想着已提供的类型)? + +约定式提交鼓励我们更多地使用某些类型的提交,比如 `fixes`。除此之外,约定式提交的灵活性也允许你的团队使用自己的类型,并随着时间的推移更改这些类型。 + +### [](#这和-semver-有什么关联呢)这和 SemVer 有什么关联呢? + +`fix` 类型提交应当对应到 `PATCH` 版本。`feat` 类型提交应该对应到 `MINOR` 版本。带有 `BREAKING CHANGE` 的提交不管类型如何,都应该对应到 `MAJOR` 版本。 + +### [](#我对约定式提交做了形如-jameswomackconventional-commit-spec-的扩展该如何版本化管理这些扩展呢)我对约定式提交做了形如 `@jameswomack/conventional-commit-spec` 的扩展,该如何版本化管理这些扩展呢? + +我们推荐使用 SemVer 来发布你对于这个规范的扩展(并鼓励你创建这些扩展!) + +### [](#如果我不小心使用了错误的提交类型该怎么办呢)如果我不小心使用了错误的提交类型,该怎么办呢? + +#### [](#当你使用了在规范中但错误的类型时例如将-feat-写成了-fix)当你使用了在规范中但错误的类型时,例如将 `feat` 写成了 `fix` + +在合并或发布这个错误之前,我们建议使用 `git rebase -i` 来编辑提交历史。而在发布之后,根据你使用的工具和流程不同,会有不同的清理方案。 + +#### [](#当使用了-不在-规范中的类型时例如将-feat-写成了-feet)当使用了 _不在_ 规范中的类型时,例如将 `feat` 写成了 `feet` + +在最坏的场景下,即便提交没有满足约定式提交的规范,也不会是世界末日。这只意味着这个提交会被基于规范的工具错过而已。 + +### [](#所有的贡献者都需要使用约定式提交规范吗)所有的贡献者都需要使用约定式提交规范吗? + +并不!如果你使用基于 squash 的 Git 工作流,主管维护者可以在合并时清理提交信息——这不会对普通提交者产生额外的负担。 有种常见的工作流是让 git 系统自动从 pull request 中 squash 出提交,并向主管维护者提供一份表单,用以在合并时输入合适的 git 提交信息。 + +### [](#约定式提交规范中如何处理还原revert提交)约定式提交规范中如何处理还原(revert)提交? + +还原提交(Reverting)会比较复杂:你还原的是多个提交吗?如果你还原了一个功能模块,下次发布的应该是补丁吗? + +约定式提交不能明确的定义还原行为。所以我们把这个问题留给工具开发者, 基于 _类型_ 和 _脚注_ 的灵活性来开发他们自己的还原处理逻辑。 + +一种建议是使用 `revert` 类型,和一个指向被还原提交摘要的脚注: + + revert: let us never again speak of the noodle incident + + Refs: 676104e, a215868 \ No newline at end of file diff --git a/docs/SEMVER.md b/docs/SEMVER.md new file mode 100644 index 0000000..53b6009 --- /dev/null +++ b/docs/SEMVER.md @@ -0,0 +1,226 @@ +语义化版本 2.0.0 +=== + +摘要 +--- + +版本格式:主版本号.次版本号.修订号,版本号递增规则如下: + +1. 主版本号:当你做了不兼容的 API 修改, +2. 次版本号:当你做了向下兼容的功能性新增, +3. 修订号:当你做了向下兼容的问题修正。 + +先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。 + +简介 +--- + +在软件管理的领域里存在着被称作“依赖地狱”的死亡之谷,系统规模越大,加入的包越多,你就越有可能在未来的某一天发现自己已深陷绝望之中。 + +在依赖高的系统中发布新版本包可能很快会成为噩梦。如果依赖关系过高,可能面临版本控制被锁死的风险(必须对每一个依赖包改版才能完成某次升级)。而如果依赖关系过于松散,又将无法避免版本的混乱(假设兼容于未来的多个版本已超出了合理数量)。当你项目的进展因为版本依赖被锁死或版本混乱变得不够简便和可靠,就意味着你正处于依赖地狱之中。 + +作为这个问题的解决方案之一,我提议用一组简单的规则及条件来约束版本号的配置和增长。这些规则是根据(但不局限于)已经被各种封闭、开放源码软件所广泛使用的惯例所设计。为了让这套理论运作,你必须先有定义好的公共 API。这可能包括文档或代码的强制要求。无论如何,这套 API 的清楚明了是十分重要的。一旦你定义了公共 API,你就可以透过修改相应的版本号来向大家说明你的修改。考虑使用这样的版本号格式:X.Y.Z(主版本号.次版本号.修订号)修复问题但不影响 API 时,递增修订号;API 保持向下兼容的新增及修改时,递增次版本号;进行不向下兼容的修改时,递增主版本号。 + +我称这套系统为“语义化的版本控制”,在这套约定下,版本号及其更新方式包含了相邻版本间的底层代码和修改内容的信息。 + +语义化版本控制规范(SemVer) +--- + +以下关键词 MUST、MUST NOT、REQUIRED、SHALL、SHALL NOT、SHOULD、SHOULD NOT、 RECOMMENDED、MAY、OPTIONAL 依照 RFC 2119 的叙述解读。 + +1. 使用语义化版本控制的软件必须(MUST)定义公共 API。该 API 可以在代码中被定义或出现于严谨的文档内。无论何种形式都应该力求精确且完整。 + +2. 标准的版本号必须(MUST)采用 X.Y.Z 的格式,其中 X、Y 和 Z 为非负的整数,且禁止(MUST NOT)在数字前方补零。X 是主版本号、Y 是次版本号、而 Z 为修订号。每个元素必须(MUST)以数值来递增。例如:1.9.1 -> 1.10.0 -> 1.11.0。 + +3. 标记版本号的软件发行后,禁止(MUST NOT)改变该版本软件的内容。任何修改都必须(MUST)以新版本发行。 + +4. 主版本号为零(0.y.z)的软件处于开发初始阶段,一切都可能随时被改变。这样的公共 API 不应该被视为稳定版。 + +5. 1.0.0 的版本号用于界定公共 API 的形成。这一版本之后所有的版本号更新都基于公共 API 及其修改内容。 + +6. 修订号 Z(x.y.Z `|` x > 0)必须(MUST)在只做了向下兼容的修正时才递增。这里的修正指的是针对不正确结果而进行的内部修改。 + +7. 次版本号 Y(x.Y.z `|` x > 0)必须(MUST)在有向下兼容的新功能出现时递增。在任何公共 API 的功能被标记为弃用时也必须(MUST)递增。也可以(MAY)在内部程序有大量新功能或改进被加入时递增,其中可以(MAY)包括修订级别的改变。每当次版本号递增时,修订号必须(MUST)归零。 + +8. 主版本号 X(X.y.z `|` X > 0)必须(MUST)在有任何不兼容的修改被加入公共 API 时递增。其中可以(MAY)包括次版本号及修订级别的改变。每当主版本号递增时,次版本号和修订号必须(MUST)归零。 + +9. 先行版本号可以(MAY)被标注在修订版之后,先加上一个连接号再加上一连串以句点分隔的标识符来修饰。标识符必须(MUST)由 ASCII 字母数字和连接号 [0-9A-Za-z-] 组成,且禁止(MUST NOT)留白。数字型的标识符禁止(MUST NOT)在前方补零。先行版的优先级低于相关联的标准版本。被标上先行版本号则表示这个版本并非稳定而且可能无法满足预期的兼容性需求。范例:1.0.0-alpha、1.0.0-alpha.1、1.0.0-0.3.7、1.0.0-x.7.z.92。 + +10. 版本编译信息可以(MAY)被标注在修订版或先行版本号之后,先加上一个加号再加上一连串以句点分隔的标识符来修饰。标识符必须(MUST)由 ASCII 字母数字和连接号 [0-9A-Za-z-] 组成,且禁止(MUST NOT)留白。当判断版本的优先层级时,版本编译信息可(SHOULD)被忽略。因此当两个版本只有在版本编译信息有差别时,属于相同的优先层级。范例:1.0.0-alpha+001、1.0.0+20130313144700、1.0.0-beta+exp.sha.5114f85。 + +11. 版本的优先层级指的是不同版本在排序时如何比较。 + + 1. 判断优先层级时,必须(MUST)把版本依序拆分为主版本号、次版本号、修订号及先行版本号后进行比较(版本编译信息不在这份比较的列表中)。 + + 2. 由左到右依序比较每个标识符,第一个差异值用来决定优先层级:主版本号、次版本号及修订号以数值比较。 + + 例如:1.0.0 < 2.0.0 < 2.1.0 < 2.1.1。 + + 3. 当主版本号、次版本号及修订号都相同时,改以优先层级比较低的先行版本号决定。 + + 例如:1.0.0-alpha < 1.0.0。 + + 4. 有相同主版本号、次版本号及修订号的两个先行版本号,其优先层级必须(MUST)透过由左到右的每个被句点分隔的标识符来比较,直到找到一个差异值后决定: + + 1. 只有数字的标识符以数值高低比较。 + + 2. 有字母或连接号时则逐字以 ASCII 的排序来比较。 + + 3. 数字的标识符比非数字的标识符优先层级低。 + + 4. 若开头的标识符都相同时,栏位比较多的先行版本号优先层级比较高。 + + 例如:1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0。 + +合法语义化版本的巴科斯范式语法 +-------------------------------------------------- +``` + ::= + | "-" + | "+" + | "-" "+" + + ::= "." "." + + ::= + + ::= + + ::= + + ::= + + ::= + | "." + + ::= + + ::= + | "." + + ::= + | + + ::= + | + + ::= + | + | + | + + ::= "0" + | + | + + ::= + | + + ::= + | + + ::= + | "-" + + ::= + | + + ::= "0" + | + + ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + + ::= "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" + | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" + | "U" | "V" | "W" | "X" | "Y" | "Z" | "a" | "b" | "c" | "d" + | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" + | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" + | "y" | "z" +``` + +为什么要使用语义化的版本控制? +--- + +这并不是一个新的或者革命性的想法。实际上,你可能已经在做一些近似的事情了。问题在于只是“近似”还不够。如果没有某个正式的规范可循,版本号对于依赖的管理并无实质意义。将上述的想法命名并给予清楚的定义,让你对软件使用者传达意向变得容易。一旦这些意向变得清楚,弹性(但又不会太弹性)的依赖规范就能达成。 + +举个简单的例子就可以展示语义化的版本控制如何让依赖地狱成为过去。假设有个名为“救火车”的函数库,它需要另一个名为“梯子”并已经有使用语义化版本控制的包。当救火车创建时,梯子的版本号为 3.1.0。因为救火车使用了一些版本 3.1.0 所新增的功能,你可以放心地指定依赖于梯子的版本号大于等于 3.1.0 但小于 4.0.0。这样,当梯子版本 3.1.1 和 3.2.0 发布时,你可以将直接它们纳入你的包管理系统,因为它们能与原有依赖的软件兼容。 + +作为一位负责任的开发者,你理当确保每次包升级的运作与版本号的表述一致。现实世界是复杂的,我们除了提高警觉外能做的不多。你所能做的就是让语义化的版本控制为你提供一个健全的方式来发行以及升级包,而无需推出新的依赖包,节省你的时间及烦恼。 + +如果你对此认同,希望立即开始使用语义化版本控制,你只需声明你的函数库正在使用它并遵循这些规则就可以了。请在你的 README 文件中保留此页链接,让别人也知道这些规则并从中受益。 + +FAQ +--- + +### 在 0.y.z 初始开发阶段,我该如何进行版本控制? + +最简单的做法是以 0.1.0 作为你的初始化开发版本,并在后续的每次发行时递增次版本号。 + +### 如何判断发布 1.0.0 版本的时机? + +当你的软件被用于正式环境,它应该已经达到了 1.0.0 版。如果你已经有个稳定的 API 被使用者依赖,也会是 1.0.0 版。如果你很担心向下兼容的问题,也应该算是 1.0.0 版了。 + +### 这不会阻碍快速开发和迭代吗? + +主版本号为零的时候就是为了做快速开发。如果你每天都在改变 API,那么你应该仍在主版本号为零的阶段(0.y.z),或是正在下个主版本的独立开发分支中。 + +### 对于公共 API,若即使是最小但不向下兼容的改变都需要产生新的主版本号,岂不是很快就达到 42.0.0 版? + +这是开发的责任感和前瞻性的问题。不兼容的改变不应该轻易被加入到有许多依赖代码的软件中。升级所付出的代价可能是巨大的。要递增主版本号来发行不兼容的改版,意味着你必须为这些改变所带来的影响深思熟虑,并且评估所涉及的成本及效益比。 + +### 为整个公共 API 写文档太费事了! + +为供他人使用的软件编写适当的文档,是你作为一名专业开发者应尽的职责。保持项目高效的一个非常重要的部分是掌控软件的复杂度,如果没有人知道如何使用你的软件或不知道哪些函数的调用是可靠的,要掌控复杂度会是困难的。长远来看,使用语义化版本控制以及对于公共 API 有良好规范的坚持,可以让每个人及每件事都运行顺畅。 + +### 万一不小心把一个不兼容的改版当成了次版本号发行了该怎么办? + +一旦发现自己破坏了语义化版本控制的规范,就要修正这个问题,并发行一个新的次版本号来更正这个问题并且恢复向下兼容。即使是这种情况,也不能去修改已发行的版本。可以的话,将有问题的版本号记录到文档中,告诉使用者问题所在,让他们能够意识到这是有问题的版本。 + +### 如果我更新了自己的依赖但没有改变公共 API 该怎么办? + +由于没有影响到公共 API,这可以被认定是兼容的。若某个软件和你的包有共同依赖,则它会有自己的依赖规范,作者也会告知可能的冲突。要判断改版是属于修订等级或是次版等级,是依据你更新的依赖关系是为了修复问题或是加入新功能。对于后者,我经常会预期伴随着更多的代码,这显然会是一个次版本号级别的递增。 + +### 如果我变更了公共 API 但无意中未遵循版本号的改动怎么办呢?(意即在修订等级的发布中,误将重大且不兼容的改变加到代码之中) + +自行做最佳的判断。如果你有庞大的使用者群在依照公共 API 的意图而变更行为后会大受影响,那么最好做一次主版本的发布,即使严格来说这个修复仅是修订等级的发布。记住, 语义化的版本控制就是透过版本号的改变来传达意义。若这些改变对你的使用者是重要的,那就透过版本号来向他们说明。 + +### 我该如何处理即将弃用的功能? + +弃用现存的功能是软件开发中的家常便饭,也通常是向前发展所必须的。当你弃用部分公共 API 时,你应该做两件事:(1)更新你的文档让使用者知道这个改变,(2)在适当的时机将弃用的功能透过新的次版本号发布。在新的主版本完全移除弃用功能前,至少要有一个次版本包含这个弃用信息,这样使用者才能平顺地转移到新版 API。 + +### 语义化版本对于版本的字符串长度是否有限制呢? + +没有,请自行做适当的判断。举例来说,长到 255 个字符的版本已过度夸张。再者,特定的系统对于字符串长度可能会有他们自己的限制。 + +### “v1.2.3” 是一个语义化版本号吗? + +“v1.2.3” 并不是一个语义化的版本号。但是,在语义化版本号之前增加前缀 “v” 是用来表示版本号的常用做法。在版本控制系统中,将 “version” 缩写为 “v” 是很常见的。比如:`git tag v1.2.3 -m "Release version 1.2.3"` 中,“v1.2.3” 表示标签名称,而 “1.2.3” 是语义化版本号。 + +### 是否有推荐的正则表达式用以检查语义化版本号的正确性? + +有两个推荐的正则表达式。第一个用于支持按组名称提取的语言(PCRE[Perl 兼容正则表达式,比如 Perl、PHP 和 R]、Python 和 Go)。 + +参见: + +``` +^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ +``` + +第二个用于支持按编号提取的语言(与第一个对应的提取项按顺序分别为:major、minor、patch、prerelease、buildmetadata)。主要包括 ECMA Script(JavaScript)、PCRE(Perl 兼容正则表达式,比如 Perl、PHP 和 R)、Python 和 Go。 +参见: + +``` +^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ +``` + +关于 +--- + +语义化版本控制的规范是由 Gravatars 创办者兼 GitHub 共同创办者 [Tom Preston-Werner](http://tom.preston-werner.com) 所建立。 + +如果您有任何建议,请到 [GitHub 上提出您的问题](https://github.com/semver/semver/issues)。 + +许可证 +--- + +[知识共享 署名 3.0 (CC BY 3.0)](http://creativecommons.org/licenses/by/3.0/) \ No newline at end of file diff --git a/dot.clean.cmd b/dot.clean.cmd deleted file mode 100644 index 3eec6ef..0000000 --- a/dot.clean.cmd +++ /dev/null @@ -1,3 +0,0 @@ -dot rbom -w -e refs -e .git -e node_modules -dot trim -w -e refs -e .git -e node_modules -dot tolf -w -e refs -e .git -e node_modules \ No newline at end of file diff --git a/dotnet-tools.json b/dotnet-tools.json index d2c1b28..64cfe12 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -2,22 +2,10 @@ "version": 1, "isRoot": true, "tools": { - "cake.tool": { - "version": "3.1.0", + "dotnet-t4": { + "version": "2.3.1", "commands": [ - "dotnet-cake" - ] - }, - "dotnet-script": { - "version": "1.4.0", - "commands": [ - "dotnet-script" - ] - }, - "jetbrains.resharper.globaltools": { - "version": "2023.2.0", - "commands": [ - "jb" + "t4" ] } } diff --git a/git.pr.ps1 b/git.pr.ps1 deleted file mode 100644 index 2b68a89..0000000 --- a/git.pr.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -$types = @{ - '1' = @('FEA', '新增特性') - '2' = @('REF', '项目重构') - '3' = @('FIX', '缺陷修复') - '4' = @('PER', '性能优化') - '5' = @('RVT', '还原变更') - '6' = @('FMT', '格式整理') - '7' = @('DOC', '文档变更') - '8' = @('TST', '单元测试') - '9' = @('BLD', '工程构建') -} -git add ./ -$prefix = '' -while ($null -eq $types[$prefix]) -{ - $prefix = Read-Host "请选择提交类型`n" $( & { param($i) $i | ForEach-Object { "$_ : $( $types[$_][0] )($( $types[$_][1] ))`n" } } $types.Keys | Sort-Object ) -} -git commit -m "[$($types[$prefix][0])] $(($(Read-Host '是否跳过自动构建?(Y/n)') -eq 'n') ? '': '[SKIP CI] ')$(Read-Host '请输入提交消息')" -$branch = $(git branch --show-current) -& './dot.clean.cmd' -git add ./ -git commit --amend --no-edit -git pull -git push --set-upstream origin $branch -Start-Process -FilePath "https://github.com/nsnail/NSExt/compare/main...$branch" -Pause \ No newline at end of file diff --git a/global.json b/global.json index 8947643..ad64c8c 100644 --- a/global.json +++ b/global.json @@ -1,10 +1,10 @@ { "sdk": { - "version": "7.0.0", + "version": "8.0.0", "rollForward": "latestMajor", "allowPrerelease": true }, "tools": { - "dotnet": "7.0.0" + "dotnet": "8.0.0" } } \ No newline at end of file diff --git a/nuget.config b/nuget.config index eb8bbca..0066ce1 100644 --- a/nuget.config +++ b/nuget.config @@ -2,7 +2,7 @@ - - + + \ No newline at end of file diff --git a/packable.props b/packable.props deleted file mode 100644 index ef69428..0000000 --- a/packable.props +++ /dev/null @@ -1,18 +0,0 @@ - - - ../../key.snk - false - true - true - true - true - true - logo.png - MIT - https://github.com/nsnail/NSExt.git - extensions - true - true - snupkg - - \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..68ef5ea --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "version": "2.0.0", + "devDependencies": { + "cz-git": "^1.7.1", + "commitizen": "^4.3.0", + "prettier": "^3.1.0", + "standard-version": "^9.5.0" + }, + "config": { + "commitizen": { + "path": "node_modules/cz-git" + } + } +} diff --git a/publish.ps1 b/publish.ps1 deleted file mode 100644 index a890466..0000000 --- a/publish.ps1 +++ /dev/null @@ -1,6 +0,0 @@ -Remove-Item ./dist -Recurse -Force -Confirm:$false -dotnet build -c Release -$apikey = Read-Host -Prompt "nuget apikey" -foreach ($file in Get-ChildItem -Path ./dist/NSExt/bin/Release | Where-Object { $_.Name -match "nupkg" }) { - dotnet nuget push $file --skip-duplicate --api-key $apikey --source https://api.nuget.org/v3/index.json -} \ No newline at end of file diff --git a/scripts/clean.ln.csx b/scripts/clean.ln.csx new file mode 100644 index 0000000..f77913d --- /dev/null +++ b/scripts/clean.ln.csx @@ -0,0 +1,26 @@ +using System.Text.RegularExpressions; + +var csFiles = Directory.EnumerateFiles(@"../src/backend", $"*.cs", new EnumerationOptions { RecurseSubdirectories = true }); +foreach (var lnFile in Directory.EnumerateFiles("../assets/res", "*.ln")) +{ + var newLines = new List(); + foreach (var line in File.ReadAllLines(lnFile)) + { + var found = false; + foreach (var csFile in csFiles) + { + if (File.ReadAllText(csFile).Contains($"Ln.{(Regex.IsMatch(line, @"^\d") ? "_" : "") + line}")) + { + found = true; + newLines.Add(line); + break; + } + } + + if (!found) + { + Console.WriteLine(line); + } + } + File.WriteAllLines(lnFile, newLines); +} \ No newline at end of file diff --git a/scripts/code.clean.csx b/scripts/code.clean.csx new file mode 100644 index 0000000..8cd6214 --- /dev/null +++ b/scripts/code.clean.csx @@ -0,0 +1,44 @@ +using System.Text.RegularExpressions; +using System.Net.Http; +using System.Net.Http.Json; + + +{ + var files = string.Join( + ';', + Args[0] + .Split('\n', StringSplitOptions.RemoveEmptyEntries) + .Select(x => x.Replace('\\', '/').Trim()) + ); + + Console.WriteLine(files); + + using var p = Process.Start( + new ProcessStartInfo + { + CreateNoWindow = true, + FileName = "dotnet", + Arguments = $"jb cleanupcode --include=\"{files}\" --no-build ../NSExt.sln", + UseShellExecute = false, + RedirectStandardOutput = true + } + ); + p.WaitForExit(); + Console.WriteLine(p.StandardOutput.ReadToEnd()); + + using var p2 = Process.Start( + new ProcessStartInfo + { + CreateNoWindow = true, + FileName = "git", + Arguments = $"status", + UseShellExecute = false, + RedirectStandardOutput = true + } + ); + p2.WaitForExit(); + var content = p2.StandardOutput.ReadToEnd(); + Console.WriteLine(content); + + return content.Contains("working tree clean") ? 0 : 1; +} \ No newline at end of file diff --git a/scripts/code.clean.ps1 b/scripts/code.clean.ps1 new file mode 100644 index 0000000..b1fbeab --- /dev/null +++ b/scripts/code.clean.ps1 @@ -0,0 +1,4 @@ +dotnet jb cleanupcode --no-build --include = $( $( git status --porcelain | Where-Object { $_ -match "^\s*[MA]" } | ForEach-Object { $_.TrimStart(" M").TrimStart(" A") } ) -join ";" ) ../NSExt.sln +dot rbom -w -e refs -e .git -e node_modules ../ +dot trim -w -e refs -e .git -e node_modules ../ +dot tolf -w -e refs -e .git -e node_modules ../ \ No newline at end of file diff --git a/scripts/gen.cs.tt b/scripts/gen.cs.tt new file mode 100644 index 0000000..5c029ee --- /dev/null +++ b/scripts/gen.cs.tt @@ -0,0 +1,77 @@ +<#@ template language="C#" #> +<#@ assembly name="System.Xml" #> +<#@ output encoding="utf-8" extension="Designer.cs" #> + +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System.CodeDom.Compiler; +using System.Diagnostics.CodeAnalysis; +using System.Resources; +using System.Runtime.CompilerServices; + +namespace NSExt.Languages; + +/// +/// A strongly-typed resource class, for looking up localized strings, etc. +/// + +// This class was auto-generated by the StronglyTypedResourceBuilder +// class via a tool like ResGen or Visual Studio. +// To add or remove a member, edit your .ResX file then rerun ResGen +// with the /str option, or rebuild your VS project. +[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] +[System.Diagnostics.DebuggerNonUserCode] +[System.Runtime.CompilerServices.CompilerGenerated] +public sealed class Ln +{ + private static ResourceManager _resourceMan; + + /// + /// Initializes a new instance of the class. + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + public Ln() { } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [EditorBrowsable(EditorBrowsableState.Advanced)] + public static ResourceManager ResourceManager { + get { + if (ReferenceEquals(_resourceMan, null)) { + var temp = new ResourceManager("NSExt.Languages.Ln", typeof(Ln).Assembly); + _resourceMan = temp; + } + + return _resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [EditorBrowsable(EditorBrowsableState.Advanced)] + public static CultureInfo Culture { get; set; } +<# + var xml = new System.Xml.XmlDocument(); + xml.Load("../assets/res/Ln.resx"); + foreach (System.Xml.XmlNode data in xml.SelectNodes("//root/data")!) + { +#> + /// + /// <#= data.SelectSingleNode("value")?.InnerText #> + /// + public static string <#= + data.Attributes!["name"].Value.Replace(" ", "_") #> => ResourceManager.GetString("<#= data.Attributes!["name"].Value #>", Culture); +<# + } +#> +} \ No newline at end of file diff --git a/scripts/gen.ln.cmd b/scripts/gen.ln.cmd new file mode 100644 index 0000000..1a86b86 --- /dev/null +++ b/scripts/gen.ln.cmd @@ -0,0 +1,2 @@ +dotnet t4 ./gen.resx.tt -o ../assets/res/Ln.resx +dotnet t4 ./gen.cs.tt -o ../dist/backend/NSExt/Ln.cs \ No newline at end of file diff --git a/scripts/gen.resx.tt b/scripts/gen.resx.tt new file mode 100644 index 0000000..6e0cad2 --- /dev/null +++ b/scripts/gen.resx.tt @@ -0,0 +1,39 @@ +<#@ template language="C#" #> +<#@ output encoding="utf-8" extension="resx" #> + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + <# + var regex = new System.Text.RegularExpressions.Regex(@"^\d", System.Text.RegularExpressions.RegexOptions.Compiled); + foreach (var file in System.IO.Directory.GetFiles("../assets/res/", "*.ln")) + { + foreach (var line in System.IO.File.ReadLines(file)) + { +#> + <#= line #>" xml:space="preserve"><#= line #> +<# + } + } +#> + \ No newline at end of file diff --git a/scripts/git.pr.ps1 b/scripts/git.pr.ps1 new file mode 100644 index 0000000..6105d98 --- /dev/null +++ b/scripts/git.pr.ps1 @@ -0,0 +1,11 @@ +$branch = $( git branch --show-current ) +git add ../ +./code.clean.ps1 +git add ../ +../node_modules/.bin/git-cz.ps1 +git pull +git push --set-upstream origin $branch +Start-Process -FilePath "https://github.com/nsnail/NSExt/compare/main...$branch" +Write-Host "按『Enter』重建分支,『Ctrl+C』退出" +Pause +./git.rc.ps1 \ No newline at end of file diff --git a/git.rc.ps1 b/scripts/git.rc.ps1 similarity index 68% rename from git.rc.ps1 rename to scripts/git.rc.ps1 index b72db93..2a66810 100644 --- a/git.rc.ps1 +++ b/scripts/git.rc.ps1 @@ -1,4 +1,4 @@ -$branch = $(git branch --show-current) +$branch = $( git branch --show-current ) git checkout main git pull git branch -D $branch diff --git a/image.optimize.csx b/scripts/image.optimize.csx similarity index 97% rename from image.optimize.csx rename to scripts/image.optimize.csx index e43a4d4..41f558c 100644 --- a/image.optimize.csx +++ b/scripts/image.optimize.csx @@ -7,7 +7,7 @@ var files = Directory .EnumerateFiles( - "./", + "../", "*.png", new EnumerationOptions { @@ -37,7 +37,7 @@ files = new[] { "*.jpg", "*.jpeg" } .SelectMany( x => Directory.EnumerateFiles( - "./", + "../", x, new EnumerationOptions { diff --git a/scripts/install.as.tpl.ps1 b/scripts/install.as.tpl.ps1 new file mode 100644 index 0000000..ad933dd --- /dev/null +++ b/scripts/install.as.tpl.ps1 @@ -0,0 +1,2 @@ +dotnet new uninstall ../ +dotnet new --install ../ \ No newline at end of file diff --git a/scripts/rename.csx b/scripts/rename.csx new file mode 100644 index 0000000..cb7672a --- /dev/null +++ b/scripts/rename.csx @@ -0,0 +1,27 @@ +#r "nuget: NSExt, 1.1.0" +using NSExt.Extensions; + +Console.WriteLine("请输入原始名称(NSExt):"); +var oldName = Console.ReadLine().NullOrEmpty("NSExt"); +Console.WriteLine("请输入替换名称:"); +var newName = Console.ReadLine(); +foreach (var path in Directory.EnumerateDirectories("../", $"*{oldName}*", + SearchOption.AllDirectories)) +{ + Console.Write($"{path} --> "); + var newPath = path.Replace(oldName, newName); + Directory.Move(path, newPath); + Console.WriteLine(newPath); +} + + +Console.WriteLine(); +foreach (var path in Directory.EnumerateFiles("../", $"*.*", SearchOption.AllDirectories)) +{ + File.WriteAllText(path, File.ReadAllText(path).Replace(oldName, newName)); + var newPath = path.Replace(oldName, newName); + if (newPath == path) continue; + Console.Write($"{path} --> "); + Directory.Move(path, newPath); + Console.WriteLine(newPath); +} \ No newline at end of file diff --git a/scripts/resharper.full.ps1 b/scripts/resharper.full.ps1 new file mode 100644 index 0000000..da69383 --- /dev/null +++ b/scripts/resharper.full.ps1 @@ -0,0 +1 @@ +dotnet jb cleanupcode --no-build ../NSExt.sln \ No newline at end of file diff --git a/scripts/switcher.nsext.json b/scripts/switcher.nsext.json new file mode 100644 index 0000000..118955a --- /dev/null +++ b/scripts/switcher.nsext.json @@ -0,0 +1,17 @@ +{ + "solution": "NSExt.sln", + "mappings": { + "NSExt": "../refs/ns-ext/src/NSExt/NSExt.csproj" + }, + "restore": [ + { + "name": "NSExt", + "packages": [ + { + "packageName": "NSExt", + "version": "1.1.0" + } + ] + } + ] +} \ No newline at end of file diff --git a/scripts/switcher.ps1 b/scripts/switcher.ps1 new file mode 100644 index 0000000..41dafe7 --- /dev/null +++ b/scripts/switcher.ps1 @@ -0,0 +1,27 @@ +# https://github.com/RicoSuter/DNT#switch-to-projects +$targets = @{ + '1' = 'switch-to-projects' + '2' = 'switch-to-packages' +} +$key = '' +while ($null -eq $targets[$key]) +{ + $key = 读取-Host '请选择:1(切换到项目引用) 2(切换到Nuget包引用)' +} +$files = Get-ChildItem Switcher.*.json +$file = 9999 +while ($null -eq $files[[int]$file - 1]) +{ + $i = 0 + Write-Host '请选择要切换的配置文件文件' + foreach ($file in $files) + { + $i++ + Write-Host $i $file.Name + } + $file = 读取-Host +} +$file = [int]$file - 1 +Copy-Item $files[$file] 'switcher.json' -Force +dotnet dnt $targets[$key] ../NSExt.sln +Remove-Item switcher.json \ No newline at end of file diff --git a/scripts/sync.sln.files.csx b/scripts/sync.sln.files.csx new file mode 100644 index 0000000..201e1d6 --- /dev/null +++ b/scripts/sync.sln.files.csx @@ -0,0 +1,63 @@ +using System.Text.RegularExpressions; + +var slnFile = Directory.GetFiles(@"../", "*.sln").First(); +var content = File.ReadAllText(slnFile); + +content = Regex.Replace( + content, + "Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"meta\", \"meta\", \"{5198A03D-0CAC-4828-A807-34A693F73859}\"(?:.|\n)*?EndProject", + $$""" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{5198A03D-0CAC-4828-A807-34A693F73859}" +{{'\t'}}ProjectSection(SolutionItems) = preProject +{{string.Join('\n', + Directory.GetFiles(@"../", "*").Where(x => !x.EndsWith(".sln") && !x.EndsWith(".user")) + .Select(x=>$"\t\t{Path.GetFileName(x)} = {Path.GetFileName(x)}") + )}} +{{'\t'}}EndProject +""" +); + +content = Regex.Replace( + content, + "Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"workflows\", \"workflows\", \"{3C6F049E-3EE8-4D66-9AFF-E8A369032487}\"(?:.|\n)*?EndProject", + $$""" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{3C6F049E-3EE8-4D66-9AFF-E8A369032487}" +{{'\t'}}ProjectSection(SolutionItems) = preProject +{{string.Join('\n', + Directory.GetFiles(@"../.github/workflows", "*") + .Select(x=>$"\t\t{Path.GetFileName(x)} = .github/workflows/{Path.GetFileName(x)}") + )}} +{{'\t'}}EndProject +""" +); + +content = Regex.Replace( + content, + "Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"scripts\", \"scripts\", \"{BB0B25C9-0901-4923-913F-00F9A6B352A5}\"(?:.|\n)*?EndProject", + $$""" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{BB0B25C9-0901-4923-913F-00F9A6B352A5}" +{{'\t'}}ProjectSection(SolutionItems) = preProject +{{string.Join('\n', + Directory.GetFiles(@"../scripts", "*") + .Select(x=>$"\t\t{Path.GetFileName(x)} = scripts/{Path.GetFileName(x)}") + )}} +{{'\t'}}EndProject +""" +); + +content = Regex.Replace( + content, + "Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"build\", \"build\", \"{8E4C93BA-9493-4892-80C4-5E174C504829}\"(?:.|\n)*?EndProject", + $$""" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{8E4C93BA-9493-4892-80C4-5E174C504829}" +{{'\t'}}ProjectSection(SolutionItems) = preProject +{{string.Join('\n', + Directory.GetFiles(@"../build", "*") + .Select(x=>$"\t\t{Path.GetFileName(x)} = build/{Path.GetFileName(x)}") + )}} +{{'\t'}}EndProject +""" +); + +Console.WriteLine(content); +File.WriteAllText(slnFile, content); \ No newline at end of file diff --git a/src/NSExt.Tests/NSExt.Tests.csproj b/src/NSExt.Tests/NSExt.Tests.csproj deleted file mode 100644 index f770abf..0000000 --- a/src/NSExt.Tests/NSExt.Tests.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/NSExt.Tests/TestCase.cs b/src/NSExt.Tests/TestCase.cs deleted file mode 100644 index 3164751..0000000 --- a/src/NSExt.Tests/TestCase.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace NSExt.Tests; - -/// -/// 测试用例 -/// -public class TestCase -{ - // private readonly ITestOutputHelper _testOutputHelper; - // - // public TestCase(ITestOutputHelper testOutputHelper) - // { - // _testOutputHelper = testOutputHelper; - // } - // - // public enum MyEnum1 - // { - // [ResourceDescription(nameof(Description))] - // Online = 1 - // - // , Offline = 2 - // } - // - // public static string Description { get; set; } = "123"; - // - // /// - // /// Case1 - // /// - // [Fact] - // public void Case1() - // { - // var test = MyEnum1.Online.ResDesc(); - // - // _testOutputHelper.WriteLine(test); - // Assert.True(test is not null); - // } -} \ No newline at end of file diff --git a/src/NSExt/GlobalUsings.cs b/src/NSExt/GlobalUsings.cs deleted file mode 100644 index ce9e85d..0000000 --- a/src/NSExt/GlobalUsings.cs +++ /dev/null @@ -1,8 +0,0 @@ -global using System.Data; -global using System.Data.Common; -global using System.Globalization; -global using System.Runtime.CompilerServices; -global using System.Text; -global using System.Text.RegularExpressions; -global using System.Web; -global using Microsoft.Extensions.Logging; \ No newline at end of file diff --git a/src/NSExt/NSExt.csproj b/src/NSExt/NSExt.csproj deleted file mode 100644 index 22c816d..0000000 --- a/src/NSExt/NSExt.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/backend/GlobalUsings.cs b/src/backend/GlobalUsings.cs new file mode 100644 index 0000000..bcf7404 --- /dev/null +++ b/src/backend/GlobalUsings.cs @@ -0,0 +1,6 @@ +global using System; +global using System.ComponentModel; +global using System.Globalization; +global using System.Text; +global using System.Text.RegularExpressions; +global using NSExt.Languages; \ No newline at end of file diff --git a/src/backend/NSExt.Tests/NSExt.Tests.csproj b/src/backend/NSExt.Tests/NSExt.Tests.csproj new file mode 100644 index 0000000..a81c311 --- /dev/null +++ b/src/backend/NSExt.Tests/NSExt.Tests.csproj @@ -0,0 +1,14 @@ + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + \ No newline at end of file diff --git a/src/NSExt/Attributes/LocalizationAttribute.cs b/src/backend/NSExt/Attributes/LocalizationAttribute.cs similarity index 100% rename from src/NSExt/Attributes/LocalizationAttribute.cs rename to src/backend/NSExt/Attributes/LocalizationAttribute.cs diff --git a/src/NSExt/Attributes/ResourceDescriptionAttribute.cs b/src/backend/NSExt/Attributes/ResourceDescriptionAttribute.cs similarity index 100% rename from src/NSExt/Attributes/ResourceDescriptionAttribute.cs rename to src/backend/NSExt/Attributes/ResourceDescriptionAttribute.cs diff --git a/src/NSExt/Constant/Regexes.cs b/src/backend/NSExt/Constant/Regexes.cs similarity index 100% rename from src/NSExt/Constant/Regexes.cs rename to src/backend/NSExt/Constant/Regexes.cs diff --git a/src/NSExt/Extensions/ByteExtensions.cs b/src/backend/NSExt/Extensions/ByteExtensions.cs similarity index 100% rename from src/NSExt/Extensions/ByteExtensions.cs rename to src/backend/NSExt/Extensions/ByteExtensions.cs diff --git a/src/NSExt/Extensions/CharExtensions.cs b/src/backend/NSExt/Extensions/CharExtensions.cs similarity index 100% rename from src/NSExt/Extensions/CharExtensions.cs rename to src/backend/NSExt/Extensions/CharExtensions.cs diff --git a/src/NSExt/Extensions/DateTimeExtensions.cs b/src/backend/NSExt/Extensions/DateTimeExtensions.cs similarity index 100% rename from src/NSExt/Extensions/DateTimeExtensions.cs rename to src/backend/NSExt/Extensions/DateTimeExtensions.cs diff --git a/src/NSExt/Extensions/DbCommandExtensions.cs b/src/backend/NSExt/Extensions/DbCommandExtensions.cs similarity index 97% rename from src/NSExt/Extensions/DbCommandExtensions.cs rename to src/backend/NSExt/Extensions/DbCommandExtensions.cs index 62b4521..e95758d 100644 --- a/src/NSExt/Extensions/DbCommandExtensions.cs +++ b/src/backend/NSExt/Extensions/DbCommandExtensions.cs @@ -1,3 +1,6 @@ +using System.Data; +using System.Data.Common; + namespace NSExt.Extensions; /// diff --git a/src/NSExt/Extensions/DecimalExtensions.cs b/src/backend/NSExt/Extensions/DecimalExtensions.cs similarity index 100% rename from src/NSExt/Extensions/DecimalExtensions.cs rename to src/backend/NSExt/Extensions/DecimalExtensions.cs diff --git a/src/NSExt/Extensions/EnumExtensions.cs b/src/backend/NSExt/Extensions/EnumExtensions.cs similarity index 100% rename from src/NSExt/Extensions/EnumExtensions.cs rename to src/backend/NSExt/Extensions/EnumExtensions.cs diff --git a/src/NSExt/Extensions/EnumerableExtensions.cs b/src/backend/NSExt/Extensions/EnumerableExtensions.cs similarity index 100% rename from src/NSExt/Extensions/EnumerableExtensions.cs rename to src/backend/NSExt/Extensions/EnumerableExtensions.cs diff --git a/src/NSExt/Extensions/GenericExtensions.cs b/src/backend/NSExt/Extensions/GenericExtensions.cs similarity index 100% rename from src/NSExt/Extensions/GenericExtensions.cs rename to src/backend/NSExt/Extensions/GenericExtensions.cs diff --git a/src/NSExt/Extensions/IntExtensions.cs b/src/backend/NSExt/Extensions/IntExtensions.cs similarity index 100% rename from src/NSExt/Extensions/IntExtensions.cs rename to src/backend/NSExt/Extensions/IntExtensions.cs diff --git a/src/NSExt/Extensions/LoggerExtensions.cs b/src/backend/NSExt/Extensions/LoggerExtensions.cs similarity index 98% rename from src/NSExt/Extensions/LoggerExtensions.cs rename to src/backend/NSExt/Extensions/LoggerExtensions.cs index 084710a..ca694c2 100644 --- a/src/NSExt/Extensions/LoggerExtensions.cs +++ b/src/backend/NSExt/Extensions/LoggerExtensions.cs @@ -1,5 +1,8 @@ // ReSharper disable TemplateIsNotCompileTimeConstantProblem +using System.Runtime.CompilerServices; +using Microsoft.Extensions.Logging; + namespace NSExt.Extensions; /// diff --git a/src/NSExt/Extensions/LongExtensions.cs b/src/backend/NSExt/Extensions/LongExtensions.cs similarity index 100% rename from src/NSExt/Extensions/LongExtensions.cs rename to src/backend/NSExt/Extensions/LongExtensions.cs diff --git a/src/NSExt/Extensions/ObjectExtensions.cs b/src/backend/NSExt/Extensions/ObjectExtensions.cs similarity index 100% rename from src/NSExt/Extensions/ObjectExtensions.cs rename to src/backend/NSExt/Extensions/ObjectExtensions.cs diff --git a/src/NSExt/Extensions/StreamExtensions.cs b/src/backend/NSExt/Extensions/StreamExtensions.cs similarity index 100% rename from src/NSExt/Extensions/StreamExtensions.cs rename to src/backend/NSExt/Extensions/StreamExtensions.cs diff --git a/src/NSExt/Extensions/StringExtensions.cs b/src/backend/NSExt/Extensions/StringExtensions.cs similarity index 99% rename from src/NSExt/Extensions/StringExtensions.cs rename to src/backend/NSExt/Extensions/StringExtensions.cs index ceeed7a..80c49fe 100644 --- a/src/NSExt/Extensions/StringExtensions.cs +++ b/src/backend/NSExt/Extensions/StringExtensions.cs @@ -4,6 +4,7 @@ #pragma warning disable CA1720 using System.Security.Cryptography; using System.Text.Json; +using System.Web; using NSExt.Constant; namespace NSExt.Extensions; @@ -141,7 +142,9 @@ public static class StringExtensions /// 转换后的日期对象 public static DateTime DateTimeTry(this string me, DateTime def) { - return !System.DateTime.TryParse(me, CultureInfo.InvariantCulture, out var ret) ? def : ret; + return !System.DateTime.TryParse(me, CultureInfo.InvariantCulture, DateTimeStyles.None, out var ret) + ? def + : ret; } /// diff --git a/src/NSExt/Extensions/TypeExtensions.cs b/src/backend/NSExt/Extensions/TypeExtensions.cs similarity index 100% rename from src/NSExt/Extensions/TypeExtensions.cs rename to src/backend/NSExt/Extensions/TypeExtensions.cs diff --git a/src/NSExt/Extensions/UriExtensions.cs b/src/backend/NSExt/Extensions/UriExtensions.cs similarity index 100% rename from src/NSExt/Extensions/UriExtensions.cs rename to src/backend/NSExt/Extensions/UriExtensions.cs diff --git a/src/backend/NSExt/NSExt.csproj b/src/backend/NSExt/NSExt.csproj new file mode 100644 index 0000000..c83cccc --- /dev/null +++ b/src/backend/NSExt/NSExt.csproj @@ -0,0 +1,32 @@ + + + ../../../key.snk + false + true + true + true + true + logo.png + MIT + https://github.com/nsnail/NSExt.git + README.md + extensions + true + NSExt + true + snupkg + + + + + + + + + + + + PreserveNewest + + + \ No newline at end of file diff --git a/stylecop.json b/stylecop.json deleted file mode 100644 index ae79eec..0000000 --- a/stylecop.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", - "settings": { - "indentation": { - "useTabs": false, - "indentationSize": 4 - } - } -} \ No newline at end of file diff --git a/sync.metafiles.csx b/sync.metafiles.csx deleted file mode 100644 index 312d601..0000000 --- a/sync.metafiles.csx +++ /dev/null @@ -1,20 +0,0 @@ -using System.Text.RegularExpressions; - -var slnFile = Directory.GetFiles(@"./", "*.sln").First(); -var content = File.ReadAllText(slnFile); - -content = Regex.Replace( - content, - "Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"meta\", \"meta\", \"{5198A03D-0CAC-4828-A807-34A693F73859}\"(?:.|\n)*?EndProject", - $$""" -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{5198A03D-0CAC-4828-A807-34A693F73859}" -{{'\t'}}ProjectSection(SolutionItems) = preProject -{{string.Join('\n', - Directory.GetFiles(@"./", "*").Where(x => !x.EndsWith(".sln") && !x.EndsWith(".user")) - .Select(x=>$"\t\t{Path.GetFileName(x)} = {Path.GetFileName(x)}") - )}} -{{'\t'}}EndProject -""" -); -Console.WriteLine(content); -File.WriteAllText(slnFile, content); \ No newline at end of file