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.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +23 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +278 -0
  5. data/ROADMAP.md +80 -0
  6. data/docs/_md_composer_architecture.md +50 -0
  7. data/docs/_md_composer_cheatsheet.md +72 -0
  8. data/docs/_md_composer_concepts.md +64 -0
  9. data/docs/_md_composer_dev_guide.md +55 -0
  10. data/docs/_md_composer_getting_started.md +114 -0
  11. data/docs/_md_composer_readme.md +93 -0
  12. data/docs/_md_composer_user_guide.md +65 -0
  13. data/docs/ai/md_composer_ai_audit.md +35 -0
  14. data/docs/ai/md_composer_ai_canonical_docs.md +44 -0
  15. data/docs/ai/md_composer_ai_source_map.md +39 -0
  16. data/docs/compose/md_composer_compose_actions.md +338 -0
  17. data/docs/compose/md_composer_compose_anatomy.md +156 -0
  18. data/docs/compose/md_composer_compose_buffer.md +81 -0
  19. data/docs/compose/md_composer_compose_examples.md +31 -0
  20. data/docs/compose/md_composer_compose_include.md +136 -0
  21. data/docs/compose/md_composer_compose_select.md +198 -0
  22. data/docs/compose/md_composer_compose_sources.md +161 -0
  23. data/docs/compose/md_composer_compose_targets.md +194 -0
  24. data/docs/examples/md_composer_example_basic_compose.md +57 -0
  25. data/docs/examples/md_composer_example_buffer_target_actions.md +83 -0
  26. data/docs/examples/md_composer_example_fixtures.md +62 -0
  27. data/docs/examples/md_composer_example_html_output.md +50 -0
  28. data/docs/examples/md_composer_example_modify.md +77 -0
  29. data/docs/examples/md_composer_example_multi_row_compose.md +67 -0
  30. data/docs/examples/md_composer_example_ruby_plans.md +62 -0
  31. data/docs/examples/md_composer_example_structured_data.md +68 -0
  32. data/docs/examples/md_composer_example_transforms.md +68 -0
  33. data/docs/examples/md_composer_example_yaml_json_rows.md +56 -0
  34. data/docs/examples/md_composer_examples_readme.md +45 -0
  35. data/docs/examples/md_composer_runnable_examples.md +374 -0
  36. data/docs/examples/md_composer_source_ruby_dsl.md +88 -0
  37. data/docs/reference/md_composer_nested.md +170 -0
  38. data/docs/reference/md_composer_reference_api.md +71 -0
  39. data/docs/reference/md_composer_reference_capabilities.md +63 -0
  40. data/docs/reference/md_composer_reference_diagnostics.md +54 -0
  41. data/docs/reference/md_composer_reference_plan_schema.md +75 -0
  42. data/docs/reference/md_composer_reference_registries.md +63 -0
  43. data/docs/reference/md_composer_take.md +221 -0
  44. data/docs/reference/md_composer_unit_tokens.md +228 -0
  45. data/docs/reference/md_composer_where.md +227 -0
  46. data/docs/transform/md_composer_transform_anatomy.md +112 -0
  47. data/docs/transform/md_composer_transform_examples.md +30 -0
  48. data/docs/transform/md_composer_transform_modes.md +83 -0
  49. data/docs/transform/md_composer_transform_options.md +142 -0
  50. data/docs/transform/md_composer_transform_scope.md +97 -0
  51. data/docs/transform/md_composer_transform_transforms.md +99 -0
  52. data/examples/README.md +20 -0
  53. data/examples/advanced_composer.rb +207 -0
  54. data/examples/basic_compose.rb +24 -0
  55. data/examples/complex_composer.rb +235 -0
  56. data/examples/example_support.rb +18 -0
  57. data/examples/fixtures/current.md +179 -0
  58. data/examples/fixtures/faq.md +58 -0
  59. data/examples/fixtures/guide.md +62 -0
  60. data/examples/fixtures/site_intro.md +29 -0
  61. data/examples/fixtures/source.html +22 -0
  62. data/examples/html_input.rb +26 -0
  63. data/examples/output/advanced_composer.md +76 -0
  64. data/examples/output/basic_compose.md +25 -0
  65. data/examples/output/complex_composer.md +85 -0
  66. data/examples/output/html_input.md +4 -0
  67. data/examples/output/source_list_dsl.md +126 -0
  68. data/examples/output/standard_composer.md +46 -0
  69. data/examples/output/standard_sources_buffer.md +31 -0
  70. data/examples/output/yaml_plan.md +43 -0
  71. data/examples/plans/basic.yml +20 -0
  72. data/examples/source_list_dsl.rb +41 -0
  73. data/examples/standard_composer.rb +42 -0
  74. data/examples/standard_sources_buffer.rb +62 -0
  75. data/examples/yaml_plan.rb +17 -0
  76. data/lib/markdown_composer/capabilities.rb +223 -0
  77. data/lib/markdown_composer/composition_buffer.rb +378 -0
  78. data/lib/markdown_composer/data_path.rb +313 -0
  79. data/lib/markdown_composer/diagnostics.rb +63 -0
  80. data/lib/markdown_composer/document_index/html_parser.rb +84 -0
  81. data/lib/markdown_composer/document_index/markdown_parser.rb +338 -0
  82. data/lib/markdown_composer/document_index.rb +94 -0
  83. data/lib/markdown_composer/executor.rb +284 -0
  84. data/lib/markdown_composer/markdown_renderer.rb +105 -0
  85. data/lib/markdown_composer/plan.rb +436 -0
  86. data/lib/markdown_composer/plan_builder.rb +111 -0
  87. data/lib/markdown_composer/registries/action_entries.rb +26 -0
  88. data/lib/markdown_composer/registries/condition_entries.rb +58 -0
  89. data/lib/markdown_composer/registries/registry.rb +69 -0
  90. data/lib/markdown_composer/registries/source_entries.rb +18 -0
  91. data/lib/markdown_composer/registries/support_values.rb +23 -0
  92. data/lib/markdown_composer/registries/take_entries.rb +31 -0
  93. data/lib/markdown_composer/registries/take_registry.rb +18 -0
  94. data/lib/markdown_composer/registries/target_entries.rb +40 -0
  95. data/lib/markdown_composer/registries/unit_token_entries.rb +62 -0
  96. data/lib/markdown_composer/registries/where_registry.rb +84 -0
  97. data/lib/markdown_composer/registries.rb +46 -0
  98. data/lib/markdown_composer/result.rb +34 -0
  99. data/lib/markdown_composer/selection_resolver.rb +181 -0
  100. data/lib/markdown_composer/source.rb +57 -0
  101. data/lib/markdown_composer/source_list_builder.rb +47 -0
  102. data/lib/markdown_composer/take.rb +129 -0
  103. data/lib/markdown_composer/transform_options.rb +66 -0
  104. data/lib/markdown_composer/transform_runner/content_placement.rb +63 -0
  105. data/lib/markdown_composer/transform_runner/field_interpolator.rb +213 -0
  106. data/lib/markdown_composer/transform_runner/heading_numbering.rb +106 -0
  107. data/lib/markdown_composer/transform_runner/scope_resolver.rb +87 -0
  108. data/lib/markdown_composer/transform_runner.rb +264 -0
  109. data/lib/markdown_composer/transforms/default_entries.rb +31 -0
  110. data/lib/markdown_composer/transforms/registry.rb +11 -0
  111. data/lib/markdown_composer/validator.rb +378 -0
  112. data/lib/markdown_composer/value_object.rb +15 -0
  113. data/lib/markdown_composer/version.rb +5 -0
  114. data/lib/markdown_composer/where.rb +313 -0
  115. data/lib/markdown_composer.rb +114 -0
  116. 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,4 @@
1
+ ## Overview
2
+
3
+ This overview comes from HTML input and includes [a product link](/features/dashboard).
4
+ Markdown Composer converts HTML through a best-effort Markdown path.
@@ -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)