memi-board 0.64.0 → 0.66.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 (67) hide show
  1. package/dist/{ar-Dg9e1ruU.js → ar-vCWN4UgB.js} +4 -1
  2. package/dist/ar-vCWN4UgB.js.map +1 -0
  3. package/dist/{commentImages-xb5Y4ySe.js → commentImages-Bdy_5GoM.js} +193 -138
  4. package/dist/commentImages-Bdy_5GoM.js.map +1 -0
  5. package/dist/composables/useMemiBoardAuthorMemo.d.ts +18 -0
  6. package/dist/composables/useMemiBoardAutoTranslate.d.ts +1 -1
  7. package/dist/{de-CpGJ3KkZ.js → de-Br2Z_mcP.js} +4 -1
  8. package/dist/de-Br2Z_mcP.js.map +1 -0
  9. package/dist/{en-I7auZHra.js → en-dwiFlzpm.js} +52 -3
  10. package/dist/en-dwiFlzpm.js.map +1 -0
  11. package/dist/{es-tMBUNff2.js → es-E1OXjEpy.js} +4 -1
  12. package/dist/{es-tMBUNff2.js.map → es-E1OXjEpy.js.map} +1 -1
  13. package/dist/{fr-BFXp_PeM.js → fr-BBiQmovr.js} +4 -1
  14. package/dist/fr-BBiQmovr.js.map +1 -0
  15. package/dist/{id-B7lgKUHZ.js → id-D-XLJeg9.js} +4 -1
  16. package/dist/id-D-XLJeg9.js.map +1 -0
  17. package/dist/index.d.ts +8 -2
  18. package/dist/index.js +1803 -1643
  19. package/dist/index.js.map +1 -1
  20. package/dist/{ja-3SXam5Sk.js → ja-DDx8RDwB.js} +4 -1
  21. package/dist/ja-DDx8RDwB.js.map +1 -0
  22. package/dist/{pt-C2_VknPa.js → pt-CmLdTNz1.js} +4 -1
  23. package/dist/pt-CmLdTNz1.js.map +1 -0
  24. package/dist/runtime/components/Attachments.vue +2 -2
  25. package/dist/runtime/components/AuthorMemoList.vue +83 -0
  26. package/dist/runtime/components/AuthorMemoListItem.vue +47 -0
  27. package/dist/runtime/components/AuthorMenu.vue +60 -23
  28. package/dist/runtime/components/CategorySettings.vue +2 -0
  29. package/dist/runtime/components/CommentItem.vue +178 -175
  30. package/dist/runtime/components/Diagnostics.vue +32 -0
  31. package/dist/runtime/components/Editor.vue +94 -8
  32. package/dist/runtime/components/Footer.vue +27 -3
  33. package/dist/runtime/components/GameMemory.vue +78 -0
  34. package/dist/runtime/components/GameSnake.vue +162 -0
  35. package/dist/runtime/components/GameSudoku.vue +118 -0
  36. package/dist/runtime/components/ListCard.vue +20 -9
  37. package/dist/runtime/components/OrphanCleanup.vue +2 -0
  38. package/dist/runtime/components/Profile.vue +14 -0
  39. package/dist/runtime/components/ProfileEditModal.vue +37 -14
  40. package/dist/runtime/components/ReportList.vue +2 -0
  41. package/dist/runtime/components/Settings.vue +4 -0
  42. package/dist/runtime/components/SettingsVersion.vue +10 -0
  43. package/dist/runtime/components/Spec.vue +276 -0
  44. package/dist/runtime/components/UsersSettings.vue +2 -0
  45. package/dist/runtime/components/WaitingGames.vue +31 -0
  46. package/dist/runtime/components/WaitingOverlay.vue +76 -0
  47. package/dist/storage.js +36 -36
  48. package/dist/utils/boardPaths.d.ts +2 -0
  49. package/dist/utils/localizedFields.d.ts +8 -0
  50. package/dist/utils/postLimits.d.ts +26 -0
  51. package/dist/utils/postSlug.d.ts +3 -1
  52. package/dist/utils/profileLimits.d.ts +5 -0
  53. package/dist/{zh-CuOjIYyr.js → zh-nWOVw2PS.js} +4 -1
  54. package/dist/zh-nWOVw2PS.js.map +1 -0
  55. package/docs/firebase-setup.md +25 -0
  56. package/docs/firestore.rules.example +114 -9
  57. package/docs/storage.rules.example +10 -1
  58. package/package.json +1 -1
  59. package/dist/ar-Dg9e1ruU.js.map +0 -1
  60. package/dist/commentImages-xb5Y4ySe.js.map +0 -1
  61. package/dist/de-CpGJ3KkZ.js.map +0 -1
  62. package/dist/en-I7auZHra.js.map +0 -1
  63. package/dist/fr-BFXp_PeM.js.map +0 -1
  64. package/dist/id-B7lgKUHZ.js.map +0 -1
  65. package/dist/ja-3SXam5Sk.js.map +0 -1
  66. package/dist/pt-C2_VknPa.js.map +0 -1
  67. package/dist/zh-CuOjIYyr.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 l } from "vue";
