Skip to content

Commit 1d00ad5

Browse files
committed
update
1 parent 3f481da commit 1d00ad5

6 files changed

Lines changed: 81 additions & 16 deletions

File tree

-32.5 KB
Loading

assets/published-sidebar.png

21.5 KB
Loading

src/App.jsx

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@ import { deletePublishedPost } from './lib/deletePublishedPost'
2020
import { PublishValidationError } from './lib/publishTemplates'
2121
import { postHref, postRepoPath } from './lib/blogPaths'
2222
import {
23-
buildOptimisticPublishedFile,
2423
filterVisiblePublishedPosts,
24+
mergeRepoPublishedWithLocal,
2525
pruneRecentlyDeletedSlugs,
26-
upsertPublishedPost,
2726
withoutDeletedPost,
2827
} from './lib/publishedPosts'
2928
import { PostTemplatePanel } from './components/PostTemplatePanel'
@@ -138,7 +137,7 @@ export default function App() {
138137
branch: githubSettings.branch?.trim() || 'main',
139138
})
140139
const sorted = [...files].sort((a, b) => a.name.localeCompare(b.name))
141-
setPublishedFiles(sorted)
140+
setPublishedFiles((current) => mergeRepoPublishedWithLocal(current, sorted))
142141
setRecentlyDeletedSlugs((prev) => pruneRecentlyDeletedSlugs(prev, sorted))
143142
return sorted
144143
} catch (err) {
@@ -414,29 +413,41 @@ export default function App() {
414413
const publishedDraftId = draftId
415414
const s = slug.trim() || slugify(title) || 'post'
416415
const path = postRepoPath(s)
416+
const currentSlug = s
417417
const result = await publishPostAndIndex({
418418
form,
419419
path,
420-
slug: s,
420+
slug: currentSlug,
421421
title,
422422
content,
423423
excerpt,
424424
category,
425425
categoryClass: 'nb-bg-pink',
426426
})
427+
console.log('Publish result:', result)
427428
setIndexHomeBanner(result.indexHomeBanner)
428429

429-
const publishedItem = buildOptimisticPublishedFile({
430-
slug: result.slug,
431-
title: result.title,
432-
excerpt: result.excerpt,
433-
category: result.category,
434-
path: result.postPath,
435-
url: result.url,
436-
publishedAt: result.publishedAt,
430+
const publishedPost = {
431+
slug: result.slug || currentSlug,
432+
title: result.title || title,
433+
excerpt: result.excerpt ?? excerpt,
434+
category: result.category ?? category,
435+
path: result.postPath || result.path || postRepoPath(currentSlug),
436+
url: result.url || postHref(currentSlug),
437+
publishedAt: result.publishedAt || new Date().toISOString(),
438+
name: `${result.slug || currentSlug}.html`,
439+
sha: null,
440+
}
441+
console.log('Optimistic published post:', publishedPost)
442+
console.log('Updating publishedPosts after publish')
443+
444+
setPublishedFiles((posts) => {
445+
const withoutExisting = posts.filter(
446+
(post) => post.slug !== publishedPost.slug && post.path !== publishedPost.path,
447+
)
448+
return [publishedPost, ...withoutExisting]
437449
})
438-
setPublishedFiles((posts) => upsertPublishedPost(posts, publishedItem))
439-
setRecentlyDeletedSlugs((prev) => prev.filter((deleted) => deleted !== result.slug))
450+
setRecentlyDeletedSlugs((prev) => prev.filter((deleted) => deleted !== publishedPost.slug))
440451
setListTab('published')
441452

442453
if (result.workflowWarning) pushToast(result.workflowWarning)

src/lib/__tests__/publishedPosts.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import { describe, expect, it } from 'vitest'
22
import {
33
buildOptimisticPublishedFile,
44
filterVisiblePublishedPosts,
5+
mergeRepoPublishedWithLocal,
56
pruneRecentlyDeletedSlugs,
7+
publishedEntrySlug,
68
publishedFileSlug,
79
upsertPublishedPost,
810
withoutDeletedPost,
@@ -53,6 +55,22 @@ describe('publishedPosts helpers', () => {
5355
expect(next2[0].title).toBe('Old revised')
5456
})
5557

58+
it('filterVisiblePublishedPosts uses explicit slug on optimistic entries', () => {
59+
const posts = [{ slug: 'x', name: 'wrong.html', path: 'blog/posts/x.html' }]
60+
expect(filterVisiblePublishedPosts(posts, ['x'])).toHaveLength(0)
61+
expect(publishedEntrySlug(posts[0])).toBe('x')
62+
})
63+
64+
it('mergeRepoPublishedWithLocal keeps optimistic posts missing from repo API', () => {
65+
const local = [
66+
{ slug: 'new', name: 'new.html', path: 'blog/posts/new.html', title: 'New', sha: null },
67+
{ slug: 'old', name: 'old.html', path: 'blog/posts/old.html', sha: 'abc' },
68+
]
69+
const repo = [{ name: 'old.html', path: 'blog/posts/old.html', sha: 'abc' }]
70+
const merged = mergeRepoPublishedWithLocal(local, repo)
71+
expect(merged.map((p) => p.slug)).toEqual(['new', 'old'])
72+
})
73+
5674
it('pruneRecentlyDeletedSlugs drops slug when file is gone from repo list', () => {
5775
expect(pruneRecentlyDeletedSlugs(['gone', 'ghost'], [{ name: 'gone.html', path: 'blog/posts/gone.html' }])).toEqual([
5876
'gone',

src/lib/publishPipeline.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export async function publishPostAndIndex({
147147
indexUpdateReason: indexResult.reason ?? 'Card inserted between BLOG_POSTS markers.',
148148
indexPath,
149149
postPath: path,
150+
path,
150151
slug,
151152
title: safeTitle,
152153
excerpt: String(excerpt ?? '').trim(),

src/lib/publishedPosts.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,42 @@ export function publishedFileSlug(file) {
55
return String(file?.name ?? '').replace(/\.html$/i, '') || ''
66
}
77

8+
/** Slug for sidebar filtering (optimistic entries store slug explicitly). */
9+
export function publishedEntrySlug(post) {
10+
const explicit = String(post?.slug ?? '').trim()
11+
if (explicit) return explicit
12+
return publishedFileSlug(post)
13+
}
14+
815
/** Sidebar list: hide posts the user just deleted until repo API confirms removal. */
916
export function filterVisiblePublishedPosts(files, recentlyDeletedSlugs) {
1017
const blocked = new Set(recentlyDeletedSlugs)
11-
return files.filter((post) => !blocked.has(publishedFileSlug(post)))
18+
return files.filter((post) => !blocked.has(publishedEntrySlug(post)))
19+
}
20+
21+
/**
22+
* Merge GitHub contents API list with local optimistic entries not yet returned by the API.
23+
* @param {Array<object>} localFiles
24+
* @param {Array<{ name: string, path: string, sha?: string }>} repoFiles
25+
*/
26+
export function mergeRepoPublishedWithLocal(localFiles, repoFiles) {
27+
const repoPaths = new Set(repoFiles.map((f) => f.path))
28+
const pendingLocal = localFiles.filter((f) => f.path && !repoPaths.has(f.path))
29+
const fromRepo = repoFiles.map((f) => {
30+
const local = localFiles.find((l) => l.path === f.path)
31+
return {
32+
...f,
33+
slug: local?.slug ?? publishedFileSlug(f),
34+
title: local?.title,
35+
excerpt: local?.excerpt,
36+
category: local?.category,
37+
url: local?.url,
38+
publishedAt: local?.publishedAt,
39+
}
40+
})
41+
return [...pendingLocal, ...fromRepo].sort((a, b) =>
42+
String(a.name ?? '').localeCompare(String(b.name ?? '')),
43+
)
1244
}
1345

1446
/**
@@ -66,7 +98,10 @@ export function buildOptimisticPublishedFile({
6698
/** Prepend or replace by slug/path (newest first). */
6799
export function upsertPublishedPost(files, item) {
68100
const withoutExisting = files.filter(
69-
(post) => publishedFileSlug(post) !== item.slug && post.path !== item.path,
101+
(post) =>
102+
publishedEntrySlug(post) !== item.slug &&
103+
post.path !== item.path &&
104+
post.slug !== item.slug,
70105
)
71106
return [item, ...withoutExisting]
72107
}

0 commit comments

Comments
 (0)