Skip to content
Open
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
27 changes: 16 additions & 11 deletions EMBEDDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

The `embed-code` utility uses a custom `<embed-code>` tag to insert code snippets from source files into Markdown documentation.

For executable examples of the embedding features described here, see the
[embed-code showcase](examples/showcase/README.md). The showcase uses paired
instruction tags and dedicated source fixtures so it can double as a guide and
an opt-in end-to-end test.

## Embedding options

There are two ways to specify which code fragment to embed:
Expand Down Expand Up @@ -209,18 +214,18 @@ Not all languages distinguish documentation from regular comments or inline from

The table below lists the supported languages and supported `comments` modes for them:

| Language | Extensions | Supported `comments` modes |
|------------------------|---------------------------------------------------------|--------------------------------------------------------------|
| Java, Kotlin, Groovy | `.java`, `.kt`, `.kts`, `.groovy` | `all`, `none`, `documentation`, `regular`, `inline`, `block` |
| C# | `.cs` | `all`, `none`, `documentation`, `regular`, `inline`, `block` |
| Language | Extensions | Supported `comments` modes |
|------------------------|----------------------------------------------------------|--------------------------------------------------------------|
| Java, Kotlin, Groovy | `.java`, `.kt`, `.kts`, `.groovy` | `all`, `none`, `documentation`, `regular`, `inline`, `block` |
| C# | `.cs` | `all`, `none`, `documentation`, `regular`, `inline`, `block` |
| C, C++ | `.c`, `.h`, `.cc`, `.cpp`, `.cxx`, `.hh`, `.hpp`, `.hxx` | `all`, `none`, `inline`, `block` |
| JavaScript, TypeScript | `.js`, `.jsx`, `.ts`, `.tsx` | `all`, `none`, `documentation`, `regular`, `inline`, `block` |
| Go | `.go` | `all`, `none`, `inline`, `block` |
| Protobuf | `.proto` | `all`, `none`, `inline`, `block` |
| Python | `.py`, `.pyi`, `.pyw` | `all`, `none` |
| YAML | `.yml`, `.yaml` | `all`, `none` |
| XML, HTML | `.xml`, `.html`, `.htm` | `all`, `none` |
| Visual Basic | `.vb`, `.bas`, `.vbs`, `.vbscript` | `all`, `none`, `documentation`, `regular` |
| JavaScript, TypeScript | `.js`, `.jsx`, `.ts`, `.tsx` | `all`, `none`, `documentation`, `regular`, `inline`, `block` |
| Go | `.go` | `all`, `none`, `inline`, `block` |
| Protobuf | `.proto` | `all`, `none`, `inline`, `block` |
| Python | `.py`, `.pyi`, `.pyw` | `all`, `none` |
| YAML | `.yml`, `.yaml` | `all`, `none` |
| XML, HTML | `.xml`, `.html`, `.htm` | `all`, `none` |
| Visual Basic | `.vb`, `.bas`, `.vbs`, `.vbscript` | `all`, `none`, `documentation`, `regular` |

## Advanced use cases

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ This project is the implementation of `embed-code` utility written in Go.

For the details of the usage in the documentation and the code, please refer to the [EMBEDDING.md](EMBEDDING.md).

For a runnable guide with positive examples, negative examples, and YAML
configuration shapes, see the [embed-code showcase](examples/showcase/README.md).
The showcase is an opt-in end-to-end test and is not part of the normal

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed adding a note about showcases not being included in the general testing workflow, but it turns out this is already documented, so the comment is no longer particularly important.

That said, I still recommend running all showcases as part of the CI/CD pipeline.

`go test ./...` flow.

## Running

Embed Code operates in two modes:
Expand Down
42 changes: 42 additions & 0 deletions examples/showcase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Embed Code Showcase

This is an executable showcase guide to `embed-code-go` and the end-to-end tests.

## How To Use This Guide

Guide is divided on two categories:

1. [Configuration](configuration/README.md) - describes how to configure the whole embed-code application.
2. [Embedding](embedding/README.md) - describes how to work with the embedding instructions.

## How To Run Tests

Run commands from the repository root.

Run the opt-in end-to-end test with the `showcase` build tag:

```bash
go test -tags showcase ./examples/showcase
```

Verify the positive embedding examples:

```bash
go run ./main.go -mode=check -config-path=examples/showcase/embedding/embed-code.yml
```

Verify the configuration examples:

```bash
go run ./main.go -mode=check -config-path=examples/showcase/configuration/single-source.yml
go run ./main.go -mode=check -config-path=examples/showcase/configuration/named-sources.yml
go run ./main.go -mode=check -config-path=examples/showcase/configuration/include-exclude.yml
go run ./main.go -mode=check -config-path=examples/showcase/configuration/multiple-embeddings.yml
```

