or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdconfiguration.mdenvironment.mdindex.mdparser.mdplugins.mdtemplates.mdutilities.md
tile.json

templates.mddocs/

0

# Template System

1

2

JSDoc's template system generates HTML documentation from parsed doclets using a flexible template engine. It supports custom templates, layouts, helper functions, and complete control over output formatting.

3

4

## Capabilities

5

6

### Template Class

7

8

Core template class for loading and rendering templates with data.

9

10

```javascript { .api }

11

class Template {

12

/**

13

* Create a new Template instance

14

* @param filepath - Path to templates directory

15

*/

16

constructor(filepath: string);

17

18

/**

19

* Load template from file and compile

20

* @param file - Template filename

21

* @returns Compiled template function

22

*/

23

load(file: string): Function;

24

25

/**

26

* Render partial template with data

27

* @param file - Template filename

28

* @param data - Template data object

29

* @returns Rendered HTML string

30

*/

31

partial(file: string, data: object): string;

32

33

/**

34

* Render complete template with layout

35

* @param file - Template filename

36

* @param data - Template data object

37

* @returns Rendered HTML string with layout applied

38

*/

39

render(file: string, data: object): string;

40

41

/**

42

* Template settings for custom tag syntax

43

*/

44

settings: {

45

evaluate: RegExp; // Code execution tags: <?js ... ?>

46

interpolate: RegExp; // Variable interpolation: <?js= ... ?>

47

escape: RegExp; // HTML escaping: <?js~ ... ?>

48

};

49

50

/**

51

* Layout template path (optional)

52

*/

53

layout: string | null;

54

55

/**

56

* Template cache for performance

57

*/

58

cache: { [file: string]: Function };

59

}

60

```

61

62

### Template Publish Function

63

64

Standard interface for template entry points.

65

66

```javascript { .api }

67

/**

68

* Main template publish function interface

69

* @param data - TaffyDB collection of all doclets

70

* @param opts - JSDoc options and configuration

71

* @param tutorials - Tutorial root object (optional)

72

* @returns Promise or undefined

73

*/

74

function publish(

75

data: TaffyDB,

76

opts: JSDocOptions,

77

tutorials?: TutorialRoot

78

): Promise<void> | void;

79

80

interface JSDocOptions {

81

destination: string; // Output directory

82

encoding: string; // File encoding

83

template: string; // Template path

84

readme?: string; // README content

85

package?: object; // Package information

86

access?: string[]; // Access levels to include

87

private?: boolean; // Include private members

88

query?: object; // Custom query parameters

89

}

90

91

interface TutorialRoot {

92

title: string;

93

children: Tutorial[];

94

}

95

```

96

97

## Built-in Templates

98

99

### Default Template

100

101

The standard HTML template included with JSDoc.

102

103

**Location**: `templates/default/`

104

105

**Key Files**:

106

- `publish.js` - Main template entry point

107

- `tmpl/` - Template fragments

108

- `static/` - CSS, JavaScript, and other assets

109

110

**Features**:

111

- Responsive HTML layout

112

- Search functionality

113

- Syntax highlighting

114

- Cross-reference navigation

115

- Tutorial integration

116

117

### Haruki Template

118

119

Minimalist template with clean design.

120

121

**Location**: `templates/haruki/`

122

123

**Features**:

124

- Simple, clean interface

125

- Minimal styling

126

- Focus on content readability

127

128

### Silent Template

129

130

Template that generates no output (for testing/validation).

131

132

**Location**: `templates/silent/`

133

134

**Usage**: Useful for syntax checking without generating files.

135

136

## Template Development

137

138

### Basic Template Structure

139

140

```

141

my-template/

142

├── publish.js # Main entry point

143

├── tmpl/ # Template fragments

144

│ ├── layout.tmpl # Main layout

145

│ ├── container.tmpl # Content container

146

│ └── ...

147

├── static/ # Static assets

148

│ ├── styles/ # CSS files

149

│ ├── scripts/ # JavaScript files

150

│ └── fonts/ # Font files

151

└── README.md # Template documentation

152

```

153

154

### Basic Publish Function

155

156

