cnc-code
Two widgets in one element. With readonly it is a syntax-highlighted snippet,
rendered entirely on the server with a copy button and no JavaScript at all. Without it, the
snippet is a first paint that upgrades into a full Ace editor once the library arrives — and
stays a readable snippet if it never does.
Quick start
For showing code, which is the common case: bind $code, name the
language, and add readonly.
function greet(name) {
return `Hello, ${name}!`
}
const names = ['Ada', 'Grace', 'Alan']
console.log(names.map(greet).join('\n'))
<cnc-code language="javascript" readonly $code="jsSample"></cnc-code>
Snippet or editor
The readonly attribute is the fork in the road, and it decides more than whether
the text can be typed into.
readonly |
editable | |
|---|---|---|
| JavaScript | None. Nothing is fetched, nothing hydrates. | Ace, from a CDN, on mount. |
| Highlighting | The built-in server highlighter — HTML, JavaScript and TypeScript. | Ace's, which covers a hundred-odd languages. |
| Copy button | Yes. | No. |
| Long class lists | Collapsed to …, click to expand. |
Shown in full. |
| Offline | Unaffected. | Falls back to the same read-only snippet rather than showing a blank box. |
So readonly is not "an editor that refuses input" — that is
disabled. Use readonly for documentation and log output, where paying
for an editor makes no sense.
Things to know
-
There is no
transparentproperty. The previous version of this page passedtransparent="true"; nothing reads it. The snippet's background comes from the stylesheet. -
codeis two-way, and the editor is the one writing. Bind it with$codeand the editor opens on that value and writes every keystroke back to it — nochangelistener needed. A page-side change still reaches the editor, unless the reader has it focused: whoever is typing keeps the buffer. -
The
changeevent andnameare still there.changecarries{ value }for a handler that wants to do more than store the text, andnamerenders a hidden input that follows the typing. Reach for them when a binding is not what you want, not because a binding does not work. -
The copy button only exists in
readonlymode. An editable editor has no copy affordance of its own — the user selects and copies, as in any text field. -
An editor needs the network once.
Ace is fetched from
cdnjs.cloudflare.com. Where it cannot be reached the widget keeps the server-rendered snippet, so the code is still readable — but not editable, and nothing says so. -
languageis passed to Ace verbatim. It becomesace/mode/<language>, so it has to be a mode Ace knows —javascript, notjs. The server highlighter is more forgiving and accepts the short forms, which means a wrong value can highlight correctly before hydration and stop afterwards. -
The editor's theme follows the page, the snippet's colours do not.
Ace re-themes live when the colour mode flips. The read-only highlighter emits fixed
dark:utility classes instead, which do the same job through CSS.
Usage guidance
Reach for readonly whenever the code is only to be read — documentation, a
configuration preview, a log. It costs nothing to ship and is complete before any script runs.
Save the editor for the places a user genuinely types code, and give it a
name
or a $code binding so the text goes somewhere. For prose with the occasional inline
snippet, cnc-markdown renders fenced code blocks itself; for a read-only value in a
table cell, cnc-display type="code" is smaller again.