or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

editor-commands.mdeditor-core.mdeditor-factory.mdextension-system.mdindex.mdlanguage-support.mdmime-type-service.mdsearch-replace.mdspecial-extensions.mdtheme-system.md
tile.json

extension-system.mddocs/

0

# Extension System

1

2

The extension system provides a comprehensive registry and configuration management for 25+ configurable extensions that customize editor behavior and appearance.

3

4

## Capabilities

5

6

### EditorExtensionRegistry

7

8

Main registry for managing editor extensions and their configurations.

9

10

```typescript { .api }

11

/**

12

* CodeMirror extensions registry

13

* Manages 25+ configurable extensions for editor customization

14

*/

15

class EditorExtensionRegistry implements IEditorExtensionRegistry {

16

constructor();

17

18

/**

19

* Base editor configuration (default config optionally modified by user)

20

*/

21

baseConfiguration: Record<string, any>;

22

23

/**

24

* Default editor configuration as defined when extensions are registered

25

*/

26

readonly defaultConfiguration: Record<string, any>;

27

28

/**

29

* Editor configuration JSON schema for validation

30

*/

31

readonly settingsSchema: ReadonlyJSONObject;

32

33

/**

34

* Add a default editor extension

35

*/

36

addExtension<T>(factory: IEditorExtensionFactory<T>): void;

37

38

/**

39

* Create a new extensions handler for an editor

40

*/

41

createNew(options: IEditorHandlerOptions): IExtensionsHandler;

42

}

43

44

interface IEditorExtensionRegistry {

45

readonly baseConfiguration: Record<string, any>;

46

addExtension<T>(factory: IEditorExtensionFactory<T>): void;

47

createNew(options: IEditorHandlerOptions): IExtensionsHandler;

48

}

49

```

50

51

**Usage Examples:**

52

53

```typescript

54

import { EditorExtensionRegistry } from "@jupyterlab/codemirror";

55

56

// Create extension registry

57

const registry = new EditorExtensionRegistry();

58

59

// Add custom extension

60

registry.addExtension({

61

name: 'myExtension',

62

factory: (options) => ({

63

instance: (value) => myCustomExtension(value),

64

reconfigure: (value) => myExtension.reconfigure(value)

65

}),

66

default: true,

67

schema: {

68

type: 'boolean',

69

description: 'Enable my custom extension'

70

}

71

});

72

73

// Create extensions handler for editor

74

const handler = registry.createNew({

75

baseConfiguration: { lineNumbers: true },

76

config: { myExtension: true }

77

});

78

```

79

80

### ExtensionsHandler

81

82

Manages individual editor configuration and extension lifecycle.

83

84

```typescript { .api }

85

/**

86

* Editor configuration handler

87

* Stores editor configuration and manages extension reconfiguration

88

*/

89

class ExtensionsHandler implements IExtensionsHandler, IObservableDisposable {

90

constructor(options?: IEditorHandlerOptions);

91

92

/**

93

* Signal triggered when editor configuration changes

94

*/

95

readonly configChanged: ISignal<this, Record<string, any>>;

96

97

/**

98

* Signal emitted when object is disposed

99

*/

100

readonly disposed: ISignal<this, void>;

101

102

/**

103

* Whether the object is disposed

104

*/

105

readonly isDisposed: boolean;

106

107

// Lifecycle

108

dispose(): void;

109

110

// Configuration management

111

getOption(option: string): unknown;

112

hasOption(option: string): boolean;

113

setOption(option: string, value: unknown): void;

114

setBaseOptions(options: Record<string, any>): void;

115

setOptions(options: Record<string, any>): void;

116

117

// Extension management

118

reconfigureExtension<T>(view: EditorView, key: string, value: T): void;

119

reconfigureExtensions(view: EditorView, configuration: Record<string, any>): void;

120

injectExtension(view: EditorView, extension: Extension): void;

121

getInitialExtensions(): Extension[];

122

}

123

124

interface IEditorHandlerOptions {

125

baseConfiguration?: Record<string, any>;

126

config?: Record<string, any>;

127

defaultExtensions?: [string, IConfigurableExtension<any>][];

128

}

129

```

130

131

**Usage Examples:**

132

133

