Improving the presentation of Swift-DocC declarations

Hello everyone.

We're looking to improve the presentation of declarations for Swift symbols in Swift-DocC. Specifically, we're focusing on a way to make the "Declaration" section easier to read and scan for functions, initializers, and subscripts when multiple parameters are involved.

Here are examples of what functions with multiple parameters look like when rendered with Swift-DocC-Render today:

Long functions like this can be a little difficult to read when the entire declaration is wrapped in this simple way.

With this Swift-DocC-Render PR, those examples would now look like this:

With this small update, each parameter of a multi-parameter function/initializer/subscript will be broken onto its own line and indented so that the symbol as a whole is easier to visually parse and understand—hopefully this makes it much simpler for developers to mentally map the "Declaration" and "Parameters" sections together when reading documentation for Swift APIs.

Single parameter symbols would continue to look the same way that they do today with this new approach.

In the future, it would be worth exploring if a tool like swift-format could be integrated with DocC to further improve the presentation of declarations and go beyond simple updates like this, although that would be a larger effort. While improving the readability of the default formatting is an immediate goal, it would also be good to explore how this kind of formatting can be customized to better match the particular style that a project has adopted for its code.

27 Likes

I find the updated view notably more readable for the complex function case, and I'm not bothered at all by the verticality that it adds - that's easier for me to scan down than to deal with the text wrapping.

Based on your post, I'm uncertain of what is considered Docc vs. Docc-Render's responsibility. I love the idea of using something like swift-format to help with this, but I'm not familiar with which piece should be responsible in this case.

I can see where Docc would be easier to integrate with swift-format since both are in swift, where Docc-Render is more javascript - but does this mean that whatever text block Docc presents in mark-down-ish (or whatever) format in the various JSON files for the renderer is expected to be respected?

1 Like

Big +1!

This is something I've never been entirely happy with in any documentation tool I've used, and to be honest it can even be difficult when manually formatting declarations in code.

I wonder if allowing manual formatting should also be an option (i.e. presenting the declaration exactly as it is in source code). It seems to me like the biggest issue when producing a great presentation for both would be differences in line length, but most projects enforce a maximum length anyway. The benefit of this approach is that it should be relatively simple to implement, and gives authors maximum control over their presentation.

Also, I like that the PR mentions allowing the indentation to be customised. 4 spaces seem a bit too much to me, and all of my code snippets use 2-space indentation. I'd like them to be consistent.

5 Likes

+1, this is a huge win for legibility :tada:

An integration with a formatting/linting tool like swift-markdown in the future would certainly make sense. We'd need the DocC compiler to invoke the formatting tool somehow, emit the formatted declaration in the Render JSON, and for DocC Render to render it verbatim. This would provide the added benefit of the declarations in the project's source code being the same as what's shown in docs.

But in the meantime, this DocC Render–only solution is a huge step forward, thank you @marcus_ortiz!

3 Likes

I find the updated view notably more readable for the complex function case, and I'm not bothered at all by the verticality that it adds - that's easier for me to scan down than to deal with the text wrapping.

Based on your post, I'm uncertain of what is considered Docc vs. Docc-Render's responsibility. I love the idea of using something like swift-format to help with this, but I'm not familiar with which piece should be responsible in this case.

I can see where Docc would be easier to integrate with swift-format since both are in swift, where Docc-Render is more javascript - but does this mean that whatever text block Docc presents in mark-down-ish (or whatever) format in the various JSON files for the renderer is expected to be respected?

I think the question of responsibility between the compiler and renderer can be slightly tricky when it comes to things like this. For this particular PR, we chose to implement it in the renderer since it is a small update that only impacts whitespace for now. However, I see this as the type of thing that we may eventually want to move to the DocC compiler side of things for a couple of reasons:

  • as you mentioned, when integrating something like swift-format, it likely makes more sense to directly integrate it as a Swift package since it is directly working with syntax trees*—or at least it would be a little awkward to have to call out to a separate process to do this on the fly in the renderer
  • by implementing this on the compiler side, other potential renderers could benefit from the same functionality without having to re-implement what Swift-DocC-Render has done

* I did actually investigate using swift-format from DocC initially, but there are some non-trivial issues to work out for this approach.

1 Like

These are all great points. I really like the idea of having the capability to have the declaration be rendered exactly as-written in the source code, however the way that the actual text data is generated for symbol graphs does not exactly mimic the in-source formatting, so that would be something that needs to be resolved first to make this possible.

For the number of spaces, I agree that it would be great to have the ability to customize this, along with a number of other stylistic choices for the declaration but also the renderer in general. I expect this kind of customization is something we want to explore in the near future.

2 Likes

I think there is value in keeping some of the responsibility within the renderer. For example, the compiler side cannot predict the size of the browser window documentations are viewed in, but the renderer should be able to know this information and adapt code presentation to it.

1 Like

Would it be possible to keep the same format as the source code? Indeed the new behaviour is way more readable and that's who I typically write long functions (thanks to swiftformat). It would be interesting if the output could match the source so a dev can tweak how they want the docs to look like.

It's not possible today due to the way that the source data is emitted in the symbol graph. However, I think it would be interesting to explore this approach in the future. It would require changes to how the symbol graph is generated, but there has been feedback from others that this would be a nice feature to have.

1 Like

I am going to die on this hill. We had the topic in my team and finding a consensus would be really hard.. because I would argue that you don't need it if the func signature carries just two params.