import disclaimerMarkdown from '../../../media/files/disclaimer.md?raw'; import privacyPolicyMarkdown from '../../../media/files/privacy_policy.md?raw'; import userAgreementMarkdown from '../../../media/files/user_agreement.md?raw'; export type LegalDocumentId = | 'user-agreement' | 'privacy-policy' | 'disclaimer'; export type LegalDocumentBlock = | { type: 'heading'; level: 2 | 3; text: string; } | { type: 'paragraph'; text: string; } | { type: 'list'; items: string[]; }; export type LegalDocument = { id: LegalDocumentId; title: string; markdown: string; blocks: LegalDocumentBlock[]; }; export const LEGAL_CONSENT_STORAGE_KEY = 'genarrative.auth.legal-consent.v1'; export const ICP_RECORD_NUMBER = '京ICP备2026025677号'; export const ICP_RECORD_URL = 'https://beian.miit.gov.cn/'; function normalizeMarkdownInlineText(value: string) { return value.replace(/`([^`]+)`/gu, '$1').trim(); } function pushParagraph( blocks: LegalDocumentBlock[], lines: string[], ) { if (lines.length === 0) { return; } const text = normalizeMarkdownInlineText(lines.join('\n')); if (text) { blocks.push({ type: 'paragraph', text }); } lines.length = 0; } function pushList(blocks: LegalDocumentBlock[], items: string[]) { if (items.length === 0) { return; } blocks.push({ type: 'list', items: items.map(normalizeMarkdownInlineText).filter(Boolean), }); items.length = 0; } function parseLegalMarkdown(markdown: string): LegalDocumentBlock[] { const blocks: LegalDocumentBlock[] = []; const paragraphLines: string[] = []; const listItems: string[] = []; markdown.split(/\r?\n/u).forEach((rawLine) => { const line = rawLine.trim(); if (!line) { pushParagraph(blocks, paragraphLines); pushList(blocks, listItems); return; } const headingMatch = /^(#{2,3})\s+(.+)$/u.exec(line); if (headingMatch) { pushParagraph(blocks, paragraphLines); pushList(blocks, listItems); blocks.push({ type: 'heading', level: headingMatch[1]?.length === 2 ? 2 : 3, text: normalizeMarkdownInlineText(headingMatch[2] ?? ''), }); return; } const listMatch = /^(?:[-*]|\d+[.)、])\s+(.+)$/u.exec(line); if (listMatch) { pushParagraph(blocks, paragraphLines); listItems.push(listMatch[1] ?? ''); return; } pushList(blocks, listItems); paragraphLines.push(line); }); pushParagraph(blocks, paragraphLines); pushList(blocks, listItems); return blocks; } const legalDocumentDefinitions = [ { id: 'user-agreement', title: '用户协议', markdown: userAgreementMarkdown, }, { id: 'privacy-policy', title: '隐私政策', markdown: privacyPolicyMarkdown, }, { id: 'disclaimer', title: '免责声明', markdown: disclaimerMarkdown, }, ] satisfies Array<{ id: LegalDocumentId; title: string; markdown: string; }>; export const LEGAL_DOCUMENTS: LegalDocument[] = legalDocumentDefinitions.map( (document) => ({ ...document, blocks: parseLegalMarkdown(document.markdown), }), ); export function getLegalDocument(id: LegalDocumentId) { return LEGAL_DOCUMENTS.find((document) => document.id === id) ?? null; } export function readStoredLegalConsent() { if (typeof window === 'undefined') { return false; } return window.localStorage.getItem(LEGAL_CONSENT_STORAGE_KEY) === 'true'; } export function persistLegalConsent() { if (typeof window === 'undefined') { return; } window.localStorage.setItem(LEGAL_CONSENT_STORAGE_KEY, 'true'); }