```javascript

157

// publish.js

158

const doop = require('jsdoc/util/doop');

159

const env = require('jsdoc/env');

160

const fs = require('jsdoc/fs');

161

const helper = require('jsdoc/util/templateHelper');

162

const path = require('jsdoc/path');

163

const { taffy } = require('@jsdoc/salty');

164

const template = require('jsdoc/template');

165

166

let data;

167

let view;

168

let outdir = path.normalize(env.opts.destination);

169

170

function find(spec) {

171

return helper.find(data, spec);

172

}

173

174

exports.publish = function(taffyData, opts, tutorials) {

175

data = taffyData;

176

177

const conf = env.conf.templates || {};

178

conf.default = conf.default || {};

179

180

const templatePath = path.normalize(env.opts.template);

181

view = new template.Template(path.join(templatePath, 'tmpl'));

182

183

// Generate output files

184

generateFiles();

185

};

186

187

function generateFiles() {

188

const classes = find({ kind: 'class' });

189

const namespaces = find({ kind: 'namespace' });

190

191

classes.forEach(function(c) {

192

generateClassDoc(c);

193

});

194

195

namespaces.forEach(function(n) {

196

generateNamespaceDoc(n);

197

});

198

}

199

```

200

201

### Advanced Template with Helpers

202

203

```javascript

204

// publish.js with helpers

205

const helper = require('jsdoc/util/templateHelper');

206

207

// Template helper functions

208

const htmlsafe = helper.htmlsafe;

209

const linkto = helper.linkto;

210

const resolveAuthorLinks = helper.resolveAuthorLinks;

211

212

function buildNav(members) {

213

let nav = '<ul>';

214

215

if (members.classes.length) {

216

nav += '<li>Classes<ul>';

217

members.classes.forEach(function(c) {

218

nav += `<li>${linkto(c.longname, c.name)}</li>`;

219

});

220

nav += '</ul></li>';

221

}

222

223

if (members.namespaces.length) {

224

nav += '<li>Namespaces<ul>';

225

members.namespaces.forEach(function(n) {

226

nav += `<li>${linkto(n.longname, n.name)}</li>`;

227

});

228

nav += '</ul></li>';

229

}

230

231

nav += '</ul>';

232

return nav;

233

}

234

235

function generateSourceFiles() {

236

const sourceFiles = {};

237

238

data().each(function(doclet) {

239

if (doclet.meta) {

240

const sourcePath = getPathFromDoclet(doclet);

241

sourceFiles[sourcePath] = {

242

shortened: sourcePath,

243

resolved: sourcePath

244

};

245

}

246

});

247

248

return sourceFiles;

249

}

250

251

exports.publish = function(taffyData, opts, tutorials) {

252

data = taffyData;

253

254

const members = helper.getMembers(data);

255

const sourceFiles = generateSourceFiles();

256

const nav = buildNav(members);

257

258

// Generate index page

259

const indexHtml = view.render('index.tmpl', {

260

title: opts.package?.name || 'API Documentation',

261

nav: nav,

262

members: members

263

});

264

265

fs.writeFileSync(path.join(outdir, 'index.html'), indexHtml, 'utf8');

266

};

267

```

268

269

### Template Fragment Examples

270

271

#### Layout Template (`tmpl/layout.tmpl`)

272

273

```html

274

<!DOCTYPE html>

275

<html lang="en">

276

<head>

277

<meta charset="utf-8">

278

<title><?js= title ?></title>

279

<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">

280

</head>

281

<body>

282

<div id="main">

283

<h1 class="page-title"><?js= title ?></h1>

284

<?js= content ?>

285

</div>

286

287

<nav>

288

<?js= this.nav ?>

289

</nav>

290

291

<script src="scripts/prettify/prettify.js"></script>

292

<script>prettyPrint();</script>

293

</body>

294

</html>

295

```

296

297

#### Class Template (`tmpl/class.tmpl`)

298

299

