Setting a documentation article’s platform availability

Hello! I’d like to propose a new feature for Swift-DocC to add some functionality that’s currently missing: Giving documentation articles their own platform availability information, separately from the “fallback” data given for the catalog as a whole.

Currently, platform availability is set in one of two ways:

  1. Directly from source code, in @available attributes in Swift and the equivalent attributes in Objective-C, or
  2. The “Default Availability” entry in the Info.plist for a documentation catalog, or the --platform flag to docc itself, which both set platform availability for the catalog as a whole.

Critically, this means that the only kinds of documentation pages that can currently set their own platform availability are symbols, and only if their source code (and symbol graph translation) have that availability set. If you were to write a documentation article or tutorial that relied on OS APIs that were added in a certain platform version, you would have to write this in your prose, separately from the page metadata that symbols otherwise get for free.

In addition, there are extra signals that are associated with “platform versioning” that are also valuable, such as deprecation, or even currently unavailable, such as “Beta” designation.

Proposed solution

I would like to add a new metadata directive that acts as an analog of the @available attribute in Swift, for the kinds of information that Swift-DocC currently uses and displays. It would allow you to set an article’s platform availability as if it were a symbol, and override a symbol’s availability via a documentation extension. This lets you flag some piece of content as only being valid for some platform or OS version.

The attribute operates similarly to the @available attribute in Swift. It would be written in the page metadata and look something like this:

@Metadata {
    @Available(iOS, introduced: "12.0")
    @Available(macOS, introduced: "10.14")
}
@Metadata {
    @Available(*, deprecated: true)
}
@Metadata {
    @Available(*, isBeta: true)
}

The first argument matches the list of platforms from the Swift reference, linked above. An asterisk (*) can be used to indicate “all platforms” for the purposes of applying deprecation or beta status.

The introduced argument allows you to specify a version number for a specific platform. The deprecated argument allows you to indicate that the page should be marked as “deprecated”. To write a deprecation message to display on the page, the @DeprecationSummary directive can be used. Conversely, the isBeta argument can be used to mark the page as “Beta”.

Open questions

  • What combination of attribute arguments makes sense to support? The @available attribute in Swift supports much more metadata than Swift-DocC currently renders.
  • Should we extend this attribute to include information without an analog in source, like the package version an API was introduced in? Or even an arbitrary string? Could that information live in a separate attribute without being too confusing, or should @Available be designed to accept this information as well?

Let me know what you think! In combination with my other proposal for Sample Code links and page kinds, this can provide a powerful mechanism to mark what OS version(s) a sample requires. I’m excited to add this feature to Swift-DocC and make documentation even more powerful.

10 Likes

It'd be useful for an article to indicate which version of an app it requires (particularly for app targets, but more generally too). Something akin to PlaygroundBluetooth indicating its availability on Swift Playgrounds 2.0+.

Yeah, i think it's valuable to be able to specify arbitrary "platforms" like that. I just wasn't sure the best way to wedge that into a directive that is meant to mirror the Swift @available attribute, or whether a separate attribute would work better.

4 Likes

This looks great! I'm excited to have this extra functionality – I think being able to mark individual symbols as beta in documentation will be especially useful for packages.

The only thing that stands out to me is the use of * for "all platforms".

I always have trouble remembering this syntax in Swift so I'd prefer to not replicate that potential problem here. I'm in support of allowing folks to write * to match the behavior of Swift, but I think ideally we shouldn't require it.

Would it be reasonable to just assume an @Available directive applies to all platforms if none is specified? Essentially allowing for:

@Metadata {
    @Available(deprecated: true)
}
@Metadata {
    @Available(isBeta: true)
}

Beyond that, my only quibble is with isBeta. Should we be consistent between the spelling for marking a symbol as deprecated and the spelling for beta? isBeta feels more "Swifty" to me but since we don't have isDeprecated it's a little inconsistent.


This looks great overall to me though – and I think is a great starting point for expanding on in the future if folks have need for some of the more advanced capabilities of Swift's @available attribute.

- Ethan

1 Like

This could work! I mainly included the asterisk requirement to mirror the Swift attribute, but i also frequently forget how its syntax works. We could probably build out something that's distinct that would provide the same information.

If we're diverging from the Swift attribute, we could probably go for isDeprecated to make it fit in a bit better. Then we could see about adding a version with arbitrary platform strings, like @krilnon asked about.

2 Likes

Circling back:

With Ethan's suggestion, the directive would look something like this:

Adding deprecation or beta markers for all platforms:

@Metadata {
    @Available(isDeprecated: true)
}
@Metadata {
    @Available(isBeta: true)
}

Setting platform availability for specific platforms would look the same as in the original proposal:

@Metadata {
    @Available(iOS, introduced: "15.0")
}

One thing i thought about while writing this out: I'll need to double-check what DocC does with a partial list of availability information. If you want to tag an article as being iOS-specific, but your Info.plist gives fallback information for macOS as well, will we need to add an unavailable: true parameter to this directive? This is something that will likely come out the initial implementation effort.

2 Likes

I've implemented a stripped-down version of the directive in add `@Available` directive for setting platform availability by QuietMisdreavus · Pull Request #440 · apple/swift-docc · GitHub. Unfortunately i had to delay adding the isBeta and isDeprecated arguments; there needs to be work done in Swift-DocC-Render first. However, this should still lay the foundation.

2 Likes

I've revisited the @Available directive because i realized it was not a huge change to allow for arbitrary "platforms" in the directive. That patch is now up here: allow arbitrary platform strings in the `@Available` directive by QuietMisdreavus · Pull Request #463 · apple/swift-docc · GitHub

With this change, these directives would now become legal, and these names will be printed verbatim on the documentation page:

@Metadata {
    @Available(MyDependency, introduced: "1.0")
    @Available("My Package", introduced: "2.0")
}
2 Likes