diff --git a/src/github/renderer/make-mark.ts b/src/github/renderer/make-mark.ts new file mode 100644 index 00000000..606574d8 --- /dev/null +++ b/src/github/renderer/make-mark.ts @@ -0,0 +1,54 @@ +import { fromMarkdown } from 'mdast-util-from-markdown'; +import { Content, Parent } from 'mdast-util-from-markdown/lib/index'; +import { gfmFromMarkdown, gfmToMarkdown } from 'mdast-util-gfm'; +import { toMarkdown } from 'mdast-util-to-markdown'; +import { gfm } from 'micromark-extension-gfm'; + +export function parseMarkdown(text: string) { + const tree = fromMarkdown(trimLeadingWS(text), { + extensions: [gfm()], + mdastExtensions: [gfmFromMarkdown()], + }); + return tree; +} + +function trimLeadingWS(str: string) { + /* + Get the initial indentation + But ignore new line characters + */ + const matcher = /^[\r\n]?(\s+)/; + if (matcher.test(str)) { + /* + Replace the initial whitespace + globally and over multiple lines + */ + return str.replace(new RegExp('^' + str.match(matcher)![1], 'gm'), ''); + } else { + // Regex doesn't match so return the original string + return str; + } +} + +export function walk(root: Parent, cb: (token: Content) => boolean | void) { + root.children.forEach((node) => { + if (node) { + const skip = cb(node); + if (!skip) { + if ((node as Parent).children) { + walk(node as Parent, cb); + } + } + } + }); +} + +export function makeMarkdown(tree: Parent) { + return toMarkdown(tree, { + extensions: [gfmToMarkdown()], + listItemIndent: 'one', + rule: '-', + fence: '`', + fences: true, + }); +} diff --git a/src/github/templates/utils.ts b/src/github/templates/utils.ts index 5d6acaa4..4772eed7 100644 --- a/src/github/templates/utils.ts +++ b/src/github/templates/utils.ts @@ -1,6 +1,10 @@ import capitalize from 'lodash/capitalize'; -import { StringBuilder, limitTextByPosition } from '@/utils/string-builder'; +import { + StringBuilder, + limitTextByPosition, + tryReplaceImageToNull, +} from '@/utils/string-builder'; import { render } from '../renderer'; diff --git a/src/github/utils.ts b/src/github/utils.ts index 31d9bbde..20781494 100644 --- a/src/github/utils.ts +++ b/src/github/utils.ts @@ -1,20 +1,11 @@ import { EmitterWebhookEventName } from '@octokit/webhooks'; -import { fromMarkdown } from 'mdast-util-from-markdown'; -import { - Root, - Content, - Parent, - Link, - Text, -} from 'mdast-util-from-markdown/lib/index'; -import { gfmFromMarkdown, gfmToMarkdown } from 'mdast-util-gfm'; -import { toMarkdown } from 'mdast-util-to-markdown'; -import { gfm } from 'micromark-extension-gfm'; +import { Link, Text } from 'mdast-util-from-markdown/lib/index'; import { markdown } from '@/im/message'; import { ISetting } from '@/kv/types'; import { send } from '@opensumi/dingtalk-bot/lib/utils'; +import { makeMarkdown, parseMarkdown, walk } from './renderer/make-mark'; import { MarkdownContent } from './types'; function securityInterception(text: string) { @@ -47,45 +38,6 @@ function checkLinkIsLiteral(link: Link) { } } -export function walk(root: Parent, cb: (token: Content) => boolean | void) { - root.children.forEach((node) => { - if (node) { - const skip = cb(node); - if (!skip) { - if ((node as Parent).children) { - walk(node as Parent, cb); - } - } - } - }); -} - -function trimLeadingWS(str: string) { - /* - Get the initial indentation - But ignore new line characters - */ - const matcher = /^[\r\n]?(\s+)/; - if (matcher.test(str)) { - /* - Replace the initial whitespace - globally and over multiple lines - */ - return str.replace(new RegExp('^' + str.match(matcher)![1], 'gm'), ''); - } else { - // Regex doesn't match so return the original string - return str; - } -} - -function parseMarkdown(text: string) { - const tree = fromMarkdown(trimLeadingWS(text), { - extensions: [gfm()], - mdastExtensions: [gfmFromMarkdown()], - }); - return tree; -} - export function replaceGitHubUrlToMarkdown( text: string, options: ReplaceOptions, @@ -134,27 +86,13 @@ export function replaceGitHubUrlToMarkdown( return true; } }); - text = toMarkdown(tree, { - extensions: [gfmToMarkdown()], - listItemIndent: 'one', - rule: '-', - }); return text; } -export function toDingtalkMarkdown(tree: Root) { - return toMarkdown(tree, { - extensions: [gfmToMarkdown()], - listItemIndent: 'one', - fence: '`', - fences: true, - }); -} - export function standardizeMarkdown(text: string) { const tree = parseMarkdown(text); - return toDingtalkMarkdown(tree); + return makeMarkdown(tree); } export async function sendContentToDing( @@ -211,6 +149,10 @@ export async function sendToDing( } export function replaceGitHubText(text: string) { + if (!text.includes(' { + if (node.type === 'image') { + imageCount++; + node.url = ''; + node.alt = ''; + node.title = ''; + return true; + } + }); + + const result = makeMarkdown(ast); + + return { result, imageCount }; +} + export function limitTextByPosition(text: string, position: number) { + // replace all image url to null + const { result, imageCount } = tryReplaceImageToNull(text); + + // if images count less than 8, we only process the non-image text + if (imageCount < 8) { + text = result; + } + const arrayOfLines = text.replace(/\r\n|\n\r|\n|\r/g, '\n').split('\n'); let count = 0; diff --git a/test/github/__snapshots__/utils.test.ts.snap b/test/github/__snapshots__/utils.test.ts.snap index ad846540..dd3e5042 100644 --- a/test/github/__snapshots__/utils.test.ts.snap +++ b/test/github/__snapshots__/utils.test.ts.snap @@ -1,5 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`github utils can replace image to null 1`] = ` +{ + "imageCount": 1, + "result": "![]() +看起来这个分支有个报错关于 TerminalClient 的,有可能是 init 时机有点问题 +", +} +`; + exports[`github utils can transform image 1`] = ` "![](https://user-images.githubusercontent.com/2226423/153811718-2babbfa7-e63f-4ec7-9fd3-9f450beaad9b.png) 看起来这个分支有个报错关于 TerminalClient 的,有可能是 init 时机有点问题" diff --git a/test/github/utils.test.ts b/test/github/utils.test.ts index d8b32ac4..6b9973a9 100644 --- a/test/github/utils.test.ts +++ b/test/github/utils.test.ts @@ -6,9 +6,16 @@ import { parseGitHubUrl, standardizeMarkdown, } from '@/github/utils'; -import { StringBuilder, limitTextByPosition } from '@/utils/string-builder'; +import { + StringBuilder, + limitTextByPosition, + tryReplaceImageToNull, +} from '@/utils/string-builder'; import * as DingUtils from '@opensumi/dingtalk-bot/lib/utils'; +const commentWithImg = `image +看起来这个分支有个报错关于 TerminalClient 的,有可能是 init 时机有点问题`; + describe('github utils', () => { it('can limit lines', () => { const text = `line1\nline2\nline3\n`; @@ -17,9 +24,7 @@ describe('github utils', () => { }); it('can transform image', () => { - const comment = `image -看起来这个分支有个报错关于 TerminalClient 的,有可能是 init 时机有点问题`; - const data = new StringBuilder(comment); + const data = new StringBuilder(commentWithImg); expect(data.build()).toMatchSnapshot(); }); @@ -293,4 +298,9 @@ https://github.com/opensumi/core/blob/3455b10620badfe7b03a02d66136d3226b7891b8/p expect(result).toContain(`hi\\~`); console.log(`it ~ result:`, result); }); + + it('can replace image to null', () => { + const d = tryReplaceImageToNull(commentWithImg); + expect(d).toMatchSnapshot(); + }); });