or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

accessibility.mddocument-rendering.mdextensions.mdindex.mdinitialization.mdinput-processing.mdoutput-formats.md

document-rendering.mddocs/

0

# Document Rendering

1

2

MathJax provides comprehensive document rendering capabilities for automatically finding, processing, and rendering mathematical expressions within HTML documents, with support for dynamic content updates and performance optimization.

3

4

## Capabilities

5

6

### Document Typesetting

7

8

Process mathematical expressions within HTML documents automatically.

9

10

```javascript { .api }

11

/**

12

* Typeset mathematics in specified elements (synchronous)

13

* @param elements - Elements to process, or null for entire document

14

*/

15

function typeset(elements?: Element[]): void;

16

17

/**

18

* Typeset mathematics in specified elements (asynchronous)

19

* @param elements - Elements to process, or null for entire document

20

* @returns Promise that resolves when typesetting is complete

21

*/

22

function typesetPromise(elements?: Element[]): Promise<void>;

23

24

/**

25

* Clear typeset mathematics from specified elements

26

* @param elements - Elements to clear, or null for entire document

27

*/

28

function typesetClear(elements?: Element[]): void;

29

30

/**

31

* Get completion promise for current operations

32

* @returns Promise that resolves when all operations are complete

33

*/

34

function done(): Promise<void>;

35

36

/**

37

* Execute callback when MathJax is ready

38

* @param callback - Function to execute when ready

39

* @returns Promise that resolves after callback execution

40

*/

41

function whenReady(callback: () => void): Promise<void>;

42

```

43

44

**Usage Examples:**

45

46

```javascript

47

// Typeset entire document

48

MathJax.typeset();

49

50

// Typeset specific elements

51

const elements = document.querySelectorAll('.math-content');

52

MathJax.typeset(Array.from(elements));

53

54

// Asynchronous typesetting

55

await MathJax.typesetPromise();

56

57

// Typeset with callback

58

MathJax.typesetPromise().then(() => {

59

console.log('Typesetting complete');

60

});

61

62

// Clear mathematics from document

63

MathJax.typesetClear();

64

65

// Wait for operations to complete

66

await MathJax.done();

67

68

// Execute when ready

69

MathJax.whenReady(() => {

70

console.log('MathJax is ready');

71

});

72

```

73

74

### Dynamic Content Updates

75

76

Handle dynamically added mathematical content:

77

78

```javascript

79

// Add new math content

80

const newContent = document.createElement('div');

81

newContent.innerHTML = 'The equation is $x^2 + y^2 = z^2$.';

82

document.body.appendChild(newContent);

83

84

// Typeset only the new content

85

MathJax.typeset([newContent]);

86

87

// Or typeset the entire document

88

MathJax.typeset();

89

90

// Handle content updates with promises

91

async function updateMathContent() {

92

// Clear existing math

93

MathJax.typesetClear([targetElement]);

94

95

// Update content

96

targetElement.innerHTML = newMathExpression;

97

98

// Re-typeset

99

await MathJax.typesetPromise([targetElement]);

100

}

101

```

102

103

### Document Processing Control

104

105

Control which elements and content get processed:

106

107

```javascript

108

// Configure processing classes

109

MathJax.config.options = {

110

processHtmlClass: 'tex2jax_process',

111

ignoreHtmlClass: 'tex2jax_ignore',

112

processScriptType: 'math/tex'

113

};

114

115

// Process only specific elements

116

const mathElements = document.querySelectorAll('.contains-math');

117

MathJax.typeset(Array.from(mathElements));

118

119

// Skip specific elements

120

const elementsToSkip = document.querySelectorAll('.skip-math');

121

elementsToSkip.forEach(el => el.classList.add('tex2jax_ignore'));

122

MathJax.typeset();

123

```

124

125

## Document Configuration

126

127

### Startup Options

128

129

```javascript { .api }

130

interface StartupOptions {

131

/** Elements to process on startup */

132

elements?: Element[] | null;

133

/** Auto-typeset on ready */

134

typeset?: boolean;

135

/** Ready callback function */

136

ready?: () => void;

137

/** Page ready callback function */

138

pageReady?: () => void;

139

/** Document or document selector */

140

document?: string | Document;

141

/** Input processors to use */

142

input?: string[];

143

/** Output processor to use */

144

output?: string;

145

/** DOM adaptor to use */

146

adaptor?: string | null;

147

/** Document handler to use */

148

handler?: string | null;

149

}

150

```

151

152

**Configuration Examples:**

153

154

