Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: improve contributing guidance for api documentation #9778

Merged
merged 1 commit into from
Mar 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
## Description

<!-- insert description here -->

## Notes for the release

<!-- If this PR should be described in the Ember release blog post please briefly describe what should be shared. -->

<!-- Thank you for opening up this PR! -->

- If this PR updates API docs, preview them by running `bun preview-api-docs`
- Read the full [contributing documentation](https://github.com/emberjs/data/blob/main/contributing/become-a-contributor.md)
- If you do not have permission to add labels or run the test-suite in CI, a team member will do this for you.
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ detailing how to become involved to best ensure your contributions are successfu
- [Becoming a Contributor](./contributing/become-a-contributor.md)
- [Requesting Features or Deprecations](./contributing/rfc-process.md)
- [Submitting Pull Requests](./contributing/submitting-prs.md)
- [Writing API Docs](./contributing/writing-api-docs.md)
- [Linking the project to your application locally](./contributing/linking-to-applications.md)
- [Key Concepts](./contributing/key-concepts.md)

Expand Down
1 change: 1 addition & 0 deletions contributing/become-a-contributor.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ or [RFCs](https://github.com/emberjs/rfcs/labels/T-ember-data), we coordinate wo

- [Setting Up The Project](./setting-up-the-project.md)
- [Project Architecture](./project-architecture.md)
- [Writing API Docs](./writing-api-docs.md)
- [Key Concepts](./key-concepts.md)
- [Terminology](./terminology.md)
- [RFC Process](./rfc-process.md)
319 changes: 319 additions & 0 deletions contributing/writing-api-docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,319 @@
# Writing API Docs

API Documentation is generated from [yuidoc](https://yui.github.io/yuidoc/) comments in the source code.

YUIDoc syntax is very similar to [JSDoc](https://jsdoc.app/) but there are occassional nuances where
it becomes best to know the underlying parser is YUIDoc.

While API Documentation lives with the source-code, the code itself plays no-part in the documentation
that is generated: everything is compiled from comments alone.

<br>

---

<br>

## Documentation Syntax

<br>

### What are Doc Comments

Only `**` comments are compiled as potential documentation, e.g.

```ts
/**
* This is a potential documentation block
*/
```

Where as single star comment blocks are not considered documentation

```ts
/*
* This is not a potential documentation block
*/
```

<br>

### Ignored Doc Comments

When compiling the API documentation, several categories of comments will be ignored:

- `@internal` - signifies internal documentation for contributors for a non-public API
- `@feature` - signifies documentation for an unreleased feature gated by a canary flag
- `@typedoc` - signifies typescript-only (in-editor) documentation that should not be compiled into the API docs

Additionally, use of the following tags will cause a doc comment to be ignored due to intended use primarily being docs
written for in-editor experience similar to `@typedoc`

- `@see`
- `@link`
- `@inheritdoc`

For example, the below doc comment would be ignored

```ts
/**
* This is a private utility for updating the state
* of a relationship.
*
* @internal
*/
```

<br>

### Always Start with `@module`

The YUIDocs parser will attribute all documentation it discovers to the most recent
`module` (package) declaration it has seen. For this reason, any file that has documentation
comments should declare the package it applies to at the top of the file.

For instance, if we were writing documentation for a feature within the `@ember-data/store`
package, we would declare the following at the top of the file:

```ts
/**
* @module @ember-data/store
*/
```

### Doc Comments can be Markdown

Doc comments can contain most any valid markdown syntax, most markdown-valid html,
and can utilize code-highlighting via language prefix on a code block comment.

For instance

```ts
/**
* ## Overview
*
* Some details
*
* ### An Example
*
* ```ts
* new Store();
* ```
*
* @class Store
* @public
*/
```

<br>

### Doc Comments should start every line with a `*`

While technically doc comments only need to start with `/**`, providing a `*` for
every line with matching indentation ensures correct parsing of all tags and documentation.

Without this, some decorators in code examples may be incorrectly parsed as documentation tags,
and some documentation may be unexpectedly truncated.

**Good**

```ts
/**
* ## Overview
*
* Some details
*
* ### An Example
*
* ```ts
* class User extends Model {
* @attr name;
* }
* ```
*
* @class Store
* @public
*/
```

**Bad**

```ts
/**
## Overview

Some details

### An Example

\```ts
class User extends Model {
@attr name;
}
\```

@class Store
@public
*/
```

### Documenting Modules

Yuidoc syntax refers to packages as "modules". To declare that some code
is part of a module, we use `@module <name>`, so the package `@warp-drive/core-types`
is `@module @warp-drive/core-types`.

Modules are documented using a special `@main` tag.

For instance, to write documentation giving an overview of `@warp-drive/core-types`
we would do the following.

```ts
/**
* This package provides essential types and symbols used
* by all the other WarpDrive/EmberData packages.
*
* @module @warp-drive/core-types
* @main @warp-drive/core-types
*/
```

Sometimes we may want to reuse the documentation for a primary default export
class as the module documentation as well. In this case `@module` will be
declared standalone while `@main` will be affixed to the exported class doc comment.

```ts
/**
* @module @ember-data/serializer/json-api
*/
/**
* << module (and class) overview goes here >>
*
* @class JSONAPISerializer
* @main @ember-data/serializer/json-api
* @public
*/
```

<br>

### Documenting Classes

Classes are documented using `@class`.

```ts
/**
* @since 1.13.0
* @class JSONAPIAdapter
* @main @ember-data/adapter/json-api
* @public
* @constructor
* @extends RESTAdapter
*/
```

Methods are documented with `@method` and attatch to the most recent class the parser has
seen.

```ts
/**
* Some documentation
*
* @method myMethod
* @public
* @param {AType} myParam explanation of the param
* @return {AnotherType} explanation of the return value
*/
```

Properties are documented with `@property` and attach to the most recent class the parser has seen.

```ts
/**
* An explanation of the property
*
* @property {SomeType} propertyName
* @public
*/
```

Static methods and properties can be documented by adding `@static` to the definition.

<br>

### Documenting Functions

Functions are documented as "static" methods on modules. For instance the method `recordIdentifierFor`
imported from `@ember-data/store` would be done like the below

```ts
/**
* Description of the function
*
* @public
* @static
* @for @ember-data/store
* @param {Object} record a record instance previously obstained from the store.
* @return {StableRecordIdentifier}
*/
```


<br>

### Documenting Interfaces and Types

Yuidoc and the ember API docs do not have a mechanism for documenting types. However, because
documentation is entirely doc-comment driven, we can document interfaces and types as classes,
and mark them as such by giving them impossible names. Generally we follow the convention of
`<Interface> AnInterface` and `<Type> AType` for this.

For example, the interface for creating a request handler is documented as a class below
whose name is `<Interface> Handler`.

```ts
/**
* << Handler Documentation >>
*
* @class <Interface> Handler
* @public
*/
```

<br>

---

<br>

## Documentation Hygeine

<br>

### Documentation Tests

Run `pnpm test:docs`

This will lint discovered doc comments for common sources of error, as well as validate that no published documentation
has been added or removed unexpectedly.

If documentation has been added, an entry for it should be added to `tests/docs/fixtures/expected.js`.
If documentation has been removed, similarly any entry for it should be removed from `tests/docs/fixtures/expected.js`.

If documentation you've added is not being discovered by the test, it is likely that either

- it may have been excluded due to using an [ignored doc comment](#ignored-doc-comments)
- it may have been excluded due to not using the right [comment syntax](#what-are-doc-comments)
- it may have been included in the list of paths to search for source code documentation in [yuidoc.json](../docs-generator/yuidoc.json)

<br>

### Previewing Documentation

Run `bun preview-api-docs` from the project root or the `docs-viewer` directory.

This will build and run the (external) api-docs app with the current state of the api docs in the repo.

Changes need to be manually rebuilt with `bun rebuild-api-docs`.

See the [Docs Viewer README](../docs-viewer/README.md) for more info.
8 changes: 4 additions & 4 deletions packages/core-types/src/schema/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1548,7 +1548,7 @@ export type Schema = ResourceSchema | ObjectSchema;
* @static
* @for @warp-drive/core-types
* @param {ResourceSchema} schema
* @returns {ResourceSchema} the passed in schema
* @return {ResourceSchema} the passed in schema
* @public
*/
export function resourceSchema<T extends ResourceSchema>(schema: T): T {
Expand All @@ -1565,7 +1565,7 @@ export function resourceSchema<T extends ResourceSchema>(schema: T): T {
* @static
* @for @warp-drive/core-types
* @param {ObjectSchema} schema
* @returns {ObjectSchema} the passed in schema
* @return {ObjectSchema} the passed in schema
* @public
*/
export function objectSchema<T extends ObjectSchema>(schema: T): T {
Expand All @@ -1579,7 +1579,7 @@ export function objectSchema<T extends ObjectSchema>(schema: T): T {
* @static
* @for @warp-drive/core-types
* @param schema
* @returns {boolean}
* @return {boolean}
* @public
*/
export function isResourceSchema(schema: ResourceSchema | ObjectSchema): schema is ResourceSchema {
Expand All @@ -1593,7 +1593,7 @@ export function isResourceSchema(schema: ResourceSchema | ObjectSchema): schema
* @static
* @for @warp-drive/core-types
* @param schema
* @returns {boolean}
* @return {boolean}
* @public
*/
export function isLegacyResourceSchema(schema: ResourceSchema | ObjectSchema): schema is LegacyResourceSchema {
Expand Down
2 changes: 1 addition & 1 deletion packages/experiments/src/persisted-cache/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export class PersistedCache implements Cache {
* @method peek
* @internal
* @param {StableRecordIdentifier | StableDocumentIdentifier} identifier
* @returns {ResourceDocument | ResourceBlob | null} the known resource data
* @return {ResourceDocument | ResourceBlob | null} the known resource data
*/
peekRemoteState<T = unknown>(identifier: StableRecordIdentifier<TypeFromInstanceOrString<T>>): T | null;
peekRemoteState(identifier: StableDocumentIdentifier): ResourceDocument | null;
Expand Down
Loading