Skip to content

Commit

Permalink
feat: support csv url to markdown table
Browse files Browse the repository at this point in the history
  • Loading branch information
WhiteMinds committed Oct 26, 2023
1 parent 226497a commit e9973df
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
4 changes: 4 additions & 0 deletions packages/app/src/utils/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ export function sample<T>(arr: T[]): T | undefined {
return arr[randomInt(0, arr.length - 1)]
}

export function unique<T>(arr: T[]): T[] {
return [...new Set(arr)]
}

export const BooleanT =
<T>() =>
(a: T | '' | 0 | 0n | false | null | undefined | void): a is T => {
Expand Down
48 changes: 46 additions & 2 deletions packages/app/src/utils/posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
getIssues,
} from './github'
import { createI18nKeyAdder } from './i18n'
import { unique } from './array'

const postSources = ['issues', 'discussions'] as const
export type PostSource = (typeof postSources)[number]
Expand Down Expand Up @@ -159,15 +160,58 @@ export async function getMenusWithPosts(topMenu?: TopLevelMenu): Promise<TopLeve
return [mergePostsToMenu(topMenu, await getPosts(topMenu))]
}

// Currently, the `<!-- PARSE_CSV_TO_MARKDOWN: ${url} -->` syntax is supported here, which replaces it with a markdown table.
async function handleRawPostBody<T extends Issue | Discussion>(raw: T): Promise<T> {
if (raw.body == null) return raw
let newBody = raw.body

const linesNeedParse = Array.from(raw.body?.match(/<!-- PARSE_CSV_TO_MARKDOWN: https:\/\/.*?\.csv -->/g) ?? [])
const csvURLs = unique(
linesNeedParse.map(wrapperd => wrapperd.replace(/<!-- PARSE_CSV_TO_MARKDOWN: (https:\/\/.*?\.csv) -->/, '$1')),
)
const csvContents = await Promise.all(csvURLs.map(url => fetch(url).then(res => res.text())))
const markdownContents = csvContents.map(content => {
content = content.trim()

// calc columnsDefineStatement
let lines = content.split('\n')
const columns = (lines[0] ?? '').split(/(?<!\\),/)
const columnsDefineStatement = columns.map(() => '--').join(' | ')

// replace `,` to `|`
// The implementation here is not rigorous, for example, it does not consider the case of escaping escape characters,
// but most of the time it will not cause problems.
content = content
.trim()
.replaceAll('|', '\\|')
.replace(/(?<!\\),/g, '|')

// insert columnsDefineStatement
lines = content.split('\n')
lines.splice(1, 0, columnsDefineStatement)
content = lines.join('\n')

return content
})

csvURLs.map((url, idx) => {
newBody = newBody.replaceAll(`<!-- PARSE_CSV_TO_MARKDOWN: ${url} -->`, markdownContents[idx] ?? '')
})

return { ...raw, body: newBody }
}

export async function getPost(source: PostSource, number: number): Promise<Post | null> {
let post: Post
switch (source) {
case 'issues':
post = issueToPost(await getIssue(number))
const issue = await handleRawPostBody(await getIssue(number))
post = issueToPost(issue)
break

case 'discussions':
post = discussionToPost(await getDiscussion(number))
const discussion = await handleRawPostBody(await getDiscussion(number))
post = discussionToPost(discussion)
break
}

Expand Down

1 comment on commit e9973df

@vercel
Copy link

@vercel vercel bot commented on e9973df Oct 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.