memi-board 0.54.0 → 0.55.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.
- package/README.md +1 -1
- package/dist/{ar-Dm3AFfeA.js → ar-ChyOgoxJ.js} +79 -5
- package/dist/ar-ChyOgoxJ.js.map +1 -0
- package/dist/{commentImages-BTm9rc5-.js → commentImages-Dm5Jv2vB.js} +303 -203
- package/dist/commentImages-Dm5Jv2vB.js.map +1 -0
- package/dist/composables/useMemiBoardAppSettings.d.ts +20 -0
- package/dist/composables/useMemiBoardPostTranslations.d.ts +17 -0
- package/dist/composables/useMemiBoardUserStats.d.ts +11 -0
- package/dist/composables/useMemiBoardWritingAssistant.d.ts +6 -0
- package/dist/config.d.ts +30 -0
- package/dist/{de-B_lTRPBf.js → de-XlC1wNZE.js} +79 -5
- package/dist/de-XlC1wNZE.js.map +1 -0
- package/dist/{en-CABPmTIs.js → en-XIVIrnU-.js} +79 -5
- package/dist/en-XIVIrnU-.js.map +1 -0
- package/dist/{es-CpiFVTjt.js → es-DYbCTY9F.js} +79 -5
- package/dist/es-DYbCTY9F.js.map +1 -0
- package/dist/{fr-NP6NJGIK.js → fr-C0cdV-Mk.js} +79 -5
- package/dist/fr-C0cdV-Mk.js.map +1 -0
- package/dist/{id-b8OF1gp-.js → id-DfP8Pyvn.js} +79 -5
- package/dist/id-DfP8Pyvn.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1134 -922
- package/dist/index.js.map +1 -1
- package/dist/{ja-BsqCfwFH.js → ja-DOu3AaTV.js} +79 -5
- package/dist/ja-DOu3AaTV.js.map +1 -0
- package/dist/module.mjs +23 -1
- package/dist/module.mjs.map +1 -1
- package/dist/{pt-Co_6IyDe.js → pt-CTeIsQdM.js} +79 -5
- package/dist/pt-CTeIsQdM.js.map +1 -0
- package/dist/runtime/components/CategorySettings.vue +49 -42
- package/dist/runtime/components/CommentAi.vue +2 -2
- package/dist/runtime/components/Detail.vue +8 -0
- package/dist/runtime/components/Editor.vue +118 -28
- package/dist/runtime/components/Footer.vue +63 -20
- package/dist/runtime/components/List.vue +2 -0
- package/dist/runtime/components/ListCard.vue +91 -0
- package/dist/runtime/components/ListViewSwitch.vue +1 -0
- package/dist/runtime/components/Profile.vue +34 -1
- package/dist/runtime/components/Settings.vue +135 -41
- package/dist/storage.js +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/{zh-DFXcYPOw.js → zh-rDhjLmNl.js} +79 -5
- package/dist/zh-rDhjLmNl.js.map +1 -0
- package/docs/internationalization.md +6 -4
- package/package.json +1 -1
- package/dist/ar-Dm3AFfeA.js.map +0 -1
- package/dist/commentImages-BTm9rc5-.js.map +0 -1
- package/dist/de-B_lTRPBf.js.map +0 -1
- package/dist/en-CABPmTIs.js.map +0 -1
- package/dist/es-CpiFVTjt.js.map +0 -1
- package/dist/fr-NP6NJGIK.js.map +0 -1
- package/dist/id-b8OF1gp-.js.map +0 -1
- package/dist/ja-BsqCfwFH.js.map +0 -1
- package/dist/pt-Co_6IyDe.js.map +0 -1
- package/dist/zh-DFXcYPOw.js.map +0 -1
|
@@ -1,8 +1,80 @@
|
|
|
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
|
|
2
|
-
import { collection as
|
|
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
|
+
//#region src/i18n/locales.ts
|
|
4
|
+
var d = [
|
|
5
|
+
{
|
|
6
|
+
code: "ko",
|
|
7
|
+
name: "한국어",
|
|
8
|
+
intl: "ko-KR",
|
|
9
|
+
dir: "ltr"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
code: "en",
|
|
13
|
+
name: "English",
|
|
14
|
+
intl: "en-US",
|
|
15
|
+
dir: "ltr"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
code: "ja",
|
|
19
|
+
name: "日本語",
|
|
20
|
+
intl: "ja-JP",
|
|
21
|
+
dir: "ltr"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
code: "de",
|
|
25
|
+
name: "Deutsch",
|
|
26
|
+
intl: "de-DE",
|
|
27
|
+
dir: "ltr"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
code: "fr",
|
|
31
|
+
name: "Français",
|
|
32
|
+
intl: "fr-FR",
|
|
33
|
+
dir: "ltr"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
code: "es",
|
|
37
|
+
name: "Español",
|
|
38
|
+
intl: "es-419",
|
|
39
|
+
dir: "ltr"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
code: "pt",
|
|
43
|
+
name: "Português",
|
|
44
|
+
intl: "pt-BR",
|
|
45
|
+
dir: "ltr"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
code: "zh",
|
|
49
|
+
name: "中文",
|
|
50
|
+
intl: "zh-CN",
|
|
51
|
+
dir: "ltr"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
code: "ar",
|
|
55
|
+
name: "العربية",
|
|
56
|
+
intl: "ar",
|
|
57
|
+
dir: "rtl"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
code: "id",
|
|
61
|
+
name: "Indonesia",
|
|
62
|
+
intl: "id-ID",
|
|
63
|
+
dir: "ltr"
|
|
64
|
+
}
|
|
65
|
+
], f = "ko", p = "en", m = new Set(d.map((e) => e.code));
|
|
66
|
+
function h(e) {
|
|
67
|
+
if (typeof e != "string") return;
|
|
68
|
+
let t = e.trim().toLowerCase().split(/[-_]/)[0];
|
|
69
|
+
return t && m.has(t) ? t : void 0;
|
|
70
|
+
}
|
|
71
|
+
function g(e) {
|
|
72
|
+
return d.find((t) => t.code === e) ?? d[0];
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
3
75
|
//#region src/utils/boardPaths.ts
|
|
4
|
-
var
|
|
5
|
-
function
|
|
76
|
+
var _ = "memiBoardPosts", v = "memiBoardComments", y = "memiBoardLikes", b = "memiBoardReports", x = "memiBoardSettings", S = "memiBoardUsers";
|
|
77
|
+
function C(e) {
|
|
6
78
|
return {
|
|
7
79
|
postsCollection: e.postsCollection?.trim() || "memiBoardPosts",
|
|
8
80
|
commentsCollection: e.commentsCollection?.trim() || "memiBoardComments",
|
|
@@ -12,75 +84,75 @@ function v(e) {
|
|
|
12
84
|
usersCollection: e.usersCollection?.trim() || "memiBoardUsers"
|
|
13
85
|
};
|
|
14
86
|
}
|
|
15
|
-
function
|
|
16
|
-
return
|
|
87
|
+
function w(e, t) {
|
|
88
|
+
return l(e, t.settingsCollection);
|
|
17
89
|
}
|
|
18
90
|
function te(e, t, n) {
|
|
19
|
-
return
|
|
91
|
+
return u(e, t.settingsCollection, n);
|
|
20
92
|
}
|
|
21
93
|
function ne(e, t) {
|
|
22
|
-
return
|
|
94
|
+
return l(e, t.postsCollection);
|
|
23
95
|
}
|
|
24
|
-
function
|
|
25
|
-
return
|
|
96
|
+
function T(e, t, n) {
|
|
97
|
+
return u(e, t.postsCollection, n);
|
|
26
98
|
}
|
|
27
|
-
function
|
|
28
|
-
return
|
|
99
|
+
function re(e, t, n) {
|
|
100
|
+
return u(e, t.postsCollection, n, "body", "main");
|
|
29
101
|
}
|
|
30
|
-
function
|
|
31
|
-
return
|
|
102
|
+
function ie(e, t) {
|
|
103
|
+
return l(e, t.commentsCollection);
|
|
32
104
|
}
|
|
33
|
-
function
|
|
34
|
-
return
|
|
105
|
+
function ae(e, t, n) {
|
|
106
|
+
return u(e, t.commentsCollection, n);
|
|
35
107
|
}
|
|
36
|
-
function
|
|
37
|
-
return
|
|
108
|
+
function oe(e, t) {
|
|
109
|
+
return l(e, t.likesCollection);
|
|
38
110
|
}
|
|
39
|
-
function
|
|
111
|
+
function E(e, t) {
|
|
40
112
|
return `${e}_${t}`;
|
|
41
113
|
}
|
|
42
|
-
function
|
|
43
|
-
return
|
|
114
|
+
function se(e, t, n, r) {
|
|
115
|
+
return u(e, t.likesCollection, E(n, r));
|
|
44
116
|
}
|
|
45
|
-
function
|
|
46
|
-
return
|
|
117
|
+
function ce(e, t) {
|
|
118
|
+
return l(e, t.reportsCollection);
|
|
47
119
|
}
|
|
48
|
-
function
|
|
120
|
+
function D(e, t) {
|
|
49
121
|
return `${e}_${t}`;
|
|
50
122
|
}
|
|
51
|
-
function
|
|
52
|
-
return
|
|
123
|
+
function le(e, t, n, r) {
|
|
124
|
+
return u(e, t.reportsCollection, D(n, r));
|
|
53
125
|
}
|
|
54
|
-
function
|
|
55
|
-
return
|
|
126
|
+
function O(e, t) {
|
|
127
|
+
return l(e, t.usersCollection);
|
|
56
128
|
}
|
|
57
|
-
function
|
|
58
|
-
return
|
|
129
|
+
function k(e, t, n) {
|
|
130
|
+
return u(e, t.usersCollection, n);
|
|
59
131
|
}
|
|
60
|
-
function
|
|
61
|
-
return
|
|
132
|
+
function A(e, t, n) {
|
|
133
|
+
return u(e, t.usersCollection, n, "private", "info");
|
|
62
134
|
}
|
|
63
|
-
function
|
|
64
|
-
return
|
|
135
|
+
function ue(e, t, n, r) {
|
|
136
|
+
return u(e, t.usersCollection, n, "memos", r);
|
|
65
137
|
}
|
|
66
|
-
function
|
|
138
|
+
function de(e, t) {
|
|
67
139
|
return `${e.postsCollection}/${t}`;
|
|
68
140
|
}
|
|
69
|
-
function
|
|
141
|
+
function fe(e, t) {
|
|
70
142
|
return `${e.postsCollection}/${e.usersCollection}/${t}`;
|
|
71
143
|
}
|
|
72
144
|
//#endregion
|
|
73
145
|
//#region src/config.ts
|
|
74
|
-
var
|
|
75
|
-
function
|
|
146
|
+
var j = "__MEMI_BOARD_CONFIG__";
|
|
147
|
+
function M() {
|
|
76
148
|
let e = globalThis;
|
|
77
|
-
return e[
|
|
78
|
-
postsCollection:
|
|
79
|
-
commentsCollection:
|
|
80
|
-
likesCollection:
|
|
81
|
-
reportsCollection:
|
|
82
|
-
settingsCollection:
|
|
83
|
-
usersCollection:
|
|
149
|
+
return e[j] || (e[j] = o({
|
|
150
|
+
postsCollection: _,
|
|
151
|
+
commentsCollection: v,
|
|
152
|
+
likesCollection: y,
|
|
153
|
+
reportsCollection: b,
|
|
154
|
+
settingsCollection: x,
|
|
155
|
+
usersCollection: S,
|
|
84
156
|
auth: { providers: ["google", "apple"] },
|
|
85
157
|
moderation: {
|
|
86
158
|
enabled: !0,
|
|
@@ -98,10 +170,10 @@ function T() {
|
|
|
98
170
|
defaultOgImage: "",
|
|
99
171
|
basePath: "/board"
|
|
100
172
|
}
|
|
101
|
-
})), e[
|
|
173
|
+
})), e[j];
|
|
102
174
|
}
|
|
103
|
-
function
|
|
104
|
-
let t =
|
|
175
|
+
function pe(e) {
|
|
176
|
+
let t = M();
|
|
105
177
|
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 = {
|
|
106
178
|
...t.i18n,
|
|
107
179
|
...e.i18n
|
|
@@ -110,96 +182,49 @@ function me(e) {
|
|
|
110
182
|
...e.translation
|
|
111
183
|
}), e.roleLabels && (t.roleLabels = { ...e.roleLabels }), e.locale && (t.locale = e.locale);
|
|
112
184
|
}
|
|
113
|
-
function
|
|
114
|
-
return
|
|
185
|
+
function N() {
|
|
186
|
+
return M();
|
|
115
187
|
}
|
|
116
|
-
function
|
|
117
|
-
return
|
|
188
|
+
function P() {
|
|
189
|
+
return N().site?.disableAi !== !0;
|
|
118
190
|
}
|
|
119
|
-
function
|
|
120
|
-
|
|
191
|
+
function me() {
|
|
192
|
+
if (!P()) throw Object.assign(/* @__PURE__ */ Error("AI features are disabled for this board service."), { code: "memi-board/ai-disabled" });
|
|
121
193
|
}
|
|
122
|
-
function
|
|
123
|
-
|
|
194
|
+
function F() {
|
|
195
|
+
let e = N();
|
|
196
|
+
return e.site?.disableI18n !== !0 && e.i18n?.enabled !== !1;
|
|
124
197
|
}
|
|
125
|
-
function
|
|
126
|
-
return
|
|
198
|
+
function I() {
|
|
199
|
+
return P() && F() && N().translation?.enabled !== !1;
|
|
127
200
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
name: "한국어",
|
|
134
|
-
intl: "ko-KR",
|
|
135
|
-
dir: "ltr"
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
code: "en",
|
|
139
|
-
name: "English",
|
|
140
|
-
intl: "en-US",
|
|
141
|
-
dir: "ltr"
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
code: "ja",
|
|
145
|
-
name: "日本語",
|
|
146
|
-
intl: "ja-JP",
|
|
147
|
-
dir: "ltr"
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
code: "de",
|
|
151
|
-
name: "Deutsch",
|
|
152
|
-
intl: "de-DE",
|
|
153
|
-
dir: "ltr"
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
code: "fr",
|
|
157
|
-
name: "Français",
|
|
158
|
-
intl: "fr-FR",
|
|
159
|
-
dir: "ltr"
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
code: "es",
|
|
163
|
-
name: "Español",
|
|
164
|
-
intl: "es-419",
|
|
165
|
-
dir: "ltr"
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
code: "pt",
|
|
169
|
-
name: "Português",
|
|
170
|
-
intl: "pt-BR",
|
|
171
|
-
dir: "ltr"
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
code: "zh",
|
|
175
|
-
name: "中文",
|
|
176
|
-
intl: "zh-CN",
|
|
177
|
-
dir: "ltr"
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
code: "ar",
|
|
181
|
-
name: "العربية",
|
|
182
|
-
intl: "ar",
|
|
183
|
-
dir: "rtl"
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
code: "id",
|
|
187
|
-
name: "Indonesia",
|
|
188
|
-
intl: "id-ID",
|
|
189
|
-
dir: "ltr"
|
|
190
|
-
}
|
|
191
|
-
], M = "ko", N = "en", P = new Set(j.map((e) => e.code));
|
|
192
|
-
function F(e) {
|
|
193
|
-
if (typeof e != "string") return;
|
|
194
|
-
let t = e.trim().toLowerCase().split(/[-_]/)[0];
|
|
195
|
-
return t && P.has(t) ? t : void 0;
|
|
201
|
+
function L() {
|
|
202
|
+
let e = d.map((e) => e.code), t = N().site?.locales;
|
|
203
|
+
if (!F() || !t?.length) return e;
|
|
204
|
+
let n = new Set(t.map((e) => h(e)).filter(Boolean)), r = e.filter((e) => n.has(e));
|
|
205
|
+
return r.length ? r : e;
|
|
196
206
|
}
|
|
197
|
-
function
|
|
198
|
-
|
|
207
|
+
function R() {
|
|
208
|
+
let e = N(), t = e.site?.locale || e.locale, n = L(), r = h(t);
|
|
209
|
+
return n.length === d.length || r && n.includes(r) ? t : n[0];
|
|
210
|
+
}
|
|
211
|
+
function z(e) {
|
|
212
|
+
N().site = {
|
|
213
|
+
disableAi: e?.disableAi === !0,
|
|
214
|
+
disableI18n: e?.disableI18n === !0,
|
|
215
|
+
locale: typeof e?.locale == "string" && e.locale ? e.locale : void 0,
|
|
216
|
+
locales: Array.isArray(e?.locales) ? e.locales.filter((e) => typeof e == "string") : void 0
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function he() {
|
|
220
|
+
if (!I()) throw Object.assign(/* @__PURE__ */ Error("Content translation is disabled for this board service."), { code: "memi-board/translation-disabled" });
|
|
221
|
+
}
|
|
222
|
+
function ge() {
|
|
223
|
+
return C(N());
|
|
199
224
|
}
|
|
200
225
|
//#endregion
|
|
201
226
|
//#region src/i18n/messages/ko/index.ts
|
|
202
|
-
var
|
|
227
|
+
var _e = {
|
|
203
228
|
attachments: {
|
|
204
229
|
attach: "파일 첨부 ({count} / {max})",
|
|
205
230
|
dropOrClick: "파일을 놓거나 클릭해서 추가",
|
|
@@ -414,6 +439,10 @@ var L = {
|
|
|
414
439
|
help: "예: 경상도 사투리 스타일로 / 정중한 문어체로 / 간결한 개조식으로",
|
|
415
440
|
placeholder: "경상도 사투리 스타일로"
|
|
416
441
|
},
|
|
442
|
+
translateView: {
|
|
443
|
+
title: "{language} 번역 미리 보기",
|
|
444
|
+
notSaved: "저장되지 않았습니다. 미리 보기일 뿐입니다."
|
|
445
|
+
},
|
|
417
446
|
aiPreview: {
|
|
418
447
|
title: "AI 결과 확인",
|
|
419
448
|
currentTitle: "현재 제목",
|
|
@@ -474,9 +503,8 @@ var L = {
|
|
|
474
503
|
summarize: "짧게 요약하기",
|
|
475
504
|
translateEn: "영어로 번역",
|
|
476
505
|
translateKo: "한국어로 번역",
|
|
506
|
+
translateView: "번역해서 보기",
|
|
477
507
|
translateAll: "{count}개 언어로 번역해 저장",
|
|
478
|
-
translateSaved: "{count}개 언어로 저장했습니다. 다른 언어로 보면 번역이 보입니다.",
|
|
479
|
-
translatePending: "{count}개 언어 번역을 준비했습니다. 글을 저장하면 함께 기록됩니다.",
|
|
480
508
|
translateEmpty: "번역할 제목이나 본문을 먼저 입력해 주세요.",
|
|
481
509
|
title: "본문에서 제목 만들기",
|
|
482
510
|
custom: "커스텀 스타일로 바꾸기…",
|
|
@@ -510,7 +538,10 @@ var L = {
|
|
|
510
538
|
writeRestricted: "콘텐츠 경고가 누적되어 글·댓글 작성이 잠시 제한됐어요.",
|
|
511
539
|
moderationBlocked: "게시할 수 없는 내용이 포함되어 있습니다."
|
|
512
540
|
},
|
|
541
|
+
titleOptionalPlaceholder: "제목 (비워 두면 AI가 만들어 드려요)",
|
|
542
|
+
titleAiNotice: "AI가 글 내용으로 제목을 만들었어요. 마음에 들면 저장하고, 아니면 고쳐 주세요.",
|
|
513
543
|
hint: {
|
|
544
|
+
titling: "제목을 만드는 중…",
|
|
514
545
|
translating: "글을 {count}개 언어로 번역하는 중…",
|
|
515
546
|
reviewing: "내용을 검토하는 중…",
|
|
516
547
|
saving: "저장하는 중…"
|
|
@@ -520,9 +551,13 @@ var L = {
|
|
|
520
551
|
introduction: "memi-board는 Nuxt 4와 Vue 3, TypeScript를 바탕으로 만들었습니다. Nuxt UI와 Firebase로 글과 댓글, 사람과 이야기를 자연스럽게 이어갑니다.",
|
|
521
552
|
eyebrow: "함께 만드는 이야기",
|
|
522
553
|
tagline: "글과 댓글로 이어지는 작은 커뮤니티.",
|
|
554
|
+
detail: "자세한 소개",
|
|
523
555
|
links: "링크 & 연락처",
|
|
524
556
|
email: "이메일",
|
|
525
557
|
credit: "만든 이: memi",
|
|
558
|
+
feedback: "피드백 보내기",
|
|
559
|
+
feedbackSubject: "memi-board 피드백",
|
|
560
|
+
feedbackBody: "의견:\n",
|
|
526
561
|
siteEyebrow: "memi-board와 함께",
|
|
527
562
|
changelog: "변경 기록",
|
|
528
563
|
info: {
|
|
@@ -537,7 +572,13 @@ var L = {
|
|
|
537
572
|
waiting: "QR로 간편하게 시작하는 대기 서비스",
|
|
538
573
|
track: "이동 경로를 기록하는 GPS 트래킹",
|
|
539
574
|
loop: "차량 운행 기록과 센서 솔루션",
|
|
540
|
-
safe: "페달 오조작 방지 장치 연결 및 설정"
|
|
575
|
+
safe: "페달 오조작 방지 장치 연결 및 설정",
|
|
576
|
+
inviteTitle: "당신도 쓰고 계신가요?",
|
|
577
|
+
invite: "사이트 주소를 알려주세요~",
|
|
578
|
+
inviteSite: "memi.dev에 남기기",
|
|
579
|
+
inviteOr: "또는",
|
|
580
|
+
inviteSubject: "memi-board를 쓰고 있어요",
|
|
581
|
+
inviteBody: "사이트 주소:\n"
|
|
541
582
|
},
|
|
542
583
|
stack: {
|
|
543
584
|
ui: "화면과 경험",
|
|
@@ -555,6 +596,7 @@ var L = {
|
|
|
555
596
|
loadFailed: "목록을 불러오지 못했습니다: {error}",
|
|
556
597
|
empty: "아직 게시글이 없습니다.",
|
|
557
598
|
notice: "공지",
|
|
599
|
+
commentCount: "댓글 {count}개",
|
|
558
600
|
photo: "사진",
|
|
559
601
|
likeCount: "추천 {count}",
|
|
560
602
|
info: {
|
|
@@ -583,6 +625,7 @@ var L = {
|
|
|
583
625
|
},
|
|
584
626
|
listViewSwitch: {
|
|
585
627
|
default: "일반",
|
|
628
|
+
card: "카드",
|
|
586
629
|
dense: "조밀",
|
|
587
630
|
video: "영상"
|
|
588
631
|
},
|
|
@@ -632,7 +675,14 @@ var L = {
|
|
|
632
675
|
notFound: "사용자를 찾을 수 없습니다.",
|
|
633
676
|
noName: "이름 없음",
|
|
634
677
|
joined: "가입 {time}",
|
|
635
|
-
lastVisit: "최근 방문 {time}"
|
|
678
|
+
lastVisit: "최근 방문 {time}",
|
|
679
|
+
stats: {
|
|
680
|
+
posts: "글 {count}",
|
|
681
|
+
comments: "댓글 {count}",
|
|
682
|
+
aiUsage: "AI 사용 {used} / {limit}",
|
|
683
|
+
aiUsageResets: "AI 사용 {used} / {limit} · {hours}시간 후 초기화",
|
|
684
|
+
warnings: "경고 {count}회"
|
|
685
|
+
}
|
|
636
686
|
},
|
|
637
687
|
profileEditModal: {
|
|
638
688
|
imageOnly: "이미지 파일만 선택할 수 있습니다.",
|
|
@@ -787,6 +837,7 @@ var L = {
|
|
|
787
837
|
label: "리스트뷰",
|
|
788
838
|
help: "게시글 목록 표시 방식",
|
|
789
839
|
options: {
|
|
840
|
+
card: "카드",
|
|
790
841
|
dense: "조밀",
|
|
791
842
|
video: "영상"
|
|
792
843
|
}
|
|
@@ -868,6 +919,54 @@ var L = {
|
|
|
868
919
|
saveFailed: "게시판 설정을 저장하지 못했습니다.",
|
|
869
920
|
deleteAllFailed: "게시판 데이터를 삭제하지 못했습니다."
|
|
870
921
|
},
|
|
922
|
+
aiTitle: {
|
|
923
|
+
label: "AI 제목 자동 만들기",
|
|
924
|
+
help: "새 글의 제목을 비우면 AI가 글(글이 없으면 첫 사진)로 제목을 만들어 줍니다. 사진은 제목을 만들 때만 Google AI로 전송됩니다. 끄면 제목을 직접 써야 하고 사진도 전송되지 않습니다."
|
|
925
|
+
},
|
|
926
|
+
site: {
|
|
927
|
+
apply: "적용",
|
|
928
|
+
applied: "적용했습니다.",
|
|
929
|
+
title: "전체 설정",
|
|
930
|
+
help: "사이트 전체에 적용됩니다. 호스트 앱의 설정 위에 덧씌워지고, 바꾸면 바로 반영됩니다.",
|
|
931
|
+
ai: {
|
|
932
|
+
label: "AI 기능 사용",
|
|
933
|
+
help: "비용 등으로 AI를 쓰지 않을 때 끄세요. 끄면 번역, 글쓰기 도우미, AI 제목, AI 검열이 모두 꺼지고 사진도 AI로 전송되지 않습니다. 금칙어 검사는 그대로 동작합니다."
|
|
934
|
+
},
|
|
935
|
+
i18n: {
|
|
936
|
+
label: "국제화 사용",
|
|
937
|
+
help: "끄면 모든 화면이 아래에서 고른 한 언어로 고정되고 번역 기능도 꺼집니다. 이미 저장된 번역은 지워지지 않습니다."
|
|
938
|
+
},
|
|
939
|
+
locales: {
|
|
940
|
+
label: "사용할 언어",
|
|
941
|
+
help: "선택한 {count}개 언어만 번역하고 언어 메뉴에 보여 줍니다. 고르지 않은 언어는 새로 번역하지 않으며, 이미 저장된 번역은 지워지지 않습니다."
|
|
942
|
+
},
|
|
943
|
+
locale: {
|
|
944
|
+
label: "기본 언어",
|
|
945
|
+
help: "호스트 앱이 언어를 정하지 않을 때 쓰는 언어입니다.",
|
|
946
|
+
fixedLabel: "고정 언어",
|
|
947
|
+
fixedHelp: "모든 화면이 이 언어로 표시됩니다."
|
|
948
|
+
}
|
|
949
|
+
},
|
|
950
|
+
i18nBoard: {
|
|
951
|
+
label: "국제화",
|
|
952
|
+
help: "켜면 게시판 이름·설명과 새 글·댓글을 {count}개 언어로 자동 번역해 함께 저장합니다. 끄면 원문만 보입니다.",
|
|
953
|
+
existing: "기존 글도 번역하기"
|
|
954
|
+
},
|
|
955
|
+
about: {
|
|
956
|
+
label: "About memi-board 표시",
|
|
957
|
+
help: "화면 아래의 About memi-board 링크와 소개 팝업을 모든 게시판 화면에 보여 줍니다. 끄면 사이트 전체에서 숨겨집니다."
|
|
958
|
+
},
|
|
959
|
+
postTranslations: {
|
|
960
|
+
label: "기존 글 번역",
|
|
961
|
+
help: "번역이 없거나 원문과 달라진 글을 찾아 한꺼번에 번역하고 저장합니다. 자동 번역을 끈 게시판이나, 번역이 빠진 글을 채울 때 쓰세요. AI 사용 횟수는 차감하지 않습니다.",
|
|
962
|
+
scan: "번역할 글 찾기",
|
|
963
|
+
run: "{count}개 글 번역하기",
|
|
964
|
+
confirm: "{count}개 글을 번역해 저장합니다. 글 수만큼 AI 호출이 일어납니다. 계속할까요?",
|
|
965
|
+
progress: "번역 중… 완료 {done}, 실패 {failed}",
|
|
966
|
+
allDone: "게시된 글 {total}개 모두 번역이 최신입니다.",
|
|
967
|
+
found: "게시된 글 {total}개 중 {count}개를 번역해야 합니다.",
|
|
968
|
+
failed: "{count}개 글은 번역하지 못했습니다. 다시 찾아서 시도해 주세요."
|
|
969
|
+
},
|
|
871
970
|
cleanup: {
|
|
872
971
|
contextChanged: "조회 이후 계정이나 게시판 설정이 변경되었습니다. 다시 조회해 주세요.",
|
|
873
972
|
title: "고아 파일·문서 정리",
|
|
@@ -964,40 +1063,40 @@ var L = {
|
|
|
964
1063
|
custom: "커스텀 스타일로 바꾸기…"
|
|
965
1064
|
}
|
|
966
1065
|
}
|
|
967
|
-
},
|
|
968
|
-
en: () => import("./en-
|
|
969
|
-
ja: () => import("./ja-
|
|
970
|
-
de: () => import("./de-
|
|
971
|
-
fr: () => import("./fr-
|
|
972
|
-
es: () => import("./es-
|
|
973
|
-
pt: () => import("./pt-
|
|
974
|
-
zh: () => import("./zh-
|
|
975
|
-
ar: () => import("./ar-
|
|
976
|
-
id: () => import("./id-
|
|
977
|
-
},
|
|
978
|
-
function
|
|
1066
|
+
}, ve = {
|
|
1067
|
+
en: () => import("./en-XIVIrnU-.js"),
|
|
1068
|
+
ja: () => import("./ja-DOu3AaTV.js"),
|
|
1069
|
+
de: () => import("./de-XlC1wNZE.js"),
|
|
1070
|
+
fr: () => import("./fr-C0cdV-Mk.js"),
|
|
1071
|
+
es: () => import("./es-DYbCTY9F.js"),
|
|
1072
|
+
pt: () => import("./pt-CTeIsQdM.js"),
|
|
1073
|
+
zh: () => import("./zh-rDhjLmNl.js"),
|
|
1074
|
+
ar: () => import("./ar-ChyOgoxJ.js"),
|
|
1075
|
+
id: () => import("./id-DfP8Pyvn.js")
|
|
1076
|
+
}, B = "__MEMI_BOARD_I18N__";
|
|
1077
|
+
function V() {
|
|
979
1078
|
let e = globalThis;
|
|
980
|
-
return e[
|
|
981
|
-
messages: { ko:
|
|
1079
|
+
return e[B] ??= {
|
|
1080
|
+
messages: { ko: _e },
|
|
982
1081
|
pending: {},
|
|
983
1082
|
version: s(0)
|
|
984
|
-
}, e[
|
|
1083
|
+
}, e[B];
|
|
985
1084
|
}
|
|
986
|
-
function
|
|
987
|
-
let t =
|
|
988
|
-
return t.messages[e] || e === "ko" ? Promise.resolve() : (t.pending[e] ??=
|
|
1085
|
+
function H(e) {
|
|
1086
|
+
let t = V();
|
|
1087
|
+
return t.messages[e] || e === "ko" ? Promise.resolve() : (t.pending[e] ??= ve[e]().then((n) => {
|
|
989
1088
|
t.messages[e] = n.default, t.version.value++;
|
|
990
1089
|
}).catch((n) => {
|
|
991
1090
|
delete t.pending[e], console.warn(`[memi-board] failed to load locale "${e}"`, n);
|
|
992
1091
|
}), t.pending[e]);
|
|
993
1092
|
}
|
|
994
|
-
function
|
|
995
|
-
return e === "ko" ? Promise.resolve() : Promise.all([
|
|
1093
|
+
function U(e) {
|
|
1094
|
+
return e === "ko" ? Promise.resolve() : Promise.all([H(e), H("en")]).then(() => void 0);
|
|
996
1095
|
}
|
|
997
|
-
function
|
|
998
|
-
return !!
|
|
1096
|
+
function ye(e) {
|
|
1097
|
+
return !!V().messages[e];
|
|
999
1098
|
}
|
|
1000
|
-
function
|
|
1099
|
+
function W(e, t) {
|
|
1001
1100
|
let n = e;
|
|
1002
1101
|
for (let e of t.split(".")) {
|
|
1003
1102
|
if (!n || typeof n == "string") return;
|
|
@@ -1005,36 +1104,36 @@ function U(e, t) {
|
|
|
1005
1104
|
}
|
|
1006
1105
|
return typeof n == "string" ? n : void 0;
|
|
1007
1106
|
}
|
|
1008
|
-
function
|
|
1107
|
+
function be(e, t) {
|
|
1009
1108
|
return t ? e.replace(/\{(\w+)\}/g, (e, n) => {
|
|
1010
1109
|
let r = t[n];
|
|
1011
1110
|
return r == null ? e : String(r);
|
|
1012
1111
|
}) : e;
|
|
1013
1112
|
}
|
|
1014
|
-
function
|
|
1015
|
-
let r =
|
|
1113
|
+
function G(e, t, n) {
|
|
1114
|
+
let r = V();
|
|
1016
1115
|
r.version.value;
|
|
1017
|
-
let i = e ?? "ko", a =
|
|
1018
|
-
return a == null ? t :
|
|
1116
|
+
let i = e ?? "ko", a = W(r.messages[i], t) ?? (i === "ko" ? void 0 : W(r.messages.en, t)) ?? W(r.messages.ko, t);
|
|
1117
|
+
return a == null ? t : be(a, n);
|
|
1019
1118
|
}
|
|
1020
1119
|
//#endregion
|
|
1021
1120
|
//#region src/utils/formatDate.ts
|
|
1022
|
-
function
|
|
1023
|
-
return
|
|
1121
|
+
function K(e) {
|
|
1122
|
+
return g(e ?? "ko").intl;
|
|
1024
1123
|
}
|
|
1025
|
-
function
|
|
1026
|
-
return e?.toDate ? e.toDate().toLocaleDateString(
|
|
1124
|
+
function q(e, t) {
|
|
1125
|
+
return e?.toDate ? e.toDate().toLocaleDateString(K(t)) : "";
|
|
1027
1126
|
}
|
|
1028
|
-
var
|
|
1029
|
-
function
|
|
1030
|
-
if (!e?.toDate) return
|
|
1127
|
+
var xe = 60, J = 3600, Se = 24 * J;
|
|
1128
|
+
function Y(e, t = Date.now(), n) {
|
|
1129
|
+
if (!e?.toDate) return G(n, "common.date.justNow");
|
|
1031
1130
|
let r = Math.max(0, Math.round((t - e.toDate().getTime()) / 1e3));
|
|
1032
|
-
if (r < 45) return
|
|
1033
|
-
let i = new Intl.RelativeTimeFormat(
|
|
1034
|
-
return r < 90 ? i.format(-1, "minute") : r < 2700 ? i.format(-Math.round(r /
|
|
1131
|
+
if (r < 45) return G(n, "common.date.fewSecondsAgo");
|
|
1132
|
+
let i = new Intl.RelativeTimeFormat(K(n), { numeric: "always" }), a = r / Se;
|
|
1133
|
+
return r < 90 ? i.format(-1, "minute") : r < 2700 ? i.format(-Math.round(r / xe), "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");
|
|
1035
1134
|
}
|
|
1036
|
-
function
|
|
1037
|
-
return e?.toDate ? new Intl.DateTimeFormat(
|
|
1135
|
+
function X(e, t) {
|
|
1136
|
+
return e?.toDate ? new Intl.DateTimeFormat(K(t), {
|
|
1038
1137
|
year: "numeric",
|
|
1039
1138
|
month: "long",
|
|
1040
1139
|
day: "numeric",
|
|
@@ -1042,56 +1141,57 @@ function Y(e, t) {
|
|
|
1042
1141
|
minute: "2-digit",
|
|
1043
1142
|
second: "2-digit",
|
|
1044
1143
|
hourCycle: "h23"
|
|
1045
|
-
}).format(e.toDate()) :
|
|
1144
|
+
}).format(e.toDate()) : G(t, "common.date.checking");
|
|
1046
1145
|
}
|
|
1047
|
-
function
|
|
1048
|
-
let r =
|
|
1049
|
-
return a == null || i == null || i === a ? [r] : [
|
|
1146
|
+
function Z(e, t, n) {
|
|
1147
|
+
let r = X(e, n), i = e?.toMillis?.(), a = t?.toMillis?.();
|
|
1148
|
+
return a == null || i == null || i === a ? [r] : [G(n, "common.date.createdAt", { time: r }), G(n, "common.date.updatedAt", { time: X(t, n) })];
|
|
1050
1149
|
}
|
|
1051
1150
|
//#endregion
|
|
1052
1151
|
//#region src/i18n/useMemiBoardI18n.ts
|
|
1053
|
-
var
|
|
1054
|
-
function
|
|
1055
|
-
let s = n(),
|
|
1056
|
-
o.boardLocale !== void 0 && s && a(
|
|
1057
|
-
let
|
|
1152
|
+
var Q = "memiBoard:hostLocale", $ = Symbol("memiBoard:boardLocale");
|
|
1153
|
+
function Ce(o = {}) {
|
|
1154
|
+
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");
|
|
1155
|
+
o.boardLocale !== void 0 && s && a($, _), ee(_, (e) => void U(e), { immediate: !0 }), t() && i(() => U(_.value));
|
|
1156
|
+
let v = e(() => g(_.value));
|
|
1058
1157
|
return {
|
|
1059
|
-
locale:
|
|
1060
|
-
i18nEnabled:
|
|
1061
|
-
translationEnabled:
|
|
1062
|
-
|
|
1063
|
-
|
|
1158
|
+
locale: _,
|
|
1159
|
+
i18nEnabled: f,
|
|
1160
|
+
translationEnabled: p,
|
|
1161
|
+
aiEnabled: m,
|
|
1162
|
+
dir: e(() => v.value.dir),
|
|
1163
|
+
intlLocale: e(() => v.value.intl),
|
|
1064
1164
|
t: (e, t) => {
|
|
1065
1165
|
let n = e.startsWith("common.role.") ? e.slice(12) : "";
|
|
1066
|
-
return
|
|
1166
|
+
return d.roleLabels?.[n] ?? G(_.value, e, t);
|
|
1067
1167
|
},
|
|
1068
|
-
formatDate: (e) =>
|
|
1069
|
-
formatFullDate: (e) =>
|
|
1070
|
-
formatRelativeDate: (e, t) =>
|
|
1071
|
-
formatTimestampDetails: (e, t) =>
|
|
1072
|
-
formatNumber: (e) => e.toLocaleString(
|
|
1168
|
+
formatDate: (e) => q(e, _.value),
|
|
1169
|
+
formatFullDate: (e) => X(e, _.value),
|
|
1170
|
+
formatRelativeDate: (e, t) => Y(e, t, _.value),
|
|
1171
|
+
formatTimestampDetails: (e, t) => Z(e, t, _.value),
|
|
1172
|
+
formatNumber: (e) => e.toLocaleString(v.value.intl)
|
|
1073
1173
|
};
|
|
1074
1174
|
}
|
|
1075
1175
|
//#endregion
|
|
1076
1176
|
//#region src/utils/slugify.ts
|
|
1077
|
-
var
|
|
1078
|
-
function
|
|
1177
|
+
var we = 40;
|
|
1178
|
+
function Te(e) {
|
|
1079
1179
|
return e.trim().replace(/\s+/g, "-").replace(/[^a-zA-Z0-9가-힣ㄱ-ㅎㅏ-ㅣ-]/g, "").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
|
|
1080
1180
|
}
|
|
1081
|
-
function
|
|
1181
|
+
function Ee(e, t = 60) {
|
|
1082
1182
|
return e.replace(/[^a-zA-Z0-9가-힣ㄱ-ㅎ._-]/g, "-").slice(0, t);
|
|
1083
1183
|
}
|
|
1084
1184
|
//#endregion
|
|
1085
1185
|
//#region src/utils/commentImages.ts
|
|
1086
|
-
var
|
|
1186
|
+
var De = /* @__PURE__ */ new Set([
|
|
1087
1187
|
"image/jpeg",
|
|
1088
1188
|
"image/png",
|
|
1089
1189
|
"image/gif",
|
|
1090
1190
|
"image/webp"
|
|
1091
1191
|
]);
|
|
1092
|
-
function
|
|
1192
|
+
function Oe(e) {
|
|
1093
1193
|
let t = (e.type || "").toLowerCase();
|
|
1094
|
-
if (
|
|
1194
|
+
if (De.has(t)) return !0;
|
|
1095
1195
|
let n = e.name.toLowerCase();
|
|
1096
1196
|
return [
|
|
1097
1197
|
".jpg",
|
|
@@ -1101,7 +1201,7 @@ function $(e) {
|
|
|
1101
1201
|
".webp"
|
|
1102
1202
|
].some((e) => n.endsWith(e));
|
|
1103
1203
|
}
|
|
1104
|
-
function
|
|
1204
|
+
function ke(e) {
|
|
1105
1205
|
if (!e?.length) return [];
|
|
1106
1206
|
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 [{
|
|
1107
1207
|
name: t.name.slice(0, 200),
|
|
@@ -1112,7 +1212,7 @@ function we(e) {
|
|
|
1112
1212
|
}];
|
|
1113
1213
|
return [];
|
|
1114
1214
|
}
|
|
1115
|
-
function
|
|
1215
|
+
function Ae(e, t) {
|
|
1116
1216
|
let n = t.endsWith("/") ? t : `${t}/`;
|
|
1117
1217
|
if (!Array.isArray(e)) return [];
|
|
1118
1218
|
let r = /* @__PURE__ */ new Set();
|
|
@@ -1124,6 +1224,6 @@ function Te(e, t) {
|
|
|
1124
1224
|
return [...r];
|
|
1125
1225
|
}
|
|
1126
1226
|
//#endregion
|
|
1127
|
-
export {
|
|
1227
|
+
export { f as $, b as A, se as B, R as C, v as D, N as E, k as F, de as G, oe as H, A as I, D as J, ne as K, O as L, S as M, ue as N, y as O, fe as P, te as Q, ae as R, I as S, ge as T, re as U, E as V, T as W, C as X, ce as Y, w as Z, me as _, Ee as a, P as b, Ce as c, Y as d, p as et, Z as f, z as g, G as h, we as i, x as j, _ as k, q as l, U as m, Oe as n, g as nt, Te as o, ye as p, le as q, ke as r, h as rt, Q as s, Ae as t, d as tt, X as u, he as v, L as w, F as x, pe as y, ie as z };
|
|
1128
1228
|
|
|
1129
|
-
//# sourceMappingURL=commentImages-
|
|
1229
|
+
//# sourceMappingURL=commentImages-Dm5Jv2vB.js.map
|