2022-12-09 15:09:53 +00:00
|
|
|
import { Decoration, EditorState, Range, syntaxTree } from "../deps.ts";
|
|
|
|
import { decoratorStateField } from "./util.ts";
|
2022-03-20 08:56:28 +00:00
|
|
|
|
|
|
|
interface WrapElement {
|
|
|
|
selector: string;
|
|
|
|
class: string;
|
|
|
|
nesting?: boolean;
|
2023-07-02 11:41:40 +00:00
|
|
|
disableSpellCheck?: boolean;
|
2022-03-20 08:56:28 +00:00
|
|
|
}
|
|
|
|
|
2022-12-09 15:09:53 +00:00
|
|
|
export function lineWrapper(wrapElements: WrapElement[]) {
|
|
|
|
return decoratorStateField((state: EditorState) => {
|
|
|
|
const widgets: Range<Decoration>[] = [];
|
|
|
|
const elementStack: string[] = [];
|
|
|
|
const doc = state.doc;
|
|
|
|
syntaxTree(state).iterate({
|
2022-09-06 12:36:31 +00:00
|
|
|
enter: ({ type, from, to }) => {
|
2022-10-17 13:48:21 +00:00
|
|
|
for (const wrapElement of wrapElements) {
|
2023-07-02 11:41:40 +00:00
|
|
|
const spellCheckAttributes = wrapElement.disableSpellCheck
|
|
|
|
? { attributes: { spellcheck: "false" } }
|
|
|
|
: {};
|
|
|
|
|
2022-09-06 12:36:31 +00:00
|
|
|
if (type.name == wrapElement.selector) {
|
2022-03-20 08:56:28 +00:00
|
|
|
if (wrapElement.nesting) {
|
2022-09-06 12:36:31 +00:00
|
|
|
elementStack.push(type.name);
|
|
|
|
}
|
|
|
|
const bodyText = doc.sliceString(from, to);
|
|
|
|
let idx = from;
|
2022-10-17 13:48:21 +00:00
|
|
|
for (const line of bodyText.split("\n")) {
|
2022-09-06 12:36:31 +00:00
|
|
|
let cls = wrapElement.class;
|
|
|
|
if (wrapElement.nesting) {
|
|
|
|
cls = `${cls} ${cls}-${elementStack.length}`;
|
|
|
|
}
|
|
|
|
widgets.push(
|
|
|
|
Decoration.line({
|
|
|
|
class: cls,
|
2023-07-02 11:41:40 +00:00
|
|
|
...spellCheckAttributes,
|
2022-10-10 12:50:21 +00:00
|
|
|
}).range(doc.lineAt(idx).from),
|
2022-09-06 12:36:31 +00:00
|
|
|
);
|
|
|
|
idx += line.length + 1;
|
2022-03-20 08:56:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-06 12:36:31 +00:00
|
|
|
},
|
|
|
|
leave({ type }) {
|
2022-10-17 13:48:21 +00:00
|
|
|
for (const wrapElement of wrapElements) {
|
2022-09-06 12:36:31 +00:00
|
|
|
if (type.name == wrapElement.selector && wrapElement.nesting) {
|
|
|
|
elementStack.pop();
|
|
|
|
}
|
2022-03-20 08:56:28 +00:00
|
|
|
}
|
2022-09-06 12:36:31 +00:00
|
|
|
},
|
|
|
|
});
|
2022-12-09 15:09:53 +00:00
|
|
|
|
|
|
|
return Decoration.set(widgets, true);
|
2022-03-20 08:56:28 +00:00
|
|
|
});
|
|
|
|
}
|