Autocomplete

Syncline Editor has a built-in completion engine covering language keywords, user-defined symbols, snippets, and Emmet. Every aspect is customisable.

Static Completions

Pass fixed keywords, types, or full CompletionItem objects through configuration. These are merged with the built-in language tokens.

static-completions.ts

import { createEditor } from '@synclineapi/editor';

const editor = createEditor(container, {
  language: 'typescript',

  // Extra symbols shown in the autocomplete popup
  extraKeywords: ['myDSLKeyword', 'LOAD', 'STORE'],
  extraTypes:    ['MyModel', 'MyService', 'UUID'],

  // Fully custom completions — symbols and snippets in one array
  completions: [
    { label: 'UUID',       kind: 'type',    detail: 'string',        documentation: 'Universally unique identifier.' },
    { label: 'API_URL',    kind: 'constant',detail: 'string',        documentation: 'Base URL of the REST API.' },
    { label: 'forEach',    kind: 'snippet', insertText: 'forEach(${1:item} => {
	$0
})', detail: 'forEach snippet' },
  ],
});

Dynamic Completions

Use provideCompletions for context-sensitive results. The callback receives a CompletionContext object (word, line, position) and can return a list or null to fall back to built-ins:

dynamic-completions.ts

import { createEditor, type CompletionContext, type CompletionItem } from '@synclineapi/editor';

const editor = createEditor(container, {
  language: 'typescript',

  // Called every time the popup opens.
  // Return null to fall back to built-in completions.
  provideCompletions(ctx: CompletionContext): CompletionItem[] | null {
    const { word, line, lineNumber, column } = ctx;

    // Only suggest when inside an import string
    if (line.includes('from ') && line.includes("'")) {
      return [
        { label: '@myorg/utils',    kind: 'module', detail: 'npm package' },
        { label: '@myorg/api-keys', kind: 'module', detail: 'npm package' },
      ];
    }

    // Prefix-based example
    if (word.startsWith('use')) {
      return [
        { label: 'useMyContext', kind: 'function', detail: '() => MyContext', documentation: 'Returns the shared context.' },
        { label: 'useMyStore',   kind: 'function', detail: '() => MyStore',   documentation: 'Zustand store hook.' },
      ];
    }

    return null; // let built-ins handle it
  },
});

Hover Documentation

Supply provideHover to show inline documentation when a user pauses over an identifier. Return null to use built-in hover:

hover-docs.ts

import { createEditor, type HoverContext, type HoverDoc } from '@synclineapi/editor';

const editor = createEditor(container, {
  provideHover(ctx: HoverContext): HoverDoc | null {
    const { word } = ctx;

    const docs: Record<string, HoverDoc> = {
      UUID:    { title: 'UUID', body: 'Universally unique identifier (RFC 4122).' },
      API_URL: { title: 'API_URL', body: 'Base URL injected at build time via VITE_API_URL.' },
    };

    return docs[word] ?? null;
  },
});

Built-in Snippets

Common patterns are available out-of-the-box. Tab stops ($1, $2, $0) are navigated with Tab:

snippets.ts

// Built-in snippets (TypeScript / JavaScript)
// --------------------------------------------------
// clg   →  console.log($1)
// fn    →  function $1($2) {\n  $0\n}
// afn   →  ($1) => {\n  $0\n}
// iife  →  (($1) => {\n  $0\n})($2)
// imp   →  import $1 from '$2';
// cls   →  class $1 {\n  $0\n}
// iff   →  if ($1) {\n  $0\n}
// fore  →  for (const $1 of $2) {\n  $0\n}
// tryc  →  try {\n  $1\n} catch (e) {\n  $0\n}
// todo  →  // TODO: $0

Emmet

Emmet abbreviations expand on Tab in HTML, Markdown, and CSS contexts. Disable with { emmet: false }:

emmet.ts

// HTML Emmet expansions (language: 'markdown' or 'css' contexts)
// --------------------------------------------------------------
// div.container  →  <div class="container"></div>
// ul>li*3        →  <ul><li></li><li></li><li></li></ul>
// a[href=#]      →  <a href="#"></a>
// h1{Hello}      →  <h1>Hello</h1>

// CSS Emmet expansions
// --------------------
// m10           →  margin: 10px;
// p10-20        →  padding: 10px 20px;
// bgc#fff       →  background-color: #fff;
// fz14          →  font-size: 14px;

CompletionItem Schema

FieldTypeRequiredDescription
labelstring

Yes

Text inserted and shown in the popup.

kind'keyword' | 'type' | 'function' | 'variable' | 'constant' | 'module' | 'snippet' | 'property'

No

Icon and sort priority.

detailstring

No

Small secondary label shown on the right (type signature etc.).

documentationstring

No

Longer description shown in the side panel.

insertTextstring

No

Text to insert when accepted. Defaults to label. Supports $1…$N tab stops.

filterTextstring

No

Alternative string used to match the prefix. Defaults to label.

sortTextstring

No

Lexicographic sort key. Defaults to label.

Syncline Editor

© 2026 Syncline Editor. All rights reserved.