@eccenca/gui-elements
Version:
GUI elements based on other libraries, usable in React application, written in Typescript.
283 lines • 12.3 kB
JavaScript
import { EditorSelection } from "@codemirror/state";
var Commands;
(function (Commands) {
Commands["header1"] = "Heading 1";
Commands["header2"] = "Heading 2";
Commands["header3"] = "Heading 3";
Commands["header4"] = "Heading 4";
Commands["header5"] = "Heading 5";
Commands["header6"] = "Heading 6";
Commands["codeBlock"] = "Code block";
Commands["quote"] = "Block quote";
Commands["bold"] = "Bold";
Commands["italic"] = "Italic";
Commands["strike"] = "StrikeThrough";
Commands["inlineCode"] = "Inline code";
Commands["unorderedList"] = "Unordered list";
Commands["orderedList"] = "Ordered list";
Commands["todoList"] = "Todo list";
Commands["link"] = "Link";
Commands["image"] = "Image";
})(Commands || (Commands = {}));
//contains all utilities for markdown toolbar
var MarkdownCommand = /** @class */ (function () {
function MarkdownCommand(view) {
var _this = this;
this.view = null;
/**
* Supported list types are ol, ul, todo.
* utility helps to determine which at the start of the line
*/
this.getListTypeOfLine = function (text) {
if (!text)
return;
text = text === null || text === void 0 ? void 0 : text.trimStart();
if (text.startsWith("- ")) {
if (text.startsWith("- [ ] ") || text.startsWith("- [x] "))
return ["todo"];
return ["ul"];
}
var v = text.match(/^(\d+)\. /);
return v ? ["ol", Number.parseInt(v[1], 10)] : undefined;
};
//factory for different list types.
this.createList = function (type) {
if (!_this.view)
return;
var view = _this.view;
var doc = view.state.doc;
var orderedList = { currentIndex: 1 };
view.dispatch(view.state.changeByRange(function (range) {
var text = doc.slice(range.from, range.to);
var changes = [];
var selectionStart = range.from;
var selectionLength = range.to - range.from;
Array.from({ length: text.lines }).forEach(function (_, index) {
var line = doc.line(doc.lineAt(range.from).number + index);
var currentListType = _this.getListTypeOfLine(line.text);
if (currentListType && currentListType[0] === type) {
if (currentListType[0] === "ol" && currentListType[1]) {
orderedList.currentIndex = currentListType[1];
}
return;
}
var content = _this.createListDelimiter(line.text, type, orderedList);
var diffLength = content.length - line.length;
changes.push({
from: line.from,
to: line.to,
insert: content,
});
if (index === 0) {
selectionStart = selectionStart + diffLength;
}
else {
selectionLength = selectionLength + diffLength;
}
});
return {
changes: changes,
range: EditorSelection.range(selectionStart, selectionStart + selectionLength),
};
}));
view.focus();
};
this.enforceCursorFocus = function (cursorPosition) {
if (!_this.view)
return;
var view = _this.view;
setTimeout(function () {
view.dispatch({
selection: EditorSelection.cursor(cursorPosition),
});
view.focus();
}, 50);
};
//supported headers from h1-h6, h6 being the smallest
this.createHeading = function (level) {
if (!_this.view)
return;
var view = _this.view;
var state = view.state;
var flags = "#".repeat(level) + " ";
var lastCursorPosition = 0;
view.dispatch(state.changeByRange(function (range) {
var line = state.doc.lineAt(range.from);
var content = line.text.replace(/^((#+) )?/, flags);
var diffLength = content.length - line.length;
lastCursorPosition = line.to + diffLength;
return {
changes: {
from: line.from,
to: line.to,
insert: content,
},
range: EditorSelection.range(range.anchor + diffLength, range.head + diffLength),
};
}));
_this.enforceCursorFocus(lastCursorPosition);
};
this.applyFormatting = function (_a) {
var start = _a.start, startDelimiter = _a.startDelimiter, _b = _a.endDelimiter, endDelimiter = _b === void 0 ? startDelimiter : _b, _c = _a.stop, stop = _c === void 0 ? start : _c;
if (!_this.view)
return;
var view = _this.view;
var _d = view.state.selection.main, from = _d.from, to = _d.to;
var text = view.state.sliceDoc(from, to);
view.dispatch(view.state.changeByRange(function (range) {
return {
changes: [{ from: range.from, to: range.to, insert: "".concat(startDelimiter).concat(text).concat(endDelimiter) }],
range: EditorSelection.range(range.from + start, range.to + stop),
};
}));
view.focus();
};
this.applyAttachment = function (type) {
if (!_this.view)
return;
var view = _this.view;
var state = view.state;
var isImageAttachmentType = type === Commands.image;
var doc = state.doc;
view.dispatch(state.changeByRange(function (range) {
var from = range.from, to = range.to;
var text = doc.sliceString(from, to);
var link = "".concat(isImageAttachmentType ? "!" : "", "[").concat(text, "]()");
var cursor = from + (text.length ? 3 + text.length : 1 + Number(isImageAttachmentType));
return {
changes: [
{
from: from,
to: to,
insert: link,
},
],
range: EditorSelection.range(cursor, cursor),
};
}));
view.focus();
};
this.applyQuoteFormatting = function () {
if (!_this.view)
return;
var view = _this.view;
var state = view.state;
var doc = state.doc;
var lastCursorPosition = 0;
view.dispatch(view.state.changeByRange(function (range) {
var startLine = doc.lineAt(range.from);
var text = doc.slice(range.from, range.to);
var lineCount = text.lines;
var changes = [];
var selectionStart = range.from;
var selectionLength = range.to - range.from;
new Array(lineCount).fill(0).forEach(function (_, index) {
var line = doc.line(startLine.number + index);
if (line.text.startsWith("> ")) {
return;
}
changes.push({
from: line.from,
insert: "> ",
});
if (index === 0) {
selectionStart = selectionStart + 2;
}
else {
selectionLength += 2;
}
});
lastCursorPosition = selectionStart + selectionLength;
return {
changes: changes,
range: EditorSelection.range(selectionStart, selectionStart + selectionLength),
};
}));
_this.enforceCursorFocus(lastCursorPosition);
};
this.executeCommand = function (command) {
var _a;
switch (command) {
case Commands.bold:
return _this.applyFormatting({ start: 2, startDelimiter: "**" });
case Commands.italic:
return _this.applyFormatting({ start: 1, startDelimiter: "*" });
case Commands.codeBlock:
return _this.applyFormatting({ start: 3, startDelimiter: "```\n", endDelimiter: "\n```" });
case Commands.strike:
return _this.applyFormatting({ start: 2, startDelimiter: "~~" });
case Commands.inlineCode:
return _this.applyFormatting({ start: 1, startDelimiter: "`" });
case Commands.header1:
case Commands.header2:
case Commands.header3:
case Commands.header4:
case Commands.header5:
case Commands.header6:
return _this.createHeading(Number(command.slice(-1)));
case Commands.unorderedList:
case Commands.orderedList:
case Commands.todoList:
return _this.createList((_a = MarkdownCommand.commands.lists.find(function (l) { return l.title === command; })) === null || _a === void 0 ? void 0 : _a.moniker);
case Commands.image:
case Commands.link:
return _this.applyAttachment(command);
case Commands.quote:
return _this.applyQuoteFormatting();
default:
return; //do nothing;
}
};
this.view = view;
}
//inserts the list delimiters of "-", "- [ ]" and "{number}."
MarkdownCommand.prototype.createListDelimiter = function (text, type, orderedList) {
return text.replace(/^(( *)(-( \[[x ]])?|\d+\.) )?/, function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var _a = args[args.length - 1].space, space = _a === void 0 ? "" : _a;
var newFlag = "- ";
if (type === "ol") {
newFlag = "".concat(orderedList.currentIndex, ". ");
orderedList.currentIndex++;
}
else if (type === "todo") {
newFlag = "- [ ] ";
}
return space + newFlag;
});
};
//list of supported commands as well as the valid icon names.
MarkdownCommand.commands = {
paragraphs: [
Commands.header1,
Commands.header2,
Commands.header3,
Commands.header4,
Commands.header5,
Commands.header6,
Commands.quote,
Commands.codeBlock,
],
basic: [
{ title: Commands.bold, icon: "operation-format-text-bold" },
{ title: Commands.italic, icon: "operation-format-text-italic" },
{ title: Commands.strike, icon: "operation-format-text-strikethrough" },
{ title: Commands.inlineCode, icon: "operation-format-text-code" },
],
lists: [
{ title: Commands.unorderedList, icon: "operation-format-list-bullet", moniker: "ul" },
{ title: Commands.orderedList, icon: "operation-format-list-numbered", moniker: "ol" },
{ title: Commands.todoList, icon: "operation-format-list-checked", moniker: "todo" },
],
attachments: [
{ title: Commands.link, icon: "operation-link" },
{ title: Commands.image, icon: "item-image" },
],
};
return MarkdownCommand;
}());
export default MarkdownCommand;
//# sourceMappingURL=markdown.command.js.map