or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

editor-core.mdindex.mdlanguages-and-providers.mdmodels-and-uris.mdother-languages.mdtypescript-language.mdworkers-and-environment.md

other-languages.mddocs/

0

# Other Language Services

1

2

JSON schema validation, CSS/SCSS/Less support, and HTML/Handlebars language features in Monaco Editor.

3

4

## JSON Language Service

5

6

Monaco provides comprehensive JSON support with schema validation and IntelliSense.

7

8

### Core Import

9

10

```typescript

11

import * as monaco from 'monaco-editor';

12

13

// Access JSON defaults

14

const jsonDefaults = monaco.languages.json.jsonDefaults;

15

```

16

17

### JSON Configuration

18

19

```typescript { .api }

20

monaco.languages.json.jsonDefaults: LanguageServiceDefaults

21

```

22

23

Configuration object for JSON language service.

24

25

### Diagnostics Options

26

27

```typescript { .api }

28

jsonDefaults.setDiagnosticsOptions(options: DiagnosticsOptions): void

29

```

30

31

Configures JSON validation and diagnostics.

32

33

```typescript { .api }

34

interface DiagnosticsOptions {

35

validate?: boolean;

36

allowComments?: boolean;

37

schemas?: JSONSchema[];

38

enableSchemaRequest?: boolean;

39

hoverSettings?: HoverSettings;

40

completionSettings?: CompletionSettings;

41

}

42

```

43

44

```typescript

45

// Configure JSON validation

46

monaco.languages.json.jsonDefaults.setDiagnosticsOptions({

47

validate: true,

48

allowComments: false,

49

schemas: [

50

{

51

uri: 'http://json-schema.org/draft-07/schema#',

52

fileMatch: ['*'],

53

schema: {

54

type: 'object',

55

properties: {

56

name: { type: 'string' },

57

version: { type: 'string' },

58

dependencies: {

59

type: 'object',

60

additionalProperties: { type: 'string' }

61

}

62

}

63

}

64

}

65

],

66

enableSchemaRequest: true

67

});

68

```

69

70

### JSON Schema Support

71

72

```typescript { .api }

73

interface JSONSchema {

74

uri: string;

75

fileMatch?: string[];

76

schema?: any;

77

}

78

```

79

80

```typescript

81

// Package.json schema example

82

const packageJsonSchema = {

83

uri: 'http://json.schemastore.org/package',

84

fileMatch: ['package.json'],

85

schema: {

86

type: 'object',

87

properties: {

88

name: {

89

type: 'string',

90

description: 'The name of the package'

91

},

92

version: {

93

type: 'string',

94

pattern: '^\\d+\\.\\d+\\.\\d+',

95

description: 'Version must be a valid semver string'

96

},

97

main: {

98

type: 'string',

99

description: 'The main entry point'

100

},

101

scripts: {

102

type: 'object',

103

additionalProperties: {

104

type: 'string'

105

},

106

description: 'Script commands'

107

},

108

dependencies: {

109

type: 'object',

110

additionalProperties: {

111

type: 'string'

112

},

113

description: 'Package dependencies'

114

},

115

devDependencies: {

116

type: 'object',

117

additionalProperties: {

118

type: 'string'

119

},

120

description: 'Development dependencies'

121

}

122

},

123

required: ['name', 'version']

124

}

125

};

126

127

monaco.languages.json.jsonDefaults.setDiagnosticsOptions({

128

validate: true,

129

schemas: [packageJsonSchema]

130

});

131

```

132

133

### JSON Model Creation

134

135

```typescript

136

// Create a JSON model with schema validation

137

const packageJsonModel = monaco.editor.createModel(`{

138

"name": "my-project",

139

"version": "1.0.0",

140

"main": "index.js",

141

"scripts": {

142

"start": "node index.js",

143

"test": "jest"

144

},

145

"dependencies": {

146

"express": "^4.18.0"

147

},

148

"devDependencies": {

149

"jest": "^28.0.0"

150

}

151

}`, 'json', monaco.Uri.parse('file:///package.json'));

152

```

153

154

## CSS Language Service

155

156

Monaco supports CSS, SCSS, and Less with IntelliSense and validation.

157

158

### Core Import

159

160

```typescript

161

// Access CSS defaults

162

const cssDefaults = monaco.languages.css.cssDefaults;

163

const scssDefaults = monaco.languages.css.scssDefaults;

164

const lessDefaults = monaco.languages.css.lessDefaults;

165

```

166

