spaday-codemirror logo, a code editor inside a browser window

CodeMirror 6 code editor for spaday.

Build Status codecov License PyPI

Usage

spaday-codemirror provides one custom element, <spaday-codemirror>, and its typed spaday binding, CodeMirror. The package registers itself as the codemirror component package, so pages load its assets with packages=["codemirror"].

from spaday.backends.starlette import serve
from spaday_codemirror import CodeMirror


def page():
    return CodeMirror(doc="print('hello')\n", language="python", theme="dark", tab_size=4)


app = serve(page, packages=["codemirror"])

To send edits to Python, bind editor-change to an action, e.g. .on("editor-change", SendPatch("editor", "doc", event_value("doc"))), and route the spaday:patch intent to your model. example.py does this over a websocket.

Without Python, load cdn/index.js and css/index.css from spaday_codemirror/extension/ (or js/dist/) and use the tag directly:

<spaday-codemirror language="json" tab_size="2"></spaday-codemirror>

Properties

Attributes share the property names.

Property

Type

Default

Description

doc

string

""

Editor contents

language

"python" | "javascript" | "json" | "markdown" | "plain"

"plain"

Syntax mode

theme

"light" | "dark"

"light"

Color theme (dark uses One Dark)

read_only

boolean

false

Disallow user edits

line_numbers

boolean

true

Show the line-number gutter

tab_size

number

4

Tab width and indent unit, in spaces

selection

{anchor: number, head?: number} | null

null

Main selection; property only. head defaults to anchor; null leaves it as-is

remote_cursors

{peer, anchor, head?, label?, color?}[]

[]

Remote selections; positions are tracked as the document changes. Labels and colors are optional

Setting a property updates the existing EditorView in place, so focus and scroll position are kept. Property changes never emit events.

Theming

Editor chrome follows spaday’s shell palette. Component tokens can be set on the editor or any ancestor; spaday_codemirror.TOKENS exposes the same names for Python css() calls.

Token

Controls

Shell fallback

--spa-codemirror-surface

Editor background

--spa-surface

--spa-codemirror-text

Editor and panel text

--spa-muted

--spa-codemirror-gutter-surface

Gutter and panel background

--spa-surface-2

--spa-codemirror-gutter-text

Line numbers

--spa-muted

--spa-codemirror-border

Editor, gutter, panel borders

--spa-border

--spa-codemirror-focus

Focused editor border

--spa-accent

--spa-codemirror-cursor

Caret and drop cursor

--spa-accent

--spa-codemirror-selection

Selection background

Theme default

--spa-codemirror-active-line

Active-line background

Theme default

--spa-codemirror-active-line-gutter

Active line-number background

Theme default

Syntax colors remain owned by CodeMirror’s light and One Dark themes. For example, CodeMirror(...).css(spa_codemirror_surface="#111", spa_codemirror_text="#ddd") changes one editor without changing the rest of the application.

Events

Both events bubble and are composed.

Event

detail

Fired when

editor-change

{doc, changes: [{from, to, insert}], selection: {anchor, head}}

The user edits the document

editor-selection

{selection: {anchor, head}}

The user moves the selection without editing

Cursor awareness

connectCursorAwareness(editor, client, modelId) publishes local selections through transports awareness, renders remote selections, maps their positions across document changes, and removes them when peers disconnect. Its optional local and remote callbacks attach and present application metadata. The collaboration example uses those callbacks for names and colors; the shared cursor state only requires a peer ID and selection.

Browser examples

  • Hosted Pyodide example: the example page running in a Python Web Worker.

  • spaday_codemirror/example.py: two editors wired to a transports-hosted model, plus a gallery covering every language and representative settings. Python computes metrics and a normalized preview on each edit, and has Normalize and Reset actions.

  • spaday_codemirror/collaboration.py: one CRDT-backed document shared by Alice and Bob, with a read-only Viewer. Open two user links in separate tabs to see character-level edits and ephemeral cursor awareness flow through Spaday and transports. The example assigns names and colors in its browser adapter; production applications should derive identity from authenticated websocket sessions.

  • js/examples/: the Pyodide page and worker.

Run the examples locally

make develop
make build
python -m spaday_codemirror.example  # http://127.0.0.1:8031/
python -m spaday_codemirror.collaboration  # http://127.0.0.1:8032/

Build and test the Pyodide example:

make test-pyodide-example
cd dist/lite && python -m http.server

Note

This library was generated using copier from the Base Python Project Template repository.