or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

binary-resolution.mdcli-utilities.mddatabase-operations.mdengine-commands.mderror-handling.mdgenerators.mdindex.mdsyntax-highlighting.mdtracing.mdutilities.md

syntax-highlighting.mddocs/

0

# Syntax Highlighting

1

2

The syntax highlighting domain provides code syntax highlighting capabilities for Prisma schemas, SQL, and TypeScript/JavaScript code, enabling rich console output and improved developer experience.

3

4

## Functions

5

6

### Prisma Schema Highlighting

7

8

#### `highlightDatamodel(str)`

9

10

Applies syntax highlighting to Prisma datamodel (schema) strings with color codes for different language elements.

11

12

```typescript { .api }

13

function highlightDatamodel(str: string): any

14

```

15

16

**Parameters:**

17

- `str: string` - Prisma datamodel string to highlight

18

19

**Returns:** `any` - String with ANSI color codes for syntax highlighting

20

21

**Highlighted Elements:**

22

- **Keywords:** `model`, `enum`, `type`, `generator`, `datasource`

23

- **Field Types:** `String`, `Int`, `Boolean`, `DateTime`, `Json`, etc.

24

- **Attributes:** `@id`, `@unique`, `@default`, `@@map`, etc.

25

- **Relations:** `@relation`

26

- **Comments:** `//` and `/* */` comments

27

- **Strings:** Quoted string values

28

- **Numbers:** Numeric literals

29

30

**Example:**

31

```typescript

32

import { highlightDatamodel } from '@prisma/internals'

33

34

const schema = `

35

model User {

36

id Int @id @default(autoincrement())

37

email String @unique

38

name String?

39

posts Post[]

40

createdAt DateTime @default(now())

41

42

@@map("users")

43

}

44

45

model Post {

46

id Int @id @default(autoincrement())

47

title String

48

content String?

49

authorId Int

50

author User @relation(fields: [authorId], references: [id])

51

}

52

`

53

54

const highlighted = highlightDatamodel(schema)

55

console.log(highlighted)

56

// Output will include color codes:

57

// - Blue for keywords (model, String, Int, etc.)

58

// - Green for attributes (@id, @unique, etc.)

59

// - Yellow for strings

60

// - Gray for comments

61

```

62

63

### SQL Highlighting

64

65

#### `highlightSql(str)`

66

67

Applies syntax highlighting to SQL query strings with appropriate color coding for SQL elements.

68

69

```typescript { .api }

70

function highlightSql(str: string): any

71

```

72

73

**Parameters:**

74

- `str: string` - SQL string to highlight

75

76

**Returns:** `any` - String with ANSI color codes for SQL syntax highlighting

77

78

**Highlighted Elements:**

79

- **Keywords:** `SELECT`, `FROM`, `WHERE`, `JOIN`, `INSERT`, `UPDATE`, `DELETE`

80

- **Functions:** `COUNT`, `SUM`, `AVG`, `MAX`, `MIN`, etc.

81

- **Operators:** `=`, `<>`, `>`, `<`, `AND`, `OR`, `NOT`

82

- **Strings:** Single-quoted string literals

83

- **Numbers:** Numeric literals

84

- **Comments:** `--` and `/* */` comments

85

- **Identifiers:** Table and column names

86

87

**Example:**

88

```typescript

89

import { highlightSql } from '@prisma/internals'

90

91

const sqlQuery = `

92

SELECT

93

u.id,

94

u.email,

95

u.name,

96

COUNT(p.id) as post_count

97

FROM users u

98

LEFT JOIN posts p ON u.id = p.author_id

99

WHERE u.created_at > '2024-01-01'

100

AND u.email LIKE '%@example.com'

101

GROUP BY u.id, u.email, u.name

102

ORDER BY post_count DESC

103

LIMIT 10;

104

`

105

106

const highlighted = highlightSql(sqlQuery)

107

console.log(highlighted)

108

// Output will include color codes:

109

// - Blue for SQL keywords (SELECT, FROM, WHERE, etc.)

110

// - Green for functions (COUNT, etc.)

111

// - Yellow for string literals

112

// - Cyan for table/column identifiers

113

```

114

115

### TypeScript/JavaScript Highlighting

