or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-processing.mdcli.mdcore-configuration.mddebugging.mdfile-operations.mdfrontmatter.mdindex.mdplugin-system.mdutilities.md

debugging.mddocs/

0

# Debugging and Logging

1

2

Debugging system with namespaced loggers and configurable output for development and troubleshooting. Metalsmith uses the `debug` module with enhanced features for plugin development and build monitoring.

3

4

## Capabilities

5

6

### Debug Logger Creation

7

8

Create namespaced debug loggers for plugins and custom code.

9

10

```javascript { .api }

11

/**

12

* Create a namespaced debug logger

13

* @param namespace - Debug namespace (typically plugin name)

14

* @returns Enhanced debugger with multiple log levels

15

*/

16

debug(namespace: string): Debugger;

17

18

interface Debugger {

19

/** Main debug function for general messages */

20

(message: string, ...args: any[]): void;

21

/** Info-level logging (namespace:info) */

22

info(message: string, ...args: any[]): void;

23

/** Warning-level logging (namespace:warn) */

24

warn(message: string, ...args: any[]): void;

25

/** Error-level logging (namespace:error) */

26

error(message: string, ...args: any[]): void;

27

}

28

```

29

30

**Usage Examples:**

31

32

```javascript

33

import Metalsmith from "metalsmith";

34

35

const metalsmith = Metalsmith(__dirname);

36

37

// Create debug logger for a plugin

38

function myPlugin(files, metalsmith, done) {

39

const debug = metalsmith.debug('metalsmith-myplugin');

40

41

debug('Starting plugin execution');

42

debug('Processing %d files', Object.keys(files).length);

43

44

Object.keys(files).forEach(filepath => {

45

debug('Processing file: %s', filepath);

46

47

try {

48

// Process file...

49

debug.info('Successfully processed: %s', filepath);

50

} catch (error) {

51

debug.error('Failed to process %s: %s', filepath, error.message);

52

}

53

});

54

55

debug('Plugin execution completed');

56

done();

57

}

58

59

// Use different log levels

60

function detailedPlugin(files, metalsmith, done) {

61

const debug = metalsmith.debug('detailed-plugin');

62

63

debug('Plugin started'); // General debug

64

debug.info('Configuration loaded'); // Info level

65

debug.warn('Deprecated option used'); // Warning level

66

debug.error('Critical error occurred'); // Error level

67

68

done();

69

}

70

```

71

72

### Debug Configuration

73

74

Control debug output through environment variables and Metalsmith settings.

75

76

```javascript { .api }

77

/**

78

* Debug configuration properties (available on metalsmith.debug)

79

*/

80

interface DebugConfig {

81

/** Enable debug output for specific namespaces */

82

enable(namespaces: string): void;

83

/** Disable debug output */

84

disable(): void;

85

/** Set custom log handler function */

86

handle: (...args: any[]) => void;

87

/** Enable/disable color output */

88

colors: boolean;

89

/** Check if debug is currently enabled */

90

enabled: boolean;

91

}

92

```

93

94

**Environment Variable Control:**

95

96

```javascript

97

// Enable debug output via environment

98

metalsmith.env('DEBUG', '@metalsmith/*'); // All metalsmith plugins

99

metalsmith.env('DEBUG', 'metalsmith-markdown'); // Specific plugin

100

metalsmith.env('DEBUG', '*'); // All debug output

101

102

// Enable in code

103

metalsmith.debug.enable('@metalsmith/*');

104

105

// Disable debug output

106

metalsmith.debug.disable();

107

108

// Check if debug is enabled

109

if (metalsmith.debug.enabled) {

110

console.log('Debug mode is active');

111

}

112

```

113

114

**Color Configuration:**

115

116

```javascript

117

// Enable colors (default for terminals)

118

metalsmith.debug.colors = true;

119

120

// Disable colors (useful for log files)

121

metalsmith.debug.colors = false;

122

```

123

124

### Custom Log Handling

125

126

Configure custom log handlers for debug output.

127

128

```javascript { .api }

129

/**

130

* Set custom debug log handler

131

* @param handler - Function to handle debug output

132

*/

133

debug.handle = (message: string) => void;

134

```

135

136

**Usage Examples:**

137

138

```javascript

139

import fs from 'fs';

140

141

// Log to file

142

const logStream = fs.createWriteStream('debug.log', { flags: 'a' });

143

metalsmith.debug.handle = (message) => {

144

logStream.write(message + '\n');

145

};

146

147

// Custom formatted logging

148

metalsmith.debug.handle = (message) => {

149

const timestamp = new Date().toISOString();

150

console.log(`[${timestamp}] ${message}`);

151

};

152

153

// Multiple handlers

154

const originalHandler = metalsmith.debug.handle;

155

metalsmith.debug.handle = (message) => {

156

originalHandler(message); // Console output

157

logStream.write(`${new Date().toISOString()}: ${message}\n`); // File output

158

};

159

```

160

161

### Built-in Debug Features

162

163

Metalsmith includes enhanced debug features beyond standard debug module.

164

165

**Buffer Formatter:**

166

167