```typescript

134

import { ExtensionsHandler } from "@jupyterlab/codemirror";

135

import { EditorView } from "@codemirror/view";

136

137

// Create handler with configuration

138

const handler = new ExtensionsHandler({

139

baseConfiguration: {

140

lineNumbers: true,

141

tabSize: 4

142

},

143

config: {

144

lineWrap: true,

145

theme: 'dark'

146

}

147

});

148

149

// Listen for configuration changes

150

handler.configChanged.connect((sender, changes) => {

151

console.log('Configuration changed:', changes);

152

});

153

154

// Update single option

155

handler.setOption('fontSize', 14);

156

157

// Update multiple options

158

handler.setOptions({

159

lineHeight: 1.5,

160

fontFamily: 'Monaco'

161

});

162

163

// Get current option value

164

const lineNumbers = handler.getOption('lineNumbers'); // true

165

166

// Reconfigure extensions on editor view

167

const view = new EditorView({...});

168

handler.reconfigureExtensions(view, {

169

lineNumbers: false,

170

lineWrap: false

171

});

172

```

173

174

### Default Extensions

175

176

The registry comes with 25+ built-in extensions for comprehensive editor customization.

177

178

```typescript { .api }

179

/**

180

* Get default editor extensions

181

* Returns array of 25+ configurable extension factories

182

*/

183

static getDefaultExtensions(options?: {

184

themes?: IEditorThemeRegistry;

185

translator?: ITranslator | null;

186

}): ReadonlyArray<Readonly<IEditorExtensionFactory<any>>>;

187

```

188

189

**Built-in Extensions:**

190

191

1. **autoClosingBrackets** - Automatically close brackets and quotes

192

2. **codeFolding** - Code folding functionality

193

3. **cursorBlinkRate** - Cursor blinking rate configuration

194

4. **highlightActiveLine** - Highlight the current line

195

5. **highlightSpecialCharacters** - Highlight special/invisible characters

196

6. **highlightTrailingWhitespace** - Highlight trailing whitespace

197

7. **highlightWhitespace** - Highlight all whitespace characters

198

8. **indentUnit** - Indentation unit size

199

9. **keymap** - Keyboard shortcuts and key bindings

200

10. **lineNumbers** - Line number display

201

11. **lineWrap** - Line wrapping behavior

202

12. **dropCursor** - Drop cursor for drag and drop

203

13. **matchBrackets** - Bracket matching

204

14. **rectangularSelection** - Rectangular/block selection

205

15. **readOnly** - Read-only mode

206

16. **rulers** - Ruler lines at specified columns

207

17. **extendSelection** - Selection extension behavior

208

18. **searchWithCM** - Native CodeMirror search panel

209

19. **scrollPastEnd** - Allow scrolling past document end

210

20. **smartIndent** - Smart indentation

211

21. **tabFocusable** - Tab key focus behavior

212

22. **tabSize** - Tab size configuration

213

23. **tooltips** - Tooltip support

214

24. **allowMultipleSelections** - Multiple cursor support

215

25. **customStyles** - Custom editor styling

216

26. **theme** - Theme support (when theme registry provided)

217

27. **translation** - Internationalization (when translator provided)

218

219

**Usage Examples:**

220

221

```typescript

222

import { EditorExtensionRegistry } from "@jupyterlab/codemirror";

223

224

// Get default extensions

225

const extensions = EditorExtensionRegistry.getDefaultExtensions();

226

227

// Get extensions with theme and translation support

228

const extensionsWithThemes = EditorExtensionRegistry.getDefaultExtensions({

229

themes: themeRegistry,

230

translator: app.translator

231

});

232

233

// Create registry with default extensions

234

const registry = new EditorExtensionRegistry();

235

extensions.forEach(extension => registry.addExtension(extension));

236

```

237

238

### Extension Factory Interface

239

240

Interface for creating configurable extensions.

241

242

```typescript { .api }

243

/**

244

* Editor extension factory interface

245

*/

246

interface IEditorExtensionFactory<T> {

247

/**

248

* Extension unique identifier

249

*/

250

readonly name: string;

251

252

/**

253

* Extension factory function

254

*/

255

readonly factory: (options: IEditorExtensionFactory.IOptions) => IConfigurableExtension<T> | null;

256

257

/**

258

* Extension default value

259

*/

260

readonly default?: T;

261

262

/**

263

* JSON schema for configurable option

264

*/

265

readonly schema?: ReadonlyJSONObject;

266

}

267

268

interface IEditorExtensionFactory.IOptions {

269

inline: boolean;

270

model: CodeEditor.IModel;

271

}

272

273

/**

274

* Dynamically configurable editor extension

275

*/

276

interface IConfigurableExtension<T> {

277

/**

278

* Create an editor extension for the provided value

279

*/

280

instance(value: T): Extension;

281

282

/**

283

* Reconfigure an editor extension with new value

284

*/

285

reconfigure(value: T): StateEffect<T> | null;

286

}

287

```