```html

300

<?js

301

var self = this;

302

var isGlobalPage;

303

304

docs.forEach(function(doc, i) {

305

?>

306

307

<section>

308

<header>

309

<h2><?js if (doc.ancestors && doc.ancestors.length) { ?>

310

<span class="ancestors"><?js= doc.ancestors.join('') ?></span>

311

<?js } ?>

312

<?js= doc.name ?>

313

<?js if (doc.variation) { ?>

314

<sup class="variation"><?js= doc.variation ?></sup>

315

<?js } ?></h2>

316

<?js if (doc.classdesc) { ?>

317

<div class="class-description"><?js= doc.classdesc ?></div>

318

<?js } ?>

319

</header>

320

321

<article>

322

<div class="container-overview">

323

<?js if (doc.kind === 'class' && doc.examples && doc.examples.length) { ?>

324

<h3>Example<?js= doc.examples.length > 1? 's':'' ?></h3>

325

<?js= this.partial('examples.tmpl', doc.examples) ?>

326

<?js } ?>

327

</div>

328

329

<?js if (doc.augments && doc.augments.length) { ?>

330

<h3 class="subsection-title">Extends</h3>

331

<?js= this.partial('augments.tmpl', doc.augments) ?>

332

<?js } ?>

333

334

<?js if (doc.requires && doc.requires.length) { ?>

335

<h3 class="subsection-title">Requires</h3>

336

<ul><?js doc.requires.forEach(function(r) { ?>

337

<li><?js= self.linkto(r, r) ?></li>

338

<?js }); ?></ul>

339

<?js } ?>

340

</article>

341

</section>

342

343

<?js }); ?>

344

```

345

346

## Template Helper Functions

347

348

### Core Helpers

349

350

JSDoc provides built-in helper functions for common template tasks.

351

352

```javascript { .api }

353

const helper = require('jsdoc/util/templateHelper');

354

355

/**

356

* Create HTML-safe string

357

* @param str - String to make HTML-safe

358

* @returns HTML-escaped string

359

*/

360

function htmlsafe(str: string): string;

361

362

/**

363

* Create link to symbol

364

* @param longname - Symbol longname

365

* @param linkText - Link text (optional)

366

* @returns HTML link element

367

*/

368

function linkto(longname: string, linkText?: string): string;

369

370

/**

371

* Find doclets matching specification

372

* @param data - TaffyDB data collection

373

* @param spec - Search specification

374

* @returns Array of matching doclets

375

*/

376

function find(data: TaffyDB, spec: object): Doclet[];

377

378

/**

379

* Get organized members from data

380

* @param data - TaffyDB data collection

381

* @returns Organized member object

382

*/

383

function getMembers(data: TaffyDB): {

384

classes: Doclet[];

385

externals: Doclet[];

386

events: Doclet[];

387

globals: Doclet[];

388

mixins: Doclet[];

389

modules: Doclet[];

390

namespaces: Doclet[];

391

tutorials: Doclet[];

392

interfaces: Doclet[];

393

};

394

395

/**

396

* Resolve author links in text

397

* @param str - String with author information

398

* @returns String with resolved links

399

*/

400

function resolveAuthorLinks(str: string): string;

401

402

/**

403

* Get ancestor links for symbol

404

* @param data - TaffyDB data collection

405

* @param doclet - Current doclet

406

* @returns Array of ancestor link strings

407

*/

408

function getAncestorLinks(data: TaffyDB, doclet: Doclet): string[];

409

```

410

411

### Custom Helper Development

412

413

```javascript

414

// Custom template helpers

415

function formatDate(date) {

416

return new Date(date).toLocaleDateString();

417

}

418

419

function getTypeNames(type) {

420

if (!type || !type.names) return 'unknown';

421

return type.names.join(' | ');

422

}

423

424

function buildParameterTable(params) {

425

if (!params || !params.length) return '';

426

427

let table = '<table class="params"><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody>';

428

429

params.forEach(function(param) {

430

table += '<tr>';

431

table += `<td>${param.name}</td>`;

432

table += `<td>${getTypeNames(param.type)}</td>`;

433

table += `<td>${param.description || ''}</td>`;

434

table += '</tr>';

435

});

436

437

table += '</tbody></table>';

438

return table;

439

}

440

441

// Use in templates

442

exports.publish = function(taffyData, opts, tutorials) {

443

// Make helpers available to templates

444

view.formatDate = formatDate;

445

view.getTypeNames = getTypeNames;

446

view.buildParameterTable = buildParameterTable;

447

};

448

```

449

450

## Template Configuration

451

452

### Template Selection

453

454

