handsome增加图片上传按钮实现图片评论功能

- 事前提要:此方法无法用于带有PJAX加载的网站,handsome需要取消使用PJAX。
- 因为文章有些杂乱,在2022.02.24对本文进行了重构,你可以在“文章历史记录”中查看之前的版本,虽然已经失去了大部分参考价值。
[toc]
(更新)一种支持PJAX的方法
这篇文章实在是太长了,就新开一篇文章来写这个东西吧。大致方法如下:
- 将pup.js里的代码封装成一个函数
function chevereto()。 - 在自定义 JavaScript中调用这个函数
chevereto()。 - 将
chevereto()加入PJAX的回调函数中。
本站使用的就是这种方法。嗯,怎么说呢,能用,但是看起来好low!虽然也没人看文章源代码就是了。
算了,又不是不能用,哪天有时间再仔细研究一下吧。(应该不会再研究了) 各位大佬如果有什么好方法,记得评论区留言一下,我先谢谢您。
新文章写好了,如下 https://kanochan.net/archives/1141.html
(更新)一种更简单的办法
经过测试,摸索出了一种比较简单的办法,不用修改js文件。略微遗憾的是,该方法还是不能支持PJAX,使用的话需要关闭主题的PJAX功能。实现方法如下:
关闭PJAX
handsome后台-主题增强功能-增强功能开关里取消勾选启用pjax
放行HTML标签
在后台-设置-评论-允许使用的HTML标签和属性中添加下列内容,并保存,否则会评论失败。
<img src="">修改handsome源码(8.3.0版本)
文件路径:/usr/themes/handsome/libs/Content.php第2324行 将
echo '<textarea id="handsome_md_text" class="hide" >' . htmlspecialchars($content) . '</textarea>';修改为
echo '<div id="handsome_md_text" class="hide" >' . htmlspecialchars($content) . '</div>';引入Chevereto上传插件
在handsome后台-开发者设置-自定义输出head 头部的HTML代码中写入以下内容:
<script async src="//pic.6zs.cn/sdk/pup.js" data-url="https://pic.6zs.cn/upload" data-palette="black" data-auto-insert="html-embed"></script>完成。刷新看一下,在评论输入框下方应该出现了一个上传按钮。如果你想知道具体的原理,可以看看后续的内容。
先上总结
测试发现,通过HTML **data-** _属性引入js的方式,仍然会与本地缓存的js冲突,我觉得这是chevereto的锅。所以采用的方法是直接修改js,放弃使用HTML data-_属性。
- 开始
- 放行Typecho评论的HTML标签
- 修改chevereto的上传插件pup.js
- 在评论区新建一个上传图片按钮
- 完成
一、前言
在评论时,我们往往需要附上图片以更明确地表达自己的想法,Typecho中虽然没有原生的评论区图片上传功能,但是也可以通过HTML的img标签在评论中附加图片。不过,这其中有一个大麻烦:图片需要上传到图床,才能获得图片链接,进而插入img标签。这是一个很麻烦的过程,也正因为如此,除非迫不得已,没有人愿意选择在评论中添加图片。 现在,我们就来解决这个问题。先附上效果图,如下,你也可以在下方的评论区中验证效果。([font color=“#FFFF00”]注意:部分图床会被qq、微信内置浏览器拦截,想要获得完整的演示,请在系统浏览器中打开网页。[/font])

二、为Handsome增加评论图片上传
此方案不兼容手机应用内置的浏览器,如QQ、微信等自带的浏览器。内置浏览器就是逊啦。因为实现上传操作需要同时打开两个窗口,而内置浏览器往往没有多窗口支持。
放行HTML标签和属性
在后台-设置-评论-允许使用的HTML标签和属性中添加下列内容,并保存,否则会评论失败。
<img src="">修改chevereto的上传插件pup.js
此方案是基于Chevereto的上传插件来实现,所有通过Chevereto部署的图床都可以应用到此方案。
chevereto是什么
关于Chevereto,你可以看看我之前写的文章: [post cid=“997” cover="" size=""/]
认识Chevereto的上传插件
Popup Upload Plugin上传插件,可谓是Chevereto的重要功能之一。PUP 将用户可编辑的内容与将触发图像上传对话框的上传按钮绑定,并自动处理图像插入所需的代码。最终用户无需离开原始网站即可体验流畅而整洁的流程。关于上传插件的更多信息,你可以查看官方文档的说明,这里不再详细介绍。说一下有几个值得我们关注的东西:
mode即插件的模式。在默认情况下,插件绑定到任何匹配的编辑器框。auto-insert嵌入图片代码自动插入到输入框。
获取插件链接
随便找一个基于Chevereto搭建的图床,如:https://www.picb.cc/
.png)
.png)
.png)
<script async src="//www.picb.cc/sdk/pup.js" data-url="https://www.picb.cc/upload" data-auto-insert="html-embed"></script>前面也提到了,通过data-*属性控制pup.js效果不尽人意,故要想得到好的体验(不出bug),需要修改js后重新引入。
修改pup.js
下载pup.js
pup.js的下载链接可以在上面的插件链接中找到,即https://www.picb.cc/sdk/pup.js,将该链接复制到下载器中下载。没有下载器的话,就打开链接,右键另存为…进行下载。
格式化pup.js
打开下载好的js,如下,可以看到代码是被压缩过的,为了便于修改,我们需要格式化它。推荐使用在线代码格式化工具:JavaScript格式化。

