DocC’s Snippets feature today lets you reference and slice Swift source files from within a catalog for inclusion in articles.
proposes extending this in two directions:
(1) content from outside the catalog — e.g. referencing a README at the repo root or generated build artifacts without moving them into the catalog;
(2) source from languages other than Swift — e.g. C/C++ (and others) so that validated, tested source (or slices) can be included in DocC articles, which is especially important for Swift interop documentation. I’d like to use this thread to align on an approach before or while contributing to this feature.
Motivation
Markdown / content outside the catalog
- Reference and include files (e.g. README) that live at the repo root or elsewhere in the project, without duplicating them into the catalog.
- Same idea for generated sources that are part of the build and are awkward to incorporate today.
Source files beyond Swift
- Today: only Swift is supported for the “snippet from file” workflow; other languages require copying snippets into the catalog (high maintenance).
- Goal: point the catalog at a specific source file (any supported language), and use it like a snippet — including optional slicing (similar to Swift snippet comments) — so it can be included in articles.
- Enables better documentation for Swift ↔ C/C++ (and other) interop, and “here’s how this code works” documentation that links to real source and shows portions inline.
Importance: Reduces friction for managing snippets, especially for non-Swift languages, and makes it easier to keep documentation in sync with actual source.
Current behavior
- Snippets today: DocC Snippets are Swift-only and live inside the catalog (e.g. in a `Snippets` directory). You reference them from articles and can slice by line or by special comments.
- External content: There’s no built-in way to “include” or “reference” a file that lives outside the catalog (markdown or source) and have it rendered as first-class content/snippet.
- Alternatives today: Manually copy external source or markdown into the catalog and maintain the duplicate.
Suggested approach (options to discuss)
Option A: “External snippet” / “external content” resource type
Introduce a catalog-level concept (e.g. “external snippet” or “external content”) where the catalog declares a path (relative to repo root or to the catalog) to a file outside the catalog. DocC then treats it like a snippet: load the file, optionally slice it (with language-specific or generic slice rules), and make it referenceable in articles.
Pros: Explicit, declarative; one place to define what’s included; works for both markdown and source.
Cons: Requires defining schema (e.g. in Info.plist or a manifest), resolution rules (relative to what?), and behavior when the file is missing or moved.
Slicing for non-Swift: Either define a simple slice format (e.g. line ranges, or a comment convention like `// snippet: id`) that multiple languages can use, or start with “whole file” and add slicing per language later.
Option B: Inline path / reference in markup
Allow article/tutorial markup to reference an external file by path (e.g. a directive like `@SourceFile(path: "Sources/Foo/bar.c")` or similar). DocC resolves the path relative to a defined root (catalog or repo) and embeds the content (or a slice) as a code listing.
Pros: Very flexible; authors reference exactly where they need; no separate “registry” of external files.
Cons: Path handling and security (what roots are allowed); harder to validate “all referenced files exist” in one pass; need a clear story for slicing (e.g. line range or named region).
Option C: Extend Snippets directory semantics
Keep a single “Snippets” (or “Content”) area but allow it to contain references (symlinks, or manifest entries) to files outside the catalog. DocC would follow the reference, detect language from extension (or manifest), and support slicing where defined (e.g. Swift-style comments for Swift; line ranges or a simple convention for others).
Pros: Reuses existing “snippet” mental model; incremental extension.
Cons: May blur “inside catalog” vs “outside”; need clear rules for resolution and fallbacks.
Option D: Phased rollout
- Phase 1: External markdown only — e.g. “include file at path X” for `.md` files (README, etc.), no new snippet semantics.
- Phase 2: External source files — support at least one non-Swift language (e.g. C/C++) with whole-file or line-range inclusion.
- Phase 3: Slicing for non-Swift (e.g. named regions via comments or line ranges) and more languages.
Scope and open questions
- Paths: Resolve relative to catalog root, package root, or a configurable “content root”? How to handle packages with multiple catalogs?
- Slicing for non-Swift: Prefer a common convention (e.g. `// snippet: name` / `# snippet: name`) or language-specific rules? Or only line ranges in v1?
- Validation: Should DocC fail the build if a referenced external file is missing, or warn and leave a placeholder?
- SourceKit-LSP / IDE: For in-editor DocC preview (e.g. via sourcekit-lsp), how should “external” paths be resolved when the workspace might not have the same layout as the package root?
- Security / sandboxing: Any constraints on which paths can be referenced (e.g. only under package root)?
Possible next steps
1. Align on approach in this thread (e.g. Option A vs B vs C, and phased vs big-bang).
2. Spec / design doc: Document the chosen approach (schema, resolution rules, slicing, supported languages for v1).
3. Implement in swift-docc: External content loading, path resolution, and rendering as code listings or included markdown.
4. Slicing: Implement line-range or named-region slicing for at least one non-Swift language (e.g. C/C++).
5. Documentation and examples: How to reference README, how to add a C file as a “snippet,” and how SourceKit-LSP / tooling discovers external paths (if relevant).
6. SourceKit-LSP (if needed): If LSP’s DocC integration needs to resolve external paths for preview, add support there once the DocC contract is clear.
References
- DocC Snippets (current): see official DocC docs for how Swift snippets work today — for contrast with the proposed extension.
I’d appreciate feedback on which option (or combination) best fits the project’s goals, on phased vs non-phased rollout, and on any edge cases or existing workflows (e.g. multi-package, generated docs) that this should account for.
