CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-monaco-editor

A browser based code editor that powers Visual Studio Code

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

other-languages.mddocs/

Other Language Services

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

JSON Language Service

Monaco provides comprehensive JSON support with schema validation and IntelliSense.

Core Import

import * as monaco from 'monaco-editor';

// Access JSON defaults
const jsonDefaults = monaco.languages.json.jsonDefaults;

JSON Configuration

monaco.languages.json.jsonDefaults: LanguageServiceDefaults

Configuration object for JSON language service.

Diagnostics Options

jsonDefaults.setDiagnosticsOptions(options: DiagnosticsOptions): void

Configures JSON validation and diagnostics.

interface DiagnosticsOptions {
    validate?: boolean;
    allowComments?: boolean;
    schemas?: JSONSchema[];
    enableSchemaRequest?: boolean;
    hoverSettings?: HoverSettings;
    completionSettings?: CompletionSettings;
}
// Configure JSON validation
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
    validate: true,
    allowComments: false,
    schemas: [
        {
            uri: 'http://json-schema.org/draft-07/schema#',
            fileMatch: ['*'],
            schema: {
                type: 'object',
                properties: {
                    name: { type: 'string' },
                    version: { type: 'string' },
                    dependencies: {
                        type: 'object',
                        additionalProperties: { type: 'string' }
                    }
                }
            }
        }
    ],
    enableSchemaRequest: true
});

JSON Schema Support

interface JSONSchema {
    uri: string;
    fileMatch?: string[];
    schema?: any;
}
// Package.json schema example
const packageJsonSchema = {
    uri: 'http://json.schemastore.org/package',
    fileMatch: ['package.json'],
    schema: {
        type: 'object',
        properties: {
            name: {
                type: 'string',
                description: 'The name of the package'
            },
            version: {
                type: 'string',
                pattern: '^\\d+\\.\\d+\\.\\d+',
                description: 'Version must be a valid semver string'
            },
            main: {
                type: 'string',
                description: 'The main entry point'
            },
            scripts: {
                type: 'object',
                additionalProperties: {
                    type: 'string'
                },
                description: 'Script commands'
            },
            dependencies: {
                type: 'object',
                additionalProperties: {
                    type: 'string'
                },
                description: 'Package dependencies'
            },
            devDependencies: {
                type: 'object',
                additionalProperties: {
                    type: 'string'
                },
                description: 'Development dependencies'
            }
        },
        required: ['name', 'version']
    }
};

monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
    validate: true,
    schemas: [packageJsonSchema]
});

JSON Model Creation

// Create a JSON model with schema validation
const packageJsonModel = monaco.editor.createModel(`{
    "name": "my-project",
    "version": "1.0.0",
    "main": "index.js",
    "scripts": {
        "start": "node index.js",
        "test": "jest"
    },
    "dependencies": {
        "express": "^4.18.0"
    },
    "devDependencies": {
        "jest": "^28.0.0"
    }
}`, 'json', monaco.Uri.parse('file:///package.json'));

CSS Language Service

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

Core Import

// Access CSS defaults
const cssDefaults = monaco.languages.css.cssDefaults;
const scssDefaults = monaco.languages.css.scssDefaults;
const lessDefaults = monaco.languages.css.lessDefaults;

CSS Configuration

cssDefaults.setOptions(options: LanguageServiceOptions): void

Configures CSS language service options.

interface LanguageServiceOptions {
    validate?: boolean;
    lint?: LintSettings;
    data?: CSSDataConfiguration;
    hoverSettings?: HoverSettings;
    completionSettings?: CompletionSettings;
}
// Configure CSS options
monaco.languages.css.cssDefaults.setOptions({
    validate: true,
    lint: {
        compatibleVendorPrefixes: 'ignore',
        vendorPrefix: 'warning',
        duplicateProperties: 'warning',
        emptyRules: 'warning',
        importStatemements: 'ignore',
        boxModel: 'ignore',
        universalSelector: 'ignore',
        zeroUnits: 'ignore',
        fontFaceProperties: 'warning',
        hexColorLength: 'error',
        argumentsInColorFunction: 'error',
        unknownProperties: 'warning',
        ieHack: 'ignore',
        unknownVendorSpecificProperties: 'ignore',
        propertyIgnoredDueToDisplay: 'warning',
        important: 'ignore',
        float: 'ignore',
        idSelector: 'ignore'
    }
});

// Configure SCSS options
monaco.languages.css.scssDefaults.setOptions({
    validate: true,
    lint: {
        // SCSS-specific lint rules
        unknownAtRules: 'ignore' // Allow SCSS @rules
    }
});

