memi-board 0.61.0 → 0.63.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.
Files changed (58) hide show
  1. package/README.md +2 -0
  2. package/dist/{ar-B6HWpN6c.js → ar-Dg9e1ruU.js} +27 -5
  3. package/dist/ar-Dg9e1ruU.js.map +1 -0
  4. package/dist/{commentImages-DZBDCMWH.js → commentImages-xb5Y4ySe.js} +174 -133
  5. package/dist/commentImages-xb5Y4ySe.js.map +1 -0
  6. package/dist/composables/useMemiBoardBannerGeneration.d.ts +1 -0
  7. package/dist/composables/useMemiBoardComments.d.ts +105 -1
  8. package/dist/composables/useMemiBoardPosts.d.ts +109 -1
  9. package/dist/composables/useMemiBoardStorage.d.ts +2 -1
  10. package/dist/{de-CDaEV4cd.js → de-CpGJ3KkZ.js} +27 -5
  11. package/dist/de-CpGJ3KkZ.js.map +1 -0
  12. package/dist/{en-lbbULqlq.js → en-I7auZHra.js} +36 -7
  13. package/dist/en-I7auZHra.js.map +1 -0
  14. package/dist/{es-D8LzeTe0.js → es-tMBUNff2.js} +27 -5
  15. package/dist/es-tMBUNff2.js.map +1 -0
  16. package/dist/{fr-CQDZqx5d.js → fr-BFXp_PeM.js} +27 -5
  17. package/dist/fr-BFXp_PeM.js.map +1 -0
  18. package/dist/{id-CIaQbTzK.js → id-B7lgKUHZ.js} +27 -5
  19. package/dist/id-B7lgKUHZ.js.map +1 -0
  20. package/dist/index.d.ts +5 -4
  21. package/dist/index.js +1223 -1085
  22. package/dist/index.js.map +1 -1
  23. package/dist/{ja-B2iAAzYv.js → ja-3SXam5Sk.js} +27 -5
  24. package/dist/ja-3SXam5Sk.js.map +1 -0
  25. package/dist/{pt-CXAWS0Km.js → pt-C2_VknPa.js} +27 -5
  26. package/dist/pt-C2_VknPa.js.map +1 -0
  27. package/dist/runtime/components/BannerEditor.vue +105 -52
  28. package/dist/runtime/components/CategorySettings.vue +10 -12
  29. package/dist/runtime/components/CommentItem.vue +61 -2
  30. package/dist/runtime/components/CommentRevisions.vue +87 -0
  31. package/dist/runtime/components/CustomFieldEditor.vue +85 -1
  32. package/dist/runtime/components/Detail.vue +62 -4
  33. package/dist/runtime/components/Editor.vue +5 -1
  34. package/dist/runtime/components/List.vue +19 -8
  35. package/dist/runtime/components/PostRevisions.vue +107 -0
  36. package/dist/runtime/components/Settings.vue +10 -11
  37. package/dist/storage.js +36 -27
  38. package/dist/storage.js.map +1 -1
  39. package/dist/types.d.ts +57 -0
  40. package/dist/utils/bannerGeneration.d.ts +1 -1
  41. package/dist/utils/boardPaths.d.ts +6 -0
  42. package/dist/utils/customFields.d.ts +1 -1
  43. package/dist/utils/editLimits.d.ts +6 -0
  44. package/dist/{zh-ByjHExJt.js → zh-CuOjIYyr.js} +27 -5
  45. package/dist/zh-CuOjIYyr.js.map +1 -0
  46. package/docs/firebase-setup.md +1 -1
  47. package/docs/firestore.rules.example +133 -2
  48. package/package.json +1 -1
  49. package/dist/ar-B6HWpN6c.js.map +0 -1
  50. package/dist/commentImages-DZBDCMWH.js.map +0 -1
  51. package/dist/de-CDaEV4cd.js.map +0 -1
  52. package/dist/en-lbbULqlq.js.map +0 -1
  53. package/dist/es-D8LzeTe0.js.map +0 -1
  54. package/dist/fr-CQDZqx5d.js.map +0 -1
  55. package/dist/id-CIaQbTzK.js.map +0 -1
  56. package/dist/ja-B2iAAzYv.js.map +0 -1
  57. package/dist/pt-CXAWS0Km.js.map +0 -1
  58. package/dist/zh-ByjHExJt.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { computed as e, getCurrentInstance as t, hasInjectionContext as n, inject as r, onServerPrefetch as i, provide as a, reactive as o, shallowRef as s, toValue as c, watch as ee } from "vue";
