Module: Esp::DocsGenerator
- Defined in:
- lib/esp/docs_generator.rb
Overview
Renders the data from Esp::Introspection into markdown files under docs/reference/. Each file is split into two regions: an ‘esp:auto` block (regenerated by `esp docs build`, enforced fresh by lefthook so it can’t drift) and a hand-written tail below it that survives rebuilds. write_doc rewrites only the auto block and preserves the tail verbatim, so an unchanged source reproduces the file byte-for-byte — that idempotence is what lets the freshness hook keep diffing the whole file.
The marker literal kept the ‘mw:auto` token for one release so existing generated files migrate cleanly: manual_tail accepts both the new `esp:auto` marker and the legacy `mw:auto` one. After the next regen, every file carries the new marker and the fallback is dead code.
Constant Summary collapse
- AUTO_OPEN =
'<!-- esp:auto — regenerated by `esp docs build`; edits here are overwritten -->'.freeze
- AUTO_CLOSE =
'<!-- /esp:auto — write durable docs below this line; they survive rebuilds -->'.freeze
- LEGACY_AUTO_CLOSE =
'<!-- /mw:auto — write durable docs below this line; they survive rebuilds -->'.freeze
Class Method Summary collapse
- .build(output_dir:) ⇒ Object
- .render_api_index(modules) ⇒ Object
- .render_commands ⇒ Object
- .render_module(mod) ⇒ Object
-
.write_doc(path, body) ⇒ Object
Write the regenerated auto block, then re-attach the file’s existing hand-written tail (everything after AUTO_CLOSE) verbatim — or scaffold one if the file is new.
Class Method Details
.build(output_dir:) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/esp/docs_generator.rb', line 23 def build(output_dir:) api_dir = File.join(output_dir, 'api') FileUtils.mkdir_p(api_dir) write_doc(File.join(output_dir, 'commands.md'), render_commands) module_docs = Esp::Introspection.module_docs module_docs.each do |mod| write_doc(File.join(api_dir, "#{slug_for(mod[:name])}.md"), render_module(mod)) end write_doc(File.join(api_dir, 'index.md'), render_api_index(module_docs)) { commands: File.join(output_dir, 'commands.md'), api_index: File.join(api_dir, 'index.md'), api_modules: module_docs.map { |m| File.join(api_dir, "#{slug_for(m[:name])}.md") } } end |
.render_api_index(modules) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/esp/docs_generator.rb', line 71 def render_api_index(modules) out = StringIO.new out.puts '# API reference' out.puts out.puts 'Core library modules. Shell modules are `Esp::<Name>`;' out.puts 'Morrowind-plugin modules are `Esp::Mw::<Name>`.' out.puts modules.each do |mod| out.puts "- [`#{mod[:name]}`](#{slug_for(mod[:name])}.md)" end out.string end |
.render_commands ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/esp/docs_generator.rb', line 46 def render_commands out = StringIO.new tree = Esp::Introspection.command_tree out.puts '# Command reference' out.puts out.puts 'Every command accepts `--json` for structured output to stdout.' out.puts 'Errors print as `{"error": "..."}` to stderr with a non-zero exit.' out.puts out.puts '## Top-level commands' out.puts tree[:commands].each { |cmd| render_command(out, cmd) } tree[:subcommands].each { |sub| render_subcommand_section(out, sub) } out.string end |
.render_module(mod) ⇒ Object
61 62 63 64 65 66 67 68 69 |
# File 'lib/esp/docs_generator.rb', line 61 def render_module(mod) <<~MD # #{mod[:name]} **Source:** `#{mod[:source]}` #{mod[:description]} MD end |
.write_doc(path, body) ⇒ Object
Write the regenerated auto block, then re-attach the file’s existing hand-written tail (everything after AUTO_CLOSE) verbatim — or scaffold one if the file is new.
42 43 44 |
# File 'lib/esp/docs_generator.rb', line 42 def write_doc(path, body) File.write(path, "#{AUTO_OPEN}\n\n#{body.strip}\n\n#{AUTO_CLOSE}#{manual_tail(path)}") end |