memi-board 0.43.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,7 +37,7 @@ const emit = defineEmits<{ saved: [id: string], cancel: [] }>()
37
37
 
38
38
  const { user, isSignedIn, isAdmin, isWriteRestricted, restrictedMessage } = useMemiBoardAuth()
39
39
  const resolvedBoardId = computed(() => props.boardId || props.fixedCategory || '')
40
- const { createPostId, getPost, createPost, updatePost } = useMemiBoardPosts(resolvedBoardId)
40
+ const { createPostId, getPost, createPost, updatePost, resolveUniqueSlug } = useMemiBoardPosts(resolvedBoardId)
41
41
  const { checkText } = useMemiBoardModeration()
42
42
  const { getBoard, ensureSettings } = useMemiBoardSettings()
43
43
  const { uploadEditorImage } = useMemiBoardStorage()
@@ -963,6 +963,9 @@ async function handleSubmit() {
963
963
 
964
964
  saving.value = true
965
965
  submitHint.value = '내용을 검토하는 중…'
966
+ // 새 글 slug 중복 확인을 검열과 동시에 시작 — 검열에 걸리면 결과만 버린다.
967
+ const slugPromise = !props.postId && !imageBoard ? resolveUniqueSlug(title.value) : null
968
+ slugPromise?.catch(() => {})
966
969
  try {
967
970
  const plain = plainTextFromHtml(content.value)
968
971
  const moderationText = imageBoard ? plain : `${title.value}\n${plain}`
@@ -991,6 +994,7 @@ async function handleSubmit() {
991
994
  else {
992
995
  const id = await createPost({
993
996
  ...payload,
997
+ slug: (await slugPromise) ?? undefined,
994
998
  postId: attachmentNamespace.value,
995
999
  authorUid: user.value.uid,
996
1000
  authorName: user.value.displayName,
@@ -10,7 +10,7 @@
10
10
  * await useMemiBoardListSeo({ category: 'notice' })
11
11
  */
12
12
  import { computed, toValue, type MaybeRefOrGetter } from 'vue'
13
- import { useAsyncData, useHead, useRequestURL, useRoute, useRuntimeConfig, useSeoMeta } from '#imports'
13
+ import { useAsyncData, useHead, useNuxtApp, useRequestURL, useRoute, useRuntimeConfig, useSeoMeta } from '#imports'
14
14
  import {
15
15
  boardListOgDescription,
16
16
  boardListOgTitle,
@@ -64,6 +64,7 @@ export async function useMemiBoardPostSeo(opts?: {
64
64
  const config = useMemiBoardConfig()
65
65
  const seo = config.seo
66
66
  const route = useRoute()
67
+ const nuxtApp = useNuxtApp()
67
68
  const siteName = seo.siteName?.trim() || 'Board'
68
69
  const origin = resolveOrigin(seo.siteUrl)
69
70
  const basePath = normalizeBasePath(seo.basePath)
@@ -153,7 +154,9 @@ export async function useMemiBoardPostSeo(opts?: {
153
154
  }))
154
155
 
155
156
  // SSR/첫 페인트용 데이터 대기 (메타는 computed 로 이미 연결됨)
156
- await postAsync
157
+ // SSR·하이드레이션에서만 기다린다. 클라이언트 이동은 크롤러와 무관하니 화면 전환을 막지 않고
158
+ // 데이터가 오면 메타만 뒤따라 갱신한다 (Safari 등 왕복이 느린 환경에서 체감 차이가 크다).
159
+ if (import.meta.server || nuxtApp.isHydrating) await postAsync
157
160
 
158
161
  return { post }
159
162
  }
@@ -167,6 +170,7 @@ export async function useMemiBoardListSeo(opts?: {
167
170
  const config = useMemiBoardConfig()
168
171
  const seo = config.seo
169
172
  const route = useRoute()
173
+ const nuxtApp = useNuxtApp()
170
174
  const siteName = seo.siteName?.trim() || 'Board'
171
175
  const origin = resolveOrigin(seo.siteUrl)
172
176
  const basePath = normalizeBasePath(seo.basePath)
@@ -246,7 +250,9 @@ export async function useMemiBoardListSeo(opts?: {
246
250
  ],
247
251
  }))
248
252
 
249
- await listAsync
253
+ // SSR·하이드레이션에서만 기다린다. 클라이언트 이동은 크롤러와 무관하니 화면 전환을 막지 않고
254
+ // 데이터가 오면 메타만 뒤따라 갱신한다 (Safari 등 왕복이 느린 환경에서 체감 차이가 크다).
255
+ if (import.meta.server || nuxtApp.isHydrating) await listAsync
250
256
 
251
257
  return { list }
252
258
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memi-board",
3
- "version": "0.43.0",
3
+ "version": "0.44.0",
4
4
  "type": "module",
5
5
  "description": "Nuxt 4 + Nuxt UI + VueFire/Firebase 전용 게시판 모듈",
6
6
  "license": "MIT",