288

289

### Extension Creation Utilities

290

291

Helper functions for creating different types of extensions.

292

293

```typescript { .api }

294

/**

295

* Creates a dynamically configurable editor extension

296

*/

297

static createConfigurableExtension<T>(

298

builder: (value: T) => Extension

299

): IConfigurableExtension<T>;

300

301

/**

302

* Creates a configurable extension returning one of two extensions

303

* based on a boolean value

304

*/

305

static createConditionalExtension(

306

truthy: Extension,

307

falsy?: Extension

308

): IConfigurableExtension<boolean>;

309

310

/**

311

* Creates an immutable extension (cannot be reconfigured)

312

*/

313

static createImmutableExtension(

314

extension: Extension

315

): IConfigurableExtension<undefined>;

316

```

317

318

**Usage Examples:**

319

320

```typescript

321

import { EditorExtensionRegistry } from "@jupyterlab/codemirror";

322

import { lineNumbers } from "@codemirror/view";

323

import { keymap } from "@codemirror/view";

324

import { defaultKeymap } from "@codemirror/commands";

325

326

// Create configurable extension

327

const configurableLineNumbers = EditorExtensionRegistry.createConfigurableExtension<boolean>(

328

(show) => show ? lineNumbers() : []

329

);

330

331

// Create conditional extension

332

const conditionalKeymap = EditorExtensionRegistry.createConditionalExtension(

333

keymap.of(defaultKeymap),

334

[] // No keymap when false

335

);

336

337

// Create immutable extension

338

const immutableTheme = EditorExtensionRegistry.createImmutableExtension(

339

EditorView.theme({

340

'.cm-editor': { fontSize: '14px' }

341

})

342

);

343

344

// Add to registry

345

registry.addExtension({

346

name: 'myLineNumbers',

347

factory: () => configurableLineNumbers,

348

default: true

349

});

350

```

351

352

### Advanced Configuration

353

354

Complex configuration scenarios and extension interactions.

355

356

```typescript

357

// Create handler with complex configuration

358

const handler = new ExtensionsHandler({

359

baseConfiguration: {

360

// Base settings applied to all editors

361

tabSize: 4,

362

indentUnit: ' ',

363

lineNumbers: true

364

},

365

config: {

366

// Specific settings for this editor

367

theme: 'jupyterlab',

368

lineWrap: true,

369

rulers: [80, 120]

370

},

371

defaultExtensions: [

372

// Custom extensions specific to this handler

373

['myCustomExtension', myCustomExtensionFactory.factory()]

374

]

375

});

376

377

// Dynamic reconfiguration based on context

378

handler.configChanged.connect((sender, changes) => {

379

if ('theme' in changes) {

380

// React to theme changes

381

updateEditorStyling(changes.theme);

382

}

383

384

if ('language' in changes) {

385

// Update language-specific extensions

386

handler.setOptions({

387

pythonBuiltin: changes.language === 'python',

388

jsxHighlighting: changes.language === 'jsx'

389

});

390

}

391

});

392

393

// Conditional extension loading

394

if (isCollaborativeMode) {

395

handler.setOptions({

396

yBinding: true,

397

collaborativeCursors: true,

398

conflictResolution: 'merge'

399

});

400

}

401

```

402

403

## Types

404

405

```typescript { .api }

406

interface IExtensionsHandler extends IDisposable {

407

readonly configChanged: ISignal<this, Record<string, any>>;

408

409

getOption(option: string): unknown;

410

hasOption(option: string): boolean;

411

setOption(option: string, value: unknown): void;

412

setBaseOptions(options: Record<string, any>): void;

413

setOptions(options: Record<string, any>): void;

414

reconfigureExtension<T>(view: EditorView, key: string, value: T): void;

415

reconfigureExtensions(view: EditorView, configuration: Record<string, any>): void;

416

injectExtension(view: EditorView, extension: Extension): void;

417

getInitialExtensions(): Extension[];

418

}

419

420

interface IEditorHandlerOptions {

421

baseConfiguration?: Record<string, any>;

422

config?: Record<string, any>;

423

defaultExtensions?: [string, IConfigurableExtension<any>][];

424

}

425

```