// Configure Less options  
monaco.languages.css.lessDefaults.setOptions({
    validate: true,
    lint: {
        // Less-specific lint rules
        unknownAtRules: 'ignore' // Allow Less @rules
    }
});

CSS Custom Data

interface CSSDataConfiguration {
    version: 1;
    properties?: IPropertyData[];
    atDirectives?: IAtDirectiveData[];
    pseudoClasses?: IPseudoClassData[];
    pseudoElements?: IPseudoElementData[];
}
// Add custom CSS properties
const customCSSData = {
    version: 1,
    properties: [
        {
            name: '--primary-color',
            description: 'Primary theme color',
            browsers: ['FF', 'S', 'C', 'IE', 'E', 'O']
        },
        {
            name: '--secondary-color', 
            description: 'Secondary theme color',
            browsers: ['FF', 'S', 'C', 'IE', 'E', 'O']
        }
    ],
    atDirectives: [
        {
            name: '@custom-media',
            description: 'Define custom media queries',
            browsers: ['FF', 'S', 'C']
        }
    ]
};

monaco.languages.css.cssDefaults.setOptions({
    data: customCSSData
});

CSS Model Examples

// CSS model
const cssModel = monaco.editor.createModel(`
:root {
    --primary-color: #3498db;
    --secondary-color: #2ecc71;
    --font-size: 16px;
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
    font-size: var(--font-size);
}

.button {
    background-color: var(--primary-color);
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

.button:hover {
    background-color: var(--secondary-color);
}

@media (max-width: 768px) {
    .container {
        padding: 10px;
    }
}
`, 'css', monaco.Uri.parse('file:///styles.css'));

// SCSS model
const scssModel = monaco.editor.createModel(`
$primary-color: #3498db;
$secondary-color: #2ecc71;
$border-radius: 4px;

%button-base {
    border: none;
    padding: 10px 20px;
    border-radius: $border-radius;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

.button {
    @extend %button-base;
    background-color: $primary-color;
    color: white;
    
    &:hover {
        background-color: darken($primary-color, 10%);
    }
    
    &.secondary {
        background-color: $secondary-color;
        
        &:hover {
            background-color: darken($secondary-color, 10%);
        }
    }
}

@mixin respond-to($breakpoint) {
    @if $breakpoint == mobile {
        @media (max-width: 768px) { @content; }
    }
    @if $breakpoint == tablet {
        @media (min-width: 769px) and (max-width: 1024px) { @content; }
    }
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
    
    @include respond-to(mobile) {
        padding: 10px;
    }
}
`, 'scss', monaco.Uri.parse('file:///styles.scss'));

// Less model
const lessModel = monaco.editor.createModel(`
@primary-color: #3498db;
@secondary-color: #2ecc71;
@border-radius: 4px;

.button-mixin(@bg-color) {
    background-color: @bg-color;
    border: none;
    padding: 10px 20px;
    border-radius: @border-radius;
    cursor: pointer;
    transition: background-color 0.3s ease;
    
    &:hover {
        background-color: darken(@bg-color, 10%);
    }
}

.button {
    .button-mixin(@primary-color);
    color: white;
    
    &.secondary {
        .button-mixin(@secondary-color);
    }
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
    
    @media (max-width: 768px) {
        padding: 10px;
    }
}
`, 'less', monaco.Uri.parse('file:///styles.less'));

HTML Language Service

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

Core Import

// Access HTML defaults
const htmlDefaults = monaco.languages.html.htmlDefaults;
const handlebarsDefaults = monaco.languages.html.handlebarDefaults;
const razorDefaults = monaco.languages.html.razorDefaults;

HTML Configuration

htmlDefaults.setOptions(options: HTMLLanguageServiceOptions): void

Configures HTML language service options.

interface HTMLLanguageServiceOptions {
    format?: HTMLFormatConfiguration;
    suggest?: HTMLSuggestOptions;
    data?: HTMLDataConfiguration;
}
// Configure HTML options
monaco.languages.html.htmlDefaults.setOptions({
    format: {
        tabSize: 2,
        insertSpaces: true,
        wrapLineLength: 120,
        unformatted: 'default',
        contentUnformatted: 'pre,code,textarea',
        indentInnerHtml: false,
        preserveNewLines: true,
        maxPreserveNewLines: 2,
        indentHandlebars: false,
        endWithNewline: false,
        extraLiners: 'head, body, /html'
    },
    suggest: {
        html5: true,
        angular1: false,
        ionic: false
    }
});

