Sandcastle (SHFB) component to resolve third-party reference links.
Copy the ResolveThirdPartyReferenceLinks.dll assembly to the %SHFBROOT%\Components folder.
The %SHFBROOT% environment variable is set by the Sandcastle Help File Builder (SHFB) installer and points to the root folder where SHFB is installed. The default location is C:\Program Files (x86)\EWSoftware\Sandcastle Help File Builder\.
Provide the <configuration> element in the component config when manually editing the .shfbproj file. Defines all the URL providers that your project needs.
The following example provides two URL providers for two different external API docs using formattedProvider that generate URLs based on a format:
<ComponentConfig id="Resolve ThirdParty Reference Links" enabled="True">
<component id="Resolve ThirdParty Reference Links">
<configuration>
<urlProviders>
<!-- URL provider for Autodesk Revit API Documentation -->
<formattedProvider title="Revit URL Provider">
<targetMatcher pattern="T:Autodesk\.Revit\..+" />
<urlFormatter format="https://api.apidocs.co/resolve/revit/{revitVersion}/?asset_id={target}" />
<parameters>
<parameter name="revitVersion" default="" />
</parameters>
</formattedProvider>
<!-- URL provider for RhinoCommon Documentation -->
<formattedProvider title="RhinoCommon URL Provider">
<targetMatcher pattern="T:Rhino\.Geometry\..+" />
<targetFormatter>
<steps>
<replace pattern="T:" with="T_" />
<replace pattern="\." with="_" />
</steps>
</targetFormatter>
<urlFormatter format="https://developer.rhino3d.com/api/RhinoCommon/html/{target}.htm" />
</formattedProvider>
</urlProviders>
</configuration>
<revitVersion value="$(RevitVersion)" />
</component>
</ComponentConfig>The next example cross-links GitHub pages using Sandcastle generated content in separate repos within the same organizational site:
<ComponentConfig id="Resolve ThirdParty Reference Links" enabled="True">
<component id="Resolve ThirdParty Reference Links">
<configuration>
<urlProviders>
<formattedProvider title="Gemstone.Communication URL Provider">
<targetMatcher pattern=".:Gemstone\.Communication(\.|$).*" fullyQualifiedMemberName="false"/>
<targetFormatter>
<steps>
<!-- Replace member separator tokens with underscores to match SHFB URL targets -->
<replace pattern=":|\.|`" with="_"/>
<!-- Remove any method parameter definitions to match SHFB URL targets -->
<replace pattern="\(([^\)]*)\)" with=""/>
<!-- When sandcastleTarget is set to "true", the above settings are the default -->
</steps>
</targetFormatter>
<urlFormatter format="https://gemstone.github.io/communication/help/html/{target}.htm" target="_self"/>
</formattedProvider>
<formattedProvider title="Gemstone.Threading URL Provider">
<targetMatcher pattern=".:Gemstone\.Threading(\.|$).*" fullyQualifiedMemberName="false" sandcastleTarget="true"/>
<urlFormatter format="https://gemstone.github.io/threading/help/html/{target}.htm" target="_self"/>
</formattedProvider>
<formattedProvider title="Gemstone.Timeseries URL Provider">
<targetMatcher pattern=".:Gemstone\.Timeseries(\.|$).*" fullyQualifiedMemberName="false" sandcastleTarget="true"/>
<urlFormatter format="https://gemstone.github.io/timeseries/help/html/{target}.htm" target="_self"/>
</formattedProvider>
<formattedProvider title="Gemstone.Diagnostics URL Provider">
<targetMatcher pattern=".:Gemstone\.Diagnostics(\.|$).*" fullyQualifiedMemberName="false" sandcastleTarget="true"/>
<urlFormatter format="https://gemstone.github.io/diagnostics/help/html/{target}.htm" target="_self"/>
</formattedProvider>
<!-- Match Gemstone IO namespace for classes not in common -->
<formattedProvider title="Gemstone.IO URL Provider">
<targetMatcher pattern=".:Gemstone\.IO(\.|$)(?!(?:Block|FilePath|Parsing\.I?Binary|Parsing\.Boolean|Parsing\.ISupportBinary|Parsing\.StringParser)).*" fullyQualifiedMemberName="false" sandcastleTarget="true"/>
<urlFormatter format="https://gemstone.github.io/io/help/html/{target}.htm" target="_self"/>
</formattedProvider>
<formattedProvider title="Gemstone.Numeric URL Provider">
<targetMatcher pattern=".:Gemstone\.Numeric(\.|$).*" fullyQualifiedMemberName="false" sandcastleTarget="true"/>
<urlFormatter format="https://gemstone.github.io/numeric/help/html/{target}.htm" target="_self"/>
</formattedProvider>
<!-- Add Gemstone root namespace last because it has the widest match criteria -->
<!-- Pattern excludes target namespace so local memmbers are not redirected to common -->
<formattedProvider title="Gemstone Common URL Provider">
<targetMatcher pattern=".:Gemstone\.(?!PhasorProtocols(\.|$)).*" fullyQualifiedMemberName="false" sandcastleTarget="true"/>
<urlFormatter format="https://gemstone.github.io/common/help/html/{target}.htm" target="_self"/>
</formattedProvider>
</urlProviders>
</configuration>
</component>
</ComponentConfig>titleattribute.targetMatcher.patternattribute: a regular expression that matches with the given key provided by Sandcastle e.gT:Autodesk.Revit.DB.Color. If this matches the given key, then the provider will be used.targetMatcher.fullyQualifiedMemberNameattribute: a boolean that indicates if the given type name is fully qualified when used as anchor text. For example,Autodesk.Revit.DB.Coloris fully qualified with a namespace, butColoris not -- defaults totrue.targetMatcher.sandcastleTargetattribute: a boolean that indicates if the given target is a Sandcastle documentation target. Whentrue, then the provider will be configured for Sandcastle rendered documentation sites which automatically detects method overloads and properly renders URL targets for the specific overloads, e.g.,_1or_2URL suffixes for second and third method overload pages, respectively. Additionally, if no target formatter steps are defined, the default steps will be set to replace:|\.|`with_and remove\(([^\)]*)\)whensandcastleTargetistrue-- defaults tofalse.parameters: a collection ofparameterelements that are inputs provided to the formatter, from the component configurations in Sandcastle e.g.revitVersionin the example above. This allows URL provides to use custom parameters set during build.
The URL format provider generates URLs based on a given format:
targetFormatter: set of steps to format the given type name e.g.T:Rhino.Geometry.CurvetoT_Rhino_Geometry_Curvein example above.urlFormatter.format: url format that includes{}tags fortargetand other parameters e.g. See{revitVersion}in the example above.urlFormatter.target: target window for the URL e.g._selfin the example above -- defaults to_blank.urlFormatter.rel: relative path to use for the anchor -- defaults tonoreferrer.
-
When targeting links to Sandcastle generated docs, it is easiest to create regular expressions for remote sites that use "member names" for topic file naming. Otherwise, explicit
targetFormatterconfiguration sections for each target may be required. -
For classes exposing generic methods from inherited types, resolving the correct type from the provided type info is not directly possible. In these cases the provided generic method type is labeled with a tick and an index, e.g.,
`0or`1, so the URL method title for type is simply rendered asT1orT2, respectively. This is usually not a huge issue since the generic type is described in the method summary and the method parameters are still rendered correctly.
- Eric Woodruff for Sandcastle (SHFB)
- Sand Castle icon by Icons8