import type { ArticleDetail } from '@geo/shared-types' export interface ArticleActionState { showPublish: boolean showEdit: boolean showPreview: boolean showCopy: boolean showDelete: boolean showRegenerate: boolean } export interface ArticleActionSource { generate_status?: string | null source_type?: string | null } const regeneratableSourceTypes = new Set(['template', 'custom_generation', 'imitation', 'kol']) export function resolveArticleActionState( articleOrGenerateStatus?: ArticleActionSource | string | null, ): ArticleActionState { const generateStatus = typeof articleOrGenerateStatus === 'string' ? articleOrGenerateStatus : articleOrGenerateStatus?.generate_status const sourceType = typeof articleOrGenerateStatus === 'string' ? undefined : articleOrGenerateStatus?.source_type if (generateStatus === 'completed') { return { showPublish: true, showEdit: true, showPreview: true, showCopy: true, showDelete: true, showRegenerate: false, } } if (generateStatus === 'draft') { return { showPublish: false, showEdit: true, showPreview: false, showCopy: false, showDelete: true, showRegenerate: false, } } if (generateStatus === 'failed') { return { showPublish: false, showEdit: false, showPreview: false, showCopy: false, showDelete: true, showRegenerate: sourceType ? regeneratableSourceTypes.has(sourceType) : false, } } return { showPublish: false, showEdit: false, showPreview: true, showCopy: false, showDelete: true, showRegenerate: false, } } export function buildArticleClipboardContent( detail: Pick, ): string { const title = detail.title?.trim() ?? '' const markdown = detail.markdown_content?.trim() ?? '' if (!title) { return markdown } if (!markdown) { return `# ${title}` } if (getLeadingH1Text(markdown) === title) { return markdown } return [`# ${title}`, markdown].join('\n\n').trim() } function getLeadingH1Text(markdown: string): string | null { const normalizedMarkdown = markdown.replace(/^\uFEFF/, '').trimStart() const firstLine = normalizedMarkdown.split(/\r?\n/, 1)[0]?.trim() ?? '' const match = firstLine.match(/^#\s+(.+?)\s*#*$/) return match?.[1]?.trim() ?? null }