Skip to content

Actions

Actions are the core of BeDoc’s functionality. There are two kinds:

  • Parsers read source files and produce a structured object.
  • Formatters take that structured object and render it into an output format (Markdown, Wikitext, …).

An action is a JavaScript file that default-exports a class. That class declares a little metadata and describes its work as a pipeline. BeDoc discovers the action, negotiates its contract against a partner action, instantiates it, and runs the pipeline over each file.

Every action class has exactly two required members:

  1. static meta — describes what the action is and points at its contract.
  2. setup — an arrow function that receives an ActionBuilder and configures the processing pipeline.
import { ActionBuilder, ACTIVITY } from "@gesslar/actioneer"
export default class MyParser {
static meta = Object.freeze({
kind: "parser",
input: "lua",
terms: "ref://./my-parser.yaml",
})
setup = builder => builder
.do("Extract blocks", this.#extractBlocks)
.do("Process functions", ACTIVITY.SPLIT,
ctx => ctx, // splitter
ctx => ctx, // rejoiner
new ActionBuilder()
.do("Extract signature", this.#extractSignature)
.do("Extract description", this.#extractDescription),
)
.done(this.#finally)
#extractBlocks = ctx => { /* … */ }
#extractSignature = ctx => { /* … */ }
#extractDescription = ctx => { /* … */ }
#finally = ctx => ({ functions: ctx })
}

meta is a frozen object. The required fields depend on the kind.

static meta = Object.freeze({
kind: "parser", // required
input: "lua", // required — the language this parser reads
terms: "ref://./my-parser.yaml", // required — path to the contract
})
Field Applies to Meaning
kind both "parser" or "formatter".
input parser The language identifier matched against --language.
format formatter The output format matched against --format.
extension formatter Extension used for written output files (e.g. md).
terms both A ref:// path to the action’s contract YAML/JSON file, resolved relative to the action file.

Instead of a single run() method, an action describes its work as a chain of named steps using the fluent ActionBuilder API from Actioneer. The setup field is an arrow function (so this is the action instance) that receives the builder and returns it configured:

setup = builder => builder
.do("Step name", this.#stepMethod)
.do("Another step", this.#anotherMethod)
.done(this.#finalize)
  • .do(name, fn) adds a step. Each step receives the current context (ctx) and returns the context for the next step.
  • .do(name, ACTIVITY.SPLIT, …) fans the context out into items, runs a sub-pipeline over each (in parallel, up to --maxConcurrent), then rejoins the results.
  • .done(fn) registers the final step that produces the action’s result.

The step names matter: they are the anchor points for hooks. A step named "Format function" can be wrapped by a before$formatFunction / after$formatFunction hook (the hook name is the camelCase of the step name).

What a parser produces / a formatter consumes

Section titled “What a parser produces / a formatter consumes”

A parser’s pipeline ends by producing the structured object promised by its contract — typically { functions: [ … ] }. That object is handed to the matched formatter, whose pipeline renders it to a string. The shape of that object is governed by the contract the two actions negotiate.

Actions are not handed a logger instance — there is no this.log on your action. BeDoc’s own debug output is controlled by the --debug / --debugLevel configuration options.

A single action file default-exports a single action. To ship one or more actions as an installable package, list the files under a bedoc.actions array in your package.json so BeDoc can discover them:

{
"name": "bedoc-mylang-parser",
"version": "1.0.0",
"type": "module",
"bedoc": {
"actions": ["./bedoc-mylang-parser.js"]
}
}

See the Modules guide for packaging and naming conventions, and the Parsers and Formatters guides for end-to-end examples.

Actions expose their named steps as hook points, letting users inject custom logic with before$/after$ handlers — without touching the action itself.

Read the Hooks Guide to learn more.