修改pup.js代码
格式化后的js代码如下,我们需要修改三个地方。
.png)
url: "https://demo.chevereto.com/upload"修改为目标图床的上传链接,如
url: "https://www.picb.cc/upload"将mode: "auto"改为mode: "manual",即让js默认不自动放置上传按钮。 将autoInsert: "bbcode-embed-medium"修改为autoInsert: "html-embed",即让js自动返回HTML格式的图片链接。 修改完成后的js部分代码如下:
(function() { for (var t = { defaultSettings: { url: "https://www.picb.cc/upload", vendor: "auto", mode: "manual", lang: "auto", autoInsert: "html-embed", palette: "default", init: "onload", containerClass: 1, ... ...图片示意如下:
[hide]
.png)
[/hide]
重新引入修改后的pup.js
- 将修改后的pup.js上传到目录
/usr/themes/handsome/assets/js/下。 - 在
handsome后台-开发者设置-自定义输出head 头部的HTML代码中写入以下内容:
<script async src="/usr/themes/handsome/assets/js/pup.js"></script>新建图片上传按钮
在主题的评论区配置文件中加入以下代码
<button data-chevereto-pup-trigger data-target="#comment">上传图片</button>- 代码解析:
data-target="#comment"是文本框的ID,每个主题的ID不同,你可以在PHP源码中找到ID。如下图,文本框的ID为:comment。 这个ID用于Chevereto上传插件的回调,即插件上传完图片后,将嵌入代码输入到文本框中。根据主题的不同,你也许需要进行相应修改。.png)
文本框ID - 按钮添加的位置: 根据不同的需要,你可以将按钮添加到任何地方。你可以通过Chrome控制台的元素指示来确定添加的位置。
对于Handsome(8.3.0版本)主题,添加的位置为.png)
元素指示 /handsome/component/comments.php中的第137行附近,如下:
<div class="comment-form-comment form-group"> <label class="padder-v-sm" for="comment"><?php _me("评论") ?> <span class="required text-danger">*</span></label> <textarea id="comment" class="textarea form-control OwO-textarea" name="text" rows="5" placeholder="<?php _me("说点什么吧……") ?>" onkeydown="if(event.ctrlKey&&event.keyCode==13){document.getElementById('submit').click();return false};"><?php $this->remember('text'); ?></textarea> 代码在这里添加 <div class="OwO padder-v-sm"></div> <?php $options = mget(); if (in_array('ajaxComment', Utils::checkArray( $options->featuresetup))): ?> <div class="secret_comment" id="secret_comment" data-toggle="tooltip" data-original-title="<?php _me("开启该功能,您的评论仅作者和评论双方可见") ?>"> <label class="secret_comment_label control-label"><?php _me("私密评论") ?></label>图片示意如下:
[hide]
.png)
[/hide]
- 给按钮加个CSS样式
经过上面的配置,理论上图片上传按钮已经处于可用的状态。但相信你也发现了,按钮挺丑的…如果你要给按钮加CSS,在<button中调用CSS样式即可,如下:
<button class="你的样式" data-chevereto-pup-trigger data-target="#comment">上传图片</button>对于Handsome主题,直接调用主题的按钮样式即可,适用于夜间模式界面,如下:
<button class="btn m-b-xs btn-dark" data-chevereto-pup-trigger data-target="#comment">上传图片</button>三、Q&A
- 要更换图床怎么办? 答:修改pup.js里的
url: "https://www.picb.cc/upload",更改图床的链接即可。
四、图床分享
最后,分享一些使用Chevereto搭建的图床(注意:本站不对图床的稳定性负责,仅供分享)
- PICBCC:https://www.picb.cc/
- 路过图床:https://imgtu.com/
- 知晓图床:https://tu.jilu.info/
- SM图床:https://www.imgsm.com/
- 鸡霸图床(老王图床):https://img.gejiba.com/
- 靠谱图床:https://img.bqe.cc/
- 伏名图床:https://ccsyn.org/
- 安享图床:https://img.ax/
本站图床由:https://pic.6zs.cn/提供。
本文<完!>,感谢你的阅览,如果觉得还不错,请随意点赞。
[collapse status=“false” title=“文章历史记录”]
- 前言
在评论时,我们往往需要附上图片以更明确地表达自己的想法,Typecho中虽然没有原生的评论区图片上传功能,但是也可以通过HTML的img标签在评论中附加图片。不过,这其中有一个大麻烦:图片需要上传到图床,才能获得图片链接,进而插入img标签。这是一个很麻烦的过程,也正因为如此,除非迫不得已,没有人愿意选择在评论中添加图片。 现在,我们就来解决这个问题。先附上效果图,如下,你也可以在下方的评论区中验证效果。

- 如果你只想配置本站同款…
如果你只想配置本站同款,而且你使用的是Handsome主题,那么按照以下步骤配置即可,后续内容可忽略。
- 在
后台-设置-评论-允许使用的HTML标签和属性中添加下列内容,并保存。
<img src="">- 在
后台主题设置-开发者设置-自定义输出head 头部的HTML代码中,填入以下内容,并保存。
<script async src="https://www.guangsu.top/pup.js"></script>- 修改
/handsome/component/comments.php文件,137行附近,在
<textarea id="comment" class="textarea form-control OwO-textarea" name="text" rows="5" placeholder="<?php _me("说点什么吧……") ?>" onkeydown="if(event.ctrlKey&&event.keyCode==13){document.getElementById('submit').click();return false};"><?php $this->remember('text'); ?></textarea>下方添加下列代码:
<button class="btn m-b-xs btn-dark" data-chevereto-pup-trigger data-target="#comment">上传图片</button>添加代码的详细位置如下:
<div class="comment-form-comment form-group"> <label class="padder-v-sm" for="comment"><?php _me("评论") ?> <span class="required text-danger">*</span></label> <textarea id="comment" class="textarea form-control OwO-textarea" name="text" rows="5" placeholder="<?php _me("说点什么吧……") ?>" onkeydown="if(event.ctrlKey&&event.keyCode==13){document.getElementById('submit').click();return false};"><?php $this->remember('text'); ?></textarea> 代码在这里添加 <div class="OwO padder-v-sm"></div> <?php $options = mget(); if (in_array('ajaxComment', Utils::checkArray( $options->featuresetup))): ?> <div class="secret_comment" id="secret_comment" data-toggle="tooltip" data-original-title="<?php _me("开启该功能,您的评论仅作者和评论双方可见") ?>"> <label class="secret_comment_label control-label"><?php _me("私密评论") ?></label>- 在
后台主题设置-PJAX-PJAX回调函数中写入下列内容,并保存。 关闭PJAX后此步不需要做。
$.getScript("https://www.guangsu.top/pup.js");- 完成
- 开始之前…
- 在
后台-设置-评论-允许使用的HTML标签和属性中添加要放行的标签:
<a href=""><img src="">- 此方案不兼容手机应用内置的浏览器,如QQ、微信等自带的浏览器。
内置浏览器就是逊啦。 - 正式开始
- 关于Chevereto
此方案是基于Chevereto的上传插件来实现,所有通过Chevereto部署的图床都可以应用到此方案。关于Chevereto,你可以看看我之前写的文章: [post cid=“997” cover="" size=""/] 本次教程针对的是Handsome主题,理论上适用于所有Typecho主题,核心方法是一样的。
- 认识Chevereto的上传插件
Popup Upload Plugin上传插件,可谓是Chevereto的重要功能之一。PUP 将用户可编辑的内容与将触发图像上传对话框的上传按钮绑定,并自动处理图像插入所需的代码。最终用户无需离开原始网站即可体验流畅而整洁的流程。关于上传插件的更多信息,你可以查看官方文档的说明,这里不再详细介绍。说一下有几个值得我们关注的东西:
mode即插件的模式。在默认情况下,插件绑定到任何匹配的编辑器框。auto-insert嵌入图片代码自动插入到输入框。- 获取插件链接
随便找一个基于Chevereto搭建的图床,如:https://www.picb.cc/
.png)
.png)
.png)
<script async src="//www.picb.cc/sdk/pup.js" data-url="https://www.picb.cc/upload" data-auto-insert="html-embed"></script>默认情况下,插件会自动匹配输入框,但是效果往往不尽人意,我们需要手动指定位置。要想自定义位置,我们需要禁用插件得自动匹配功能,即上文所述的mode,在上面复制出来的链接中添加:data-mode=“manual”参数用于禁用插件的自动匹配。关于这些参数的介绍,在前述的官方文档链接中讲有。修改好的插件链接如下:
<script async src="//www.picb.cc/sdk/pup.js" data-url="https://www.picb.cc/upload" data-auto-insert="html-embed" data-mode="manual"></script>- 部署插件
将修改好的链接,放置到主题的<#head>…<#/head>头部里(请忽略#号),如下 [hide]
.png)
[/hide]
对于Hansome主题,可在后台-开发者设置-自定义输出head 头部的HTML代码中添加插件链接。
.png)
- 添加
上传图片按钮
在主题的评论区配置文件中加入以下代码
<button data-chevereto-pup-trigger data-target="#comment">上传图片</button>代码解析: data-target="#comment"是文本框的ID,每个主题的ID不同,你可以在PHP源码中找到ID。如下图,文本框的ID为:comment。
.png)
.png)
/handsome/component/comments.php中的第137行附近,如下:<div class="comment-form-comment form-group"> <label class="padder-v-sm" for="comment"><?php _me("评论") ?> <span class="required text-danger">*</span></label> <textarea id="comment" class="textarea form-control OwO-textarea" name="text" rows="5" placeholder="<?php _me("说点什么吧……") ?>" onkeydown="if(event.ctrlKey&&event.keyCode==13){document.getElementById('submit').click();return false};"><?php $this->remember('text'); ?></textarea> 代码在这里添加 <div class="OwO padder-v-sm"></div> <?php $options = mget(); if (in_array('ajaxComment', Utils::checkArray( $options->featuresetup))): ?> <div class="secret_comment" id="secret_comment" data-toggle="tooltip" data-original-title="<?php _me("开启该功能,您的评论仅作者和评论双方可见") ?>"> <label class="secret_comment_label control-label"><?php _me("私密评论") ?></label>图片示意如下:
[hide]
.png)
[/hide]
- 给按钮加个CSS样式
经过上面的配置,理论上图片上传按钮已经处于可用的状态。但相信你也发现了,按钮挺丑的…CSS这东西吧,因人而异,我就不写了懒。如果你要给按钮加CSS,在<button中调用CSS样式即可,如下:
<button class="你的样式" data-chevereto-pup-trigger data-target="#comment">上传图片</button>对于Handsome主题,直接调用主题的按钮样式即可,适用于夜间模式界面,如下:
<button class="btn m-b-xs btn-dark" data-chevereto-pup-trigger data-target="#comment">上传图片</button>- PJAX回调
需要注意的是,如果你的网站启用了PJAX,会导致Chevereto的上传插件,也就是pup.js,无法重新加载。非常抱歉的是,我不知道怎么回调带有用户参数的script,在Chevereto的script中带有两个参数,分别是 data-auto-insert="html-embed" 、data-mode="manual",其中,前者定义了插件的返回图片地址的代码格式,后者定义了插件的工作模式。
如果只是单独重载pup.js,那么会造成一些错误,如点开上传按钮,跳转到的是https://demo.chevereto.com/upload,以及出现两个上传按钮的状况。我不知道的是,怎么样才能让PJAX重新加载整个script,使用户信息随之重载。如果有人研究出来了,请务必留言告诉我,多谢!
经过研究,虽然无法从根本上解决上面的问题,但是也可以通过下面的的方法来曲线救国。 没有救,只能把PJAX关了,以下内容失效。
- 修改js文件,再重新引入修改后的js
pup.js存放于图床的服务器上,我们当然不可能更改。可以将目标图床的pup.js下载到本地进行修改。如https://pic.6zs.cn/sdk/pup.js,下载好的js如下:
`(function(){for(var t={defaultSettings:{url:"https://demo.chevereto.com/upload",vendor:"auto",mode:"auto",lang:"auto",autoInsert:"bbcode-embed-medium",palette:"default",init:"onload",containerClass:1,buttonClass:1,sibling:0,siblingPos:"after",fitEditor:0,observe:0,observeCache:1,html:'%iconSvg%text',css:".%cClass{display:inline-block;margin-top:5px;margin-bottom:5px}.%bClass{line-height:normal;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s;outline:0;color:%2;border:none;cursor:pointer;border:1px solid rgba(0,0,0,.15);background:%1;border-radius:.2em;padding:.5em 1em;font-size:12px;font-weight:700;text-shadow:none}.%bClass:hover{background:%3;color:%4;border-color:rgba(0,0,0,.1)}.%iClass,.%tClass{display:inline-block;vertical-align:middle}.%iClass svg{display:block;width:1em;height:1em;fill:currentColor}.%tClass{margin-left:.25em}"},ns:{plugin:"chevereto-pup"},palettes:{default:["#ececec","#333","#2980b9","#fff"],clear:["inherit","inherit","inherit","#2980b9"],turquoise:["#16a085","#fff","#1abc9c","#fff"],green:["#27ae60","#fff","#2ecc71","#fff"],blue:["#2980b9","#fff","#3498db","#fff"],purple:["#8e44ad","#fff","#9b59b6","#fff"],darkblue:["#2c3e50","#fff","#34495e","#fff"],yellow:["#f39c12","#fff","#f1c40f","#fff"],orange:["#d35400","#fff","#e67e22","#fff"],red:["#c0392b","#fff","#e74c3c","#fff"],grey:["#ececec","#000","#e0e0e0","#000"],black:["#333","#fff","#666","#fff"]},classProps:["button","container"],iconSvg:'',l10n:{ar:"تحميل الصور",cs:"Nahrát obrázky",da:"Upload billeder",de:"Bilder hochladen",es:"Subir imágenes",fi:"Lataa kuvia",fr:"Importer des images",id:"Unggah gambar",it:"Carica immagini",ja:"画像をアップロード",nb:"Last opp bilder",nl:"Upload afbeeldingen",pl:"Wyślij obrazy",pt_BR:"Enviar imagens",ru:"Загрузить изображения",tr:"Resim Yukle",uk:"Завантажити зображення",zh_CN:"上传图片",zh_TW:"上傳圖片"},vendors:{default:{check:function(){return 1},getEditor:function(){var t={textarea:{name:["recaptcha","search","recipients","coppa","^comment_list","username_list","add"]},ce:{dataset:["gramm"]}},e=["~","|","^","$","*"],i={};for(var s in t){i[s]="";var n=t[s];for(var r in n)for(var o=0;o-1&&(a=d,l=l.substring(1)),i[s]+=":not(["+("dataset"==r?"data-"+l:r+a+'="'+l+'"')+"])"}}return document.querySelectorAll('[contenteditable=""]'+i.ce+',[contenteditable="true"]'+i.ce+",textarea:not([readonly])"+i.textarea)}},bbpress:{settings:{autoInsert:"html-embed-medium",html:'',sibling:"#qt_bbp_reply_content_img",siblingPos:"before"},check:"bbpEngagementJS"},discourse:{settings:{autoInsert:"markdown-embed-medium",html:'',sibling:".upload.btn",siblingPos:"before",observe:".create,#create-topic,.usercard-controls button",observeCache:0,onDemand:1},check:"Discourse"},discuz:{settings:{buttonClass:1,html:'%iconSvg',sibling:".fclr,#e_attach",css:"a.%bClass,.bar a.%bClass{box-sizing:border-box;cursor:pointer;background:%1;color:%2;text-indent:unset;position:relative}.b1r a.%bClass:hover,a.%bClass:hover{background:%3;color:%4}a.%bClass{font-size:14px}.b1r a.%bClass{border:1px solid rgba(0,0,0,.15)!important;font-size:20px;padding:0;height:44px}.%bClass svg{font-size:1em;width:1em;height:1em;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;fill:currentColor}",palette:"purple"},palettes:{default:["transparent","#333","#2980b9","#fff"]},check:"DISCUZCODE",getEditor:function(){return document.querySelector('.area textarea[name="message"]')}},ipb:{settings:{autoInsert:"html-embed-medium",html:'%iconSvg%text',sibling:".cke_button__ipslink",siblingPos:"before",css:".cke_button.%bClass{background:%1;position:relative}.cke_button.%bClass:hover{background:%3;border-color:%5}.cke_button.%bClass svg{font-size:15px;width:1em;height:1em;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;fill:%2}.cke_button.%bClass:hover svg{fill:%4}"},palettes:{default:["inherit","#444","","inherit"]},check:"ips",getEditorFn:function(){var t=this.getEditor().dataset.ipseditorName;return CKEDITOR.instances[t]},getEditor:function(){return document.querySelector("[data-ipseditor-name]")},editorValue:function(t){var e=CKEDITOR.dom.element.createFromHtml(""+t+"");this.getEditorFn().insertElement(e)},useCustomEditor:function(){return 1}},mybb:{settings:{sibling:"#quickreply_e > tr > td > *:last-child, .sceditor-container",fitEditor:0,extracss:".trow2 .%cClass{margin-bottom:0}"},check:"MyBB",getEditor:function(){return MyBBEditor?MyBBEditor.getContentAreaContainer().parentElement:document.querySelector("#quickreply_e textarea")},editorValue:function(t){if(MyBBEditor){var e=MyBBEditor.inSourceMode()?"insert":"wysiwygEditorInsertHtml";MyBBEditor[e]("insert"==e?t:MyBBEditor.fromBBCode(t))}else this.getEditor().value+=t},useCustomEditor:function(){return!!MyBBEditor}},nodebb:{settings:{autoInsert:"markdown-embed-medium",html:'',sibling:'[data-format="picture-o"]',siblingPos:"before",observe:'[component="category/post"],[component="topic/reply"],[component="topic/reply-as-topic"],[component="post/reply"],[component="post/quote"]',observeCache:0,onDemand:1},check:"__nodebbSpamBeGoneCreateCaptcha__",callback:function(){for(var t=document.querySelectorAll(".btn-toolbar .img-upload-btn"),e=0;e ':' ',sibling:document.querySelector("#format-buttons *:first-child")&&"BUTTON"==document.querySelector("#format-buttons *:first-child").tagName?".bbcode-img":"#message-box textarea.inputbox",siblingPos:"after"},check:"phpbb",getEditor:function(){if("undefined"!=typeof form_name&&"undefined"!=typeof text_name)return document.forms[form_name].elements[text_name]}},proboards:{settings:{html:' ',css:"",sibling:"input[type=submit]",siblingPos:"before"},check:"proboards",editorValue:function(t){var e=$(".wysiwyg-textarea").data("wysiwyg"),i=e.editors[e.currentEditorName];i.setContent(i.getContent()+t)},useCustomEditor:function(){return 1!==$(".container.quick-reply").size()},getEditor:function(){return document.querySelector("textarea[name=message]")}},redactor2:{getEditor:function(){var t=this.getEditorFn();return t?this.useCustomEditor()?t.$box[0]:t[0]:null},getEditorEl:function(){return this.useCustomEditor()?this.getEditorFn().$editor[0]:this.getEditorFn()[0]},editorValue:function(t){var e="",i=this.useCustomEditor()?"innerHTML":"value";if("string"!=typeof t){var s=this.getEditorEl()[i];return this.useCustomEditor()&&""==s?"":this.getEditorEl()[i]}if(this.useCustomEditor()){var n=""+t+"";this.getEditorFn().insert.html(""!==this.editorValue()?e+n:n)}else this.getEditorEl()[i]=t},useCustomEditor:function(){return!(this.getEditorFn()instanceof jQuery)}},smf:{settings:{html:' %iconSvg%text ',css:"%defaultCSS #bbcBox_message .%bClass{margin-right:1px;transition:none;color:%2;padding:0;width:23px;height:21px;border-radius:5px;background-color:%1}#bbcBox_message .%bClass:hover{background-color:%3}#bbcBox_message .%tClass{display:none}",sibling:"#BBCBox_message_button_1_1,.quickReplyContent + div",siblingPos:"before",fitEditor:1},palettes:{default:["#E7E7E7","#333","#B0C4D6","#333"]},check:"smf_scripturl",getEditor:function(){return smf_editorArray.length>0?smf_editorArray[0].oTextHandle:document.querySelector(".quickReplyContent textarea")}},quill:{settings:{autoInsert:"html-embed-medium",html:'%iconSvg',sibling:"ul.richEditor-menuItems li.richEditor-menuItem:last-child",css:".%iClass {display: block; height: 24px; margin: auto; width: 24px;}"},check:"quill",editorValue:function(t){quill.clipboard.dangerouslyPasteHTML("\n"==quill.getText()?0:quill.getLength(),t)},useCustomEditor:function(){return 1},getEditor:function(){return quill.container}},vanilla:{settings:{autoInsert:"markdown-embed-medium",html:'',sibling:".editor-dropdown-upload"},check:"Vanilla",getEditor:function(){return document.getElementById("Form_Body")}},vbulletin:{settings:{autoInsert:"html-embed-medium",html:'%iconSvg',sibling:".b-toolbar__item--secondary:first-child",siblingPos:"before",css:".%bClass{background:%1;color:%2;position:relative}.%bClass:hover{background:%3;color:%4;border-color:%5}.%bClass svg{font-size:15px;width:1em;height:1em;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;fill:currentColor}"},palettes:{default:["","#4B6977","","#007EB8"]},check:"vBulletin",getEditorFn:function(){var t=this.getEditor().getAttribute("ck-editorid");return CKEDITOR.instances[t]},getEditor:function(){return document.querySelector("[data-message-type]")},editorValue:function(t){var e=CKEDITOR.dom.element.createFromHtml(""+t+"");this.getEditorFn().insertElement(e)},useCustomEditor:function(){return 1}},WoltLab:{settings:{autoInsert:"html-embed-medium",sibling:'li[data-name="settings"]',html:' %text'},check:"WBB",getEditorFn:function(){var t=$("#text").data("redactor");return t||null}},XF1:{settings:{autoInsert:"html-embed-medium",containerClass:1,buttonClass:1,html:'%iconSvg',sibling:".redactor_btn_container_image",siblingPos:"before",css:"li.%cClass .%bClass{background:%1;color:%2;text-indent:unset;border-radius:3px;position:relative}li.%cClass a.%bClass:hover{background:%3;color:%4;border-color:%5}.%cClass .%bClass svg{font-size:15px;width:1em;height:1em;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;fill:currentColor}",observe:".edit.OverlayTrigger",observeCache:1},palettes:{default:["none","inherit","none","inherit",""]},check:"XenForo",getEditorFn:function(){var t=document.querySelector("#exposeMask")&&document.querySelector("#exposeMask").offsetParent?".xenOverlay form":"form";if("form"!==t)for(var e=document.querySelectorAll(t),i=0;i"==s?"":this.getEditorEl()[i]}if(this.useCustomEditor()){var n=""+t+"";this.getEditorFn().insertHtml(""!==this.editorValue()?e+n:n)}else this.getEditorEl()[i]=t},useCustomEditor:function(){return!(this.getEditorFn()instanceof jQuery)}},XF2:{settings:{autoInsert:"html-embed-medium",containerClass:1,buttonClass:"button--link js-attachmentUpload button button--icon button--icon--upload fa--xf",html:'%text',sibling:"",siblingPos:"after",observe:'[data-xf-click="quick-edit"]',observeCache:1},palettes:{default:["transparent","#505050","rgba(20,20,20,0.06)","#141414"]},check:"XF",getEditorFn:function(t){var e=".js-editor";return"string"==typeof t&&(e=this.getEditorSel(t)),XF.getEditorInContainer($(e))},getEditorSel:function(e){return"["+t.ns.dataPluginTarget+'="'+e+'"]'},getEditor:function(t){return"string"==typeof t?document.querySelector(this.getEditorSel(t)):document.querySelectorAll(".js-editor")},getBbCode:function(t){return t.getTextArea()[0].value},editorValue:function(t,e){var i="",s=this.getEditorFn(e),n=s.ed.bbCode.isBbCodeView()?["bbCode","getBbCode","insertBbCode"]:["html","get","insert"],r=s.ed[n[0]];if("string"!=typeof t){if(void 0===r[n[1]])var o=this.getBbCode(r);else o=r[n[1]]();return this.useCustomEditor()&&o==i?"":o}var a=""!==this.editorValue(!1,e);if("html"==n[0]){var l=""+t+"";r[n[2]](a?i+l:l)}else{var d=XF.ajax("POST",XF.canonicalizeUrl("index.php?editor/to-bb-code"),{html:t});d.done(function(t){r[n[2]](a?"\n"+t.bbCode:t.bbCode)})}},useCustomEditor:function(){return void 0!==XF.getEditorInContainer($(".js-editor"))}}},generateGuid:function(){var t=(new Date).getTime();return"undefined"!=typeof performance&&"function"==typeof performance.now&&(t+=performance.now()),"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var i=(t+16*Math.random())%16|0;return t=Math.floor(t/16),("x"===e?i:3&i|8).toString(16)})},getNewValue:function(t,e){var i="string"!=typeof t.getAttribute("contenteditable")?"value":"innerHTML",s="value"==i?"\n":"",n=t[i],r=e,o=!1;if(o&&(r=String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""")),0==n.length)return r;var a="",l=n.match(/\n+$/g),d=l?l[0].split("\n").length:0;if(d<=2){var u=0==d?2:1;a+=s.repeat(u)}return a+r},insertTrigger:function(){var t,e=this.vendors[this.settings.vendor],i=this.settings.sibling?document.querySelectorAll(this.settings.sibling+":not(["+this.ns.dataPlugin+"])")[0]:0;if("auto"==this.settings.mode)t=this.vendors[e.hasOwnProperty("getEditor")?this.settings.vendor:"default"].getEditor();else{for(var s=document.querySelectorAll("["+this.ns.dataPluginTrigger+"][data-target]:not(["+this.ns.dataPluginId+"])"),n=[],r=0;r0&&(t=document.querySelectorAll(n.join(",")))}if(t){if(!document.getElementById(this.ns.pluginStyle)&&this.settings.css){var o=document.createElement("style"),a=this.settings.css;a=this.appyTemplate(a),o.type="text/css",o.innerHTML=a.replace(/%p/g,"."+this.ns.plugin),o.setAttribute("id",this.ns.pluginStyle),document.body.appendChild(o)}t instanceof NodeList||(t=[t]);var l=0;for(r=0;rn[r]&&(s[r]=i[r]*n[r]);var o={l:Math.trunc(i.w/2-s.w/2+i.l),t:Math.trunc(i.h/2-s.h/2+i.t)};this.popups[t].window=window.open(this.settings.url,t,"width="+s.w+",height="+s.h+",top="+o.t+",left="+o.l),this.popups[t].timer=window.setInterval(function(){e.popups[t].window&&!1===e.popups[t].window.closed||(window.clearInterval(e.popups[t].timer),e.popups[t]=void 0)},200)}else this.popups[t].window.focus()}},postSettings:function(t){this.popups[t].window.postMessage({id:t,settings:this.settings},this.settings.url)},liveBind:function(t,e,i){document.addEventListener(e,function(e){var s=document.querySelectorAll(t);if(s){for(var n=e.target,r=-1;n&&-1===(r=Array.prototype.indexOf.call(s,n));)n=n.parentElement;r>-1&&(e.preventDefault(),i.call(e,n))}},!0)},prepare:function(){var t=this;this.ns.dataPlugin="data-"+this.ns.plugin,this.ns.dataPluginId=this.ns.dataPlugin+"-id",this.ns.dataPluginTrigger=this.ns.dataPlugin+"-trigger",this.ns.dataPluginTarget=this.ns.dataPlugin+"-target",this.ns.pluginStyle=this.ns.plugin+"-style",this.ns.selDataPluginTrigger="["+this.ns.dataPluginTrigger+"]";var e=document.currentScript||document.getElementById(this.ns.plugin+"-src");e?e.dataset.buttonTemplate&&(e.dataset.html=e.dataset.buttonTemplate):e={dataset:{}};var i=0;for(var s in this.settings={},this.defaultSettings){var n=e&&e.dataset[s]?e.dataset[s]:this.defaultSettings[s];"1"!==n&&"0"!==n||(n="true"==n),"string"==typeof n&&this.classProps.indexOf(s.replace(/Class$/,""))>-1&&(i=1),this.settings[s]=n}if("auto"==this.settings.vendor)for(var s in this.settings.vendor="default",this.settings.fitEditor=0,this.vendors)if("default"!=s&&void 0!==window[this.vendors[s].check]){this.settings.vendor=s;break}var r=["lang","url","vendor","target"];"default"==this.settings.vendor&&(this.vendors.default.settings={});var o=this.vendors[this.settings.vendor];if(o.settings)for(var s in o.settings)e&&e.dataset.hasOwnProperty(s)||(this.settings[s]=o.settings[s]);else for(var s in o.settings={},this.defaultSettings)-1==r.indexOf(s)&&(o.settings[s]=this.defaultSettings[s]);if("default"!==this.settings.vendor)if(o.settings.hasOwnProperty("fitEditor")||e.dataset.hasOwnProperty("fitEditor")||(this.settings.fitEditor=1),this.settings.fitEditor)i=!o.settings.css;else{r=["autoInsert","observe","observeCache"];for(var s in o.settings)-1!=r.indexOf(s)||e.dataset.hasOwnProperty(s)||(this.settings[s]=this.defaultSettings[s])}if(i)this.settings.css="";else{this.settings.css=this.settings.css.replace("%defaultCSS",this.defaultSettings.css),o.settings.extracss&&this.settings.css&&(this.settings.css+=o.settings.extracss);var a=this.settings.palette.split(",");a.length>1?this.palette=a:this.palettes.hasOwnProperty(a)||(this.settings.palette="default"),this.palette||(this.palette=(this.settings.fitEditor&&o.palettes&&o.palettes[this.settings.palette]?o:this).palettes[this.settings.palette])}for(var l=this.classProps,d=0;d0)for(d=0;d为了便于理解,我们需要格式化js代码,可以通过在线工具JavaScript格式化来格式化代码。

格式化后的js代码如下:
(function() { for (var t = { defaultSettings: { url: "https://demo.chevereto.com/upload", vendor: "auto", mode: "auto", lang: "auto", autoInsert: "bbcode-embed-medium", palette: "default", init: "onload", containerClass: 1, buttonClass: 1, sibling: 0, siblingPos: "after", fitEditor: 0, observe: 0, observeCache: 1, html: '<div class="%cClass"><button %x class="%bClass"><span class="%iClass">%iconSvg</span><span class="%tClass">%text</span></button></div>', css: ".%cClass{display:inline-block;margin-top:5px;margin-bottom:5px}.%bClass{line-height:normal;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s;outline:0;color:%2;border:none;cursor:pointer;border:1px solid rgba(0,0,0,.15);background:%1;border-radius:.2em;padding:.5em 1em;font-size:12px;font-weight:700;text-shadow:none}.%bClass:hover{background:%3;color:%4;border-color:rgba(0,0,0,.1)}.%iClass,.%tClass{display:inline-block;vertical-align:middle}.%iClass svg{display:block;width:1em;height:1em;fill:currentColor}.%tClass{margin-left:.25em}" }, ns: { plugin: "chevereto-pup" }, palettes: { default: ["#ececec", "#333", "#2980b9", "#fff"], clear: ["inherit", "inherit", "inherit", "#2980b9"], turquoise: ["#16a085", "#fff", "#1abc9c", "#fff"], green: ["#27ae60", "#fff", "#2ecc71", "#fff"], blue: ["#2980b9", "#fff", "#3498db", "#fff"], purple: ["#8e44ad", "#fff", "#9b59b6", "#fff"], darkblue: ["#2c3e50", "#fff", "#34495e", "#fff"], yellow: ["#f39c12", "#fff", "#f1c40f", "#fff"], orange: ["#d35400", "#fff", "#e67e22", "#fff"], red: ["#c0392b", "#fff", "#e74c3c", "#fff"], grey: ["#ececec", "#000", "#e0e0e0", "#000"], black: ["#333", "#fff", "#666", "#fff"] }, classProps: ["button", "container"], iconSvg: '<svg class="%iClass" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M76.7 87.5c12.8 0 23.3-13.3 23.3-29.4 0-13.6-5.2-25.7-15.4-27.5 0 0-3.5-0.7-5.6 1.7 0 0 0.6 9.4-2.9 12.6 0 0 8.7-32.4-23.7-32.4 -29.3 0-22.5 34.5-22.5 34.5 -5-6.4-0.6-19.6-0.6-19.6 -2.5-2.6-6.1-2.5-6.1-2.5C10.9 25 0 39.1 0 54.6c0 15.5 9.3 32.7 29.3 32.7 2 0 6.4 0 11.7 0V68.5h-13l22-22 22 22H59v18.8C68.6 87.4 76.7 87.5 76.7 87.5z" style="fill: currentcolor;"/></svg>', l10n: { ar: "تحميل الصور", cs: "Nahrát obrázky", da: "Upload billeder", de: "Bilder hochladen", es: "Subir imágenes", fi: "Lataa kuvia", fr: "Importer des images", id: "Unggah gambar", it: "Carica immagini", ja: "画像をアップロード", nb: "Last opp bilder", nl: "Upload afbeeldingen", pl: "Wyślij obrazy", pt_BR: "Enviar imagens", ru: "Загрузить изображения", tr: "Resim Yukle", uk: "Завантажити зображення", zh_CN: "上传图片", zh_TW: "上傳圖片" }, vendors: { default: { check: function() { return 1 }, getEditor: function() { var t = { textarea: { name: ["recaptcha", "search", "recipients", "coppa", "^comment_list", "username_list", "add"] }, ce: { dataset: ["gramm"] } }, e = ["~", "|", "^", "$", "*"], i = {}; for (var s in t) { i[s] = ""; var n = t[s]; for (var r in n) for (var o = 0; o < n[r].length; o++) { var a = "", l = n[r][o], d = l.charAt(0); e.indexOf(d) > -1 && (a = d, l = l.substring(1)), i[s] += ":not([" + ("dataset" == r ? "data-" + l: r + a + '="' + l + '"') + "])" } } return document.querySelectorAll('[contenteditable=""]' + i.ce + ',[contenteditable="true"]' + i.ce + ",textarea:not([readonly])" + i.textarea) } }, bbpress: { settings: { autoInsert: "html-embed-medium", html: '<input %x type="button" class="ed_button button button-small" aria-label="%text" value="%text">', sibling: "#qt_bbp_reply_content_img", siblingPos: "before" }, check: "bbpEngagementJS" }, discourse: { settings: { autoInsert: "markdown-embed-medium", html: '<button %x title="%text" class="upload btn no-text btn-icon ember-view"><i class="fa fa-cloud-upload d-icon d-icon-upload"></i></button>', sibling: ".upload.btn", siblingPos: "before", observe: ".create,#create-topic,.usercard-controls button", observeCache: 0, onDemand: 1 }, check: "Discourse" }, discuz: { settings: { buttonClass: 1, html: '<a %x title="%text" class="%bClass">%iconSvg</a>', sibling: ".fclr,#e_attach", css: "a.%bClass,.bar a.%bClass{box-sizing:border-box;cursor:pointer;background:%1;color:%2;text-indent:unset;position:relative}.b1r a.%bClass:hover,a.%bClass:hover{background:%3;color:%4}a.%bClass{font-size:14px}.b1r a.%bClass{border:1px solid rgba(0,0,0,.15)!important;font-size:20px;padding:0;height:44px}.%bClass svg{font-size:1em;width:1em;height:1em;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;fill:currentColor}", palette: "purple" }, palettes: { default: ["transparent", "#333", "#2980b9", "#fff"] }, check: "DISCUZCODE", getEditor: function() { return document.querySelector('.area textarea[name="message"]') } }, ipb: { settings: { autoInsert: "html-embed-medium", html: '<a %x class="cke_button cke_button_off %bClass" title="%text" tabindex="-1" hidefocus="true" role="button"><span class="cke_button_icon">%iconSvg</span><span class="cke_button_label" aria-hidden="false">%text</span><span class="cke_button_label" aria-hidden="false"></span></a>', sibling: ".cke_button__ipslink", siblingPos: "before", css: ".cke_button.%bClass{background:%1;position:relative}.cke_button.%bClass:hover{background:%3;border-color:%5}.cke_button.%bClass svg{font-size:15px;width:1em;height:1em;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;fill:%2}.cke_button.%bClass:hover svg{fill:%4}" }, palettes: { default: ["inherit", "#444", "", "inherit"] }, check: "ips", getEditorFn: function() { var t = this.getEditor().dataset.ipseditorName; return CKEDITOR.instances[t] }, getEditor: function() { return document.querySelector("[data-ipseditor-name]") }, editorValue: function(t) { var e = CKEDITOR.dom.element.createFromHtml("<p>" + t + "</p>"); this.getEditorFn().insertElement(e) }, useCustomEditor: function() { return 1 } }, mybb: { settings: { sibling: "#quickreply_e > tr > td > *:last-child, .sceditor-container", fitEditor: 0, extracss: ".trow2 .%cClass{margin-bottom:0}" }, check: "MyBB", getEditor: function() { return MyBBEditor ? MyBBEditor.getContentAreaContainer().parentElement: document.querySelector("#quickreply_e textarea") }, editorValue: function(t) { if (MyBBEditor) { var e = MyBBEditor.inSourceMode() ? "insert": "wysiwygEditorInsertHtml"; MyBBEditor[e]("insert" == e ? t: MyBBEditor.fromBBCode(t)) } else this.getEditor().value += t }, useCustomEditor: function() { return !! MyBBEditor } }, nodebb: { settings: { autoInsert: "markdown-embed-medium", html: '<li %x tabindex="-1" title="%text"><i class="fa fa-cloud-upload"></i></li>', sibling: '[data-format="picture-o"]', siblingPos: "before", observe: '[component="category/post"],[component="topic/reply"],[component="topic/reply-as-topic"],[component="post/reply"],[component="post/quote"]', observeCache: 0, onDemand: 1 }, check: "__nodebbSpamBeGoneCreateCaptcha__", callback: function() { for (var t = document.querySelectorAll(".btn-toolbar .img-upload-btn"), e = 0; e < t.length; e++) t[e].parentNode.removeChild(t[e]) } }, phpbb: { settings: { html: document.querySelector("#format-buttons *:first-child") && "BUTTON" == document.querySelector("#format-buttons *:first-child").tagName ? ' <button %x type="button" class="button button-icon-only" title="%text"><i class="icon fa-cloud-upload fa-fw" aria-hidden="true"></i></button> ': ' <input %x type="button" class="button2" value="%text"> ', sibling: document.querySelector("#format-buttons *:first-child") && "BUTTON" == document.querySelector("#format-buttons *:first-child").tagName ? ".bbcode-img": "#message-box textarea.inputbox", siblingPos: "after" }, check: "phpbb", getEditor: function() { if ("undefined" != typeof form_name && "undefined" != typeof text_name) return document.forms[form_name].elements[text_name] } }, proboards: { settings: { html: ' <input %x type="submit" value="%text"> ', css: "", sibling: "input[type=submit]", siblingPos: "before" }, check: "proboards", editorValue: function(t) { var e = $(".wysiwyg-textarea").data("wysiwyg"), i = e.editors[e.currentEditorName]; i.setContent(i.getContent() + t) }, useCustomEditor: function() { return 1 !== $(".container.quick-reply").size() }, getEditor: function() { return document.querySelector("textarea[name=message]") } }, redactor2: { getEditor: function() { var t = this.getEditorFn(); return t ? this.useCustomEditor() ? t.$box[0] : t[0] : null }, getEditorEl: function() { return this.useCustomEditor() ? this.getEditorFn().$editor[0] : this.getEditorFn()[0] }, editorValue: function(t) { var e = "<p><br></p>", i = this.useCustomEditor() ? "innerHTML": "value"; if ("string" != typeof t) { var s = this.getEditorEl()[i]; return this.useCustomEditor() && "<p><br></p>" == s ? "": this.getEditorEl()[i] } if (this.useCustomEditor()) { var n = "<p>" + t + "</p>"; this.getEditorFn().insert.html("" !== this.editorValue() ? e + n: n) } else this.getEditorEl()[i] = t }, useCustomEditor: function() { return ! (this.getEditorFn() instanceof jQuery) } }, smf: { settings: { html: ' <button %x title="%text" class="%bClass"><span class="%iClass">%iconSvg</span><span class="%tClass">%text</span></button> ', css: "%defaultCSS #bbcBox_message .%bClass{margin-right:1px;transition:none;color:%2;padding:0;width:23px;height:21px;border-radius:5px;background-color:%1}#bbcBox_message .%bClass:hover{background-color:%3}#bbcBox_message .%tClass{display:none}", sibling: "#BBCBox_message_button_1_1,.quickReplyContent + div", siblingPos: "before", fitEditor: 1 }, palettes: { default: ["#E7E7E7", "#333", "#B0C4D6", "#333"] }, check: "smf_scripturl", getEditor: function() { return smf_editorArray.length > 0 ? smf_editorArray[0].oTextHandle: document.querySelector(".quickReplyContent textarea") } }, quill: { settings: { autoInsert: "html-embed-medium", html: '<li class="richEditor-menuItem richEditor-menuItem_f1af88yq" role="menuitem"><button %x class="richEditor-button richEditor-embedButton richEditor-button_f1fodmu3" type="button" aria-pressed="false"><span class="richEditor-iconWrap_f13bdese"></span>%iconSvg</button></li>', sibling: "ul.richEditor-menuItems li.richEditor-menuItem:last-child", css: ".%iClass {display: block; height: 24px; margin: auto; width: 24px;}" }, check: "quill", editorValue: function(t) { quill.clipboard.dangerouslyPasteHTML("\n" == quill.getText() ? 0 : quill.getLength(), t) }, useCustomEditor: function() { return 1 }, getEditor: function() { return quill.container } }, vanilla: { settings: { autoInsert: "markdown-embed-medium", html: '<span %x class="fas fa-cloud-upload-alt" title="%text"></span>', sibling: ".editor-dropdown-upload" }, check: "Vanilla", getEditor: function() { return document.getElementById("Form_Body") } }, vbulletin: { settings: { autoInsert: "html-embed-medium", html: '<li %x class="%bClass b-toolbar__item b-toolbar__item--secondary" title="%text" tabindex="0">%iconSvg</li>', sibling: ".b-toolbar__item--secondary:first-child", siblingPos: "before", css: ".%bClass{background:%1;color:%2;position:relative}.%bClass:hover{background:%3;color:%4;border-color:%5}.%bClass svg{font-size:15px;width:1em;height:1em;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;fill:currentColor}" }, palettes: { default: ["", "#4B6977", "", "#007EB8"] }, check: "vBulletin", getEditorFn: function() { var t = this.getEditor().getAttribute("ck-editorid"); return CKEDITOR.instances[t] }, getEditor: function() { return document.querySelector("[data-message-type]") }, editorValue: function(t) { var e = CKEDITOR.dom.element.createFromHtml("<p>" + t + "</p>"); this.getEditorFn().insertElement(e) }, useCustomEditor: function() { return 1 } }, WoltLab: { settings: { autoInsert: "html-embed-medium", sibling: 'li[data-name="settings"]', html: '<li %x><a><span class="icon icon16 fa-cloud-upload"></span> <span>%text</span></a></li>' }, check: "WBB", getEditorFn: function() { var t = $("#text").data("redactor"); return t || null } }, XF1: { settings: { autoInsert: "html-embed-medium", containerClass: 1, buttonClass: 1, html: '<li class="%cClass"><a %x class="%bClass" unselectable="on" title="%text">%iconSvg</a></li>', sibling: ".redactor_btn_container_image", siblingPos: "before", css: "li.%cClass .%bClass{background:%1;color:%2;text-indent:unset;border-radius:3px;position:relative}li.%cClass a.%bClass:hover{background:%3;color:%4;border-color:%5}.%cClass .%bClass svg{font-size:15px;width:1em;height:1em;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;left:50%;top:50%;fill:currentColor}", observe: ".edit.OverlayTrigger", observeCache: 1 }, palettes: { default: ["none", "inherit", "none", "inherit", ""] }, check: "XenForo", getEditorFn: function() { var t = document.querySelector("#exposeMask") && document.querySelector("#exposeMask").offsetParent ? ".xenOverlay form": "form"; if ("form" !== t) for (var e = document.querySelectorAll(t), i = 0; i < e.length; i++) if (e[i].offsetParent) { t += '[action="' + e[i].getAttribute("action") + '"]'; break } return XenForo.getEditorInForm(t) }, getEditor: function() { var t = this.getEditorFn(); return t ? this.useCustomEditor() ? t.$box[0] : t[0] : null }, getEditorEl: function() { return this.useCustomEditor() ? this.getEditorFn().$editor[0] : this.getEditorFn()[0] }, editorValue: function(t) { var e = "<p><br></p>", i = this.useCustomEditor() ? "innerHTML": "value"; if ("string" != typeof t) { var s = this.getEditorEl()[i]; return this.useCustomEditor() && "<p><br></p>" == s ? "": this.getEditorEl()[i] } if (this.useCustomEditor()) { var n = "<p>" + t + "</p>"; this.getEditorFn().insertHtml("" !== this.editorValue() ? e + n: n) } else this.getEditorEl()[i] = t }, useCustomEditor: function() { return ! (this.getEditorFn() instanceof jQuery) } }, XF2: { settings: { autoInsert: "html-embed-medium", containerClass: 1, buttonClass: "button--link js-attachmentUpload button button--icon button--icon--upload fa--xf", html: '<div class="formButtonGroup"><div class="formButtonGroup-extra"><button type="button" tabindex="-1" role="button" title="%text" class="%bClass" %x><span class="button-text">%text</span></button></div></div>', sibling: "", siblingPos: "after", observe: '[data-xf-click="quick-edit"]', observeCache: 1 }, palettes: { default: ["transparent", "#505050", "rgba(20,20,20,0.06)", "#141414"] }, check: "XF", getEditorFn: function(t) { var e = ".js-editor"; return "string" == typeof t && (e = this.getEditorSel(t)), XF.getEditorInContainer($(e)) }, getEditorSel: function(e) { return "[" + t.ns.dataPluginTarget + '="' + e + '"]' }, getEditor: function(t) { return "string" == typeof t ? document.querySelector(this.getEditorSel(t)) : document.querySelectorAll(".js-editor") }, getBbCode: function(t) { return t.getTextArea()[0].value }, editorValue: function(t, e) { var i = "<p><br></p>", s = this.getEditorFn(e), n = s.ed.bbCode.isBbCodeView() ? ["bbCode", "getBbCode", "insertBbCode"] : ["html", "get", "insert"], r = s.ed[n[0]]; if ("string" != typeof t) { if (void 0 === r[n[1]]) var o = this.getBbCode(r); else o = r[n[1]](); return this.useCustomEditor() && o == i ? "": o } var a = "" !== this.editorValue(!1, e); if ("html" == n[0]) { var l = "<p>" + t + "</p>"; r[n[2]](a ? i + l: l) } else { var d = XF.ajax("POST", XF.canonicalizeUrl("index.php?editor/to-bb-code"), { html: t }); d.done(function(t) { r[n[2]](a ? "\n" + t.bbCode: t.bbCode) }) } }, useCustomEditor: function() { return void 0 !== XF.getEditorInContainer($(".js-editor")) } } }, generateGuid: function() { var t = (new Date).getTime(); return "undefined" != typeof performance && "function" == typeof performance.now && (t += performance.now()), "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(e) { var i = (t + 16 * Math.random()) % 16 | 0; return t = Math.floor(t / 16), ("x" === e ? i: 3 & i | 8).toString(16) }) }, getNewValue: function(t, e) { var i = "string" != typeof t.getAttribute("contenteditable") ? "value": "innerHTML", s = "value" == i ? "\n": "<br>", n = t[i], r = e, o = !1; if (o && (r = String(e).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """)), 0 == n.length) return r; var a = "", l = n.match(/\n+$/g), d = l ? l[0].split("\n").length: 0; if (d <= 2) { var u = 0 == d ? 2 : 1; a += s.repeat(u) } return a + r }, insertTrigger: function() { var t, e = this.vendors[this.settings.vendor], i = this.settings.sibling ? document.querySelectorAll(this.settings.sibling + ":not([" + this.ns.dataPlugin + "])")[0] : 0; if ("auto" == this.settings.mode) t = this.vendors[e.hasOwnProperty("getEditor") ? this.settings.vendor: "default"].getEditor(); else { for (var s = document.querySelectorAll("[" + this.ns.dataPluginTrigger + "][data-target]:not([" + this.ns.dataPluginId + "])"), n = [], r = 0; r < s.length; r++) n.push(s[r].dataset.target); n.length > 0 && (t = document.querySelectorAll(n.join(","))) } if (t) { if (!document.getElementById(this.ns.pluginStyle) && this.settings.css) { var o = document.createElement("style"), a = this.settings.css; a = this.appyTemplate(a), o.type = "text/css", o.innerHTML = a.replace(/%p/g, "." + this.ns.plugin), o.setAttribute("id", this.ns.pluginStyle), document.body.appendChild(o) } t instanceof NodeList || (t = [t]); var l = 0; for (r = 0; r < t.length; r++) if (!t[r].getAttribute(this.ns.dataPluginTarget)) { var d = i || t[r]; d.setAttribute(this.ns.dataPlugin, "sibling"), d.insertAdjacentHTML({ before: "beforebegin", after: "afterend" } [this.settings.siblingPos], this.appyTemplate(this.settings.html)); var u = d.parentElement.querySelector("[" + this.ns.dataPluginTrigger + "]"); this.setBoundId(u, t[r]), l++ } this.triggerCounter = l, "function" == typeof e.callback && e.callback.call() } }, appyTemplate: function(t) { if (!this.cacheTable) { var e = [{ "%iconSvg": this.iconSvg }, { "%text": this.settings.langString }]; if (this.palette) { for (var i = /%(\d+)/g, s = i.exec(t), n = []; null !== s;) - 1 == n.indexOf(s[1]) && n.push(s[1]), s = i.exec(t); if (n) { n.sort(function(t, e) { return e - t }); this.vendors[this.settings.vendor]; for (var r = 0; r < n.length; r++) { var o = n[r] - 1, a = this.palette[o] || ""; a || "default" === this.settings.vendor || "default" === this.settings.palette || (a = this.palette[o - 2]); var l = {}; l["%" + n[r]] = a, e.push(l) } } } var d = this.settings.buttonClass || this.ns.plugin + "-button", u = [{ "%cClass": this.settings.containerClass || this.ns.plugin + "-container" }, { "%bClass": d }, { "%iClass": d + "-icon" }, { "%tClass": d + "-text" }, { "%x": this.ns.dataPluginTrigger }, { "%p": this.ns.plugin }]; for (r = 0; r < u.length; r++) e.push(u[r]); this.cacheTable = e } return this.strtr(t, this.cacheTable) }, strtr: function(t, e) { t = t.toString(); if (!t || void 0 === e) return t; for (var i = 0; i < e.length; i++) { var s = e[i]; for (var n in s) void 0 !== s[n] && (re = new RegExp(n, "g"), t = t.replace(re, s[n])) } return t }, setBoundId: function(t, e) { var i = this.generateGuid(); t.setAttribute(this.ns.dataPluginId, i), e.setAttribute(this.ns.dataPluginTarget, i) }, openPopup: function(t) { if ("string" == typeof t) { var e = this; if (void 0 === this.popups && (this.popups = {}), void 0 === this.popups[t]) { this.popups[t] = {}; var i = { l: null != window.screenLeft ? window.screenLeft: screen.left, t: null != window.screenTop ? window.screenTop: screen.top, w: window.innerWidth ? window.innerWidth: document.documentElement.clientWidth ? document.documentElement.clientWidth: screen.width, h: window.innerHeight ? window.innerHeight: document.documentElement.clientHeight ? document.documentElement.clientHeight: screen.height }, s = { w: 720, h: 690 }, n = { w: .5, h: .85 }; for (var r in s) s[r] / i[r] > n[r] && (s[r] = i[r] * n[r]); var o = { l: Math.trunc(i.w / 2 - s.w / 2 + i.l), t: Math.trunc(i.h / 2 - s.h / 2 + i.t) }; this.popups[t].window = window.open(this.settings.url, t, "width=" + s.w + ",height=" + s.h + ",top=" + o.t + ",left=" + o.l), this.popups[t].timer = window.setInterval(function() { e.popups[t].window && !1 === e.popups[t].window.closed || (window.clearInterval(e.popups[t].timer), e.popups[t] = void 0) }, 200) } else this.popups[t].window.focus() } }, postSettings: function(t) { this.popups[t].window.postMessage({ id: t, settings: this.settings }, this.settings.url) }, liveBind: function(t, e, i) { document.addEventListener(e, function(e) { var s = document.querySelectorAll(t); if (s) { for (var n = e.target, r = -1; n && -1 === (r = Array.prototype.indexOf.call(s, n));) n = n.parentElement; r > -1 && (e.preventDefault(), i.call(e, n)) } }, !0) }, prepare: function() { var t = this; this.ns.dataPlugin = "data-" + this.ns.plugin, this.ns.dataPluginId = this.ns.dataPlugin + "-id", this.ns.dataPluginTrigger = this.ns.dataPlugin + "-trigger", this.ns.dataPluginTarget = this.ns.dataPlugin + "-target", this.ns.pluginStyle = this.ns.plugin + "-style", this.ns.selDataPluginTrigger = "[" + this.ns.dataPluginTrigger + "]"; var e = document.currentScript || document.getElementById(this.ns.plugin + "-src"); e ? e.dataset.buttonTemplate && (e.dataset.html = e.dataset.buttonTemplate) : e = { dataset: {} }; var i = 0; for (var s in this.settings = {}, this.defaultSettings) { var n = e && e.dataset[s] ? e.dataset[s] : this.defaultSettings[s]; "1" !== n && "0" !== n || (n = "true" == n), "string" == typeof n && this.classProps.indexOf(s.replace(/Class$/, "")) > -1 && (i = 1), this.settings[s] = n } if ("auto" == this.settings.vendor) for (var s in this.settings.vendor = "default", this.settings.fitEditor = 0, this.vendors) if ("default" != s && void 0 !== window[this.vendors[s].check]) { this.settings.vendor = s; break } var r = ["lang", "url", "vendor", "target"]; "default" == this.settings.vendor && (this.vendors. default.settings = {}); var o = this.vendors[this.settings.vendor]; if (o.settings) for (var s in o.settings) e && e.dataset.hasOwnProperty(s) || (this.settings[s] = o.settings[s]); else for (var s in o.settings = {}, this.defaultSettings) - 1 == r.indexOf(s) && (o.settings[s] = this.defaultSettings[s]); if ("default" !== this.settings.vendor) if (o.settings.hasOwnProperty("fitEditor") || e.dataset.hasOwnProperty("fitEditor") || (this.settings.fitEditor = 1), this.settings.fitEditor) i = !o.settings.css; else { r = ["autoInsert", "observe", "observeCache"]; for (var s in o.settings) - 1 != r.indexOf(s) || e.dataset.hasOwnProperty(s) || (this.settings[s] = this.defaultSettings[s]) } if (i) this.settings.css = ""; else { this.settings.css = this.settings.css.replace("%defaultCSS", this.defaultSettings.css), o.settings.extracss && this.settings.css && (this.settings.css += o.settings.extracss); var a = this.settings.palette.split(","); a.length > 1 ? this.palette = a: this.palettes.hasOwnProperty(a) || (this.settings.palette = "default"), this.palette || (this.palette = (this.settings.fitEditor && o.palettes && o.palettes[this.settings.palette] ? o: this).palettes[this.settings.palette]) } for (var l = this.classProps, d = 0; d < l.length; d++) { var u = l[d] + "Class"; "string" != typeof this.settings[u] && (this.settings[u] = this.ns.plugin + "-" + l[d], this.settings.fitEditor && (this.settings[u] += "--" + this.settings.vendor)) } var c = ("auto" == this.settings.lang ? navigator.language || navigator.userLanguage: this.settings.lang).replace("-", "_"); this.settings.langString = "Upload images"; var g = c in this.l10n ? c: c.substring(0, 2) in this.l10n ? c.substring(0, 2) : null; g && (this.settings.langString = this.l10n[g]); var h = document.createElement("a"); h.href = this.settings.url, this.originUrlPattern = "^" + (h.protocol + "//" + h.hostname).replace(/\./g, "\\.").replace(/\//g, "\\/") + "$"; var f = document.querySelectorAll(this.ns.selDataPluginTrigger + "[data-target]"); if (f.length > 0) for (d = 0; d < f.length; d++) { var p = document.querySelector(f[d].dataset.target); this.setBoundId(f[d], p) } if (this.settings.observe) { var b = this.settings.observe; this.settings.observeCache && (b += ":not([" + this.ns.dataPlugin + "])"), this.liveBind(b, "click", function(e) { e.setAttribute(t.ns.dataPlugin, 1), t.observe() }.bind(this)) } this.settings.sibling && !this.settings.onDemand ? this.waitForSibling() : "onload" == this.settings.init ? "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", function(e) { t.init() }, !1) : this.init() : this.observe() }, observe: function() { this.waitForSibling("observe") }, waitForSibling: function(t) { var e = this.initialized ? "insertTrigger": "init"; if (this.settings.sibling) var i = document.querySelector(this.settings.sibling + ":not([" + this.ns.dataPlugin + "])"); else if ("observe" == t && (this[e](), this.triggerCounter)) return; if (i) this[e](); else { if ("complete" === document.readyState && "observe" !== t) return; setTimeout(("observe" == t ? this.observe: this.waitForSibling).bind(this), 250) } }, init: function() { this.insertTrigger(); var t = this, e = this.vendors[this.settings.vendor]; this.liveBind(this.ns.selDataPluginTrigger, "click", function(e) { var i = e.getAttribute(t.ns.dataPluginId); t.openPopup(i) }), window.addEventListener("message", function(i) { var s = new RegExp(t.originUrlPattern, "i"); if (s.test(i.origin) || void 0 !== i.data.id && void 0 !== i.data.message) { var n = i.data.id; if (n && i.source === t.popups[n].window) if (i.data.requestAction && t.hasOwnProperty(i.data.requestAction)) t[i.data.requestAction](n); else { var r; if ("default" !== t.settings.vendor) { if (e.hasOwnProperty("useCustomEditor") && e.useCustomEditor()) return void e.editorValue(i.data.message, n); e.hasOwnProperty("getEditor") && (r = e.getEditor()) } if (r || (r = document.querySelector("[" + t.ns.dataPluginTarget + '="' + n + '"]'), r)) { var o = null === r.getAttribute("contenteditable") ? "value": "innerHTML"; r[o] += t.getNewValue(r, i.data.message); for (var a = ["blur", "focus", "input", "change", "paste"], l = 0; l < a.length; l++) { var d = new Event(a[l]); r.dispatchEvent(d) } } else alert("Target not found") } } }, !1), this.initialized = 1 } }, e = ["WoltLab", "XF1"], i = 0; i < e.length; i++) t.vendors[e[i]] = Object.assign(Object.assign({}, t.vendors.redactor2), t.vendors[e[i]]); t.prepare()})();格式化后的pup.js需要修改三个地方,如下:
.png)
url: "https://demo.chevereto.com/upload"修改为目标图床的上传链接,如
url: "https://pic.6zs.cn/upload"将mode: "auto"改为mode: "manual",即让js默认不自动放置上传按钮。 将autoInsert: "bbcode-embed-medium"修改为autoInsert: "html-embed",即让js自动返回HTML格式的图片链接。 另外一个可选的修改项是上传按钮的外观样式,palette: "default",有下面多种外观可选,如果你想使用black样式,将palette: "default"修改为palette: "black"即可。
default: ["#ececec", "#333", "#2980b9", "#fff"], clear: ["inherit", "inherit", "inherit", "#2980b9"], turquoise: ["#16a085", "#fff", "#1abc9c", "#fff"], green: ["#27ae60", "#fff", "#2ecc71", "#fff"], blue: ["#2980b9", "#fff", "#3498db", "#fff"], purple: ["#8e44ad", "#fff", "#9b59b6", "#fff"], darkblue: ["#2c3e50", "#fff", "#34495e", "#fff"], yellow: ["#f39c12", "#fff", "#f1c40f", "#fff"], orange: ["#d35400", "#fff", "#e67e22", "#fff"], red: ["#c0392b", "#fff", "#e74c3c", "#fff"], grey: ["#ececec", "#000", "#e0e0e0", "#000"], black: ["#333", "#fff", "#666", "#fff"]修改完成的部分代码如下:
(function() { for (var t = { defaultSettings: { url: "https://pic.6zs.cn/upload", vendor: "auto", mode: "manual", lang: "auto", autoInsert: "html-embed", palette: "black", init: "onload", containerClass: 1, buttonClass: 1, sibling: 0, siblingPos: "after", fitEditor: 0, observe: 0, observeCache: 1, html: '<div class="%cClass"><button %x class="%bClass"><span class="%iClass">%iconSvg</span><span class="%tClass">%text</span></button></div>', css: ".%cClass{display:inline-block;margin-top:5px;margin-bottom:5px}.%bClass{line-height:normal;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s;outline:0;color:%2;border:none;cursor:pointer;border:1px solid rgba(0,0,0,.15);background:%1;border-radius:.2em;padding:.5em 1em;font-size:12px;font-weight:700;text-shadow:none}.%bClass:hover{background:%3;color:%4;border-color:rgba(0,0,0,.1)}.%iClass,.%tClass{display:inline-block;vertical-align:middle}.%iClass svg{display:block;width:1em;height:1em;fill:currentColor}.%tClass{margin-left:.25em}" },将修改后的pup.js保存到网站的js目录,如放到/usr/themes/handsome/assets/js目录下,此时pup.js的文件路径为/usr/themes/handsome/assets/js/pup.js 之后和前边一样,将
<script async src="/usr/themes/handsome/assets/js/pup.js"></script>放入到head之中,此时只是单纯引入js即可,不必指定参数data-auto-insert="html-embed" data-mode="manual"和上传链接url="https://pic.6zs.cn/upload",因为参数已经在js里边写死了。 最后一步,需要增加PJAX回调函数使pup.js跟随页面重载,在回调函数中写入
$.getScript("/usr/themes/handsome/assets/js/pup.js")到这了,本文差不多结束了,来总结一下:
- 放行HTML标签
- 获取图床上传插件
- 将插件代码插入到<#head>中
- 新建按钮,并放在合适的位置
- 给按钮美化一下
- 配置PJAX函数回调
如果要更换图床怎么办?如果你能够解决PJAX回调,只需要把插件链接里的
src="//www.picb.cc/sdk/pup.js" data-url="https://www.picb.cc/upload"替换掉即可。注意要保留data-auto-insert="html-embed" data-mode="manual"这两个参数。 如果你不会PJAX回调,直接修改js文件里的url: "https://pic.6zs.cn/upload",将链接修改为目标图床的链接即可。
最后,分享一些使用Chevereto搭建的图床
- PICBCC:https://www.picb.cc/
- 路过图床:https://imgtu.com/
- 知晓图床:https://tu.jilu.info/
- SM图床:https://www.imgsm.com/
- 鸡霸图床(老王图床):https://img.gejiba.com/
- 靠谱图床:https://img.bqe.cc/
- 伏名图床:https://ccsyn.org/
- 安享图床:https://img.ax/
本站图床由:https://pic.6zs.cn/提供。
完结!感谢您的阅览。
[/collapse]
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!