HTML Custom Data

interface HTMLDataConfiguration {
    version: 1;
    tags?: ITagData[];
    attributes?: IAttributeData[];
    valueSets?: IValueSet[];
}
// Add custom HTML elements and attributes
const customHTMLData = {
    version: 1,
    tags: [
        {
            name: 'my-component',
            description: 'Custom component',
            attributes: [
                {
                    name: 'prop1',
                    description: 'First property',
                    valueSet: 'string'
                },
                {
                    name: 'prop2',
                    description: 'Second property',
                    valueSet: 'boolean'
                }
            ]
        }
    ],
    attributes: [
        {
            name: 'data-testid',
            description: 'Test identifier for automated testing',
            valueSet: 'string'
        }
    ]
};

monaco.languages.html.htmlDefaults.setOptions({
    data: customHTMLData
});

HTML Model Examples

// HTML model
const htmlModel = monaco.editor.createModel(`
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Monaco Editor Example</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Welcome to Monaco Editor</h1>
        <p>This is a demonstration of HTML editing capabilities.</p>
        <my-component prop1="value1" prop2="true" data-testid="demo-component">
            <span>Custom component content</span>
        </my-component>
        <button onclick="handleClick()">Click me</button>
    </div>
    
    <script>
        function handleClick() {
            alert('Button clicked!');
        }
    </script>
</body>
</html>
`, 'html', monaco.Uri.parse('file:///index.html'));

// Handlebars model
const handlebarsModel = monaco.editor.createModel(`
<!DOCTYPE html>
<html>
<head>
    <title>{{title}}</title>
</head>
<body>
    <h1>{{heading}}</h1>
    
    {{#if user}}
        <p>Welcome, {{user.name}}!</p>
        <p>Email: {{user.email}}</p>
    {{else}}
        <p>Please log in.</p>
    {{/if}}
    
    <ul>
        {{#each items}}
            <li>
                <strong>{{this.name}}</strong>
                {{#if this.description}}
                    - {{this.description}}
                {{/if}}
            </li>
        {{/each}}
    </ul>
    
    {{> footer}}
</body>
</html>
`, 'handlebars', monaco.Uri.parse('file:///template.hbs'));

Language Service Features

All language services provide common IntelliSense features:

Code Completion

  • Tag and attribute completion for HTML
  • Property and value completion for CSS
  • Schema-based completion for JSON

Validation

  • Syntax error detection
  • Schema validation for JSON
  • CSS property validation
  • HTML tag and attribute validation

Hover Information

  • Property descriptions
  • Value information
  • Schema documentation

Formatting

  • Automatic indentation
  • Code beautification
  • Configurable formatting rules

Color Support

  • Color decorations in CSS
  • Color picker integration
  • Color format conversion

Worker Configuration

Language services run in web workers for performance:

self.MonacoEnvironment = {
    getWorkerUrl: function (moduleId, label) {
        if (label === 'json') {
            return './json.worker.bundle.js';
        }
        if (label === 'css' || label === 'scss' || label === 'less') {
            return './css.worker.bundle.js';
        }
        if (label === 'html' || label === 'handlebars' || label === 'razor') {
            return './html.worker.bundle.js';
        }
        return './editor.worker.bundle.js';
    }
};

Complete Example

// Configure all language services
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
    validate: true,
    allowComments: true,
    schemas: [
        {
            uri: 'http://json-schema.org/package',
            fileMatch: ['package.json'],
            schema: packageJsonSchema
        }
    ]
});

monaco.languages.css.cssDefaults.setOptions({
    validate: true,
    lint: {
        duplicateProperties: 'warning',
        unknownProperties: 'warning'
    }
});

monaco.languages.html.htmlDefaults.setOptions({
    format: {
        tabSize: 2,
        insertSpaces: true
    },
    suggest: {
        html5: true
    }
});

// Create models for different languages
const models = [
    monaco.editor.createModel(jsonContent, 'json', monaco.Uri.parse('file:///config.json')),
    monaco.editor.createModel(cssContent, 'css', monaco.Uri.parse('file:///styles.css')),
    monaco.editor.createModel(htmlContent, 'html', monaco.Uri.parse('file:///index.html'))
];

// Create editor and switch between models
const editor = monaco.editor.create(document.getElementById('container'));
editor.setModel(models[0]); // Start with JSON

docs

editor-core.md

index.md

languages-and-providers.md

models-and-uris.md

other-languages.md

typescript-language.md

workers-and-environment.md

tile.json