Let users download shared notes as Markdown
The shared notes had no way out: everything lived in the SQLite row and the
only reader was the panel itself. Add two export endpoints and buttons for
them at the bottom of the note panel.
GET /api/notes/{page_id}/export returns one page as .md, and
GET /api/notes/export returns every page as a zip laid out as
<section>/<NN>_<title>.md. Pages are not concatenated into a single file on
purpose - the headings inside a page would collide with whatever heading
level we used as a page separator, so each page stays a verbatim file and the
numeric prefix carries the tab order instead.
Titles reach the filesystem here, so strip the Windows-forbidden characters
and control characters, cap the length, and send Content-Disposition with an
RFC 5987 filename* so Japanese titles survive. The front end deliberately
omits the anchor's download attribute to let that name win.
notes store: flush() now returns a promise so the download can wait for
pending edits to be saved before asking the server for the file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,8 @@ import {
|
||||
createNotePage,
|
||||
updateNotePage,
|
||||
deleteNotePage,
|
||||
exportNotePage,
|
||||
exportAllNotePages,
|
||||
renameNoteSection,
|
||||
reorderNotePages,
|
||||
type NotePage,
|
||||
@@ -140,13 +142,28 @@ export const useNotesStore = defineStore('notes', () => {
|
||||
}
|
||||
}
|
||||
|
||||
/** 保留中の保存を直ちに実行する(タブ切替・パネルを閉じる時など)。 */
|
||||
function flush(): void {
|
||||
/**
|
||||
* 保留中の保存を直ちに実行する(タブ切替・パネルを閉じる時など)。
|
||||
* await すれば保存の完了まで待てる(save() は自分でエラーを握るので reject はしない)。
|
||||
*/
|
||||
function flush(): Promise<void> {
|
||||
if (saveTimer !== null) {
|
||||
clearTimeout(saveTimer)
|
||||
saveTimer = null
|
||||
}
|
||||
for (const id of [...dirtyIds.value]) void save(id)
|
||||
return Promise.all([...dirtyIds.value].map((id) => save(id))).then(() => undefined)
|
||||
}
|
||||
|
||||
/** 編集中の内容を保存してから、そのページを Markdown としてダウンロードする。 */
|
||||
async function downloadPage(id: number): Promise<void> {
|
||||
await flush()
|
||||
exportNotePage(id)
|
||||
}
|
||||
|
||||
/** 編集中の内容を保存してから、全ページを ZIP としてダウンロードする。 */
|
||||
async function downloadAll(): Promise<void> {
|
||||
await flush()
|
||||
exportAllNotePages()
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -164,5 +181,7 @@ export const useNotesStore = defineStore('notes', () => {
|
||||
renameSection,
|
||||
reorder,
|
||||
flush,
|
||||
downloadPage,
|
||||
downloadAll,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user