renderText Service
Interface
The service creates an async function that accepts a single function parameter:
await this.renderText(textFunction)
Parameters
textFunction
(function) - A function that receives a utilities object with text formatting methods (echo
,line
,indent
)
Return Value
Returns a Promise
that resolves to a Text
instance that:
- Can be converted to string with
toString()
- Can be used in HTTP responses with
toResponseArray()
- Provides plain text content with proper line breaks and indentation
Description
The renderText
service is a powerful plain text template rendering utility that:
- Provides structured text output through specialized formatting functions (
echo
,line
,indent
) - Handles asynchronous content by supporting promises in all text operations
- Manages indentation automatically with nested scope-aware indentation levels
- Supports flexible text composition ideal for code generation, configuration files, and formatted output
- Processes content lazily allowing for complex nested structures and conditional rendering
- Returns structured text objects that can be converted to strings or HTTP responses
The service is built on top of the Text
class and is available on all views via this.renderText
.
Key Features
- Line-based output with automatic newline management
- Scope-aware indentation with 4-space increments per level
- Promise-aware rendering for async content resolution
- Minimal API with just three core functions:
echo
,line
,indent
- HTTP response compatibility for serving text content directly
Examples
Basic Text Output
// Simple text with echo
const result = await this.renderText(({ echo }) => {
echo('Hello world');
});
// Result: "Hello world"
// Line-based output
const result = await this.renderText(({ line }) => {
line('First line');
line('Second line');
});
// Result: "First line\nSecond line"
File Generation
// Generate a JavaScript service file
const serviceCode = await this.renderText(({ line, indent }) => {
line(`export default {`);
indent(({ line, indent }) => {
line('create(){');
indent(({ line }) => {
line(`return 'Example ${serviceName} service'`);
});
line('}');
});
line('};');
});
// Result:
// export default {
// create(){
// return 'Example MyService service'
// }
// };
Email Template Generation
// Generate plain text email content
const emailBody = await this.renderText(({ line, indent }) => {
line('Dear Customer,');
line();
line('Thank you for your recent order. Here are the details:');
line();
indent(({ line }) => {
line(`Order ID: ${order.id}`);
line(`Date: ${order.date}`);
line(`Total: $${order.total}`);
});
line();
line('Best regards,');
line('The Team');
});
Configuration File Generation
// Generate configuration files
const configFile = await this.renderText(({ line, indent }) => {
line('[database]');
indent(({ line }) => {
line(`host = ${config.db.host}`);
line(`port = ${config.db.port}`);
line(`name = ${config.db.name}`);
});
line();
line('[server]');
indent(({ line }) => {
line(`port = ${config.server.port}`);
line(`debug = ${config.server.debug}`);
});
});
Asynchronous Content
// Handle promises and async operations
const report = await this.renderText(async ({ line, indent }) => {
line('System Report');
line('=============');
line();
const users = await this.database.users.count();
line(`Total Users: ${users}`);
const posts = await this.database.posts.count();
line(`Total Posts: ${posts}`);
line();
line('Recent Activity:');
indent(async ({ line }) => {
const recentUsers = await this.database.users.recent(5);
for(const user of recentUsers) {
line(`- ${user.name} joined ${user.createdAt}`);
}
});
});
Multi-level Indentation
// Complex nested structure generation
const structuredOutput = await this.renderText(({ line, indent }) => {
line('Root Level');
indent(({ line, indent }) => {
line('Level 1');
indent(({ line, indent }) => {
line('Level 2');
indent(({ line }) => {
line('Level 3');
line('Still Level 3');
});
line('Back to Level 2');
});
line('Back to Level 1');
});
line('Back to Root');
});
// Result:
// Root Level
// Level 1
// Level 2
// Level 3
// Still Level 3
// Back to Level 2
// Back to Level 1
// Back to Root
Conditional Content Generation
// Generate content based on conditions
const buildScript = await this.renderText(({ line, indent }) => {
line('#!/bin/bash');
line();
line('echo "Starting build process..."');
line();
if(includeTests) {
line('echo "Running tests..."');
line('npm test');
line();
}
line('echo "Building application..."');
line('npm run build');
if(deployAfterBuild) {
line();
line('echo "Deploying..."');
indent(({ line }) => {
line('if [ $? -eq 0 ]; then');
line(' npm run deploy');
line(' echo "Deployment complete"');
line('else');
line(' echo "Build failed, skipping deployment"');
line('fi');
});
}
});
Integration with Other Services
export default {
async render() {
if(this.requestMethod === 'GET') {
// Return HTML form
return this.renderView('_form', { model: this.user });
}
// Generate notification email on form submission
const emailText = await this.renderText(({ line, indent }) => {
line(`Hello ${this.user.name},`);
line();
line('Your profile has been updated with the following changes:');
line();
indent(({ line }) => {
if(this.user.nameChanged) line(`- Name: ${this.user.name}`);
if(this.user.emailChanged) line(`- Email: ${this.user.email}`);
if(this.user.bioChanged) line(`- Bio: ${this.user.bio}`);
});
});
await this.sendMail({
to: this.user.email,
subject: 'Profile Updated',
text: emailText
});
return this.renderRedirect('/profile');
}
}
Utilities Reference
echo(content)
Adds content directly to the output buffer without adding line breaks.
echo('Hello ');
echo('World');
// Result: "Hello World"
line(content = '')
Adds content as a new line. If called without arguments, adds an empty line.
line('First line');
line('Second line');
line(); // Empty line
line('After empty line');
// Result: "First line\nSecond line\n\nAfter empty line"
indent(function)
Creates a new indentation scope (4 spaces) and executes the provided function within that scope.
line('Root');
indent(({ line }) => {
line('Indented');
line('Also indented');
});
line('Back to root');
// Result: "Root\n Indented\n Also indented\nBack to root"
Common Use Cases
Code Generation
- Service files: Generate JavaScript service templates
- Model classes: Create database model boilerplate
- Configuration: Generate configuration files and scripts
- Build scripts: Create deployment and build automation
Communication
- Email templates: Plain text email bodies with structured content
- Notifications: System alerts and user notifications
- Reports: Generate formatted text reports and logs
- Documentation: Create structured text documentation
Data Export
- CSV files: Generate comma-separated value files
- Configuration dumps: Export system settings
- Log files: Create structured log output
- API responses: Plain text API responses
Performance Notes
- Content is rendered asynchronously and supports promises throughout
- Indentation is calculated efficiently using string manipulation
- Output buffer is optimized for append operations
- Memory usage scales linearly with content size
- The service is designed for server-side text generation
Return Value Details
The Text
instance returned by renderText
provides:
const textResult = await this.renderText(/* ... */);
// Convert to string
const stringContent = textResult.toString();
// Convert to HTTP response
const [status, headers, body] = textResult.toResponseArray();
// Returns: [200, {'content-type': 'text/plain'}, [content]]
// Custom HTTP response with different status
const [status, headers, body] = textResult.toResponseArray(404, {'custom': 'header'});