167

### CSS Configuration

168

169

```typescript { .api }

170

cssDefaults.setOptions(options: LanguageServiceOptions): void

171

```

172

173

Configures CSS language service options.

174

175

```typescript { .api }

176

interface LanguageServiceOptions {

177

validate?: boolean;

178

lint?: LintSettings;

179

data?: CSSDataConfiguration;

180

hoverSettings?: HoverSettings;

181

completionSettings?: CompletionSettings;

182

}

183

```

184

185

```typescript

186

// Configure CSS options

187

monaco.languages.css.cssDefaults.setOptions({

188

validate: true,

189

lint: {

190

compatibleVendorPrefixes: 'ignore',

191

vendorPrefix: 'warning',

192

duplicateProperties: 'warning',

193

emptyRules: 'warning',

194

importStatemements: 'ignore',

195

boxModel: 'ignore',

196

universalSelector: 'ignore',

197

zeroUnits: 'ignore',

198

fontFaceProperties: 'warning',

199

hexColorLength: 'error',

200

argumentsInColorFunction: 'error',

201

unknownProperties: 'warning',

202

ieHack: 'ignore',

203

unknownVendorSpecificProperties: 'ignore',

204

propertyIgnoredDueToDisplay: 'warning',

205

important: 'ignore',

206

float: 'ignore',

207

idSelector: 'ignore'

208

}

209

});

210

211

// Configure SCSS options

212

monaco.languages.css.scssDefaults.setOptions({

213

validate: true,

214

lint: {

215

// SCSS-specific lint rules

216

unknownAtRules: 'ignore' // Allow SCSS @rules

217

}

218

});

219

220

// Configure Less options

221

monaco.languages.css.lessDefaults.setOptions({

222

validate: true,

223

lint: {

224

// Less-specific lint rules

225

unknownAtRules: 'ignore' // Allow Less @rules

226

}

227

});

228

```

229

230

### CSS Custom Data

231

232

```typescript { .api }

233

interface CSSDataConfiguration {

234

version: 1;

235

properties?: IPropertyData[];

236

atDirectives?: IAtDirectiveData[];

237

pseudoClasses?: IPseudoClassData[];

238

pseudoElements?: IPseudoElementData[];

239

}

240

```

241

242

```typescript

243

// Add custom CSS properties

244

const customCSSData = {

245

version: 1,

246

properties: [

247

{

248

name: '--primary-color',

249

description: 'Primary theme color',

250

browsers: ['FF', 'S', 'C', 'IE', 'E', 'O']

251

},

252

{

253

name: '--secondary-color',

254

description: 'Secondary theme color',

255

browsers: ['FF', 'S', 'C', 'IE', 'E', 'O']

256

}

257

],

258

atDirectives: [

259

{

260

name: '@custom-media',

261

description: 'Define custom media queries',

262

browsers: ['FF', 'S', 'C']

263

}

264

]

265

};

266

267

monaco.languages.css.cssDefaults.setOptions({

268

data: customCSSData

269

});

270

```

271

272

### CSS Model Examples

273

274

```typescript

275

// CSS model

276

const cssModel = monaco.editor.createModel(`

277

:root {

278

--primary-color: #3498db;

279

--secondary-color: #2ecc71;

280

--font-size: 16px;

281

}

282

283

.container {

284

max-width: 1200px;

285

margin: 0 auto;

286

padding: 20px;

287

font-size: var(--font-size);

288

}

289

290

.button {

291

background-color: var(--primary-color);

292

color: white;

293

border: none;

294

padding: 10px 20px;

295

border-radius: 4px;

296

cursor: pointer;

297

transition: background-color 0.3s ease;

298

}

299

300

.button:hover {

301

background-color: var(--secondary-color);

302

}

303

304

@media (max-width: 768px) {

305

.container {

306

padding: 10px;

307

}

308

}

309

`, 'css', monaco.Uri.parse('file:///styles.css'));

310

311

// SCSS model

312

const scssModel = monaco.editor.createModel(`

313

$primary-color: #3498db;

314

$secondary-color: #2ecc71;

315

$border-radius: 4px;

316

317

%button-base {

318

border: none;

319

padding: 10px 20px;

320

border-radius: $border-radius;

321

cursor: pointer;

322

transition: background-color 0.3s ease;

323

}

324

325

