diff --git a/__tests__/github/renderer/__snapshots__/make-mark.test.ts.snap b/__tests__/github/renderer/__snapshots__/make-mark.test.ts.snap new file mode 100644 index 0000000..c0efdb7 --- /dev/null +++ b/__tests__/github/renderer/__snapshots__/make-mark.test.ts.snap @@ -0,0 +1,150 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`github renderer make-mark convertToDingMarkdown: convertToDingMarkdown 1`] = ` +"#### [coderabbitai\\[bot\\]](https://github.com/apps/coderabbitai) created [review comment](https://github.com/opensumi/core/pull/4026#discussion_r1766221614) on [pull request](https://github.com/opensumi/core/pull/4026) + +#### [#4026 fix: use async in watch file changes](https://github.com/opensumi/core/pull/4026) + +--- + +> \\[!TIP] +> Codebase Verification + +**建议移除未使用的常量 FRAME\\_FOUR,保留 FRAME\\_FIVE。** + +经过验证,发现: + +* \`FRAME_FOUR\` 常量在代码库中除了定义外没有被使用。建议将其移除,以减少不必要的代码。 +* \`FRAME_FIVE\` 常量在 \`packages/file-service/src/node/recursive/file-service-watcher.ts\` 文件中被使用,用于 throttle 函数的实现。应当保留此常量。 + +建议采取的行动: + +* 删除 \`packages/utils/src/async.ts\` 文件中的 \`FRAME_FOUR\` 常量定义。 +* 保留 \`FRAME_FIVE\` 常量,因为它在项目中有实际用途。 + +
+Analysis chain + +**检查新增常量在代码库中的使用情况。** + +新增的 \`FRAME_FOUR\` 和 \`FRAME_FIVE\` 常量本身没有问题,但需要检查它们在代码库中是否被实际使用到。如果只是添加了常量而没有在任何地方引用,那么这些常量的存在就没有太大意义,反而会增加代码的理解难度。 + +运行以下脚本检查常量的使用情况: + +如果搜索结果只有常量的定义而没有其他引用,那么建议移除这两个目前没有被使用的常量。 + +
+ +
+Scripts executed + +The following scripts were executed for the analysis: + +Script: + +\`\`\`shell +#!/bin/bash +# 检查 FRAME_FOUR 和 FRAME_FIVE 常量的使用情况 + +# 在 .ts 和 .js 文件中搜索对 FRAME_FOUR 的使用 +rg --type ts --type js $'FRAME_FOUR' + +# 在 .ts 和 .js 文件中搜索对 FRAME_FIVE 的使用 +rg --type ts --type js $'FRAME_FIVE' + +\`\`\` + +Length of output: 466 + +
+" +`; + +exports[`github renderer make-mark parse and make 1`] = ` +"# GFM + +## Autolink literals + +[www.example.com](http://www.example.com), , and . + +## Footnote + +A note[^1] + +[^1]: Big note. + +## Strikethrough + +~~one~~ or ~~two~~ tildes. + +## Table + +| a | b | c | d | +| - | :- | -: | :-: | + +## Tasklist + +* [ ] to do +* [x] done +" +`; + +exports[`github renderer make-mark parse and make with code 1`] = ` +"#### [coderabbitai\\[bot\\]](https://github.com/apps/coderabbitai) created [review comment](https://github.com/opensumi/core/pull/4026#discussion_r1766221614) on [pull request](https://github.com/opensumi/core/pull/4026) + +#### [#4026 fix: use async in watch file changes](https://github.com/opensumi/core/pull/4026) + +--- + +> \\[!TIP] +> Codebase Verification + +**建议移除未使用的常量 FRAME\\_FOUR,保留 FRAME\\_FIVE。** + +经过验证,发现: + +* \`FRAME_FOUR\` 常量在代码库中除了定义外没有被使用。建议将其移除,以减少不必要的代码。 +* \`FRAME_FIVE\` 常量在 \`packages/file-service/src/node/recursive/file-service-watcher.ts\` 文件中被使用,用于 throttle 函数的实现。应当保留此常量。 + +建议采取的行动: + +* 删除 \`packages/utils/src/async.ts\` 文件中的 \`FRAME_FOUR\` 常量定义。 +* 保留 \`FRAME_FIVE\` 常量,因为它在项目中有实际用途。 + +
+Analysis chain + +**检查新增常量在代码库中的使用情况。** + +新增的 \`FRAME_FOUR\` 和 \`FRAME_FIVE\` 常量本身没有问题,但需要检查它们在代码库中是否被实际使用到。如果只是添加了常量而没有在任何地方引用,那么这些常量的存在就没有太大意义,反而会增加代码的理解难度。 + +运行以下脚本检查常量的使用情况: + +如果搜索结果只有常量的定义而没有其他引用,那么建议移除这两个目前没有被使用的常量。 + +
+ +
+Scripts executed + +The following scripts were executed for the analysis: + +Script: + +\`\`\`shell +#!/bin/bash +# 检查 FRAME_FOUR 和 FRAME_FIVE 常量的使用情况 + +# 在 .ts 和 .js 文件中搜索对 FRAME_FOUR 的使用 +rg --type ts --type js $'FRAME_FOUR' + +# 在 .ts 和 .js 文件中搜索对 FRAME_FIVE 的使用 +rg --type ts --type js $'FRAME_FIVE' + +\`\`\` + +Length of output: 466 + +
+" +`; diff --git a/__tests__/github/renderer/gfm.md b/__tests__/github/renderer/gfm.md new file mode 100644 index 0000000..60420d2 --- /dev/null +++ b/__tests__/github/renderer/gfm.md @@ -0,0 +1,25 @@ +# GFM + +## Autolink literals + +[www.example.com](http://www.example.com), , and . + +## Footnote + +A note[^1] + +[^1]: Big note. + +## Strikethrough + +~~one~~ or ~~two~~ tildes. + +## Table + +| a | b | c | d | +| --- | :-- | --: | :-: | + +## Tasklist + +- [ ] to do +- [x] done diff --git a/__tests__/github/renderer/make-mark.test.ts b/__tests__/github/renderer/make-mark.test.ts new file mode 100644 index 0000000..6166cb7 --- /dev/null +++ b/__tests__/github/renderer/make-mark.test.ts @@ -0,0 +1,35 @@ +import { readFile } from 'fs/promises'; +import path from 'path'; + +import { convertToDingMarkdown } from '@/github/dingtalk'; +import { replaceGitHubText } from '@/github/gfm'; +import { parseMarkdown, makeMarkdown } from '@/github/renderer/make-mark'; + +describe('github renderer make-mark', () => { + it('parse and make', async () => { + const md = await readFile(path.join(__dirname, './gfm.md'), 'utf-8'); + const parsed = parseMarkdown(md); + const made = makeMarkdown(parsed); + expect(made).toMatchSnapshot(); + }); + it('parse and make with code', async () => { + let md = await readFile( + path.join(__dirname, './review_comment_created.md'), + 'utf-8', + ); + + md = replaceGitHubText(md); + const parsed = parseMarkdown(md); + const made = makeMarkdown(parsed); + expect(made).toMatchSnapshot(); + }); + + it('convertToDingMarkdown', async () => { + const md = await readFile( + path.join(__dirname, './review_comment_created.md'), + 'utf-8', + ); + const made = convertToDingMarkdown('', md); + expect(made.markdown.text).toMatchSnapshot('convertToDingMarkdown'); + }); +}); diff --git a/__tests__/github/renderer/review_comment_created.md b/__tests__/github/renderer/review_comment_created.md new file mode 100644 index 0000000..ca4e36a --- /dev/null +++ b/__tests__/github/renderer/review_comment_created.md @@ -0,0 +1,56 @@ +#### [coderabbitai\[bot\]](https://github.com/apps/coderabbitai) created [review comment](https://github.com/opensumi/core/pull/4026#discussion_r1766221614) on [pull request](https://github.com/opensumi/core/pull/4026) + +#### [#4026 fix: use async in watch file changes](https://github.com/opensumi/core/pull/4026) + +--- + +> [!TIP] +> Codebase Verification + +**建议移除未使用的常量 FRAME_FOUR,保留 FRAME_FIVE。** + +经过验证,发现: + +- `FRAME_FOUR` 常量在代码库中除了定义外没有被使用。建议将其移除,以减少不必要的代码。 +- `FRAME_FIVE` 常量在 `packages/file-service/src/node/recursive/file-service-watcher.ts` 文件中被使用,用于 throttle 函数的实现。应当保留此常量。 + +建议采取的行动: + +- 删除 `packages/utils/src/async.ts` 文件中的 `FRAME_FOUR` 常量定义。 +- 保留 `FRAME_FIVE` 常量,因为它在项目中有实际用途。 + +
+Analysis chain + +**检查新增常量在代码库中的使用情况。** + +新增的 `FRAME_FOUR` 和 `FRAME_FIVE` 常量本身没有问题,但需要检查它们在代码库中是否被实际使用到。如果只是添加了常量而没有在任何地方引用,那么这些常量的存在就没有太大意义,反而会增加代码的理解难度。 + +运行以下脚本检查常量的使用情况: + +如果搜索结果只有常量的定义而没有其他引用,那么建议移除这两个目前没有被使用的常量。 + +
+ +
+Scripts executed + +The following scripts were executed for the analysis: + +Script: + +```shell +#!/bin/bash +# 检查 FRAME_FOUR 和 FRAME_FIVE 常量的使用情况 + +# 在 .ts 和 .js 文件中搜索对 FRAME_FOUR 的使用 +rg --type ts --type js $'FRAME_FOUR' + +# 在 .ts 和 .js 文件中搜索对 FRAME_FIVE 的使用 +rg --type ts --type js $'FRAME_FIVE' + +``` + +Length of output: 466 + +
diff --git a/__tests__/github/templates/__snapshots__/review.test.ts.snap b/__tests__/github/templates/__snapshots__/review.test.ts.snap index 51680ef..f3523ca 100644 --- a/__tests__/github/templates/__snapshots__/review.test.ts.snap +++ b/__tests__/github/templates/__snapshots__/review.test.ts.snap @@ -126,6 +126,72 @@ Length of output: 466 } `; +exports[`github templates pr review can handle complex code review 2`] = ` +{ + "markdown": { + "text": "#### [coderabbitai\\[bot\\]](https://github.com/apps/coderabbitai) created [review comment](https://github.com/opensumi/core/pull/4026#discussion_r1766221614) on [pull request](https://github.com/opensumi/core/pull/4026) + +#### [#4026 fix: use async in watch file changes](https://github.com/opensumi/core/pull/4026) + +--- + +> \\[!TIP] +> Codebase Verification + +**建议移除未使用的常量 FRAME\\_FOUR,保留 FRAME\\_FIVE。** + +经过验证,发现: + +* \`FRAME_FOUR\` 常量在代码库中除了定义外没有被使用。建议将其移除,以减少不必要的代码。 +* \`FRAME_FIVE\` 常量在 \`packages/file-service/src/node/recursive/file-service-watcher.ts\` 文件中被使用,用于 throttle 函数的实现。应当保留此常量。 + +建议采取的行动: + +* 删除 \`packages/utils/src/async.ts\` 文件中的 \`FRAME_FOUR\` 常量定义。 +* 保留 \`FRAME_FIVE\` 常量,因为它在项目中有实际用途。 + +
+Analysis chain + +**检查新增常量在代码库中的使用情况。** + +新增的 \`FRAME_FOUR\` 和 \`FRAME_FIVE\` 常量本身没有问题,但需要检查它们在代码库中是否被实际使用到。如果只是添加了常量而没有在任何地方引用,那么这些常量的存在就没有太大意义,反而会增加代码的理解难度。 + +运行以下脚本检查常量的使用情况: + +如果搜索结果只有常量的定义而没有其他引用,那么建议移除这两个目前没有被使用的常量。 + +
+ +
+Scripts executed + +The following scripts were executed for the analysis: + +Script: + +\`\`\`shell +#!/bin/bash +# 检查 FRAME_FOUR 和 FRAME_FIVE 常量的使用情况 + +# 在 .ts 和 .js 文件中搜索对 FRAME_FOUR 的使用 +rg --type ts --type js $'FRAME_FOUR' + +# 在 .ts 和 .js 文件中搜索对 FRAME_FIVE 的使用 +rg --type ts --type js $'FRAME_FIVE' + +\`\`\` + +Length of output: 466 + +
+", + "title": "Review comment created", + }, + "msgtype": "markdown", +} +`; + exports[`github templates pr review can handle pull_request_review_2_1_dismissed_dismissed 1`] = ` { "compactText": undefined, diff --git a/__tests__/github/templates/review.test.ts b/__tests__/github/templates/review.test.ts index b54f3e7..c4ebb3e 100644 --- a/__tests__/github/templates/review.test.ts +++ b/__tests__/github/templates/review.test.ts @@ -1,3 +1,7 @@ +import { writeFile } from 'fs/promises'; +import path from 'path'; + +import { convertToDingMarkdown } from '@/github/dingtalk'; import { handleReviewComment } from '@/github/templates/comment'; import { handleReview } from '@/github/templates/review'; @@ -19,8 +23,18 @@ describe('github templates pr review', () => { }); it('can handle complex code review', async () => { const result = await handleReviewComment(review_comment_created, ctx); - console.log(`review_comment_created ~ result`, result); expect(result).toMatchSnapshot(); + + if (process.env.WRITE_FILE) { + writeFile( + path.join(__dirname, './review_comment_created.md'), + result.text, + ); + } + + const dingContent = convertToDingMarkdown(result.title, result.text); + + expect(dingContent).toMatchSnapshot(); }); it('can handle pull_request_review_2_1_dismissed_dismissed', async () => { const result = await handleReview( diff --git a/__tests__/github/utils.test.ts b/__tests__/github/utils.test.ts index d94320d..2c949c3 100644 --- a/__tests__/github/utils.test.ts +++ b/__tests__/github/utils.test.ts @@ -10,7 +10,6 @@ import { StringBuilder, limitLine, limitTextByPosition, - transformMarkdownToLimitable, } from '@/utils/string-builder'; import * as DingUtils from '@opensumi/dingtalk-bot/lib/utils'; @@ -85,7 +84,7 @@ describe('github utils', () => { const urls = [] as string[]; jest .spyOn(DingUtils, 'send') - .mockImplementation(async (content, url, secret): Promise => { + .mockImplementation(async (content, url): Promise => { urls.push(url); }); @@ -311,18 +310,6 @@ https://github.com/opensumi/core/blob/3455b10620badfe7b03a02d66136d3226b7891b8/p console.log(`it ~ result:`, result); }); - it('can transform markdown to limitable', () => { - const d = transformMarkdownToLimitable(` - ${commentWithImg} -\`\`\` -asdfg -\`\`\` - -# a -## b - `); - expect(d).toMatchSnapshot(); - }); it('can handle pull_request_opened', async () => { const result = await handlePr(pr3628_open, ctx); diff --git a/lefthook.yml b/lefthook.yml index bb38217..2c5e6be 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -6,7 +6,7 @@ pre-commit: run: yarn eslint {staged_files} prettier: glob: '*.{js,ts,jsx,tsx,css,less,scss,vue,json,gql,md}' - run: + run: | yarn prettier {staged_files} -w git update-index --again diff --git a/package.json b/package.json index 11fc5d9..237d4d4 100644 --- a/package.json +++ b/package.json @@ -58,10 +58,8 @@ "lodash": "^4.17.21", "mdast-util-from-markdown": "^2.0.1", "mdast-util-gfm": "^3.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-to-markdown": "^2.1.0", "micromark-extension-gfm": "^3.0.0", - "micromark-extension-gfm-autolink-literal": "^2.0.0", "mnemonist": "^0.39.5", "mri": "^1.2.0", "openai-fetch": "^1.1.0", diff --git a/src/github/dingtalk.ts b/src/github/dingtalk.ts index 0fa583d..6972b40 100644 --- a/src/github/dingtalk.ts +++ b/src/github/dingtalk.ts @@ -15,6 +15,11 @@ import { send } from '@opensumi/dingtalk-bot/lib/utils'; import { MarkdownContent } from './types'; +function dingSecurityInterception(text: string) { + text = text.replaceAll('dingtalk://dingtalkclient/page/link?url=', ''); + return text; +} + /** * 钉钉最大 5000 字 */ @@ -23,13 +28,9 @@ export function convertToDingMarkdown( text: string, options?: IMakeMarkdownOptions, ): Markdown { - const _text = limitTextByPosition(text, 5000 - title.length - 10); - return _markdown(title, standardizeMarkdown(_text, options)); -} - -function dingSecurityInterception(text: string) { - text = text.replaceAll('dingtalk://dingtalkclient/page/link?url=', ''); - return text; + text = dingSecurityInterception(text); + text = limitTextByPosition(text, 5000 - title.length - 10); + return _markdown(title, standardizeMarkdown(text, options)); } export const createImageProxy = () => { @@ -37,7 +38,7 @@ export const createImageProxy = () => { handleImageUrl: (url: string) => { try { return context().getProxiedUrl(url); - } catch (error) { + } catch { return url; } }, @@ -60,10 +61,6 @@ export async function sendToDing( createImageProxy(), ); - dingContent.markdown.text = dingSecurityInterception( - dingContent.markdown.text, - ); - await sendContentToDing(dingContent, eventName, setting); } diff --git a/src/utils/string-builder.ts b/src/utils/string-builder.ts index 17d3233..e834ff8 100644 --- a/src/utils/string-builder.ts +++ b/src/utils/string-builder.ts @@ -1,6 +1,5 @@ import { replaceGitHubText } from '@/github/gfm'; import { render } from '@/github/renderer'; -import { makeMarkdown, parseMarkdown, walk } from '@/github/renderer/make-mark'; export interface IBuildOptions { appendNewLineToTheEnd?: boolean; @@ -100,57 +99,11 @@ export class StringBuilder { } } -/** - * remove image url and alt text, - * remove heading - * remove code block - */ -export function transformMarkdownToLimitable(text: string) { - text = replaceGitHubText(text); - - const ast = parseMarkdown(text); - - let imageCount = 0; - let headingDepthCount = 0; - - walk(ast, (node) => { - if (node.type === 'image') { - imageCount++; - node.url = ''; - node.alt = ''; - node.title = ''; - return true; - } else if (node.type === 'code') { - (node as any).type = 'text'; - node.lang = ''; - node.meta = ''; - return true; - } else if (node.type === 'heading') { - headingDepthCount = headingDepthCount + node.depth; - } - }); - - const result = makeMarkdown(ast); - - return { result, imageCount, headingDepthCount }; -} - export function limitTextByPosition( text: string, position: number, minLine = 6, ) { - // replace all image url to null - const { result, imageCount, headingDepthCount } = - transformMarkdownToLimitable(text); - - // if images count less than 8, we only process the non-image text - if (imageCount < 8) { - text = result; - // tolerate heading depth - position = position + headingDepthCount; - } - const arrayOfLines = text.replace(/\r\n|\n\r|\n|\r/g, '\n').split('\n'); let count = 0; @@ -168,12 +121,7 @@ export function limitTextByPosition( // 如果 limit 过后的行数小于 minLine, 则使用 minLine lineNo = lineNo < minLine ? minLine : lineNo; - const finalLines = arrayOfLines.slice(0, lineNo); - let finalContent = finalLines.join('\n').trim(); - if (lineNo < arrayOfLines.length) { - finalContent = finalContent + '\n...'; - } - return finalContent; + return limitLine(text, lineNo); } export function limitLine( diff --git a/yarn.lock b/yarn.lock index 4c7c9d6..e319e6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2415,10 +2415,8 @@ __metadata: lodash: "npm:^4.17.21" mdast-util-from-markdown: "npm:^2.0.1" mdast-util-gfm: "npm:^3.0.0" - mdast-util-gfm-autolink-literal: "npm:^2.0.0" mdast-util-to-markdown: "npm:^2.1.0" micromark-extension-gfm: "npm:^3.0.0" - micromark-extension-gfm-autolink-literal: "npm:^2.0.0" mnemonist: "npm:^0.39.5" mri: "npm:^1.2.0" nodemon: "npm:^3.1.4" @@ -9081,20 +9079,20 @@ __metadata: linkType: hard "micromark-extension-gfm-autolink-literal@npm:^2.0.0": - version: 2.0.0 - resolution: "micromark-extension-gfm-autolink-literal@npm:2.0.0" + version: 2.1.0 + resolution: "micromark-extension-gfm-autolink-literal@npm:2.1.0" dependencies: micromark-util-character: "npm:^2.0.0" micromark-util-sanitize-uri: "npm:^2.0.0" micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" - checksum: 10/77a3a3563ab2ffcf44c774a3f0ddcc1662d664e53ff2f42a528fb53564e9307331b35d01e7942a027198eb2e958cc2825cac96e87d6c4de301f535cfcaea0dc4 + checksum: 10/933b9b96ca62cd50732d9e58ae90ba446f4314e0ecbff3127e9aae430d9a295346f88fb33b5532acaf648d659b0db92e0c00c2e9f504c0d7b8bb4553318cac50 languageName: node linkType: hard "micromark-extension-gfm-footnote@npm:^2.0.0": - version: 2.0.0 - resolution: "micromark-extension-gfm-footnote@npm:2.0.0" + version: 2.1.0 + resolution: "micromark-extension-gfm-footnote@npm:2.1.0" dependencies: devlop: "npm:^1.0.0" micromark-core-commonmark: "npm:^2.0.0" @@ -9104,13 +9102,13 @@ __metadata: micromark-util-sanitize-uri: "npm:^2.0.0" micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" - checksum: 10/7813d226b862f84d417ff890f263961c1fdceaf4b02d543bf754e21b46b834bf524962acc9bb058af26edc65c838c194735fd858079c6340a0f217d031e0932d + checksum: 10/7e019414e31ab53c49c909b7068adbbcb1726433fce82bf735219276fe6e00a42b66288acb5c8831f80e77480fac34880eeeb60b1dc09d5885862b31db4b9ea2 languageName: node linkType: hard "micromark-extension-gfm-strikethrough@npm:^2.0.0": - version: 2.0.0 - resolution: "micromark-extension-gfm-strikethrough@npm:2.0.0" + version: 2.1.0 + resolution: "micromark-extension-gfm-strikethrough@npm:2.1.0" dependencies: devlop: "npm:^1.0.0" micromark-util-chunked: "npm:^2.0.0" @@ -9118,20 +9116,20 @@ __metadata: micromark-util-resolve-all: "npm:^2.0.0" micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" - checksum: 10/a06470195c55c20e6c8f4ecf0208ff3b58e1e4d530b1f377a9eaad857722b891a74aacb6dbc9755716282a1807d6acb6bb1e6e92295b7cef9060ab172d4abbed + checksum: 10/eaf2c7b1e3eb2a7d7f405e8abe561be083cc52b8e027225ed286490939f527d18c120df59c8d8e17fdcf284f8d014502bf3db45d8e36e3109457ece8fb1db29b languageName: node linkType: hard "micromark-extension-gfm-table@npm:^2.0.0": - version: 2.0.0 - resolution: "micromark-extension-gfm-table@npm:2.0.0" + version: 2.1.0 + resolution: "micromark-extension-gfm-table@npm:2.1.0" dependencies: devlop: "npm:^1.0.0" micromark-factory-space: "npm:^2.0.0" micromark-util-character: "npm:^2.0.0" micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" - checksum: 10/3fbdf52ba8c9d0fa2dddab2f6a669e4386ea58ff6b979de16e6d1ff4c055b7b933f138257326ee45b2b14c8319b7cdb264a9bb77330caccae176765c8a488fd0 + checksum: 10/37385c3b6e4833f9d9a277f98062af40ccf8c70e83726ab0c1ef9d6cb5784dd18489d1df62b241e8289349be11f5ab0ab3337043fe004bc9150f1067f9476c9b languageName: node linkType: hard @@ -9145,15 +9143,15 @@ __metadata: linkType: hard "micromark-extension-gfm-task-list-item@npm:^2.0.0": - version: 2.0.1 - resolution: "micromark-extension-gfm-task-list-item@npm:2.0.1" + version: 2.1.0 + resolution: "micromark-extension-gfm-task-list-item@npm:2.1.0" dependencies: devlop: "npm:^1.0.0" micromark-factory-space: "npm:^2.0.0" micromark-util-character: "npm:^2.0.0" micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" - checksum: 10/aa448eeac58e031ff863bcf40475a531c07cff10a127d77cd09ebce76922a329e1908091430102a253fc0fd79345f31273ee6a2b5a71344e4c400f532efb9472 + checksum: 10/c5f72929f0dca77df01442b721356624de6657364e2264ef50fc7226305976f302a49b670836f9494ce70a9b0335d974b5ef8e6457553c4c200bfc06d6951964 languageName: node linkType: hard