diff --git a/package.json b/package.json index 807d2253b..b5b85bb71 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,9 @@ "jsonwebtoken": "^9.0.2", "libsodium-wrappers": "^0.7.11", "lint-staged": "^13.1.0", + "mdast-util-from-markdown": "^0.8.5", + "mdast-util-gfm": "^0.1.2", + "micromark-extension-gfm": "^0.3.3", "lodash": "^4.17.21", "ms": "^2.1.3", "node-html-parser": "^6.1.5", diff --git a/src/bindings/config.ts b/src/bindings/config.ts index 55d0fb8be..43b5718fa 100644 --- a/src/bindings/config.ts +++ b/src/bindings/config.ts @@ -65,9 +65,7 @@ export const loadConfig = async (context: Context): Promise => { permitBaseUrl: process.env.PERMIT_BASE_URL || permitBaseUrl, }, unassign: { - timeRangeForMaxIssue: process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE - ? Number(process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE) - : timeRangeForMaxIssue, + timeRangeForMaxIssue: process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE ? Number(process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE) : timeRangeForMaxIssue, timeRangeForMaxIssueEnabled: process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE_ENABLED ? process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE_ENABLED == "true" : timeRangeForMaxIssueEnabled, diff --git a/src/configs/ubiquibot-config-default.ts b/src/configs/ubiquibot-config-default.ts index 9598ef782..f3e480666 100644 --- a/src/configs/ubiquibot-config-default.ts +++ b/src/configs/ubiquibot-config-default.ts @@ -87,7 +87,20 @@ export const DefaultConfig: MergedConfig = { ], incentives: { comment: { - elements: {}, + issue: { + assignee: false, + creator: false, + default: true, + }, + pullRequest: { + assignee: false, + creator: false, + reviewer: true, + default: true, + }, + elements: { + p: 0.1, + }, totals: { word: 0, }, diff --git a/src/decs.d.ts b/src/decs.d.ts new file mode 100644 index 000000000..2e182e95b --- /dev/null +++ b/src/decs.d.ts @@ -0,0 +1 @@ +declare module "mdast-util-gfm"; diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index e1ef60e76..7b7d4a3fe 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -2,12 +2,13 @@ import { getWalletAddress } from "../../adapters/supabase"; import { getBotContext, getLogger } from "../../bindings"; import { getAllIssueComments, getAllPullRequestReviews, getIssueDescription, parseComments } from "../../helpers"; import { getLatestPullRequest, gitLinkedPrParser } from "../../helpers/parser"; -import { Incentives, MarkdownItem, Payload, UserType } from "../../types"; +import { Incentives, MarkdownItem, MarkdownItems, Payload, UserType } from "../../types"; import { RewardsResponse, commentParser } from "../comment"; import Decimal from "decimal.js"; import { bountyInfo } from "../wildcard"; import { IncentivesCalculationResult } from "./action"; import { BigNumber } from "ethers"; +import { HTMLItem } from "../../types/html"; export interface CreatorCommentResult { title: string; @@ -50,8 +51,8 @@ export const calculateIssueConversationReward = async (calculateIncentives: Ince logger.info(`Skipping to parse the comment because it contains commands. comment: ${JSON.stringify(issueComment)}`); continue; } - if (!issueComment.body_html) { - logger.info(`Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(issueComment)}`); + if (!issueComment.body) { + logger.info(`Skipping to parse the comment because body is undefined. comment: ${JSON.stringify(issueComment)}`); continue; } @@ -59,7 +60,7 @@ export const calculateIssueConversationReward = async (calculateIncentives: Ince if (!issueCommentsByUser[user.login]) { issueCommentsByUser[user.login] = { id: user.id, comments: [] }; } - issueCommentsByUser[user.login].comments.push(issueComment.body_html); + issueCommentsByUser[user.login].comments.push(issueComment.body); } logger.info(`Filtering by the user type done. commentsByUser: ${JSON.stringify(issueCommentsByUser)}`); @@ -298,45 +299,80 @@ const generatePermitForComments = async ( * @returns - The reward value */ const calculateRewardValue = ( - comments: Record, + comments: Record, incentives: Incentives ): { sum: Decimal; sumByType: Record } => { let sum = new Decimal(0); const sumByType: Record = {}; - for (const key of Object.keys(comments)) { - const value = comments[key]; + for (const item of MarkdownItems) { + const value = comments[item]; // Initialize the sum for this key if it doesn't exist - if (!sumByType[key]) { - sumByType[key] = { + if (!sumByType[item]) { + sumByType[item] = { count: 0, reward: new Decimal(0), }; } // if it's a text node calculate word count and multiply with the reward value - if (key == "#text") { + if (item === MarkdownItem.Text) { if (!incentives.comment.totals.word) { continue; } const wordReward = new Decimal(incentives.comment.totals.word); const wordCount = value.map((str) => str.trim().split(" ").length).reduce((totalWords, wordCount) => totalWords + wordCount, 0); const reward = wordReward.mul(wordCount); - sumByType[key].count += wordCount; - sumByType[key].reward = wordReward; + sumByType[item].count += wordCount; + sumByType[item].reward = wordReward; sum = sum.add(reward); } else { - if (!incentives.comment.elements[key]) { + const htmlTag = MarkdownItemToHTMLTag[item]; + if (!htmlTag || !incentives.comment.elements[htmlTag]) { continue; } - const rewardValue = new Decimal(incentives.comment.elements[key]); + const rewardValue = new Decimal(incentives.comment.elements[htmlTag]); const reward = rewardValue.mul(value.length); - sumByType[key].count += value.length; - sumByType[key].reward = rewardValue; + sumByType[item].count += value.length; + sumByType[item].reward = rewardValue; sum = sum.add(reward); } } return { sum, sumByType }; }; + +const MarkdownItemToHTMLTag: Record = { + [MarkdownItem.Text]: HTMLItem.P, + [MarkdownItem.Paragraph]: HTMLItem.P, + [MarkdownItem.Heading]: HTMLItem.H1, + [MarkdownItem.Heading1]: HTMLItem.H1, + [MarkdownItem.Heading2]: HTMLItem.H2, + [MarkdownItem.Heading3]: HTMLItem.H3, + [MarkdownItem.Heading4]: HTMLItem.H4, + [MarkdownItem.Heading5]: HTMLItem.H5, + [MarkdownItem.Heading6]: HTMLItem.H6, + [MarkdownItem.ListItem]: HTMLItem.LI, + [MarkdownItem.List]: HTMLItem.UL, + [MarkdownItem.Link]: HTMLItem.A, + [MarkdownItem.Image]: HTMLItem.IMG, + [MarkdownItem.BlockQuote]: HTMLItem.BLOCKQUOTE, + [MarkdownItem.Code]: HTMLItem.PRE, + [MarkdownItem.Emphasis]: HTMLItem.EM, + [MarkdownItem.Strong]: HTMLItem.STRONG, + [MarkdownItem.Delete]: HTMLItem.DEL, + [MarkdownItem.HTML]: HTMLItem.HTML, + [MarkdownItem.InlineCode]: HTMLItem.CODE, + [MarkdownItem.LinkReference]: HTMLItem.A, + [MarkdownItem.ImageReference]: HTMLItem.IMG, + [MarkdownItem.FootnoteReference]: HTMLItem.SUP, + [MarkdownItem.FootnoteDefinition]: HTMLItem.P, + [MarkdownItem.Table]: HTMLItem.TABLE, + [MarkdownItem.TableCell]: HTMLItem.TD, + [MarkdownItem.TableRow]: HTMLItem.TR, + [MarkdownItem.ThematicBreak]: HTMLItem.HR, + [MarkdownItem.Break]: HTMLItem.BR, + [MarkdownItem.Root]: HTMLItem.HTML, + [MarkdownItem.Definition]: HTMLItem.DL, +}; diff --git a/src/helpers/comment.ts b/src/helpers/comment.ts index 7be39376c..ada859c14 100644 --- a/src/helpers/comment.ts +++ b/src/helpers/comment.ts @@ -1,45 +1,92 @@ +import { MarkdownItem } from "../types"; +import fromMarkdown from "mdast-util-from-markdown"; +import gfmFromMarkdown from "mdast-util-gfm"; +import gfm from "micromark-extension-gfm"; import Decimal from "decimal.js"; import { isEmpty } from "lodash"; -import * as parse5 from "parse5"; type Node = { - nodeName: string; - tagName?: string; - value?: string; - childNodes?: Node[]; + type: MarkdownItem; + value: string; + depth?: number; + children: Node[]; }; -const traverse = (result: Record, node: Node, itemsToExclude: string[]): Record => { - if (itemsToExclude.includes(node.nodeName)) { - return result; +const traverse = (result: Record, node: Node, itemsToExclude: string[]): Record => { + if (!result[node.type]) { + result[node.type] = []; } - if (!result[node.nodeName]) { - result[node.nodeName] = []; + if (node.type === MarkdownItem.Heading) { + node.type = `heading${node.depth}` as MarkdownItem; } - result[node.nodeName].push(node.value?.trim() ?? ""); + result[node.type].push(node.value?.trim() ?? ""); + + if (itemsToExclude.includes(node.type)) { + return result; + } - if (node.childNodes && node.childNodes.length > 0) { - node.childNodes.forEach((child) => traverse(result, child, itemsToExclude)); + if (node.children && node.children.length > 0) { + node.children.forEach((child) => traverse(result, child, itemsToExclude)); } return result; }; -export const parseComments = (comments: string[], itemsToExclude: string[]): Record => { - const result: Record = {}; +export const parseComments = async (comments: string[], itemsToExclude: string[]): Promise> => { + const result: Record = { + [MarkdownItem.Text]: [], + [MarkdownItem.Paragraph]: [], + [MarkdownItem.Heading]: [], + [MarkdownItem.Heading1]: [], + [MarkdownItem.Heading2]: [], + [MarkdownItem.Heading3]: [], + [MarkdownItem.Heading4]: [], + [MarkdownItem.Heading5]: [], + [MarkdownItem.Heading6]: [], + [MarkdownItem.ListItem]: [], + [MarkdownItem.List]: [], + [MarkdownItem.Link]: [], + [MarkdownItem.Image]: [], + [MarkdownItem.BlockQuote]: [], + [MarkdownItem.Code]: [], + [MarkdownItem.Emphasis]: [], + [MarkdownItem.Strong]: [], + [MarkdownItem.Delete]: [], + [MarkdownItem.HTML]: [], + [MarkdownItem.InlineCode]: [], + [MarkdownItem.LinkReference]: [], + [MarkdownItem.ImageReference]: [], + [MarkdownItem.FootnoteReference]: [], + [MarkdownItem.FootnoteDefinition]: [], + [MarkdownItem.Table]: [], + [MarkdownItem.TableCell]: [], + [MarkdownItem.TableRow]: [], + [MarkdownItem.ThematicBreak]: [], + [MarkdownItem.Break]: [], + [MarkdownItem.Root]: [], + [MarkdownItem.Definition]: [], + }; for (const comment of comments) { - const fragment = parse5.parseFragment(comment); - traverse(result, fragment as Node, itemsToExclude); + const tree = fromMarkdown(comment, { + extensions: [gfm()], + mdastExtensions: [gfmFromMarkdown.fromMarkdown], + }); + console.log(`Comment Mdast Tree: ${JSON.stringify(tree, null, 2)}`); + traverse(result, tree as Node, itemsToExclude); } + console.log(`Comment Parsed: ${JSON.stringify(result, null, 2)}`); + // remove empty values - if (result["#text"]) { - result["#text"] = result["#text"].filter((str) => str.length > 0); + if (result[MarkdownItem.Text]) { + result[MarkdownItem.Text] = result[MarkdownItem.Text].filter((str) => str.length > 0); } + console.log(`Comment Parsed Cleaned: ${JSON.stringify(result, null, 2)}`); + return result; }; diff --git a/src/types/config.ts b/src/types/config.ts index a22683a28..577756af3 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -13,6 +13,23 @@ export type LabelItem = Static; const CommentIncentivesSchema = Type.Object( { + issue: Type.Object( + { + assignee: Type.Boolean(), + creator: Type.Boolean(), + default: Type.Boolean(), + }, + { additionalProperties: false } + ), + pullRequest: Type.Object( + { + assignee: Type.Boolean(), + creator: Type.Boolean(), + reviewer: Type.Boolean(), + default: Type.Boolean(), + }, + { additionalProperties: false } + ), elements: Type.Record(Type.String(), Type.Number()), totals: Type.Object( { diff --git a/src/types/html.ts b/src/types/html.ts new file mode 100644 index 000000000..33cb32d01 --- /dev/null +++ b/src/types/html.ts @@ -0,0 +1,27 @@ +export enum HTMLItem { + P = "p", + H1 = "h1", + H2 = "h2", + H3 = "h3", + H4 = "h4", + H5 = "h5", + H6 = "h6", + UL = "ul", + A = "a", + IMG = "img", + BLOCKQUOTE = "blockquote", + CODE = "code", + EM = "em", + STRONG = "strong", + DEL = "del", + HTML = "html", + SUP = "sup", + LI = "li", + TABLE = "table", + TR = "tr", + TD = "td", + HR = "hr", + BR = "br", + DL = "dl", + PRE = "pre", +} diff --git a/src/types/markdown.ts b/src/types/markdown.ts index 3b5d8f5d3..ae7b36cd8 100644 --- a/src/types/markdown.ts +++ b/src/types/markdown.ts @@ -1,10 +1,70 @@ -export const MarkdownItem = { - Paragraph: "paragraph", - List: "list", - Link: "link", - Text: "text", - Code: "code", - Image: "image", - BlockQuote: "blockquote", -} as const; -export type MarkdownItem = (typeof MarkdownItem)[keyof typeof MarkdownItem]; +// All types supported by standard Markdown and GFM +export enum MarkdownItem { + // Standard Markdown + BlockQuote = "blockquote", + Break = "break", + Code = "code", + Definition = "definition", + Emphasis = "emphasis", + Heading = "heading", + HTML = "html", + Image = "image", + ImageReference = "imageReference", + InlineCode = "inlineCode", + Link = "link", + LinkReference = "linkReference", + List = "list", + ListItem = "listItem", + Paragraph = "paragraph", + Root = "root", + Strong = "strong", + Text = "text", + ThematicBreak = "thematicBreak", + // GFM + Delete = "delete", + FootnoteDefinition = "footnoteDefinition", + FootnoteReference = "footnoteReference", + Table = "table", + TableCell = "tableCell", + TableRow = "tableRow", + // Our custom types to make it compatible with HTML + Heading1 = "heading1", + Heading2 = "heading2", + Heading3 = "heading3", + Heading4 = "heading4", + Heading5 = "heading5", + Heading6 = "heading6", +} +export const MarkdownItems = [ + MarkdownItem.BlockQuote, + MarkdownItem.Break, + MarkdownItem.Code, + MarkdownItem.Definition, + MarkdownItem.Emphasis, + MarkdownItem.Heading, + MarkdownItem.HTML, + MarkdownItem.Image, + MarkdownItem.ImageReference, + MarkdownItem.InlineCode, + MarkdownItem.Link, + MarkdownItem.LinkReference, + MarkdownItem.List, + MarkdownItem.ListItem, + MarkdownItem.Paragraph, + MarkdownItem.Root, + MarkdownItem.Strong, + MarkdownItem.Text, + MarkdownItem.ThematicBreak, + MarkdownItem.Delete, + MarkdownItem.FootnoteDefinition, + MarkdownItem.FootnoteReference, + MarkdownItem.Table, + MarkdownItem.TableCell, + MarkdownItem.TableRow, + MarkdownItem.Heading1, + MarkdownItem.Heading2, + MarkdownItem.Heading3, + MarkdownItem.Heading4, + MarkdownItem.Heading5, + MarkdownItem.Heading6, +] as const; diff --git a/yarn.lock b/yarn.lock index 65e3ead1b..bb224a210 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2528,6 +2528,13 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.198.tgz#4d27465257011aedc741a809f1269941fa2c5d4c" integrity sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg== +"@types/mdast@^3.0.0": + version "3.0.12" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.12.tgz#beeb511b977c875a5b0cc92eab6fcac2f0895514" + integrity sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg== + dependencies: + "@types/unist" "^2" + "@types/mime@*": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" @@ -2678,6 +2685,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== +"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.7.tgz#5b06ad6894b236a1d2bd6b2f07850ca5c59cf4d6" + integrity sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g== + "@types/websocket@^1.0.3": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.6.tgz#ec8dce5915741632ac3a4b1f951b6d4156e32d03" @@ -3483,6 +3495,11 @@ capture-exit@^2.0.0: dependencies: rsvp "^4.8.4" +ccount@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" + integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== + chalk-template@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-1.1.0.tgz#ffc55db6dd745e9394b85327c8ac8466edb7a7b1" @@ -3517,6 +3534,21 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + charenc@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" @@ -4090,7 +4122,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -5622,6 +5654,19 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -5672,6 +5717,11 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -5739,6 +5789,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -6783,6 +6838,11 @@ log-update@^5.0.1: strip-ansi "^7.0.1" wrap-ansi "^8.0.1" +longest-streak@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" + integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== + lowercase-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" @@ -6853,6 +6913,13 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-table@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b" + integrity sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A== + dependencies: + repeat-string "^1.0.0" + md5@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" @@ -6862,6 +6929,85 @@ md5@^2.3.0: crypt "0.0.2" is-buffer "~1.1.6" +mdast-util-find-and-replace@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz#b7db1e873f96f66588c321f1363069abf607d1b5" + integrity sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA== + dependencies: + escape-string-regexp "^4.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +mdast-util-from-markdown@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" + integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-string "^2.0.0" + micromark "~2.11.0" + parse-entities "^2.0.0" + unist-util-stringify-position "^2.0.0" + +mdast-util-gfm-autolink-literal@^0.1.0: + version "0.1.3" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.3.tgz#9c4ff399c5ddd2ece40bd3b13e5447d84e385fb7" + integrity sha512-GjmLjWrXg1wqMIO9+ZsRik/s7PLwTaeCHVB7vRxUwLntZc8mzmTsLVr6HW1yLokcnhfURsn5zmSVdi3/xWWu1A== + dependencies: + ccount "^1.0.0" + mdast-util-find-and-replace "^1.1.0" + micromark "^2.11.3" + +mdast-util-gfm-strikethrough@^0.2.0: + version "0.2.3" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz#45eea337b7fff0755a291844fbea79996c322890" + integrity sha512-5OQLXpt6qdbttcDG/UxYY7Yjj3e8P7X16LzvpX8pIQPYJ/C2Z1qFGMmcw+1PZMUM3Z8wt8NRfYTvCni93mgsgA== + dependencies: + mdast-util-to-markdown "^0.6.0" + +mdast-util-gfm-table@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.6.tgz#af05aeadc8e5ee004eeddfb324b2ad8c029b6ecf" + integrity sha512-j4yDxQ66AJSBwGkbpFEp9uG/LS1tZV3P33fN1gkyRB2LoRL+RR3f76m0HPHaby6F4Z5xr9Fv1URmATlRRUIpRQ== + dependencies: + markdown-table "^2.0.0" + mdast-util-to-markdown "~0.6.0" + +mdast-util-gfm-task-list-item@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz#70c885e6b9f543ddd7e6b41f9703ee55b084af10" + integrity sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A== + dependencies: + mdast-util-to-markdown "~0.6.0" + +mdast-util-gfm@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-0.1.2.tgz#8ecddafe57d266540f6881f5c57ff19725bd351c" + integrity sha512-NNkhDx/qYcuOWB7xHUGWZYVXvjPFFd6afg6/e2g+SV4r9q5XUcCbV4Wfa3DLYIiD+xAEZc6K4MGaE/m0KDcPwQ== + dependencies: + mdast-util-gfm-autolink-literal "^0.1.0" + mdast-util-gfm-strikethrough "^0.2.0" + mdast-util-gfm-table "^0.1.0" + mdast-util-gfm-task-list-item "^0.1.0" + mdast-util-to-markdown "^0.6.1" + +mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-markdown@~0.6.0: + version "0.6.5" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" + integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ== + dependencies: + "@types/unist" "^2.0.0" + longest-streak "^2.0.0" + mdast-util-to-string "^2.0.0" + parse-entities "^2.0.0" + repeat-string "^1.0.0" + zwitch "^1.0.0" + +mdast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" + integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -6904,6 +7050,59 @@ methods@^1.1.2, methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micromark-extension-gfm-autolink-literal@~0.5.0: + version "0.5.7" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz#53866c1f0c7ef940ae7ca1f72c6faef8fed9f204" + integrity sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw== + dependencies: + micromark "~2.11.3" + +micromark-extension-gfm-strikethrough@~0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz#96cb83356ff87bf31670eefb7ad7bba73e6514d1" + integrity sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw== + dependencies: + micromark "~2.11.0" + +micromark-extension-gfm-table@~0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz#4d49f1ce0ca84996c853880b9446698947f1802b" + integrity sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA== + dependencies: + micromark "~2.11.0" + +micromark-extension-gfm-tagfilter@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz#d9f26a65adee984c9ccdd7e182220493562841ad" + integrity sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q== + +micromark-extension-gfm-task-list-item@~0.3.0: + version "0.3.3" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz#d90c755f2533ed55a718129cee11257f136283b8" + integrity sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ== + dependencies: + micromark "~2.11.0" + +micromark-extension-gfm@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz#36d1a4c089ca8bdfd978c9bd2bf1a0cb24e2acfe" + integrity sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A== + dependencies: + micromark "~2.11.0" + micromark-extension-gfm-autolink-literal "~0.5.0" + micromark-extension-gfm-strikethrough "~0.6.5" + micromark-extension-gfm-table "~0.4.0" + micromark-extension-gfm-tagfilter "~0.3.0" + micromark-extension-gfm-task-list-item "~0.3.0" + +micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3: + version "2.11.4" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" + integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== + dependencies: + debug "^4.0.0" + parse-entities "^2.0.0" + micromatch@4.0.5, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -7549,6 +7748,18 @@ parse-bmfont-xml@^1.1.4: xml-parse-from-string "^1.0.0" xml2js "^0.4.5" +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + parse-headers@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" @@ -8187,7 +8398,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== -repeat-string@^1.6.1: +repeat-string@^1.0.0, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== @@ -9251,6 +9462,26 @@ unique-string@^3.0.0: dependencies: crypto-random-string "^4.0.0" +unist-util-is@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" + integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== + +unist-util-stringify-position@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + dependencies: + "@types/unist" "^2.0.2" + +unist-util-visit-parents@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" + integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + universal-github-app-jwt@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.1.1.tgz#d57cee49020662a95ca750a057e758a1a7190e6e" @@ -9748,3 +9979,8 @@ yocto-queue@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== + +zwitch@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" + integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==