memi-board 0.44.0 → 0.44.1

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.
package/dist/index.js CHANGED
@@ -421,8 +421,29 @@ function ct() {
421
421
  };
422
422
  }
423
423
  //#endregion
424
+ //#region src/utils/imeSafeSubmit.ts
425
+ var lt = /* @__PURE__ */ new WeakMap();
426
+ function ut(e) {
427
+ let t = e.currentTarget;
428
+ return t instanceof HTMLButtonElement ? t : t instanceof Element ? t.closest("button") : null;
429
+ }
430
+ function dt(e) {
431
+ if (e.pointerType !== "mouse" || e.button !== 0) return;
432
+ let t = ut(e), n = t?.form;
433
+ if (!t || !n || t.disabled) return;
434
+ lt.set(t, Date.now() + 1e3);
435
+ let r = document.activeElement;
436
+ r instanceof HTMLElement && r.blur(), setTimeout(() => n.requestSubmit(t), 0);
437
+ }
438
+ function ft(e) {
439
+ let t = ut(e);
440
+ if (!t) return;
441
+ let n = lt.get(t);
442
+ n && Date.now() < n && (e.preventDefault(), lt.delete(t));
443
+ }
444
+ //#endregion
424
445
  //#region src/utils/extractEditorImageUrls.ts
425
- function lt(e) {
446
+ function pt(e) {
426
447
  if (!e) return [];
427
448
  let t = /* @__PURE__ */ new Set();
428
449
  for (let n of e.matchAll(/!\[[^\]]*]\((https?:\/\/[^)\s]+)\)/g)) n[1] && t.add(n[1].replaceAll("&amp;", "&"));
@@ -431,7 +452,7 @@ function lt(e) {
431
452
  }
432
453
  //#endregion
433
454
  //#region src/utils/storagePath.ts
