Processing Pipeline¶
PM processes prompts through a four-stage pipeline. The first three stages run at parse time; the fourth runs on demand when to_s is called.
Overview¶
graph TD
A["Raw Input<br/>(file, symbol, word, or string)"] --> B["1. Strip HTML Comments"]
B --> C["2. Extract YAML Metadata"]
C --> D["3. Shell Expansion"]
D --> E["PM::Parsed<br/>(metadata + content)"]
E -->|"to_s(values)"| F["4. ERB Rendering"]
F --> G["Rendered String"]
style A fill:#00695c,color:#fff
style E fill:#00695c,color:#fff
style G fill:#f57f17,color:#000
Stage 1: Strip HTML Comments¶
When: Parse time
Method: PM.strip_comments
All <!-- ... --> comments are removed, including multiline spans. This runs first so comments don't interfere with metadata extraction.
Input: "<!-- draft -->\n---\ntitle: Test\n---\nContent <!-- note -->"
Output: "\n---\ntitle: Test\n---\nContent "
Stage 2: Extract YAML Metadata¶
When: Parse time
Regex: PM::METADATA_REGEXP
The ----delimited front-matter is parsed with YAML.safe_load into a Hash, then wrapped in a PM::Metadata object. Global defaults for shell and erb are applied if the file doesn't specify them.
For file sources, directory, name, created_at, and modified_at are added from file stats.
Input: "---\ntitle: Test\nshell: true\n---\nContent"
Output: metadata = PM::Metadata(title: "Test", shell: true, erb: true)
content = "Content"
Stage 3: Shell Expansion¶
When: Parse time (if shell: true)
Method: PM.expand_shell
Two sub-stages run in order:
3a. Command Substitution¶
$(command) sequences are found (with proper nesting of parentheses), executed, and replaced with stdout.
3b. Environment Variables¶
$VAR and ${VAR} patterns (UPPERCASE only) are replaced with the corresponding environment variable value. Missing variables become empty strings.
Stage 4: ERB Rendering¶
When: On demand (to_s call, if erb: true)
Method: PM::Parsed#to_s
The content is evaluated as an ERB template. Parameter values (defaults merged with to_s arguments) and registered directives are available as local methods in the template.
This stage also handles the include directive, which recursively parses and renders included files through the full pipeline.
Conditional Stages¶
Stages 3 and 4 can be independently disabled:
| Setting | Effect |
|---|---|
shell: false |
Stage 3 skipped; $VAR and $(cmd) preserved |
erb: false |
Stage 4 skipped; <%= ... %> preserved |
Settings can be per-file (YAML metadata) or global (PM.configure). Per-file always wins.
Data Flow¶
graph LR
subgraph "Parse Time"
A[Raw Text] --> B[No Comments]
B --> C[Metadata + Content]
C --> D[Shell-Expanded Content]
end
subgraph "Render Time"
D --> E[ERB Template]
E --> F[Final Output]
end
style A fill:#00695c,color:#fff
style F fill:#f57f17,color:#000
The PM::Parsed object returned by PM.parse holds the result of stages 1-3. Calling to_s triggers stage 4 and returns the final string.