UNPKG

slack-message-parser

Version:
181 lines (180 loc) 6.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Node_js_1 = require("./types/Node.js"); const combinator_js_1 = require("./combinator.js"); const parseBold = (0, combinator_js_1.explicit)((0, combinator_js_1.regexp)(/^\*(\S([^*\n]*?|[^*\n]*? `.*?` )[^\s*]|\S)\*(?=[\s~!#$%^)\-+={}[\];:'",.?/]|$)/, (match, _text, position, parseText) => { const [matchedText, content] = match; return [ { type: Node_js_1.NodeType.Bold, children: parseText(content), source: matchedText, }, position + matchedText.length, ]; })); const parseCode = (0, combinator_js_1.explicit)((0, combinator_js_1.regexp)(/^`([^`]+?)`(?=[\s.,\])}!?\-=]|$)/, (match, _text, position) => { const [matchedText, content] = match; return [ { type: Node_js_1.NodeType.Code, text: content, source: matchedText, }, position + matchedText.length, ]; })); const parsePreText = (0, combinator_js_1.explicit)((0, combinator_js_1.regexp)(/^```(\s*\S[\s\S]*?\s*)```(?=[\s.,\])}!?\-=]|$)/, (match, _text, position) => { const [matchedText, content] = match; return [ { type: Node_js_1.NodeType.PreText, text: content, source: matchedText, }, position + matchedText.length, ]; })); const parseItalic = (0, combinator_js_1.explicit)((0, combinator_js_1.regexp)(/^_(\S([^_\n]*?|[^_\n]*? `.*?` )\S|\S)\_(?=[\s.,\])}!?\-=]|$)/, (match, _text, position, parseText) => { const [matchedText, content] = match; return [ { type: Node_js_1.NodeType.Italic, children: parseText(content), source: matchedText, }, position + matchedText.length, ]; })); const parseStrike = (0, combinator_js_1.explicit)((0, combinator_js_1.regexp)(/^~(\S([^~\n]*?|[^~\n]*? `.*?` )\S|\S)\~(?=[\s.,\])}!?\-=]|$)/, (match, _text, position, parseText) => { const [matchedText, content] = match; return [ { type: Node_js_1.NodeType.Strike, children: parseText(content), source: matchedText, }, position + matchedText.length, ]; })); const parseQuoteLine = (0, combinator_js_1.topOfLine)((0, combinator_js_1.regexp)(/^&gt;(.*)(\n&gt;|\n|$)/, (match, _text, position, parseText) => { const [matchedText, content] = match; const repeatedGt = content.match(/^((&gt;)+)(.*)$/); // If the next line is also starts with ">", do not include the character // (simulating RegExp's non-capturing group) const source = matchedText.replace(/\n&gt;$/, "\n"); // `source` and `matchedText` are same unless the next line starts with ">" // due to the above line removes the ">". const isNextLineStartsWithGt = source !== matchedText; return [ { type: Node_js_1.NodeType.Quote, children: repeatedGt ? [ { type: Node_js_1.NodeType.Text, text: repeatedGt[1], source: repeatedGt[1], }, ...parseText(repeatedGt[3]), ] // Only the last LF could be a terminator character of quote. // Non-last LFs should be parsed as well as `content`. : parseText(isNextLineStartsWithGt ? content + "\n" : content), source, }, position + source.length, ]; })); const parseQuote = (0, combinator_js_1.or)([ (0, combinator_js_1.topOfLine)((0, combinator_js_1.regexp)(/^&gt;&gt;&gt;([\s\S]+)$/, (match, _text, position, parseText) => { const [matchedText, content] = match; return [ { type: Node_js_1.NodeType.Quote, children: parseText(content), source: matchedText, }, position + matchedText.length, ]; })), (0, combinator_js_1.oneOrMore)(parseQuoteLine, (quotes) => { return { type: Node_js_1.NodeType.Quote, children: quotes.map((quote) => quote.children).flat(), source: quotes.map((quote) => quote.source).join(""), }; }), ]); const parseEmoji = (0, combinator_js_1.regexp)(/^:([^:<`*#@!\s()$%]+):(:(skin-tone-.+?):)?/, (match, _text, position) => { const [matchedText, name, _, variation] = match; return [ { type: Node_js_1.NodeType.Emoji, name, variation, source: matchedText, }, position + matchedText.length, ]; }); const parseLink = (0, combinator_js_1.regexp)(/^<([^\s<>][^\n<>]*?)(\|([^<>]+?))?>/, (match, _text, position, parseText) => { const [matchedText, link, _, label] = match; const nextPosition = position + matchedText.length; const labelNodes = label ? parseText(label) : undefined; switch (link.charAt(0)) { case "@": return [ { type: Node_js_1.NodeType.UserLink, userID: link.slice(1), label: labelNodes, source: matchedText, }, nextPosition, ]; case "#": return [ { type: Node_js_1.NodeType.ChannelLink, channelID: link.slice(1), label: labelNodes, source: matchedText, }, nextPosition, ]; case "!": { const [commandName, ...args] = link.slice(1).split("^"); return [ { type: Node_js_1.NodeType.Command, name: commandName, arguments: args, label: labelNodes, source: matchedText, }, nextPosition, ]; } default: return [ { type: Node_js_1.NodeType.URL, url: link, label: labelNodes, source: matchedText, }, nextPosition, ]; } }); exports.default = (0, combinator_js_1.or)([ parseBold, parsePreText, parseCode, parseEmoji, parseItalic, parseQuote, parseLink, parseStrike, ]);