434
- function ut(e) {
455
+ function mt(e) {
435
456
  try {
436
457
  let t = new URL(e), n = t.hostname.toLowerCase();
437
458
  if (!(n === "firebasestorage.googleapis.com" || n.endsWith(".firebasestorage.app"))) return null;
@@ -441,109 +462,109 @@ function ut(e) {
441
462
  return null;
442
463
  }
443
464
  }
444
- function dt(e) {
465
+ function ht(e) {
445
466
  return e.match(/(?:^|\/)posts\/([^/]+)\//)?.[1] ?? null;
446
467
  }
447
468
  //#endregion
448
469
  //#region src/utils/deletePostCascade.ts
449
- async function ft(e) {
470
+ async function gt(e) {
450
471
  try {
451
472
  let t = await ve(e);
452
- await Promise.all([...t.items.map((e) => ge(e).catch(() => {})), ...t.prefixes.map((e) => ft(e))]);
473
+ await Promise.all([...t.items.map((e) => ge(e).catch(() => {})), ...t.prefixes.map((e) => gt(e))]);
453
474
  } catch {}
454
475
  }
455
- async function pt(e, t) {
456
- await ft(ye(e, `${t}/images`)), await ft(ye(e, `${t}/attachments`));
476
+ async function _t(e, t) {
477
+ await gt(ye(e, `${t}/images`)), await gt(ye(e, `${t}/attachments`));
457
478
  }
458
- async function mt(e, t) {
479
+ async function vt(e, t) {
459
480
  let n = [...new Set([...t].filter(Boolean))];
460
481
  await Promise.all(n.map((t) => ge(ye(e, t)).catch(() => {})));
461
482
  }
462
- var ht = 450;
463
- async function gt(e, t) {
483
+ var yt = 450;
484
+ async function bt(e, t) {
464
485
  let n = await z(t);
465
- for (let t = 0; t < n.docs.length; t += ht) {
486
+ for (let t = 0; t < n.docs.length; t += yt) {
466
487
  let r = X(e);
467
- n.docs.slice(t, t + ht).forEach((e) => r.delete(e.ref)), await r.commit();
488
+ n.docs.slice(t, t + yt).forEach((e) => r.delete(e.ref)), await r.commit();
468
489
  }
469
490
  }
470
- async function _t(e, t, n) {
471
- await gt(e, W(O(e, t), Y("postId", "==", n)));
491
+ async function xt(e, t, n) {
492
+ await bt(e, W(O(e, t), Y("postId", "==", n)));
472
493
  }
473
- async function vt(e, t, n) {
474
- await gt(e, W(i(e, t), Y("postId", "==", n)));
494
+ async function St(e, t, n) {
495
+ await bt(e, W(i(e, t), Y("postId", "==", n)));
475
496
  }
476
- async function yt(e, t, n) {
477
- await gt(e, W(O(e, t), Y("commentId", "==", n)));
497
+ async function Ct(e, t, n) {
498
+ await bt(e, W(O(e, t), Y("commentId", "==", n)));
478
499
  }
479
- async function bt(e, n, r, i) {
500
+ async function wt(e, n, r, i) {
480
501
  let o = t(e, r, i), s = a(e, r, i), [c, l] = await Promise.all([R(o), R(s)]);
481
502
  if (!c.exists()) return;
482
503
  let u = c.data(), d = l.exists() ? String(l.data().content ?? "") : "";
483
- await gt(e, W(E(e, r), Y("postId", "==", i))), await _t(e, r, i), await vt(e, r, i);
504
+ await bt(e, W(E(e, r), Y("postId", "==", i))), await xt(e, r, i), await St(e, r, i);
484
505
  let f = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set();
485
506
  for (let e of u.attachments ?? []) {
486
507
  if (!e?.path) continue;
487
508
  f.add(e.path);
488
- let t = dt(e.path);
509
+ let t = ht(e.path);
489
510
  t && t !== i && p.add(t);
490
511
  }
491
- for (let e of lt(d)) {
492
- let t = ut(e);
512
+ for (let e of pt(d)) {
513
+ let t = mt(e);
493
514
  if (!t) continue;
494
515
  f.add(t);
495
516
  let n = t.replace(/\/images\/([^/]+)$/, "/images/thumbnails/$1").replace(/\.[^.]+$/, ".jpg");
496
517
  n !== t && n.includes("/images/thumbnails/") && f.add(n);
497
518
  let r = t.match(/^(.*\/images\/)([^/]+)\.[^.]+$/);
498
519
  r && !t.includes("/thumbnails/") && f.add(`${r[1]}thumbnails/${r[2]}.jpg`);
499
- let a = dt(t);
520
+ let a = ht(t);
500
521
  a && a !== i && p.add(a);
501
522
  }
502
- await F(s), await pt(n, D(r, i));
503
- for (let e of p) await pt(n, D(r, e));
504
- await mt(n, f), await F(o);
523
+ await F(s), await _t(n, D(r, i));
524
+ for (let e of p) await _t(n, D(r, e));
525
+ await vt(n, f), await F(o);
505
526
  }
506
527
  //#endregion
507
528
  //#region src/utils/postBody.ts
508
- function xt(e) {
529
+ function Tt(e) {
509
530
  return String(e || "").replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<img\b[^>]*>/gi, " ").replace(/<iframe\b[^>]*>[\s\S]*?<\/iframe>/gi, " ").replace(/<video\b[\s\S]*?<\/video>/gi, " ").replace(/<audio\b[\s\S]*?<\/audio>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&nbsp;/gi, " ").replace(/&#160;/g, " ").replace(/&[a-z]+;/gi, " ").replace(/&#\d+;/g, " ").replace(/[\u200B-\u200D\uFEFF\u00AD]/g, "").replace(/\s+/g, " ").trim();
510
531
  }
511
- function St(e, t = 40) {
512
- let n = xt(e);
532
+ function Et(e, t = 40) {
533
+ let n = Tt(e);
513
534
  if (!n) return "";
514
535
  if (n.length <= t) return n;
515
536
  let r = n.slice(0, t), i = r.lastIndexOf(" ");
516
537
  return `${(i >= Math.floor(t * .6) ? r.slice(0, i) : r).trimEnd()}…`;
517
538
  }
518
- function Ct(e) {
519
- return xt(e).length > 0;
539
+ function Dt(e) {
540
+ return Tt(e).length > 0;
520
541
  }
521
- function wt(e, t) {
542
+ function Ot(e, t) {
522
543
  return /<img\b/i.test(String(e || "")) ? !0 : (t || []).some((e) => !!e?.type?.startsWith("image/"));
523
544
  }
524
- function Tt(e) {
525
- return !Ct(e);
545
+ function kt(e) {
546
+ return !Dt(e);
526
547
  }
527
548
  //#endregion
528
549
  //#region src/utils/postPreview.ts
529
- function Et(e) {
550
+ function At(e) {
530
551
  return e.replace(/&amp;/g, "&").replace(/&quot;/g, "\"").replace(/&#39;/g, "'");
531
552
  }
532
- function Dt(e) {
553
+ function jt(e) {
533
554
  if (e) try {
534
- let t = new URL(Et(e)), n = t.hostname.toLowerCase().replace(/^www\./, "");
555
+ let t = new URL(At(e)), n = t.hostname.toLowerCase().replace(/^www\./, "");
535
556
  if (n === "youtu.be") return t.pathname.split("/").filter(Boolean)[0];
536
557
  if (n.endsWith("youtube.com") || n === "youtube-nocookie.com") return t.pathname.startsWith("/embed/") || t.pathname.startsWith("/shorts/") ? t.pathname.split("/")[2] : t.searchParams.get("v") || void 0;
537
558
  } catch {
538
559
  return;
539
560
  }
540
561
  }
541
- function Ot(e) {
542
- let t = Dt(e.videoUrl);
562
+ function Mt(e) {
563
+ let t = jt(e.videoUrl);
543
564
  return t ? `https://i.ytimg.com/vi/${t}/hqdefault.jpg` : e.previewImage || e.attachments?.find((e) => e.type.startsWith("image/"))?.url;
544
565
  }
545
- function kt(e, t = []) {
546
- let n = e.match(/<img\b[^>]*\bsrc=["']([^"']+)["']/i), r = e.match(/<iframe\b[^>]*\bsrc=["']([^"']+)["']/i), i = t.find((e) => e.type.startsWith("image/"))?.url, a = t.find((e) => e.type.startsWith("video/"))?.url, o = r ? Et(r[1]) : a, s = o ? Dt(o) : void 0, c = n ? Et(n[1]) : i || (s ? `https://i.ytimg.com/vi/${s}/hqdefault.jpg` : void 0);
566
+ function Nt(e, t = []) {
567
+ let n = e.match(/<img\b[^>]*\bsrc=["']([^"']+)["']/i), r = e.match(/<iframe\b[^>]*\bsrc=["']([^"']+)["']/i), i = t.find((e) => e.type.startsWith("image/"))?.url, a = t.find((e) => e.type.startsWith("video/"))?.url, o = r ? At(r[1]) : a, s = o ? jt(o) : void 0, c = n ? At(n[1]) : i || (s ? `https://i.ytimg.com/vi/${s}/hqdefault.jpg` : void 0);
547
568
  return {
548
569
  summary: e.replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div|li|h[1-6]|blockquote)>/gi, "\n").replace(/<[^>]+>/g, " ").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/[^\S\n]+/g, " ").replace(/ *\n */g, "\n").replace(/\n{2,}/g, "\n").trim().slice(0, 160),
549
570
  ...c ? { previewImage: c } : {},
@@ -552,7 +573,7 @@ function kt(e, t = []) {
552
573
  }
553
574
  //#endregion
554
575
  //#region src/composables/useMemiBoardSettings.ts
555
- var At = [
576
+ var Pt = [
556
577
  {
557
578
  id: "free",
558
579
  label: "자유",
@@ -580,17 +601,17 @@ var At = [
580
601
  visibility: "public",
581
602
  order: 2
582
603
  }
583
- ], jt = At;
584
- function Mt(e) {
604
+ ], Ft = Pt;
605
+ function It(e) {
585
606
  return e === "hidden" ? "hidden" : "public";
586
607
  }
587
- function Nt(e, t, n) {
608
+ function Lt(e, t, n) {
588
609
  return {
589
610
  id: e,
590
611
  label: typeof t.label == "string" && t.label.trim() ? t.label.trim() : e,
591
612
  order: typeof t.order == "number" ? t.order : n,
592
613
  description: (typeof t.description == "string" ? t.description : "") || "",
593
- visibility: Mt(t.visibility),
614
+ visibility: It(t.visibility),
594
615
  listView: t.listView ?? "default",
595
616
  editorType: t.editorType ?? (t.listView === "image" ? "image" : "default"),
596
617
  writeRole: t.writeRole ?? "user",
@@ -598,8 +619,8 @@ function Nt(e, t, n) {
598
619
  allowedStaffUids: Array.isArray(t.allowedStaffUids) ? t.allowedStaffUids : []
599
620
  };
600
621
  }
601
- function Pt() {
602
- let t = () => h(), n = Q(), r = se(), { isSignedIn: i, isAdmin: a, isStaff: s, user: c } = ct(), l = A(() => W(e(n, t()), U("order", "asc"))), { data: u, pending: d } = ae(l, { ssrKey: S(t(), "boards") }), f = A(() => u.value.map((e, t) => Nt(e.id, e, t))), p = f, m = A(() => f.value.filter((e) => e.visibility !== "hidden")), _ = m;
622
+ function Rt() {
623
+ let t = () => h(), n = Q(), r = se(), { isSignedIn: i, isAdmin: a, isStaff: s, user: c } = ct(), l = A(() => W(e(n, t()), U("order", "asc"))), { data: u, pending: d } = ae(l, { ssrKey: S(t(), "boards") }), f = A(() => u.value.map((e, t) => Lt(e.id, e, t))), p = f, m = A(() => f.value.filter((e) => e.visibility !== "hidden")), _ = m;
603
624
  function v(e) {
604
625
  if (e) return f.value.find((t) => t.id === e)?.label ?? e;
605
626
  }
@@ -641,7 +662,7 @@ function Pt() {
641
662
  return {
642
663
  label: e.label.trim(),
643
664
  description: (e.description ?? "").trim(),
644
- visibility: Mt(e.visibility),
665
+ visibility: It(e.visibility),
645
666
  listView: e.listView ?? "default",
646
667
  editorType: e.editorType ?? (e.listView === "image" ? "image" : "default"),
647
668
  writeRole: e.writeRole ?? "user",
@@ -655,7 +676,7 @@ function Pt() {
655
676
  if (!i.value) throw Error("로그인이 필요합니다.");
656
677
  let a = e.id.trim(), o = e.label.trim();
657
678
  if (!a || !o) throw Error("보드 ID와 이름을 입력해 주세요.");
658
- let s = Mt(e.visibility), c = P({
679
+ let s = It(e.visibility), c = P({
659
680
  ...e,
660
681
  label: o,
661
682
  visibility: s
@@ -669,7 +690,7 @@ function Pt() {
669
690
  e.forEach((e, i) => {
670
691
  let s = e.id.trim(), c = e.label.trim();
671
692
  if (!s || !c) throw Error("보드 ID와 이름을 입력해 주세요.");
672
- let l = Mt(e.visibility), u = P({
693
+ let l = It(e.visibility), u = P({
673
694
  ...e,
674
695
  label: c,
675
696
  visibility: l
@@ -689,7 +710,7 @@ function Pt() {
689
710
  for (;;) {
690
711
  let e = await z(W(o(n, t()), Y("boardId", "==", a), V(25)));
691
712
  if (e.empty) break;
692
- for (let i of e.docs) await bt(n, _e(r), t(), i.id);
713
+ for (let i of e.docs) await wt(n, _e(r), t(), i.id);
693
714
  }
694
715
  await F(g(n, t(), e));
695
716
  }
@@ -742,25 +763,25 @@ function Pt() {
742
763
  saveCategories: ne,
743
764
  deleteBoard: R,
744
765
  deleteCategory: B,
745
- DEFAULT_BOARDS: At,
746
- DEFAULT_CATEGORIES: jt
766
+ DEFAULT_BOARDS: Pt,
767
+ DEFAULT_CATEGORIES: Ft
747
768
  };
748
769
  }
749
770
  //#endregion
750
771
  //#region src/composables/useMemiBoardPosts.ts
751
- var Ft = /* @__PURE__ */ new Map();
752
- function It(e) {
772
+ var zt = /* @__PURE__ */ new Map();
773
+ function Bt(e) {
753
774
  if (!e || typeof e != "object") return !1;
754
775
  let t = "code" in e ? String(e.code) : "";
755
776
  return t === "permission-denied" || t === "firestore/permission-denied";
756
777
  }
757
- function Lt(e) {
778
+ function Vt(e) {
758
779
  let t = N(e)?.trim();
759
780
  if (!t) throw Error("[memi-board] boardId 가 필요합니다.");
760
781
  return t;
761
782
  }
762
- function Rt(e) {
763
- let n = Q(), r = se(), { isBoardHidden: i, getBoard: s } = Pt(), c = () => h(), l = () => Lt(e), u = () => o(n, c()), d = (e) => t(n, c(), e), f = (e) => a(n, c(), e);
783
+ function Ht(e) {
784
+ let n = Q(), r = se(), { isBoardHidden: i, getBoard: s } = Rt(), c = () => h(), l = () => Vt(e), u = () => o(n, c()), d = (e) => t(n, c(), e), f = (e) => a(n, c(), e);
764
785
  function p() {
765
786
  return !i(l());
766
787
  }
@@ -768,7 +789,7 @@ function Rt(e) {
768
789
  return s(l())?.editorType === "image";
769
790
  }
770
791
  function g(e) {
771
- let t = m(), n = Ct(e.content), r = wt(e.content, e.attachments);
792
+ let t = m(), n = Dt(e.content), r = Ot(e.content, e.attachments);
772
793
  if (t) {
773
794
  if (!r) throw Error("사진을 올려 주세요.");
774
795
  return;
@@ -811,20 +832,20 @@ function Rt(e) {
811
832
  post: e
812
833
  } : { status: "not-found" };
813
834
  } catch (e) {
814
- return It(e) ? { status: "permission-denied" } : {
835
+ return Bt(e) ? { status: "permission-denied" } : {
815
836
  status: "error",
816
837
  message: e instanceof Error ? e.message : String(e)
817
838
  };
818
839
  }
819
840
  } catch (e) {
820
- return It(e) ? { status: "permission-denied" } : {
841
+ return Bt(e) ? { status: "permission-denied" } : {
821
842
  status: "error",
822
843
  message: e instanceof Error ? e.message : String(e)
823
844
  };
824
845
  }
825
846
  }
826
847
  async function S(e) {
827
- let t = e.trim(), n = Ft.get(`${l()}/${t}`);
848
+ let t = e.trim(), n = zt.get(`${l()}/${t}`);
828
849
  if (n) return {
829
850
  status: "ok",
830
851
  id: n
@@ -836,7 +857,7 @@ function Rt(e) {
836
857
  id: e.id
837
858
  } : { status: "not-found" };
838
859
  } catch (e) {
839
- return It(e) ? { status: "permission-denied" } : {
860
+ return Bt(e) ? { status: "permission-denied" } : {
840
861
  status: "error",
841
862
  message: e instanceof Error ? e.message : String(e)
842
863
  };
@@ -879,8 +900,8 @@ function Rt(e) {
879
900
  async function T(e) {
880
901
  g(e);
881
902
  let t = e.postId || _(), r = m(), i, a;
882
- r ? (i = t, a = St(e.content)) : (a = e.title.trim(), i = e.slug?.trim() || await C(a));
883
- let o = kt(e.content, e.attachments), s = p(), c = X(n);
903
+ r ? (i = t, a = Et(e.content)) : (a = e.title.trim(), i = e.slug?.trim() || await C(a));
904
+ let o = Nt(e.content, e.attachments), s = p(), c = X(n);
884
905
  return c.set(d(t), {
885
906
  boardId: l(),
886
907
  slug: i,
@@ -900,11 +921,11 @@ function Rt(e) {
900
921
  moderationModel: e.moderationModel ?? null,
901
922
  createdAt: G(),
902
923
  updatedAt: G()
903
- }), c.set(f(t), { content: e.content }), await c.commit(), Ft.set(`${l()}/${i}`, t), i;
924
+ }), c.set(f(t), { content: e.content }), await c.commit(), zt.set(`${l()}/${i}`, t), i;
904
925
  }
905
926
  async function E(e, t) {
906
927
  g(t);
907
- let n = m() ? St(t.content) : t.title.trim(), r = kt(t.content, t.attachments), i = p();
928
+ let n = m() ? Et(t.content) : t.title.trim(), r = Nt(t.content, t.attachments), i = p();
908
929
  await Promise.all([J(d(e), {
909
930
  title: n,
910
931
  ...r,
@@ -924,8 +945,8 @@ function Rt(e) {
924
945
  });
925
946
  }
926
947
  async function O(e) {
927
- await bt(n, _e(r), c(), e);
928
- for (let [t, n] of Ft) n === e && Ft.delete(t);
948
+ await wt(n, _e(r), c(), e);
949
+ for (let [t, n] of zt) n === e && zt.delete(t);
929
950
  }
930
951
  return {
931
952
  createPostId: _,
@@ -941,9 +962,9 @@ function Rt(e) {
941
962
  deletePost: O
942
963
  };
943
964
  }
944
- var zt = 10;
945
- function Bt(e, t = {}) {
946
- let n = Q(), { isAdmin: r, user: i, canManageBoard: a } = ct(), s = () => h(), c = t.pageSize ?? zt, l = A(() => i.value?.uid ?? ""), u = A(() => Lt(e)), d = () => o(n, s()), f = A(() => t.publicOnly === void 0 ? !(r.value || a(u.value)) : typeof t.publicOnly == "boolean" ? t.publicOnly : t.publicOnly.value), p = M([]), m = M([]), g = M([]), _ = M(!0), v = M(!0), y = M(!1), b = M(""), x = null, S = null, C, w;
965
+ var Ut = 10;
966
+ function Wt(e, t = {}) {
967
+ let n = Q(), { isAdmin: r, user: i, canManageBoard: a } = ct(), s = () => h(), c = t.pageSize ?? Ut, l = A(() => i.value?.uid ?? ""), u = A(() => Vt(e)), d = () => o(n, s()), f = A(() => t.publicOnly === void 0 ? !(r.value || a(u.value)) : typeof t.publicOnly == "boolean" ? t.publicOnly : t.publicOnly.value), p = M([]), m = M([]), g = M([]), _ = M(!0), v = M(!0), y = M(!1), b = M(""), x = null, S = null, C, w;
947
968
  function T(e) {
948
969
  return e.createdAt?.toMillis?.() ?? 0;
949
970
  }
@@ -1026,8 +1047,8 @@ function Bt(e, t = {}) {
1026
1047
  loadMore: ee
1027
1048
  };
1028
1049
  }
1029
- function Vt(e, n) {
1030
- let r = Q(), i = () => h(), o = A(() => Lt(e)), s = A(() => typeof n == "string" ? n : n.value), c = A(() => t(r, i(), s.value)), l = A(() => a(r, i(), s.value)), { data: u, pending: d } = oe(c), { data: f, pending: p } = oe(l);
1050
+ function Gt(e, n) {
1051
+ let r = Q(), i = () => h(), o = A(() => Vt(e)), s = A(() => typeof n == "string" ? n : n.value), c = A(() => t(r, i(), s.value)), l = A(() => a(r, i(), s.value)), { data: u, pending: d } = oe(c), { data: f, pending: p } = oe(l);
1031
1052
  return {
1032
1053
  post: A(() => !u.value || u.value.boardId !== o.value ? null : {
1033
1054
  ...u.value,
@@ -1039,9 +1060,9 @@ function Vt(e, n) {
1039
1060
  }
1040
1061
  //#endregion
1041
1062
  //#region src/composables/useMemiBoardUserPosts.ts
1042
- var Ht = 10;
1043
- function Ut(e, t = {}) {
1044
- let n = Q(), r = () => h(), i = () => o(n, r()), a = t.pageSize ?? Ht, s = A(() => N(e)?.trim() || ""), c = M([]), l = M([]), u = M(!0), d = M(!0), f = M(!1), p = M(""), m = null, g = null, _;
1063
+ var Kt = 10;
1064
+ function qt(e, t = {}) {
1065
+ let n = Q(), r = () => h(), i = () => o(n, r()), a = t.pageSize ?? Kt, s = A(() => N(e)?.trim() || ""), c = M([]), l = M([]), u = M(!0), d = M(!0), f = M(!1), p = M(""), m = null, g = null, _;
1045
1066
  function v(e) {
1046
1067
  return {
1047
1068
  id: e.id,
@@ -1107,9 +1128,9 @@ function Ut(e, t = {}) {
1107
1128
  }
1108
1129
  //#endregion
1109
1130
  //#region src/composables/useMemiBoardUserComments.ts
1110
- var Wt = 10;
1111
- function Gt(e, t = {}) {
1112
- let n = Q(), r = () => h(), i = () => E(n, r()), a = t.pageSize ?? Wt, o = A(() => N(e)?.trim() || ""), s = M([]), c = M([]), l = M(!0), u = M(!0), d = M(!1), f = M(""), p = null, m = null, g;
1131
+ var Jt = 10;
1132
+ function Yt(e, t = {}) {
1133
+ let n = Q(), r = () => h(), i = () => E(n, r()), a = t.pageSize ?? Jt, o = A(() => N(e)?.trim() || ""), s = M([]), c = M([]), l = M(!0), u = M(!0), d = M(!1), f = M(""), p = null, m = null, g;
1113
1134
  function _(e) {
1114
1135
  return {
1115
1136
  id: e.id,
@@ -1171,11 +1192,11 @@ function Gt(e, t = {}) {
1171
1192
  }
1172
1193
  //#endregion
1173
1194
  //#region src/composables/useMemiBoardCommentFeed.ts
1174
- var Kt = 10;
1175
- function qt(e = "latest", t = {}) {
1195
+ var Xt = 10;
1196
+ function Zt(e = "latest", t = {}) {
1176
1197
  let n = Q(), r = () => h(), i = () => E(n, r()), a = A(() => {
1177
1198
  let e = Math.floor(Number(N(t.pageSize)));
1178
- return Number.isFinite(e) && e > 0 ? e : Kt;
1199
+ return Number.isFinite(e) && e > 0 ? e : Xt;
1179
1200
  }), o = A(() => N(e) === "likes" ? "likes" : "latest"), s = M([]), c = M([]), l = M(!0), u = M(!0), d = M(!1), f = M(""), p = null, m = null, g;
1180
1201
  function _(e) {
1181
1202
  return {
@@ -1245,9 +1266,9 @@ function qt(e = "latest", t = {}) {
1245
1266
  }
1246
1267
  //#endregion
1247
1268
  //#region src/composables/useMemiBoardAuthorMemo.ts
1248
- var Jt = 100, Yt = /* @__PURE__ */ new Map();
1269
+ var Qt = 100, $t = /* @__PURE__ */ new Map();
1249
1270
  function $(e) {
1250
- let t = Yt.get(e);
1271
+ let t = $t.get(e);
1251
1272
  return t || (t = ee({
1252
1273
  text: "",
1253
1274
  sentiment: null,
@@ -1255,9 +1276,9 @@ function $(e) {
1255
1276
  pending: !1,
1256
1277
  saving: !1,
1257
1278
  error: ""
1258
- }), Yt.set(e, t)), t;
1279
+ }), $t.set(e, t)), t;
1259
1280
  }
1260
- function Xt(e) {
1281
+ function en(e) {
1261
1282
  let t = Q(), n = () => h(), { user: r } = ct(), i = A(() => N(e)), a = A(() => `${r.value?.uid ?? ""}:${i.value}`), o = A(() => {
1262
1283
  let e = r.value?.uid, a = i.value;
1263
1284
  return !e || !a ? null : f(t, n(), e, a);
@@ -1327,15 +1348,15 @@ function Xt(e) {
1327
1348
  }
1328
1349
  //#endregion
1329
1350
  //#region src/composables/useMemiBoardComments.ts
1330
- var Zt = 10, Qt = 5, $t = 1e3;
1331
- function en(e) {
1351
+ var tn = 10, nn = 5, rn = 1e3;
1352
+ function an(e) {
1332
1353
  let t = e.trim();
1333
1354
  if (!t) throw Error("댓글 내용을 입력해 주세요.");
1334
- if (t.length > 1e3) throw Error(`댓글은 ${$t.toLocaleString()}자까지 작성할 수 있습니다.`);
1355
+ if (t.length > 1e3) throw Error(`댓글은 ${rn.toLocaleString()}자까지 작성할 수 있습니다.`);
1335
1356
  return t;
1336
1357
  }
1337
- function tn(e, n, r = {}) {
1338
- let i = Q(), a = () => h(), { isBoardHidden: o } = Pt(), c = () => E(i, a()), l = A(() => N(e)), u = A(() => N(n)), d = () => !o(l.value), f = M([]), p = M([]), m = M(r.subscribe !== !1), g = M([]), _ = M(!1), v = M(r.subscribe !== !1), y = M(r.subscribe !== !1), b = null, x, S;
1358
+ function on(e, n, r = {}) {
1359
+ let i = Q(), a = () => h(), { isBoardHidden: o } = Rt(), c = () => E(i, a()), l = A(() => N(e)), u = A(() => N(n)), d = () => !o(l.value), f = M([]), p = M([]), m = M(r.subscribe !== !1), g = M([]), _ = M(!1), v = M(r.subscribe !== !1), y = M(r.subscribe !== !1), b = null, x, S;
1339
1360
  function C(e) {
1340
1361
  return e.createdAt?.toMillis?.() ?? 0;
1341
1362
  }
@@ -1389,11 +1410,11 @@ function tn(e, n, r = {}) {
1389
1410
  U(L(), "asc"),
1390
1411
  ...b ? [q(b)] : [],
1391
1412
  V(11)
1392
- ], t = await z(W(c(), ...e)), n = t.docs.slice(0, Zt), r = n.map((e) => ({
1413
+ ], t = await z(W(c(), ...e)), n = t.docs.slice(0, tn), r = n.map((e) => ({
1393
1414
  id: e.id,
1394
1415
  ...e.data()
1395
1416
  })), i = new Set(g.value.map((e) => e.id));
1396
- g.value.push(...r.filter((e) => !i.has(e.id))), b = n.at(-1) ?? b, t.size <= Zt && (v.value = !1, x = setTimeout(() => {
1417
+ g.value.push(...r.filter((e) => !i.has(e.id))), b = n.at(-1) ?? b, t.size <= tn && (v.value = !1, x = setTimeout(() => {
1397
1418
  x = void 0, T();
1398
1419
  }, 1e3));
1399
1420
  } finally {
@@ -1405,7 +1426,7 @@ function tn(e, n, r = {}) {
1405
1426
  clearTimeout(x), S?.();
1406
1427
  });
1407
1428
  async function O(e) {
1408
- let n = en(e.body), r = X(i), o = te(c());
1429
+ let n = an(e.body), r = X(i), o = te(c());
1409
1430
  r.set(o, {
1410
1431
  postId: u.value,
1411
1432
  boardId: l.value,
@@ -1428,7 +1449,7 @@ function tn(e, n, r = {}) {
1428
1449
  }), r.update(t(i, a(), u.value), { commentCount: B(1) }), await r.commit();
1429
1450
  }
1430
1451
  async function k(e) {
1431
- let n = en(e.body);
1452
+ let n = an(e.body);
1432
1453
  if (!e.parent.id) throw Error("답글 대상 댓글을 찾을 수 없습니다.");
1433
1454
  let r = X(i), o = te(c()), f = e.parent.parentId == null ? e.parent.id : e.parent.rootId;
1434
1455
  if (!f) throw Error("댓글 스레드를 찾을 수 없습니다.");
@@ -1457,12 +1478,12 @@ function tn(e, n, r = {}) {
1457
1478
  async function ee(e) {
1458
1479
  if (!e.id) return;
1459
1480
  if (e.parentId == null && (e.replyCount ?? 0) > 0) throw Error("답글이 있는 댓글은 현재 삭제할 수 없습니다.");
1460
- await yt(i, a(), e.id);
1481
+ await Ct(i, a(), e.id);
1461
1482
  let n = X(i);
1462
1483
  n.delete(s(i, a(), e.id)), e.parentId && e.rootId && n.update(s(i, a(), e.rootId), { replyCount: B(-1) }), n.update(t(i, a(), u.value), { commentCount: B(-1) }), await n.commit(), g.value = g.value.filter((t) => t.id !== e.id), p.value = p.value.filter((t) => t.id !== e.id), f.value = f.value.filter((t) => t.id !== e.id);
1463
1484
  }
1464
1485
  async function F(e, t) {
1465
- let n = en(t);
1486
+ let n = an(t);
1466
1487
  await J(s(i, a(), e), {
1467
1488
  body: n,
1468
1489
  updatedAt: G()
@@ -1488,7 +1509,7 @@ function tn(e, n, r = {}) {
1488
1509
  deleteComment: ee
1489
1510
  };
1490
1511
  }
1491
- function nn(e, t, n) {
1512
+ function sn(e, t, n) {
1492
1513
  let r = Q(), i = () => h(), a = () => E(r, i()), o = t.trim(), s = M([]), c = M(!1), l = M(!1), u = M(!0), d = null, f;
1493
1514
  function p(e) {
1494
1515
  return e.sort((e, t) => (e.createdAt?.toMillis?.() ?? 0) - (t.createdAt?.toMillis?.() ?? 0) || String(e.id).localeCompare(String(t.id)));
@@ -1517,11 +1538,11 @@ function nn(e, t, n) {
1517
1538
  U(L(), "asc"),
1518
1539
  ...d ? [q(d)] : [],
1519
1540
  V(6)
1520
- ], t = await z(W(a(), ...e)), r = new Set(s.value.map((e) => e.id)), i = t.docs.slice(0, Qt), c = i.map((e) => ({
1541
+ ], t = await z(W(a(), ...e)), r = new Set(s.value.map((e) => e.id)), i = t.docs.slice(0, nn), c = i.map((e) => ({
1521
1542
  id: e.id,
1522
1543
  ...e.data()
1523
1544
  })).filter((e) => !r.has(e.id));
1524
- s.value = p([...s.value, ...c]), d = i.at(-1) ?? d, l.value = !0, t.size <= Qt && (u.value = !1, m());
1545
+ s.value = p([...s.value, ...c]), d = i.at(-1) ?? d, l.value = !0, t.size <= nn && (u.value = !1, m());
1525
1546
  } finally {
1526
1547
  c.value = !1;
1527
1548
  }
@@ -1544,7 +1565,7 @@ function nn(e, t, n) {
1544
1565
  }
1545
1566
  //#endregion
1546
1567
  //#region src/composables/useMemiBoardLikes.ts
1547
- function rn(e, n) {
1568
+ function cn(e, n) {
1548
1569
  let r = () => h(), i = Q(), a = Z(), o = M(!1), s = M(!1), c;
1549
1570
  function l(e) {
1550
1571
  return k(i, r(), n, e);
@@ -1583,8 +1604,8 @@ function rn(e, n) {
1583
1604
  toggleLike: u
1584
1605
  };
1585
1606
  }
1586
- var an = Symbol.for("memi-board:comment-likes");
1587
- function on(e, t) {
1607
+ var ln = Symbol.for("memi-board:comment-likes");
1608
+ function un(e, t) {
1588
1609
  let n = () => h(), r = Q(), i = Z(), a = A(() => N(e)), o = A(() => N(t)), c = M(/* @__PURE__ */ new Set()), l = M(null), u;
1589
1610
  P([i, o], ([e, t]) => {
1590
1611
  u?.(), u = void 0, c.value = /* @__PURE__ */ new Set(), e && t && (u = H(W(O(r, n()), Y("uid", "==", e.uid), Y("postId", "==", t), Y("target", "==", "comment")), (e) => {
@@ -1637,7 +1658,7 @@ function on(e, t) {
1637
1658
  }
1638
1659
  //#endregion
1639
1660
  //#region src/composables/useMemiBoardReports.ts
1640
- var sn = 200, cn = [
1661
+ var dn = 200, fn = [
1641
1662
  {
1642
1663
  value: "spam",
1643
1664
  label: "스팸·광고"
@@ -1659,10 +1680,10 @@ var sn = 200, cn = [
1659
1680
  label: "기타"
1660
1681
  }
1661
1682
  ];
1662
- function ln(e) {
1663
- return cn.find((t) => t.value === e)?.label || e || "신고";
1683
+ function pn(e) {
1684
+ return fn.find((t) => t.value === e)?.label || e || "신고";
1664
1685
  }
1665
- function un(e, t) {
1686
+ function mn(e, t) {
1666
1687
  let n = () => h(), i = Q(), a = Z(), o = M(!1), s = M(!1), c;
1667
1688
  P(a, (e) => {
1668
1689
  if (c?.(), c = void 0, !e) {
@@ -1680,7 +1701,7 @@ function un(e, t) {
1680
1701
  if (!l) throw Error("로그인이 필요합니다.");
1681
1702
  if (s.value) return;
1682
1703
  if (c.authorUid && c.authorUid === l) throw Error("자신의 글은 신고할 수 없습니다.");
1683
- let u = cn.some((e) => e.value === c.reason) ? c.reason : null;
1704
+ let u = fn.some((e) => e.value === c.reason) ? c.reason : null;
1684
1705
  if (!u) throw Error("신고 사유를 선택해 주세요.");
1685
1706
  let d = (c.detail || "").trim();
1686
1707
  if (d.length > 200) throw Error("자세한 내용은 200자까지입니다.");
@@ -1709,9 +1730,9 @@ function un(e, t) {
1709
1730
  submitReport: l
1710
1731
  };
1711
1732
  }
1712
- var dn = 20;
1713
- function fn(e = {}) {
1714
- let t = () => h(), n = Q(), { canManageContent: a, canManageBoard: o } = ct(), s = e.pageSize ?? dn, c = A(() => N(e.boardId)?.trim() || ""), l = M([]), u = M(!0), d = M(!1), f = M(!1), p = M(""), m = null, g;
1733
+ var hn = 20;
1734
+ function gn(e = {}) {
1735
+ let t = () => h(), n = Q(), { canManageContent: a, canManageBoard: o } = ct(), s = e.pageSize ?? hn, c = A(() => N(e.boardId)?.trim() || ""), l = M([]), u = M(!0), d = M(!1), f = M(!1), p = M(""), m = null, g;
1715
1736
  function _(e) {
1716
1737
  return {
1717
1738
  id: e.id,
@@ -1765,7 +1786,7 @@ function fn(e = {}) {
1765
1786
  }
1766
1787
  //#endregion
1767
1788
  //#region src/composables/useMemiBoardViews.ts
1768
- function pn() {
1789
+ function _n() {
1769
1790
  let e = () => h(), n = Q();
1770
1791
  function r(t, n) {
1771
1792
  let { postsCollection: r } = e();
@@ -1805,7 +1826,7 @@ function pn() {
1805
1826
  }
1806
1827
  //#endregion
1807
1828
  //#region src/utils/moderation-prompt.ts
1808
- var mn = "당신은 게시판 콘텐츠를 심사하는 엄격한 모더레이터입니다.\n아래 텍스트에 욕설·비속어·성희롱·혐오·위협·스팸·도배성 광고가 있으면 반드시 거부(flagged=true)합니다.\n\nflagged=true 예:\n- 욕설/비속어: 씨발, 시발, 병신, 지랄, 좆, 개새끼, 존나, fuck, shit, bitch 등\n- 성적 모욕, 혐오 발언, 협박\n- 게시판 주제와 무관한 도배성 광고/스팸\n\nflagged=false:\n- 게시판 주제에 맞는 정상적인 글/댓글 (강한 의견이나 정당한 비판은 허용)\n\nJSON만 출력:\n{\"flagged\":boolean,\"category\":\"none\"|\"abuse\"|\"spam\"|\"adult\"|\"violence\"|\"other\",\"reason\":string}\n- flagged=true면 category를 고르고, reason은 한국어로 **무엇이 문제인지** 구체적으로 1문장\n (예: \"욕설(비속어)이 포함되어 게시할 수 없습니다.\", \"광고·스팸성 문구가 있어 게시할 수 없습니다.\")\n 욕설 단어 전체를 그대로 길게 인용하지 말고, 유형(욕설/혐오/스팸 등)을 분명히 밝힌다.\n- flagged=false면 category는 \"none\", reason은 \"\"", hn = {
1829
+ var vn = "당신은 게시판 콘텐츠를 심사하는 엄격한 모더레이터입니다.\n아래 텍스트에 욕설·비속어·성희롱·혐오·위협·스팸·도배성 광고가 있으면 반드시 거부(flagged=true)합니다.\n\nflagged=true 예:\n- 욕설/비속어: 씨발, 시발, 병신, 지랄, 좆, 개새끼, 존나, fuck, shit, bitch 등\n- 성적 모욕, 혐오 발언, 협박\n- 게시판 주제와 무관한 도배성 광고/스팸\n\nflagged=false:\n- 게시판 주제에 맞는 정상적인 글/댓글 (강한 의견이나 정당한 비판은 허용)\n\nJSON만 출력:\n{\"flagged\":boolean,\"category\":\"none\"|\"abuse\"|\"spam\"|\"adult\"|\"violence\"|\"other\",\"reason\":string}\n- flagged=true면 category를 고르고, reason은 한국어로 **무엇이 문제인지** 구체적으로 1문장\n (예: \"욕설(비속어)이 포함되어 게시할 수 없습니다.\", \"광고·스팸성 문구가 있어 게시할 수 없습니다.\")\n 욕설 단어 전체를 그대로 길게 인용하지 말고, 유형(욕설/혐오/스팸 등)을 분명히 밝힌다.\n- flagged=false면 category는 \"none\", reason은 \"\"", yn = {
1809
1830
  abuse: "욕설·비속어·모욕",
1810
1831
  spam: "스팸·광고",
1811
1832
  adult: "선정적·성인 내용",
@@ -1813,17 +1834,17 @@ var mn = "당신은 게시판 콘텐츠를 심사하는 엄격한 모더레이
1813
1834
  other: "부적절한 내용",
1814
1835
  none: ""
1815
1836
  };
1816
- function gn(e) {
1837
+ function bn(e) {
1817
1838
  if (e.via === "local" && e.localHit) {
1818
1839
  let t = e.localHit.trim();
1819
1840
  return t.length > 0 && t.length <= 12 ? `「${t}」 같은 표현은 사용할 수 없습니다. 다른 말로 바꿔 주세요.` : "욕설·비속어가 포함되어 게시할 수 없습니다. 표현을 바꿔 주세요.";
1820
1841
  }
1821
1842
  let t = (e.reason || "").trim();
1822
1843
  if (t) return t;
1823
- let n = e.category && e.category !== "none" ? hn[e.category] || e.category : "";
1844
+ let n = e.category && e.category !== "none" ? yn[e.category] || e.category : "";
1824
1845
  return n ? `${n}이(가) 포함되어 게시할 수 없습니다. 내용을 수정해 주세요.` : "게시할 수 없는 내용이 포함되어 있습니다. 내용을 수정해 주세요.";
1825
1846
  }
1826
- var _n = [
1847
+ var xn = [
1827
1848
  "씨발",
1828
1849
  "시발",
1829
1850
  "시이발",
@@ -1849,10 +1870,10 @@ var _n = [
1849
1870
  "bitch",
1850
1871
  "asshole"
1851
1872
  ];
1852
- function vn(e) {
1873
+ function Sn(e) {
1853
1874
  return new RegExp(e.join("|"), "i");
1854
1875
  }
1855
- var yn = /* @__PURE__ */ new Set([
1876
+ var Cn = /* @__PURE__ */ new Set([
1856
1877
  "none",
1857
1878
  "abuse",
1858
1879
  "spam",
@@ -1860,7 +1881,7 @@ var yn = /* @__PURE__ */ new Set([
1860
1881
  "violence",
1861
1882
  "other"
1862
1883
  ]);
1863
- function bn(e) {
1884
+ function wn(e) {
1864
1885
  let t = e.trim();
1865
1886
  if (!t) return null;
1866
1887
  let n;
@@ -1878,7 +1899,7 @@ function bn(e) {
1878
1899
  if (typeof n != "object" || !n) return null;
1879
1900
  let r = n;
1880
1901
  if (typeof r.flagged != "boolean") return null;
1881
- let i = typeof r.category == "string" && yn.has(r.category) ? r.category : r.flagged ? "other" : "none", a = typeof r.reason == "string" ? r.reason : "";
1902
+ let i = typeof r.category == "string" && Cn.has(r.category) ? r.category : r.flagged ? "other" : "none", a = typeof r.reason == "string" ? r.reason : "";
1882
1903
  return {
1883
1904
  flagged: r.flagged,
1884
1905
  category: i,
@@ -1887,20 +1908,20 @@ function bn(e) {
1887
1908
  }
1888
1909
  //#endregion
1889
1910
  //#region src/composables/useMemiBoardModeration.ts
1890
- var xn = {
1911
+ var Tn = {
1891
1912
  flagged: !1,
1892
1913
  category: "none",
1893
1914
  reason: "",
1894
1915
  via: "empty"
1895
1916
  };
1896
- function Sn() {
1897
- let e = c().moderation ?? {}, t = se(), { isWriteRestricted: n, restrictedMessage: r, recordContentModerationBlock: i } = ct(), a = vn([..._n, ...e.localBlocklist ?? []]);
1917
+ function En() {
1918
+ let e = c().moderation ?? {}, t = se(), { isWriteRestricted: n, restrictedMessage: r, recordContentModerationBlock: i } = ct(), a = Sn([...xn, ...e.localBlocklist ?? []]);
1898
1919
  function o(e) {
1899
1920
  let t = e.match(a);
1900
1921
  return t ? {
1901
1922
  flagged: !0,
1902
1923
  category: "abuse",
1903
- reason: gn({
1924
+ reason: bn({
1904
1925
  via: "local",
1905
1926
  localHit: t[0] || "",
1906
1927
  category: "abuse"
@@ -1915,7 +1936,7 @@ function Sn() {
1915
1936
  });
1916
1937
  return Ce(i, {
1917
1938
  model: n,
1918
- systemInstruction: mn,
1939
+ systemInstruction: vn,
1919
1940
  generationConfig: {
1920
1941
  temperature: 0,
1921
1942
  maxOutputTokens: 256,
@@ -1944,7 +1965,7 @@ function Sn() {
1944
1965
  };
1945
1966
  }
1946
1967
  function u(e, t = "") {
1947
- let n = gn({
1968
+ let n = bn({
1948
1969
  reason: e.reason,
1949
1970
  category: e.category,
1950
1971
  via: e.via
@@ -1972,26 +1993,26 @@ function Sn() {
1972
1993
  };
1973
1994
  let a = t.trim();
1974
1995
  if (!a) return {
1975
- ...xn,
1996
+ ...Tn,
1976
1997
  via: "empty"
1977
1998
  };
1978
1999
  if (i?.skipFilter) return {
1979
- ...xn,
2000
+ ...Tn,
1980
2001
  via: "admin-override"
1981
2002
  };
1982
2003
  let c = o(a);
1983
2004
  if (c) return d(c);
1984
2005
  if (e.enabled === !1) return {
1985
- ...xn,
2006
+ ...Tn,
1986
2007
  via: "disabled"
1987
2008
  };
1988
2009
  try {
1989
- let e = bn((await s().generateContent(`심사할 텍스트:\n"""${a.slice(0, 4e3)}"""`)).response.text());
2010
+ let e = wn((await s().generateContent(`심사할 텍스트:\n"""${a.slice(0, 4e3)}"""`)).response.text());
1990
2011
  if (!e) return l();
1991
2012
  let t = {
1992
2013
  flagged: e.flagged,
1993
2014
  category: e.category,
1994
- reason: gn({
2015
+ reason: bn({
1995
2016
  reason: e.reason,
1996
2017
  category: e.category,
1997
2018
  via: "ai"
@@ -2011,14 +2032,14 @@ function Sn() {
2011
2032
  via: "restricted"
2012
2033
  };
2013
2034
  if (e.enabled === !1 || !e.moderateImages) return {
2014
- ...xn,
2035
+ ...Tn,
2015
2036
  via: "disabled"
2016
2037
  };
2017
2038
  try {
2018
2039
  let e = await new Promise((e, n) => {
2019
2040
  let r = new FileReader();
2020
2041
  r.onload = () => e(r.result.split(",")[1] ?? ""), r.onerror = n, r.readAsDataURL(t);
2021
- }), n = bn((await s().generateContent([{ inlineData: {
2042
+ }), n = wn((await s().generateContent([{ inlineData: {
2022
2043
  mimeType: t.type || "image/jpeg",
2023
2044
  data: e
2024
2045
  } }, "이 이미지를 심사해 주세요."])).response.text());
@@ -2026,7 +2047,7 @@ function Sn() {
2026
2047
  let r = {
2027
2048
  flagged: n.flagged,
2028
2049
  category: n.category,
2029
- reason: gn({
2050
+ reason: bn({
2030
2051
  reason: n.reason,
2031
2052
  category: n.category,
2032
2053
  via: "ai"
@@ -2045,7 +2066,7 @@ function Sn() {
2045
2066
  }
2046
2067
  //#endregion
2047
2068
  //#region src/composables/useMemiBoardUsers.ts
2048
- var Cn = [
2069
+ var Dn = [
2049
2070
  {
2050
2071
  value: "admin",
2051
2072
  label: "관리자",
@@ -2062,10 +2083,10 @@ var Cn = [
2062
2083
  description: "글과 댓글을 작성하고 본인이 작성한 콘텐츠만 수정·삭제할 수 있습니다."
2063
2084
  }
2064
2085
  ];
2065
- function wn(e = {}) {
2086
+ function On(e = {}) {
2066
2087
  let t = () => h(), n = Q(), r = A(() => N(e.enabled) ?? !0 ? p(n, t()) : null), i = ae(r, { ssrKey: S(t(), "users-management") });
2067
2088
  async function a(e, r) {
2068
- if (!Cn.some((e) => e.value === r)) throw Error("지원하지 않는 역할입니다.");
2089
+ if (!Dn.some((e) => e.value === r)) throw Error("지원하지 않는 역할입니다.");
2069
2090
  await J(y(n, t(), e), {
2070
2091
  role: r,
2071
2092
  updatedAt: G()
@@ -2079,7 +2100,7 @@ function wn(e = {}) {
2079
2100
  }
2080
2101
  //#endregion
2081
2102
  //#region src/composables/useMemiBoardUserProfile.ts
2082
- function Tn(e) {
2103
+ function kn(e) {
2083
2104
  let t = Q(), n = () => h(), r = A(() => N(e)), i = A(() => {
2084
2105
  let e = r.value;
2085
2106
  return e ? y(t, n(), e) : null;
@@ -2091,7 +2112,7 @@ function Tn(e) {
2091
2112
  }
2092
2113
  //#endregion
2093
2114
  //#region src/utils/section.ts
2094
- var En = [
2115
+ var An = [
2095
2116
  3,
2096
2117
  4,
2097
2118
  5,
@@ -2100,7 +2121,7 @@ var En = [
2100
2121
  8,
2101
2122
  9,
2102
2123
  12
2103
- ], Dn = [
2124
+ ], jn = [
2104
2125
  {
2105
2126
  value: "list",
2106
2127
  label: "게시목록"
@@ -2113,24 +2134,24 @@ var En = [
2113
2134
  value: "comments",
2114
2135
  label: "댓글모음"
2115
2136
  }
2116
- ], On = [{
2137
+ ], Mn = [{
2117
2138
  value: "latest",
2118
2139
  label: "최신순"
2119
2140
  }, {
2120
2141
  value: "likes",
2121
2142
  label: "좋아요순"
2122
2143
  }];
2123
- function kn(e) {
2144
+ function Nn(e) {
2124
2145
  return e === "list" ? 5 : 4;
2125
2146
  }
2126
- function An(e, t) {
2147
+ function Pn(e, t) {
2127
2148
  let n = Math.floor(Number(t));
2128
- return Number.isFinite(n) ? Math.min(e === "list" ? 20 : 10, Math.max(1, n)) : kn(e);
2149
+ return Number.isFinite(n) ? Math.min(e === "list" ? 20 : 10, Math.max(1, n)) : Nn(e);
2129
2150
  }
2130
- function jn(e) {
2151
+ function Fn(e) {
2131
2152
  return e === 12 ? null : 12 - e;
2132
2153
  }
2133
- function Mn(e) {
2154
+ function In(e) {
2134
2155
  return {
2135
2156
  3: "col-span-12 md:col-span-3",
2136
2157
  4: "col-span-12 md:col-span-4",
@@ -2142,36 +2163,36 @@ function Mn(e) {
2142
2163
  12: "col-span-12"
2143
2164
  }[e];
2144
2165
  }
2145
- function Nn(e) {
2166
+ function Ln(e) {
2146
2167
  return e === "sm" ? "min-h-40" : e === "lg" ? "min-h-80" : "min-h-56";
2147
2168
  }
2148
- function Pn(e) {
2169
+ function Rn(e) {
2149
2170
  let t = e.boardId || e.category || "free";
2150
2171
  return e.slug ? `/board/${t}/${e.slug}` : `/board/${t}`;
2151
2172
  }
2152
- function Fn(e) {
2173
+ function zn(e) {
2153
2174
  return e.kind === "comments" ? e.sort === "likes" ? "/boardComments?sort=likes" : "/boardComments" : e.kind === "list" && e.boardId ? `/board/${e.boardId}` : "/board";
2154
2175
  }
2155
- function In(e) {
2176
+ function Bn(e) {
2156
2177
  if (e.boardId && e.postId) return `/board/${e.boardId}/post/${e.postId}`;
2157
2178
  }
2158
- function Ln(e) {
2179
+ function Vn(e) {
2159
2180
  return e.previewImage || e.attachments?.find((e) => e.type.startsWith("image/"))?.url;
2160
2181
  }
2161
- function Rn(e) {
2182
+ function Hn(e) {
2162
2183
  return e.title?.trim() || e.summary || "게시물";
2163
2184
  }
2164
- function zn(e) {
2185
+ function Un(e) {
2165
2186
  return e === "image" || e === "video" ? "media" : "list";
2166
2187
  }
2167
- function Bn(e) {
2168
- return zn(e) === "media" ? "미디어" : "목록";
2188
+ function Wn(e) {
2189
+ return Un(e) === "media" ? "미디어" : "목록";
2169
2190
  }
2170
- function Vn(e, t) {
2191
+ function Gn(e, t) {
2171
2192
  return e ? t(e)?.listView ?? "default" : "default";
2172
2193
  }
2173
- function Hn(e, t) {
2174
- let n = e.map((e) => Vn(e.boardId, t));
2194
+ function Kn(e, t) {
2195
+ let n = e.map((e) => Gn(e.boardId, t));
2175
2196
  if (!n.length) return "default";
2176
2197
  if (n.every((e) => e === n[0])) return n[0];
2177
2198
  let r = n.filter((e) => e === "image").length, i = n.filter((e) => e === "video").length;
@@ -2179,27 +2200,27 @@ function Hn(e, t) {
2179
2200
  }
2180
2201
  //#endregion
2181
2202
  //#region src/composables/useMemiBoardSections.ts
2182
- var Un = [];
2183
- function Wn(e) {
2203
+ var qn = [];
2204
+ function Jn(e) {
2184
2205
  let t = Number(e.cols);
2185
- if (En.includes(t)) return t;
2206
+ if (An.includes(t)) return t;
2186
2207
  let n = e.width;
2187
2208
  return n === "xs" ? 3 : n === "sm" ? 4 : n === "lg" || Number(e.span) === 2 ? 12 : 6;
2188
2209
  }
2189
- function Gn(e) {
2210
+ function Yn(e) {
2190
2211
  let t = e.height ?? e.size;
2191
2212
  return t === "sm" || t === "lg" ? t : "md";
2192
2213
  }
2193
- function Kn(e) {
2214
+ function Xn(e) {
2194
2215
  return e.kind === "post" || e.kind === "comments" ? e.kind : "list";
2195
2216
  }
2196
- function qn(e) {
2217
+ function Zn(e) {
2197
2218
  return e.sort === "likes" ? "likes" : "latest";
2198
2219
  }
2199
- function Jn(e) {
2220
+ function Qn(e) {
2200
2221
  return (typeof e.boardId == "string" ? e.boardId.trim() : "") || null;
2201
2222
  }
2202
- function Yn(e, t) {
2223
+ function $n(e, t) {
2203
2224
  let n = Array.isArray(e.postIds) ? e.postIds : [], r = [];
2204
2225
  for (let e of n) {
2205
2226
  let n = String(e || "").trim();
@@ -2207,40 +2228,40 @@ function Yn(e, t) {
2207
2228
  }
2208
2229
  return r;
2209
2230
  }
2210
- function Xn(e, t) {
2211
- let n = Kn(e), r = An(n, e.count);
2231
+ function er(e, t) {
2232
+ let n = Xn(e), r = Pn(n, e.count);
2212
2233
  return {
2213
2234
  id: String(e.id || `box-${t + 1}`),
2214
2235
  title: String(e.title || `섹션 ${t + 1}`),
2215
2236
  showTitle: e.showTitle !== !1,
2216
2237
  kind: n,
2217
- boardId: Jn(e),
2238
+ boardId: Qn(e),
2218
2239
  count: r,
2219
- postIds: Yn(e, r),
2220
- sort: qn(e),
2221
- cols: Wn(e),
2222
- height: Gn(e),
2240
+ postIds: $n(e, r),
2241
+ sort: Zn(e),
2242
+ cols: Jn(e),
2243
+ height: Yn(e),
2223
2244
  order: t
2224
2245
  };
2225
2246
  }
2226
- function Zn() {
2227
- let e = Q(), t = te(e, "settings", "homeLayout"), { data: n, pending: r } = oe(t), i = A(() => (Array.isArray(n.value?.blocks) ? n.value.blocks : Un).map((e, t) => Xn(e, t)));
2247
+ function tr() {
2248
+ let e = Q(), t = te(e, "settings", "homeLayout"), { data: n, pending: r } = oe(t), i = A(() => (Array.isArray(n.value?.blocks) ? n.value.blocks : qn).map((e, t) => er(e, t)));
2228
2249
  async function a(e) {
2229
2250
  await K(t, {
2230
2251
  columns: 12,
2231
2252
  blocks: e.map((e, t) => {
2232
- let n = e, r = Kn(n), i = An(r, e.count);
2253
+ let n = e, r = Xn(n), i = Pn(r, e.count);
2233
2254
  return {
2234
2255
  id: e.id,
2235
2256
  title: e.title.trim() || `섹션 ${t + 1}`,
2236
2257
  showTitle: e.showTitle !== !1,
2237
2258
  kind: r,
2238
- boardId: Jn(n),
2259
+ boardId: Qn(n),
2239
2260
  count: i,
2240
- postIds: Yn(n, i),
2241
- sort: qn(n),
2242
- cols: Wn(n),
2243
- height: Gn(n),
2261
+ postIds: $n(n, i),
2262
+ sort: Zn(n),
2263
+ cols: Jn(n),
2264
+ height: Yn(n),
2244
2265
  order: t
2245
2266
  };
2246
2267
  }),
@@ -2259,7 +2280,7 @@ function Zn() {
2259
2280
  }
2260
2281
  //#endregion
2261
2282
  //#region src/composables/useMemiBoardMiniPosts.ts
2262
- function Qn(e, t) {
2283
+ function nr(e, t) {
2263
2284
  let n = Q(), r = () => h(), i = N(e)?.trim() || "all", a = A(() => {
2264
2285
  let i = Math.max(1, Math.floor(Number(N(t)) || 5)), a = N(e)?.trim() || "", s = [Y("isPublished", "==", !0), Y("listed", "==", !0)];
2265
2286
  return a && s.unshift(Y("boardId", "==", a)), W(o(n, r()), ...s, U("createdAt", "desc"), V(i));
@@ -2270,7 +2291,7 @@ function Qn(e, t) {
2270
2291
  error: l
2271
2292
  };
2272
2293
  }
2273
- function $n(e) {
2294
+ function rr(e) {
2274
2295
  let t = Q(), n = () => h(), r = A(() => [...new Set(N(e).map((e) => e.trim()).filter(Boolean))].slice(0, 10)), i = r.value.join(",") || "none", a = A(() => r.value.length ? W(o(t, n()), Y(L(), "in", r.value)) : null), { data: s, pending: c, error: l } = ae(a, { ssrKey: S(n(), `mini-picked/${i}`) });
2275
2296
  return {
2276
2297
  posts: A(() => {
@@ -2287,7 +2308,12 @@ function $n(e) {
2287
2308
  }
2288
2309
  //#endregion
2289
2310
  //#region src/data/versionHistory.ts
2290
- var er = [
2311
+ var ir = [
2312
+ {
2313
+ version: "0.44.1",
2314
+ date: "2026-10-01",
2315
+ highlights: ["Mac Safari에서 한글을 입력하고 바로 등록 버튼을 누를 때 두 번 눌러야 하던 문제를 고쳤어요"]
2316
+ },
2291
2317
  {
2292
2318
  version: "0.44.0",
2293
2319
  date: "2026-10-01",
@@ -2562,7 +2588,7 @@ var er = [
2562
2588
  highlights: ["글쓰기·댓글·첨부·로그인 권한으로 게시판을 바로 시작할 수 있어요", "부적절한 글·댓글은 AI 검열로 막을 수 있어요"],
2563
2589
  note: "실제 보안은 호스트 Firebase 규칙 등록이 필요합니다."
2564
2590
  }
2565
- ], tr = /* @__PURE__ */ Ae(((e, t) => {
2591
+ ], ar = /* @__PURE__ */ Ae(((e, t) => {
2566
2592
  (function(n, r) {
2567
2593
  typeof e == "object" && t !== void 0 ? t.exports = r() : typeof define == "function" && define.amd ? define(r) : (n = typeof globalThis < "u" ? globalThis : n || self).dayjs = r();
2568
2594
  })(e, (function() {
@@ -2856,7 +2882,7 @@ var er = [
2856
2882
  return w(1e3 * e);
2857
2883
  }, w.en = b[y], w.Ls = b, w.p = {}, w;
2858
2884
  }));
2859
- })), nr = /* @__PURE__ */ Ae(((e, t) => {
2885
+ })), or = /* @__PURE__ */ Ae(((e, t) => {
2860
2886
  (function(n, r) {
2861
2887
  typeof e == "object" && t !== void 0 ? t.exports = r() : typeof define == "function" && define.amd ? define(r) : (n = typeof globalThis < "u" ? globalThis : n || self).dayjs_plugin_relativeTime = r();
2862
2888
  })(e, (function() {
@@ -2960,9 +2986,9 @@ var er = [
2960
2986
  };
2961
2987
  };
2962
2988
  }));
2963
- })), rr = /* @__PURE__ */ Ae(((e, t) => {
2989
+ })), sr = /* @__PURE__ */ Ae(((e, t) => {
2964
2990
  (function(n, r) {
2965
- typeof e == "object" && t !== void 0 ? t.exports = r(tr()) : typeof define == "function" && define.amd ? define(["dayjs"], r) : (n = typeof globalThis < "u" ? globalThis : n || self).dayjs_locale_ko = r(n.dayjs);
2991
+ typeof e == "object" && t !== void 0 ? t.exports = r(ar()) : typeof define == "function" && define.amd ? define(["dayjs"], r) : (n = typeof globalThis < "u" ? globalThis : n || self).dayjs_locale_ko = r(n.dayjs);
2966
2992
  })(e, (function(e) {
2967
2993
  function t(e) {
2968
2994
  return e && typeof e == "object" && "default" in e ? e : { default: e };
@@ -3010,24 +3036,24 @@ var er = [
3010
3036
  };
3011
3037
  return n.default.locale(r, null, !0), r;
3012
3038
  }));
3013
- })), ir = /* @__PURE__ */ Me(tr(), 1), ar = /* @__PURE__ */ Me(nr(), 1);
3014
- rr(), ir.default.extend(ar.default), ir.default.locale("ko");
3015
- function or(e) {
3039
+ })), cr = /* @__PURE__ */ Me(ar(), 1), lr = /* @__PURE__ */ Me(or(), 1);
3040
+ sr(), cr.default.extend(lr.default), cr.default.locale("ko");
3041
+ function ur(e) {
3016
3042
  return e?.toDate ? e.toDate().toLocaleDateString("ko-KR") : "";
3017
3043
  }
3018
- function sr(e, t = Date.now()) {
3019
- return e?.toDate ? (0, ir.default)(e.toDate()).from((0, ir.default)(t)) : "방금 전";
3044
+ function dr(e, t = Date.now()) {
3045
+ return e?.toDate ? (0, cr.default)(e.toDate()).from((0, cr.default)(t)) : "방금 전";
3020
3046
  }
3021
- function cr(e) {
3022
- return e?.toDate ? (0, ir.default)(e.toDate()).format("YYYY년 M월 D일 HH:mm:ss") : "시간 확인 중";
3047
+ function fr(e) {
3048
+ return e?.toDate ? (0, cr.default)(e.toDate()).format("YYYY년 M월 D일 HH:mm:ss") : "시간 확인 중";
3023
3049
  }
3024
- function lr(e, t) {
3025
- let n = cr(e), r = e?.toMillis?.(), i = t?.toMillis?.();
3026
- return i == null || r == null || r === i ? [n] : [`생성시간: ${n}`, `수정시간: ${cr(t)}`];
3050
+ function pr(e, t) {
3051
+ let n = fr(e), r = e?.toMillis?.(), i = t?.toMillis?.();
3052
+ return i == null || r == null || r === i ? [n] : [`생성시간: ${n}`, `수정시간: ${fr(t)}`];
3027
3053
  }
3028
3054
  //#endregion
3029
3055
  //#region src/composables/useMemiBoardWritingAssistant.ts
3030
- var ur = 10, dr = 864e5, fr = 200, pr = {
3056
+ var mr = 10, hr = 864e5, gr = 200, _r = {
3031
3057
  proofread: "맞춤법, 띄어쓰기, 문법 오류만 고쳐라. 의미와 말투는 바꾸지 마라.",
3032
3058
  polish: "뜻과 작성자의 말투를 유지하면서 더 자연스럽고 읽기 좋은 문장으로 다듬어라.",
3033
3059
  continue: "앞의 맥락과 말투에 맞는 내용을 과장 없이 한두 문단 이어서 작성하라.",
@@ -3036,19 +3062,19 @@ var ur = 10, dr = 864e5, fr = 200, pr = {
3036
3062
  "translate-ko": "자연스러운 한국어로 번역하라. 고유명사와 기술 용어는 정확히 유지하라.",
3037
3063
  title: "본문을 대표하는 간결한 한국어 제목 하나를 만들어라. 따옴표나 설명 없이 제목만 출력하라."
3038
3064
  };
3039
- function mr(e) {
3040
- if (e.action !== "custom") return pr[e.action];
3041
- let t = e.customInstruction?.trim().slice(0, fr);
3065
+ function vr(e) {
3066
+ if (e.action !== "custom") return _r[e.action];
3067
+ let t = e.customInstruction?.trim().slice(0, gr);
3042
3068
  if (!t) throw Error("어떻게 바꿀지 지시문을 입력해 주세요.");
3043
3069
  return `뜻은 유지하면서 다음 스타일 지시를 반영해 다시 써라: ${t}`;
3044
3070
  }
3045
- function hr(e) {
3071
+ function yr(e) {
3046
3072
  return e.trim().replace(/^```(?:html|text)?\s*/i, "").replace(/\s*```$/, "").trim();
3047
3073
  }
3048
- function gr(e) {
3074
+ function br(e) {
3049
3075
  return !e || typeof e != "object" ? null : "toMillis" in e && typeof e.toMillis == "function" ? e.toMillis() : null;
3050
3076
  }
3051
- function _r() {
3077
+ function xr() {
3052
3078
  let e = se(), t = Q(), n = Z(), r = c();
3053
3079
  async function i() {
3054
3080
  let e = n.value?.uid;
@@ -3056,9 +3082,9 @@ function _r() {
3056
3082
  await ie(t, async (n) => {
3057
3083
  let r = y(t, h(), e), i = await n.get(r);
3058
3084
  if (!i.exists()) throw Error("사용자 정보를 확인한 뒤 다시 시도해 주세요.");
3059
- let a = i.data(), o = gr(a.aiWritingWindowAt), s = Math.max(0, Math.floor(Number(a.aiWritingCount) || 0)), c = Date.now(), l = o != null && c - o < dr;
3085
+ let a = i.data(), o = br(a.aiWritingWindowAt), s = Math.max(0, Math.floor(Number(a.aiWritingCount) || 0)), c = Date.now(), l = o != null && c - o < hr;
3060
3086
  if (l && s >= 10) {
3061
- let e = o + dr, t = Math.max(1, Math.ceil((e - c) / 36e5));
3087
+ let e = o + hr, t = Math.max(1, Math.ceil((e - c) / 36e5));
3062
3088
  throw Error(`AI 글쓰기 도우미는 하루 10회까지 사용할 수 있습니다. 약 ${t}시간 후 다시 이용해 주세요.`);
3063
3089
  }
3064
3090
  n.update(r, {
@@ -3069,7 +3095,7 @@ function _r() {
3069
3095
  });
3070
3096
  }
3071
3097
  async function a(t) {
3072
- let n = mr(t);
3098
+ let n = vr(t);
3073
3099
  if (!t.content.trim()) throw Error("AI로 다듬을 내용을 먼저 입력해 주세요.");
3074
3100
  await i();
3075
3101
  let a = r.moderation ?? {}, o = Se(e, {
@@ -3090,7 +3116,7 @@ function _r() {
3090
3116
  `작업: ${n}`,
3091
3117
  t.title ? `현재 제목: ${t.title}` : "",
3092
3118
  `본문:\n${c.slice(0, 12e3)}`
3093
- ].filter(Boolean).join("\n\n"), u = hr((await s.generateContent(l)).response.text());
3119
+ ].filter(Boolean).join("\n\n"), u = yr((await s.generateContent(l)).response.text());
3094
3120
  if (!u) throw Error("AI가 결과를 만들지 못했습니다. 다시 시도해 주세요.");
3095
3121
  return u;
3096
3122
  }
@@ -3098,14 +3124,14 @@ function _r() {
3098
3124
  }
3099
3125
  //#endregion
3100
3126
  //#region src/utils/renderMarkdown.ts
3101
- function vr(e) {
3127
+ function Sr(e) {
3102
3128
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
3103
3129
  }
3104
- function yr(e) {
3130
+ function Cr(e) {
3105
3131
  let t = e;
3106
3132
  return t = t.replace(/`([^`]+)`/g, "<code>$1</code>"), t = t.replace(/!\[([^\]]*)\]\((https?:\/\/[^)\s]+)\)/g, "<img src=\"$2\" alt=\"$1\" class=\"max-w-full h-auto rounded-lg my-3\" loading=\"lazy\" />"), t = t.replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g, "<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-primary underline\">$1</a>"), t = t.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>"), t = t.replace(/\*([^*]+)\*/g, "<em>$1</em>"), t = t.replace(/~~([^~]+)~~/g, "<del>$1</del>"), t;
3107
3133
  }
3108
- function br(e) {
3134
+ function wr(e) {
3109
3135
  if (!e?.trim()) return "";
3110
3136
  let t = e.replace(/\r\n/g, "\n").split("\n"), n = [], r = 0, i = !1, a = [], o = null, s = [];
3111
3137
  function c() {
@@ -3114,7 +3140,7 @@ function br(e) {
3114
3140
  return;
3115
3141
  }
3116
3142
  let e = o;
3117
- n.push(`<${e}>${s.map((e) => `<li>${yr(e)}</li>`).join("")}</${e}>`), o = null, s = [];
3143
+ n.push(`<${e}>${s.map((e) => `<li>${Cr(e)}</li>`).join("")}</${e}>`), o = null, s = [];
3118
3144
  }
3119
3145
  for (; r < t.length;) {
3120
3146
  let e = t[r] ?? "", l = e.match(/^```(\w*)\s*$/);
@@ -3123,7 +3149,7 @@ function br(e) {
3123
3149
  continue;
3124
3150
  }
3125
3151
  if (i) {
3126
- a.push(vr(e)), r++;
3152
+ a.push(Sr(e)), r++;
3127
3153
  continue;
3128
3154
  }
3129
3155
  if (/^(-{3,}|\*{3,}|_{3,})\s*$/.test(e)) {
@@ -3134,24 +3160,24 @@ function br(e) {
3134
3160
  if (u) {
3135
3161
  c();
3136
3162
  let e = u[1].length;
3137
- n.push(`<h${e} class="font-semibold mt-4 mb-2">${yr(vr(u[2]))}</h${e}>`), r++;
3163
+ n.push(`<h${e} class="font-semibold mt-4 mb-2">${Cr(Sr(u[2]))}</h${e}>`), r++;
3138
3164
  continue;
3139
3165
  }
3140
3166
  if (e.startsWith("> ")) {
3141
3167
  c();
3142
3168
  let e = [];
3143
- for (; r < t.length && (t[r] ?? "").startsWith("> ");) e.push(vr((t[r] ?? "").slice(2))), r++;
3144
- n.push(`<blockquote class="border-l-4 border-default pl-3 text-muted my-3">${yr(e.join("<br />"))}</blockquote>`);
3169
+ for (; r < t.length && (t[r] ?? "").startsWith("> ");) e.push(Sr((t[r] ?? "").slice(2))), r++;
3170
+ n.push(`<blockquote class="border-l-4 border-default pl-3 text-muted my-3">${Cr(e.join("<br />"))}</blockquote>`);
3145
3171
  continue;
3146
3172
  }
3147
3173
  let d = e.match(/^[-*+]\s+(.+)$/);
3148
3174
  if (d) {
3149
- o && o !== "ul" && c(), o = "ul", s.push(vr(d[1])), r++;
3175
+ o && o !== "ul" && c(), o = "ul", s.push(Sr(d[1])), r++;
3150
3176
  continue;
3151
3177
  }
3152
3178
  let f = e.match(/^\d+\.\s+(.+)$/);
3153
3179
  if (f) {
3154
- o && o !== "ol" && c(), o = "ol", s.push(vr(f[1])), r++;
3180
+ o && o !== "ol" && c(), o = "ol", s.push(Sr(f[1])), r++;
3155
3181
  continue;
3156
3182
  }
3157
3183
  if (!e.trim()) {
@@ -3163,13 +3189,13 @@ function br(e) {
3163
3189
  for (; r < t.length;) {
3164
3190
  let e = t[r] ?? "";
3165
3191
  if (!e.trim() || /^(#{1,3}\s|```|[-*+]\s|\d+\.\s|> |(-{3,}|\*{3,})\s*$)/.test(e)) break;
3166
- p.push(vr(e)), r++;
3192
+ p.push(Sr(e)), r++;
3167
3193
  }
3168
- n.push(`<p class="my-2 leading-relaxed">${yr(p.join("<br />"))}</p>`);
3194
+ n.push(`<p class="my-2 leading-relaxed">${Cr(p.join("<br />"))}</p>`);
3169
3195
  }
3170
3196
  return c(), i && a.length && n.push(`<pre class="overflow-x-auto rounded-lg bg-muted p-3 text-sm"><code>${a.join("\n")}</code></pre>`), n.join("\n");
3171
3197
  }
3172
3198
  //#endregion
3173
- export { Jt as AUTHOR_MEMO_MAX_LENGTH, En as BOARD_SECTION_COLS, Dn as BOARD_SECTION_KINDS, On as BOARD_SECTION_SORTS, Cn as BOARD_USER_ROLES, $t as COMMENT_BODY_MAX_LENGTH, et as DEFAULT_BLOCK_BAN_DECAY_MS, $e as DEFAULT_BLOCK_BAN_THRESHOLD, At as DEFAULT_BOARDS, jt as DEFAULT_CATEGORIES, x as DEFAULT_COMMENTS_COLLECTION, w as DEFAULT_LIKES_COLLECTION, u as DEFAULT_POSTS_COLLECTION, v as DEFAULT_REPORTS_COLLECTION, T as DEFAULT_SETTINGS_COLLECTION, d as DEFAULT_USERS_COLLECTION, sn as REPORT_DETAIL_MAX_LENGTH, cn as REPORT_REASONS, ur as WRITING_ASSISTANT_DAILY_LIMIT, Ne as asHttpUrl, ze as boardListOgDescription, Re as boardListOgTitle, Le as boardPostOgDescription, Ie as boardPostOgTitle, S as boardSsrKey, y as boardUserDoc, p as boardUsersCol, kt as buildPostPreview, Je as canManageBoardByRole, Ye as canWriteCommentByRole, An as clampSectionCount, s as commentDoc, E as commentsCol, C as configureMemiBoard, kn as defaultSectionCount, tt as effectiveModerationBlockCount, lt as extractEditorImageUrls, Ge as fetchPublicListForSeo, We as fetchPublicPostForSeo, or as formatDate, cr as formatFullDate, sr as formatRelativeDate, it as formatRestrictedUntilLabel, lr as formatTimestampDetails, wt as hasBodyImage, Ct as hasBodyText, qe as isAssignedStaff, Tt as isContentEmpty, It as isFirestorePermissionDenied, rt as isModerationWriteRestricted, k as likeDoc, l as likeDocId, O as likesCol, an as memiBoardCommentLikesKey, Vn as miniBoardView, In as miniCommentLink, Fn as miniMoreLink, Ln as miniPostImage, Pn as miniPostLink, Rn as miniPostTitle, Hn as miniPostsView, zn as miniViewGroup, Bn as miniViewLabel, nt as moderationWriteRestrictedUntilMs, Be as normalizeBasePath, Xn as normalizeBoardSection, jn as pairSectionCols, xt as plainTextFromHtml, a as postBodyDoc, t as postDoc, dt as postNamespaceFromStoragePath, D as postStorageFolder, o as postsCol, br as renderMarkdownToHtml, r as reportDoc, n as reportDocId, ln as reportReasonLabel, i as reportsCol, _ as resolveBoardPathConfig, Ve as resolvePublicSeoDb, Mn as sectionColClass, Nn as sectionMinHeight, e as settingsCol, g as settingsDoc, b as slugify, ut as storagePathFromDownloadUrl, St as titleFromBody, Fe as toAbsoluteUrl, Pe as toBoardOgImageUrl, h as useBoardPathConfig, ct as useMemiBoardAuth, Xt as useMemiBoardAuthorMemo, qt as useMemiBoardCommentFeed, on as useMemiBoardCommentLikes, tn as useMemiBoardComments, c as useMemiBoardConfig, rn as useMemiBoardLikes, Qn as useMemiBoardMiniLatest, $n as useMemiBoardMiniPicked, Sn as useMemiBoardModeration, Vt as useMemiBoardPost, Bt as useMemiBoardPostList, Rt as useMemiBoardPosts, nn as useMemiBoardReplies, fn as useMemiBoardReportQueue, un as useMemiBoardReports, Zn as useMemiBoardSections, Pt as useMemiBoardSettings, Gt as useMemiBoardUserComments, Ut as useMemiBoardUserPosts, Tn as useMemiBoardUserProfile, wn as useMemiBoardUsers, pn as useMemiBoardViews, _r as useMemiBoardWritingAssistant, er as versionHistory, Ot as videoListCoverUrl, Dt as youtubeId };
3199
+ export { Qt as AUTHOR_MEMO_MAX_LENGTH, An as BOARD_SECTION_COLS, jn as BOARD_SECTION_KINDS, Mn as BOARD_SECTION_SORTS, Dn as BOARD_USER_ROLES, rn as COMMENT_BODY_MAX_LENGTH, et as DEFAULT_BLOCK_BAN_DECAY_MS, $e as DEFAULT_BLOCK_BAN_THRESHOLD, Pt as DEFAULT_BOARDS, Ft as DEFAULT_CATEGORIES, x as DEFAULT_COMMENTS_COLLECTION, w as DEFAULT_LIKES_COLLECTION, u as DEFAULT_POSTS_COLLECTION, v as DEFAULT_REPORTS_COLLECTION, T as DEFAULT_SETTINGS_COLLECTION, d as DEFAULT_USERS_COLLECTION, dn as REPORT_DETAIL_MAX_LENGTH, fn as REPORT_REASONS, mr as WRITING_ASSISTANT_DAILY_LIMIT, Ne as asHttpUrl, ze as boardListOgDescription, Re as boardListOgTitle, Le as boardPostOgDescription, Ie as boardPostOgTitle, S as boardSsrKey, y as boardUserDoc, p as boardUsersCol, Nt as buildPostPreview, Je as canManageBoardByRole, Ye as canWriteCommentByRole, Pn as clampSectionCount, s as commentDoc, E as commentsCol, C as configureMemiBoard, Nn as defaultSectionCount, tt as effectiveModerationBlockCount, pt as extractEditorImageUrls, Ge as fetchPublicListForSeo, We as fetchPublicPostForSeo, ur as formatDate, fr as formatFullDate, dr as formatRelativeDate, it as formatRestrictedUntilLabel, pr as formatTimestampDetails, Ot as hasBodyImage, Dt as hasBodyText, ft as imeSafeSubmitClick, dt as imeSafeSubmitPointerDown, qe as isAssignedStaff, kt as isContentEmpty, Bt as isFirestorePermissionDenied, rt as isModerationWriteRestricted, k as likeDoc, l as likeDocId, O as likesCol, ln as memiBoardCommentLikesKey, Gn as miniBoardView, Bn as miniCommentLink, zn as miniMoreLink, Vn as miniPostImage, Rn as miniPostLink, Hn as miniPostTitle, Kn as miniPostsView, Un as miniViewGroup, Wn as miniViewLabel, nt as moderationWriteRestrictedUntilMs, Be as normalizeBasePath, er as normalizeBoardSection, Fn as pairSectionCols, Tt as plainTextFromHtml, a as postBodyDoc, t as postDoc, ht as postNamespaceFromStoragePath, D as postStorageFolder, o as postsCol, wr as renderMarkdownToHtml, r as reportDoc, n as reportDocId, pn as reportReasonLabel, i as reportsCol, _ as resolveBoardPathConfig, Ve as resolvePublicSeoDb, In as sectionColClass, Ln as sectionMinHeight, e as settingsCol, g as settingsDoc, b as slugify, mt as storagePathFromDownloadUrl, Et as titleFromBody, Fe as toAbsoluteUrl, Pe as toBoardOgImageUrl, h as useBoardPathConfig, ct as useMemiBoardAuth, en as useMemiBoardAuthorMemo, Zt as useMemiBoardCommentFeed, un as useMemiBoardCommentLikes, on as useMemiBoardComments, c as useMemiBoardConfig, cn as useMemiBoardLikes, nr as useMemiBoardMiniLatest, rr as useMemiBoardMiniPicked, En as useMemiBoardModeration, Gt as useMemiBoardPost, Wt as useMemiBoardPostList, Ht as useMemiBoardPosts, sn as useMemiBoardReplies, gn as useMemiBoardReportQueue, mn as useMemiBoardReports, tr as useMemiBoardSections, Rt as useMemiBoardSettings, Yt as useMemiBoardUserComments, qt as useMemiBoardUserPosts, kn as useMemiBoardUserProfile, On as useMemiBoardUsers, _n as useMemiBoardViews, xr as useMemiBoardWritingAssistant, ir as versionHistory, Mt as videoListCoverUrl, jt as youtubeId };
3174
3200
 
3175
3201
  //# sourceMappingURL=index.js.map