app/components/editor/source-views.ts
62 lines and 11 functions in DrDustinEdwards/carrel, at commit d5d5e82 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| sourceBlockView | 7 to 52 | 1 | 0% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
| addNodeView | 9 to 50 | 1 | 100% | OkCRAP 1 | No data: mutation testing has not run on this repo yet |
| <anonymous:10> | 10 to 49 | 1 | 0% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
| show | 21 to 27 | 2 | 0% | WatchCRAP 6 | No data: mutation testing has not run on this repo yet |
| <anonymous:29> | 29 to 34 | 3 | 0% | WatchCRAP 12 | No data: mutation testing has not run on this repo yet |
| update | 39 to 44 | 2 | 0% | WatchCRAP 6 | No data: mutation testing has not run on this repo yet |
| stopEvent | 46 to 46 | 1 | 0% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
| ignoreMutation | 47 to 47 | 1 | 0% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
| addNodeView | 56 to 64 | 1 | 100% | OkCRAP 1 | No data: mutation testing has not run on this repo yet |
| <anonymous:57> | 57 to 63 | 1 | 0% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
| ignoreMutation | 62 to 62 | 1 | 0% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
Imports
It imports app/lib/editor/schema.mjs. Imported by app/components/editor/rich-editor.tsx.
Source
// The formatted editor's views of Markdown it does not format (rich-editor.tsx): a source block edited
// as Markdown in a labelled textarea, and inline source shown as written.
import { SourceBlock, SourceInline } from "~/lib/editor/schema.mjs";
/** A source block in the formatted view: its kind, then its Markdown in a labelled textarea. */
export function sourceBlockView(readOnly: () => boolean) {
return SourceBlock.extend({
addNodeView() {
return ({ node, getPos, editor }) => {
let current = node;
const dom = document.createElement("div");
dom.className = "app-src-block";
dom.contentEditable = "false";
const label = document.createElement("span");
label.className = "app-src-kind";
label.setAttribute("aria-hidden", "true");
const area = document.createElement("textarea");
area.className = "app-src-text";
area.spellcheck = false;
const show = () => {
label.textContent = `${current.attrs.kind}, Markdown`;
area.setAttribute("aria-label", `${current.attrs.kind}, Markdown`);
if (area.value !== current.attrs.text) area.value = current.attrs.text;
area.rows = Math.max(1, area.value.split("\n").length);
area.readOnly = readOnly();
};
show();
area.addEventListener("input", () => {
const pos = typeof getPos === "function" ? getPos() : undefined;
if (pos === undefined) return;
area.rows = Math.max(1, area.value.split("\n").length);
editor.view.dispatch(editor.state.tr.setNodeMarkup(pos, undefined, { ...current.attrs, text: area.value }));
});
dom.appendChild(label);
dom.appendChild(area);
return {
dom,
update: (next) => {
if (next.type !== current.type) return false;
current = next;
show();
return true;
},
// Keys and clicks in the textarea are the textarea's own, not the editor's.
stopEvent: (event) => event.target === area,
ignoreMutation: () => true,
};
};
},
});
}
/** Markdown kept as written inside a paragraph: a directive, math, an image, a bare link. */
export const SourceInlineView = SourceInline.extend({
addNodeView() {
return ({ node }) => {
const dom = document.createElement("code");
dom.className = "app-src-inline";
dom.contentEditable = "false";
dom.textContent = node.attrs.text;
return { dom, ignoreMutation: () => true };
};
},
});