UNPKG

@eccenca/gui-elements

Version:

GUI elements based on other libraries, usable in React application, written in Typescript.

283 lines 12.3 kB
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