Skip to content

Commit 7e8f02f

Browse files
committed
Respect tagsSorter for hub primary tag selection
Update signalr-openapi-plugin.js to select the primary tag per hub based on the SwaggerUI tagsSorter config: use alphabetical order when tagsSorter is "alpha", otherwise use document tag order. Move fallback logic for missing tags to apply only in document order mode. Add a test to verify alphabetical sorting logic is present in the plugin JS.
1 parent 5f2d63c commit 7e8f02f

2 files changed

Lines changed: 55 additions & 20 deletions

File tree

src/SignalR.OpenApi.SwaggerUi/Resources/signalr-openapi-plugin.js

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -489,31 +489,47 @@ var SignalROpenApiPlugin = function (system) {
489489
});
490490
}
491491

492-
// Determine the primary tag per hub using the document-level tags
493-
// array, which defines the order SwaggerUI renders tag sections.
494-
// This ensures the connection bar appears above the first visible
495-
// tag section for each hub, not at a path-scan-order position.
492+
// Determine the primary tag per hub the first tag SwaggerUI
493+
// actually renders for each hub. When tagsSorter is "alpha",
494+
// SwaggerUI sorts tags alphabetically, overriding document order.
495+
// Otherwise the document-level tags array defines render order.
496496
var hubPrimaryTag = {};
497-
var docTagsIm = specIm.get("tags");
498-
if (docTagsIm) {
499-
docTagsIm.forEach(function (tagObj) {
500-
var name = tagObj && typeof tagObj.get === "function"
501-
? tagObj.get("name")
502-
: (typeof tagObj === "string" ? tagObj : null);
503-
if (name && tagMap[name] && !hubPrimaryTag[tagMap[name]]) {
504-
hubPrimaryTag[tagMap[name]] = name;
497+
var configs = system.getConfigs ? system.getConfigs() : {};
498+
if (configs.tagsSorter === "alpha") {
499+
// Alphabetical sort: pick the lexicographically first tag per hub
500+
var sortedTags = Object.keys(tagMap).sort(function (a, b) {
501+
return a.localeCompare(b);
502+
});
503+
for (var si = 0; si < sortedTags.length; si++) {
504+
var hp = tagMap[sortedTags[si]];
505+
if (!hubPrimaryTag[hp]) {
506+
hubPrimaryTag[hp] = sortedTags[si];
507+
}
508+
}
509+
} else {
510+
// Document order: iterate the document-level tags array which
511+
// matches the order SwaggerUI renders tag sections by default.
512+
var docTagsIm = specIm.get("tags");
513+
if (docTagsIm) {
514+
docTagsIm.forEach(function (tagObj) {
515+
var name = tagObj && typeof tagObj.get === "function"
516+
? tagObj.get("name")
517+
: (typeof tagObj === "string" ? tagObj : null);
518+
if (name && tagMap[name] && !hubPrimaryTag[tagMap[name]]) {
519+
hubPrimaryTag[tagMap[name]] = name;
520+
}
521+
});
522+
}
523+
524+
// Fallback for tags not listed in the document-level tags array
525+
Object.keys(tagMap).forEach(function (tag) {
526+
var hp = tagMap[tag];
527+
if (!hubPrimaryTag[hp]) {
528+
hubPrimaryTag[hp] = tag;
505529
}
506530
});
507531
}
508532

509-
// Fallback for tags not listed in the document-level tags array
510-
Object.keys(tagMap).forEach(function (tag) {
511-
var hp = tagMap[tag];
512-
if (!hubPrimaryTag[hp]) {
513-
hubPrimaryTag[hp] = tag;
514-
}
515-
});
516-
517533
_cachedTagHubMapVersion = specIm;
518534
_cachedTagHubMap = tagMap;
519535
_cachedHubPrimaryTag = hubPrimaryTag;

test/SignalR.OpenApi.Tests/SwaggerUiIntegrationTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,25 @@ public async Task PluginJs_DeterminesPrimaryTagFromDocumentTagsArray()
585585
Assert.IsTrue(content.Contains("tagObj.get(\"name\")"), "Plugin JS should extract tag names from the document tags array");
586586
}
587587

588+
/// <summary>
589+
/// Verifies that the plugin JS uses alphabetical sorting for the primary
590+
/// tag when tagsSorter is "alpha", so the connection bar renders above
591+
/// the first alphabetically-sorted tag section for each hub.
592+
/// </summary>
593+
/// <returns>A <see cref="Task"/> representing the asynchronous test.</returns>
594+
[TestMethod]
595+
public async Task PluginJs_UsesAlphabeticalPrimaryTagWhenTagsSorterAlpha()
596+
{
597+
using var host = await CreateTestHost();
598+
using var client = host.GetTestClient();
599+
600+
using var response = await client.GetAsync("/signalr-swagger/_resources/signalr-openapi-plugin.js");
601+
var content = await response.Content.ReadAsStringAsync();
602+
603+
Assert.IsTrue(content.Contains("configs.tagsSorter === \"alpha\""), "Plugin JS should check tagsSorter config for alphabetical sorting");
604+
Assert.IsTrue(content.Contains("localeCompare"), "Plugin JS should sort tags alphabetically when tagsSorter is alpha");
605+
}
606+
588607
/// <summary>
589608
/// Verifies that the CSS contains connection bar styles.
590609
/// </summary>

0 commit comments

Comments
 (0)