import { renderMarkdown } from '../lib/markdown'
import type { Post } from '../types'
import { escapeHtml, escapeAttr, formatDateJa } from '../lib/util'
// Note post has extra fields for member content
interface NotePost extends Post {
value: Post['value'] & {
member?: {
text: string
bonus?: string
}
}
}
// Render note list page
export function renderNoteListPage(posts: NotePost[], handle: string): string {
if (posts.length === 0) {
return `
No note articles yet.
`
}
const items = posts.map(post => {
const rkey = post.uri.split('/').pop() || ''
const date = new Date(post.value.publishedAt).toLocaleDateString('ja-JP', {
year: 'numeric', month: '2-digit', day: '2-digit'
})
const tags = post.value.tags?.map(t => `${t} `).join('') || ''
return `
`
}).join('')
return `${items}
`
}
// Render single note detail with preview + copy
export function renderNoteDetailPage(
post: NotePost,
_handle: string,
isOwner: boolean
): string {
const rkey = post.uri.split('/').pop() || ''
const date = formatDateJa(post.value.publishedAt)
const freeText = post.value.content?.text || ''
const memberText = post.value.member?.text || ''
const bonusText = post.value.member?.bonus || ''
const freeHtml = renderMarkdown(freeText)
const memberHtml = memberText ? renderMarkdown(memberText) : ''
const bonusHtml = bonusText ? renderMarkdown(bonusText) : ''
let html = ''
// Action buttons at top
if (isOwner) {
html += `
Copy Title
Copy 全文
Edit
`
}
html += `
${escapeHtml(post.value.title)}
${date}
`
if (memberText) {
html += `
── 有料ライン ──
`
}
if (bonusText) {
html += `
今日のひとこま(おまけ)
${bonusHtml}
`
}
html += `
`
// Edit form (below content)
if (isOwner) {
html += `
`
}
return html
}
// Setup note detail page (copy + edit handlers)
export function setupNoteDetail(
post: NotePost,
_onSave?: (rkey: string, record: Record) => Promise
): void {
const freeText = post.value.content?.text || ''
const memberText = post.value.member?.text || ''
const bonusText = post.value.member?.bonus || ''
// Copy buttons
const copyTitle = document.getElementById('note-copy-title')
const copyAll = document.getElementById('note-copy-all')
const copyStatus = document.getElementById('note-copy-status')
function copyToClipboard(text: string) {
navigator.clipboard.writeText(text).then(() => {
if (copyStatus) {
copyStatus.textContent = 'Copied!'
setTimeout(() => { copyStatus.textContent = '' }, 2000)
}
})
}
copyTitle?.addEventListener('click', () => copyToClipboard(post.value.title))
copyAll?.addEventListener('click', () => {
const parts = [freeText, memberText, bonusText].filter(Boolean)
copyToClipboard(parts.join('\n\n'))
})
// Edit toggle
const editBtn = document.getElementById('note-edit-btn')
const editForm = document.getElementById('note-edit-form')
const display = document.getElementById('note-display')
const cancelBtn = document.getElementById('note-edit-cancel')
const saveBtn = document.getElementById('note-edit-save')
editBtn?.addEventListener('click', () => {
if (display) display.style.display = 'none'
if (editForm) editForm.style.display = 'block'
if (editBtn) editBtn.style.display = 'none'
})
cancelBtn?.addEventListener('click', () => {
if (editForm) editForm.style.display = 'none'
if (display) display.style.display = ''
if (editBtn) editBtn.style.display = ''
})
saveBtn?.addEventListener('click', () => {
const rkey = saveBtn.getAttribute('data-rkey')
if (!rkey) return
const title = (document.getElementById('note-edit-title') as HTMLInputElement)?.value.trim()
const free = (document.getElementById('note-edit-free') as HTMLTextAreaElement)?.value.trim()
const member = (document.getElementById('note-edit-member') as HTMLTextAreaElement)?.value.trim()
const bonus = (document.getElementById('note-edit-bonus') as HTMLTextAreaElement)?.value.trim()
if (!title || !free) {
alert('Title and content are required')
return
}
const did = post.uri.split('/')[2]
const record: Record = {
cid: '',
uri: post.uri,
value: {
$type: 'ai.syui.note.post',
site: post.value.site,
title,
content: {
$type: 'ai.syui.note.post#markdown',
text: free,
},
publishedAt: post.value.publishedAt,
langs: post.value.langs || ['ja'],
tags: post.value.tags || [],
} as Record,
}
if (member || bonus) {
const memberObj: Record = {}
if (member) memberObj.text = member
if (bonus) memberObj.bonus = bonus
;(record.value as Record).member = memberObj
}
const json = JSON.stringify(record, null, 2)
navigator.clipboard.writeText(json).then(() => {
const statusEl = document.getElementById('note-edit-status')
const filePath = `public/at/${did}/ai.syui.note.post/${rkey}.json`
if (statusEl) {
statusEl.innerHTML = `JSON copied! Paste to: ${filePath} `
}
})
})
}