.button {

326

@extend %button-base;

327

background-color: $primary-color;

328

color: white;

329

330

&:hover {

331

background-color: darken($primary-color, 10%);

332

}

333

334

&.secondary {

335

background-color: $secondary-color;

336

337

&:hover {

338

background-color: darken($secondary-color, 10%);

339

}

340

}

341

}

342

343

@mixin respond-to($breakpoint) {

344

@if $breakpoint == mobile {

345

@media (max-width: 768px) { @content; }

346

}

347

@if $breakpoint == tablet {

348

@media (min-width: 769px) and (max-width: 1024px) { @content; }

349

}

350

}

351

352

.container {

353

max-width: 1200px;

354

margin: 0 auto;

355

padding: 20px;

356

357

@include respond-to(mobile) {

358

padding: 10px;

359

}

360

}

361

`, 'scss', monaco.Uri.parse('file:///styles.scss'));

362

363

// Less model

364

const lessModel = monaco.editor.createModel(`

365

@primary-color: #3498db;

366

@secondary-color: #2ecc71;

367

@border-radius: 4px;

368

369

.button-mixin(@bg-color) {

370

background-color: @bg-color;

371

border: none;

372

padding: 10px 20px;

373

border-radius: @border-radius;

374

cursor: pointer;

375

transition: background-color 0.3s ease;

376

377

&:hover {

378

background-color: darken(@bg-color, 10%);

379

}

380

}

381

382

.button {

383

.button-mixin(@primary-color);

384

color: white;

385

386

&.secondary {

387

.button-mixin(@secondary-color);

388

}

389

}

390

391

.container {

392

max-width: 1200px;

393

margin: 0 auto;

394

padding: 20px;

395

396

@media (max-width: 768px) {

397

padding: 10px;

398

}

399

}

400

`, 'less', monaco.Uri.parse('file:///styles.less'));

401

```

402

403

## HTML Language Service

404

405

Monaco provides HTML support with tag completion, attribute validation, and embedded CSS/JavaScript.

406

407

### Core Import

408

409

```typescript

410

// Access HTML defaults

411

const htmlDefaults = monaco.languages.html.htmlDefaults;

412

const handlebarsDefaults = monaco.languages.html.handlebarDefaults;

413

const razorDefaults = monaco.languages.html.razorDefaults;

414

```

415

416

### HTML Configuration

417

418

```typescript { .api }

419

htmlDefaults.setOptions(options: HTMLLanguageServiceOptions): void

420

```

421

422

Configures HTML language service options.

423

424

```typescript { .api }

425

interface HTMLLanguageServiceOptions {

426

format?: HTMLFormatConfiguration;

427

suggest?: HTMLSuggestOptions;

428

data?: HTMLDataConfiguration;

429

}

430

```

431

432

```typescript

433

// Configure HTML options

434

monaco.languages.html.htmlDefaults.setOptions({

435

format: {

436

tabSize: 2,

437

insertSpaces: true,

438

wrapLineLength: 120,

439

unformatted: 'default',

440

contentUnformatted: 'pre,code,textarea',

441

indentInnerHtml: false,

442

preserveNewLines: true,

443

maxPreserveNewLines: 2,

444

indentHandlebars: false,

445

endWithNewline: false,

446

extraLiners: 'head, body, /html'

447

},

448

suggest: {

449

html5: true,

450

angular1: false,

451

ionic: false

452

}

453

});

454

```

455

456

### HTML Custom Data

457

458

```typescript { .api }

459

interface HTMLDataConfiguration {

460

version: 1;

461

tags?: ITagData[];

462

attributes?: IAttributeData[];

463

valueSets?: IValueSet[];

464

}

465

```

466

467

```typescript

468

// Add custom HTML elements and attributes

469

const customHTMLData = {

470

version: 1,

471

tags: [

472

{

473

name: 'my-component',

474

description: 'Custom component',

475

attributes: [

476

{

477

name: 'prop1',

478

description: 'First property',

479

valueSet: 'string'

480

},

481

{

482

name: 'prop2',

483

description: 'Second property',

484

valueSet: 'boolean'

485

}

486

]

487

}

488

],

489

attributes: [

490

{

491

name: 'data-testid',

492

description: 'Test identifier for automated testing',

493

valueSet: 'string'

494

}

495

]

496

};

497

498

monaco.languages.html.htmlDefaults.setOptions({

499

data: customHTMLData

500

});

501

```

502

503

### HTML Model Examples

504

505

```typescript

506

// HTML model

507

const htmlModel = monaco.editor.createModel(`

508

<!DOCTYPE html>

509

<html lang="en">

510

<head>

