com.wallstop-studios.dxmessaging 2.0.0-rc27 → 2.0.0-rc27.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.config/dotnet-tools.json +10 -10
- package/.csharpierignore +1 -0
- package/.csharpierrc.json +3 -0
- package/.editorconfig +184 -184
- package/.gitattributes +87 -63
- package/.github/dependabot.yml +32 -10
- package/.github/scripts/check-markdown-links.ps1 +77 -0
- package/.github/scripts/check_markdown_links.py +89 -0
- package/.github/scripts/check_markdown_url_encoding.py +74 -0
- package/.github/scripts/validate_markdown_links.py +194 -0
- package/.github/workflows/csharpier-autofix.yml +152 -0
- package/.github/workflows/format-on-demand.yml +305 -0
- package/.github/workflows/json-format-check.yml +34 -0
- package/.github/workflows/lint-doc-links.yml +30 -0
- package/.github/workflows/markdown-json.yml +45 -0
- package/.github/workflows/markdown-link-text-check.yml +21 -0
- package/.github/workflows/markdown-link-validity.yml +32 -0
- package/.github/workflows/markdownlint.yml +31 -0
- package/.github/workflows/npm-publish.yml +75 -75
- package/.github/workflows/prettier-autofix.yml +195 -0
- package/.github/workflows/update-dotnet-tools.yml +80 -0
- package/.github/workflows/yaml-format-lint.yml +41 -0
- package/.lychee.toml +26 -0
- package/.markdownlint-cli2.jsonc +14 -0
- package/.markdownlint.json +21 -0
- package/.markdownlint.jsonc +21 -0
- package/.markdownlintignore +7 -0
- package/.pre-commit-config.yaml +58 -22
- package/.prettierignore +21 -0
- package/.prettierrc.json +20 -0
- package/.yamllint.yaml +31 -0
- package/AGENTS.md +49 -0
- package/AGENTS.md.meta +7 -0
- package/CHANGELOG.md.meta +7 -7
- package/CONTRIBUTING.md +33 -0
- package/CONTRIBUTING.md.meta +7 -0
- package/Docs/Advanced.md +236 -0
- package/Docs/Advanced.md.meta +7 -0
- package/Docs/Comparisons.md +468 -0
- package/Docs/Comparisons.md.meta +7 -0
- package/Docs/Compatibility.md +17 -0
- package/Docs/Compatibility.md.meta +7 -0
- package/Docs/DesignAndArchitecture.md +140 -0
- package/Docs/DesignAndArchitecture.md.meta +7 -0
- package/Docs/Diagnostics.md +61 -0
- package/Docs/Diagnostics.md.meta +7 -0
- package/Docs/EmitShorthands.md +437 -0
- package/Docs/EmitShorthands.md.meta +8 -0
- package/Docs/EndToEnd.md +139 -0
- package/Docs/EndToEnd.md.meta +7 -0
- package/Docs/EndToEndSceneTransitions.md +130 -0
- package/Docs/EndToEndSceneTransitions.md.meta +7 -0
- package/Docs/FAQ.md +62 -0
- package/Docs/FAQ.md.meta +7 -0
- package/Docs/GettingStarted.md +133 -0
- package/Docs/GettingStarted.md.meta +7 -0
- package/Docs/Glossary.md +262 -0
- package/Docs/Glossary.md.meta +7 -0
- package/Docs/Helpers.md +559 -0
- package/Docs/Helpers.md.meta +7 -0
- package/Docs/Index.md +303 -0
- package/Docs/Index.md.meta +7 -0
- package/Docs/Install.md +36 -0
- package/Docs/Install.md.meta +7 -0
- package/Docs/InterceptorsAndOrdering.md +167 -0
- package/Docs/InterceptorsAndOrdering.md.meta +7 -0
- package/Docs/ListeningPatterns.md +58 -0
- package/Docs/ListeningPatterns.md.meta +7 -0
- package/Docs/MessageTypes.md +141 -0
- package/Docs/MessageTypes.md.meta +7 -0
- package/Docs/MigrationGuide.md +468 -0
- package/Docs/MigrationGuide.md.meta +7 -0
- package/Docs/Overview.md +63 -0
- package/Docs/Overview.md.meta +7 -0
- package/Docs/Patterns.md +755 -0
- package/Docs/Patterns.md.meta +7 -0
- package/Docs/Performance.md +33 -0
- package/Docs/Performance.md.meta +7 -0
- package/Docs/QuickReference.md +164 -0
- package/Docs/QuickReference.md.meta +7 -0
- package/Docs/QuickStart.md +168 -0
- package/Docs/QuickStart.md.meta +7 -0
- package/Docs/Reference.md +88 -0
- package/Docs/Reference.md.meta +7 -0
- package/Docs/StringMessages.md +71 -0
- package/Docs/StringMessages.md.meta +7 -0
- package/Docs/TargetingAndContext.md +451 -0
- package/Docs/TargetingAndContext.md.meta +7 -0
- package/Docs/Troubleshooting.md +68 -0
- package/Docs/Troubleshooting.md.meta +7 -0
- package/Docs/UnityIntegration.md +137 -0
- package/Docs/UnityIntegration.md.meta +7 -0
- package/Docs/VisualGuide.md +488 -0
- package/Docs/VisualGuide.md.meta +7 -0
- package/Docs.meta +8 -0
- package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +33 -33
- package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +33 -33
- package/Editor/Analyzers/System.Collections.Immutable.dll.meta +33 -33
- package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +33 -33
- package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +33 -33
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +71 -71
- package/Editor/Analyzers.meta +8 -8
- package/Editor/CustomEditors/MessagingComponentEditor.cs +530 -530
- package/Editor/CustomEditors/MessagingComponentEditor.cs.meta +2 -2
- package/Editor/CustomEditors.meta +2 -2
- package/Editor/DxMessagingEditorInitializer.cs +22 -19
- package/Editor/DxMessagingEditorInitializer.cs.meta +2 -2
- package/Editor/Settings/DxMessagingSettings.cs +87 -68
- package/Editor/Settings/DxMessagingSettings.cs.meta +2 -2
- package/Editor/Settings/DxMessagingSettingsProvider.cs +61 -55
- package/Editor/Settings/DxMessagingSettingsProvider.cs.meta +2 -2
- package/Editor/Settings.meta +2 -2
- package/Editor/SetupCscRsp.cs +187 -187
- package/Editor/SetupCscRsp.cs.meta +2 -2
- package/Editor/WallstopStudios.DxMessaging.Editor.asmdef +14 -18
- package/Editor/WallstopStudios.DxMessaging.Editor.asmdef.meta +7 -7
- package/Editor.meta +8 -8
- package/LICENSE.md +9 -7
- package/LICENSE.md.meta +7 -7
- package/README.md +447 -396
- package/README.md.meta +7 -7
- package/Runtime/AssemblyInfo.cs +7 -7
- package/Runtime/AssemblyInfo.cs.meta +2 -2
- package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs +32 -14
- package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs.meta +2 -2
- package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs +29 -11
- package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs.meta +2 -2
- package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +24 -10
- package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs.meta +2 -2
- package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs +30 -11
- package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs.meta +2 -2
- package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs +30 -11
- package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs.meta +2 -2
- package/Runtime/Core/Attributes.meta +2 -2
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +318 -263
- package/Runtime/Core/DataStructure/CyclicBuffer.cs.meta +2 -2
- package/Runtime/Core/DataStructure.meta +2 -2
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs +74 -53
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs.meta +2 -2
- package/Runtime/Core/Diagnostics/MessageRegistrationData.cs +46 -25
- package/Runtime/Core/Diagnostics/MessageRegistrationData.cs.meta +2 -2
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs +21 -21
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs.meta +2 -2
- package/Runtime/Core/Diagnostics.meta +2 -2
- package/Runtime/Core/Extensions/EnumExtensions.cs +44 -44
- package/Runtime/Core/Extensions/EnumExtensions.cs.meta +2 -2
- package/Runtime/Core/Extensions/IListExtensions.cs +48 -48
- package/Runtime/Core/Extensions/IListExtensions.cs.meta +2 -2
- package/Runtime/Core/Extensions/MessageExtensions.cs +615 -408
- package/Runtime/Core/Extensions/MessageExtensions.cs.meta +11 -11
- package/Runtime/Core/Extensions.meta +8 -8
- package/Runtime/Core/Helper/MessageCache.cs +192 -150
- package/Runtime/Core/Helper/MessageCache.cs.meta +2 -2
- package/Runtime/Core/Helper/MessageHelperIndexer.cs +14 -14
- package/Runtime/Core/Helper/MessageHelperIndexer.cs.meta +2 -2
- package/Runtime/Core/Helper.meta +2 -2
- package/Runtime/Core/IMessage.cs +39 -12
- package/Runtime/Core/IMessage.cs.meta +11 -11
- package/Runtime/Core/InstanceId.cs +145 -133
- package/Runtime/Core/InstanceId.cs.meta +11 -11
- package/Runtime/Core/MessageBus/IMessageBus.cs +367 -324
- package/Runtime/Core/MessageBus/IMessageBus.cs.meta +11 -11
- package/Runtime/Core/MessageBus/MessageBus.cs +4285 -3538
- package/Runtime/Core/MessageBus/MessageBus.cs.meta +11 -11
- package/Runtime/Core/MessageBus/MessagingRegistration.cs +105 -105
- package/Runtime/Core/MessageBus/MessagingRegistration.cs.meta +11 -11
- package/Runtime/Core/MessageBus/RegistrationLog.cs +117 -111
- package/Runtime/Core/MessageBus/RegistrationLog.cs.meta +11 -11
- package/Runtime/Core/MessageBus.meta +8 -8
- package/Runtime/Core/MessageHandler.cs +3866 -3060
- package/Runtime/Core/MessageHandler.cs.meta +11 -11
- package/Runtime/Core/MessageRegistrationHandle.cs +119 -110
- package/Runtime/Core/MessageRegistrationHandle.cs.meta +11 -11
- package/Runtime/Core/MessageRegistrationToken.cs +2006 -1820
- package/Runtime/Core/MessageRegistrationToken.cs.meta +11 -11
- package/Runtime/Core/Messages/GlobalStringMessage.cs +34 -16
- package/Runtime/Core/Messages/GlobalStringMessage.cs.meta +2 -2
- package/Runtime/Core/Messages/IBroadcastMessage.cs +42 -27
- package/Runtime/Core/Messages/IBroadcastMessage.cs.meta +11 -11
- package/Runtime/Core/Messages/ITargetedMessage.cs +43 -27
- package/Runtime/Core/Messages/ITargetedMessage.cs.meta +11 -11
- package/Runtime/Core/Messages/IUntargetedMessage.cs +43 -27
- package/Runtime/Core/Messages/IUntargetedMessage.cs.meta +11 -11
- package/Runtime/Core/Messages/ReflexiveMessage.cs +201 -152
- package/Runtime/Core/Messages/ReflexiveMessage.cs.meta +2 -2
- package/Runtime/Core/Messages/SourcedStringMessage.cs +34 -0
- package/Runtime/Core/Messages/SourcedStringMessage.cs.meta +11 -0
- package/Runtime/Core/Messages/StringMessage.cs +36 -16
- package/Runtime/Core/Messages/StringMessage.cs.meta +2 -2
- package/Runtime/Core/Messages.meta +8 -8
- package/Runtime/Core/MessagingDebug.cs +82 -77
- package/Runtime/Core/MessagingDebug.cs.meta +11 -11
- package/Runtime/Core.meta +8 -8
- package/Runtime/Unity/MessageAwareComponent.cs +167 -95
- package/Runtime/Unity/MessageAwareComponent.cs.meta +11 -11
- package/Runtime/Unity/MessagingComponent.cs +125 -88
- package/Runtime/Unity/MessagingComponent.cs.meta +11 -11
- package/Runtime/Unity.meta +8 -8
- package/Runtime/WallstopStudios.DxMessaging.asmdef +14 -16
- package/Runtime/WallstopStudios.DxMessaging.asmdef.meta +7 -7
- package/Runtime.meta +8 -8
- package/Samples~/Mini Combat/Boot.cs +19 -0
- package/Samples~/Mini Combat/Boot.cs.meta +11 -0
- package/Samples~/Mini Combat/Enemy.cs +13 -0
- package/Samples~/Mini Combat/Enemy.cs.meta +11 -0
- package/Samples~/Mini Combat/Messages.cs +23 -0
- package/Samples~/Mini Combat/Messages.cs.meta +11 -0
- package/Samples~/Mini Combat/Player.cs +20 -0
- package/Samples~/Mini Combat/Player.cs.meta +11 -0
- package/Samples~/Mini Combat/README.md +265 -0
- package/Samples~/Mini Combat/README.md.meta +7 -0
- package/Samples~/Mini Combat/UIOverlay.cs +20 -0
- package/Samples~/Mini Combat/UIOverlay.cs.meta +11 -0
- package/Samples~/Mini Combat/Walkthrough.md +414 -0
- package/Samples~/Mini Combat/Walkthrough.md.meta +7 -0
- package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef +13 -0
- package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef.meta +7 -0
- package/Samples~/Mini Combat.meta +8 -0
- package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs +17 -0
- package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs.meta +11 -0
- package/Samples~/UI Buttons + Inspector/Messages.cs +8 -0
- package/Samples~/UI Buttons + Inspector/Messages.cs.meta +11 -0
- package/Samples~/UI Buttons + Inspector/MessagingObserver.cs +26 -0
- package/Samples~/UI Buttons + Inspector/MessagingObserver.cs.meta +11 -0
- package/Samples~/UI Buttons + Inspector/README.md +166 -0
- package/Samples~/UI Buttons + Inspector/UIButtonEmitter.cs +20 -0
- package/Samples~/UI Buttons + Inspector/UIButtonEmitter.cs.meta +11 -0
- package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef +13 -0
- package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef.meta +7 -0
- package/Samples~/UI Buttons + Inspector.meta +8 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +273 -273
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs.meta +11 -11
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +308 -308
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs.meta +2 -2
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +18 -18
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj.meta +7 -7
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.meta +8 -8
- package/SourceGenerators.meta +8 -8
- package/Tests/Runtime/Benchmarks/PerformanceTests.cs +838 -742
- package/Tests/Runtime/Benchmarks/PerformanceTests.cs.meta +11 -11
- package/Tests/Runtime/Benchmarks.meta +8 -8
- package/Tests/Runtime/Core/AlternateBusTests.cs +82 -82
- package/Tests/Runtime/Core/AlternateBusTests.cs.meta +11 -11
- package/Tests/Runtime/Core/BroadcastTests.cs +897 -897
- package/Tests/Runtime/Core/BroadcastTests.cs.meta +11 -11
- package/Tests/Runtime/Core/CyclicBufferTests.cs +70 -0
- package/Tests/Runtime/Core/CyclicBufferTests.cs.meta +11 -0
- package/Tests/Runtime/Core/DiagnosticsTests.cs +118 -118
- package/Tests/Runtime/Core/DiagnosticsTests.cs.meta +11 -11
- package/Tests/Runtime/Core/EdgeCaseTests.cs +579 -565
- package/Tests/Runtime/Core/EdgeCaseTests.cs.meta +11 -11
- package/Tests/Runtime/Core/EnablementTests.cs +69 -69
- package/Tests/Runtime/Core/EnablementTests.cs.meta +2 -2
- package/Tests/Runtime/Core/GenericMessageTests.cs +47 -47
- package/Tests/Runtime/Core/GenericMessageTests.cs.meta +2 -2
- package/Tests/Runtime/Core/GlobalAcceptAllTests.cs +190 -190
- package/Tests/Runtime/Core/GlobalAcceptAllTests.cs.meta +11 -11
- package/Tests/Runtime/Core/InterceptorCancellationTests.cs +170 -0
- package/Tests/Runtime/Core/InterceptorCancellationTests.cs.meta +11 -0
- package/Tests/Runtime/Core/LifecycleTests.cs +72 -72
- package/Tests/Runtime/Core/LifecycleTests.cs.meta +11 -11
- package/Tests/Runtime/Core/MessagingTestBase.cs +208 -208
- package/Tests/Runtime/Core/MessagingTestBase.cs.meta +11 -11
- package/Tests/Runtime/Core/MutationDedupeTests.cs +98 -0
- package/Tests/Runtime/Core/MutationDedupeTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MutationDestructionTests.cs +434 -0
- package/Tests/Runtime/Core/MutationDestructionTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MutationDuringEmissionTests.cs +2021 -0
- package/Tests/Runtime/Core/MutationDuringEmissionTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MutationGlobalAddTests.cs +99 -0
- package/Tests/Runtime/Core/MutationGlobalAddTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MutationInterceptorTests.cs +187 -0
- package/Tests/Runtime/Core/MutationInterceptorTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MutationPostProcessorAcrossHandlersTests.cs +112 -0
- package/Tests/Runtime/Core/MutationPostProcessorAcrossHandlersTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MutationPostProcessorMoreTests.cs +114 -0
- package/Tests/Runtime/Core/MutationPostProcessorMoreTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MutationPriorityTests.cs +116 -0
- package/Tests/Runtime/Core/MutationPriorityTests.cs.meta +11 -0
- package/Tests/Runtime/Core/NominalTests.cs +1734 -1734
- package/Tests/Runtime/Core/NominalTests.cs.meta +11 -11
- package/Tests/Runtime/Core/OrderingTests.cs +1929 -0
- package/Tests/Runtime/Core/OrderingTests.cs.meta +11 -0
- package/Tests/Runtime/Core/OverDeregistrationTests.cs +125 -0
- package/Tests/Runtime/Core/OverDeregistrationTests.cs.meta +11 -0
- package/Tests/Runtime/Core/PostProcessorTests.cs +1236 -1236
- package/Tests/Runtime/Core/PostProcessorTests.cs.meta +11 -11
- package/Tests/Runtime/Core/ReflexiveErrorTests.cs +40 -0
- package/Tests/Runtime/Core/ReflexiveErrorTests.cs.meta +11 -0
- package/Tests/Runtime/Core/ReflexiveTests.cs +170 -171
- package/Tests/Runtime/Core/ReflexiveTests.cs.meta +11 -11
- package/Tests/Runtime/Core/RegistrationTests.cs +1266 -1266
- package/Tests/Runtime/Core/RegistrationTests.cs.meta +11 -11
- package/Tests/Runtime/Core/StringShorthandTests.cs +98 -0
- package/Tests/Runtime/Core/StringShorthandTests.cs.meta +12 -0
- package/Tests/Runtime/Core/TargetedTests.cs +888 -888
- package/Tests/Runtime/Core/TargetedTests.cs.meta +11 -11
- package/Tests/Runtime/Core/TypedShorthandTests.cs +230 -0
- package/Tests/Runtime/Core/TypedShorthandTests.cs.meta +12 -0
- package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs +170 -0
- package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs.meta +12 -0
- package/Tests/Runtime/Core/UntargetedTests.cs +272 -272
- package/Tests/Runtime/Core/UntargetedTests.cs.meta +11 -11
- package/Tests/Runtime/Core.meta +8 -8
- package/Tests/Runtime/Scripts/Components/EmptyMessageAwareComponent.cs +9 -9
- package/Tests/Runtime/Scripts/Components/EmptyMessageAwareComponent.cs.meta +11 -11
- package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +18 -19
- package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs.meta +2 -2
- package/Tests/Runtime/Scripts/Components/ManualListenerComponent.cs +22 -22
- package/Tests/Runtime/Scripts/Components/ManualListenerComponent.cs.meta +11 -11
- package/Tests/Runtime/Scripts/Components/ShorthandTargetedBroadcastComponent.cs +46 -0
- package/Tests/Runtime/Scripts/Components/ShorthandTargetedBroadcastComponent.cs.meta +12 -0
- package/Tests/Runtime/Scripts/Components/SimpleMessageAwareComponent.cs +198 -198
- package/Tests/Runtime/Scripts/Components/SimpleMessageAwareComponent.cs.meta +11 -11
- package/Tests/Runtime/Scripts/Components/StringMessageAwareComponent.cs +75 -0
- package/Tests/Runtime/Scripts/Components/StringMessageAwareComponent.cs.meta +12 -0
- package/Tests/Runtime/Scripts/Components/UntargetedClassReceiverComponent.cs +16 -0
- package/Tests/Runtime/Scripts/Components/UntargetedClassReceiverComponent.cs.meta +12 -0
- package/Tests/Runtime/Scripts/Components/UntargetedReceiverComponent.cs +16 -0
- package/Tests/Runtime/Scripts/Components/UntargetedReceiverComponent.cs.meta +12 -0
- package/Tests/Runtime/Scripts/Components.meta +8 -8
- package/Tests/Runtime/Scripts/Messages/ClassUntargetedMessage.cs +17 -0
- package/Tests/Runtime/Scripts/Messages/ClassUntargetedMessage.cs.meta +12 -0
- package/Tests/Runtime/Scripts/Messages/ComplexTargetedMessage.cs +29 -30
- package/Tests/Runtime/Scripts/Messages/ComplexTargetedMessage.cs.meta +11 -11
- package/Tests/Runtime/Scripts/Messages/GenericUntargetedMessage.cs +7 -7
- package/Tests/Runtime/Scripts/Messages/GenericUntargetedMessage.cs.meta +2 -2
- package/Tests/Runtime/Scripts/Messages/SimpleBroadcastMessage.cs +7 -8
- package/Tests/Runtime/Scripts/Messages/SimpleBroadcastMessage.cs.meta +11 -11
- package/Tests/Runtime/Scripts/Messages/SimpleTargetedMessage.cs +7 -8
- package/Tests/Runtime/Scripts/Messages/SimpleTargetedMessage.cs.meta +11 -11
- package/Tests/Runtime/Scripts/Messages/SimpleUntargetedMessage.cs +7 -8
- package/Tests/Runtime/Scripts/Messages/SimpleUntargetedMessage.cs.meta +11 -11
- package/Tests/Runtime/Scripts/Messages.meta +8 -8
- package/Tests/Runtime/Scripts.meta +8 -8
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.asmdef +19 -23
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.asmdef.meta +7 -7
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +7 -7
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj.meta +7 -7
- package/Tests/Runtime.meta +8 -8
- package/Tests.meta +8 -8
- package/Third Party Notices.md +3 -1
- package/Third Party Notices.md.meta +7 -7
- package/package-lock.json.meta +7 -0
- package/package.json +61 -34
- package/package.json.meta +7 -7
- package/scripts/check-eol.js +94 -0
- package/scripts/check-eol.js.meta +7 -0
- package/scripts/check-eol.ps1 +91 -0
- package/scripts/check-eol.ps1.meta +8 -0
- package/scripts/fix-eol.js +97 -0
- package/scripts/fix-eol.js.meta +7 -0
- package/scripts/fix-markdown-file.js +64 -0
- package/scripts/fix-markdown-file.js.meta +7 -0
- package/scripts/lint-doc-links.ps1 +25 -0
- package/scripts/lint-doc-links.ps1.meta +7 -0
- package/scripts.meta +8 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Param(
|
|
2
|
+
[string]$Root = "."
|
|
3
|
+
)
|
|
4
|
+
|
|
5
|
+
$ErrorActionPreference = 'Stop'
|
|
6
|
+
|
|
7
|
+
function Normalize-Name {
|
|
8
|
+
param([string]$s)
|
|
9
|
+
if ([string]::IsNullOrWhiteSpace($s)) { return "" }
|
|
10
|
+
# Remove extension (like .md), collapse non-alphanumerics, lowercase
|
|
11
|
+
$noExt = $s -replace '\.[^\.]+$',''
|
|
12
|
+
$normalized = ($noExt -replace '[^A-Za-z0-9]', '')
|
|
13
|
+
return $normalized.ToLowerInvariant()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
$issueCount = 0
|
|
17
|
+
|
|
18
|
+
# Exclude typical directories that shouldn't be scanned
|
|
19
|
+
$excludeDirs = @('.git', 'node_modules', '.vs')
|
|
20
|
+
|
|
21
|
+
$mdFiles = Get-ChildItem -Path $Root -Recurse -File -Filter *.md |
|
|
22
|
+
Where-Object { $excludeDirs -notcontains $_.Directory.Name }
|
|
23
|
+
|
|
24
|
+
# Regex for inline markdown links (exclude images), capture optional title
|
|
25
|
+
$pattern = '(?<!\!)\[(?<text>[^\]]+)\]\((?<target>[^)\s]+)(?:\s+"[^"]*")?\)'
|
|
26
|
+
|
|
27
|
+
foreach ($file in $mdFiles) {
|
|
28
|
+
$lines = Get-Content -LiteralPath $file.FullName -Encoding UTF8
|
|
29
|
+
for ($i = 0; $i -lt $lines.Count; $i++) {
|
|
30
|
+
$line = $lines[$i]
|
|
31
|
+
$matches = [System.Text.RegularExpressions.Regex]::Matches($line, $pattern)
|
|
32
|
+
foreach ($m in $matches) {
|
|
33
|
+
$text = $m.Groups['text'].Value.Trim()
|
|
34
|
+
$targetRaw = $m.Groups['target'].Value.Trim()
|
|
35
|
+
|
|
36
|
+
# Skip anchors, external links, and mailto
|
|
37
|
+
if ($targetRaw -match '^(#|https?://|mailto:|tel:|data:)') { continue }
|
|
38
|
+
|
|
39
|
+
# Remove query/anchor for file checks
|
|
40
|
+
$targetCore = $targetRaw -replace '[?#].*$',''
|
|
41
|
+
|
|
42
|
+
# Decode URL-encoded chars
|
|
43
|
+
try { $targetCore = [uri]::UnescapeDataString($targetCore) } catch { }
|
|
44
|
+
|
|
45
|
+
# Only care about links to markdown files
|
|
46
|
+
if (-not ($targetCore -match '\.md$')) { continue }
|
|
47
|
+
|
|
48
|
+
$fileName = [System.IO.Path]::GetFileName($targetCore)
|
|
49
|
+
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($targetCore)
|
|
50
|
+
|
|
51
|
+
# Fail when the visible link text is the raw file name
|
|
52
|
+
$isExactFileName = $text.Equals($fileName, [System.StringComparison]::OrdinalIgnoreCase)
|
|
53
|
+
|
|
54
|
+
# Also fail when the visible text looks like a path or ends with .md
|
|
55
|
+
# contains path separators and no whitespace (heuristic for raw paths)
|
|
56
|
+
$looksLikePath = ($text -match '[\\/]' -and -not ($text -match '\\s'))
|
|
57
|
+
$looksLikeMarkdownFileName = $text.Trim().ToLowerInvariant().EndsWith('.md')
|
|
58
|
+
|
|
59
|
+
if ($isExactFileName -or $looksLikePath -or $looksLikeMarkdownFileName) {
|
|
60
|
+
$issueCount++
|
|
61
|
+
$lineNo = $i + 1
|
|
62
|
+
$msg = "Link text '$text' should be human-readable, not a raw file name or path"
|
|
63
|
+
# GitHub Actions annotation
|
|
64
|
+
Write-Output "::error file=$($file.FullName),line=$lineNo::$msg (target: $targetRaw)"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if ($issueCount -gt 0) {
|
|
71
|
+
Write-Host "Found $issueCount documentation link(s) with non-human-readable text." -ForegroundColor Red
|
|
72
|
+
Write-Host "Use a descriptive phrase instead of the raw file name."
|
|
73
|
+
exit 1
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
Write-Host "All markdown links have human-readable text."
|
|
77
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import sys
|
|
5
|
+
import urllib.parse
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
EXCLUDE_DIRS = {".git", "node_modules", ".vs"}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def normalize_name(s: str) -> str:
|
|
12
|
+
if not s:
|
|
13
|
+
return ""
|
|
14
|
+
# remove extension, strip non-alphanumerics, lowercase
|
|
15
|
+
base = re.sub(r"\.[^.]+$", "", s)
|
|
16
|
+
return re.sub(r"[^A-Za-z0-9]", "", base).lower()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
LINK_RE = re.compile(r"(?<!\!)\[(?P<text>[^\]]+)\]\((?P<target>[^)\s]+)(?:\s+\"[^\"]*\")?\)")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def should_check_target(target: str) -> bool:
|
|
23
|
+
if re.match(r"^(#|https?://|mailto:|tel:|data:)", target):
|
|
24
|
+
return False
|
|
25
|
+
# only check links that end in .md (ignoring anchors/query)
|
|
26
|
+
core = re.sub(r"[?#].*$", "", target)
|
|
27
|
+
try:
|
|
28
|
+
core = urllib.parse.unquote(core)
|
|
29
|
+
except Exception:
|
|
30
|
+
pass
|
|
31
|
+
return core.lower().endswith(".md")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def main(root: str) -> int:
|
|
35
|
+
issues = 0
|
|
36
|
+
for dirpath, dirnames, filenames in os.walk(root):
|
|
37
|
+
# prune excluded directories
|
|
38
|
+
dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS]
|
|
39
|
+
for filename in filenames:
|
|
40
|
+
if not filename.lower().endswith(".md"):
|
|
41
|
+
continue
|
|
42
|
+
path = os.path.join(dirpath, filename)
|
|
43
|
+
try:
|
|
44
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
45
|
+
lines = f.readlines()
|
|
46
|
+
except Exception:
|
|
47
|
+
continue
|
|
48
|
+
for idx, line in enumerate(lines, start=1):
|
|
49
|
+
for m in LINK_RE.finditer(line):
|
|
50
|
+
text = m.group("text").strip()
|
|
51
|
+
target_raw = m.group("target").strip()
|
|
52
|
+
if not should_check_target(target_raw):
|
|
53
|
+
continue
|
|
54
|
+
target_core = re.sub(r"[?#].*$", "", target_raw)
|
|
55
|
+
try:
|
|
56
|
+
target_core = urllib.parse.unquote(target_core)
|
|
57
|
+
except Exception:
|
|
58
|
+
pass
|
|
59
|
+
file_name = os.path.basename(target_core)
|
|
60
|
+
base_name, _ = os.path.splitext(file_name)
|
|
61
|
+
|
|
62
|
+
is_exact_file_name = text.lower() == file_name.lower()
|
|
63
|
+
looks_like_path = (("/" in text) or ("\\" in text)) and not re.search(r"\s", text)
|
|
64
|
+
looks_like_markdown = text.strip().lower().endswith(".md")
|
|
65
|
+
|
|
66
|
+
if (
|
|
67
|
+
is_exact_file_name
|
|
68
|
+
or looks_like_path
|
|
69
|
+
or looks_like_markdown
|
|
70
|
+
):
|
|
71
|
+
issues += 1
|
|
72
|
+
msg = f"{path}:{idx}: Link text '{text}' should be human-readable, not a raw file name or path (target: {target_raw})"
|
|
73
|
+
print(msg)
|
|
74
|
+
|
|
75
|
+
if issues:
|
|
76
|
+
print(
|
|
77
|
+
f"Found {issues} documentation link(s) with non-human-readable text.",
|
|
78
|
+
file=sys.stderr,
|
|
79
|
+
)
|
|
80
|
+
print(
|
|
81
|
+
"Use a descriptive phrase instead of the raw file name.", file=sys.stderr
|
|
82
|
+
)
|
|
83
|
+
return 1
|
|
84
|
+
return 0
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
root = sys.argv[1] if len(sys.argv) > 1 else "."
|
|
89
|
+
sys.exit(main(root))
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
EXCLUDE_DIRS = {".git", "node_modules", ".vs", ".vscode", "Library", "Temp"}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Inline markdown link or image:  or [text](target "title")
|
|
11
|
+
INLINE_LINK_RE = re.compile(
|
|
12
|
+
r"!?(?P<all>\[(?P<text>[^\]]+)\]\((?P<target>[^)\s]+)(?:\s+\"[^\"]*\")?\))"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
# Reference-style link definitions: [id]: target "title"
|
|
16
|
+
REF_DEF_RE = re.compile(r"^\s*\[[^\]]+\]:\s*(?P<target>\S+)(?:\s+\"[^\"]*\")?\s*$")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def is_external(target: str) -> bool:
|
|
20
|
+
return target.startswith("http://") or target.startswith("https://") or target.startswith("mailto:") or target.startswith("tel:") or target.startswith("data:")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def has_unencoded_chars(target: str) -> bool:
|
|
24
|
+
# Only flag raw spaces or plus signs in the path/query/fragment
|
|
25
|
+
return (" " in target) or ("+" in target)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def scan_file(path: str) -> int:
|
|
29
|
+
issues = 0
|
|
30
|
+
try:
|
|
31
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
32
|
+
lines = f.readlines()
|
|
33
|
+
except Exception:
|
|
34
|
+
return 0
|
|
35
|
+
|
|
36
|
+
for idx, line in enumerate(lines, start=1):
|
|
37
|
+
# Inline links/images
|
|
38
|
+
for m in INLINE_LINK_RE.finditer(line):
|
|
39
|
+
target = m.group("target").strip()
|
|
40
|
+
if is_external(target):
|
|
41
|
+
continue
|
|
42
|
+
if has_unencoded_chars(target):
|
|
43
|
+
issues += 1
|
|
44
|
+
print(f"{path}:{idx}: Unencoded character(s) in link target: '{target}'. Encode spaces as %20 and '+' as %2B.")
|
|
45
|
+
|
|
46
|
+
# Reference-style link definitions
|
|
47
|
+
m = REF_DEF_RE.match(line)
|
|
48
|
+
if m:
|
|
49
|
+
target = m.group("target").strip()
|
|
50
|
+
if not is_external(target) and has_unencoded_chars(target):
|
|
51
|
+
issues += 1
|
|
52
|
+
print(f"{path}:{idx}: Unencoded character(s) in link definition: '{target}'. Encode spaces as %20 and '+' as %2B.")
|
|
53
|
+
|
|
54
|
+
return issues
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def main(root: str) -> int:
|
|
58
|
+
issues = 0
|
|
59
|
+
for dirpath, dirnames, filenames in os.walk(root):
|
|
60
|
+
dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS]
|
|
61
|
+
for filename in filenames:
|
|
62
|
+
if filename.lower().endswith(".md"):
|
|
63
|
+
issues += scan_file(os.path.join(dirpath, filename))
|
|
64
|
+
if issues:
|
|
65
|
+
print(f"Found {issues} markdown link(s) with unencoded spaces or plus signs.", file=sys.stderr)
|
|
66
|
+
print("Please URL-encode spaces as %20 and '+' as %2B in relative links.", file=sys.stderr)
|
|
67
|
+
return 1
|
|
68
|
+
return 0
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
if __name__ == "__main__":
|
|
72
|
+
root = sys.argv[1] if len(sys.argv) > 1 else "."
|
|
73
|
+
sys.exit(main(root))
|
|
74
|
+
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
import sys
|
|
5
|
+
import urllib.parse
|
|
6
|
+
from typing import Dict, List, Set, Tuple
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
EXCLUDE_DIRS = {".git", "node_modules", ".vs"}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
LINK_RE = re.compile(r"(?<!\!)\[(?P<text>[^\]]+)\]\((?P<target>[^)\s]+)(?:\s+\"[^\"]*\")?\)")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def unescape_uri(s: str) -> str:
|
|
16
|
+
try:
|
|
17
|
+
return urllib.parse.unquote(s)
|
|
18
|
+
except Exception:
|
|
19
|
+
return s
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def normalize_heading_to_id(text: str) -> str:
|
|
23
|
+
"""
|
|
24
|
+
Approximate GitHub-style anchor slug generation (GFM):
|
|
25
|
+
- Lowercase
|
|
26
|
+
- Strip Markdown formatting and code ticks
|
|
27
|
+
- Remove most punctuation
|
|
28
|
+
- Replace whitespace with hyphens
|
|
29
|
+
- Collapse multiple hyphens
|
|
30
|
+
- Trim leading/trailing hyphens
|
|
31
|
+
"""
|
|
32
|
+
if not text:
|
|
33
|
+
return ""
|
|
34
|
+
t = text
|
|
35
|
+
# Remove inline code ticks
|
|
36
|
+
t = t.replace("`", "")
|
|
37
|
+
# Remove Markdown emphasis markers
|
|
38
|
+
t = t.replace("*", "").replace("_", "").replace("~", "")
|
|
39
|
+
# Remove link/image markup inside headings e.g. [text](url)
|
|
40
|
+
t = re.sub(r"!?\[[^\]]*\]\([^)]*\)", "", t)
|
|
41
|
+
# Remove HTML tags
|
|
42
|
+
t = re.sub(r"<[^>]+>", "", t)
|
|
43
|
+
# Lowercase
|
|
44
|
+
t = t.lower()
|
|
45
|
+
# Replace whitespace with hyphens
|
|
46
|
+
t = re.sub(r"\s+", "-", t)
|
|
47
|
+
# Remove punctuation except hyphens and alphanumerics
|
|
48
|
+
t = re.sub(r"[^a-z0-9-]", "", t)
|
|
49
|
+
# Collapse multiple hyphens
|
|
50
|
+
t = re.sub(r"-+", "-", t)
|
|
51
|
+
# Trim hyphens
|
|
52
|
+
t = t.strip("-")
|
|
53
|
+
return t
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def collect_heading_ids(file_path: str) -> Set[str]:
|
|
57
|
+
"""
|
|
58
|
+
Build the set of anchor IDs generated by headings within a markdown file.
|
|
59
|
+
Handles ATX (# ...) and Setext (underlined) headings. Accounts for duplicate
|
|
60
|
+
slugs by adding -1, -2, ... suffixes (GitHub behavior).
|
|
61
|
+
"""
|
|
62
|
+
try:
|
|
63
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
64
|
+
lines = f.readlines()
|
|
65
|
+
except Exception:
|
|
66
|
+
return set()
|
|
67
|
+
|
|
68
|
+
ids: Set[str] = set()
|
|
69
|
+
slug_counts: Dict[str, int] = {}
|
|
70
|
+
|
|
71
|
+
def add_slug_from_text(text: str):
|
|
72
|
+
slug = normalize_heading_to_id(text)
|
|
73
|
+
if slug == "":
|
|
74
|
+
return
|
|
75
|
+
count = slug_counts.get(slug, 0)
|
|
76
|
+
if count == 0:
|
|
77
|
+
final = slug
|
|
78
|
+
else:
|
|
79
|
+
final = f"{slug}-{count}"
|
|
80
|
+
slug_counts[slug] = count + 1
|
|
81
|
+
ids.add(final)
|
|
82
|
+
|
|
83
|
+
# ATX headings
|
|
84
|
+
atx_re = re.compile(r"^\s{0,3}#{1,6}\s+(.*)$")
|
|
85
|
+
|
|
86
|
+
# Walk lines, handle setext headings by looking ahead
|
|
87
|
+
i = 0
|
|
88
|
+
while i < len(lines):
|
|
89
|
+
line = lines[i].rstrip("\n")
|
|
90
|
+
m = atx_re.match(line)
|
|
91
|
+
if m:
|
|
92
|
+
add_slug_from_text(m.group(1).strip())
|
|
93
|
+
i += 1
|
|
94
|
+
continue
|
|
95
|
+
# Setext H1/H2
|
|
96
|
+
if i + 1 < len(lines):
|
|
97
|
+
underline = lines[i + 1].rstrip("\n")
|
|
98
|
+
if re.match(r"^\s{0,3}=+\s*$", underline) or re.match(r"^\s{0,3}-+\s*$", underline):
|
|
99
|
+
add_slug_from_text(line.strip())
|
|
100
|
+
i += 2
|
|
101
|
+
continue
|
|
102
|
+
i += 1
|
|
103
|
+
|
|
104
|
+
return ids
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def is_external(target: str) -> bool:
|
|
108
|
+
return bool(re.match(r"^(https?://|mailto:|tel:|data:)", target))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def resolve_path(base_dir: str, target_path: str) -> str:
|
|
112
|
+
return os.path.normpath(os.path.join(base_dir, target_path))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def check_internal_link(src_file: str, target_raw: str) -> Tuple[bool, str]:
|
|
116
|
+
# Separate fragment
|
|
117
|
+
if target_raw.startswith("#"):
|
|
118
|
+
# Anchor within same file
|
|
119
|
+
frag = target_raw[1:]
|
|
120
|
+
anchor = unescape_uri(frag)
|
|
121
|
+
anchor = anchor.strip()
|
|
122
|
+
anchor = anchor.lower()
|
|
123
|
+
ids = collect_heading_ids(src_file)
|
|
124
|
+
if anchor in ids:
|
|
125
|
+
return True, ""
|
|
126
|
+
return False, f"dangling anchor '#{frag}' (no matching heading)"
|
|
127
|
+
|
|
128
|
+
# Split off query/fragment
|
|
129
|
+
core = re.sub(r"[?#].*$", "", target_raw)
|
|
130
|
+
core = unescape_uri(core)
|
|
131
|
+
base_dir = os.path.dirname(src_file)
|
|
132
|
+
target_fs = resolve_path(base_dir, core)
|
|
133
|
+
if not os.path.exists(target_fs):
|
|
134
|
+
return False, f"target file not found: {core}"
|
|
135
|
+
|
|
136
|
+
# Fragment check if present
|
|
137
|
+
m = re.search(r"#(.+)$", target_raw)
|
|
138
|
+
if m:
|
|
139
|
+
frag = m.group(1)
|
|
140
|
+
anchor = unescape_uri(frag).strip().lower()
|
|
141
|
+
ids = collect_heading_ids(target_fs)
|
|
142
|
+
if anchor not in ids:
|
|
143
|
+
return False, f"dangling anchor '#{frag}' in {core}"
|
|
144
|
+
|
|
145
|
+
return True, ""
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def main(paths: List[str]) -> int:
|
|
149
|
+
issues = 0
|
|
150
|
+
|
|
151
|
+
def iter_markdown_files() -> List[str]:
|
|
152
|
+
files: List[str] = []
|
|
153
|
+
for p in paths:
|
|
154
|
+
if os.path.isdir(p):
|
|
155
|
+
for dirpath, dirnames, filenames in os.walk(p):
|
|
156
|
+
dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS]
|
|
157
|
+
for filename in filenames:
|
|
158
|
+
if filename.lower().endswith(".md"):
|
|
159
|
+
files.append(os.path.join(dirpath, filename))
|
|
160
|
+
else:
|
|
161
|
+
if p.lower().endswith(".md") and os.path.exists(p):
|
|
162
|
+
files.append(p)
|
|
163
|
+
return files
|
|
164
|
+
|
|
165
|
+
files = iter_markdown_files()
|
|
166
|
+
for path in files:
|
|
167
|
+
try:
|
|
168
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
169
|
+
lines = f.readlines()
|
|
170
|
+
except Exception:
|
|
171
|
+
continue
|
|
172
|
+
for idx, line in enumerate(lines, start=1):
|
|
173
|
+
for m in LINK_RE.finditer(line):
|
|
174
|
+
target = m.group("target").strip()
|
|
175
|
+
# Skip images, external links, anchors we can't resolve externally here
|
|
176
|
+
if is_external(target):
|
|
177
|
+
continue
|
|
178
|
+
ok, reason = check_internal_link(path, target)
|
|
179
|
+
if not ok:
|
|
180
|
+
issues += 1
|
|
181
|
+
print(f"{path}:{idx}: Broken link '{target}': {reason}")
|
|
182
|
+
|
|
183
|
+
if issues:
|
|
184
|
+
print(f"Found {issues} broken internal markdown link(s).", file=sys.stderr)
|
|
185
|
+
print("Fix the paths or anchors so links resolve.", file=sys.stderr)
|
|
186
|
+
return 1
|
|
187
|
+
return 0
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
if __name__ == "__main__":
|
|
191
|
+
args = sys.argv[1:]
|
|
192
|
+
if not args:
|
|
193
|
+
args = ["."]
|
|
194
|
+
sys.exit(main(args))
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
name: CSharpier Auto Format
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
pull_request_target:
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
format:
|
|
14
|
+
name: Format and propose changes
|
|
15
|
+
if: ${{ github.event_name != 'pull_request_target' }}
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout
|
|
19
|
+
uses: actions/checkout@v5
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
|
|
23
|
+
- name: Setup .NET
|
|
24
|
+
uses: actions/setup-dotnet@v5
|
|
25
|
+
with:
|
|
26
|
+
dotnet-version: "8.0.x"
|
|
27
|
+
|
|
28
|
+
- name: Restore .NET tools
|
|
29
|
+
run: dotnet tool restore
|
|
30
|
+
|
|
31
|
+
- name: Run CSharpier (format repository)
|
|
32
|
+
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.user.login == 'dependabot[bot]' }}
|
|
33
|
+
run: dotnet tool run csharpier format
|
|
34
|
+
|
|
35
|
+
- name: Commit formatting changes to PR branch (Dependabot only)
|
|
36
|
+
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.user.login == 'dependabot[bot]' }}
|
|
37
|
+
uses: stefanzweifel/git-auto-commit-action@v7
|
|
38
|
+
with:
|
|
39
|
+
commit_message: "chore(format): apply CSharpier formatting"
|
|
40
|
+
branch: ${{ github.head_ref }}
|
|
41
|
+
file_pattern: |
|
|
42
|
+
**/*.cs
|
|
43
|
+
|
|
44
|
+
- name: Verify formatting (CI gate)
|
|
45
|
+
run: dotnet tool run csharpier check .
|
|
46
|
+
|
|
47
|
+
format_fork:
|
|
48
|
+
name: Fork PR bot formatting PR (Dependabot only)
|
|
49
|
+
if: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && github.event.pull_request.user.login == 'dependabot[bot]' }}
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- name: Checkout fork PR HEAD
|
|
53
|
+
uses: actions/checkout@v5
|
|
54
|
+
with:
|
|
55
|
+
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
|
56
|
+
ref: ${{ github.event.pull_request.head.ref }}
|
|
57
|
+
persist-credentials: false
|
|
58
|
+
fetch-depth: 0
|
|
59
|
+
|
|
60
|
+
- name: Setup .NET
|
|
61
|
+
uses: actions/setup-dotnet@v5
|
|
62
|
+
with:
|
|
63
|
+
dotnet-version: "8.0.x"
|
|
64
|
+
|
|
65
|
+
- name: Install CSharpier (pinned)
|
|
66
|
+
run: dotnet tool install -g csharpier --version 1.1.2
|
|
67
|
+
|
|
68
|
+
- name: Run CSharpier (format repository)
|
|
69
|
+
run: ~/.dotnet/tools/csharpier .
|
|
70
|
+
|
|
71
|
+
- name: Detect changes
|
|
72
|
+
id: changes
|
|
73
|
+
shell: bash
|
|
74
|
+
run: |
|
|
75
|
+
if git diff --quiet; then
|
|
76
|
+
echo "has_changes=false" >> $GITHUB_OUTPUT
|
|
77
|
+
else
|
|
78
|
+
echo "has_changes=true" >> $GITHUB_OUTPUT
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
- name: Create bot branch and push to base repo
|
|
82
|
+
if: steps.changes.outputs.has_changes == 'true'
|
|
83
|
+
shell: bash
|
|
84
|
+
env:
|
|
85
|
+
GH_REPO: ${{ github.repository }}
|
|
86
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
87
|
+
run: |
|
|
88
|
+
set -euo pipefail
|
|
89
|
+
BRANCH="bot/csharpier/pr-${{ github.event.pull_request.number }}"
|
|
90
|
+
git config user.name "github-actions[bot]"
|
|
91
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
92
|
+
git checkout -B "$BRANCH"
|
|
93
|
+
# Only stage C# files to avoid touching workflow YAML (requires special permissions)
|
|
94
|
+
git add '**/*.cs'
|
|
95
|
+
git commit -m "chore(format): apply CSharpier formatting for PR #${{ github.event.pull_request.number }}"
|
|
96
|
+
git remote add upstream "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
|
|
97
|
+
git fetch upstream
|
|
98
|
+
git push upstream "$BRANCH" --force
|
|
99
|
+
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
|
|
100
|
+
|
|
101
|
+
- name: Open or update formatting PR in base repo
|
|
102
|
+
if: steps.changes.outputs.has_changes == 'true'
|
|
103
|
+
uses: actions/github-script@v7
|
|
104
|
+
with:
|
|
105
|
+
script: |
|
|
106
|
+
const prNumber = context.payload.pull_request.number;
|
|
107
|
+
const baseRef = context.payload.pull_request.base.ref;
|
|
108
|
+
const headBranch = `bot/csharpier/pr-${prNumber}`;
|
|
109
|
+
const {owner, repo} = context.repo;
|
|
110
|
+
const title = `chore(format): Apply CSharpier to PR #${prNumber}`;
|
|
111
|
+
const body = [
|
|
112
|
+
`This automated PR applies CSharpier formatting to the changes from PR #${prNumber}.`,
|
|
113
|
+
'',
|
|
114
|
+
`- Source PR (fork): #${prNumber}`,
|
|
115
|
+
`- Target branch: ${baseRef}`,
|
|
116
|
+
'',
|
|
117
|
+
'If this PR is merged, it will include the contributor\'s changes plus required formatting.',
|
|
118
|
+
'You can then close the original PR or ask the author to rebase.',
|
|
119
|
+
].join('\n');
|
|
120
|
+
|
|
121
|
+
// Check if a PR from this branch already exists
|
|
122
|
+
const existing = await github.rest.pulls.list({ owner, repo, state: 'open', head: `${owner}:${headBranch}` });
|
|
123
|
+
if (existing.data.length === 0) {
|
|
124
|
+
await github.rest.pulls.create({ owner, repo, head: headBranch, base: baseRef, title, body });
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
- name: Comment link on original PR
|
|
128
|
+
if: steps.changes.outputs.has_changes == 'true'
|
|
129
|
+
uses: actions/github-script@v7
|
|
130
|
+
with:
|
|
131
|
+
script: |
|
|
132
|
+
const prNumber = context.payload.pull_request.number;
|
|
133
|
+
const {owner, repo} = context.repo;
|
|
134
|
+
const headBranch = `bot/csharpier/pr-${prNumber}`;
|
|
135
|
+
// Find the formatting PR we just created or updated
|
|
136
|
+
const resp = await github.rest.pulls.list({ owner, repo, state: 'open', head: `${owner}:${headBranch}` });
|
|
137
|
+
if (resp.data.length > 0) {
|
|
138
|
+
const fmtPr = resp.data[0];
|
|
139
|
+
const body = `A formatting PR has been opened: #${fmtPr.number} (applies CSharpier to this PR).`;
|
|
140
|
+
// Avoid duplicate comments by checking recent comments
|
|
141
|
+
const comments = await github.rest.issues.listComments({ owner, repo, issue_number: prNumber, per_page: 50 });
|
|
142
|
+
const already = comments.data.some(
|
|
143
|
+
(c) =>
|
|
144
|
+
c.body &&
|
|
145
|
+
c.body.includes(`#${fmtPr.number}`) &&
|
|
146
|
+
c.user &&
|
|
147
|
+
c.user.login === 'github-actions[bot]'
|
|
148
|
+
);
|
|
149
|
+
if (!already) {
|
|
150
|
+
await github.rest.issues.createComment({ owner, repo, issue_number: prNumber, body });
|
|
151
|
+
}
|
|
152
|
+
}
|