artalk 2.1.7 → 2.2.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/LICENSE +165 -0
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.es.js +337 -83
- package/dist/Artalk.iife.js +1 -1
- package/dist/Artalk.js +1 -1
- package/package.json +14 -13
- package/src/api/index.ts +35 -0
- package/src/api/request.ts +1 -0
- package/src/artalk.ts +18 -0
- package/src/components/editor.ts +120 -5
- package/src/components/layer.ts +19 -8
- package/src/components/list-lite.ts +19 -10
- package/src/components/list.ts +6 -3
- package/src/components/sidebar-layer.ts +24 -2
- package/src/context.ts +3 -0
- package/src/defaults.ts +2 -0
- package/src/lib/checker/admin-checker.ts +4 -4
- package/src/lib/checker/captcha-checker.ts +52 -6
- package/src/lib/checker/index.ts +65 -23
- package/src/lib/ui.ts +2 -1
- package/src/lib/utils.ts +56 -35
- package/src/style/comment.less +3 -0
- package/src/style/list.less +7 -4
- package/src/style/main.less +35 -0
- package/tsconfig.json +1 -16
- package/types/artalk-config.d.ts +6 -0
- package/types/artalk-data.d.ts +3 -0
- package/types/event.d.ts +2 -0
- package/types/vite-env.d.ts +0 -1
package/dist/Artalk.es.js
CHANGED
|
@@ -68,6 +68,7 @@ class Context {
|
|
|
68
68
|
__publicField(this, "conf");
|
|
69
69
|
__publicField(this, "user");
|
|
70
70
|
__publicField(this, "eventList", []);
|
|
71
|
+
__publicField(this, "markedInstance");
|
|
71
72
|
this.cid = +new Date();
|
|
72
73
|
this.$root = rootEl;
|
|
73
74
|
this.conf = conf;
|
|
@@ -102,6 +103,7 @@ const defaults$3 = {
|
|
|
102
103
|
vote: true,
|
|
103
104
|
voteDown: false,
|
|
104
105
|
uaBadge: true,
|
|
106
|
+
listSort: true,
|
|
105
107
|
pvEl: "#ArtalkPV",
|
|
106
108
|
flatMode: "auto",
|
|
107
109
|
maxNesting: 3,
|
|
@@ -118,6 +120,7 @@ const defaults$3 = {
|
|
|
118
120
|
content: 300,
|
|
119
121
|
children: 400
|
|
120
122
|
},
|
|
123
|
+
imgUpload: true,
|
|
121
124
|
reqTimeout: 15e3,
|
|
122
125
|
versionCheck: true
|
|
123
126
|
};
|
|
@@ -2654,37 +2657,36 @@ function versionCompare(a, b) {
|
|
|
2654
2657
|
}
|
|
2655
2658
|
return 0;
|
|
2656
2659
|
}
|
|
2657
|
-
|
|
2660
|
+
function initMarked(ctx) {
|
|
2661
|
+
const renderer = new marked$1.Renderer();
|
|
2662
|
+
const linkRenderer = renderer.link;
|
|
2663
|
+
renderer.link = (href, title, text) => {
|
|
2664
|
+
const localLink = href == null ? void 0 : href.startsWith(`${window.location.protocol}//${window.location.hostname}`);
|
|
2665
|
+
const html = linkRenderer.call(renderer, href, title, text);
|
|
2666
|
+
return html.replace(/^<a /, `<a target="_blank" ${!localLink ? `rel="noreferrer noopener nofollow"` : ""} `);
|
|
2667
|
+
};
|
|
2668
|
+
const nMarked = marked$1;
|
|
2669
|
+
marked$1.setOptions({
|
|
2670
|
+
renderer,
|
|
2671
|
+
highlight: (code) => hanabi(code),
|
|
2672
|
+
pedantic: false,
|
|
2673
|
+
gfm: true,
|
|
2674
|
+
breaks: true,
|
|
2675
|
+
smartLists: true,
|
|
2676
|
+
smartypants: true,
|
|
2677
|
+
xhtml: false,
|
|
2678
|
+
sanitize: true,
|
|
2679
|
+
sanitizer: (html) => insane_1(html, __spreadProps(__spreadValues({}, insane_1.defaults), {
|
|
2680
|
+
allowedAttributes: __spreadProps(__spreadValues({}, insane_1.defaults.allowedAttributes), {
|
|
2681
|
+
img: ["src", "atk-emoticon"]
|
|
2682
|
+
})
|
|
2683
|
+
})),
|
|
2684
|
+
silent: true
|
|
2685
|
+
});
|
|
2686
|
+
ctx.markedInstance = nMarked;
|
|
2687
|
+
}
|
|
2658
2688
|
function marked(ctx, src) {
|
|
2659
|
-
|
|
2660
|
-
const renderer = new marked$1.Renderer();
|
|
2661
|
-
const linkRenderer = renderer.link;
|
|
2662
|
-
renderer.link = (href, title, text) => {
|
|
2663
|
-
const localLink = href == null ? void 0 : href.startsWith(`${window.location.protocol}//${window.location.hostname}`);
|
|
2664
|
-
const html = linkRenderer.call(renderer, href, title, text);
|
|
2665
|
-
return html.replace(/^<a /, `<a target="_blank" ${!localLink ? `rel="noreferrer noopener nofollow"` : ""} `);
|
|
2666
|
-
};
|
|
2667
|
-
const nMarked = marked$1;
|
|
2668
|
-
marked$1.setOptions({
|
|
2669
|
-
renderer,
|
|
2670
|
-
highlight: (code) => hanabi(code),
|
|
2671
|
-
pedantic: false,
|
|
2672
|
-
gfm: true,
|
|
2673
|
-
breaks: true,
|
|
2674
|
-
smartLists: true,
|
|
2675
|
-
smartypants: true,
|
|
2676
|
-
xhtml: false,
|
|
2677
|
-
sanitize: true,
|
|
2678
|
-
sanitizer: (html) => insane_1(html, __spreadProps(__spreadValues({}, insane_1.defaults), {
|
|
2679
|
-
allowedAttributes: __spreadProps(__spreadValues({}, insane_1.defaults.allowedAttributes), {
|
|
2680
|
-
img: ["src", "atk-emoticon"]
|
|
2681
|
-
})
|
|
2682
|
-
})),
|
|
2683
|
-
silent: true
|
|
2684
|
-
});
|
|
2685
|
-
markedInstance = nMarked;
|
|
2686
|
-
}
|
|
2687
|
-
return markedInstance.parse(src);
|
|
2689
|
+
return ctx.markedInstance.parse(src);
|
|
2688
2690
|
}
|
|
2689
2691
|
function getCorrectUserAgent() {
|
|
2690
2692
|
return __async(this, null, function* () {
|
|
@@ -2710,7 +2712,19 @@ function getCorrectUserAgent() {
|
|
|
2710
2712
|
return uaRaw;
|
|
2711
2713
|
});
|
|
2712
2714
|
}
|
|
2713
|
-
function
|
|
2715
|
+
function isValidURL(urlRaw) {
|
|
2716
|
+
let url;
|
|
2717
|
+
try {
|
|
2718
|
+
url = new URL(urlRaw);
|
|
2719
|
+
} catch (_) {
|
|
2720
|
+
return false;
|
|
2721
|
+
}
|
|
2722
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
2723
|
+
}
|
|
2724
|
+
function getURLBasedOnApi(ctx, path) {
|
|
2725
|
+
return `${ctx.conf.server.replace(/\/api\/?$/, "")}/${path.replace(/^\//, "")}`;
|
|
2726
|
+
}
|
|
2727
|
+
function showLoading(parentElem, conf) {
|
|
2714
2728
|
if (parentElem instanceof Context)
|
|
2715
2729
|
parentElem = parentElem.$root;
|
|
2716
2730
|
let $loading = parentElem.querySelector(".atk-loading");
|
|
@@ -2720,6 +2734,8 @@ function showLoading(parentElem) {
|
|
|
2720
2734
|
<svg viewBox="25 25 50 50"><circle cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"></circle></svg>
|
|
2721
2735
|
</div>
|
|
2722
2736
|
</div>`);
|
|
2737
|
+
if (conf == null ? void 0 : conf.transparentBg)
|
|
2738
|
+
$loading.style.background = "transparent";
|
|
2723
2739
|
parentElem.appendChild($loading);
|
|
2724
2740
|
}
|
|
2725
2741
|
$loading.style.display = "";
|
|
@@ -2886,11 +2902,7 @@ const _Layer = class extends Component {
|
|
|
2886
2902
|
if (this.maskClickHideEnable)
|
|
2887
2903
|
this.hide();
|
|
2888
2904
|
};
|
|
2889
|
-
this.
|
|
2890
|
-
this.bodyStyleOrgPaddingRight = document.body.style.paddingRight;
|
|
2891
|
-
document.body.style.overflow = "hidden";
|
|
2892
|
-
const bpr = parseInt(window.getComputedStyle(document.body, null).getPropertyValue("padding-right"), 10);
|
|
2893
|
-
document.body.style.paddingRight = `${getScrollBarWidth() + bpr || 0}px`;
|
|
2905
|
+
this.pageBodyScrollBarHide();
|
|
2894
2906
|
}
|
|
2895
2907
|
hide() {
|
|
2896
2908
|
if (this.afterHide)
|
|
@@ -2899,8 +2911,7 @@ const _Layer = class extends Component {
|
|
|
2899
2911
|
this.$el.style.display = "none";
|
|
2900
2912
|
this.newActionTimer(() => {
|
|
2901
2913
|
this.$wrap.style.display = "none";
|
|
2902
|
-
|
|
2903
|
-
document.body.style.paddingRight = this.bodyStyleOrgPaddingRight;
|
|
2914
|
+
this.pageBodyScrollBarShow();
|
|
2904
2915
|
this.checkCleanLayer();
|
|
2905
2916
|
}, 450);
|
|
2906
2917
|
this.newActionTimer(() => {
|
|
@@ -2911,6 +2922,17 @@ const _Layer = class extends Component {
|
|
|
2911
2922
|
setMaskClickHide(enable) {
|
|
2912
2923
|
this.maskClickHideEnable = enable;
|
|
2913
2924
|
}
|
|
2925
|
+
pageBodyScrollBarHide() {
|
|
2926
|
+
this.bodyStyleOrgOverflow = document.body.style.overflow;
|
|
2927
|
+
this.bodyStyleOrgPaddingRight = document.body.style.paddingRight;
|
|
2928
|
+
document.body.style.overflow = "hidden";
|
|
2929
|
+
const bpr = parseInt(window.getComputedStyle(document.body, null).getPropertyValue("padding-right"), 10);
|
|
2930
|
+
document.body.style.paddingRight = `${getScrollBarWidth() + bpr || 0}px`;
|
|
2931
|
+
}
|
|
2932
|
+
pageBodyScrollBarShow() {
|
|
2933
|
+
document.body.style.overflow = this.bodyStyleOrgOverflow;
|
|
2934
|
+
document.body.style.paddingRight = this.bodyStyleOrgPaddingRight;
|
|
2935
|
+
}
|
|
2914
2936
|
newActionTimer(func, delay) {
|
|
2915
2937
|
const act = () => {
|
|
2916
2938
|
func();
|
|
@@ -2928,6 +2950,7 @@ const _Layer = class extends Component {
|
|
|
2928
2950
|
disposeNow() {
|
|
2929
2951
|
document.body.style.overflow = "";
|
|
2930
2952
|
this.$el.remove();
|
|
2953
|
+
this.pageBodyScrollBarShow();
|
|
2931
2954
|
this.checkCleanLayer();
|
|
2932
2955
|
}
|
|
2933
2956
|
dispose() {
|
|
@@ -3018,6 +3041,7 @@ function Fetch(ctx, input, init, timeout) {
|
|
|
3018
3041
|
json = yield new Promise((resolve, reject) => {
|
|
3019
3042
|
ctx.trigger("checker-captcha", {
|
|
3020
3043
|
imgData: json.data.img_data,
|
|
3044
|
+
iframe: json.data.iframe,
|
|
3021
3045
|
onSuccess: () => {
|
|
3022
3046
|
recall(resolve, reject);
|
|
3023
3047
|
},
|
|
@@ -3182,6 +3206,12 @@ class Api {
|
|
|
3182
3206
|
}
|
|
3183
3207
|
};
|
|
3184
3208
|
}
|
|
3209
|
+
loginStatus() {
|
|
3210
|
+
return __async(this, null, function* () {
|
|
3211
|
+
const data = yield GET(this.ctx, `${this.baseURL}/login-status`);
|
|
3212
|
+
return data || { is_login: false };
|
|
3213
|
+
});
|
|
3214
|
+
}
|
|
3185
3215
|
pageGet(siteName, offset, limit) {
|
|
3186
3216
|
return __async(this, null, function* () {
|
|
3187
3217
|
const params = {
|
|
@@ -3300,6 +3330,25 @@ class Api {
|
|
|
3300
3330
|
return p.pv;
|
|
3301
3331
|
});
|
|
3302
3332
|
}
|
|
3333
|
+
imgUpload(file) {
|
|
3334
|
+
return __async(this, null, function* () {
|
|
3335
|
+
const params = {
|
|
3336
|
+
name: this.ctx.user.data.nick,
|
|
3337
|
+
email: this.ctx.user.data.email,
|
|
3338
|
+
page_key: this.ctx.conf.pageKey
|
|
3339
|
+
};
|
|
3340
|
+
if (this.ctx.conf.site)
|
|
3341
|
+
params.site_name = this.ctx.conf.site;
|
|
3342
|
+
const form = ToFormData(params);
|
|
3343
|
+
form.set("file", file);
|
|
3344
|
+
const init = {
|
|
3345
|
+
method: "POST",
|
|
3346
|
+
body: form
|
|
3347
|
+
};
|
|
3348
|
+
const json = yield Fetch(this.ctx, `${this.baseURL}/img-upload`, init);
|
|
3349
|
+
return json.data || {};
|
|
3350
|
+
});
|
|
3351
|
+
}
|
|
3303
3352
|
captchaGet() {
|
|
3304
3353
|
return __async(this, null, function* () {
|
|
3305
3354
|
const data = yield GET(this.ctx, `${this.baseURL}/captcha/refresh`);
|
|
@@ -3312,13 +3361,64 @@ class Api {
|
|
|
3312
3361
|
return data.img_data || "";
|
|
3313
3362
|
});
|
|
3314
3363
|
}
|
|
3364
|
+
captchaStatus() {
|
|
3365
|
+
return __async(this, null, function* () {
|
|
3366
|
+
const data = yield GET(this.ctx, `${this.baseURL}/captcha/status`);
|
|
3367
|
+
return data || { is_pass: false };
|
|
3368
|
+
});
|
|
3369
|
+
}
|
|
3315
3370
|
}
|
|
3316
3371
|
const CaptchaChecker = {
|
|
3317
|
-
request(that, inputVal) {
|
|
3372
|
+
request(that, ctx, inputVal) {
|
|
3318
3373
|
return new Api(that.ctx).captchaCheck(inputVal);
|
|
3319
3374
|
},
|
|
3320
|
-
body(that) {
|
|
3321
|
-
|
|
3375
|
+
body(that, ctx) {
|
|
3376
|
+
if (that.captchaConf.iframe) {
|
|
3377
|
+
const $iframeWrap = createElement(`<div class="atk-checker-iframe-wrap"></div>`);
|
|
3378
|
+
const $iframe = createElement(`<iframe class="atk-fade-in"></iframe>`);
|
|
3379
|
+
$iframe.style.display = "none";
|
|
3380
|
+
showLoading($iframeWrap, { transparentBg: true });
|
|
3381
|
+
$iframe.src = `${that.ctx.conf.server}/captcha/get`;
|
|
3382
|
+
$iframe.onload = () => {
|
|
3383
|
+
$iframe.style.display = "";
|
|
3384
|
+
hideLoading($iframeWrap);
|
|
3385
|
+
};
|
|
3386
|
+
$iframeWrap.append($iframe);
|
|
3387
|
+
const $closeBtn = createElement(`<div class="atk-close-btn"><i class="atk-icon atk-icon-close"></i></div>`);
|
|
3388
|
+
$iframeWrap.append($closeBtn);
|
|
3389
|
+
ctx.hideInteractInput();
|
|
3390
|
+
let stop = false;
|
|
3391
|
+
const sleep = (ms) => new Promise((resolve) => {
|
|
3392
|
+
window.setTimeout(() => {
|
|
3393
|
+
resolve(null);
|
|
3394
|
+
}, ms);
|
|
3395
|
+
});
|
|
3396
|
+
(function queryStatus() {
|
|
3397
|
+
return __async(this, null, function* () {
|
|
3398
|
+
yield sleep(1e3);
|
|
3399
|
+
if (stop)
|
|
3400
|
+
return;
|
|
3401
|
+
let isPass = false;
|
|
3402
|
+
try {
|
|
3403
|
+
const resp = yield new Api(that.ctx).captchaStatus();
|
|
3404
|
+
isPass = resp.is_pass;
|
|
3405
|
+
} catch (e) {
|
|
3406
|
+
isPass = false;
|
|
3407
|
+
}
|
|
3408
|
+
if (isPass) {
|
|
3409
|
+
ctx.triggerSuccess();
|
|
3410
|
+
} else {
|
|
3411
|
+
queryStatus();
|
|
3412
|
+
}
|
|
3413
|
+
});
|
|
3414
|
+
})();
|
|
3415
|
+
$closeBtn.onclick = () => {
|
|
3416
|
+
stop = true;
|
|
3417
|
+
ctx.cancel();
|
|
3418
|
+
};
|
|
3419
|
+
return $iframeWrap;
|
|
3420
|
+
}
|
|
3421
|
+
const elem = createElement(`<span><img class="atk-captcha-img" src="${that.captchaConf.imgData || ""}" alt="\u9A8C\u8BC1\u7801">\u6572\u5165\u9A8C\u8BC1\u7801\u7EE7\u7EED\uFF1A</span>`);
|
|
3322
3422
|
elem.querySelector(".atk-captcha-img").onclick = () => {
|
|
3323
3423
|
const imgEl = elem.querySelector(".atk-captcha-img");
|
|
3324
3424
|
new Api(that.ctx).captchaGet().then((imgData) => {
|
|
@@ -3329,16 +3429,16 @@ const CaptchaChecker = {
|
|
|
3329
3429
|
};
|
|
3330
3430
|
return elem;
|
|
3331
3431
|
},
|
|
3332
|
-
onSuccess(that, data, inputVal, formEl) {
|
|
3333
|
-
that.
|
|
3432
|
+
onSuccess(that, ctx, data, inputVal, formEl) {
|
|
3433
|
+
that.captchaConf.val = inputVal;
|
|
3334
3434
|
},
|
|
3335
|
-
onError(that, err, inputVal, formEl) {
|
|
3435
|
+
onError(that, ctx, err, inputVal, formEl) {
|
|
3336
3436
|
formEl.querySelector(".atk-captcha-img").click();
|
|
3337
3437
|
}
|
|
3338
3438
|
};
|
|
3339
3439
|
const AdminChecker = {
|
|
3340
3440
|
inputType: "password",
|
|
3341
|
-
request(that, inputVal) {
|
|
3441
|
+
request(that, ctx, inputVal) {
|
|
3342
3442
|
const data = {
|
|
3343
3443
|
name: that.ctx.user.data.nick,
|
|
3344
3444
|
email: that.ctx.user.data.email,
|
|
@@ -3346,33 +3446,33 @@ const AdminChecker = {
|
|
|
3346
3446
|
};
|
|
3347
3447
|
return new Api(that.ctx).login(data.name, data.email, data.password);
|
|
3348
3448
|
},
|
|
3349
|
-
body() {
|
|
3449
|
+
body(that, ctx) {
|
|
3350
3450
|
return createElement("<span>\u6572\u5165\u5BC6\u7801\u6765\u9A8C\u8BC1\u7BA1\u7406\u5458\u8EAB\u4EFD\uFF1A</span>");
|
|
3351
3451
|
},
|
|
3352
|
-
onSuccess(that, userToken, inputVal, formEl) {
|
|
3452
|
+
onSuccess(that, ctx, userToken, inputVal, formEl) {
|
|
3353
3453
|
that.ctx.user.data.isAdmin = true;
|
|
3354
3454
|
that.ctx.user.data.token = userToken;
|
|
3355
3455
|
that.ctx.user.save();
|
|
3356
3456
|
that.ctx.trigger("user-changed", that.ctx.user.data);
|
|
3357
3457
|
that.ctx.trigger("list-reload");
|
|
3358
3458
|
},
|
|
3359
|
-
onError(that, err, inputVal, formEl) {
|
|
3459
|
+
onError(that, ctx, err, inputVal, formEl) {
|
|
3360
3460
|
}
|
|
3361
3461
|
};
|
|
3362
3462
|
class CheckerLauncher {
|
|
3363
3463
|
constructor(ctx) {
|
|
3364
3464
|
__publicField(this, "ctx");
|
|
3365
3465
|
__publicField(this, "launched", []);
|
|
3366
|
-
__publicField(this, "
|
|
3367
|
-
__publicField(this, "submitCaptchaImgData");
|
|
3466
|
+
__publicField(this, "captchaConf", {});
|
|
3368
3467
|
this.ctx = ctx;
|
|
3369
3468
|
this.initEventBind();
|
|
3370
3469
|
}
|
|
3371
3470
|
initEventBind() {
|
|
3372
3471
|
this.ctx.on("checker-captcha", (conf) => {
|
|
3373
|
-
if (conf.imgData)
|
|
3374
|
-
this.
|
|
3375
|
-
|
|
3472
|
+
if (conf.imgData)
|
|
3473
|
+
this.captchaConf.imgData = conf.imgData;
|
|
3474
|
+
if (conf.iframe)
|
|
3475
|
+
this.captchaConf.iframe = conf.iframe;
|
|
3376
3476
|
this.fire(CaptchaChecker, conf);
|
|
3377
3477
|
});
|
|
3378
3478
|
this.ctx.on("checker-admin", (conf) => {
|
|
@@ -3386,12 +3486,31 @@ class CheckerLauncher {
|
|
|
3386
3486
|
const layer = new Layer(this.ctx, `checker-${new Date().getTime()}`);
|
|
3387
3487
|
layer.setMaskClickHide(false);
|
|
3388
3488
|
layer.show();
|
|
3489
|
+
let hideInteractInput = false;
|
|
3490
|
+
const checkerCtx = {
|
|
3491
|
+
getLayer: () => layer,
|
|
3492
|
+
hideInteractInput: () => {
|
|
3493
|
+
hideInteractInput = true;
|
|
3494
|
+
},
|
|
3495
|
+
triggerSuccess: () => {
|
|
3496
|
+
this.close(checker, layer);
|
|
3497
|
+
if (checker.onSuccess)
|
|
3498
|
+
checker.onSuccess(this, checkerCtx, "", "", formEl);
|
|
3499
|
+
if (payload.onSuccess)
|
|
3500
|
+
payload.onSuccess("", dialog.$el);
|
|
3501
|
+
},
|
|
3502
|
+
cancel: () => {
|
|
3503
|
+
this.close(checker, layer);
|
|
3504
|
+
if (payload.onCancel)
|
|
3505
|
+
payload.onCancel();
|
|
3506
|
+
}
|
|
3507
|
+
};
|
|
3389
3508
|
const formEl = createElement();
|
|
3390
|
-
formEl.appendChild(checker.body(this));
|
|
3391
|
-
const input = createElement(`<input id="check" type="${checker.inputType || "text"}" autocomplete="off" required placeholder="">`);
|
|
3392
|
-
formEl.appendChild(input);
|
|
3393
|
-
setTimeout(() => input.focus(), 80);
|
|
3394
|
-
input.onkeyup = (evt) => {
|
|
3509
|
+
formEl.appendChild(checker.body(this, checkerCtx));
|
|
3510
|
+
const $input = createElement(`<input id="check" type="${checker.inputType || "text"}" autocomplete="off" required placeholder="">`);
|
|
3511
|
+
formEl.appendChild($input);
|
|
3512
|
+
setTimeout(() => $input.focus(), 80);
|
|
3513
|
+
$input.onkeyup = (evt) => {
|
|
3395
3514
|
if (evt.key === "Enter" || evt.keyCode === 13) {
|
|
3396
3515
|
evt.preventDefault();
|
|
3397
3516
|
layer.getEl().querySelector('button[data-action="confirm"]').click();
|
|
@@ -3400,7 +3519,7 @@ class CheckerLauncher {
|
|
|
3400
3519
|
let btnTextOrg;
|
|
3401
3520
|
const dialog = new Dialog(formEl);
|
|
3402
3521
|
dialog.setYes((btnEl) => {
|
|
3403
|
-
const inputVal = input.value.trim();
|
|
3522
|
+
const inputVal = $input.value.trim();
|
|
3404
3523
|
if (!btnTextOrg)
|
|
3405
3524
|
btnTextOrg = btnEl.innerText;
|
|
3406
3525
|
const btnTextSet = (btnText) => {
|
|
@@ -3412,18 +3531,18 @@ class CheckerLauncher {
|
|
|
3412
3531
|
btnEl.classList.remove("error");
|
|
3413
3532
|
};
|
|
3414
3533
|
btnEl.innerText = "\u52A0\u8F7D\u4E2D...";
|
|
3415
|
-
checker.request(this, inputVal).then((data) => {
|
|
3416
|
-
this.
|
|
3534
|
+
checker.request(this, checkerCtx, inputVal).then((data) => {
|
|
3535
|
+
this.close(checker, layer);
|
|
3417
3536
|
if (checker.onSuccess)
|
|
3418
|
-
checker.onSuccess(this, data, inputVal, formEl);
|
|
3537
|
+
checker.onSuccess(this, checkerCtx, data, inputVal, formEl);
|
|
3419
3538
|
if (payload.onSuccess)
|
|
3420
3539
|
payload.onSuccess(inputVal, dialog.$el);
|
|
3421
3540
|
}).catch((err) => {
|
|
3422
3541
|
btnTextSet(String(err.msg || String(err)));
|
|
3423
3542
|
if (checker.onError)
|
|
3424
|
-
checker.onError(this, err, inputVal, formEl);
|
|
3543
|
+
checker.onError(this, checkerCtx, err, inputVal, formEl);
|
|
3425
3544
|
const tf = setTimeout(() => btnTextRestore(), 3e3);
|
|
3426
|
-
input.onfocus = () => {
|
|
3545
|
+
$input.onfocus = () => {
|
|
3427
3546
|
btnTextRestore();
|
|
3428
3547
|
clearTimeout(tf);
|
|
3429
3548
|
};
|
|
@@ -3431,16 +3550,20 @@ class CheckerLauncher {
|
|
|
3431
3550
|
return false;
|
|
3432
3551
|
});
|
|
3433
3552
|
dialog.setNo(() => {
|
|
3434
|
-
this.
|
|
3553
|
+
this.close(checker, layer);
|
|
3435
3554
|
if (payload.onCancel)
|
|
3436
3555
|
payload.onCancel();
|
|
3437
3556
|
return false;
|
|
3438
3557
|
});
|
|
3558
|
+
if (hideInteractInput) {
|
|
3559
|
+
$input.style.display = "none";
|
|
3560
|
+
dialog.$el.querySelector(".atk-layer-dialog-actions").style.display = "none";
|
|
3561
|
+
}
|
|
3439
3562
|
layer.getEl().append(dialog.$el);
|
|
3440
3563
|
if (payload.onMount)
|
|
3441
3564
|
payload.onMount(dialog.$el);
|
|
3442
3565
|
}
|
|
3443
|
-
|
|
3566
|
+
close(checker, layer) {
|
|
3444
3567
|
layer.disposeNow();
|
|
3445
3568
|
this.launched = this.launched.filter((c) => c !== checker);
|
|
3446
3569
|
}
|
|
@@ -3723,6 +3846,7 @@ class Editor extends Component {
|
|
|
3723
3846
|
__publicField(this, "$plugWrap");
|
|
3724
3847
|
__publicField(this, "$bottom");
|
|
3725
3848
|
__publicField(this, "$plugBtnWrap");
|
|
3849
|
+
__publicField(this, "$imgUploadBtn");
|
|
3726
3850
|
__publicField(this, "$submitBtn");
|
|
3727
3851
|
__publicField(this, "$notifyWrap");
|
|
3728
3852
|
__publicField(this, "replyComment", null);
|
|
@@ -3733,6 +3857,7 @@ class Editor extends Component {
|
|
|
3733
3857
|
abortFunc: null
|
|
3734
3858
|
});
|
|
3735
3859
|
__publicField(this, "openedPlugName", null);
|
|
3860
|
+
__publicField(this, "allowImgExts", ["png", "jpg", "jpeg", "gif", "bmp", "svg", "webp"]);
|
|
3736
3861
|
this.$el = createElement(EditorHTML);
|
|
3737
3862
|
this.$header = this.$el.querySelector(".atk-header");
|
|
3738
3863
|
this.$textareaWrap = this.$el.querySelector(".atk-textarea-wrap");
|
|
@@ -3756,6 +3881,7 @@ class Editor extends Component {
|
|
|
3756
3881
|
this.ctx.on("editor-notify", (f) => this.showNotify(f.msg, f.type));
|
|
3757
3882
|
this.ctx.on("editor-travel", ($el) => this.travel($el));
|
|
3758
3883
|
this.ctx.on("editor-travel-back", () => this.travelBack());
|
|
3884
|
+
this.ctx.on("conf-updated", () => this.refreshUploadBtn());
|
|
3759
3885
|
}
|
|
3760
3886
|
get user() {
|
|
3761
3887
|
return this.ctx.user;
|
|
@@ -3854,7 +3980,7 @@ class Editor extends Component {
|
|
|
3854
3980
|
this.openedPlugName = null;
|
|
3855
3981
|
this.$plugBtnWrap.innerHTML = "";
|
|
3856
3982
|
this.LOADABLE_PLUG_LIST.forEach((PlugObj) => {
|
|
3857
|
-
const btnElem = createElement(`<span class="atk-plug-btn">${PlugObj.BtnHTML}</span>`);
|
|
3983
|
+
const btnElem = createElement(`<span class="atk-plug-btn" data-plug-name="${PlugObj.Name}">${PlugObj.BtnHTML}</span>`);
|
|
3858
3984
|
this.$plugBtnWrap.appendChild(btnElem);
|
|
3859
3985
|
btnElem.addEventListener("click", () => {
|
|
3860
3986
|
let plug = this.plugList[PlugObj.Name];
|
|
@@ -3890,12 +4016,98 @@ class Editor extends Component {
|
|
|
3890
4016
|
btnElem.classList.add("active");
|
|
3891
4017
|
});
|
|
3892
4018
|
});
|
|
4019
|
+
this.initImgUpload();
|
|
3893
4020
|
}
|
|
3894
4021
|
closePlug() {
|
|
3895
4022
|
this.$plugWrap.innerHTML = "";
|
|
3896
4023
|
this.$plugWrap.style.display = "none";
|
|
3897
4024
|
this.openedPlugName = null;
|
|
3898
4025
|
}
|
|
4026
|
+
initImgUpload() {
|
|
4027
|
+
this.$imgUploadBtn = createElement(`<span class="atk-plug-btn">\u56FE\u7247</span>`);
|
|
4028
|
+
this.$plugBtnWrap.querySelector('[data-plug-name="preview"]').before(this.$imgUploadBtn);
|
|
4029
|
+
this.$imgUploadBtn.onclick = () => {
|
|
4030
|
+
const $input = document.createElement("input");
|
|
4031
|
+
$input.type = "file";
|
|
4032
|
+
$input.accept = this.allowImgExts.map((o) => `.${o}`).join(",");
|
|
4033
|
+
$input.onchange = () => {
|
|
4034
|
+
(() => __async(this, null, function* () {
|
|
4035
|
+
if (!$input.files || $input.files.length === 0)
|
|
4036
|
+
return;
|
|
4037
|
+
const file = $input.files[0];
|
|
4038
|
+
this.uploadImg(file);
|
|
4039
|
+
}))();
|
|
4040
|
+
};
|
|
4041
|
+
$input.click();
|
|
4042
|
+
};
|
|
4043
|
+
const uploadFromFileList = (files) => {
|
|
4044
|
+
if (!files)
|
|
4045
|
+
return;
|
|
4046
|
+
for (let i = 0; i < files.length; i++) {
|
|
4047
|
+
const file = files[i];
|
|
4048
|
+
this.uploadImg(file);
|
|
4049
|
+
}
|
|
4050
|
+
};
|
|
4051
|
+
this.$textarea.addEventListener("dragover", (evt) => {
|
|
4052
|
+
evt.stopPropagation();
|
|
4053
|
+
evt.preventDefault();
|
|
4054
|
+
});
|
|
4055
|
+
this.$textarea.addEventListener("drop", (evt) => {
|
|
4056
|
+
var _a;
|
|
4057
|
+
const files = (_a = evt.dataTransfer) == null ? void 0 : _a.files;
|
|
4058
|
+
if (files == null ? void 0 : files.length) {
|
|
4059
|
+
evt.preventDefault();
|
|
4060
|
+
uploadFromFileList(files);
|
|
4061
|
+
}
|
|
4062
|
+
});
|
|
4063
|
+
this.$textarea.addEventListener("paste", (evt) => {
|
|
4064
|
+
var _a;
|
|
4065
|
+
const files = (_a = evt.clipboardData) == null ? void 0 : _a.files;
|
|
4066
|
+
if (files == null ? void 0 : files.length) {
|
|
4067
|
+
evt.preventDefault();
|
|
4068
|
+
uploadFromFileList(files);
|
|
4069
|
+
}
|
|
4070
|
+
});
|
|
4071
|
+
}
|
|
4072
|
+
refreshUploadBtn() {
|
|
4073
|
+
if (!this.$imgUploadBtn)
|
|
4074
|
+
return;
|
|
4075
|
+
if (!this.ctx.conf.imgUpload) {
|
|
4076
|
+
this.$imgUploadBtn.setAttribute("atk-only-admin-show", "");
|
|
4077
|
+
this.ctx.trigger("check-admin-show-el");
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
uploadImg(file) {
|
|
4081
|
+
return __async(this, null, function* () {
|
|
4082
|
+
const fileExt = /[^.]+$/.exec(file.name);
|
|
4083
|
+
if (!fileExt || !this.allowImgExts.includes(fileExt[0]))
|
|
4084
|
+
return;
|
|
4085
|
+
if (!this.ctx.user.checkHasBasicUserInfo()) {
|
|
4086
|
+
this.showNotify("\u586B\u5165\u4F60\u7684\u540D\u5B57\u90AE\u7BB1\u624D\u80FD\u4E0A\u4F20\u54E6", "w");
|
|
4087
|
+
return;
|
|
4088
|
+
}
|
|
4089
|
+
let insertPrefix = "\n";
|
|
4090
|
+
if (this.$textarea.value.trim() === "")
|
|
4091
|
+
insertPrefix = "";
|
|
4092
|
+
const uploadPlaceholderTxt = `${insertPrefix}`;
|
|
4093
|
+
this.insertContent(uploadPlaceholderTxt);
|
|
4094
|
+
let resp;
|
|
4095
|
+
try {
|
|
4096
|
+
resp = yield new Api(this.ctx).imgUpload(file);
|
|
4097
|
+
} catch (err) {
|
|
4098
|
+
console.error(err);
|
|
4099
|
+
this.showNotify(`\u56FE\u7247\u4E0A\u4F20\u5931\u8D25\uFF0C${err.msg}`, "e");
|
|
4100
|
+
}
|
|
4101
|
+
if (!!resp && resp.img_url) {
|
|
4102
|
+
let imgURL = resp.img_url;
|
|
4103
|
+
if (!isValidURL(imgURL))
|
|
4104
|
+
imgURL = getURLBasedOnApi(this.ctx, imgURL);
|
|
4105
|
+
this.setContent(this.$textarea.value.replace(uploadPlaceholderTxt, `${insertPrefix}`));
|
|
4106
|
+
} else {
|
|
4107
|
+
this.setContent(this.$textarea.value.replace(uploadPlaceholderTxt, ""));
|
|
4108
|
+
}
|
|
4109
|
+
});
|
|
4110
|
+
}
|
|
3899
4111
|
insertContent(val) {
|
|
3900
4112
|
if (document.selection) {
|
|
3901
4113
|
this.$textarea.focus();
|
|
@@ -3927,7 +4139,7 @@ class Editor extends Component {
|
|
|
3927
4139
|
this.setContent("");
|
|
3928
4140
|
this.cancelReply();
|
|
3929
4141
|
}
|
|
3930
|
-
|
|
4142
|
+
getFinalContent() {
|
|
3931
4143
|
let content = this.getContentOriginal();
|
|
3932
4144
|
if (this.plugList && this.plugList.emoticons) {
|
|
3933
4145
|
const emoticonsPlug2 = this.plugList.emoticons;
|
|
@@ -3939,7 +4151,7 @@ class Editor extends Component {
|
|
|
3939
4151
|
return this.$textarea.value || "";
|
|
3940
4152
|
}
|
|
3941
4153
|
getContentMarked() {
|
|
3942
|
-
return marked(this.ctx, this.
|
|
4154
|
+
return marked(this.ctx, this.getFinalContent());
|
|
3943
4155
|
}
|
|
3944
4156
|
initBottomPart() {
|
|
3945
4157
|
this.initReply();
|
|
@@ -3988,7 +4200,7 @@ class Editor extends Component {
|
|
|
3988
4200
|
}
|
|
3989
4201
|
submit() {
|
|
3990
4202
|
return __async(this, null, function* () {
|
|
3991
|
-
if (this.
|
|
4203
|
+
if (this.getFinalContent().trim() === "") {
|
|
3992
4204
|
this.$textarea.focus();
|
|
3993
4205
|
return;
|
|
3994
4206
|
}
|
|
@@ -3996,7 +4208,7 @@ class Editor extends Component {
|
|
|
3996
4208
|
showLoading(this.$el);
|
|
3997
4209
|
try {
|
|
3998
4210
|
const nComment = yield new Api(this.ctx).add({
|
|
3999
|
-
content: this.
|
|
4211
|
+
content: this.getFinalContent(),
|
|
4000
4212
|
nick: this.user.data.nick,
|
|
4001
4213
|
email: this.user.data.email,
|
|
4002
4214
|
link: this.user.data.link,
|
|
@@ -5071,6 +5283,7 @@ class ReadMoreBtn {
|
|
|
5071
5283
|
this.hide();
|
|
5072
5284
|
}
|
|
5073
5285
|
}
|
|
5286
|
+
const backendMinVersion = "2.1.1";
|
|
5074
5287
|
class ListLite extends Component {
|
|
5075
5288
|
constructor(ctx) {
|
|
5076
5289
|
super(ctx);
|
|
@@ -5152,17 +5365,25 @@ class ListLite extends Component {
|
|
|
5152
5365
|
});
|
|
5153
5366
|
}
|
|
5154
5367
|
onLoad(data, offset) {
|
|
5368
|
+
var _a, _b;
|
|
5155
5369
|
if (this.pageMode === "pagination") {
|
|
5156
5370
|
this.clearAllComments();
|
|
5157
5371
|
}
|
|
5158
5372
|
this.data = data;
|
|
5159
|
-
|
|
5373
|
+
const feMinVersion = ((_a = data.api_version) == null ? void 0 : _a.fe_min_version) || "0.0.0";
|
|
5374
|
+
if (this.ctx.conf.versionCheck && this.versionCheck("\u524D\u7AEF", feMinVersion, "2.2.0"))
|
|
5375
|
+
return;
|
|
5376
|
+
if (this.ctx.conf.versionCheck && this.versionCheck("\u540E\u7AEF", backendMinVersion, (_b = data.api_version) == null ? void 0 : _b.version))
|
|
5160
5377
|
return;
|
|
5378
|
+
if (data.conf && typeof data.conf.img_upload === "boolean") {
|
|
5379
|
+
this.ctx.conf.imgUpload = data.conf.img_upload;
|
|
5380
|
+
}
|
|
5161
5381
|
this.importComments(data.comments);
|
|
5162
5382
|
this.refreshPagination(offset, this.flatMode ? data.total : data.total_roots);
|
|
5163
5383
|
this.refreshUI();
|
|
5164
5384
|
this.ctx.trigger("unread-update", { notifies: data.unread || [] });
|
|
5165
5385
|
this.ctx.trigger("comments-loaded");
|
|
5386
|
+
this.ctx.trigger("conf-updated");
|
|
5166
5387
|
if (this.onAfterLoad)
|
|
5167
5388
|
this.onAfterLoad(data);
|
|
5168
5389
|
}
|
|
@@ -5427,19 +5648,19 @@ class ListLite extends Component {
|
|
|
5427
5648
|
});
|
|
5428
5649
|
}
|
|
5429
5650
|
}
|
|
5430
|
-
versionCheck(
|
|
5431
|
-
const
|
|
5432
|
-
const needUpdate = versionCompare(needVersion, "2.1.7") === 1;
|
|
5651
|
+
versionCheck(name, needVersion, curtVersion) {
|
|
5652
|
+
const needUpdate = versionCompare(needVersion, curtVersion) === 1;
|
|
5433
5653
|
if (needUpdate) {
|
|
5434
|
-
const errEl = createElement(`<div
|
|
5654
|
+
const errEl = createElement(`<div>Artalk ${name}\u7248\u672C\u5DF2\u8FC7\u65F6\uFF0C\u8BF7\u66F4\u65B0\u4EE5\u83B7\u5F97\u5B8C\u6574\u4F53\u9A8C<br/>\u5982\u679C\u4F60\u662F\u7BA1\u7406\u5458\uFF0C\u8BF7\u524D\u5F80 \u201C<a href="https://artalk.js.org/" target="_blank">\u5B98\u65B9\u6587\u6863</a>\u201D \u83B7\u5F97\u5E2E\u52A9<br/><br/><span style="color: var(--at-color-meta);">\u5F53\u524D${name}\u7248\u672C ${curtVersion}\uFF0C\u9700\u6C42\u7248\u672C >= ${needVersion}</span><br/><br/></div>`);
|
|
5435
5655
|
const ignoreBtn = createElement('<span style="cursor:pointer;">\u5FFD\u7565</span>');
|
|
5436
5656
|
ignoreBtn.onclick = () => {
|
|
5437
|
-
setError(this.
|
|
5657
|
+
setError(this.$el.parentElement, null);
|
|
5438
5658
|
this.ctx.conf.versionCheck = false;
|
|
5659
|
+
this.ctx.trigger("conf-updated");
|
|
5439
5660
|
this.fetchComments(0);
|
|
5440
5661
|
};
|
|
5441
5662
|
errEl.append(ignoreBtn);
|
|
5442
|
-
setError(this.
|
|
5663
|
+
setError(this.$el.parentElement, errEl, '<span class="atk-warn-title">Artalk Warn</span>');
|
|
5443
5664
|
}
|
|
5444
5665
|
return needUpdate;
|
|
5445
5666
|
}
|
|
@@ -5469,8 +5690,10 @@ class List extends ListLite {
|
|
|
5469
5690
|
this.repositionAt = this.$el;
|
|
5470
5691
|
this.initListActionBtn();
|
|
5471
5692
|
this.$commentCount = this.$el.querySelector(".atk-comment-count");
|
|
5472
|
-
this.
|
|
5473
|
-
|
|
5693
|
+
if (this.ctx.conf.listSort) {
|
|
5694
|
+
this.initDropdown();
|
|
5695
|
+
}
|
|
5696
|
+
this.$el.querySelector(".atk-copyright").innerHTML = `Powered By <a href="https://artalk.js.org" target="_blank" title="Artalk v${"2.2.0"}">Artalk</a>`;
|
|
5474
5697
|
this.ctx.on("list-reload", () => this.fetchComments(0));
|
|
5475
5698
|
this.ctx.on("list-refresh-ui", () => this.refreshUI());
|
|
5476
5699
|
this.ctx.on("list-import", (data) => this.importComments(data));
|
|
@@ -5576,7 +5799,7 @@ class List extends ListLite {
|
|
|
5576
5799
|
initDropdown() {
|
|
5577
5800
|
this.$dropdownWrap = this.$commentCount;
|
|
5578
5801
|
this.$commentCount.classList.add("atk-dropdown-wrap");
|
|
5579
|
-
this.$
|
|
5802
|
+
this.$dropdownWrap.append(createElement(`<span class="atk-arrow-down-icon"></span>`));
|
|
5580
5803
|
const reloadUseParamsEditor = (func) => {
|
|
5581
5804
|
this.paramsEditor = (p) => {
|
|
5582
5805
|
func(p);
|
|
@@ -5676,11 +5899,31 @@ class SidebarLayer extends Component {
|
|
|
5676
5899
|
this.$el.style.transform = "translate(0, 0)";
|
|
5677
5900
|
}, 20);
|
|
5678
5901
|
if (this.firstShow) {
|
|
5902
|
+
if (this.ctx.user.data.isAdmin) {
|
|
5903
|
+
const resp = yield new Api(this.ctx).loginStatus();
|
|
5904
|
+
if (!resp.is_login) {
|
|
5905
|
+
yield new Promise((resolve, reject) => {
|
|
5906
|
+
this.ctx.trigger("checker-admin", {
|
|
5907
|
+
onSuccess: () => {
|
|
5908
|
+
resolve(null);
|
|
5909
|
+
setTimeout(() => {
|
|
5910
|
+
this.show();
|
|
5911
|
+
}, 500);
|
|
5912
|
+
},
|
|
5913
|
+
onCancel: () => {
|
|
5914
|
+
var _a;
|
|
5915
|
+
(_a = this.layer) == null ? void 0 : _a.hide();
|
|
5916
|
+
}
|
|
5917
|
+
});
|
|
5918
|
+
});
|
|
5919
|
+
}
|
|
5920
|
+
}
|
|
5679
5921
|
this.$iframeWrap.innerHTML = "";
|
|
5680
5922
|
this.$iframe = createElement("<iframe></iframe>");
|
|
5681
|
-
const baseURL =
|
|
5923
|
+
const baseURL = getURLBasedOnApi(this.ctx, "sidebar/");
|
|
5682
5924
|
const userData = encodeURIComponent(JSON.stringify(this.ctx.user.data));
|
|
5683
|
-
|
|
5925
|
+
const location = window.location;
|
|
5926
|
+
this.iframeLoad(`${baseURL}?pageKey=${encodeURIComponent(this.conf.pageKey)}&site=${encodeURIComponent(this.conf.site || "")}&user=${userData}&referer=${encodeURIComponent(`${location.protocol}//${location.host}${location.pathname}`)}${this.conf.darkMode ? `&darkMode=1` : ``}`);
|
|
5684
5927
|
this.$iframeWrap.append(this.$iframe);
|
|
5685
5928
|
this.firstShow = false;
|
|
5686
5929
|
} else {
|
|
@@ -5760,6 +6003,7 @@ const _Artalk = class {
|
|
|
5760
6003
|
this.$root.innerHTML = "";
|
|
5761
6004
|
this.initDarkMode();
|
|
5762
6005
|
this.checkerLauncher = new CheckerLauncher(this.ctx);
|
|
6006
|
+
initMarked(this.ctx);
|
|
5763
6007
|
this.editor = new Editor(this.ctx);
|
|
5764
6008
|
this.$root.appendChild(this.editor.$el);
|
|
5765
6009
|
this.list = new List(this.ctx);
|
|
@@ -5769,6 +6013,11 @@ const _Artalk = class {
|
|
|
5769
6013
|
this.list.fetchComments(0);
|
|
5770
6014
|
this.initEventBind();
|
|
5771
6015
|
this.initPV();
|
|
6016
|
+
_Artalk.Plugins.forEach((plugin) => {
|
|
6017
|
+
if (typeof plugin === "function") {
|
|
6018
|
+
plugin(this.ctx);
|
|
6019
|
+
}
|
|
6020
|
+
});
|
|
5772
6021
|
}
|
|
5773
6022
|
initEventBind() {
|
|
5774
6023
|
window.addEventListener("hashchange", () => {
|
|
@@ -5816,6 +6065,7 @@ const _Artalk = class {
|
|
|
5816
6065
|
}
|
|
5817
6066
|
setDarkMode(darkMode) {
|
|
5818
6067
|
this.ctx.conf.darkMode = darkMode;
|
|
6068
|
+
this.ctx.trigger("conf-updated");
|
|
5819
6069
|
this.initDarkMode();
|
|
5820
6070
|
}
|
|
5821
6071
|
initPV() {
|
|
@@ -5838,7 +6088,11 @@ const _Artalk = class {
|
|
|
5838
6088
|
trigger(name, payload) {
|
|
5839
6089
|
this.ctx.trigger(name, payload, "external");
|
|
5840
6090
|
}
|
|
6091
|
+
static Use(plugin) {
|
|
6092
|
+
this.Plugins.push(plugin);
|
|
6093
|
+
}
|
|
5841
6094
|
};
|
|
5842
6095
|
let Artalk = _Artalk;
|
|
5843
6096
|
__publicField(Artalk, "defaults", defaults$3);
|
|
6097
|
+
__publicField(Artalk, "Plugins", []);
|
|
5844
6098
|
export { Artalk as default };
|