116

117

#### `highlightTS(str)`

118

119

Applies syntax highlighting to TypeScript/JavaScript code strings with color coding for language constructs.

120

121

```typescript { .api }

122

function highlightTS(str: string): any

123

```

124

125

**Parameters:**

126

- `str: string` - TypeScript/JavaScript string to highlight

127

128

**Returns:** `any` - String with ANSI color codes for TypeScript/JavaScript syntax highlighting

129

130

**Highlighted Elements:**

131

- **Keywords:** `function`, `const`, `let`, `var`, `if`, `else`, `for`, `while`, `class`, `interface`, `type`

132

- **Types:** `string`, `number`, `boolean`, `object`, `any`, `void`, `undefined`

133

- **Operators:** `=`, `===`, `!==`, `=>`, `&&`, `||`, `!`

134

- **Strings:** Single and double-quoted strings, template literals

135

- **Numbers:** Numeric literals

136

- **Comments:** `//` and `/* */` comments

137

- **Built-ins:** `console`, `Promise`, `Array`, etc.

138

139

**Example:**

140

```typescript

141

import { highlightTS } from '@prisma/internals'

142

143

const code = `

144

interface User {

145

id: number;

146

email: string;

147

name?: string;

148

posts: Post[];

149

}

150

151

async function createUser(data: Omit<User, 'id'>): Promise<User> {

152

const user = await prisma.user.create({

153

data: {

154

email: data.email,

155

name: data.name || 'Anonymous'

156

},

157

include: {

158

posts: true

159

}

160

});

161

162

console.log(\`Created user: \${user.email}\`);

163

return user;

164

}

165

166

const newUser = await createUser({

167

email: 'john@example.com',

168

name: 'John Doe',

169

posts: []

170

});

171

`

172

173

const highlighted = highlightTS(code)

174

console.log(highlighted)

175

// Output will include color codes:

176

// - Purple for keywords (interface, async, function, etc.)

177

// - Blue for types (number, string, Promise, etc.)

178

// - Green for strings and template literals

179

// - Yellow for function names

180

// - Cyan for object properties

181

```

182

183

## Examples

184

185

### Code Documentation Generator

186

187

```typescript

188

import {

189

highlightDatamodel,

190

highlightSql,

191

highlightTS

192

} from '@prisma/internals'

193

194

interface CodeBlock {

195

language: 'prisma' | 'sql' | 'typescript' | 'javascript'

196

code: string

197

title?: string

198

description?: string

199

}

200

201

class DocumentationGenerator {

202

203

/**

204

* Generate highlighted code block for documentation

205

*/

206

generateCodeBlock(block: CodeBlock): string {

207

const { language, code, title, description } = block

208

209

let highlighted: string

210

211

// Apply appropriate highlighting based on language

212

switch (language) {

213

case 'prisma':

214

highlighted = highlightDatamodel(code)

215

break

216

case 'sql':

217

highlighted = highlightSql(code)

218

break

219

case 'typescript':

220

case 'javascript':

221

highlighted = highlightTS(code)

222

break

223

default:

224

highlighted = code // No highlighting for unknown languages

225

}

226

227

// Build formatted output

228

let output = ''

229

230

if (title) {

231

output += `\nπŸ“„ ${title}\n`

232

output += '='.repeat(title.length + 3) + '\n'

233

}

234

235

if (description) {

236

output += `${description}\n\n`

237

}

238

239

output += `Language: ${language.toUpperCase()}\n`

240

output += '-'.repeat(40) + '\n'

241

output += highlighted

242

output += '\n' + '-'.repeat(40) + '\n'

243

244

return output

245

}

246

247

/**

248

* Generate documentation for multiple code blocks

249

*/

250

generateDocumentation(blocks: CodeBlock[]): string {

251

return blocks

252

.map(block => this.generateCodeBlock(block))

253

.join('\n\n')

254

}

255

}

256

257

// Usage example

258

const docGen = new DocumentationGenerator()

259

260

const codeBlocks: CodeBlock[] = [

261

{

262

language: 'prisma',

263

title: 'User Model Definition',

264

description: 'Defines the User model with relations to posts',

265

code: `

266

model User {

267

id Int @id @default(autoincrement())

268

email String @unique

269

name String?

270

posts Post[]

271

profile Profile?

272

createdAt DateTime @default(now())

273

updatedAt DateTime @updatedAt

274

275

@@map("users")

276

}

277

`.trim()

278

},

279

{

280

language: 'sql',

281

title: 'User Analytics Query',

282

description: 'Retrieves user statistics with post counts',

283

code: `

284

SELECT

285

u.id,

286

u.email,

287

u.name,

288

COUNT(p.id) as total_posts,

289

MAX(p.created_at) as last_post_date

290

FROM users u

291

LEFT JOIN posts p ON u.id = p.author_id

292

GROUP BY u.id, u.email, u.name

293

HAVING COUNT(p.id) > 0

294

ORDER BY total_posts DESC;

295

`.trim()

296

},

297

{

298

language: 'typescript',

299

title: 'User Service Implementation',

300

description: 'TypeScript service for user operations',

301

code: `

302

class UserService {

303

constructor(private prisma: PrismaClient) {}

304

305

async createUser(data: CreateUserData): Promise<User> {

306

const user = await this.prisma.user.create({

307

data: {

308

email: data.email,

309

name: data.name,

310

profile: data.profile ? {

311

create: data.profile

312

} : undefined

313

},

314

include: {

315

profile: true,

316

posts: true

317

}

318

});

319

320

return user;

321

}

322

323

async getUserStats(userId: number): Promise<UserStats> {

324

const user = await this.prisma.user.findUnique({

325

where: { id: userId },

326

include: {

327

_count: {

328

select: { posts: true }

329

}

330

}

331

});

332

333

if (!user) {

334

throw new Error('User not found');

335

}

336

337

return {

338

id: user.id,

339

email: user.email,

340

postCount: user._count.posts

341

};

342

}

343

}

344

`.trim()

345

}

346

]

347

348

const documentation = docGen.generateDocumentation(codeBlocks)

349

console.log(documentation)

350

```

351

352

### Interactive Code Viewer

353

354

```typescript

355

import {

356

highlightDatamodel,

357

highlightSql,

358

highlightTS

359

} from '@prisma/internals'

360

361

interface ViewerOptions {

362

showLineNumbers?: boolean

363

wrapLongLines?: boolean

364

colorScheme?: 'dark' | 'light'

365

}

366

367

class InteractiveCodeViewer {

368

private options: ViewerOptions

369

370

constructor(options: ViewerOptions = {}) {

371

this.options = {

372

showLineNumbers: true,

373

wrapLongLines: true,

374

colorScheme: 'dark',

375

...options

376

}

377

}

378

379

/**

380

* Display code with syntax highlighting and optional line numbers

381

*/

382

displayCode(

383

code: string,

384

language: 'prisma' | 'sql' | 'typescript',

385

title?: string

386

): void {

387

// Apply syntax highlighting

388

let highlighted: string

389

switch (language) {

390

case 'prisma':

391

highlighted = highlightDatamodel(code)

392

break

393

case 'sql':

394

highlighted = highlightSql(code)

395

break

396

case 'typescript':

397

highlighted = highlightTS(code)

398

break

399

}

400

401

// Split into lines for processing

402

const lines = highlighted.split('\n')

403

404

// Display header

405

if (title) {

406

console.log(`\nπŸ” ${title}`)

407

console.log('─'.repeat(process.stdout.columns || 80))

408

}

409

410

// Display code with optional line numbers

411

lines.forEach((line, index) => {

412

let output = ''

413

414

if (this.options.showLineNumbers) {

415

const lineNum = (index + 1).toString().padStart(3, ' ')

416

output += `${lineNum} β”‚ `

417

}

418

419

output += line

420

421

// Handle long lines

422

if (this.options.wrapLongLines && output.length > (process.stdout.columns || 80)) {

423

// Simple wrapping - could be enhanced

424

console.log(output.substring(0, process.stdout.columns || 80))

425

console.log(' β”‚ ' + output.substring(process.stdout.columns || 80))

426

} else {

427

console.log(output)

428

}

429

})

430

431

console.log('─'.repeat(process.stdout.columns || 80))

432

console.log(`Language: ${language.toUpperCase()} | Lines: ${lines.length}`)

433

}

434

435

/**

436

* Compare two code blocks side by side

437

*/

438

compareCode(

439

leftCode: string,

440

rightCode: string,

441

leftLanguage: 'prisma' | 'sql' | 'typescript',

442

rightLanguage: 'prisma' | 'sql' | 'typescript',

443

leftTitle = 'Before',

444

rightTitle = 'After'

445

): void {

446

const leftHighlighted = this.highlightByLanguage(leftCode, leftLanguage)

447

const rightHighlighted = this.highlightByLanguage(rightCode, rightLanguage)

448

449

const leftLines = leftHighlighted.split('\n')

450

const rightLines = rightHighlighted.split('\n')

451

const maxLines = Math.max(leftLines.length, rightLines.length)

452

const halfWidth = Math.floor((process.stdout.columns || 80) / 2) - 2

453

454

console.log(`\n${leftTitle.padEnd(halfWidth)} β”‚ ${rightTitle}`)

455

console.log('─'.repeat(halfWidth) + 'β”Ό' + '─'.repeat(halfWidth))

456

457

for (let i = 0; i < maxLines; i++) {

458

const leftLine = (leftLines[i] || '').substring(0, halfWidth).padEnd(halfWidth)

459

const rightLine = (rightLines[i] || '').substring(0, halfWidth)

460

461

console.log(`${leftLine} β”‚ ${rightLine}`)

462

}

463

464

console.log('─'.repeat(halfWidth) + 'β”΄' + '─'.repeat(halfWidth))

465

}

466

467

private highlightByLanguage(

468

code: string,

469

language: 'prisma' | 'sql' | 'typescript'

470

): string {

471

switch (language) {

472

case 'prisma':

473

return highlightDatamodel(code)

474

case 'sql':

475

return highlightSql(code)

476

case 'typescript':

477

return highlightTS(code)

478

default:

479

return code

480

}

481

}

482

}

483

484

// Usage

485

const viewer = new InteractiveCodeViewer({

486

showLineNumbers: true,

487

wrapLongLines: true,

488

colorScheme: 'dark'

489

})

490

491

// Display Prisma schema

492

viewer.displayCode(`

493

model User {

494

id Int @id @default(autoincrement())

495

email String @unique

496

posts Post[]

497

}

498

499

model Post {

500

id Int @id @default(autoincrement())

501

title String

502

authorId Int

503

author User @relation(fields: [authorId], references: [id])

504

}

505

`, 'prisma', 'Database Schema')

506

507

// Compare SQL queries

508

viewer.compareCode(

509

`SELECT * FROM users WHERE active = true`,

510

`SELECT id, email, name FROM users WHERE active = true AND verified = true`,

511

'sql',

512

'sql',

513

'Original Query',

514

'Optimized Query'

515

)

516

```

517

518

### Code Quality Reporter

519

520

```typescript

521

import {

522

highlightDatamodel,

523

highlightSql,

524

highlightTS

525

} from '@prisma/internals'

526

527

interface CodeIssue {

528

line: number

529

column: number

530

severity: 'error' | 'warning' | 'info'

531

message: string

532

rule?: string

533

}

534

535

interface AnalysisResult {

536

code: string

537

language: 'prisma' | 'sql' | 'typescript'

538

issues: CodeIssue[]

539

score: number

540

}

541

542

class CodeQualityReporter {

543

544

/**

545

* Generate quality report with highlighted code and issues

546

*/

547

generateReport(result: AnalysisResult): void {

548

const { code, language, issues, score } = result

549

550

console.log('\nπŸ“Š Code Quality Report')

551

console.log('═'.repeat(50))

552

553

// Overall score

554

const scoreColor = score >= 80 ? '🟒' : score >= 60 ? '🟑' : 'πŸ”΄'

555

console.log(`${scoreColor} Quality Score: ${score}/100`)

556

console.log(`πŸ“ Language: ${language.toUpperCase()}`)

557

console.log(`⚠️ Issues Found: ${issues.length}`)

558

console.log()

559

560

// Issue summary

561

const errors = issues.filter(i => i.severity === 'error').length

562

const warnings = issues.filter(i => i.severity === 'warning').length

563

const infos = issues.filter(i => i.severity === 'info').length

564

565

if (issues.length > 0) {

566

console.log('πŸ“‹ Issue Summary:')

567

if (errors > 0) console.log(` πŸ”΄ Errors: ${errors}`)

568

if (warnings > 0) console.log(` 🟑 Warnings: ${warnings}`)

569

if (infos > 0) console.log(` πŸ”΅ Info: ${infos}`)

570

console.log()

571

}

572

573

// Highlighted code with issue markers

574

console.log('πŸ“„ Code with Issues:')

575

console.log('─'.repeat(50))

576

577

let highlighted: string

578

switch (language) {

579

case 'prisma':

580

highlighted = highlightDatamodel(code)

581

break

582

case 'sql':

583

highlighted = highlightSql(code)

584

break

585

case 'typescript':

586

highlighted = highlightTS(code)

587

break

588

}

589

590

const lines = highlighted.split('\n')

591

592

lines.forEach((line, index) => {

593

const lineNumber = index + 1

594

const lineIssues = issues.filter(issue => issue.line === lineNumber)

595

596

// Display line with number

597

const lineNumStr = lineNumber.toString().padStart(3, ' ')

598

let prefix = ' '

599

600

if (lineIssues.length > 0) {

601

const maxSeverity = lineIssues.reduce((max, issue) => {

602

if (issue.severity === 'error') return 'error'

603

if (max === 'error') return max

604

if (issue.severity === 'warning') return 'warning'

605

return issue.severity

606

}, 'info' as const)

607

608

switch (maxSeverity) {

609

case 'error':

610

prefix = 'πŸ”΄ '

611

break

612

case 'warning':

613

prefix = '🟑 '

614

break

615

case 'info':

616

prefix = 'πŸ”΅ '

617

break

618

}

619

}

620

621

console.log(`${prefix}${lineNumStr} β”‚ ${line}`)

622

623

// Display issues for this line

624

lineIssues.forEach(issue => {

625

const indent = ' '.repeat(7 + issue.column)

626

const marker = '^'.repeat(Math.min(issue.message.length, 20))

627

console.log(`${indent}${marker}`)

628

629

const severityIcon = {

630

error: 'πŸ”΄',

631

warning: '🟑',

632

info: 'πŸ”΅'

633

}[issue.severity]

634

635

console.log(`${indent}${severityIcon} ${issue.message}`)

636

if (issue.rule) {

637

console.log(`${indent} Rule: ${issue.rule}`)

638

}

639

})

640

})

641

642

console.log('─'.repeat(50))

643

644

// Recommendations

645

if (issues.length > 0) {

646

console.log('\nπŸ’‘ Recommendations:')

647

const uniqueRules = [...new Set(issues.map(i => i.rule).filter(Boolean))]

648

uniqueRules.forEach(rule => {

649

console.log(` β€’ Review rule: ${rule}`)

650

})

651

652

if (errors > 0) {

653

console.log(' β€’ Fix all errors before deployment')

654

}

655

if (warnings > 5) {

656

console.log(' β€’ Consider addressing warnings to improve code quality')

657

}

658

} else {

659

console.log('\nβœ… No issues found - great job!')

660

}

661

}

662

}

663

664

// Usage

665

const reporter = new CodeQualityReporter()

666

667

const analysisResult: AnalysisResult = {

668

code: `

669

model User {

670

id Int @id @default(autoincrement())

671

email String @unique

672

password String // Should be hashed

673

posts Post[]

674

}

675

676

model Post {

677

id Int @id @default(autoincrement())

678

title String

679

authorId Int

680

author User @relation(fields: [authorId], references: [id])

681

}

682

`.trim(),

683

language: 'prisma',

684

issues: [

685

{

686

line: 4,

687

column: 12,

688

severity: 'warning',

689

message: 'Password field should include @db.Text for longer hashes',

690

rule: 'password-field-type'

691

},

692

{

693

line: 11,

694

column: 3,

695

severity: 'info',

696

message: 'Consider adding cascade delete behavior',

697

rule: 'relation-delete-behavior'

698

}

699

],

700

score: 85

701

}

702

703

reporter.generateReport(analysisResult)

704

```