Skip to content

Code Block Plugin

The CodeBlockPlugin adds fenced code blocks with a non-editable header (language label + copy button), keyboard-driven indentation, Markdown input rules, and full color theming.

import { CodeBlockPlugin } from '@notectl/core';
// Default (dark theme)
new CodeBlockPlugin()
// Light theme
new CodeBlockPlugin({
background: '#f8f9fa',
headerBackground: '#e9ecef',
textColor: '#212529',
headerColor: '#868e96',
})
interface CodeBlockConfig {
/** Optional syntax highlighter implementation. */
readonly highlighter?: SyntaxHighlighter;
/** Default language when creating new code blocks. */
readonly defaultLanguage?: string;
/** Use spaces instead of tabs for indentation. */
readonly useSpaces?: boolean;
/** Number of spaces per indent level (default: 2). */
readonly spaceCount?: number;
/** Show the copy button in the header (default: true). */
readonly showCopyButton?: boolean;
/** Render separator after toolbar item. */
readonly separatorAfter?: boolean;
/** Body background color (overrides --notectl-code-block-bg). */
readonly background?: string;
/** Header background color (overrides --notectl-code-block-header-bg). */
readonly headerBackground?: string;
/** Code text color (overrides --notectl-code-block-color). */
readonly textColor?: string;
/** Header/label text color (overrides --notectl-code-block-header-color). */
readonly headerColor?: string;
/** Customize keyboard bindings for code block actions. */
readonly keymap?: CodeBlockKeymap;
/** Locale override for user-facing strings. */
readonly locale?: CodeBlockLocale;
}
interface CodeBlockKeymap {
/** Insert a paragraph below the code block. Default: 'Mod-Enter'. Set to null to disable. */
readonly insertAfter?: string | null;
/** Toggle between code block and paragraph. Default: 'Mod-Shift-M'. Set to null to disable. */
readonly toggle?: string | null;
}

Override or disable the default code block shortcuts:

new CodeBlockPlugin({
keymap: {
insertAfter: 'Mod-Shift-Enter', // override default Mod-Enter
toggle: 'Mod-Shift-C', // override default Mod-Shift-M
},
})

Set a binding to null to disable it entirely:

new CodeBlockPlugin({
keymap: {
insertAfter: null, // disable insert-after shortcut
toggle: 'Mod-Shift-C',
},
})

Mod resolves to Cmd on macOS and Ctrl on Windows/Linux.

There are two ways to customize code block colors:

Pass colors directly in the constructor. Best for fixed application themes.

new CodeBlockPlugin({
background: '#f8f9fa',
headerBackground: '#e9ecef',
textColor: '#212529',
headerColor: '#868e96',
})

Set CSS variables on the <notectl-editor> element. Best for dynamic theming (dark/light mode toggle, media queries).

notectl-editor {
--notectl-code-block-bg: #f8f9fa;
--notectl-code-block-header-bg: #e9ecef;
--notectl-code-block-color: #212529;
--notectl-code-block-header-color: #868e96;
--notectl-code-block-header-border: #dee2e6;
}

Or responsive with media queries:

@media (prefers-color-scheme: light) {
notectl-editor {
--notectl-code-block-bg: #f8f9fa;
--notectl-code-block-color: #212529;
--notectl-code-block-header-bg: #e9ecef;
--notectl-code-block-header-color: #868e96;
}
}
@media (prefers-color-scheme: dark) {
notectl-editor {
--notectl-code-block-bg: #1e1e2e;
--notectl-code-block-color: #cdd6f4;
--notectl-code-block-header-bg: rgba(255, 255, 255, 0.06);
--notectl-code-block-header-color: #7f849c;
}
}
PropertyDefaultDescription
--notectl-code-block-bg#1e1e2eBody background
--notectl-code-block-color#cdd6f4Code text color
--notectl-code-block-header-bgrgba(255,255,255,0.06)Header background
--notectl-code-block-header-color#7f849cHeader label and copy button color
--notectl-code-block-header-borderrgba(255,255,255,0.08)Header bottom border

When both methods are used, plugin config wins because it sets inline CSS custom properties on each <pre> element:

  1. CSS defaults in stylesheet (lowest)
  2. External CSS custom properties on notectl-editor
  3. Plugin config (highest)
CommandDescriptionReturns
toggleCodeBlockToggle between paragraph and code blockboolean
insertCodeBlockConvert the current block to a code blockboolean
exitCodeBlockExit the code block (same as Escape)boolean
setCodeBlockLanguageReserved — use the Service API insteadfalse
setCodeBlockBackgroundReserved — use the Service API insteadfalse
editor.executeCommand('toggleCodeBlock');
ShortcutAction
Ctrl+Shift+M / Cmd+Shift+MToggle code block (configurable via keymap.toggle)
EnterInsert newline within code block
Enter (twice, on empty last line)Exit code block, create paragraph below
TabInsert indent (tab or spaces)
Shift+TabRemove indent from current line
Ctrl+Enter / Cmd+EnterInsert paragraph below and move cursor there (configurable via keymap.insertAfter)
EscapeExit code block to next block or new paragraph
ArrowDown (on last line)Exit code block to next block or new paragraph
ArrowUp (on first line)Exit to previous block
ArrowRight (at end)Exit code block to next block
ArrowLeft (at start)Exit code block to previous block
Backspace (at position 0)Convert code block back to paragraph
PatternResult
``` + SpaceCreate empty code block
```typescript + SpaceCreate code block with language set to “typescript”

The code block button appears in the block toolbar group with the </> icon. It shows as active when the cursor is inside a code block.

TypeHTML TagAttributesDescription
code_block<pre><code>language, backgroundColorFenced code block

The plugin registers a typed service for programmatic access:

import { CODE_BLOCK_SERVICE_KEY } from '@notectl/core';
const service = context.getService(CODE_BLOCK_SERVICE_KEY);
service.setLanguage(blockId, 'python');
service.getLanguage(blockId); // 'python'
service.setBackground(blockId, '#282c34');
service.getBackground(blockId); // '#282c34'
service.isCodeBlock(blockId); // true
service.getSupportedLanguages(); // ['typescript', 'python', ...]

Provide a SyntaxHighlighter implementation to enable token-based highlighting:

interface SyntaxHighlighter {
tokenize(code: string, language: string): readonly SyntaxToken[];
getSupportedLanguages(): readonly string[];
}
interface SyntaxToken {
readonly from: number;
readonly to: number;
readonly type: string; // e.g. 'keyword', 'string', 'number', 'comment'
}

The plugin generates decoration classes like notectl-token--keyword, notectl-token--string, etc. Style them in your CSS:

notectl-editor .notectl-token--keyword { color: #c678dd; }
notectl-editor .notectl-token--string { color: #98c379; }
notectl-editor .notectl-token--number { color: #d19a66; }
notectl-editor .notectl-token--comment { color: #5c6370; font-style: italic; }

The plugin automatically prevents formatting marks (bold, italic, underline, etc.) from being applied inside code blocks via middleware.