-
Notifications
You must be signed in to change notification settings - Fork 137
Description
This issue proposes 3 new dartdoc directives:
{@include <path-to-file>[#<region>] [<options>]}, include a file region as markdown.{@example <path-to-file>[#<region>] [<options>]}, include a file region as fenced code snippet.
, where
<path-to-file>is one of:- relative-path (e.g.
../test/example.dart), relative to the file that the directive appears in. - absolute-path (e.g.
/src/myfile.dart), relative to thepackageUri` of the current packagepackageUriislib/folder in the root of the current package directory.- This the same logic as
import-statements.
- package URI (e.g.
package:foo/foo.dart), URI relative tolib/within given package.
- relative-path (e.g.
<region>is a region within the file (see Region resolution below), given as fragment in the URI for the file.<options>is space separated list of (optional) options:lang=<language>, language marker for the example (only applicable to{@example}directive).
Default value is inferred from the file extension of<path-to-file>.indent=keep|strip, whether to keep or strip indentation (see Whitespace stripping below)
Use cases:
- Testable code samples in documentation (by embedding regions from a test file)
- Break large code samples into small regions, embed and explain them bit by bit.
- Include a markdown file when writing very large documentation comments, instead of writing hundreds of lines in
///-prefixed doc comments (for better ergonomics).
Region resolution
We should allow authors to not just reference a specific file, but also a region within said file.
This proposal suggests that:
- Region
foois referenced using a URL-fragment, like../test/example.dart#foo. - Region
foois defined as:- Lines between
#region fooand matching#endregion(allowing for nested regions) - Omitting lines that include
#hide,#regionand#endregion
- Lines between
Example: example/hello.dart
/// Copyright 2025 Google LLC.
/// SPDX-License-Identifier: Apache-2.0
// #region main
void main() {
// #region hello
print('hello world');
// #endregion
exit(0); // force exit! #hide
}
// #endregionExample: example/hello.dart#hello
The region becomes:
print('hello world');Note: lines with #region and #endregion are not included!
Example: example/hello.dart#main
The region becomes:
void main() {
print('hello world');
}Note: lines with #hide are not included!
Whitespace stripping
Many examples are likely to appear nested inside main()/group()/test() callbacks in a file like test/example.dart file. Thus, it's often preferable to strip indentation.
Thus, we propose a indent=strip|keep option that defaults to strip!
Stripping indentation simply means:
- For each non-empty line, remove the minimum number of whitespaces that all non-empty lines has.
It's possible that we should do special things for \t, and that we should consider only removing an even number of whitespaces (I don't know anyone who uses indentation 1).
Example use case
With {@example} directive, we'd be able to write documentation like:
/// The following examples show to use [print]:
/// {@example example/hello.dart#hello}
void print(String line) {And get the following markdown:
The following examples show to use [print]:
```dart
print('hello world');
```
Notice:
- The language marker
dartcomes from the file extension. - We default to stripping indentation.
Upsides:
- Documentation examples can be included from
example/ortest/:- Giving users: auto-completion, syntax highlighting and formatting when writing examples.
- Enabling documentation examples to also run as test (covered by CI).
- Authors can omit test setup and technicalities using
#region/#hide.
- Compared to
{@tool}directives, this is fast and can work on pub.dev (without security concerns). - Inferring language marker from file extension just works for most file types (dart, yaml, etc).
- Stripping indentation is a good default for most use-cases.
- Path resolution is consistent
import-statements from Dart!
Downsides:
- We've introduce a new
#region/#endregion/#hidesyntax! (inspired by#regionin C#) - Stripping indentation can be a bit surprising.
- Using the same path resolution a
import-statements makes it a bit difficult to reference things fromtest/andexample/folders.