The negative examples are intentionally broken, so these commands should fail:

```bash
go run ./main.go -mode=check -config-path=examples/showcase/embedding/negative/processing-errors.yml
go run ./main.go -mode=check -config-path=examples/showcase/embedding/negative/stale.yml
```
14 changes: 14 additions & 0 deletions examples/showcase/code/java/org/showcase/CommentModes.java

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's delete examples package. Store all just in showcase.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.showcase;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add copyright.


/**
* Creates public greetings.
*/
public interface CommentModes {
/*
* Internal implementation note.
*/
String URL = "http://example.org/*not-comment*/";

// Regular inline comment.
String greet(String name); // trailing inline comment.
}
17 changes: 17 additions & 0 deletions examples/showcase/code/java/org/showcase/Greeting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.showcase;

// #docfragment "Greeter class"
public final class Greeting {
private Greeting() {}

// #docfragment "main()"
public static void main(String[] args) {
System.out.println(greeting("Ada"));
}
// #enddocfragment "main()"

public static String greeting(String name) {
return "Hello, " + name + "!";
}
}
// #enddocfragment "Greeter class"
23 changes: 23 additions & 0 deletions examples/showcase/code/java/org/showcase/MultiPartWorkflow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.showcase;

// #docfragment "Workflow"
public final class MultiPartWorkflow {
// #enddocfragment "Workflow"
private MultiPartWorkflow() {}

// #docfragment "Workflow"
public static void start() {
// #enddocfragment "Workflow"
System.out.println("Internal setup is hidden.");
// #docfragment "Workflow"
System.out.println("Start workflow");
}
// #enddocfragment "Workflow"

public static void finish() {
System.out.println("Finish workflow");
}

// #docfragment "Workflow"
}
// #enddocfragment "Workflow"
28 changes: 28 additions & 0 deletions examples/showcase/code/java/org/showcase/OverlappingFragments.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.showcase;

// #docfragment "Class wrapper", "Greeting method"
public final class OverlappingFragments {
// #enddocfragment "Class wrapper", "Greeting method"
private OverlappingFragments() {}

// #docfragment "Class wrapper"
public static void boot() {
// #enddocfragment "Class wrapper"
System.out.println("Boot details are hidden.");
// #docfragment "Class wrapper"
System.out.println("Boot complete");
}
// #enddocfragment "Class wrapper"

// #docfragment "Greeting method"
public static String greeting(String name) {
// #enddocfragment "Greeting method"
var normalized = name.trim();
// #docfragment "Greeting method"
return "Hello, " + normalized + "!";
}
// #enddocfragment "Greeting method"

// #docfragment "Class wrapper", "Greeting method"
}
// #enddocfragment "Class wrapper", "Greeting method"
22 changes: 22 additions & 0 deletions examples/showcase/code/java/org/showcase/PatternSamples.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.showcase;

class PatternSamples {

private static final String ESCAPED_NEWLINE = "\n";

@Scenario
@Name("adds two numbers")
void addsTwoNumbers() {
int total = 1 + 1;

assertEquals(2, total);
}

@Scenario
@Name("subtracts two numbers")
void subtractsTwoNumbers() {
int total = 2 - 1;

assertEquals(1, total);
}
}
11 changes: 11 additions & 0 deletions examples/showcase/code/kotlin/org/showcase/KotlinGreeting.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.showcase

object KotlinGreeting {

// #docfragment "main()"
@JvmStatic
fun main(args: Array<String>) {
println("Hello from Kotlin")
}
// #enddocfragment "main()"
}
5 changes: 5 additions & 0 deletions examples/showcase/code/text/glob-patterns.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
padded text
Use * to multiply
The total is $5
The value ends with $
^ starts with caret
121 changes: 121 additions & 0 deletions examples/showcase/configuration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Configuration Examples

This folder is a runnable guide to YAML configuration. Start with the smallest
working config, then add only the options your documentation needs.

## Minimal Config

A configuration needs one source root and one documentation root:

```yaml
code-path: examples/showcase/code/java
docs-path: examples/showcase/configuration/docs/single-source
```

This config is shown by [single-source.yml](single-source.yml).

The application scans files under `docs-path`, finds `<embed-code>` instructions,
and resolves each instruction's `file` path from `code-path`. For example, see
instruction in [docs/single-source/greeting.md](docs/single-source/greeting.md).

Relative paths in `code-path` and `docs-path` are resolved
from the command's current working directory.

Run this example (from the project root):

```bash
go run ./main.go -mode=check -config-path=examples/showcase/configuration/single-source.yml
```

## Add Document Selection