```javascript

155

// Browser configuration

156

window.MathJax = {

157

startup: {

158

elements: null, // Process entire document

159

typeset: true, // Auto-typeset on load

160

ready: () => {

161

console.log('MathJax startup complete');

162

},

163

pageReady: () => {

164

console.log('Page ready for typesetting');

165

}

166

}

167

};

168

169

// Node.js configuration

170

const config = {

171

startup: {

172

typeset: false, // Don't auto-typeset in Node.js

173

document: myDocument,

174

elements: specificElements

175

}

176

};

177

```

178

179

### Processing Options

180

181

```javascript { .api }

182

interface ProcessingOptions {

183

/** Elements to process */

184

elements?: Element[];

185

/** HTML class for processing */

186

processHtmlClass?: string;

187

/** HTML class to ignore */

188

ignoreHtmlClass?: string;

189

/** Script type to process */

190

processScriptType?: string;

191

/** Enable assistive MathML */

192

enableAssistiveMml?: boolean;

193

/** Compile error handler */

194

compileError?: (doc: MathDocument, math: MathItem, error: Error) => void;

195

/** Typeset error handler */

196

typesetError?: (doc: MathDocument, math: MathItem, error: Error) => void;

197

}

198

```

199

200

## Error Handling

201

202

### Processing Errors

203

204

Handle errors during document processing:

205

206

```javascript

207

// Configure error handlers

208

MathJax.config.options = {

209

compileError: (doc, math, error) => {

210

console.error('Compilation error:', error.message);

211

// Display error message in place of math

212

math.typesetRoot.innerHTML = `<span style="color:red">[${error.message}]</span>`;

213

},

214

215

typesetError: (doc, math, error) => {

216

console.error('Typesetting error:', error.message);

217

// Handle typesetting failure

218

math.typesetRoot.innerHTML = '<span style="color:red">[Typeset Error]</span>';

219

}

220

};

221

```

222

223

### Graceful Error Recovery

224

225

```javascript

226

async function safeTypeset(elements) {

227

try {

228

await MathJax.typesetPromise(elements);

229

} catch (error) {

230

console.error('Typesetting failed:', error.message);

231

232

// Fallback: try individual elements

233

if (elements) {

234

for (const element of elements) {

235

try {

236

await MathJax.typesetPromise([element]);

237

} catch (elementError) {

238

console.warn(`Failed to typeset element:`, elementError.message);

239

// Mark element with error class

240

element.classList.add('math-error');

241

}

242

}

243

}

244

}

245

}

246

```

247

248

## Performance Optimization

249

250

### Efficient Document Processing

251

252

```javascript

253

// Process only changed content

254

class MathContentManager {

255

constructor() {

256

this.processedElements = new WeakSet();

257

}

258

259

async updateElement(element) {

260

// Clear if previously processed

261

if (this.processedElements.has(element)) {

262

MathJax.typesetClear([element]);

263

}

264

265

// Process element

266

await MathJax.typesetPromise([element]);

267

this.processedElements.add(element);

268

}

269

270

async updateMultiple(elements) {

271

// Clear all elements first

272

const toProcess = elements.filter(el => this.processedElements.has(el));

273

if (toProcess.length > 0) {

274

MathJax.typesetClear(toProcess);

275

}

276

277

// Process all elements

278

await MathJax.typesetPromise(elements);

279

elements.forEach(el => this.processedElements.add(el));

280

}

281

}

282

```

283

284

### Batch Processing

285

286

```javascript

287

// Batch multiple updates

288

class BatchProcessor {

289

constructor() {

290

this.pendingElements = new Set();

291

this.timeoutId = null;

292

}

293

294

scheduleUpdate(element) {

295

this.pendingElements.add(element);

296

297

// Debounce updates

298

if (this.timeoutId) {

299

clearTimeout(this.timeoutId);

300

}

301

302

this.timeoutId = setTimeout(() => {

303

this.processBatch();

304

}, 100);

305

}

306

307

async processBatch() {

308

if (this.pendingElements.size === 0) return;

309

310

const elements = Array.from(this.pendingElements);

311

this.pendingElements.clear();

312

313

await MathJax.typesetPromise(elements);

314

}

315

}

316

```

317

318

## Advanced Document Processing

319

320

### Custom Math Discovery

321

322

```javascript

323

// Custom math finder

324

function findCustomMath(container) {

325

const mathElements = [];

326

327

// Find custom math delimiters

328

const walker = document.createTreeWalker(

329

container,

330

NodeFilter.SHOW_TEXT,

331

null,

332

false

333

);

334

335

let node;

336

while (node = walker.nextNode()) {

337

if (node.textContent.includes('{{math}}')) {

338

// Process custom math syntax

339

mathElements.push(node.parentElement);

340

}

341

}

342

343

return mathElements;

344

}

345

346

// Process custom math

347

const customMath = findCustomMath(document.body);

348

MathJax.typeset(customMath);

349

```