```bash

455

# Use specific template

456

jsdoc -t templates/custom src/

457

458

# Use template from node_modules

459

jsdoc -t node_modules/my-jsdoc-template src/

460

```

461

462

### Template Configuration in JSDoc Config

463

464

```json

465

{

466

"opts": {

467

"template": "./templates/custom"

468

},

469

"templates": {

470

"cleverLinks": false,

471

"monospaceLinks": false,

472

"dateFormat": "MMMM Do YYYY, h:mm:ss a",

473

"outputSourceFiles": true,

474

"outputSourcePath": true,

475

"systemName": "My API",

476

"footer": "Copyright 2023",

477

"copyright": "Copyright 2023 My Company",

478

"includeDate": true,

479

"navType": "vertical",

480

"theme": "cerulean",

481

"linenums": true,

482

"collapseSymbols": false,

483

"inverseNav": true,

484

"protocol": "html://",

485

"methodHeadingReturns": false

486

}

487

}

488

```

489

490

## Usage Examples

491

492

### Simple Custom Template

493

494

```javascript

495

// simple-template/publish.js

496

const fs = require('jsdoc/fs');

497

const path = require('jsdoc/path');

498

const { taffy } = require('@jsdoc/salty');

499

500

exports.publish = function(data, opts) {

501

const outdir = path.normalize(opts.destination);

502

503

// Generate simple HTML

504

let html = `

505

<!DOCTYPE html>

506

<html>

507

<head><title>API Documentation</title></head>

508

<body>

509

<h1>API Documentation</h1>

510

<ul>

511

`;

512

513

data({ kind: ['class', 'function', 'namespace'] }).each(function(doclet) {

514

html += `<li><strong>${doclet.name}</strong> - ${doclet.description || 'No description'}</li>`;

515

});

516

517

html += `

518

</ul>

519

</body>

520

</html>

521

`;

522

523

fs.writeFileSync(path.join(outdir, 'index.html'), html, 'utf8');

524

};

525

```

526

527

### JSON Output Template

528

529

```javascript

530

// json-template/publish.js

531

const fs = require('jsdoc/fs');

532

const path = require('jsdoc/path');

533

534

exports.publish = function(data, opts) {

535

const outdir = path.normalize(opts.destination);

536

537

const docs = data().get().map(function(doclet) {

538

return {

539

name: doclet.name,

540

longname: doclet.longname,

541

kind: doclet.kind,

542

description: doclet.description,

543

params: doclet.params,

544

returns: doclet.returns,

545

examples: doclet.examples

546

};

547

});

548

549

const output = {

550

generated: new Date().toISOString(),

551

package: opts.package,

552

docs: docs

553

};

554

555

fs.writeFileSync(

556

path.join(outdir, 'api.json'),

557

JSON.stringify(output, null, 2),

558

'utf8'

559

);

560

};

561

```

562

563

### Markdown Template

564

565

```javascript

566

// markdown-template/publish.js

567

const fs = require('jsdoc/fs');

568

const path = require('jsdoc/path');

569

570

exports.publish = function(data, opts) {

571

const outdir = path.normalize(opts.destination);

572

573

let markdown = `# ${opts.package?.name || 'API'} Documentation\n\n`;

574

575

const classes = data({ kind: 'class' }).get();

576

const functions = data({ kind: 'function' }).get();

577

578

if (classes.length) {

579

markdown += '## Classes\n\n';

580

classes.forEach(function(cls) {

581

markdown += `### ${cls.name}\n\n`;

582

if (cls.description) {

583

markdown += `${cls.description}\n\n`;

584

}

585

});

586

}

587

588

if (functions.length) {

589

markdown += '## Functions\n\n';

590

functions.forEach(function(fn) {

591

markdown += `### ${fn.name}\n\n`;

592

if (fn.description) {

593

markdown += `${fn.description}\n\n`;

594

}

595

if (fn.params && fn.params.length) {

596

markdown += '**Parameters:**\n\n';

597

fn.params.forEach(function(param) {

598

markdown += `- \`${param.name}\` - ${param.description || ''}\n`;

599

});

600

markdown += '\n';

601

}

602

});

603

}

604

605

fs.writeFileSync(path.join(outdir, 'README.md'), markdown, 'utf8');

606

};

607

```