Add `doc-includes` when only some files under `docs-path` should be scanned.
Add `doc-excludes` when selected files should be skipped:

```yaml
code-path: examples/showcase/code/java
docs-path: examples/showcase/configuration/docs/include-exclude
doc-includes:
- "**/*.md"
doc-excludes:
- excluded.md
```

This shape is shown by [include-exclude.yml](include-exclude.yml). It processes
[docs/include-exclude/included.md](docs/include-exclude/included.md) and skips

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[docs/include-exclude/included.md](docs/include-exclude/included.md) and skips
[included.md](docs/include-exclude/included.md) and skips

And in all places.

[docs/include-exclude/excluded.md](docs/include-exclude/excluded.md).

Use include and exclude patterns to skip drafts, generated docs, deprecated
pages, or any file that should not be scanned for active instructions.

```bash
go run ./main.go -mode=check -config-path=examples/showcase/configuration/include-exclude.yml
```

## Add Named Source Roots

Use named source roots when one documentation tree embeds snippets from several
source trees:

```yaml
code-path:
- name: java
path: examples/showcase/code/java
- name: kotlin
path: examples/showcase/code/kotlin
- name: text
path: examples/showcase/code/text
docs-path: examples/showcase/configuration/docs/named-sources
```

This shape is shown by [named-sources.yml](named-sources.yml). Its docs live in
[docs/named-sources](docs/named-sources/).

Instructions choose a source root with the `$name` prefix:

```markdown
<embed-code file="$kotlin/org/showcase/KotlinGreeting.kt" fragment="main()"></embed-code>
```

Run the named-source example:

```bash
go run ./main.go -mode=check -config-path=examples/showcase/configuration/named-sources.yml
```

## Add Multiple Documentation Targets

Use `embeddings` when one command should process several independent
documentation targets. Each entry has its own `name`, `code-path`, `docs-path`,
and optional settings:

```yaml
embeddings:
- name: java-guide
code-path: examples/showcase/code/java
docs-path: examples/showcase/configuration/docs/multiple/java
- name: kotlin-guide
code-path:
- name: kotlin
path: examples/showcase/code/kotlin
docs-path: examples/showcase/configuration/docs/multiple/kotlin
```

This shape is shown by [multiple-embeddings.yml](multiple-embeddings.yml). It
processes [docs/multiple/java](docs/multiple/java/) and
[docs/multiple/kotlin](docs/multiple/kotlin/) in one run.

```bash
go run ./main.go -mode=check -config-path=examples/showcase/configuration/multiple-embeddings.yml
```

## All Configuration Checks

Run commands from the project root.

```bash
go run ./main.go -mode=check -config-path=examples/showcase/configuration/single-source.yml
go run ./main.go -mode=check -config-path=examples/showcase/configuration/named-sources.yml
go run ./main.go -mode=check -config-path=examples/showcase/configuration/include-exclude.yml
go run ./main.go -mode=check -config-path=examples/showcase/configuration/multiple-embeddings.yml
```
14 changes: 14 additions & 0 deletions examples/showcase/configuration/docs/include-exclude/excluded.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Excluded Document

The config excludes this file. The intentionally missing source file proves
that excluded documents are not processed.

## How It Works

[../../include-exclude.yml](../../include-exclude.yml) lists this file in
`doc-excludes`. The instruction points at a missing source file, but the command
still succeeds because excluded files are skipped before instruction parsing.

<embed-code file="org/showcase/DoesNotExist.java"></embed-code>
```java
```
18 changes: 18 additions & 0 deletions examples/showcase/configuration/docs/include-exclude/included.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Included Document

The `doc-includes` pattern selects this Markdown file, so the instruction is
processed normally.

## How It Works

[../../include-exclude.yml](../../include-exclude.yml) includes Markdown files
under this docs root. Because this file is not listed in `doc-excludes`, check
mode resolves the instruction and compares the rendered fence with the Java
source fragment.

<embed-code file="org/showcase/Greeting.java" fragment="main()"></embed-code>
```java
public static void main(String[] args) {
System.out.println(greeting("Ada"));
}
```
17 changes: 17 additions & 0 deletions examples/showcase/configuration/docs/multiple/java/greeting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Java Embedding Entry

This document is processed by the `java-guide` entry in an `embeddings` config.

## How It Works

[../../../multiple-embeddings.yml](../../../multiple-embeddings.yml) contains a
`java-guide` entry with its own `code-path` and `docs-path`. This document lives
under that entry's docs root, so the unprefixed source path resolves against the
Java source tree.

<embed-code file="org/showcase/Greeting.java" fragment="main()"></embed-code>
```java
public static void main(String[] args) {
System.out.println(greeting("Ada"));
}
```
Loading
Loading