mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 15:36:33 +00:00
refactor(admin): share the GitHub release history between desktop and phone
useGithubReleases holds the paged fetch, the prerelease filter, the expanded rows and the date format, and parseReleaseNotes splits a release body into the blocks both panels draw. The phone keeps its page walk past hidden prereleases through the fillPages option, its repository link and its own inline link scan; the desktop keeps one page per load.
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/** One block of a release body: a heading, a paragraph, or a run of list items. */
|
||||
export type ReleaseNoteBlock = { kind: 'h3' | 'h4' | 'p'; text: string } | { kind: 'ul'; items: string[] };
|
||||
|
||||
/** Escapes the characters that would let release text break out of the HTML it is placed in. */
|
||||
export function escapeReleaseHtml(str: string): string {
|
||||
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a GitHub release body into the blocks both admin shells render: `### ` and `## `
|
||||
* headings, `- ` or `* ` list items gathered into one list until anything else breaks the
|
||||
* run, and every other non-empty line as a paragraph. Blank lines only end a list. The
|
||||
* text stays raw; each shell formats it inline itself.
|
||||
*/
|
||||
export function parseReleaseNotes(body: string): ReleaseNoteBlock[] {
|
||||
const blocks: ReleaseNoteBlock[] = [];
|
||||
let listItems: string[] = [];
|
||||
|
||||
const flushList = () => {
|
||||
if (listItems.length > 0) {
|
||||
blocks.push({ kind: 'ul', items: listItems });
|
||||
listItems = [];
|
||||
}
|
||||
};
|
||||
|
||||
for (const line of body.split('\n')) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed) {
|
||||
flushList();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (trimmed.startsWith('### ')) {
|
||||
flushList();
|
||||
blocks.push({ kind: 'h4', text: trimmed.slice(4) });
|
||||
} else if (trimmed.startsWith('## ')) {
|
||||
flushList();
|
||||
blocks.push({ kind: 'h3', text: trimmed.slice(3) });
|
||||
} else if (/^[-*] /.test(trimmed)) {
|
||||
listItems.push(trimmed.slice(2));
|
||||
} else {
|
||||
flushList();
|
||||
blocks.push({ kind: 'p', text: trimmed });
|
||||
}
|
||||
}
|
||||
flushList();
|
||||
return blocks;
|
||||
}
|
||||
Reference in New Issue
Block a user