```javascript

168

// Debug includes a %b formatter for buffers

169

function plugin(files, metalsmith, done) {

170

const debug = metalsmith.debug('my-plugin');

171

172

Object.keys(files).forEach(filepath => {

173

const file = files[filepath];

174

175

// %b formatter shows buffer content preview

176

debug('File contents: %b', file.contents);

177

// Output: "File contents: <Buffer contents preview...>"

178

});

179

180

done();

181

}

182

```

183

184

**Performance Monitoring:**

185

186

```javascript

187

function performancePlugin(files, metalsmith, done) {

188

const debug = metalsmith.debug('performance');

189

190

const startTime = Date.now();

191

192

// Process files...

193

194

const duration = Date.now() - startTime;

195

debug('Processing completed in %dms', duration);

196

debug.info('Processed %d files', Object.keys(files).length);

197

198

done();

199

}

200

```

201

202

### Debug-enabled Build Process

203

204

Using debug output to monitor the build process.

205

206

```javascript

207

// Enable comprehensive debugging

208

metalsmith

209

.env('DEBUG', '*')

210

.env('DEBUG_LOG', 'build.log') // Optional: log to file

211

.build((error, files) => {

212

if (error) {

213

console.error('Build failed:', error);

214

return;

215

}

216

console.log('Build completed successfully');

217

});

218

```

219

220

### Plugin Debug Patterns

221

222

Best practices for debugging in plugins.

223

224

```javascript

225

function robustPlugin(options = {}) {

226

return function plugin(files, metalsmith, done) {

227

const debug = metalsmith.debug('robust-plugin');

228

229

// Log plugin start with configuration

230

debug('Plugin starting with options: %o', options);

231

232

const startTime = process.hrtime();

233

const fileCount = Object.keys(files).length;

234

235

debug('Processing %d files', fileCount);

236

237

try {

238

let processed = 0;

239

240

Object.keys(files).forEach(filepath => {

241

debug('Processing file %d/%d: %s', ++processed, fileCount, filepath);

242

243

const file = files[filepath];

244

245

// Detailed file information

246

debug('File size: %d bytes', file.contents.length);

247

debug('File metadata: %o', {

248

title: file.title,

249

date: file.date,

250

tags: file.tags

251

});

252

253

// Process file with error handling

254

try {

255

// File processing logic...

256

debug.info('Successfully processed: %s', filepath);

257

} catch (fileError) {

258

debug.error('Error processing %s: %s', filepath, fileError.message);

259

throw fileError; // Re-throw to stop build

260

}

261

});

262

263

const [seconds, nanoseconds] = process.hrtime(startTime);

264

const duration = (seconds * 1000) + (nanoseconds / 1000000);

265

266

debug('Plugin completed in %dms', duration.toFixed(2));

267

debug.info('Successfully processed %d files', processed);

268

269

done();

270

} catch (error) {

271

debug.error('Plugin failed: %s', error.message);

272

debug.error('Stack trace: %s', error.stack);

273

done(error);

274

}

275

};

276

}

277

```

278

279

### Environment-specific Debug Configuration

280

281

Configure debugging based on environment settings.

282

283

```javascript

284

// Development environment with verbose debugging

285

if (process.env.NODE_ENV === 'development') {

286

metalsmith

287

.env('DEBUG', '@metalsmith/*,my-plugin*')

288

.env('DEBUG_LOG', 'logs/debug.log');

289

290

metalsmith.debug.colors = true;

291

}

292

293

// Production environment with error-only logging

294

if (process.env.NODE_ENV === 'production') {

295

metalsmith.env('DEBUG', false);

296

297

// Custom error-only handler

298

metalsmith.debug.handle = (message) => {

299

if (message.includes(':error')) {

300

console.error(message);

301

}

302

};

303

}

304

305

// Conditional debugging in plugins

306

function conditionalPlugin(files, metalsmith, done) {

307

const debug = metalsmith.debug('conditional-plugin');

308

const verbose = metalsmith.env('VERBOSE');

309

310

if (verbose) {

311

debug('Verbose mode enabled');

312

debug('File list: %o', Object.keys(files));

313

}

314

315

// Process files...

316

done();

317

}

318

```

319

320

### Debugging File Processing Issues

321

322

Common debugging scenarios for file processing problems.

323

324

```javascript

325

function diagnosticPlugin(files, metalsmith, done) {

326

const debug = metalsmith.debug('diagnostics');

327

328

debug('=== DIAGNOSTIC INFORMATION ===');

329

debug('Working directory: %s', metalsmith.directory());

330

debug('Source directory: %s', metalsmith.source());

331

debug('Destination directory: %s', metalsmith.destination());

332

debug('Global metadata: %o', metalsmith.metadata());

333

debug('Environment: %o', metalsmith.env());

334

335

debug('=== FILE ANALYSIS ===');

336

debug('Total files: %d', Object.keys(files).length);

337

338

Object.keys(files).forEach(filepath => {

339

const file = files[filepath];

340

341

debug('File: %s', filepath);

342

debug(' Size: %d bytes', file.contents.length);

343

debug(' Mode: %s', file.mode);

344

debug(' Stats: %o', file.stats);

345

debug(' Metadata keys: %o', Object.keys(file).filter(k => !['contents', 'stats', 'mode'].includes(k)));

346

347

// Check for front-matter parsing issues

348

if (file.contents.toString().startsWith('---')) {

349

debug.warn(' Potential front-matter parsing issue detected');

350

}

351

});

352

353

done();

354

}

355

```