Syncing With Upstream JSON Format Changes In Typst Documentation

by StackCamp Team 65 views

Hey guys! Let's dive into the recent updates and changes in Typst's docs.json format. This is a crucial update, especially if you're contributing to the documentation or working with Typst's internals. We’re going to break down the key changes, why they matter, and how you can adapt to them. So, buckle up and let's get started!

Understanding the docs.json Format Change

The recent merge in https://github.com/typst/typst/pull/7011 brought about significant changes to the docs.json format. The primary motivation behind these changes is to enhance the flexibility and structure of the documentation, making it more comprehensive and user-friendly. The two major updates revolve around the fields in FuncModel and ParamModel, as well as the structure of examples within the documentation. Understanding these changes is the first step in ensuring a smooth transition and maintaining the quality of Typst's documentation.

Combining details: Html and example: Option<Html> into details: Vec<DetailsBlock>

One of the most significant changes is the consolidation of the details: Html and example: Option<Html> fields within FuncModel and ParamModel. Previously, these fields were separate entities, leading to potential redundancy and a less structured approach to documentation. Now, they've been combined into a new field: details: Vec<DetailsBlock>. This change allows for a more organized and versatile way to present detailed information and examples.

The DetailsBlock enum is the heart of this update. It provides a structured way to represent different types of content within the documentation, whether it's plain HTML or an example. This is a big step towards making our documentation more maintainable and expressive. By using a vector of DetailsBlock, we can include multiple types of content—HTML explanations, code examples, and more—in a single, coherent section. This new structure not only simplifies the data model but also enhances the readability and utility of the documentation. It gives us the flexibility to mix and match different content types, creating a richer and more engaging learning experience for users. Think of it as leveling up our documentation game from simple text blocks to a dynamic, multi-faceted presentation.

Introducing Optional Titles for Examples

The second major update is the introduction of optional titles for examples. Previously, examples were presented without a title, which sometimes made it challenging to understand the context or purpose of the example at a glance. Now, the Example struct within DetailsBlock can have an optional title, providing a concise description or context for the example. This seemingly small change can significantly improve the usability of the documentation, especially for complex functions or parameters.

Titles help users quickly grasp the intent of the example and how it applies to their specific use case. This addition is about making the documentation more accessible and user-friendly. A title can act as a quick guide, helping users decide whether a particular example is relevant to their needs. Imagine scanning through a list of examples and instantly knowing which ones are most likely to help you – that's the power of a well-crafted title. Moreover, this update allows documentation contributors to add context and clarity to examples, ensuring that users can easily understand and apply the provided code snippets. It’s a small enhancement, but one that speaks volumes about our commitment to creating top-notch documentation.

Diving Deep into the Rust Code: DetailsBlock

To truly grasp the changes, let's dive into the Rust code snippet provided. This code defines the DetailsBlock enum, which is central to the updated docs.json format. Understanding this code will give you a clearer picture of how the new structure works and how you can leverage it in your documentation efforts.

/// A block-level segment in a function's or parameters documentation.
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "kind", content = "content")]
pub enum DetailsBlock {
    /// A block of HTML.
    Html(Html),
    /// An example with an optional title.
    Example { body: Html, title: Option<EcoString> },
}

Breakdown of the DetailsBlock Enum

The DetailsBlock enum is defined with two variants: Html and Example. The Html variant represents a block of HTML content, allowing you to include formatted text, links, and other HTML elements in your documentation. The Example variant, on the other hand, represents an example with an optional title. This variant contains two fields: body, which is the HTML content of the example, and title, which is an Option<EcoString> representing the optional title. Let's break down each component to fully appreciate its role.

Html(Html)

The Html(Html) variant is straightforward. It’s designed to hold HTML content, which means you can include anything from basic text formatting to complex layouts. The flexibility here is key. You can use HTML to create lists, tables, formatted paragraphs, and more. This ensures that your documentation can handle a wide range of presentation needs. Think of this as your canvas for explaining concepts in detail. You can embed links, use different text styles, and even include images if needed. The goal is to make the documentation as informative and engaging as possible.

Example { body: Html, title: Option<EcoString> }

This is where the magic happens. The Example variant is a struct-like variant that holds the actual example code or demonstration (body) and an optional title (title). The body is of type Html, giving you the same flexibility as the Html variant for formatting the example. The title is an Option<EcoString>, which means it can either contain a title or be None. This optional title is a game-changer. It allows you to provide a brief, descriptive label for each example, making it easier for users to understand its purpose and relevance.

Serde Attributes

The DetailsBlock enum also uses several Serde attributes, which are crucial for serialization and deserialization. These attributes tell Serde how to convert the Rust enum into a JSON representation and vice versa. Let's take a closer look at these attributes:

  • #[derive(Debug, Serialize)]: This attribute tells Rust to automatically generate code for debugging and serialization. The Debug trait allows you to print the enum for debugging purposes, while the Serialize trait allows you to convert the enum into a JSON string.
  • #[serde(rename_all = "camelCase")]: This attribute tells Serde to rename all the enum variants to camel case when serializing to JSON. For example, the Html variant will be serialized as "html", and the Example variant will be serialized as "example". This ensures consistency with the JSON format used in Typst's documentation.
  • #[serde(tag = "kind", content = "content")]: This attribute is the most interesting one. It tells Serde to serialize the enum as a tagged enum. In a tagged enum, the enum variant is represented as a JSON object with two fields: kind and content. The kind field contains the name of the enum variant (e.g., "html" or "example"), and the content field contains the value of the variant. For the Html variant, the content field will contain the HTML content. For the Example variant, the content field will be a JSON object containing the body and title fields. This format is highly structured and makes it easy to parse and work with the JSON data.

Why These Changes Matter

So, why should you care about these changes? Well, these updates are all about making Typst's documentation better, more accessible, and easier to maintain. And that benefits everyone who uses Typst. Let's break down the key reasons why these changes are significant.

Enhanced Documentation Structure and Readability

The move to Vec<DetailsBlock> provides a more structured and organized way to present documentation details. By combining HTML content and examples into a single vector, we can create a more cohesive and readable documentation experience. This means that related information stays together, making it easier for users to follow along and understand complex concepts. Think of it as decluttering your desk – when everything has its place, it's much easier to find what you need. This improved structure also allows us to mix different types of content seamlessly. We can interleave explanations with examples, providing a more engaging and effective learning experience.

Improved User Experience

Optional titles for examples are a game-changer when it comes to user experience. A clear, descriptive title can immediately tell users what an example is about, saving them time and effort. This is particularly useful for complex functions or parameters where multiple examples might be needed to cover different use cases. Imagine you're looking for a specific example, like how to format a date in Typst. If each example has a title like