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,58 @@
|
|
|
1
|
+
# FAQ
|
|
2
|
+
|
|
3
|
+
This FAQ is another `explicit` source.
|
|
4
|
+
|
|
5
|
+
## Can I use this outside Rails?
|
|
6
|
+
|
|
7
|
+
Yes. Markdown Composer is a headless Ruby gem and works in plain Ruby scripts.
|
|
8
|
+
|
|
9
|
+
### Plain Ruby Example
|
|
10
|
+
|
|
11
|
+
This minimal script shape is enough for a standalone Ruby project.
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
require "markdown_composer"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
You provide Markdown or HTML directly through the `sources:` keyword.
|
|
18
|
+
|
|
19
|
+
## Can plans be YAML?
|
|
20
|
+
|
|
21
|
+
Yes. Use `MarkdownComposer.parse_yaml` to load a YAML plan.
|
|
22
|
+
|
|
23
|
+
### YAML Shape
|
|
24
|
+
|
|
25
|
+
The YAML shape mirrors the Ruby plan rows used in the examples.
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
output: markdown
|
|
29
|
+
compose:
|
|
30
|
+
- source: current
|
|
31
|
+
select: h2_section[first:1]
|
|
32
|
+
include: all
|
|
33
|
+
action: set
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## What source types exist?
|
|
37
|
+
|
|
38
|
+
Runtime sources are passed to `compose`, while plan sources are row-level references.
|
|
39
|
+
|
|
40
|
+
| Source | Runtime or Plan | Notes |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| current | runtime | Main source |
|
|
43
|
+
| explicit | runtime | Keyed source |
|
|
44
|
+
| inherited | runtime | Host-resolved source |
|
|
45
|
+
| previous | plan | Reuses previous row source |
|
|
46
|
+
| buffer | plan | Reads composed output |
|
|
47
|
+
| inline | plan | Embeds small content |
|
|
48
|
+
|
|
49
|
+
## Can I transform output?
|
|
50
|
+
|
|
51
|
+
Yes. Add a transform section to the plan.
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
transform "output", "heading_numbers", "rebuild", {
|
|
55
|
+
"levels" => ["h2"],
|
|
56
|
+
"start" => 1
|
|
57
|
+
}
|
|
58
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Installation Guide
|
|
2
|
+
|
|
3
|
+
This guide is an `explicit` source selected by key.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Add the gem to your Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem "markdown_composer"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then run `bundle install`.
|
|
14
|
+
|
|
15
|
+
### Standalone Script
|
|
16
|
+
|
|
17
|
+
For a standalone Ruby script, install the gem directly:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
gem install markdown_composer
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Configure
|
|
24
|
+
|
|
25
|
+
Pass plain Markdown or HTML sources into `MarkdownComposer.compose`.
|
|
26
|
+
|
|
27
|
+
### Source List DSL
|
|
28
|
+
|
|
29
|
+
The source list DSL returns the same source hashes accepted by `compose`.
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
sources = MarkdownComposer.source_list do
|
|
33
|
+
current File.read("source_current.md")
|
|
34
|
+
explicit :guide, File.read("guide.md")
|
|
35
|
+
end
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Key Matching
|
|
39
|
+
|
|
40
|
+
The key in `explicit :guide` matches `from({ type: "explicit", key: "guide" })` in a plan.
|
|
41
|
+
|
|
42
|
+
## Validate
|
|
43
|
+
|
|
44
|
+
Validate a plan before running it when user input is involved.
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
validation = MarkdownComposer.validate(config: config, sources: sources)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
| Field | Purpose |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| valid | Boolean success flag |
|
|
53
|
+
| errors | Blocking diagnostics |
|
|
54
|
+
| diagnostics | Warnings and details |
|
|
55
|
+
|
|
56
|
+
## Publish
|
|
57
|
+
|
|
58
|
+
Build the gem package locally before release:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
gem build markdown_composer.gemspec
|
|
62
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Site Introduction
|
|
2
|
+
|
|
3
|
+
This file acts like a host-resolved `inherited` source.
|
|
4
|
+
|
|
5
|
+
## Welcome
|
|
6
|
+
|
|
7
|
+
This inherited introduction can be prepended to composed output.
|
|
8
|
+
|
|
9
|
+
### Audience
|
|
10
|
+
|
|
11
|
+
Use inherited sources for defaults supplied by a host application, tenant, site, or workspace.
|
|
12
|
+
|
|
13
|
+
#### Tenant Context
|
|
14
|
+
|
|
15
|
+
The gem does not enforce tenant rules itself. The host application resolves and authorizes inherited content before calling Composer.
|
|
16
|
+
|
|
17
|
+
## Navigation
|
|
18
|
+
|
|
19
|
+
Navigation content demonstrates inherited tables in composed output.
|
|
20
|
+
|
|
21
|
+
| Item | Path |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| Overview | /docs/overview |
|
|
24
|
+
| API | /docs/api |
|
|
25
|
+
| Support | /support |
|
|
26
|
+
|
|
27
|
+
### Footer Note
|
|
28
|
+
|
|
29
|
+
This section gives examples another nested H3 to select.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>HTML Source Example</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<article>
|
|
9
|
+
<h1>HTML Knowledge Base</h1>
|
|
10
|
+
<section>
|
|
11
|
+
<h2>Overview</h2>
|
|
12
|
+
<p>This overview comes from HTML input and includes <a href="/features/dashboard">a product link</a>.</p>
|
|
13
|
+
<p>Markdown Composer converts HTML through a best-effort Markdown path.</p>
|
|
14
|
+
</section>
|
|
15
|
+
<section>
|
|
16
|
+
<h2>Details</h2>
|
|
17
|
+
<p>This section is not selected by the basic HTML example.</p>
|
|
18
|
+
</section>
|
|
19
|
+
</article>
|
|
20
|
+
</body>
|
|
21
|
+
</html>
|
|
22
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "markdown_composer"
|
|
4
|
+
require_relative "example_support"
|
|
5
|
+
|
|
6
|
+
root = File.expand_path(__dir__)
|
|
7
|
+
html = File.read(File.join(root, "fixtures/source.html"))
|
|
8
|
+
|
|
9
|
+
# Read HTML input, convert it through Composer, and emit Markdown output.
|
|
10
|
+
plan = MarkdownComposer.plan do
|
|
11
|
+
output :markdown
|
|
12
|
+
|
|
13
|
+
from :current
|
|
14
|
+
select "h2_section[first:1]"
|
|
15
|
+
include "all"
|
|
16
|
+
set
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
result = MarkdownComposer.compose(
|
|
20
|
+
sources: [
|
|
21
|
+
{ key: "current", type: "current", html: html, preferred_format: :html }
|
|
22
|
+
],
|
|
23
|
+
plan: plan
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
ExampleSupport.write_output(root, "html_input", result)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Advanced Composer Walkthrough
|
|
2
|
+
|
|
3
|
+
The table below is intended for table selection and table-row experiments.
|
|
4
|
+
|
|
5
|
+
[Open](https://example.test/features/dashboard)
|
|
6
|
+
|
|
7
|
+
| Feature | Status | Owner | Link |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| Dashboard | ready | Product | [Open](/features/dashboard) |
|
|
10
|
+
| Automation | beta | Platform | [Open](/features/automation) |
|
|
11
|
+
| Reporting | draft | Data | [Open](/features/reporting) |
|
|
12
|
+
|
|
13
|
+
## Dashboard Snapshot
|
|
14
|
+
|
|
15
|
+
Dashboard Snapshot cards should keep this heading and paragraph when selected.
|
|
16
|
+
|
|
17
|
+
This paragraph was inserted by the modify action before final output transforms run.
|
|
18
|
+
|
|
19
|
+
| Card | Visible |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| Summary | yes |
|
|
22
|
+
| Activity | yes |
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
class DashboardCard
|
|
26
|
+
def visible?
|
|
27
|
+
status == "ready"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Release Note
|
|
33
|
+
|
|
34
|
+
This inserted note shows small inline Markdown inside a larger plan.
|
|
35
|
+
|
|
36
|
+
## Support Note
|
|
37
|
+
|
|
38
|
+
This note is inserted between two existing composed sections.
|
|
39
|
+
|
|
40
|
+
## Reporting
|
|
41
|
+
|
|
42
|
+
Reporting is marked draft so examples can filter it out by title or selected position.
|
|
43
|
+
|
|
44
|
+
## Monitoring
|
|
45
|
+
|
|
46
|
+
Monitor compose success rate, validation errors, and unexpected empty selections.
|
|
47
|
+
|
|
48
|
+
## Welcome
|
|
49
|
+
|
|
50
|
+
This inherited introduction can be prepended to composed output.
|
|
51
|
+
|
|
52
|
+
## Validation Snapshot
|
|
53
|
+
|
|
54
|
+
Validate a plan before running it when user input is involved.
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
validation = MarkdownComposer.validate(config: config, sources: sources)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
| Field | Purpose |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| valid | Boolean success flag |
|
|
63
|
+
| errors | Blocking diagnostics |
|
|
64
|
+
| diagnostics | Warnings and details |
|
|
65
|
+
|
|
66
|
+
## Release Checklist
|
|
67
|
+
|
|
68
|
+
Build the gem package locally before release:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
gem build markdown_composer.gemspec
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Advanced Preface
|
|
75
|
+
|
|
76
|
+
This section is prepended first, then moved into a better reading position.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
|
|
3
|
+
This overview section is the normal starting point for Markdown Composer examples.
|
|
4
|
+
|
|
5
|
+
It includes [a product link](/features/dashboard), inline code `composer.preview`, and a second paragraph so include rules can choose content.
|
|
6
|
+
|
|
7
|
+
### What Composer Should See
|
|
8
|
+
|
|
9
|
+
Composer should index nested sections under Overview and keep selected content in source order.
|
|
10
|
+
|
|
11
|
+
- The first bullet links to [getting started](/docs/getting-started).
|
|
12
|
+
- The second bullet mentions `source_list`.
|
|
13
|
+
- The third bullet is plain text for list-item selection.
|
|
14
|
+
|
|
15
|
+
#### Selector Notes
|
|
16
|
+
|
|
17
|
+
Use `h2_section[first:1]` to select the whole Overview section, including this H4.
|
|
18
|
+
|
|
19
|
+
Use `paragraph[first:1]` inside an include rule to keep only the first paragraph.
|
|
20
|
+
|
|
21
|
+
### What Composer Should Ignore
|
|
22
|
+
|
|
23
|
+
This H3 gives you a second nested section to filter by title or position.
|
|
24
|
+
|
|
25
|
+
> Blockquotes are useful for testing paragraph and block-level extraction.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Complex Composer Walkthrough
|
|
2
|
+
|
|
3
|
+
The table below is intended for table selection and table-row experiments.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Summary
|
|
7
|
+
|
|
8
|
+
This summary was inserted by a final transform after composition actions completed.
|
|
9
|
+
|
|
10
|
+
[Open](https://example.test/features/dashboard)
|
|
11
|
+
|
|
12
|
+
| Feature | Status | Owner | Link |
|
|
13
|
+
| --- | --- | --- | --- |
|
|
14
|
+
| Dashboard | ready | Product | [Open](/features/dashboard) |
|
|
15
|
+
| Automation | beta | Platform | [Open](/features/automation) |
|
|
16
|
+
| Reporting | draft | Data | [Open](/features/reporting) |
|
|
17
|
+
|
|
18
|
+
## Dashboard Snapshot
|
|
19
|
+
|
|
20
|
+
Dashboard Snapshot cards should keep this heading and paragraph when selected.
|
|
21
|
+
|
|
22
|
+
This paragraph was inserted by the modify action before final output transforms run.
|
|
23
|
+
|
|
24
|
+
| Card | Visible |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| Summary | yes |
|
|
27
|
+
| Activity | yes |
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
class DashboardCard
|
|
31
|
+
def visible?
|
|
32
|
+
status == "ready"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Release Note
|
|
38
|
+
|
|
39
|
+
This inserted note shows small inline Markdown inside a larger plan.
|
|
40
|
+
|
|
41
|
+
## Support Note
|
|
42
|
+
|
|
43
|
+
This note is inserted between two existing composed sections.
|
|
44
|
+
|
|
45
|
+
## Reporting
|
|
46
|
+
|
|
47
|
+
Reporting is marked draft so examples can filter it out by title or selected position.
|
|
48
|
+
|
|
49
|
+
## Monitoring
|
|
50
|
+
|
|
51
|
+
Monitor compose success rate, validation errors, and unexpected empty selections.
|
|
52
|
+
|
|
53
|
+
## Welcome
|
|
54
|
+
|
|
55
|
+
This inherited introduction can be prepended to composed output.
|
|
56
|
+
|
|
57
|
+
## Validation Snapshot
|
|
58
|
+
|
|
59
|
+
Validate a plan before running it when user input is involved.
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
validation = MarkdownComposer.validate(config: config, sources: sources)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
| Field | Purpose |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| valid | Boolean success flag |
|
|
68
|
+
| errors | Blocking diagnostics |
|
|
69
|
+
| diagnostics | Warnings and details |
|
|
70
|
+
|
|
71
|
+
## Release Checklist
|
|
72
|
+
|
|
73
|
+
Build the gem package locally before release:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
gem build markdown_composer.gemspec
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Source Type Notes
|
|
80
|
+
|
|
81
|
+
Runtime sources are passed to `compose`, while plan sources are row-level references.
|
|
82
|
+
|
|
83
|
+
## Complex Preface
|
|
84
|
+
|
|
85
|
+
This section is prepended first, then moved into the final reading order.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
## Welcome
|
|
2
|
+
|
|
3
|
+
This inherited introduction can be prepended to composed output.
|
|
4
|
+
|
|
5
|
+
### Audience
|
|
6
|
+
|
|
7
|
+
Use inherited sources for defaults supplied by a host application, tenant, site, or workspace.
|
|
8
|
+
|
|
9
|
+
#### Tenant Context
|
|
10
|
+
|
|
11
|
+
The gem does not enforce tenant rules itself. The host application resolves and authorizes inherited content before calling Composer.
|
|
12
|
+
|
|
13
|
+
## Navigation
|
|
14
|
+
|
|
15
|
+
Navigation content demonstrates inherited tables in composed output.
|
|
16
|
+
|
|
17
|
+
| Item | Path |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| Overview | /docs/overview |
|
|
20
|
+
| API | /docs/api |
|
|
21
|
+
| Support | /support |
|
|
22
|
+
|
|
23
|
+
### Footer Note
|
|
24
|
+
|
|
25
|
+
This section gives examples another nested H3 to select.
|
|
26
|
+
|
|
27
|
+
## Overview
|
|
28
|
+
|
|
29
|
+
This overview section is the normal starting point for Markdown Composer examples.
|
|
30
|
+
|
|
31
|
+
It includes [a product link](/features/dashboard), inline code `composer.preview`, and a second paragraph so include rules can choose content.
|
|
32
|
+
|
|
33
|
+
### What Composer Should See
|
|
34
|
+
|
|
35
|
+
Composer should index nested sections under Overview and keep selected content in source order.
|
|
36
|
+
|
|
37
|
+
- The first bullet links to [getting started](/docs/getting-started).
|
|
38
|
+
- The second bullet mentions `source_list`.
|
|
39
|
+
- The third bullet is plain text for list-item selection.
|
|
40
|
+
|
|
41
|
+
#### Selector Notes
|
|
42
|
+
|
|
43
|
+
Use `h2_section[first:1]` to select the whole Overview section, including this H4.
|
|
44
|
+
|
|
45
|
+
Use `paragraph[first:1]` inside an include rule to keep only the first paragraph.
|
|
46
|
+
|
|
47
|
+
### What Composer Should Ignore
|
|
48
|
+
|
|
49
|
+
This H3 gives you a second nested section to filter by title or position.
|
|
50
|
+
|
|
51
|
+
> Blockquotes are useful for testing paragraph and block-level extraction.
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
Add the gem to your Gemfile:
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
gem "markdown_composer"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Then run `bundle install`.
|
|
62
|
+
|
|
63
|
+
### Standalone Script
|
|
64
|
+
|
|
65
|
+
For a standalone Ruby script, install the gem directly:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
gem install markdown_composer
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Configure
|
|
72
|
+
|
|
73
|
+
Pass plain Markdown or HTML sources into `MarkdownComposer.compose`.
|
|
74
|
+
|
|
75
|
+
### Source List DSL
|
|
76
|
+
|
|
77
|
+
The source list DSL returns the same source hashes accepted by `compose`.
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
sources = MarkdownComposer.source_list do
|
|
81
|
+
current File.read("source_current.md")
|
|
82
|
+
explicit :guide, File.read("guide.md")
|
|
83
|
+
end
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### Key Matching
|
|
87
|
+
|
|
88
|
+
The key in `explicit :guide` matches `from({ type: "explicit", key: "guide" })` in a plan.
|
|
89
|
+
|
|
90
|
+
## Validate
|
|
91
|
+
|
|
92
|
+
Validate a plan before running it when user input is involved.
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
validation = MarkdownComposer.validate(config: config, sources: sources)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
| Field | Purpose |
|
|
99
|
+
| --- | --- |
|
|
100
|
+
| valid | Boolean success flag |
|
|
101
|
+
| errors | Blocking diagnostics |
|
|
102
|
+
| diagnostics | Warnings and details |
|
|
103
|
+
|
|
104
|
+
## Publish
|
|
105
|
+
|
|
106
|
+
Build the gem package locally before release:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
gem build markdown_composer.gemspec
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Can I use this outside Rails?
|
|
113
|
+
|
|
114
|
+
Yes. Markdown Composer is a headless Ruby gem and works in plain Ruby scripts.
|
|
115
|
+
|
|
116
|
+
## Can plans be YAML?
|
|
117
|
+
|
|
118
|
+
Yes. Use `MarkdownComposer.parse_yaml` to load a YAML plan.
|
|
119
|
+
|
|
120
|
+
## What source types exist?
|
|
121
|
+
|
|
122
|
+
Runtime sources are passed to `compose`, while plan sources are row-level references.
|
|
123
|
+
|
|
124
|
+
## Can I transform output?
|
|
125
|
+
|
|
126
|
+
Yes. Add a transform section to the plan.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Feature Matrix Summary
|
|
2
|
+
|
|
3
|
+
The table below is intended for table selection and table-row experiments.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Summary
|
|
7
|
+
|
|
8
|
+
This generated summary highlights the selected feature table and the two focused child sections.
|
|
9
|
+
|
|
10
|
+
[Open](/features/dashboard)
|
|
11
|
+
|
|
12
|
+
| Feature | Status | Owner | Link |
|
|
13
|
+
| --- | --- | --- | --- |
|
|
14
|
+
| Dashboard | ready | Product | [Open](/features/dashboard) |
|
|
15
|
+
| Automation | beta | Platform | [Open](/features/automation) |
|
|
16
|
+
| Reporting | draft | Data | [Open](/features/reporting) |
|
|
17
|
+
|
|
18
|
+
## Dashboard
|
|
19
|
+
|
|
20
|
+
Dashboard cards should keep this heading and paragraph when selected.
|
|
21
|
+
|
|
22
|
+
| Card | Visible |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| Summary | yes |
|
|
25
|
+
| Activity | yes |
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
class DashboardCard
|
|
29
|
+
def visible?
|
|
30
|
+
status == "ready"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Automation
|
|
36
|
+
|
|
37
|
+
Automation has two paragraphs so examples can select first or last content.
|
|
38
|
+
|
|
39
|
+
| Trigger | Retry |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| webhook | yes |
|
|
42
|
+
| schedule | yes |
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
bundle exec ruby automation_rule.rb
|
|
46
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Product Knowledge Base
|
|
2
|
+
|
|
3
|
+
Welcome to the product knowledge base. This file is the main `current` source for runnable examples.
|
|
4
|
+
|
|
5
|
+
## 1.1 Standard Operations
|
|
6
|
+
|
|
7
|
+
Operations content gives the examples runbook-style Markdown.
|
|
8
|
+
|
|
9
|
+
### 1.1.1 Release Steps
|
|
10
|
+
|
|
11
|
+
Deployment notes keep release steps short, repeatable, and easy to audit.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bundle exec rake test
|
|
15
|
+
gem build markdown_composer.gemspec
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## 1.2 Validate
|
|
20
|
+
|
|
21
|
+
Validate a plan before running it when user input is involved.
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
validation = MarkdownComposer.validate(config: config, sources: sources)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
| Field | Purpose |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| valid | Boolean success flag |
|
|
30
|
+
| errors | Blocking diagnostics |
|
|
31
|
+
| diagnostics | Warnings and details |
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
## 1. Overview
|
|
2
|
+
|
|
3
|
+
This overview section is the normal starting point for Markdown Composer examples.
|
|
4
|
+
|
|
5
|
+
It includes [a product link](/features/dashboard), inline code `composer.preview`, and a second paragraph so include rules can choose content.
|
|
6
|
+
|
|
7
|
+
### What Composer Should See
|
|
8
|
+
|
|
9
|
+
Composer should index nested sections under Overview and keep selected content in source order.
|
|
10
|
+
|
|
11
|
+
- The first bullet links to [getting started](/docs/getting-started).
|
|
12
|
+
- The second bullet mentions `source_list`.
|
|
13
|
+
- The third bullet is plain text for list-item selection.
|
|
14
|
+
|
|
15
|
+
#### Selector Notes
|
|
16
|
+
|
|
17
|
+
Use `h2_section[first:1]` to select the whole Overview section, including this H4.
|
|
18
|
+
|
|
19
|
+
Use `paragraph[first:1]` inside an include rule to keep only the first paragraph.
|
|
20
|
+
|
|
21
|
+
### What Composer Should Ignore
|
|
22
|
+
|
|
23
|
+
This H3 gives you a second nested section to filter by title or position.
|
|
24
|
+
|
|
25
|
+
> Blockquotes are useful for testing paragraph and block-level extraction.
|
|
26
|
+
|
|
27
|
+
## 2. Install
|
|
28
|
+
|
|
29
|
+
Add the gem to your Gemfile:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
gem "markdown_composer"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then run `bundle install`.
|
|
36
|
+
|
|
37
|
+
### Standalone Script
|
|
38
|
+
|
|
39
|
+
For a standalone Ruby script, install the gem directly:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
gem install markdown_composer
|
|
43
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
output: markdown
|
|
2
|
+
compose:
|
|
3
|
+
- source: current
|
|
4
|
+
select: h2_section[first:1]
|
|
5
|
+
include: all
|
|
6
|
+
action: set
|
|
7
|
+
- source:
|
|
8
|
+
type: explicit
|
|
9
|
+
key: guide
|
|
10
|
+
select: h2_section[first:1]
|
|
11
|
+
include: all
|
|
12
|
+
action: append
|
|
13
|
+
transform:
|
|
14
|
+
- scope: output
|
|
15
|
+
transform: heading_numbers
|
|
16
|
+
mode: rebuild
|
|
17
|
+
options:
|
|
18
|
+
levels:
|
|
19
|
+
- h2
|
|
20
|
+
start: 1
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "markdown_composer"
|
|
4
|
+
require_relative "example_support"
|
|
5
|
+
|
|
6
|
+
root = File.expand_path(__dir__)
|
|
7
|
+
|
|
8
|
+
sources = MarkdownComposer.source_list do
|
|
9
|
+
current File.read(File.join(root, "fixtures/current.md"))
|
|
10
|
+
explicit :guide, File.read(File.join(root, "fixtures/guide.md"))
|
|
11
|
+
explicit :faq, File.read(File.join(root, "fixtures/faq.md"))
|
|
12
|
+
inherited :site_intro, File.read(File.join(root, "fixtures/site_intro.md"))
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Compose from current, explicit, and inherited sources using the source_list DSL.
|
|
16
|
+
plan = MarkdownComposer.plan do
|
|
17
|
+
from :current
|
|
18
|
+
select "h2_section[first:1]"
|
|
19
|
+
include "all"
|
|
20
|
+
set
|
|
21
|
+
|
|
22
|
+
from({ type: "explicit", key: "guide" })
|
|
23
|
+
select "h2_section"
|
|
24
|
+
include "all"
|
|
25
|
+
append
|
|
26
|
+
|
|
27
|
+
from({ type: "explicit", key: "faq" })
|
|
28
|
+
select "h2_section"
|
|
29
|
+
include "heading_title"
|
|
30
|
+
include "paragraph[first:1]"
|
|
31
|
+
append
|
|
32
|
+
|
|
33
|
+
from({ type: "inherited", key: "site_intro" })
|
|
34
|
+
select "h2_section"
|
|
35
|
+
include "all"
|
|
36
|
+
prepend
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
result = MarkdownComposer.compose(sources: sources, plan: plan)
|
|
40
|
+
|
|
41
|
+
ExampleSupport.write_output(root, "source_list_dsl", result)
|