511

<meta charset="UTF-8">

512

<meta name="viewport" content="width=device-width, initial-scale=1.0">

513

<title>Monaco Editor Example</title>

514

<style>

515

body {

516

font-family: Arial, sans-serif;

517

margin: 0;

518

padding: 20px;

519

}

520

.container {

521

max-width: 800px;

522

margin: 0 auto;

523

}

524

</style>

525

</head>

526

<body>

527

<div class="container">

528

<h1>Welcome to Monaco Editor</h1>

529

<p>This is a demonstration of HTML editing capabilities.</p>

530

<my-component prop1="value1" prop2="true" data-testid="demo-component">

531

<span>Custom component content</span>

532

</my-component>

533

<button onclick="handleClick()">Click me</button>

534

</div>

535

536

<script>

537

function handleClick() {

538

alert('Button clicked!');

539

}

540

</script>

541

</body>

542

</html>

543

`, 'html', monaco.Uri.parse('file:///index.html'));

544

545

// Handlebars model

546

const handlebarsModel = monaco.editor.createModel(`

547

<!DOCTYPE html>

548

<html>

549

<head>

550

<title>{{title}}</title>

551

</head>

552

<body>

553

<h1>{{heading}}</h1>

554

555

{{#if user}}

556

<p>Welcome, {{user.name}}!</p>

557

<p>Email: {{user.email}}</p>

558

{{else}}

559

<p>Please log in.</p>

560

{{/if}}

561

562

<ul>

563

{{#each items}}

564

<li>

565

<strong>{{this.name}}</strong>

566

{{#if this.description}}

567

- {{this.description}}

568

{{/if}}

569

</li>

570

{{/each}}

571

</ul>

572

573

{{> footer}}

574

</body>

575

</html>

576

`, 'handlebars', monaco.Uri.parse('file:///template.hbs'));

577

```

578

579

## Language Service Features

580

581

All language services provide common IntelliSense features:

582

583

### Code Completion

584

- Tag and attribute completion for HTML

585

- Property and value completion for CSS

586

- Schema-based completion for JSON

587

588

### Validation

589

- Syntax error detection

590

- Schema validation for JSON

591

- CSS property validation

592

- HTML tag and attribute validation

593

594

### Hover Information

595

- Property descriptions

596

- Value information

597

- Schema documentation

598

599

### Formatting

600

- Automatic indentation

601

- Code beautification

602

- Configurable formatting rules

603

604

### Color Support

605

- Color decorations in CSS

606

- Color picker integration

607

- Color format conversion

608

609

## Worker Configuration

610

611

Language services run in web workers for performance:

612

613

```typescript

614

self.MonacoEnvironment = {

615

getWorkerUrl: function (moduleId, label) {

616

if (label === 'json') {

617

return './json.worker.bundle.js';

618

}

619

if (label === 'css' || label === 'scss' || label === 'less') {

620

return './css.worker.bundle.js';

621

}

622

if (label === 'html' || label === 'handlebars' || label === 'razor') {

623

return './html.worker.bundle.js';

624

}

625

return './editor.worker.bundle.js';

626

}

627

};

628

```

629

630

## Complete Example

631

632

```typescript

633

// Configure all language services

634

monaco.languages.json.jsonDefaults.setDiagnosticsOptions({

635

validate: true,

636

allowComments: true,

637

schemas: [

638

{

639

uri: 'http://json-schema.org/package',

640

fileMatch: ['package.json'],

641

schema: packageJsonSchema

642

}

643

]

644

});

645

646

monaco.languages.css.cssDefaults.setOptions({

647

validate: true,

648

lint: {

649

duplicateProperties: 'warning',

650

unknownProperties: 'warning'

651

}

652

});

653

654

monaco.languages.html.htmlDefaults.setOptions({

655

format: {

656

tabSize: 2,

657

insertSpaces: true

658

},

659

suggest: {

660

html5: true

661

}

662

});

663

664

// Create models for different languages

665

const models = [

666

monaco.editor.createModel(jsonContent, 'json', monaco.Uri.parse('file:///config.json')),

667

monaco.editor.createModel(cssContent, 'css', monaco.Uri.parse('file:///styles.css')),

668

monaco.editor.createModel(htmlContent, 'html', monaco.Uri.parse('file:///index.html'))

669

];

670

671

// Create editor and switch between models

672

const editor = monaco.editor.create(document.getElementById('container'));

673

editor.setModel(models[0]); // Start with JSON

674

```