2
- import { collection as u, doc as d } 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 ee } from "vue";
2
+ import { collection as l, doc as u } from "firebase/firestore";
3
3
  //#region src/i18n/locales.ts
4
- var f = [
4
+ var d = [
5
5
  {
6
6
  code: "ko",
7
7
  name: "한국어",
@@ -62,19 +62,19 @@ var f = [
62
62
  intl: "id-ID",
63
63
  dir: "ltr"
64
64
  }
65
- ], p = "ko", m = "en", h = new Set(f.map((e) => e.code));
66
- function g(e) {
65
+ ], f = "ko", p = "en", m = new Set(d.map((e) => e.code));
66
+ function h(e) {
67
67
  if (typeof e != "string") return;
68
68
  let t = e.trim().toLowerCase().split(/[-_]/)[0];
69
- return t && h.has(t) ? t : void 0;
69
+ return t && m.has(t) ? t : void 0;
70
70
  }
71
- function _(e) {
72
- return f.find((t) => t.code === e) ?? f[0];
71
+ function g(e) {
72
+ return d.find((t) => t.code === e) ?? d[0];
73
73
  }
74
74
  //#endregion
75
75
  //#region src/utils/boardPaths.ts
76
- var v = "memiBoardPosts", y = "memiBoardComments", b = "memiBoardLikes", x = "memiBoardReports", S = "memiBoardSettings", C = "memiBoardUsers";
77
- function w(e) {
76
+ var _ = "memiBoardPosts", v = "memiBoardComments", y = "memiBoardLikes", b = "memiBoardReports", x = "memiBoardSettings", S = "memiBoardUsers";
77
+ function C(e) {
78
78
  return {
79
79
  postsCollection: e.postsCollection?.trim() || "memiBoardPosts",
80
80
  commentsCollection: e.commentsCollection?.trim() || "memiBoardComments",
@@ -84,96 +84,99 @@ function w(e) {
84
84
  usersCollection: e.usersCollection?.trim() || "memiBoardUsers"
85
85
  };
86
86
  }
87
- function ee(e, t) {
88
- return u(e, t.settingsCollection);
89
- }
90
- function te(e, t, n) {
91
- return d(e, t.settingsCollection, n);
87
+ function te(e, t) {
88
+ return l(e, t.settingsCollection);
92
89
  }
93
- function ne(e, t) {
94
- return u(e, t.postsCollection);
90
+ function ne(e, t, n) {
91
+ return u(e, t.settingsCollection, n);
95
92
  }
96
- function re(e, t, n) {
97
- return d(e, t.postsCollection, n);
93
+ function re(e, t) {
94
+ return l(e, t.postsCollection);
98
95
  }
99
96
  function ie(e, t, n) {
100
- return d(e, t.postsCollection, n, "body", "main");
97
+ return u(e, t.postsCollection, n);
101
98
  }
102
99
  function ae(e, t, n) {
103
- return u(e, t.postsCollection, n, "revisions");
100
+ return u(e, t.postsCollection, n, "body", "main");
104
101
  }
105
- function oe(e, t, n, r) {
106
- return d(e, t.postsCollection, n, "revisions", String(r));
102
+ function oe(e, t, n) {
103
+ return l(e, t.postsCollection, n, "revisions");
107
104
  }
108
- function se(e, t) {
109
- return u(e, t.commentsCollection);
105
+ function se(e, t, n, r) {
106
+ return u(e, t.postsCollection, n, "revisions", String(r));
110
107
  }
111
- function ce(e, t, n) {
112
- return d(e, t.commentsCollection, n);
108
+ function ce(e, t) {
109
+ return l(e, t.commentsCollection);
113
110
  }
114
111
  function le(e, t, n) {
115
- return u(e, t.commentsCollection, n, "revisions");
112
+ return u(e, t.commentsCollection, n);
116
113
  }
117
- function T(e, t, n, r) {
118
- return d(e, t.commentsCollection, n, "revisions", String(r));
114
+ function ue(e, t, n) {
115
+ return l(e, t.commentsCollection, n, "revisions");
119
116
  }
120
- function E(e, t) {
121
- return u(e, t.likesCollection);
117
+ function w(e, t, n, r) {
118
+ return u(e, t.commentsCollection, n, "revisions", String(r));
122
119
  }
123
- function D(e, t) {
120
+ function T(e, t) {
121
+ return l(e, t.likesCollection);
122
+ }
123
+ function E(e, t) {
124
124
  return `${e}_${t}`;
125
125
  }
126
- function ue(e, t, n, r) {
127
- return d(e, t.likesCollection, D(n, r));
126
+ function de(e, t, n, r) {
127
+ return u(e, t.likesCollection, E(n, r));
128
128
  }
129
- function de(e, t) {
130
- return u(e, t.reportsCollection);
129
+ function fe(e, t) {
130
+ return l(e, t.reportsCollection);
131
131
  }
132
- function O(e, t) {
132
+ function D(e, t) {
133
133
  return `${e}_${t}`;
134
134
  }
135
- function fe(e, t, n, r) {
136
- return d(e, t.reportsCollection, O(n, r));
135
+ function pe(e, t, n, r) {
136
+ return u(e, t.reportsCollection, D(n, r));
137
137
  }
138
- function k(e, t) {
138
+ function O(e, t) {
139
139
  return `c_${e}_${t}`;
140
140
  }
141
- function pe(e, t, n, r) {
142
- return d(e, t.reportsCollection, k(n, r));
141
+ function me(e, t, n, r) {
142
+ return u(e, t.reportsCollection, O(n, r));
143
143
  }
144
- function A(e, t, n) {
145
- return d(e, t.reportsCollection, n);
144
+ function he(e, t, n) {
145
+ return u(e, t.reportsCollection, n);
146
146
  }
147
- function me(e, t) {
148
- return u(e, t.usersCollection);
147
+ function ge(e, t) {
148
+ return l(e, t.usersCollection);
149
149
  }
150
- function he(e, t, n) {
151
- return d(e, t.usersCollection, n);
150
+ function _e(e, t, n) {
151
+ return u(e, t.usersCollection, n);
152
152
  }
153
- function ge(e, t, n) {
154
- return d(e, t.usersCollection, n, "private", "info");
153
+ function ve(e, t, n) {
154
+ return u(e, t.usersCollection, n, "private", "info");
155
155
  }
156
- function _e(e, t, n, r) {
157
- return d(e, t.usersCollection, n, "memos", r);
156
+ function ye(e, t, n, r) {
157
+ return u(e, t.usersCollection, n, "memos", r);
158
158
  }
159
- function ve(e, t) {
159
+ function be(e, t, n) {
160
+ return l(e, t.usersCollection, n, "memos");
161
+ }
162
+ function xe(e, t) {
160
163
  return `${e.postsCollection}/${t}`;
161
164
  }
162
- function ye(e, t) {
165
+ function k(e, t) {
163
166
  return `${e.postsCollection}/${e.usersCollection}/${t}`;
164
167
  }
165
168
  //#endregion
166
169
  //#region src/config.ts
167
- var j = "__MEMI_BOARD_CONFIG__";
168
- function M() {
170
+ var A = "__MEMI_BOARD_CONFIG__";
171
+ function j() {
169
172
  let e = globalThis;
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,
173
+ return e[A] || (e[A] = o({
174
+ postsCollection: _,
175
+ commentsCollection: v,
176
+ likesCollection: y,
177
+ reportsCollection: b,
178
+ settingsCollection: x,
179
+ usersCollection: S,
177
180
  auth: { providers: ["google", "apple"] },
178
181
  moderation: {
179
182
  enabled: !0,
@@ -191,10 +194,10 @@ function M() {
191
194
  defaultOgImage: "",
192
195
  basePath: "/board"
193
196
  }
194
- })), e[j];
197
+ })), e[A];
195
198
  }
196
- function N(e) {
197
- let t = M();
199
+ function M(e) {
200
+ let t = j();
198
201
  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 = {
199
202
  ...t.i18n,
200
203
  ...e.i18n
@@ -206,49 +209,49 @@ function N(e) {
206
209
  ...e.bannerGeneration
207
210
  }), e.roleLabels && (t.roleLabels = { ...e.roleLabels }), e.locale && (t.locale = e.locale);
208
211
  }
212
+ function N() {
213
+ return j();
214
+ }
209
215
  function P() {
210
- return M();
216
+ return N().site?.disableAi !== !0;
211
217
  }
212
- function F() {
213
- return P().site?.disableAi !== !0;
218
+ function Se() {
219
+ if (!P()) throw Object.assign(/* @__PURE__ */ Error("AI features are disabled for this board service."), { code: "memi-board/ai-disabled" });
214
220
  }
215
- function be() {
216
- if (!F()) throw Object.assign(/* @__PURE__ */ Error("AI features are disabled for this board service."), { code: "memi-board/ai-disabled" });
221
+ function F() {
222
+ let e = N();
223
+ return e.site?.disableI18n !== !0 && e.i18n?.enabled !== !1;
217
224
  }
218
225
  function I() {
219
- let e = P();
220
- return e.site?.disableI18n !== !0 && e.i18n?.enabled !== !1;
226
+ return P() && F() && N().translation?.enabled !== !1;
221
227
  }
222
228
  function L() {
223
- return F() && I() && P().translation?.enabled !== !1;
224
- }
225
- function R() {
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
+ let e = d.map((e) => e.code), t = N().site?.locales;
230
+ if (!F() || !t?.length) return e;
231
+ let n = new Set(t.map((e) => h(e)).filter(Boolean)), r = e.filter((e) => n.has(e));
229
232
  return r.length ? r : e;
230
233
  }
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];
234
+ function R() {
235
+ let e = N(), t = e.site?.locale || e.locale, n = L(), r = h(t);
236
+ return n.length === d.length || r && n.includes(r) ? t : n[0];
234
237
  }
235
- function xe(e) {
236
- P().site = {
238
+ function Ce(e) {
239
+ N().site = {
237
240
  disableAi: e?.disableAi === !0,
238
241
  disableI18n: e?.disableI18n === !0,
239
242
  locale: typeof e?.locale == "string" && e.locale ? e.locale : void 0,
240
243
  locales: Array.isArray(e?.locales) ? e.locales.filter((e) => typeof e == "string") : void 0
241
244
  };
242
245
  }
243
- function Se() {
244
- if (!L()) throw Object.assign(/* @__PURE__ */ Error("Content translation is disabled for this board service."), { code: "memi-board/translation-disabled" });
246
+ function we() {
247
+ if (!I()) throw Object.assign(/* @__PURE__ */ Error("Content translation is disabled for this board service."), { code: "memi-board/translation-disabled" });
245
248
  }
246
- function Ce() {
247
- return w(P());
249
+ function Te() {
250
+ return C(N());
248
251
  }
249
252
  //#endregion
250
253
  //#region src/i18n/messages/ko/index.ts
251
- var we = {
254
+ var Ee = {
252
255
  accountDeletion: {
253
256
  title: "회원 탈퇴",
254
257
  intro: "계정과 개인정보를 삭제하려면 탈퇴를 진행해 주세요.",
@@ -290,7 +293,10 @@ var we = {
290
293
  strikeRestricted: " 경고 {count}회가 되어 글·댓글 작성이 제한됩니다.",
291
294
  notInitialized: "[memi-board] Firebase Auth가 초기화되지 않았습니다."
292
295
  },
293
- authorMemo: { tooLong: "메모는 {max}자까지 작성할 수 있습니다." },
296
+ authorMemo: {
297
+ tooLong: "메모는 {max}자까지 작성할 수 있습니다.",
298
+ limitReached: "메모는 최대 {max}개까지 남길 수 있습니다. 내 프로필에서 안 쓰는 메모를 지워주세요."
299
+ },
294
300
  authorMenu: {
295
301
  menu: "작성자 메뉴",
296
302
  viewProfile: "프로필 보기",
@@ -300,7 +306,9 @@ var we = {
300
306
  memoTitle: "나만 보는 메모",
301
307
  memoPlaceholder: "이 작성자에 대해 적어두기…",
302
308
  bad: "나쁨",
303
- good: "좋음"
309
+ good: "좋음",
310
+ myMemosTitle: "내가 남긴 메모",
311
+ myMemosEmpty: "아직 남긴 메모가 없어요. 작성자 이름을 눌러 메모를 남길 수 있어요."
304
312
  },
305
313
  avatarCropModal: {
306
314
  title: "프로필 사진 자르기",
@@ -505,6 +513,8 @@ var we = {
505
513
  submitNext: "다음: 미리보기",
506
514
  apply: "적용",
507
515
  imageOptimizing: "이미지 최적화 및 업로드 중…",
516
+ bodyUsage: "본문 {count} / {max}자 (HTML 기준)",
517
+ bodyUsageTranslated: "번역 언어 {languages}개에 맞춘 한도입니다.",
508
518
  cover: {
509
519
  hint: "사진 {count}/{max} · 대표사진 선택 · 끌어 순서 변경 · 파일 드롭/붙여넣기로 추가",
510
520
  imageLink: "이미지 링크",
@@ -784,6 +794,7 @@ var we = {
784
794
  boardIdRequired: "[memi-board] boardId 가 필요합니다.",
785
795
  photoRequired: "사진을 올려 주세요.",
786
796
  bodyRequired: "본문에 글자를 입력하거나 이미지를 첨부해 주세요.",
797
+ bodyTooLong: "본문이 너무 깁니다. 이 보드에서는 HTML 기준 {max}자까지 저장할 수 있어요.",
787
798
  titleRequired: "제목을 입력해 주세요.",
788
799
  editLimitReached: "수정은 최대 {max}번까지 할 수 있어요. 더 고쳐야 하면 보드 관리자에게 요청해 주세요."
789
800
  },
@@ -1182,6 +1193,13 @@ var we = {
1182
1193
  like: "좋아요 문서"
1183
1194
  }
1184
1195
  },
1196
+ diagnostics: {
1197
+ title: "진단",
1198
+ description: "전체 사용자를 한 번 훑어서, 앱에서만 막고 있는 한도를 넘긴 데이터를 찾습니다. 아직 준비 중입니다.",
1199
+ scan: "진단 실행",
1200
+ comingSoon: "준비 중",
1201
+ checks: { authorMemoCount: "작성자 메모를 {max}개 넘게 저장한 사용자" }
1202
+ },
1185
1203
  danger: {
1186
1204
  title: "위험 영역",
1187
1205
  description: "모든 게시글, 댓글, 댓글 이미지, 첨부파일과 카테고리 설정을 영구 삭제합니다. 보드 사용자와 관리자 권한은 유지합니다.",
@@ -1261,6 +1279,40 @@ var we = {
1261
1279
  emailLoadFailed: "이메일을 불러오지 못했습니다.",
1262
1280
  moderationWarnings: "콘텐츠 경고 {count}회"
1263
1281
  },
1282
+ waiting: {
1283
+ title: "글을 번역하고 있어요~",
1284
+ subtitle: "여러 언어로 번역하느라 조금 걸려요. 그동안 미니게임을 즐겨보세요!",
1285
+ demoLink: "번역 대기 화면 시험해 보기",
1286
+ doneTitle: "번역이 끝나 글이 올라갔어요!",
1287
+ doneSubtitle: "게임은 계속 즐기셔도 돼요. 준비되면 글을 보러 가세요.",
1288
+ continue: "글 보러 가기",
1289
+ close: "닫기",
1290
+ restart: "다시 하기",
1291
+ games: {
1292
+ memory: "짝 맞추기",
1293
+ snake: "스네이크",
1294
+ sudoku: "스도쿠"
1295
+ },
1296
+ memory: {
1297
+ moves: "시도 {count}회",
1298
+ cleared: "모두 맞췄어요! ({count}회)"
1299
+ },
1300
+ snake: {
1301
+ score: "점수 {score}",
1302
+ best: "최고 {best}",
1303
+ gameOver: "게임 오버",
1304
+ start: "아무 방향이나 눌러 시작",
1305
+ up: "위",
1306
+ down: "아래",
1307
+ left: "왼쪽",
1308
+ right: "오른쪽"
1309
+ },
1310
+ sudoku: {
1311
+ hint: "칸을 눌러 숫자를 채워 보세요",
1312
+ solved: "완성! 🎉",
1313
+ erase: "지우기"
1314
+ }
1315
+ },
1264
1316
  writingAssistant: {
1265
1317
  loginRequired: "AI 글쓰기 도우미는 로그인 후 사용할 수 있습니다.",
1266
1318
  userMissing: "사용자 정보를 확인한 뒤 다시 시도해 주세요.",
@@ -1284,28 +1336,28 @@ var we = {
1284
1336
  custom: "커스텀 스타일로 바꾸기…"
1285
1337
  }
1286
1338
  }
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")
1339
+ }, z = {
1340
+ en: () => import("./en-dwiFlzpm.js"),
1341
+ ja: () => import("./ja-DDx8RDwB.js"),
1342
+ de: () => import("./de-Br2Z_mcP.js"),
1343
+ fr: () => import("./fr-BBiQmovr.js"),
1344
+ es: () => import("./es-E1OXjEpy.js"),
1345
+ pt: () => import("./pt-CmLdTNz1.js"),
1346
+ zh: () => import("./zh-nWOVw2PS.js"),
1347
+ ar: () => import("./ar-vCWN4UgB.js"),
1348
+ id: () => import("./id-D-XLJeg9.js")
1297
1349
  }, B = "__MEMI_BOARD_I18N__";
1298
1350
  function V() {
1299
1351
  let e = globalThis;
1300
1352
  return e[B] ??= {
1301
- messages: { ko: we },
1353
+ messages: { ko: Ee },
1302
1354
  pending: {},
1303
1355
  version: s(0)
1304
1356
  }, e[B];
1305
1357
  }
1306
1358
  function H(e) {
1307
1359
  let t = V();
1308
- return t.messages[e] || e === "ko" ? Promise.resolve() : (t.pending[e] ??= Te[e]().then((n) => {
1360
+ return t.messages[e] || e === "ko" ? Promise.resolve() : (t.pending[e] ??= z[e]().then((n) => {
1309
1361
  t.messages[e] = n.default, t.version.value++;
1310
1362
  }).catch((n) => {
1311
1363
  delete t.pending[e], console.warn(`[memi-board] failed to load locale "${e}"`, n);
@@ -1314,7 +1366,7 @@ function H(e) {
1314
1366
  function U(e) {
1315
1367
  return e === "ko" ? Promise.resolve() : Promise.all([H(e), H("en")]).then(() => void 0);
1316
1368
  }
1317
- function Ee(e) {
1369
+ function De(e) {
1318
1370
  return !!V().messages[e];
1319
1371
  }
1320
1372
  function W(e, t) {
@@ -1325,7 +1377,7 @@ function W(e, t) {
1325
1377
  }
1326
1378
  return typeof n == "string" ? n : void 0;
1327
1379
  }
1328
- function De(e, t) {
1380
+ function Oe(e, t) {
1329
1381
  return t ? e.replace(/\{(\w+)\}/g, (e, n) => {
1330
1382
  let r = t[n];
1331
1383
  return r == null ? e : String(r);
@@ -1335,23 +1387,23 @@ function G(e, t, n) {
1335
1387
  let r = V();
1336
1388
  r.version.value;
1337
1389
  let i = e ?? "ko", a = W(r.messages[i], t) ?? (i === "ko" ? void 0 : W(r.messages.en, t)) ?? W(r.messages.ko, t);
1338
- return a == null ? t : De(a, n);
1390
+ return a == null ? t : Oe(a, n);
1339
1391
  }
1340
1392
  //#endregion
1341
1393
  //#region src/utils/formatDate.ts
1342
1394
  function K(e) {
1343
- return _(e ?? "ko").intl;
1395
+ return g(e ?? "ko").intl;
1344
1396
  }
1345
1397
  function q(e, t) {
1346
1398
  return e?.toDate ? e.toDate().toLocaleDateString(K(t)) : "";
1347
1399
  }
1348
- var Oe = 60, J = 3600, ke = 24 * J;
1400
+ var ke = 60, J = 3600, Ae = 24 * J;
1349
1401
  function Y(e, t = Date.now(), n) {
1350
1402
  if (!e?.toDate) return G(n, "common.date.justNow");
1351
1403
  let r = Math.max(0, Math.round((t - e.toDate().getTime()) / 1e3));
1352
1404
  if (r < 45) return G(n, "common.date.fewSecondsAgo");
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");
1405
+ let i = new Intl.RelativeTimeFormat(K(n), { numeric: "always" }), a = r / Ae;
1406
+ return r < 90 ? i.format(-1, "minute") : r < 2700 ? i.format(-Math.round(r / ke), "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");
1355
1407
  }
1356
1408
  function X(e, t) {
1357
1409
  return e?.toDate ? new Intl.DateTimeFormat(K(t), {
@@ -1371,48 +1423,51 @@ function Z(e, t, n) {
1371
1423
  //#endregion
1372
1424
  //#region src/i18n/useMemiBoardI18n.ts
1373
1425
  var Q = "memiBoard:hostLocale", $ = Symbol("memiBoard:boardLocale");
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));
1426
+ function je(o = {}) {
1427
+ let s = n(), l = s ? r($, null) : null, u = s ? r(Q, null) : null, d = N(), f = e(F), p = e(I), m = e(P), _ = e(() => f.value ? h(c(o.boardLocale)) ?? l?.value ?? h(c(u)) ?? h(R()) ?? "ko" : h(R()) ?? "ko");
1428
+ o.boardLocale !== void 0 && s && a($, _), ee(_, (e) => void U(e), { immediate: !0 }), t() && i(() => U(_.value));
1429
+ let v = e(() => g(_.value));
1378
1430
  return {
1379
- locale: v,
1380
- i18nEnabled: p,
1381
- translationEnabled: m,
1382
- aiEnabled: h,
1383
- dir: e(() => y.value.dir),
1384
- intlLocale: e(() => y.value.intl),
1431
+ locale: _,
1432
+ i18nEnabled: f,
1433
+ translationEnabled: p,
1434
+ aiEnabled: m,
1435
+ dir: e(() => v.value.dir),
1436
+ intlLocale: e(() => v.value.intl),
1385
1437
  t: (e, t) => {
1386
1438
  let n = e.startsWith("common.role.") ? e.slice(12) : "";
1387
- return f.roleLabels?.[n] ?? G(v.value, e, t);
1439
+ return d.roleLabels?.[n] ?? G(_.value, e, t);
1388
1440
  },
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)
1441
+ formatDate: (e) => q(e, _.value),
1442
+ formatFullDate: (e) => X(e, _.value),
1443
+ formatRelativeDate: (e, t) => Y(e, t, _.value),
1444
+ formatTimestampDetails: (e, t) => Z(e, t, _.value),
1445
+ formatNumber: (e) => e.toLocaleString(v.value.intl)
1394
1446
  };
1395
1447
  }
1396
1448
  //#endregion
1397
1449
  //#region src/utils/slugify.ts
1398
- var je = 40;
1399
- function Me(e) {
1450
+ var Me = 40;
1451
+ function Ne(e) {
1400
1452
  return e.trim().replace(/\s+/g, "-").replace(/[^a-zA-Z0-9가-힣ㄱ-ㅎㅏ-ㅣ-]/g, "").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
1401
1453
  }
1402
- function Ne(e, t = 60) {
1403
- return e.replace(/[^a-zA-Z0-9가-힣ㄱ-ㅎ._-]/g, "-").slice(0, t);
1454
+ function Pe(e, t = 60) {
1455
+ let n = e.replace(/[^a-zA-Z0-9가-힣ㄱ-ㅎ._-]/g, "-");
1456
+ if (n.length <= t) return n;
1457
+ let r = n.lastIndexOf("."), i = r > 0 && n.length - r <= 10 ? n.slice(r) : "";
1458
+ return n.slice(0, t - i.length) + i;
1404
1459
  }
1405
1460
  //#endregion
1406
1461
  //#region src/utils/commentImages.ts
1407
- var Pe = /* @__PURE__ */ new Set([
1462
+ var Fe = 1, Ie = /* @__PURE__ */ new Set([
1408
1463
  "image/jpeg",
1409
1464
  "image/png",
1410
1465
  "image/gif",
1411
1466
  "image/webp"
1412
1467
  ]);
1413
- function Fe(e) {
1468
+ function Le(e) {
1414
1469
  let t = (e.type || "").toLowerCase();
1415
- if (Pe.has(t)) return !0;
1470
+ if (Ie.has(t)) return !0;
1416
1471
  let n = e.name.toLowerCase();
1417
1472
  return [
1418
1473
  ".jpg",
@@ -1422,7 +1477,7 @@ function Fe(e) {
1422
1477
  ".webp"
1423
1478
  ].some((e) => n.endsWith(e));
1424
1479
  }
1425
- function Ie(e) {
1480
+ function Re(e) {
1426
1481
  if (!e?.length) return [];
1427
1482
  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 [{
1428
1483
  name: t.name.slice(0, 200),
@@ -1433,7 +1488,7 @@ function Ie(e) {
1433
1488
  }];
1434
1489
  return [];
1435
1490
  }
1436
- function Le(e, t) {
1491
+ function ze(e, t) {
1437
1492
  let n = t.endsWith("/") ? t : `${t}/`;
1438
1493
  if (!Array.isArray(e)) return [];
1439
1494
  let r = /* @__PURE__ */ new Set();
@@ -1445,6 +1500,6 @@ function Le(e, t) {
1445
1500
  return [...r];
1446
1501
  }
1447
1502
  //#endregion
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 };
1503
+ export { xe as $, _ as A, le as B, I as C, N as D, Te as E, be as F, ce as G, O as H, k as I, T as J, de as K, _e as L, x as M, S as N, v as O, ye as P, oe as Q, ve as R, F as S, L as T, w as U, me as V, ue as W, ie as X, ae as Y, se as Z, Ce as _, Me as a, C as at, M as b, Q as c, f as ct, X as d, g as dt, re as et, Y as f, h as ft, G as g, U as h, Re as i, fe as it, b as j, y as k, je as l, p as lt, De as m, ze as n, he as nt, Pe as o, te as ot, Z as p, E as q, Le as r, D as rt, Ne as s, ne as st, Fe as t, pe as tt, q as u, d as ut, Se as v, R as w, P as x, we as y, ge as z };
1449
1504
 
1450
- //# sourceMappingURL=commentImages-xb5Y4ySe.js.map
1505
+ //# sourceMappingURL=commentImages-Bdy_5GoM.js.map