markdown_composer 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +23 -0
- data/LICENSE.txt +21 -0
- data/README.md +278 -0
- data/ROADMAP.md +80 -0
- data/docs/_md_composer_architecture.md +50 -0
- data/docs/_md_composer_cheatsheet.md +72 -0
- data/docs/_md_composer_concepts.md +64 -0
- data/docs/_md_composer_dev_guide.md +55 -0
- data/docs/_md_composer_getting_started.md +114 -0
- data/docs/_md_composer_readme.md +93 -0
- data/docs/_md_composer_user_guide.md +65 -0
- data/docs/ai/md_composer_ai_audit.md +35 -0
- data/docs/ai/md_composer_ai_canonical_docs.md +44 -0
- data/docs/ai/md_composer_ai_source_map.md +39 -0
- data/docs/compose/md_composer_compose_actions.md +338 -0
- data/docs/compose/md_composer_compose_anatomy.md +156 -0
- data/docs/compose/md_composer_compose_buffer.md +81 -0
- data/docs/compose/md_composer_compose_examples.md +31 -0
- data/docs/compose/md_composer_compose_include.md +136 -0
- data/docs/compose/md_composer_compose_select.md +198 -0
- data/docs/compose/md_composer_compose_sources.md +161 -0
- data/docs/compose/md_composer_compose_targets.md +194 -0
- data/docs/examples/md_composer_example_basic_compose.md +57 -0
- data/docs/examples/md_composer_example_buffer_target_actions.md +83 -0
- data/docs/examples/md_composer_example_fixtures.md +62 -0
- data/docs/examples/md_composer_example_html_output.md +50 -0
- data/docs/examples/md_composer_example_modify.md +77 -0
- data/docs/examples/md_composer_example_multi_row_compose.md +67 -0
- data/docs/examples/md_composer_example_ruby_plans.md +62 -0
- data/docs/examples/md_composer_example_structured_data.md +68 -0
- data/docs/examples/md_composer_example_transforms.md +68 -0
- data/docs/examples/md_composer_example_yaml_json_rows.md +56 -0
- data/docs/examples/md_composer_examples_readme.md +45 -0
- data/docs/examples/md_composer_runnable_examples.md +374 -0
- data/docs/examples/md_composer_source_ruby_dsl.md +88 -0
- data/docs/reference/md_composer_nested.md +170 -0
- data/docs/reference/md_composer_reference_api.md +71 -0
- data/docs/reference/md_composer_reference_capabilities.md +63 -0
- data/docs/reference/md_composer_reference_diagnostics.md +54 -0
- data/docs/reference/md_composer_reference_plan_schema.md +75 -0
- data/docs/reference/md_composer_reference_registries.md +63 -0
- data/docs/reference/md_composer_take.md +221 -0
- data/docs/reference/md_composer_unit_tokens.md +228 -0
- data/docs/reference/md_composer_where.md +227 -0
- data/docs/transform/md_composer_transform_anatomy.md +112 -0
- data/docs/transform/md_composer_transform_examples.md +30 -0
- data/docs/transform/md_composer_transform_modes.md +83 -0
- data/docs/transform/md_composer_transform_options.md +142 -0
- data/docs/transform/md_composer_transform_scope.md +97 -0
- data/docs/transform/md_composer_transform_transforms.md +99 -0
- data/examples/README.md +20 -0
- data/examples/advanced_composer.rb +207 -0
- data/examples/basic_compose.rb +24 -0
- data/examples/complex_composer.rb +235 -0
- data/examples/example_support.rb +18 -0
- data/examples/fixtures/current.md +179 -0
- data/examples/fixtures/faq.md +58 -0
- data/examples/fixtures/guide.md +62 -0
- data/examples/fixtures/site_intro.md +29 -0
- data/examples/fixtures/source.html +22 -0
- data/examples/html_input.rb +26 -0
- data/examples/output/advanced_composer.md +76 -0
- data/examples/output/basic_compose.md +25 -0
- data/examples/output/complex_composer.md +85 -0
- data/examples/output/html_input.md +4 -0
- data/examples/output/source_list_dsl.md +126 -0
- data/examples/output/standard_composer.md +46 -0
- data/examples/output/standard_sources_buffer.md +31 -0
- data/examples/output/yaml_plan.md +43 -0
- data/examples/plans/basic.yml +20 -0
- data/examples/source_list_dsl.rb +41 -0
- data/examples/standard_composer.rb +42 -0
- data/examples/standard_sources_buffer.rb +62 -0
- data/examples/yaml_plan.rb +17 -0
- data/lib/markdown_composer/capabilities.rb +223 -0
- data/lib/markdown_composer/composition_buffer.rb +378 -0
- data/lib/markdown_composer/data_path.rb +313 -0
- data/lib/markdown_composer/diagnostics.rb +63 -0
- data/lib/markdown_composer/document_index/html_parser.rb +84 -0
- data/lib/markdown_composer/document_index/markdown_parser.rb +338 -0
- data/lib/markdown_composer/document_index.rb +94 -0
- data/lib/markdown_composer/executor.rb +284 -0
- data/lib/markdown_composer/markdown_renderer.rb +105 -0
- data/lib/markdown_composer/plan.rb +436 -0
- data/lib/markdown_composer/plan_builder.rb +111 -0
- data/lib/markdown_composer/registries/action_entries.rb +26 -0
- data/lib/markdown_composer/registries/condition_entries.rb +58 -0
- data/lib/markdown_composer/registries/registry.rb +69 -0
- data/lib/markdown_composer/registries/source_entries.rb +18 -0
- data/lib/markdown_composer/registries/support_values.rb +23 -0
- data/lib/markdown_composer/registries/take_entries.rb +31 -0
- data/lib/markdown_composer/registries/take_registry.rb +18 -0
- data/lib/markdown_composer/registries/target_entries.rb +40 -0
- data/lib/markdown_composer/registries/unit_token_entries.rb +62 -0
- data/lib/markdown_composer/registries/where_registry.rb +84 -0
- data/lib/markdown_composer/registries.rb +46 -0
- data/lib/markdown_composer/result.rb +34 -0
- data/lib/markdown_composer/selection_resolver.rb +181 -0
- data/lib/markdown_composer/source.rb +57 -0
- data/lib/markdown_composer/source_list_builder.rb +47 -0
- data/lib/markdown_composer/take.rb +129 -0
- data/lib/markdown_composer/transform_options.rb +66 -0
- data/lib/markdown_composer/transform_runner/content_placement.rb +63 -0
- data/lib/markdown_composer/transform_runner/field_interpolator.rb +213 -0
- data/lib/markdown_composer/transform_runner/heading_numbering.rb +106 -0
- data/lib/markdown_composer/transform_runner/scope_resolver.rb +87 -0
- data/lib/markdown_composer/transform_runner.rb +264 -0
- data/lib/markdown_composer/transforms/default_entries.rb +31 -0
- data/lib/markdown_composer/transforms/registry.rb +11 -0
- data/lib/markdown_composer/validator.rb +378 -0
- data/lib/markdown_composer/value_object.rb +15 -0
- data/lib/markdown_composer/version.rb +5 -0
- data/lib/markdown_composer/where.rb +313 -0
- data/lib/markdown_composer.rb +114 -0
- metadata +260 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Markdown Composer Examples
|
|
3
|
+
type: examples
|
|
4
|
+
status: current
|
|
5
|
+
updated: 2026-06-07
|
|
6
|
+
description: Public index of Markdown Composer examples by task.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Markdown Composer Examples
|
|
10
|
+
|
|
11
|
+
### References
|
|
12
|
+
|
|
13
|
+
| What | Where |
|
|
14
|
+
|------|-------|
|
|
15
|
+
| Getting started | [../_md_composer_getting_started.md](../_md_composer_getting_started.md) |
|
|
16
|
+
| Compose anatomy | [../compose/md_composer_compose_anatomy.md](../compose/md_composer_compose_anatomy.md) |
|
|
17
|
+
| Transform anatomy | [../transform/md_composer_transform_anatomy.md](../transform/md_composer_transform_anatomy.md) |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1. How To Use Examples
|
|
22
|
+
|
|
23
|
+
Use the runnable examples first when you want copy-paste Ruby. They read shared fixtures from `examples/fixtures/` and write output to `examples/output/`.
|
|
24
|
+
|
|
25
|
+
For task-focused learning, use the individual examples below. Each task page shows the source shape, plan/config shape, expected output, and notes.
|
|
26
|
+
|
|
27
|
+
| What | Where |
|
|
28
|
+
|------|-------|
|
|
29
|
+
| Runnable Ruby scripts | [Runnable examples](./md_composer_runnable_examples.md) |
|
|
30
|
+
| Shared fixture map | [Example fixtures](./md_composer_example_fixtures.md) |
|
|
31
|
+
|
|
32
|
+
## 2. Example Index
|
|
33
|
+
|
|
34
|
+
| Task | Example |
|
|
35
|
+
|------|---------|
|
|
36
|
+
| Select one section | [Basic compose](./md_composer_example_basic_compose.md) |
|
|
37
|
+
| Define sources with Ruby DSL | [Source Ruby DSL](./md_composer_source_ruby_dsl.md) |
|
|
38
|
+
| Build output from several rows | [Multi-row compose](./md_composer_example_multi_row_compose.md) |
|
|
39
|
+
| Transform selected source content | [Modify](./md_composer_example_modify.md) |
|
|
40
|
+
| Remove or transform existing buffer content | [Buffer target actions](./md_composer_example_buffer_target_actions.md) |
|
|
41
|
+
| Run top-level transforms | [Transforms](./md_composer_example_transforms.md) |
|
|
42
|
+
| Extract YAML/JSON values | [Structured data](./md_composer_example_structured_data.md) |
|
|
43
|
+
| Render HTML output | [HTML output](./md_composer_example_html_output.md) |
|
|
44
|
+
| Author Ruby DSL plans | [Ruby plans](./md_composer_example_ruby_plans.md) |
|
|
45
|
+
| Import/export YAML, JSON, and rows | [YAML, JSON, and rows](./md_composer_example_yaml_json_rows.md) |
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Markdown Composer Runnable Examples
|
|
3
|
+
type: examples
|
|
4
|
+
status: current
|
|
5
|
+
updated: 2026-06-07
|
|
6
|
+
description: Copy-paste guide to the runnable Ruby examples shipped with Markdown Composer.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Markdown Composer Runnable Examples
|
|
10
|
+
|
|
11
|
+
### References
|
|
12
|
+
|
|
13
|
+
| What | Where |
|
|
14
|
+
|------|-------|
|
|
15
|
+
| Fixture map | [./md_composer_example_fixtures.md](./md_composer_example_fixtures.md) |
|
|
16
|
+
| Source Ruby DSL | [./md_composer_source_ruby_dsl.md](./md_composer_source_ruby_dsl.md) |
|
|
17
|
+
| Examples index | [./md_composer_examples_readme.md](./md_composer_examples_readme.md) |
|
|
18
|
+
| API reference | [../reference/md_composer_reference_api.md](../reference/md_composer_reference_api.md) |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 1. How To Run
|
|
23
|
+
|
|
24
|
+
Run examples from the gem root:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
ruby -Ilib examples/basic_compose.rb
|
|
28
|
+
ruby -Ilib examples/source_list_dsl.rb
|
|
29
|
+
ruby -Ilib examples/yaml_plan.rb
|
|
30
|
+
ruby -Ilib examples/html_input.rb
|
|
31
|
+
ruby -Ilib examples/standard_composer.rb
|
|
32
|
+
ruby -Ilib examples/standard_sources_buffer.rb
|
|
33
|
+
ruby -Ilib examples/advanced_composer.rb
|
|
34
|
+
ruby -Ilib examples/complex_composer.rb
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Each script prints Markdown and writes the same result to `examples/output/*.md`.
|
|
38
|
+
|
|
39
|
+
## 2. Runnable Example Index
|
|
40
|
+
|
|
41
|
+
| Script | What it shows | Fixtures | Output |
|
|
42
|
+
|--------|---------------|----------|--------|
|
|
43
|
+
| [basic_compose.rb](../../examples/basic_compose.rb) | Select one H2 section from the current source. | [current.md](../../examples/fixtures/current.md) | [basic_compose.md](../../examples/output/basic_compose.md) |
|
|
44
|
+
| [source_list_dsl.rb](../../examples/source_list_dsl.rb) | Build sources with `MarkdownComposer.source_list` and compose current, explicit, and inherited inputs. | [current.md](../../examples/fixtures/current.md), [guide.md](../../examples/fixtures/guide.md), [faq.md](../../examples/fixtures/faq.md), [site_intro.md](../../examples/fixtures/site_intro.md) | [source_list_dsl.md](../../examples/output/source_list_dsl.md) |
|
|
45
|
+
| [yaml_plan.rb](../../examples/yaml_plan.rb) | Load a YAML plan from `examples/plans/basic.yml`. | [current.md](../../examples/fixtures/current.md), [guide.md](../../examples/fixtures/guide.md) | [yaml_plan.md](../../examples/output/yaml_plan.md) |
|
|
46
|
+
| [html_input.rb](../../examples/html_input.rb) | Compose from HTML input through the best-effort HTML path. | [source.html](../../examples/fixtures/source.html) | [html_input.md](../../examples/output/html_input.md) |
|
|
47
|
+
| [standard_composer.rb](../../examples/standard_composer.rb) | Select one H2 section, promote heading levels, and insert a generated Summary section. | [current.md](../../examples/fixtures/current.md) | [standard_composer.md](../../examples/output/standard_composer.md) |
|
|
48
|
+
| [standard_sources_buffer.rb](../../examples/standard_sources_buffer.rb) | Use current, explicit, previous, and buffer sources with heading rename/number transforms. | [current.md](../../examples/fixtures/current.md), [guide.md](../../examples/fixtures/guide.md) | [standard_sources_buffer.md](../../examples/output/standard_sources_buffer.md) |
|
|
49
|
+
| [advanced_composer.rb](../../examples/advanced_composer.rb) | Demonstrate all source types, all compose actions, nested modify transforms, and final output transforms. | [current.md](../../examples/fixtures/current.md), [guide.md](../../examples/fixtures/guide.md), [site_intro.md](../../examples/fixtures/site_intro.md) | [advanced_composer.md](../../examples/output/advanced_composer.md) |
|
|
50
|
+
| [complex_composer.rb](../../examples/complex_composer.rb) | Broader copy-paste walkthrough with all source types, all actions, multiple explicit sources, and final transforms. | [current.md](../../examples/fixtures/current.md), [guide.md](../../examples/fixtures/guide.md), [faq.md](../../examples/fixtures/faq.md), [site_intro.md](../../examples/fixtures/site_intro.md) | [complex_composer.md](../../examples/output/complex_composer.md) |
|
|
51
|
+
|
|
52
|
+
### 2.1 Basic Compose
|
|
53
|
+
|
|
54
|
+
[basic_compose.rb](../../examples/basic_compose.rb) is the smallest runnable compose example. It reads one Markdown fixture, selects the first H2 section from that source, and writes the selected section unchanged to [basic_compose.md](../../examples/output/basic_compose.md).
|
|
55
|
+
|
|
56
|
+
Run it from the gem root:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
ruby -Ilib examples/basic_compose.rb
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
#### Sources
|
|
63
|
+
|
|
64
|
+
| Key | Type | File | Purpose |
|
|
65
|
+
|-----|------|------|---------|
|
|
66
|
+
| `current` | `current` | [current.md](../../examples/fixtures/current.md) | Main Markdown source. The example selects the first `##` section, which is `Overview`. |
|
|
67
|
+
|
|
68
|
+
This example intentionally uses the raw source hash shape:
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
sources: [
|
|
72
|
+
{ key: "current", type: "current", markdown: current_markdown }
|
|
73
|
+
]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
That is equivalent in purpose to a single-source `MarkdownComposer.source_list`, but keeps the most basic example close to the underlying `compose` contract.
|
|
77
|
+
|
|
78
|
+
#### Composer Rows
|
|
79
|
+
|
|
80
|
+
| Step | [Source](../compose/md_composer_compose_sources.md) | [Select](../compose/md_composer_compose_select.md) | [Include](../compose/md_composer_compose_include.md) | [Action](../compose/md_composer_compose_actions.md) | What it does |
|
|
81
|
+
|------|--------|--------|---------|--------|--------------|
|
|
82
|
+
| 1 | [`current`](../compose/md_composer_compose_sources.md#4-current-source) | [`h2_section`](../compose/md_composer_compose_select.md#3-section-versus-node-tokens)[`[first:1]`](../reference/md_composer_take.md#4-common-take-forms) | `all` | [`set`](../compose/md_composer_compose_actions.md#41-set) | Reads the first H2 section from `current.md`, keeps the heading and full section body, and replaces the output buffer with that selected content. |
|
|
83
|
+
|
|
84
|
+
#### Output Shape
|
|
85
|
+
|
|
86
|
+
The output starts with:
|
|
87
|
+
|
|
88
|
+
```markdown
|
|
89
|
+
## Overview
|
|
90
|
+
|
|
91
|
+
This overview section is the normal starting point for Markdown Composer examples.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 2.2 Source List DSL
|
|
95
|
+
|
|
96
|
+
[source_list_dsl.rb](../../examples/source_list_dsl.rb) demonstrates the Ruby `MarkdownComposer.source_list` helper with current, explicit, and inherited runtime sources. It composes sections from multiple files, then prepends inherited site content.
|
|
97
|
+
|
|
98
|
+
Run it from the gem root:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
ruby -Ilib examples/source_list_dsl.rb
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### Sources
|
|
105
|
+
|
|
106
|
+
| Key | Type | File | Purpose |
|
|
107
|
+
|-----|------|------|---------|
|
|
108
|
+
| `current` | `current` | [current.md](../../examples/fixtures/current.md) | Main source. Supplies the first H2 section, `Overview`. |
|
|
109
|
+
| `guide` | `explicit` | [guide.md](../../examples/fixtures/guide.md) | Explicit source selected by key. Supplies install/configure/validate/publish sections. |
|
|
110
|
+
| `faq` | `explicit` | [faq.md](../../examples/fixtures/faq.md) | Explicit source selected by key. Supplies FAQ headings and first paragraphs. |
|
|
111
|
+
| `site_intro` | `inherited` | [site_intro.md](../../examples/fixtures/site_intro.md) | Inherited source selected by key. Prepended to the composed output. |
|
|
112
|
+
|
|
113
|
+
#### Composer Rows
|
|
114
|
+
|
|
115
|
+
| Step | [Source](../compose/md_composer_compose_sources.md) | [Select](../compose/md_composer_compose_select.md) | [Include](../compose/md_composer_compose_include.md) | [Action](../compose/md_composer_compose_actions.md) | What it does |
|
|
116
|
+
|------|--------|--------|---------|--------|--------------|
|
|
117
|
+
| 1 | [`current`](../compose/md_composer_compose_sources.md#4-current-source) | [`h2_section`](../compose/md_composer_compose_select.md#3-section-versus-node-tokens)[`[first:1]`](../reference/md_composer_take.md#4-common-take-forms) | `all` | [`set`](../compose/md_composer_compose_actions.md#41-set) | Starts the buffer with the first current-source H2 section. |
|
|
118
|
+
| 2 | [`explicit`](../compose/md_composer_compose_sources.md#5-explicit-source) `guide` | `h2_section` | `all` | [`append`](../compose/md_composer_compose_actions.md#42-append) | Appends all guide H2 sections. |
|
|
119
|
+
| 3 | [`explicit`](../compose/md_composer_compose_sources.md#5-explicit-source) `faq` | `h2_section` | `heading_title`, `paragraph[first:1]` | [`append`](../compose/md_composer_compose_actions.md#42-append) | Appends each FAQ H2 heading and its first paragraph. |
|
|
120
|
+
| 4 | [`inherited`](../compose/md_composer_compose_sources.md#3-source-tokens) `site_intro` | `h2_section` | `all` | [`prepend`](../compose/md_composer_compose_actions.md#43-prepend) | Prepends inherited site-introduction sections before the current and explicit content. |
|
|
121
|
+
|
|
122
|
+
#### Output Shape
|
|
123
|
+
|
|
124
|
+
The output starts with inherited `## Welcome` content, then includes `## Overview`, guide sections, and FAQ heading/paragraph summaries.
|
|
125
|
+
|
|
126
|
+
### 2.3 YAML Plan
|
|
127
|
+
|
|
128
|
+
[yaml_plan.rb](../../examples/yaml_plan.rb) shows the same compose model loaded from [basic.yml](../../examples/plans/basic.yml) instead of the Ruby plan DSL. Sources are still provided at runtime through `MarkdownComposer.source_list`.
|
|
129
|
+
|
|
130
|
+
Run it from the gem root:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
ruby -Ilib examples/yaml_plan.rb
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Sources
|
|
137
|
+
|
|
138
|
+
| Key | Type | File | Purpose |
|
|
139
|
+
|-----|------|------|---------|
|
|
140
|
+
| `current` | `current` | [current.md](../../examples/fixtures/current.md) | Supplies the first H2 section, `Overview`. |
|
|
141
|
+
| `guide` | `explicit` | [guide.md](../../examples/fixtures/guide.md) | Supplies the first guide H2 section, `Install`. |
|
|
142
|
+
|
|
143
|
+
#### Composer Rows
|
|
144
|
+
|
|
145
|
+
| Step | [Source](../compose/md_composer_compose_sources.md) | [Select](../compose/md_composer_compose_select.md) | [Include](../compose/md_composer_compose_include.md) | [Action](../compose/md_composer_compose_actions.md) | What it does |
|
|
146
|
+
|------|--------|--------|---------|--------|--------------|
|
|
147
|
+
| 1 | [`current`](../compose/md_composer_compose_sources.md#4-current-source) | `h2_section[first:1]` | `all` | [`set`](../compose/md_composer_compose_actions.md#41-set) | Starts the output with `Overview` from `current.md`. |
|
|
148
|
+
| 2 | [`explicit`](../compose/md_composer_compose_sources.md#5-explicit-source) `guide` | `h2_section[first:1]` | `all` | [`append`](../compose/md_composer_compose_actions.md#42-append) | Appends `Install` from `guide.md`. |
|
|
149
|
+
|
|
150
|
+
#### Transform Rows
|
|
151
|
+
|
|
152
|
+
| Step | [Scope](../transform/md_composer_transform_scope.md) | [Transform](../transform/md_composer_transform_transforms.md) | [Mode](../transform/md_composer_transform_modes.md) | Options | What it does |
|
|
153
|
+
|------|--------|-----------|------|---------|--------------|
|
|
154
|
+
| 1 | `output` | `heading_numbers` | `rebuild` | `levels: h2`, `start: 1` | Rebuilds H2 numbering so the selected sections become `## 1. Overview` and `## 2. Install`. |
|
|
155
|
+
|
|
156
|
+
#### Output Shape
|
|
157
|
+
|
|
158
|
+
The output contains numbered H2 sections from two sources: `## 1. Overview` followed by `## 2. Install`.
|
|
159
|
+
|
|
160
|
+
### 2.4 HTML Input
|
|
161
|
+
|
|
162
|
+
[html_input.rb](../../examples/html_input.rb) reads HTML instead of Markdown and emits Markdown output. It demonstrates the gem's best-effort HTML-to-Markdown input path.
|
|
163
|
+
|
|
164
|
+
Run it from the gem root:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
ruby -Ilib examples/html_input.rb
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### Sources
|
|
171
|
+
|
|
172
|
+
| Key | Type | File | Purpose |
|
|
173
|
+
|-----|------|------|---------|
|
|
174
|
+
| `current` | `current` with `html` | [source.html](../../examples/fixtures/source.html) | HTML source converted through Composer before selection. |
|
|
175
|
+
|
|
176
|
+
#### Composer Rows
|
|
177
|
+
|
|
178
|
+
| Step | [Source](../compose/md_composer_compose_sources.md) | [Select](../compose/md_composer_compose_select.md) | [Include](../compose/md_composer_compose_include.md) | [Action](../compose/md_composer_compose_actions.md) | What it does |
|
|
179
|
+
|------|--------|--------|---------|--------|--------------|
|
|
180
|
+
| 1 | [`current`](../compose/md_composer_compose_sources.md#4-current-source) | `h2_section[first:1]` | `all` | [`set`](../compose/md_composer_compose_actions.md#41-set) | Selects the first H2 section from the converted HTML source and makes it the output. |
|
|
181
|
+
|
|
182
|
+
#### Output Shape
|
|
183
|
+
|
|
184
|
+
The output is Markdown, starting with `## Overview` and the converted HTML paragraph/link content.
|
|
185
|
+
|
|
186
|
+
### 2.5 Standard Composer
|
|
187
|
+
|
|
188
|
+
[standard_composer.rb](../../examples/standard_composer.rb) selects one focused H2 section, keeps selected child content, renames the H2, promotes heading levels, and inserts a generated `## Summary` section with a transform.
|
|
189
|
+
|
|
190
|
+
Run it from the gem root:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
ruby -Ilib examples/standard_composer.rb
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### Sources
|
|
197
|
+
|
|
198
|
+
| Key | Type | File | Purpose |
|
|
199
|
+
|-----|------|------|---------|
|
|
200
|
+
| `current` | `current` | [current.md](../../examples/fixtures/current.md) | Supplies `Feature Matrix` and its first two H3 child sections. |
|
|
201
|
+
|
|
202
|
+
#### Composer Rows
|
|
203
|
+
|
|
204
|
+
| Step | [Source](../compose/md_composer_compose_sources.md) | [Select](../compose/md_composer_compose_select.md) | [Include](../compose/md_composer_compose_include.md) | [Action](../compose/md_composer_compose_actions.md) | What it does |
|
|
205
|
+
|------|--------|--------|---------|--------|--------------|
|
|
206
|
+
| 1 | [`current`](../compose/md_composer_compose_sources.md#4-current-source) | `h2_section where title:equals("Feature Matrix")` | `heading_title`, `paragraph[first:1]`, `link[first:1]`, `table[first:1]`, first two H3 sections with paragraph/code/table content | [`append`](../compose/md_composer_compose_actions.md#42-append) | Builds a focused feature-matrix slice from the current source. |
|
|
207
|
+
|
|
208
|
+
#### Transform Rows
|
|
209
|
+
|
|
210
|
+
| Step | [Scope](../transform/md_composer_transform_scope.md) | [Transform](../transform/md_composer_transform_transforms.md) | [Mode](../transform/md_composer_transform_modes.md) | Options | What it does |
|
|
211
|
+
|------|--------|-----------|------|---------|--------------|
|
|
212
|
+
| 1 | `heading_2` | `replace_text` | `literal` | `Feature Matrix` to `Feature Matrix Summary` | Renames the selected H2 heading. |
|
|
213
|
+
| 2 | `heading` | `heading_levels` | `promote` | `by: 1` | Promotes `##` to `#` and `###` to `##`. |
|
|
214
|
+
| 3 | `paragraph[first:1]` | `insert_after` | `insert` | raw Markdown `## Summary` plus paragraph | Inserts a generated Summary section after the lead paragraph. |
|
|
215
|
+
|
|
216
|
+
#### Output Shape
|
|
217
|
+
|
|
218
|
+
The output starts with `# Feature Matrix Summary`, then a generated `## Summary`, followed by selected table and child-section content.
|
|
219
|
+
|
|
220
|
+
### 2.6 Standard Sources Buffer
|
|
221
|
+
|
|
222
|
+
[standard_sources_buffer.rb](../../examples/standard_sources_buffer.rb) demonstrates current, explicit, previous, and buffer sources. It composes a document title and operations section, appends guide content, reuses the previous explicit source, removes a buffer section, then renames and numbers headings.
|
|
223
|
+
|
|
224
|
+
Run it from the gem root:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
ruby -Ilib examples/standard_sources_buffer.rb
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### Sources
|
|
231
|
+
|
|
232
|
+
| Key | Type | File | Purpose |
|
|
233
|
+
|-----|------|------|---------|
|
|
234
|
+
| `current` | `current` | [current.md](../../examples/fixtures/current.md) | Supplies the H1 title/intro and `Operations` content. |
|
|
235
|
+
| `guide` | `explicit` | [guide.md](../../examples/fixtures/guide.md) | Supplies `Install` and `Validate` sections. |
|
|
236
|
+
|
|
237
|
+
#### Composer Rows
|
|
238
|
+
|
|
239
|
+
| Step | [Source](../compose/md_composer_compose_sources.md) | [Select](../compose/md_composer_compose_select.md) | [Include](../compose/md_composer_compose_include.md) | [Action](../compose/md_composer_compose_actions.md) | What it does |
|
|
240
|
+
|------|--------|--------|---------|--------|--------------|
|
|
241
|
+
| 1 | [`current`](../compose/md_composer_compose_sources.md#4-current-source) | `heading_1_section[first:1]` | `heading_title`, `paragraph[first:1]` | [`set`](../compose/md_composer_compose_actions.md#41-set) | Starts with the document H1 and its first paragraph. |
|
|
242
|
+
| 2 | [`current`](../compose/md_composer_compose_sources.md#4-current-source) | `h2_section where title:equals("Operations")` | heading, first paragraph, and first H3 subsection with paragraph/code | [`append`](../compose/md_composer_compose_actions.md#42-append) | Appends a focused operations runbook section. |
|
|
243
|
+
| 3 | [`explicit`](../compose/md_composer_compose_sources.md#5-explicit-source) `guide` | `h2_section where title:equals("Install")` | `all` | [`append`](../compose/md_composer_compose_actions.md#42-append) | Appends guide install content. |
|
|
244
|
+
| 4 | [`previous`](../compose/md_composer_compose_sources.md#6-previous-source) | `h2_section where title:equals("Validate")` | `all` | [`append`](../compose/md_composer_compose_actions.md#42-append) | Reuses the previous explicit guide source to append validation content. |
|
|
245
|
+
| 5 | [`buffer`](../compose/md_composer_compose_sources.md#7-buffer-source) | `h2_section where title:equals("Install")` | `all` | [`remove_buffer_target`](../compose/md_composer_compose_actions.md#412-remove-buffer-target) | Removes the already-composed Install section from the buffer. |
|
|
246
|
+
|
|
247
|
+
#### Transform Rows
|
|
248
|
+
|
|
249
|
+
| Step | [Scope](../transform/md_composer_transform_scope.md) | [Transform](../transform/md_composer_transform_transforms.md) | [Mode](../transform/md_composer_transform_modes.md) | Options | What it does |
|
|
250
|
+
|------|--------|-----------|------|---------|--------------|
|
|
251
|
+
| 1 | `heading_2` | `replace_text` | `literal` | `Operations` to `Standard Operations` | Renames the operations H2. |
|
|
252
|
+
| 2 | `heading_3` | `replace_text` | `literal` | `Deployment` to `Release Steps` | Renames the selected H3. |
|
|
253
|
+
| 3 | `output` | `heading_numbers` | `rebuild` | `levels: h2,h3`, `start: 1` | Rebuilds H2/H3 numbering after composition. |
|
|
254
|
+
|
|
255
|
+
#### Output Shape
|
|
256
|
+
|
|
257
|
+
The output starts with `# Product Knowledge Base`, then numbered `Standard Operations` and `Validate` sections.
|
|
258
|
+
|
|
259
|
+
### 2.7 Advanced Composer
|
|
260
|
+
|
|
261
|
+
[advanced_composer.rb](../../examples/advanced_composer.rb) is a broad but readable DSL example. It uses runtime `current`, `explicit`, and `inherited` sources plus row-level `inline`, `previous`, and `buffer` sources. It demonstrates every compose action and several transform families.
|
|
262
|
+
|
|
263
|
+
Run it from the gem root:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
ruby -Ilib examples/advanced_composer.rb
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### Sources
|
|
270
|
+
|
|
271
|
+
| Key | Type | File | Purpose |
|
|
272
|
+
|-----|------|------|---------|
|
|
273
|
+
| `current` | `current` | [current.md](../../examples/fixtures/current.md) | Supplies feature, reporting, monitoring, and dashboard content. |
|
|
274
|
+
| `guide` | `explicit` | [guide.md](../../examples/fixtures/guide.md) | Supplies validation and publishing sections. |
|
|
275
|
+
| `site_intro` | `inherited` | [site_intro.md](../../examples/fixtures/site_intro.md) | Supplies inherited Welcome content. |
|
|
276
|
+
|
|
277
|
+
#### Composer Rows
|
|
278
|
+
|
|
279
|
+
| Step | [Source](../compose/md_composer_compose_sources.md) | [Action](../compose/md_composer_compose_actions.md) | What it does |
|
|
280
|
+
|------|--------|--------|--------------|
|
|
281
|
+
| 1 | `current` | [`set`](../compose/md_composer_compose_actions.md#41-set) | Starts with a focused `Feature Matrix` slice. |
|
|
282
|
+
| 2 | `inline` | [`prepend`](../compose/md_composer_compose_actions.md#43-prepend) | Adds an Advanced Preface at the start. |
|
|
283
|
+
| 3 | `inherited site_intro` | [`append`](../compose/md_composer_compose_actions.md#42-append) | Appends inherited Welcome content. |
|
|
284
|
+
| 4 | `buffer target` | [`transform_buffer_target`](../compose/md_composer_compose_actions.md#413-transform-buffer-target) | Demotes Welcome while it is already in the buffer. |
|
|
285
|
+
| 5 | `explicit guide` | [`append`](../compose/md_composer_compose_actions.md#42-append) | Appends Validate content. |
|
|
286
|
+
| 6 | `previous` | [`append`](../compose/md_composer_compose_actions.md#42-append) | Reuses the guide source to append Publish content. |
|
|
287
|
+
| 7-8 | `buffer target` | [`transform_buffer_target`](../compose/md_composer_compose_actions.md#413-transform-buffer-target) | Demotes and renames Validate and Publish headings. |
|
|
288
|
+
| 9 | `inline` | [`insert_before`](../compose/md_composer_compose_actions.md#44-insert-before) | Inserts Release Note before Automation. |
|
|
289
|
+
| 10 | `current` | [`replace`](../compose/md_composer_compose_actions.md#47-replace) | Replaces Automation with Reporting. |
|
|
290
|
+
| 11 | `inline` | [`insert_between`](../compose/md_composer_compose_actions.md#46-insert-between) | Inserts Support Note between Release Note and Reporting. |
|
|
291
|
+
| 12 | `current` | [`insert_after`](../compose/md_composer_compose_actions.md#45-insert-after) | Inserts Monitoring after Reporting. |
|
|
292
|
+
| 13 | `buffer` | [`copy`](../compose/md_composer_compose_actions.md#48-copy) | Copies Release Note to the end; final dedupe removes the duplicate. |
|
|
293
|
+
| 14 | `buffer` | [`modify`](../compose/md_composer_compose_actions.md#410-modify) | Modifies Dashboard in place, renaming it and inserting a paragraph. |
|
|
294
|
+
| 15 | `buffer` | [`move`](../compose/md_composer_compose_actions.md#49-move) | Moves Advanced Preface into the body. |
|
|
295
|
+
| 16-17 | `inline`, then `buffer` | [`remove_buffer_target`](../compose/md_composer_compose_actions.md#412-remove-buffer-target) | Adds and removes a temporary cleanup marker. |
|
|
296
|
+
|
|
297
|
+
#### Transform Rows
|
|
298
|
+
|
|
299
|
+
| Step | [Transform](../transform/md_composer_transform_transforms.md) | What it does |
|
|
300
|
+
|------|-----------|--------------|
|
|
301
|
+
| 1 | `dedupe` | Removes duplicate composed content by normalized text. |
|
|
302
|
+
| 2 | `replace_text` | Renames `Feature Matrix` to `Advanced Composer Walkthrough`. |
|
|
303
|
+
| 3 | `links` | Rewrites the first dashboard link to an absolute example URL. |
|
|
304
|
+
| 4 | `heading_levels` | Promotes headings for the final output shape. |
|
|
305
|
+
|
|
306
|
+
#### Output Shape
|
|
307
|
+
|
|
308
|
+
The output starts with `# Advanced Composer Walkthrough`, then contains Dashboard Snapshot, Release Note, Support Note, Reporting, Monitoring, Welcome, Validation Snapshot, Release Checklist, and Advanced Preface sections.
|
|
309
|
+
|
|
310
|
+
### 2.8 Complex Composer
|
|
311
|
+
|
|
312
|
+
[complex_composer.rb](../../examples/complex_composer.rb) is the most comprehensive copy-paste walkthrough. It keeps sources inside `result = MarkdownComposer.compose(...)`, uses multiple explicit sources, demonstrates every source type and action, and adds a final generated Summary section.
|
|
313
|
+
|
|
314
|
+
Run it from the gem root:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
ruby -Ilib examples/complex_composer.rb
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Sources
|
|
321
|
+
|
|
322
|
+
| Key | Type | File | Purpose |
|
|
323
|
+
|-----|------|------|---------|
|
|
324
|
+
| `current` | `current` | [current.md](../../examples/fixtures/current.md) | Supplies feature, reporting, monitoring, and dashboard content. |
|
|
325
|
+
| `guide` | `explicit` | [guide.md](../../examples/fixtures/guide.md) | Supplies validation and publishing sections. |
|
|
326
|
+
| `faq` | `explicit` | [faq.md](../../examples/fixtures/faq.md) | Supplies Source Type Notes. |
|
|
327
|
+
| `site_intro` | `inherited` | [site_intro.md](../../examples/fixtures/site_intro.md) | Supplies inherited Welcome content. |
|
|
328
|
+
|
|
329
|
+
#### Composer Rows
|
|
330
|
+
|
|
331
|
+
| Step | [Source](../compose/md_composer_compose_sources.md) | [Action](../compose/md_composer_compose_actions.md) | What it does |
|
|
332
|
+
|------|--------|--------|--------------|
|
|
333
|
+
| 1 | `current` | [`set`](../compose/md_composer_compose_actions.md#41-set) | Starts with a focused `Feature Matrix` slice. |
|
|
334
|
+
| 2 | `inline` | [`prepend`](../compose/md_composer_compose_actions.md#43-prepend) | Adds Complex Preface before other content. |
|
|
335
|
+
| 3-4 | `inherited`, then `buffer target` | [`append`](../compose/md_composer_compose_actions.md#42-append), [`transform_buffer_target`](../compose/md_composer_compose_actions.md#413-transform-buffer-target) | Appends and demotes Welcome. |
|
|
336
|
+
| 5-8 | `explicit guide`, `previous`, then buffer targets | [`append`](../compose/md_composer_compose_actions.md#42-append), [`transform_buffer_target`](../compose/md_composer_compose_actions.md#413-transform-buffer-target) | Appends Validate and Publish, then demotes/renames them. |
|
|
337
|
+
| 9-10 | `explicit faq`, then buffer target | [`append`](../compose/md_composer_compose_actions.md#42-append), [`transform_buffer_target`](../compose/md_composer_compose_actions.md#413-transform-buffer-target) | Adds Source Type Notes from FAQ content. |
|
|
338
|
+
| 11-12 | `inline` | [`insert_before`](../compose/md_composer_compose_actions.md#44-insert-before), [`insert_between`](../compose/md_composer_compose_actions.md#46-insert-between) | Adds Release Note and Support Note around existing child sections. |
|
|
339
|
+
| 13-14 | `current` | [`replace`](../compose/md_composer_compose_actions.md#47-replace), [`insert_after`](../compose/md_composer_compose_actions.md#45-insert-after) | Replaces Automation with Reporting and inserts Monitoring after it. |
|
|
340
|
+
| 15 | `buffer` | [`copy`](../compose/md_composer_compose_actions.md#48-copy) | Copies Release Note; final dedupe removes the duplicate. |
|
|
341
|
+
| 16 | `buffer` | [`modify`](../compose/md_composer_compose_actions.md#410-modify) | Renames Dashboard to Dashboard Snapshot and inserts an explanatory paragraph. |
|
|
342
|
+
| 17 | `buffer` | [`move`](../compose/md_composer_compose_actions.md#49-move) | Moves Complex Preface into final reading order. |
|
|
343
|
+
| 18-19 | `inline`, then `buffer` | [`append`](../compose/md_composer_compose_actions.md#42-append), [`remove_buffer_target`](../compose/md_composer_compose_actions.md#412-remove-buffer-target) | Adds and removes a Cleanup Marker. |
|
|
344
|
+
|
|
345
|
+
#### Transform Rows
|
|
346
|
+
|
|
347
|
+
| Step | [Transform](../transform/md_composer_transform_transforms.md) | What it does |
|
|
348
|
+
|------|-----------|--------------|
|
|
349
|
+
| 1 | `dedupe` | Removes copied duplicate content by normalized text. |
|
|
350
|
+
| 2 | `replace_text` | Renames `Feature Matrix` to `Complex Composer Walkthrough`. |
|
|
351
|
+
| 3 | `links` | Rewrites the first dashboard link to an absolute example URL. |
|
|
352
|
+
| 4 | `heading_levels` | Promotes headings for final output. |
|
|
353
|
+
| 5 | `insert_after` | Inserts a generated `## Summary` section after the lead paragraph. |
|
|
354
|
+
|
|
355
|
+
#### Output Shape
|
|
356
|
+
|
|
357
|
+
The output starts with `# Complex Composer Walkthrough`, includes a generated `## Summary`, then shows composed current, inherited, guide, FAQ, inline, and buffer-modified content.
|
|
358
|
+
|
|
359
|
+
## 3. Copy-Paste Pattern
|
|
360
|
+
|
|
361
|
+
Use `File.read` to load fixture Markdown, then pass sources into `MarkdownComposer.compose`:
|
|
362
|
+
|
|
363
|
+
```ruby
|
|
364
|
+
root = File.expand_path("../../examples", __dir__)
|
|
365
|
+
|
|
366
|
+
sources = MarkdownComposer.source_list do
|
|
367
|
+
current File.read(File.join(root, "fixtures/current.md"))
|
|
368
|
+
explicit :guide, File.read(File.join(root, "fixtures/guide.md"))
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
result = MarkdownComposer.compose(sources: sources, plan: plan)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Runtime sources belong in `sources:`. Plan-only sources such as `inline`, `previous`, and `buffer` stay in compose rows.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Markdown Composer Source Ruby DSL Example
|
|
3
|
+
type: examples
|
|
4
|
+
status: current
|
|
5
|
+
updated: 2026-06-07
|
|
6
|
+
description: Example for defining Markdown Composer runtime sources with the Ruby source_list DSL.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Markdown Composer Source Ruby DSL Example
|
|
10
|
+
|
|
11
|
+
### References
|
|
12
|
+
|
|
13
|
+
| What | Where |
|
|
14
|
+
|------|-------|
|
|
15
|
+
| Source guide | [../compose/md_composer_compose_sources.md](../compose/md_composer_compose_sources.md) |
|
|
16
|
+
| Fixture map | [./md_composer_example_fixtures.md](./md_composer_example_fixtures.md) |
|
|
17
|
+
| Runnable examples | [./md_composer_runnable_examples.md](./md_composer_runnable_examples.md) |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1. Goal
|
|
22
|
+
|
|
23
|
+
Define readable runtime sources in Ruby without hand-writing array-of-hash source records.
|
|
24
|
+
|
|
25
|
+
## 2. Source List DSL
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
sources = MarkdownComposer.source_list do
|
|
29
|
+
current File.read("examples/fixtures/current.md")
|
|
30
|
+
explicit :guide, File.read("examples/fixtures/guide.md")
|
|
31
|
+
explicit :faq, File.read("examples/fixtures/faq.md")
|
|
32
|
+
inherited :site_intro, File.read("examples/fixtures/site_intro.md")
|
|
33
|
+
end
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This returns the same source shape accepted by `MarkdownComposer.compose`.
|
|
37
|
+
|
|
38
|
+
## 3. Use The Sources In A Plan
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
plan = MarkdownComposer.plan do
|
|
42
|
+
from :current
|
|
43
|
+
select 'h2_section where title:equals("Overview")'
|
|
44
|
+
include "all"
|
|
45
|
+
set
|
|
46
|
+
|
|
47
|
+
from({ type: "explicit", key: "guide" })
|
|
48
|
+
select 'h2_section where title:equals("Validate")'
|
|
49
|
+
include "all"
|
|
50
|
+
append
|
|
51
|
+
|
|
52
|
+
from({ type: "inherited", key: "site_intro" })
|
|
53
|
+
select 'h2_section where title:equals("Welcome")'
|
|
54
|
+
include "heading_title"
|
|
55
|
+
include "paragraph[first:1]"
|
|
56
|
+
prepend
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
result = MarkdownComposer.compose(sources: sources, plan: plan)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 4. Key Matching
|
|
63
|
+
|
|
64
|
+
The key in a source definition is the key used by the plan:
|
|
65
|
+
|
|
66
|
+
| Source definition | Plan reference |
|
|
67
|
+
|-------------------|----------------|
|
|
68
|
+
| `explicit :guide, ...` | `from({ type: "explicit", key: "guide" })` |
|
|
69
|
+
| `explicit :faq, ...` | `from({ type: "explicit", key: "faq" })` |
|
|
70
|
+
| `inherited :site_intro, ...` | `from({ type: "inherited", key: "site_intro" })` |
|
|
71
|
+
|
|
72
|
+
`current` defaults to key `"current"`. If a plan has more than one current source, use keyed source references instead of ambiguous `from :current`.
|
|
73
|
+
|
|
74
|
+
## 5. What Does Not Go In `source_list`
|
|
75
|
+
|
|
76
|
+
`previous`, `buffer`, and `inline` are plan-row source references, not runtime source records:
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
from :previous
|
|
80
|
+
from :buffer
|
|
81
|
+
from({ type: "inline", markdown: "## Note\n\nInline body." })
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Runnable examples using this pattern:
|
|
85
|
+
|
|
86
|
+
- [../../examples/source_list_dsl.rb](../../examples/source_list_dsl.rb)
|
|
87
|
+
- [../../examples/advanced_composer.rb](../../examples/advanced_composer.rb)
|
|
88
|
+
- [../../examples/complex_composer.rb](../../examples/complex_composer.rb)
|