Hi all!
I'm excited to pitch new support in Swift-DocC for customizing some of the documentation compiler's default behaviors to support more contents types, especially thinking about more book-like content. These changes will make Swift-DocC a more appropriate tool for content like The Swift Standard Library and other large collections of conceptual documentation that are often put together for larger libraries or library ecosystems.
By default, Swift-DocC is optimized for documentation sites that include many symbols but comparatively few articles. This creates some problems when writing documentation that is made up of largely article-based content.
In order to address this, Swift-DocC will add a new kind of directive called an "option directive". Option directives will be similar to Swift-DocC's existing @Metadata directives but will be placed in a parent @Options
directive to set options for the current page. An option directive should customize an automatic behavior of the DocC compiler. This is distinct from DocC's existing concept of a Metadata directive which customizes some kind of content of the current page that isn't authored anywhere on the page body.
This pitch is organized similar to Supporting more dynamic content in Swift-DocC reference documentation as a collection of new directives.
I'm looking forward to your feedback around the naming and behavior of these directives.
@Options
A new @Options
directive for holding other directives describing how content on the local page should be autogenerated and rendered. This directive will function like the existing @Metadata
directive but be used specifically for “option directives” that effect the way content is rendered on the page (and not the content itself).
Any directive that can be used in @Options
is called an “option directive” and must also be supported in the corresponding @GlobalOptions
directive.
@Options {
@AutomaticTitleHeading(disabled)
@AutomaticSeeAlso(siblingPages)
@TopicsVisualStyle(list)
}
@GlobalOptions
A new @GlobalOptions
for holding option directives describing how a DocC archive should be rendered. The options included in this directive will apply to all pages in the current catalog.
If a catalog contains multiple @GlobalOptions
directives a warning will be emitted and both will be ignored.
The options included in the global options block will be superseded by any colliding elements in a page-specific @Options
block. This allows for authors to set a general behavior that most pages in a catalog will adhere to, while still customizing the behavior of certain specific pages.
@GlobalOptions {
@AutomaticTitleHeading(disabled)
@TopicsVisualStyle(grid)
}
@AutomaticTitleHeading
A new @AutomaticTitleHeading
option directive for customizing the way a page-title’s heading (also known as an eyebrow or kicker) is automatically generated.
Currently we render a page-title heading (also known as an eyebrow or kicker) describing the kind of the page on every page. For book-like content this might be less appropriate since the majority of pages are articles. The new @AutomaticTitleHeading
directive will allow for customizing this behavior on a given page.
@AutomaticTitleHeading
accepts an unnamed parameter containing one of the following:
-
pageKind
: A page-title heading will be automatically added based on the page’s kind. This is Swift-DocC’s current default if no automatic subheading generation style is specified. -
disabled
: A page-title heading will not be automatically created for the page. A page-title heading can still be explicitly created with the@TitleHeading
directive.
Examples
# ``SlothCreator``
@Options {
@AutomaticTitleHeading(disabled)
}
Catalog sloths you find in nature and create new adorable virtual sloths.
# ``SlothCreator``
@Options {
@AutomaticTitleHeading(pageKind)
}
Catalog sloths you find in nature and create new adorable virtual sloths.
Alternatives Considered
I’ve considered several alternative names for this directive and am very interested in feedback here. Some alternatives:
@AutomaticPretitle
@AutomaticEyebrow
@AutomaticSubheading
@AutomaticKicker
Unfortunately there doesn’t seem to be wide agreement on what to call this particular UI element. I feel strongly we should name it separately from its current relation to the page’s kind since authors could choose to put any information in the title heading so making this association is likely to lead to confusion.
@TitleHeading
A new @TitleHeading
metadata directive for customizing the text of a page-title heading (also known as an eyebrow or kick).
@TitleHeading
accepts an unnamed parameter containing containing the page-title’s heading text.
Examples
@Metadata {
@TitleHeading("Release Notes")
}
@AutomaticSeeAlso
A new @AutomaticSeeAlso
option directive for customizing the way See Also sections are automatically generated on a given page.
With the introduction of the navigation sidebar, Swift-DocC’s current automatic see also sections that are based on sibling pages have become somewhat redundant with the sidebar. I still see value in the autogenerated See Also sections, especially for readers on mobile devices where the sidebar is automatically collapsed, but exposing an option to exclude these items is appropriate.
In the future, we could imagine adding additional styles of automatically generated see also sections that authors could opt-in to here – beyond just sibling pages.
@AutomaticSeeAlso
accepts an unnamed parameter containing one of the following:
-
siblingPages
: The current list of auto-generated “See Also” items based on sibling items. This is Swift-DocC’s current default if an automatic see also style is not specified. -
disabled
: Do not automatically generate any See Also items.
Examples
@Options {
@AutomaticSeeAlso(disabled)
}
@TopicsVisualStyle
A new @TopicsVisualStyle
option directive for customizing the way Topics sections are rendered on a given page.
Swift-DocC’s current list-style of child topics is great for API-style documentation where we expect pages to not have too many children and we expect page titles to be relatively long declarations. But for book-like content where items are divided into chapters and page titles are generally shorter, a grid-like view can offer a better experience. For other cases, it might be better to do away with on-page rendering of child pages entirely and allow the navigator to be the singular-stop for navigation. The new @TopicsVisualStyle
directive will allow for customizing the way child pages are rendered on the page.
This directive can be used in combination with the below @PageImage
directive by providing a page image with a card
purpose. If no explicit card image is provided, then the page’s icon will be used to auto-generate a card image.
@TopicsVisualStyle
accepts an unnamed parameter containing one of the following:
-
list
: The current list of topics we render on page, including their abstracts. This is Swift-DocC’s current default if a topics style is not specified. -
compactGrid
: A grid of items based on the card image for each page. Includes each page’s title and card image but excludes their abstracts. -
detailedGrid
: A grid of items based on the card image for each page, includes the abstract for each page. -
hidden
: Don’t show child pages anywhere on the page.
Examples
# Feeding a Sloth
Find out how to feed a sloth and how to keep your sloth healthy.
@Options {
@TopicsVisualStyle(compactGrid)
}
## Topics
### Sloth Dietary Preferences
- <doc:Get-Started-Preparing-Sloth-Food>
- <doc:Feeding-your-Sloth-in-the-Winter>
- <doc:Ordering-Food-Delivery>
### Healthy Habits for Sloths
- <doc:Balancing-Meals>
- <doc:Meal-Prep-for-Sloths>
- <doc:Staying-Hydrated>
- <doc:Components>
- <doc:Inputs>
- <doc:Technologies>
### Treats for your Sloth
...
# Feeding a Sloth
Find out how to feed a sloth and how to keep your sloth healthy.
@Options {
@TopicsVisualStyle(detailedGrid)
}
...
@PageImage
A new @PageImage
directive that can be placed inside a page’s @Metadata
directive block to allow for customizing the images that will be used to represent the page in the navigator, hero, and elsewhere in the UI.
For article-only catalogs it’s likely helpful to distinguish between articles with custom icons- in the same way we have different icons for different kinds of symbol pages.
@PageImage
accepts the following parameters:
-
purpose
: The purpose of the image. One of the following:-
icon
: This image should be used in place of wherever a generic icon for the page would usually be rendered. Today that includes page’s hero introduction section and the navigator sidebar. -
card
: This image should be used whenever rendering a card representing this page. Today that includes Topics sections that are styled as grids.
-
-
source
: A string containing the name of an image in your DocC catalog. -
alt
: (optional) A string containing a description of the image.
Examples
# Feeding a Sloth
@Metadata {
@PageImage(purpose: icon, source: "leaf.svg", alt: "An icon representing a leaf.")
}
# Meal Prep for Sloths
@Metadata {
@PageImage(purpose: icon, source: "hot-soup.svg", alt: "An icon representing a bowl of hot soup.")
}
# Get Started Preparing Sloth Food
Learn how to meal prep for your sloth and plan ahead for busy weeks.
@Metadata {
@PageImage(purpose: card, source: "sloth-with-food", alt: "A happy sloth eating a snack.")
}
@CustomMetadata
A new @CustomMetadata
directive that accepts an arbitrary key/value pair and emits it into the metadata of the created RenderJSON describing the page. This adds some flexibility for developers who might want to extend Swift-DocC’s functionality with another tool that acts on the emitted JSON – without requiring modification to the DocC compiler itself.
@CustomMetadata
accepts the following parameters:
-
key
: A key to identify the piece of metadata. -
value
: The value for the metadata.
Future Directions
This general framework of directives allows for some exciting possibilities such as:
@AutomaticPagination
A new @AutomaticPagination
option directive to allow for automatic generation of next and previous page navigation that is commonly found in book-like documentation sites like The Swift Programming Language:
@NextPage
and @PreviousPage
New @NextPage
and @PreviousPage
metadata directives that allow for explicitly specifying next and previous page navigation for a given page.
@AutomaticTopics
A new @AutomaticTopics
option directive that allows for controlling the way child topics are automatically organized. This could be a great way to address Default to order by source line number instead of alphabetically for default layout · Issue #340 · apple/swift-docc · GitHub.
/// Something here
///
/// @Options {
/// @AutomaticTopics(sourceOrder)
/// }
enum A {
case one
case two
case three
}
@PageColor
A new @PageColor
metadata directive that would behave much like the pitched @PageImage
directive and allow for specifying what color should be used to represent the given page.
@ChildOptions
A new @ChildOptions
directive to go with the @GlobalOptions
and @Options
directive. This directive would be used to set options for pages that are organized as children of the page that owns this directive.
This would allow for authors to more easily create subsections of their documentation that are generated in a more book-like fashion (with pagination for example) while using different options for the more API-like part of their documentation.
These changes create a framework to allow Swift-DocC to address the needs of many different kinds of documentation while still supporting a great out-of-the-box experience for the most common use cases.