2
- import { collection as l, doc as u } from "firebase/firestore";
1
+ import { computed as e, getCurrentInstance as t, hasInjectionContext as n, inject as r, onServerPrefetch as i, provide as a, reactive as o, shallowRef as s, toValue as c, watch as l } from "vue";
2
+ import { collection as u, doc as d } from "firebase/firestore";
3
3
  //#region src/i18n/locales.ts
4
- var d = [
4
+ var f = [
5
5
  {
6
6
  code: "ko",
7
7
  name: "한국어",
@@ -62,19 +62,19 @@ var d = [
62
62
  intl: "id-ID",
63
63
  dir: "ltr"
64
64
  }
65
- ], f = "ko", p = "en", m = new Set(d.map((e) => e.code));
66
- function h(e) {
65
+ ], p = "ko", m = "en", h = new Set(f.map((e) => e.code));
66
+ function g(e) {
67
67
  if (typeof e != "string") return;
68
68
  let t = e.trim().toLowerCase().split(/[-_]/)[0];
69
- return t && m.has(t) ? t : void 0;
69
+ return t && h.has(t) ? t : void 0;
70
70
  }
71
- function g(e) {
72
- return d.find((t) => t.code === e) ?? d[0];
71
+ function _(e) {
72
+ return f.find((t) => t.code === e) ?? f[0];
73
73
  }
74
74
  //#endregion
75
75
  //#region src/utils/boardPaths.ts
76
- var _ = "memiBoardPosts", v = "memiBoardComments", y = "memiBoardLikes", b = "memiBoardReports", x = "memiBoardSettings", S = "memiBoardUsers";
77
- function C(e) {
76
+ var v = "memiBoardPosts", y = "memiBoardComments", b = "memiBoardLikes", x = "memiBoardReports", S = "memiBoardSettings", C = "memiBoardUsers";
77
+ function w(e) {
78
78
  return {
79
79
  postsCollection: e.postsCollection?.trim() || "memiBoardPosts",
80
80
  commentsCollection: e.commentsCollection?.trim() || "memiBoardComments",
@@ -84,84 +84,96 @@ function C(e) {
84
84
  usersCollection: e.usersCollection?.trim() || "memiBoardUsers"
85
85
  };
86
86
  }
87
- function te(e, t) {
88
- return l(e, t.settingsCollection);
87
+ function ee(e, t) {
88
+ return u(e, t.settingsCollection);
89
89
  }
90
- function ne(e, t, n) {
91
- return u(e, t.settingsCollection, n);
90
+ function te(e, t, n) {
91
+ return d(e, t.settingsCollection, n);
92
92
  }
93
- function re(e, t) {
94
- return l(e, t.postsCollection);
93
+ function ne(e, t) {
94
+ return u(e, t.postsCollection);
95
+ }
96
+ function re(e, t, n) {
97
+ return d(e, t.postsCollection, n);
95
98
  }
96
99
  function ie(e, t, n) {
97
- return u(e, t.postsCollection, n);
100
+ return d(e, t.postsCollection, n, "body", "main");
98
101
  }
99
102
  function ae(e, t, n) {
100
- return u(e, t.postsCollection, n, "body", "main");
103
+ return u(e, t.postsCollection, n, "revisions");
101
104
  }
102
- function oe(e, t) {
103
- return l(e, t.commentsCollection);
105
+ function oe(e, t, n, r) {
106
+ return d(e, t.postsCollection, n, "revisions", String(r));
104
107
  }
105
- function se(e, t, n) {
106
- return u(e, t.commentsCollection, n);
108
+ function se(e, t) {
109
+ return u(e, t.commentsCollection);
107
110
  }
108
- function ce(e, t) {
109
- return l(e, t.likesCollection);
111
+ function ce(e, t, n) {
112
+ return d(e, t.commentsCollection, n);
110
113
  }
111
- function w(e, t) {
112
- return `${e}_${t}`;
114
+ function le(e, t, n) {
115
+ return u(e, t.commentsCollection, n, "revisions");
113
116
  }
114
117
  function T(e, t, n, r) {
115
- return u(e, t.likesCollection, w(n, r));
116
- }
117
- function le(e, t) {
118
- return l(e, t.reportsCollection);
118
+ return d(e, t.commentsCollection, n, "revisions", String(r));
119
119
  }
120
120
  function E(e, t) {
121
+ return u(e, t.likesCollection);
122
+ }
123
+ function D(e, t) {
121
124
  return `${e}_${t}`;
122
125
  }
123
- function D(e, t, n, r) {
124
- return u(e, t.reportsCollection, E(n, r));
126
+ function ue(e, t, n, r) {
127
+ return d(e, t.likesCollection, D(n, r));
128
+ }
129
+ function de(e, t) {
130
+ return u(e, t.reportsCollection);
125
131
  }
126
132
  function O(e, t) {
133
+ return `${e}_${t}`;
134
+ }
135
+ function fe(e, t, n, r) {
136
+ return d(e, t.reportsCollection, O(n, r));
137
+ }
138
+ function k(e, t) {
127
139
  return `c_${e}_${t}`;
128
140
  }
129
- function k(e, t, n, r) {
130
- return u(e, t.reportsCollection, O(n, r));
141
+ function pe(e, t, n, r) {
142
+ return d(e, t.reportsCollection, k(n, r));
131
143
  }
132
- function ue(e, t, n) {
133
- return u(e, t.reportsCollection, n);
144
+ function A(e, t, n) {
145
+ return d(e, t.reportsCollection, n);
134
146
  }
135
- function de(e, t) {
136
- return l(e, t.usersCollection);
147
+ function me(e, t) {
148
+ return u(e, t.usersCollection);
137
149
  }
138
- function fe(e, t, n) {
139
- return u(e, t.usersCollection, n);
150
+ function he(e, t, n) {
151
+ return d(e, t.usersCollection, n);
140
152
  }
141
- function pe(e, t, n) {
142
- return u(e, t.usersCollection, n, "private", "info");
153
+ function ge(e, t, n) {
154
+ return d(e, t.usersCollection, n, "private", "info");
143
155
  }
144
- function me(e, t, n, r) {
145
- return u(e, t.usersCollection, n, "memos", r);
156
+ function _e(e, t, n, r) {
157
+ return d(e, t.usersCollection, n, "memos", r);
146
158
  }
147
- function he(e, t) {
159
+ function ve(e, t) {
148
160
  return `${e.postsCollection}/${t}`;
149
161
  }
150
- function ge(e, t) {
162
+ function ye(e, t) {
151
163
  return `${e.postsCollection}/${e.usersCollection}/${t}`;
152
164
  }
153
165
  //#endregion
154
166
  //#region src/config.ts
155
- var A = "__MEMI_BOARD_CONFIG__";
156
- function j() {
167
+ var j = "__MEMI_BOARD_CONFIG__";
168
+ function M() {
157
169
  let e = globalThis;
158
- return e[A] || (e[A] = o({
159
- postsCollection: _,
160
- commentsCollection: v,
161
- likesCollection: y,
162
- reportsCollection: b,
163
- settingsCollection: x,
164
- usersCollection: S,
170
+ return e[j] || (e[j] = o({
171
+ postsCollection: v,
172
+ commentsCollection: y,
173
+ likesCollection: b,
174
+ reportsCollection: x,
175
+ settingsCollection: S,
176
+ usersCollection: C,
165
177
  auth: { providers: ["google", "apple"] },
166
178
  moderation: {
167
179
  enabled: !0,
@@ -179,10 +191,10 @@ function j() {
179
191
  defaultOgImage: "",
180
192
  basePath: "/board"
181
193
  }
182
- })), e[A];
194
+ })), e[j];
183
195
  }
184
- function _e(e) {
185
- let t = j();
196
+ function N(e) {
197
+ let t = M();
186
198
  e.postsCollection != null && e.postsCollection !== "" && (t.postsCollection = e.postsCollection.trim()), e.commentsCollection != null && e.commentsCollection !== "" && (t.commentsCollection = e.commentsCollection.trim()), e.likesCollection != null && e.likesCollection !== "" && (t.likesCollection = e.likesCollection.trim()), e.reportsCollection != null && e.reportsCollection !== "" && (t.reportsCollection = e.reportsCollection.trim()), e.settingsCollection != null && e.settingsCollection !== "" && (t.settingsCollection = e.settingsCollection.trim()), e.usersCollection != null && e.usersCollection !== "" && (t.usersCollection = e.usersCollection.trim()), e.auth && Object.assign(t.auth, e.auth), e.moderation && Object.assign(t.moderation, e.moderation), e.seo && Object.assign(t.seo, e.seo), e.i18n && (t.i18n = {
187
199
  ...t.i18n,
188
200
  ...e.i18n
@@ -194,49 +206,49 @@ function _e(e) {
194
206
  ...e.bannerGeneration
195
207
  }), e.roleLabels && (t.roleLabels = { ...e.roleLabels }), e.locale && (t.locale = e.locale);
196
208
  }
197
- function M() {
198
- return j();
199
- }
200
- function N() {
201
- return M().site?.disableAi !== !0;
202
- }
203
209
  function P() {
204
- if (!N()) throw Object.assign(/* @__PURE__ */ Error("AI features are disabled for this board service."), { code: "memi-board/ai-disabled" });
210
+ return M();
205
211
  }
206
212
  function F() {
207
- let e = M();
208
- return e.site?.disableI18n !== !0 && e.i18n?.enabled !== !1;
213
+ return P().site?.disableAi !== !0;
214
+ }
215
+ function be() {
216
+ if (!F()) throw Object.assign(/* @__PURE__ */ Error("AI features are disabled for this board service."), { code: "memi-board/ai-disabled" });
209
217
  }
210
218
  function I() {
211
- return N() && F() && M().translation?.enabled !== !1;
219
+ let e = P();
220
+ return e.site?.disableI18n !== !0 && e.i18n?.enabled !== !1;
212
221
  }
213
222
  function L() {
214
- let e = d.map((e) => e.code), t = M().site?.locales;
215
- if (!F() || !t?.length) return e;
216
- let n = new Set(t.map((e) => h(e)).filter(Boolean)), r = e.filter((e) => n.has(e));
217
- return r.length ? r : e;
223
+ return F() && I() && P().translation?.enabled !== !1;
218
224
  }
219
225
  function R() {
220
- let e = M(), t = e.site?.locale || e.locale, n = L(), r = h(t);
221
- return n.length === d.length || r && n.includes(r) ? t : n[0];
226
+ let e = f.map((e) => e.code), t = P().site?.locales;
227
+ if (!I() || !t?.length) return e;
228
+ let n = new Set(t.map((e) => g(e)).filter(Boolean)), r = e.filter((e) => n.has(e));
229
+ return r.length ? r : e;
230
+ }
231
+ function z() {
232
+ let e = P(), t = e.site?.locale || e.locale, n = R(), r = g(t);
233
+ return n.length === f.length || r && n.includes(r) ? t : n[0];
222
234
  }
223
- function ve(e) {
224
- M().site = {
235
+ function xe(e) {
236
+ P().site = {
225
237
  disableAi: e?.disableAi === !0,
226
238
  disableI18n: e?.disableI18n === !0,
227
239
  locale: typeof e?.locale == "string" && e.locale ? e.locale : void 0,
228
240
  locales: Array.isArray(e?.locales) ? e.locales.filter((e) => typeof e == "string") : void 0
229
241
  };
230
242
  }
231
- function z() {
232
- if (!I()) throw Object.assign(/* @__PURE__ */ Error("Content translation is disabled for this board service."), { code: "memi-board/translation-disabled" });
243
+ function Se() {
244
+ if (!L()) throw Object.assign(/* @__PURE__ */ Error("Content translation is disabled for this board service."), { code: "memi-board/translation-disabled" });
233
245
  }
234
- function ye() {
235
- return C(M());
246
+ function Ce() {
247
+ return w(P());
236
248
  }
237
249
  //#endregion
238
250
  //#region src/i18n/messages/ko/index.ts
239
- var be = {
251
+ var we = {
240
252
  accountDeletion: {
241
253
  title: "회원 탈퇴",
242
254
  intro: "계정과 개인정보를 삭제하려면 탈퇴를 진행해 주세요.",
@@ -381,7 +393,11 @@ var be = {
381
393
  edit: "댓글 수정",
382
394
  blind: "댓글 블라인드",
383
395
  unblind: "댓글 블라인드 해제",
384
- delete: "댓글 삭제"
396
+ delete: "댓글 삭제",
397
+ edited: "수정됨",
398
+ editedTooltip: "{count}번 수정됨 · 마지막 수정 {time}",
399
+ history: "수정 기록",
400
+ editLimitTitle: "더 이상 수정할 수 없어요"
385
401
  },
386
402
  commentList: {
387
403
  loading: "댓글을 불러오고 있습니다",
@@ -401,7 +417,9 @@ var be = {
401
417
  bodyTooLong: "댓글은 {max}자까지 작성할 수 있습니다.",
402
418
  replyTargetNotFound: "답글 대상 댓글을 찾을 수 없습니다.",
403
419
  threadNotFound: "댓글 스레드를 찾을 수 없습니다.",
404
- hasRepliesCannotDelete: "답글이 있는 댓글은 현재 삭제할 수 없습니다."
420
+ hasRepliesCannotDelete: "답글이 있는 댓글은 현재 삭제할 수 없습니다.",
421
+ commentNotFound: "댓글을 찾을 수 없습니다.",
422
+ editLimitReached: "댓글 수정은 최대 {max}번까지 할 수 있어요. 더 고쳐야 하면 보드 관리자에게 요청해 주세요."
405
423
  },
406
424
  common: {
407
425
  action: {
@@ -468,7 +486,12 @@ var be = {
468
486
  backToList: "목록으로 돌아가기",
469
487
  postNav: "게시글 이동",
470
488
  list: "목록",
471
- comments: "댓글"
489
+ comments: "댓글",
490
+ edited: "수정됨",
491
+ editedCount: "{count}번 수정됨",
492
+ editedTooltip: "{count}번 수정됨 · 마지막 수정 {time}",
493
+ revisions: "수정 기록 {count}",
494
+ editLimitTitle: "더 이상 수정할 수 없어요"
472
495
  },
473
496
  editor: {
474
497
  confirmLeave: "저장하지 않은 내용이 있습니다. 이 페이지를 나가시겠습니까?",
@@ -747,11 +770,22 @@ var be = {
747
770
  liftInDays: "약 {days}일 후 해제",
748
771
  liftInDaysHours: "약 {days}일 {hours}시간 후 해제"
749
772
  },
773
+ postRevisions: {
774
+ title: "수정 기록",
775
+ description: "수정으로 바뀌기 전의 내용이에요. 기록은 고치거나 지울 수 없고 보드 관리자만 볼 수 있어요.",
776
+ original: "원본",
777
+ version: "{version}차 수정본",
778
+ replacedAt: "{time}에 바뀜",
779
+ replacedBy: "수정한 사람: {name}",
780
+ empty: "남아 있는 수정 기록이 없어요.",
781
+ loadFailed: "수정 기록을 불러오지 못했어요."
782
+ },
750
783
  posts: {
751
784
  boardIdRequired: "[memi-board] boardId 가 필요합니다.",
752
785
  photoRequired: "사진을 올려 주세요.",
753
786
  bodyRequired: "본문에 글자를 입력하거나 이미지를 첨부해 주세요.",
754
- titleRequired: "제목을 입력해 주세요."
787
+ titleRequired: "제목을 입력해 주세요.",
788
+ editLimitReached: "수정은 최대 {max}번까지 할 수 있어요. 더 고쳐야 하면 보드 관리자에게 요청해 주세요."
755
789
  },
756
790
  profile: {
757
791
  myAccount: "내 계정",
@@ -903,7 +937,11 @@ var be = {
903
937
  contextChanged: "생성 중 제목이나 설명이 바뀌었습니다. 현재 내용으로 다시 생성해 주세요.",
904
938
  generateFailed: "배너를 생성하지 못했습니다. AI Logic 이미지 모델 사용 설정과 App Check를 확인한 뒤 다시 시도해 주세요.",
905
939
  label: "보드 상단 배너",
906
- help: "권장 크기 2400 × 300px (8:1). 이미지를 이동하거나 확대해 표시할 영역을 선택하세요. 설정을 저장하면 적용됩니다.",
940
+ help: "데스크톱과 휴대폰 배너를 따로 올릴 수 있습니다. 이미지를 이동하거나 확대해 표시할 영역을 선택하세요. 설정을 저장하면 적용됩니다.",
941
+ desktop: "데스크톱 배너",
942
+ desktopHelp: "권장 2400 × 300px (8:1). 비워 두면 휴대폰 배너를 사용합니다.",
943
+ mobile: "휴대폰 배너",
944
+ mobileHelp: "권장 1200 × 400px (3:1). 비워 두면 데스크톱 배너를 사용합니다.",
907
945
  select: "이미지 선택",
908
946
  remove: "배너 제거",
909
947
  crop: "배너 이미지 자르기",
@@ -1017,10 +1055,13 @@ var be = {
1017
1055
  placeholder: "플레이스홀더",
1018
1056
  inputPlaceholder: "글쓰기 칸에 흐리게 보일 문구",
1019
1057
  add: "필드 추가",
1020
- limit: "커스텀 필드는 8개까지입니다.",
1058
+ limit: "커스텀 필드는 20개까지입니다.",
1021
1059
  invalidKey: "키는 영문 소문자로 시작하고, 영문·숫자·밑줄만 32자 이내로 쓸 수 있습니다.",
1022
1060
  duplicateKey: "키 {key}가 중복입니다.",
1023
- labelRequired: "키 {key}의 이름을 입력해 주세요."
1061
+ labelRequired: "키 {key}의 이름을 입력해 주세요.",
1062
+ moveUp: "위로 이동",
1063
+ moveDown: "아래로 이동",
1064
+ drag: "드래그해서 순서 변경 (방향키도 가능)"
1024
1065
  },
1025
1066
  locale: {
1026
1067
  label: "보드 언어",
@@ -1243,28 +1284,28 @@ var be = {
1243
1284
  custom: "커스텀 스타일로 바꾸기…"
1244
1285
  }
1245
1286
  }
1246
- }, xe = {
1247
- en: () => import("./en-lbbULqlq.js"),
1248
- ja: () => import("./ja-B2iAAzYv.js"),
1249
- de: () => import("./de-CDaEV4cd.js"),
1250
- fr: () => import("./fr-CQDZqx5d.js"),
1251
- es: () => import("./es-D8LzeTe0.js"),
1252
- pt: () => import("./pt-CXAWS0Km.js"),
1253
- zh: () => import("./zh-ByjHExJt.js"),
1254
- ar: () => import("./ar-B6HWpN6c.js"),
1255
- id: () => import("./id-CIaQbTzK.js")
1287
+ }, Te = {
1288
+ en: () => import("./en-I7auZHra.js"),
1289
+ ja: () => import("./ja-3SXam5Sk.js"),
1290
+ de: () => import("./de-CpGJ3KkZ.js"),
1291
+ fr: () => import("./fr-BFXp_PeM.js"),
1292
+ es: () => import("./es-tMBUNff2.js"),
1293
+ pt: () => import("./pt-C2_VknPa.js"),
1294
+ zh: () => import("./zh-CuOjIYyr.js"),
1295
+ ar: () => import("./ar-Dg9e1ruU.js"),
1296
+ id: () => import("./id-B7lgKUHZ.js")
1256
1297
  }, B = "__MEMI_BOARD_I18N__";
1257
1298
  function V() {
1258
1299
  let e = globalThis;
1259
1300
  return e[B] ??= {
1260
- messages: { ko: be },
1301
+ messages: { ko: we },
1261
1302
  pending: {},
1262
1303
  version: s(0)
1263
1304
  }, e[B];
1264
1305
  }
1265
1306
  function H(e) {
1266
1307
  let t = V();
1267
- return t.messages[e] || e === "ko" ? Promise.resolve() : (t.pending[e] ??= xe[e]().then((n) => {
1308
+ return t.messages[e] || e === "ko" ? Promise.resolve() : (t.pending[e] ??= Te[e]().then((n) => {
1268
1309
  t.messages[e] = n.default, t.version.value++;
1269
1310
  }).catch((n) => {
1270
1311
  delete t.pending[e], console.warn(`[memi-board] failed to load locale "${e}"`, n);
@@ -1273,7 +1314,7 @@ function H(e) {
1273
1314
  function U(e) {
1274
1315
  return e === "ko" ? Promise.resolve() : Promise.all([H(e), H("en")]).then(() => void 0);
1275
1316
  }
1276
- function Se(e) {
1317
+ function Ee(e) {
1277
1318
  return !!V().messages[e];
1278
1319
  }
1279
1320
  function W(e, t) {
@@ -1284,7 +1325,7 @@ function W(e, t) {
1284
1325
  }
1285
1326
  return typeof n == "string" ? n : void 0;
1286
1327
  }
1287
- function Ce(e, t) {
1328
+ function De(e, t) {
1288
1329
  return t ? e.replace(/\{(\w+)\}/g, (e, n) => {
1289
1330
  let r = t[n];
1290
1331
  return r == null ? e : String(r);
@@ -1294,23 +1335,23 @@ function G(e, t, n) {
1294
1335
  let r = V();
1295
1336
  r.version.value;
1296
1337
  let i = e ?? "ko", a = W(r.messages[i], t) ?? (i === "ko" ? void 0 : W(r.messages.en, t)) ?? W(r.messages.ko, t);
1297
- return a == null ? t : Ce(a, n);
1338
+ return a == null ? t : De(a, n);
1298
1339
  }
1299
1340
  //#endregion
1300
1341
  //#region src/utils/formatDate.ts
1301
1342
  function K(e) {
1302
- return g(e ?? "ko").intl;
1343
+ return _(e ?? "ko").intl;
1303
1344
  }
1304
1345
  function q(e, t) {
1305
1346
  return e?.toDate ? e.toDate().toLocaleDateString(K(t)) : "";
1306
1347
  }
1307
- var we = 60, J = 3600, Te = 24 * J;
1348
+ var Oe = 60, J = 3600, ke = 24 * J;
1308
1349
  function Y(e, t = Date.now(), n) {
1309
1350
  if (!e?.toDate) return G(n, "common.date.justNow");
1310
1351
  let r = Math.max(0, Math.round((t - e.toDate().getTime()) / 1e3));
1311
1352
  if (r < 45) return G(n, "common.date.fewSecondsAgo");
1312
- let i = new Intl.RelativeTimeFormat(K(n), { numeric: "always" }), a = r / Te;
1313
- return r < 90 ? i.format(-1, "minute") : r < 2700 ? i.format(-Math.round(r / we), "minute") : r < 5400 ? i.format(-1, "hour") : r < 22 * J ? i.format(-Math.round(r / J), "hour") : r < 36 * J ? i.format(-1, "day") : a < 26 ? i.format(-Math.round(a), "day") : a < 46 ? i.format(-1, "month") : a < 320 ? i.format(-Math.round(a / 30.4), "month") : a < 548 ? i.format(-1, "year") : i.format(-Math.round(a / 365), "year");
1353
+ let i = new Intl.RelativeTimeFormat(K(n), { numeric: "always" }), a = r / ke;
1354
+ return r < 90 ? i.format(-1, "minute") : r < 2700 ? i.format(-Math.round(r / Oe), "minute") : r < 5400 ? i.format(-1, "hour") : r < 22 * J ? i.format(-Math.round(r / J), "hour") : r < 36 * J ? i.format(-1, "day") : a < 26 ? i.format(-Math.round(a), "day") : a < 46 ? i.format(-1, "month") : a < 320 ? i.format(-Math.round(a / 30.4), "month") : a < 548 ? i.format(-1, "year") : i.format(-Math.round(a / 365), "year");
1314
1355
  }
1315
1356
  function X(e, t) {
1316
1357
  return e?.toDate ? new Intl.DateTimeFormat(K(t), {
@@ -1330,48 +1371,48 @@ function Z(e, t, n) {
1330
1371
  //#endregion
1331
1372
  //#region src/i18n/useMemiBoardI18n.ts
1332
1373
  var Q = "memiBoard:hostLocale", $ = Symbol("memiBoard:boardLocale");
1333
- function Ee(o = {}) {
1334
- let s = n(), l = s ? r($, null) : null, u = s ? r(Q, null) : null, d = M(), f = e(F), p = e(I), m = e(N), _ = e(() => f.value ? h(c(o.boardLocale)) ?? l?.value ?? h(c(u)) ?? h(R()) ?? "ko" : h(R()) ?? "ko");
1335
- o.boardLocale !== void 0 && s && a($, _), ee(_, (e) => void U(e), { immediate: !0 }), t() && i(() => U(_.value));
1336
- let v = e(() => g(_.value));
1374
+ function Ae(o = {}) {
1375
+ let s = n(), u = s ? r($, null) : null, d = s ? r(Q, null) : null, f = P(), p = e(I), m = e(L), h = e(F), v = e(() => p.value ? g(c(o.boardLocale)) ?? u?.value ?? g(c(d)) ?? g(z()) ?? "ko" : g(z()) ?? "ko");
1376
+ o.boardLocale !== void 0 && s && a($, v), l(v, (e) => void U(e), { immediate: !0 }), t() && i(() => U(v.value));
1377
+ let y = e(() => _(v.value));
1337
1378
  return {
1338
- locale: _,
1339
- i18nEnabled: f,
1340
- translationEnabled: p,
1341
- aiEnabled: m,
1342
- dir: e(() => v.value.dir),
1343
- intlLocale: e(() => v.value.intl),
1379
+ locale: v,
1380
+ i18nEnabled: p,
1381
+ translationEnabled: m,
1382
+ aiEnabled: h,
1383
+ dir: e(() => y.value.dir),
1384
+ intlLocale: e(() => y.value.intl),
1344
1385
  t: (e, t) => {
1345
1386
  let n = e.startsWith("common.role.") ? e.slice(12) : "";
1346
- return d.roleLabels?.[n] ?? G(_.value, e, t);
1387
+ return f.roleLabels?.[n] ?? G(v.value, e, t);
1347
1388
  },
1348
- formatDate: (e) => q(e, _.value),
1349
- formatFullDate: (e) => X(e, _.value),
1350
- formatRelativeDate: (e, t) => Y(e, t, _.value),
1351
- formatTimestampDetails: (e, t) => Z(e, t, _.value),
1352
- formatNumber: (e) => e.toLocaleString(v.value.intl)
1389
+ formatDate: (e) => q(e, v.value),
1390
+ formatFullDate: (e) => X(e, v.value),
1391
+ formatRelativeDate: (e, t) => Y(e, t, v.value),
1392
+ formatTimestampDetails: (e, t) => Z(e, t, v.value),
1393
+ formatNumber: (e) => e.toLocaleString(y.value.intl)
1353
1394
  };
1354
1395
  }
1355
1396
  //#endregion
1356
1397
  //#region src/utils/slugify.ts
1357
- var De = 40;
1358
- function Oe(e) {
1398
+ var je = 40;
1399
+ function Me(e) {
1359
1400
  return e.trim().replace(/\s+/g, "-").replace(/[^a-zA-Z0-9가-힣ㄱ-ㅎㅏ-ㅣ-]/g, "").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
1360
1401
  }
1361
- function ke(e, t = 60) {
1402
+ function Ne(e, t = 60) {
1362
1403
  return e.replace(/[^a-zA-Z0-9가-힣ㄱ-ㅎ._-]/g, "-").slice(0, t);
1363
1404
  }
1364
1405
  //#endregion
1365
1406
  //#region src/utils/commentImages.ts
1366
- var Ae = /* @__PURE__ */ new Set([
1407
+ var Pe = /* @__PURE__ */ new Set([
1367
1408
  "image/jpeg",
1368
1409
  "image/png",
1369
1410
  "image/gif",
1370
1411
  "image/webp"
1371
1412
  ]);
1372
- function je(e) {
1413
+ function Fe(e) {
1373
1414
  let t = (e.type || "").toLowerCase();
1374
- if (Ae.has(t)) return !0;
1415
+ if (Pe.has(t)) return !0;
1375
1416
  let n = e.name.toLowerCase();
1376
1417
  return [
1377
1418
  ".jpg",
@@ -1381,7 +1422,7 @@ function je(e) {
1381
1422
  ".webp"
1382
1423
  ].some((e) => n.endsWith(e));
1383
1424
  }
1384
- function Me(e) {
1425
+ function Ie(e) {
1385
1426
  if (!e?.length) return [];
1386
1427
  for (let t of e) if (t?.name && t.url?.startsWith("https://") && t.path && !t.path.includes("..") && t.type?.startsWith("image/") && !(!Number.isFinite(t.size) || t.size <= 0)) return [{
1387
1428
  name: t.name.slice(0, 200),
@@ -1392,7 +1433,7 @@ function Me(e) {
1392
1433
  }];
1393
1434
  return [];
1394
1435
  }
1395
- function Ne(e, t) {
1436
+ function Le(e, t) {
1396
1437
  let n = t.endsWith("/") ? t : `${t}/`;
1397
1438
  if (!Array.isArray(e)) return [];
1398
1439
  let r = /* @__PURE__ */ new Set();
@@ -1404,6 +1445,6 @@ function Ne(e, t) {
1404
1445
  return [...r];
1405
1446
  }
1406
1447
  //#endregion
1407
- export { C as $, b as A, O as B, R as C, v as D, M as E, fe as F, ae as G, T as H, pe as I, re as J, ie as K, de as L, S as M, me as N, y as O, ge as P, le as Q, se as R, I as S, ye as T, w as U, oe as V, ce as W, ue as X, D as Y, E as Z, P as _, ke as a, g as at, N as b, Ee as c, Y as d, te as et, Z as f, ve as g, G as h, De as i, d as it, x as j, _ as k, q as l, U as m, je as n, f as nt, Oe as o, h as ot, Se as p, he as q, Me as r, p as rt, Q as s, Ne as t, ne as tt, X as u, z as v, L as w, F as x, _e as y, k as z };
1448
+ export { fe as $, x as A, k as B, z as C, y as D, P as E, he as F, D as G, le as H, ge as I, re as J, E as K, me as L, C as M, _e as N, b as O, ye as P, ne as Q, ce as R, L as S, Ce as T, se as U, T as V, ue as W, ae as X, oe as Y, ve as Z, be as _, Ne as a, te as at, F as b, Ae as c, f as ct, Y as d, A as et, Z as f, xe as g, G as h, je as i, ee as it, S as j, v as k, q as l, _ as lt, U as m, Fe as n, de as nt, Me as o, p as ot, Ee as p, ie as q, Ie as r, w as rt, Q as s, m as st, Le as t, O as tt, X as u, g as ut, Se as v, R as w, I as x, N as y, pe as z };
1408
1449
 
1409
- //# sourceMappingURL=commentImages-DZBDCMWH.js.map
1450
+ //# sourceMappingURL=commentImages-xb5Y4ySe.js.map