<light-editor>

A minimal plain text editor with syntax highlighting, line numbers, and line highlighting. <light-editor> is not intended to replace full solutions like CodeMirror, but it is a lightweight alternative using a <pre> overlaid on top of a <textarea> and a few extra divs to make for an enjoyable text editing experience.

If you check the source code in the above example, you’ll notice a &lt;/script>.

For more on why script tags are used, check out Why script tags for further reading.

Examples

Using the value attribute

Using the value attribute is the generally recommended way to provide the most consistent experience. By default, leading and trailing newlines / whitespace will be stripped.

Preserve white space with value attribute

By default, extra white space before the first character and after the last character will be stripped. If you want to leave extra white-space, pass the preserve-whitespace boolean attribute to the editor.

With a template tag

We can use a <template> tag to be able to “slot” in the default value

Changing the highlight language to CSS

By default, the highlighter from Highlight.js only supports HTML / CSS / JS. This is intentional to keep the bundle size low. Supported languages are html, css, and js.

Using a script tag

HTML
<light-editor>
  <!-- Important to use `type="text/plain"` -->
  <script type="text/plain">
    <script>&lt;/script>
  </script>
</light-editor>

Disabled Editor

To disable the editor, provide a disabled attribute.

Editor with a placeholder

To provide a placeholder, use the placeholder attribute. Note, this does not support a <slot> because it’s using the native <textarea> placeholder attribute.

Editor with validations

Validations are handled using “Form Associated Custom Elements”.

<light-editor> supports minlength, maxlength, and required just like the native <textarea> element.

minlength, maxlength, required validations

Removing line numbers

Removing line numbers can be done with the boolean attribute disable-line-numbers

Whitespace wrapping

By default <light-preview> will “soft wrap” lines for you. Meaning, code will wrap and not overflow the container. If this is undesirable, you can pass wrap="hard" and lines will not wrap.

Here’s a preview of soft wrapping vs hard wrapping.

Additional Notes

Caveats to the initial editor value

Declarative slots are hard. The most “consistent” way to provide a default value for the editor is to use value attribute. Like so:

HTML
<light-editor value="<html></html>"></light-editor>

Problems with declarative slotting

If you really want declarative slotting, it’s best to use a <textarea> in the default slot. The editor is really a <textarea> at it’s core, so its recommended to use the <textarea> element to slot in elements. It has 1 drawback which is around not being able to slot in a <textarea> directly. And showing &lt; and &gt; literals is challenging. &amp;lt;html&amp;gt; is equivalent to &gt;html&lt;> This limitation only exists for slotting.

Using a <textarea> element for the default slot requires the following markup to nest a <textarea> string literal inside of it:

HTML
<light-editor>
  <textarea>
    &lt;textarea&gt;&lt;/textarea&gt;
  </textarea>
</light-editor>

Other slottable tags

<template> formats the HTML and strips improper HTML. It’s also not suitable for non-HTML strings. You can do it, but you’ve been warned. <xmp> is deprecated and also has some issues around if you do something like: <!DOCTYPE html > <!-- --> isn’t supported like with Prism’s auto escape plugin could be used, but runs into issues if you want comments nested in comments.

API Reference

Imports

Script
HTML
<!-- Auto registers as <light-editor> -->
<script type="module" src="https://cdn.jsdelivr.net/npm/light-pen/exports/components/light-editor/light-editor-register.js"></script>
CDN
HTML
<script type="module">
  // Auto registers as <light-editor>
  import "https://cdn.jsdelivr.net/npm/light-pen/exports/components/light-editor/light-editor-register.js"

  // Manual Register
  import LightEditor from "https://cdn.jsdelivr.net/npm/light-pen/exports/components/light-editor/light-editor.js"
  LightEditor.define()
  // => Registers as <light-editor>
</script>
Bundler
JavaScript
// Auto registers as <light-editor>
import "light-pen/exports/components/light-editor/light-editor-register.js"

// Manual Register
import LightEditor "light-pen/exports/components/light-editor/light-editor.js"
LightEditor.define()
// => Registers as <light-editor>

Attributes

Name Description Reflects Type Default
[Attribute + Property]
language

The language used for highlighting. Default is “html”. “css” and “js” also included by default.

string "html"
[Attribute + Property]
src

Points to a remote file source that should be accessible via fetch()

string | null null
[Attribute + Property]
wrap

If wrap="soft", lines will wrap when they reach the edge of their container. If wrap="hard", lines will not wrap instead all the user to scroll horizontally to see more code.

"soft" | "hard" "soft"
[Attribute]
preserve-whitespace

[Property]
preserveWhitespace

Whether to strip whitespace before first character, and after the last character.

boolean false
[Attribute]
disable-line-numbers

[Property]
disableLineNumbers
-
boolean false
[Attribute]
data-has-focused

[Property]
hasFocused
-
boolean
-

Events

Name Description
light-value-change

Emitted whenever the “value” attribute of the editor changes.

change
-
light-focus

Re-emits the textarea’s “focus” event

light-blur

Re-emits the textarea’s “blur” event

light-selectionchange

Re-emits the textarea’s “selectionchange” event

light-input

Re-emits the textarea’s “input” event

input
-
light-resize

Is emitting whenever the editor resizes.

light-change

Re-emits the textarea’s “change” event

Functions

Name Description Parameters
click()
-
-
focus()
-
options: FocusOptions
getCaretPosition()
-
-
setCurrentLineHighlight()
-
-
getLinesToSelectionStart()
-
-
getCurrentLineNumber()
-
-