diff --git a/server/api/changelog/md/[provider]/[owner]/[repo]/[...path].get.ts b/server/api/changelog/md/[provider]/[owner]/[repo]/[...path].get.ts index a1582b1414..07174f2518 100644 --- a/server/api/changelog/md/[provider]/[owner]/[repo]/[...path].get.ts +++ b/server/api/changelog/md/[provider]/[owner]/[repo]/[...path].get.ts @@ -2,9 +2,13 @@ import { resolveURL } from 'ufo' import * as v from 'valibot' import { getBaseFileUrl } from '~~/server/utils/changelog/baseFileUrl' import { + createBitbucketRepoInfo, createForgejoRepoInfo, + createGiteaRepoInfo, + createGiteeRepoInfo, createGithubRepoInfo, createGitLabRepoInfo, + createSourcehutRepoInfo, createTangledInfo, } from '~~/server/utils/changelog/mdRepoInfo' import { validateHostWithValibot } from '~~/server/utils/changelog/validateHost' @@ -56,6 +60,7 @@ export default defineCachedEventHandler( headers: { 'User-Agent': 'npmx.dev', }, + timeout: 15_000, }) const markdown = v.parse(v.string(), data) if (raw != undefined) { @@ -114,5 +119,13 @@ function getRepoInfo( return createGitLabRepoInfo(host ?? 'gitlab.com', owner, repo, path) case 'tangled': return createTangledInfo(owner, repo, path) + case 'gitea': + return createGiteaRepoInfo(host ?? 'gitea.com', owner, repo, path) + case 'bitbucket': + return createBitbucketRepoInfo(owner, repo, path) + case 'sourcehut': + return createSourcehutRepoInfo(owner, repo, path) + case 'gitee': + return createGiteeRepoInfo(owner, repo, path) } } diff --git a/server/api/changelog/releases/[provider]/[owner]/[repo].get.ts b/server/api/changelog/releases/[provider]/[owner]/[repo].get.ts index 20e618072a..9737803d41 100644 --- a/server/api/changelog/releases/[provider]/[owner]/[repo].get.ts +++ b/server/api/changelog/releases/[provider]/[owner]/[repo].get.ts @@ -9,11 +9,19 @@ import { GithubReleaseCollectionSchama, ForgejoReleaseCollectionSchema, GitlabReleaseCollectionSchema, + GiteaReleaseCollectionSchema, + GiteeReleaseCollectionSchema, } from '~~/shared/schemas/changelog/release' import { changelogRenderer } from '~~/server/utils/changelog/markdown' -import { createForgejoRepoInfo, createGithubRepoInfo } from '~~/server/utils/changelog/mdRepoInfo' +import { + createForgejoRepoInfo, + createGiteaRepoInfo, + createGithubRepoInfo, +} from '~~/server/utils/changelog/mdRepoInfo' import { validateHostWithValibot } from '~~/server/utils/changelog/validateHost' +const TIMEOUT_TIME = 15_000 + export default defineCachedEventHandler( async event => { const provider = getRouterParam(event, 'provider') as ProviderId @@ -39,6 +47,10 @@ export default defineCachedEventHandler( return await getReleasesFromForgejo(owner, repo, host) case 'gitlab': return await getReleasesFromGitlab(owner, repo, host) + case 'gitea': + return await getReleasesFromGitea(owner, repo, host) + case 'gitee': + return await getReleasesFromGitee(owner, repo) default: throw createError({ @@ -79,6 +91,7 @@ async function getReleasesFromGithub(owner: string, repo: string) { 'Accept': '*/*', 'User-Agent': 'npmx.dev', }, + timeout: TIMEOUT_TIME, }) const { releases } = v.parse(GithubReleaseCollectionSchama, data) @@ -107,6 +120,7 @@ async function getReleasesFromForgejo(owner: string, repo: string, host: string) headers: { 'User-Agent': 'npmx.dev', }, + timeout: TIMEOUT_TIME, }) const releases = v.parse(ForgejoReleaseCollectionSchema, data) @@ -137,6 +151,7 @@ async function getReleasesFromGitlab(owner: string, repo: string, host: string) headers: { 'User-Agent': 'npmx.dev', }, + timeout: TIMEOUT_TIME, }) const releases = v.parse(GitlabReleaseCollectionSchema, data) @@ -158,3 +173,60 @@ async function getReleasesFromGitlab(owner: string, repo: string, host: string) } satisfies ReleaseData }) } + +async function getReleasesFromGitea(owner: string, repo: string, host: string) { + const data = await $fetch(`https://${host}/api/v1/repos/${owner}/${repo}/releases?draft=false`, { + headers: { + 'User-Agent': 'npmx.dev', + }, + timeout: TIMEOUT_TIME, + }) + const releases = v.parse(GiteaReleaseCollectionSchema, data) + + const render = await changelogRenderer(createGiteaRepoInfo(host, owner, repo)) + + return releases.map(r => { + const { html, toc } = render(r.body, r.id) + return { + id: r.id, + html: html?.replace(/(?)\n/g, '
') ?? null, + title: r.name || r.tag_name, + prerelease: r.prerelease, + toc, + link: r.html_url, + publishedAt: r.published_at, + draft: r.draft, + tag: r.tag_name, + } satisfies ReleaseData + }) +} + +async function getReleasesFromGitee(owner: string, repo: string) { + const data = await $fetch( + `https://gitee.com/api/v5/repos/${owner}/${repo}/releases?per_page=30`, + { + headers: { + 'User-Agent': 'npmx.dev', + }, + timeout: TIMEOUT_TIME, + }, + ) + + const releases = v.parse(GiteeReleaseCollectionSchema, data) + + const render = await changelogRenderer(createGiteeRepoInfo(owner, repo)) + + return releases.map(r => { + const { html, toc } = render(r.body, r.id) + return { + id: r.id, + html: html?.replace(/(?)\n/g, '
') ?? null, + title: r.name || r.tag_name, + prerelease: r.prerelease, + toc, + link: `https://gitee.com/${owner}/${repo}/releases/tag/${r.tag_name}`, + publishedAt: r.created_at, + tag: r.tag_name, + } satisfies ReleaseData + }) +} diff --git a/server/api/changelog/releases/[provider]/[owner]/[repo]/raw/[tag].get.ts b/server/api/changelog/releases/[provider]/[owner]/[repo]/raw/[tag].get.ts index a09079a1a8..4b623d2124 100644 --- a/server/api/changelog/releases/[provider]/[owner]/[repo]/raw/[tag].get.ts +++ b/server/api/changelog/releases/[provider]/[owner]/[repo]/raw/[tag].get.ts @@ -3,11 +3,15 @@ import * as v from 'valibot' import { ERROR_THROW_INCOMPLETE_PARAM } from '~~/shared/utils/constants' import { ForgejoReleaseSchama, + GiteaReleaseSchema, + GiteeReleaseSchema, GithubReleaseCollectionSchama, GitlabReleaseSchame, } from '~~/shared/schemas/changelog/release' import { validateHostWithValibot } from '~~/server/utils/changelog/validateHost' +const TIMEOUT_TIME = 15_000 + export default defineCachedEventHandler( async event => { const provider = getRouterParam(event, 'provider') as ProviderId @@ -40,6 +44,10 @@ export default defineCachedEventHandler( return await getMarkdownFromForgejo(owner, repo, encodedTag, host) case 'gitlab': return await getMarkdownFromGitlab(owner, repo, encodedTag, host) + case 'gitea': + return await getMarkdownFromGitea(owner, repo, encodedTag, host) + case 'gitee': + return await getMarkdownFromGitee(owner, repo, encodedTag) default: throw createError({ status: 404, @@ -84,8 +92,9 @@ async function getMarkdownFromGithub(owner: string, repo: string, tag: string, e 'User-Agent': 'npmx.dev', }, ignoreResponseError: true, + timeout: TIMEOUT_TIME, }, - ) + ).catch(() => null) const parsed = v.safeParse(v.object({ body: v.string() }), responseGithub) @@ -101,6 +110,7 @@ async function getMarkdownFromGithub(owner: string, repo: string, tag: string, e 'Accept': '*/*', 'User-Agent': 'npmx.dev', }, + timeout: TIMEOUT_TIME, }) const { releases } = v.parse(GithubReleaseCollectionSchama, responseUngh) @@ -129,6 +139,7 @@ async function getMarkdownFromForgejo( headers: { 'User-Agent': 'npmx.dev', }, + timeout: TIMEOUT_TIME, }) const release = v.parse(ForgejoReleaseSchama, data) @@ -150,9 +161,50 @@ async function getMarkdownFromGitlab( headers: { 'User-Agent': 'npmx.dev', }, + timeout: TIMEOUT_TIME, }) const release = v.parse(GitlabReleaseSchame, data) return release.description } + +async function getMarkdownFromGitea( + owner: string, + repo: string, + /** tag should be encoded */ + tag: string, + host: string = 'gitea.com', +) { + const data = await $fetch(`https://${host}/api/v1/repos/${owner}/${repo}/releases/tags/${tag}`, { + headers: { + 'User-Agent': 'npmx.dev', + }, + timeout: TIMEOUT_TIME, + }) + + const release = v.parse(GiteaReleaseSchema, data) + + return release.body +} + +async function getMarkdownFromGitee( + owner: string, + repo: string, + /** tag should be encoded */ + tag: string, +) { + const data = await $fetch( + `https://gitee.com/api/v5/repos/${owner}/${repo}/releases/tags/${tag}`, + { + headers: { + 'User-Agent': 'npmx.dev', + }, + timeout: TIMEOUT_TIME, + }, + ) + + const release = v.parse(GiteeReleaseSchema, data) + + return release.body +} diff --git a/server/utils/changelog/baseFileUrl.ts b/server/utils/changelog/baseFileUrl.ts index 7cda63169b..8643dc3e3e 100644 --- a/server/utils/changelog/baseFileUrl.ts +++ b/server/utils/changelog/baseFileUrl.ts @@ -16,7 +16,14 @@ export function getBaseFileUrl(ref: RepoRef): RepoFileUrl | null { raw: `https://codeberg.org/${ref.owner}/${ref.repo}/raw/branch/HEAD`, } case 'forgejo': { - const host = ref.host + return { + blob: `https://${ref.host}/${ref.owner}/${ref.repo}/src/branch/HEAD`, + raw: `https://${ref.host}/${ref.owner}/${ref.repo}/raw/branch/HEAD`, + } + } + case 'gitea': { + // although similar to forgejo, we keep these seperate because they're seperately maintained projects + const host = ref.host ?? 'gitea.com' return { blob: `https://${host}/${ref.owner}/${ref.repo}/src/branch/HEAD`, raw: `https://${host}/${ref.owner}/${ref.repo}/raw/branch/HEAD`, @@ -35,6 +42,24 @@ export function getBaseFileUrl(ref: RepoRef): RepoFileUrl | null { raw: `https://tangled.org/${ref.owner}/${ref.repo}/raw/HEAD`, } } + case 'bitbucket': { + return { + blob: `https://bitbucket.org/${ref.owner}/${ref.repo}/src/HEAD`, + raw: `https://bitbucket.org/${ref.owner}/${ref.repo}/raw/HEAD`, + } + } + case 'sourcehut': { + return { + blob: `https://git.sr.ht/${ref.owner}/${ref.repo}/tree/HEAD/item`, + raw: `https://git.sr.ht/${ref.owner}/${ref.repo}/blob/HEAD`, + } + } + case 'gitee': { + return { + blob: `https://gitee.com/${ref.owner}/${ref.repo}/blob/main`, + raw: `https://gitee.com/${ref.owner}/${ref.repo}/raw/main`, + } + } } return null } diff --git a/server/utils/changelog/detectChangelog.ts b/server/utils/changelog/detectChangelog.ts index 6289a7aebd..f7e3be71b1 100644 --- a/server/utils/changelog/detectChangelog.ts +++ b/server/utils/changelog/detectChangelog.ts @@ -8,6 +8,8 @@ import { GithubReleaseSchama, ForgejoReleaseSchama, GitlabReleaseSchame, + GiteaReleaseSchema, + GiteeReleaseSchema, } from '~~/shared/schemas/changelog/release' import { resolveURL } from 'ufo' import * as v from 'valibot' @@ -66,6 +68,12 @@ async function checkReleases( case 'gitlab': { return checkLatestGitlabRelease(ref, directory) } + case 'gitea': { + return checkLatestGiteaRelease(ref, directory) + } + case 'gitee': { + return checkLatestGiteeRelease(ref, directory) + } } return [false, null] } @@ -340,3 +348,130 @@ async function checkLatestGitlabRelease( } return [false, null] } + +// gitea +async function checkLatestGiteaRelease( + ref: RepoRef, + directory?: string, +): Promise> { + try { + const host = ref.host ?? 'gitea.com' + + const response = await $fetch( + `https://${host}/api/v1/repos/${ref.owner}/${ref.repo}/releases/latest`, + { + headers: { + 'User-Agent': 'npmx.dev', + 'accept': 'application/json', + }, + }, + ) + + const release = v.parse(GiteaReleaseSchema, response) + + const matchedChangelog = release.body?.match(MD_REGEX)?.at(0) + + // /src/branch/ can be similar to /blob/ + if (!matchedChangelog || !matchedChangelog.includes('/src/branch/')) { + return [ + { + type: 'release', + link: `https://${host}/${ref.owner}/${ref.repo}/releases`, + provider: ref.provider, + repo: `${ref.owner}/${ref.repo}`, + host: ref.host, + }, + null, + ] + } + + const path = matchedChangelog.replace(/^.*\/src\/branch\/[^/]+\//i, '') + if ( + directory && + !( + path.startsWith(directory.endsWith('/') ? directory : `${directory}/`) || + ROOT_ONLY_REGEX.test(path) + ) + ) { + return [false, null] as const + } + return [ + { + provider: ref.provider, + type: 'md', + path, + repo: `${ref.owner}/${ref.repo}`, + link: matchedChangelog, + host: ref.host, + }, + null, + ] + } catch (e) { + if (e instanceof Error) { + return [null, e] + } + } + return [false, null] +} + +async function checkLatestGiteeRelease( + ref: RepoRef, + directory?: string, +): Promise> { + try { + const response = await $fetch( + `https://gitee.com/api/v5/repos/${ref.owner}/${ref.repo}/releases/latest`, + { + headers: { + 'User-Agent': 'npmx.dev', + 'accept': 'application/json', + }, + }, + ) + + const release = v.parse(GiteeReleaseSchema, response) + + const matchedChangelog = release.body?.match(MD_REGEX)?.at(0) + + // if no changelog.md or the url doesn't contain /blob/ + if (!matchedChangelog || !matchedChangelog.includes('/blob/')) { + return [ + { + provider: ref.provider, + type: 'release', + repo: `${ref.owner}/${ref.repo}`, + link: `https://gitee.com/${ref.owner}/${ref.repo}/releases`, + }, + null, + ] + } + + const path = matchedChangelog.replace(/^.*\/blob\/[^/]+\//i, '') + + // makes sure that the correct directory is matched + if ( + directory && + !( + path.startsWith(directory.endsWith('/') ? directory : `${directory}/`) || + ROOT_ONLY_REGEX.test(path) + ) + ) { + return [false, null] + } + return [ + { + provider: ref.provider, + type: 'md', + path, + repo: `${ref.owner}/${ref.repo}`, + link: matchedChangelog, + }, + null, + ] + } catch (e) { + if (e instanceof Error) { + return [null, e] + } + } + return [false, null] +} diff --git a/server/utils/changelog/markdown.ts b/server/utils/changelog/markdown.ts index e57d3f42e3..43ca44b870 100644 --- a/server/utils/changelog/markdown.ts +++ b/server/utils/changelog/markdown.ts @@ -118,19 +118,21 @@ export interface MarkdownRepoInfo { /** the base url of repository commit */ commitBaseUrl: string /** base url for a repository issue */ - issueBaseUrl: string + issueBaseUrl?: string /** the text char that indicates an issue */ - issueChar: keyof typeof issuePrRegexes + issueChar?: keyof typeof issuePrRegexes + /** custom regex in case the git provider's issues uses a different format */ + issueRegex?: RegExp /** base url for a repository pull/merge request */ - prBaseUrl: string + prBaseUrl?: string /** * the text char that indicates a pull/merge request * * if it's the same as issueChar, than links will be parsed as issues and repo host is reponsible to redirect to pull/merge request x*/ - prChar: keyof typeof issuePrRegexes + prChar?: keyof typeof issuePrRegexes /** base url for a repository compare */ - compareBaseUrl: string + compareBaseUrl?: string } function resolveUrl(url: string, repoInfo: MarkdownRepoInfo, toUserContentId: ToUserContentIdFn) { @@ -218,15 +220,17 @@ function resolveGitLinkText(href: string, label: string, repoInfo: MarkdownRepoI switch (true) { case href.startsWith(repoInfo.commitBaseUrl): { - return lastSegment.slice(0, 7) // only show the first 6 letters/numbers of a commit + return lastSegment.slice(0, 7) // only show the first 7 letters/numbers of a commit } - case href.startsWith(repoInfo.issueBaseUrl): { + case !!repoInfo.issueChar && + !!repoInfo.issueBaseUrl && + href.startsWith(repoInfo.issueBaseUrl): { return `${repoInfo.issueChar}${lastSegment}` } - case href.startsWith(repoInfo.prBaseUrl): { + case !!repoInfo.prChar && !!repoInfo.prBaseUrl && href.startsWith(repoInfo.prBaseUrl): { return `${repoInfo.prChar}${lastSegment}` } - case href.startsWith(repoInfo.compareBaseUrl): { + case !!repoInfo.compareBaseUrl && href.startsWith(repoInfo.compareBaseUrl): { return lastSegment } // for account we don't resolve, this is something the git providers also don't do @@ -256,21 +260,24 @@ function createResolveGitTextToLinks(mdInfo: MarkdownRepoInfo): IOptions['textFi return `${match.slice(0, 7)}` }) - .replace(issuePrRegexes[mdInfo.issueChar], match => { - const id = match.replace(mdInfo.issueChar, '') - return `${match}` - }) // account .replace(accountRegex, match => { const acc = match.replace('@', '') return `${match}` }) + if (mdInfo.issueChar && mdInfo.issueBaseUrl) { + text = text.replace(mdInfo.issueRegex ?? issuePrRegexes[mdInfo.issueChar], match => { + const id = match.replace(mdInfo.issueChar!, '') + return `${match}` + }) + } + // pr/mr - if (mdInfo.issueChar != mdInfo.prChar) { + if (mdInfo.issueChar != mdInfo.prChar && mdInfo.prChar && mdInfo.prBaseUrl) { text = text.replace(issuePrRegexes[mdInfo.prChar], match => { - const id = match.replace(mdInfo.prChar, '') - return `${match}` + const id = match.replace(mdInfo.prChar!, '') + return `${match}` }) } diff --git a/server/utils/changelog/mdRepoInfo.ts b/server/utils/changelog/mdRepoInfo.ts index fca0f1dd74..fec175da4f 100644 --- a/server/utils/changelog/mdRepoInfo.ts +++ b/server/utils/changelog/mdRepoInfo.ts @@ -78,3 +78,76 @@ export function createTangledInfo(owner: string, repo: string, path?: string): M compareBaseUrl: `${hostBaseUrl}/${owner}/${repo}/compare`, } } + +// similar to forgejo, but they're seperate projects so keeping this also seperate +export function createGiteaRepoInfo( + host: string, + owner: string, + repo: string, + path?: string, +): MarkdownRepoInfo { + const hostBaseUrl = `https://${host}` + return { + hostBaseUrl, + blobBaseUrl: `${hostBaseUrl}/${owner}/${repo}/src/branch/HEAD`, + rawBaseUrl: `${hostBaseUrl}/${owner}/${repo}/raw/branch/HEAD`, + path, + commitBaseUrl: `${hostBaseUrl}/${owner}/${repo}/commit`, + issueChar: '#', + issueBaseUrl: `${hostBaseUrl}/${owner}/${repo}/issues`, + prChar: '#', + prBaseUrl: `${hostBaseUrl}/${owner}/${repo}/pulls`, + compareBaseUrl: `${hostBaseUrl}/${owner}/${repo}/compare`, + } +} + +export function createBitbucketRepoInfo( + owner: string, + repo: string, + path?: string, +): MarkdownRepoInfo { + const hostBaseUrl = 'https://bitbucket.org' + return { + hostBaseUrl, + blobBaseUrl: `${hostBaseUrl}/${owner}/${repo}/src/HEAD`, + rawBaseUrl: `${hostBaseUrl}/${owner}/${repo}/raw/HEAD`, + path, + commitBaseUrl: `${hostBaseUrl}/${owner}/${repo}/commits`, + prChar: '#', + prBaseUrl: `${hostBaseUrl}/${owner}/${repo}/pull-requests`, + // bitbucket uses jira instead of normal issues which can't be resolved, further the compare page also seems to be different + } +} + +export function createSourcehutRepoInfo( + owner: string, + repo: string, + path?: string, +): MarkdownRepoInfo { + const hostBaseUrl = 'https://git.sr.ht' + return { + hostBaseUrl, + blobBaseUrl: `${hostBaseUrl}/${owner}/${repo}/tree/HEAD/item`, + rawBaseUrl: `${hostBaseUrl}/${owner}/${repo}/blob/HEAD`, + path, + commitBaseUrl: `${hostBaseUrl}/${owner}/${repo}/commit`, + // source hut doesn't have/support issues,pr & compare + } +} + +export function createGiteeRepoInfo(owner: string, repo: string, path?: string): MarkdownRepoInfo { + const hostBaseUrl = `https://gitee.com` + return { + hostBaseUrl, + blobBaseUrl: `${hostBaseUrl}/${owner}/${repo}/blob/HREAD`, + rawBaseUrl: `${hostBaseUrl}/${owner}/${repo}/raw/HEAD`, + path, + commitBaseUrl: `${hostBaseUrl}/${owner}/${repo}/commit`, + issueChar: '#', + issueBaseUrl: `${hostBaseUrl}/${owner}/${repo}/issues`, + issueRegex: /\B#[\dA-Z]+\b/g, + prChar: '!', + prBaseUrl: `${hostBaseUrl}/${owner}/${repo}/pulls`, + compareBaseUrl: `${hostBaseUrl}/${owner}/${repo}/compare`, + } +} diff --git a/shared/schemas/changelog/release.ts b/shared/schemas/changelog/release.ts index 0ac03ddd5c..f6915855ca 100644 --- a/shared/schemas/changelog/release.ts +++ b/shared/schemas/changelog/release.ts @@ -46,3 +46,27 @@ export const GitlabReleaseSchame = v.object({ }) export const GitlabReleaseCollectionSchema = v.array(GitlabReleaseSchame) + +export const GiteaReleaseSchema = v.object({ + id: v.number(), + tag_name: v.string(), + name: v.string(), + body: v.string(), + html_url: v.pipe(v.string(), v.url()), + draft: v.boolean(), + prerelease: v.boolean(), + published_at: v.pipe(v.string(), v.isoTimestamp()), +}) + +export const GiteaReleaseCollectionSchema = v.array(GiteaReleaseSchema) + +export const GiteeReleaseSchema = v.object({ + id: v.number(), + tag_name: v.string(), + name: v.string(), + body: v.string(), + prerelease: v.boolean(), + created_at: v.pipe(v.string(), v.isoTimestamp()), +}) + +export const GiteeReleaseCollectionSchema = v.array(GiteeReleaseSchema) diff --git a/test/unit/server/utils/changelog/markdown.spec.ts b/test/unit/server/utils/changelog/markdown.spec.ts index 55f841b1b7..cc9e6ca1c4 100644 --- a/test/unit/server/utils/changelog/markdown.spec.ts +++ b/test/unit/server/utils/changelog/markdown.spec.ts @@ -1,6 +1,10 @@ import type { MarkdownRepoInfo } from '~~/server/utils/changelog/markdown' import { describe, expect, it, vi, beforeAll } from 'vitest' -import { createGithubRepoInfo, createGitLabRepoInfo } from '~~/server/utils/changelog/mdRepoInfo' +import { + createGithubRepoInfo, + createGitLabRepoInfo, + createGiteeRepoInfo, +} from '~~/server/utils/changelog/mdRepoInfo' // testing changelog specific needs, others things are tested at ../readme.spec.ts @@ -729,6 +733,43 @@ describe('Turn plaintext #isssue/#pr, !pr, @account & commmit into links', () => `, ) }) + + // gitee + describe('gitee issue formatting', () => { + it('should turn issue into formatted links', async () => { + const info = createGiteeRepoInfo('test-owner', 'test-repo') + const renderer = await changelogRenderer(info) + // text from date-fns v4.3.0 + const markdown = `- Fixed pt locale first day of week to be Sunday. See #IKF9K6 +- Fixed zh-CN, zh-HK, and zh-TW locale month parsing for October, November, and December. See #I9T5LW +` + const result = renderer(markdown) + + expect(result.html).toBe(` +`) + }) + + it('should turn issue into links between ()', async () => { + const info = createGiteeRepoInfo('test-owner', 'test-repo') + const renderer = await changelogRenderer(info) + // text comes from npmx release 0.15.0 + const markdown = `- Minor ui improvements (#IKF9K6) +- deps: Update module-replacements (#I9T5LW) +- Release v0.15.0 (#IKEIK1)` + + const result = renderer(markdown) + + expect(result.html).toBe(` +`) + }) + }) }) describe('format unformatted/auto links to git', () => {