350

351

### Integration with Frameworks

352

353

#### React Integration

354

355

```javascript

356

import { useEffect, useRef } from 'react';

357

358

function MathComponent({ expression, display = false }) {

359

const mathRef = useRef();

360

361

useEffect(() => {

362

if (mathRef.current && window.MathJax) {

363

// Clear previous content

364

MathJax.typesetClear([mathRef.current]);

365

366

// Set new content

367

mathRef.current.innerHTML = display

368

? `$$${expression}$$`

369

: `$${expression}$`;

370

371

// Typeset new content

372

MathJax.typeset([mathRef.current]);

373

}

374

}, [expression, display]);

375

376

return <div ref={mathRef} />;

377

}

378

```

379

380

#### Vue Integration

381

382

```javascript

383

export default {

384

props: ['expression', 'display'],

385

mounted() {

386

this.renderMath();

387

},

388

updated() {

389

this.renderMath();

390

},

391

methods: {

392

async renderMath() {

393

if (this.$refs.math && window.MathJax) {

394

MathJax.typesetClear([this.$refs.math]);

395

396

const delimiter = this.display ? '$$' : '$';

397

this.$refs.math.innerHTML = `${delimiter}${this.expression}${delimiter}`;

398

399

await MathJax.typesetPromise([this.$refs.math]);

400

}

401

}

402

},

403

template: '<div ref="math"></div>'

404

};

405

```

406

407

### Progressive Enhancement

408

409

```javascript

410

// Progressive enhancement for math content

411

class MathEnhancer {

412

constructor() {

413

this.observer = new MutationObserver(this.handleMutations.bind(this));

414

}

415

416

start() {

417

// Process existing content

418

MathJax.typeset();

419

420

// Watch for new content

421

this.observer.observe(document.body, {

422

childList: true,

423

subtree: true

424

});

425

}

426

427

stop() {

428

this.observer.disconnect();

429

}

430

431

handleMutations(mutations) {

432

const elementsToProcess = new Set();

433

434

mutations.forEach(mutation => {

435

mutation.addedNodes.forEach(node => {

436

if (node.nodeType === Node.ELEMENT_NODE) {

437

// Check if element contains math

438

if (this.containsMath(node)) {

439

elementsToProcess.add(node);

440

}

441

442

// Check child elements

443

const mathElements = node.querySelectorAll('.math, .tex');

444

mathElements.forEach(el => elementsToProcess.add(el));

445

}

446

});

447

});

448

449

if (elementsToProcess.size > 0) {

450

MathJax.typeset(Array.from(elementsToProcess));

451

}

452

}

453

454

containsMath(element) {

455

const text = element.textContent || '';

456

return text.includes('$') || text.includes('\\(') || text.includes('\\[');

457

}

458

}

459

460

// Start progressive enhancement

461

const enhancer = new MathEnhancer();

462

enhancer.start();

463

```

464

465

## Document States and Lifecycle

466

467

### Processing States

468

469

MathJax processes mathematics through several states:

470

471

```javascript { .api }

472

const STATE = {

473

UNPROCESSED: 0, // Initial state

474

FINDMATH: 10, // Finding math in document

475

COMPILED: 20, // Math compiled to internal format

476

CONVERT: 100, // Converting to output format

477

METRICS: 110, // Computing metrics

478

RERENDER: 125, // Re-rendering if needed

479

TYPESET: 150, // Typesetting complete

480

INSERTED: 200, // Inserted into document

481

LAST: 10000 // Final state

482

};

483

```

484

485

### Lifecycle Hooks

486

487

```javascript

488

// Hook into processing lifecycle

489

MathJax.config.options = {

490

renderActions: {

491

findScript: [150, (doc) => {

492

// Custom script finding logic

493

console.log('Finding scripts in document');

494

}],

495

496

insertedScript: [200, (doc) => {

497

// After insertion callback

498

console.log('Math inserted into document');

499

}]

500

}

501

};

502

```

503

504

### Document Ready Events

505

506

```javascript

507

// Wait for document ready

508

MathJax.whenReady(() => {

509

console.log('MathJax is ready');

510

511

// Safe to perform operations

512

MathJax.typeset();

513

});

514

515

// Promise-based ready handling

516

const mathReady = MathJax.done();

517

mathReady.then(() => {

518

console.log('All math processing complete');

519

});

520

521

// Chained operations

522

MathJax.typesetPromise()

523

.then(() => MathJax.done())

524

.then(() => {

525

console.log('Document fully processed');

526

});

527

```