From 7d2a98a45420ccaf845336ec3eac3d9a6caababd Mon Sep 17 00:00:00 2001 From: Arronlong Date: Sun, 31 Jan 2021 03:26:08 +0800 Subject: [PATCH 01/16] =?UTF-8?q?=E5=BC=80=E6=BA=90index.js=EF=BC=8C?= =?UTF-8?q?=E8=AF=A6=E8=A7=81index=5Fplus.js=EF=BC=8C=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=BB=E9=A2=98=E4=B8=AD=E7=9A=84=E4=B8=BB=E9=A2=98=E5=9C=B0?= =?UTF-8?q?=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 40 +- index_decrypt.js | 603 ++++++++++++++++++++++ index_plus.js | 898 +++++++++++++++++++++++++++++++++ themes/JustNews/article.html | 18 +- themes/JustNews/index.html | 18 +- themes/default/index.html | 2 +- themes/default2.0/article.html | 2 +- themes/default2.0/index.html | 2 +- themes/yinwang/article.html | 8 +- themes/yinwang/index.html | 8 +- 10 files changed, 1554 insertions(+), 45 deletions(-) create mode 100644 index_decrypt.js create mode 100644 index_plus.js diff --git a/README.md b/README.md index 0187743a..c7c3c06e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,24 @@ +本项目**CFBlog-Plus**是由基于[gdtool/cloudflare-workers-blog](https://github.com/gdtool/cloudflare-workers-blog)二次开发而来,主要是对cf worker中的js进行自主开源,并扩展了许多功能。 + +## 与CF-Blog相比,有哪些变更: + +1. 开源部署在workers中的js,根据自己的理解,进行自主开发并开源,详见[index_plus.js](https://github.com/Arronlong/cfblog-plus/blob/master/index_plus.js) +2. 扩展md编辑器配置,可以自行根据需要修改配置。目前可配置支持html标签解析(默认关闭),更多设置参考[editormd官网](https://pandao.github.io/editor.md/) +3. 后台新建页和编辑页,自动设置时间和默认图片(使用JustNews主题时必须设置,否则样式大变),默认图片为:![](https://cdn.jsdelivr.net/gh/Arronlong/cdn@master/cfblog/cfblog-plus.png) + +一些功能还在规划中: +1. 文章公开、隐藏设置 +2. 文章置顶设置 +3. 文章独立密码 +4. 静态搜索 + +--- + > 这是一个运行在cloudflare workers 上的博客程序,使用 cloudflare KV作为数据库,无其他依赖. 兼容静态博客的速度,以及动态博客的灵活性,方便搭建不折腾. -演示地址: [https://blog.gezhong.vip](https://blog.gezhong.vip "cf-blog演示站点") +演示地址: [https://blog.arrontg.cf](https://blog.arrontg.cf ) -### TG 讨论群: [@CloudflareBlog](https://t.me/cloudflareblog "") +### 原CFBlog-TG 讨论群: [@CloudflareBlog](https://t.me/cloudflareblog ) # 主要特点 * 使用workers提供的KV作为数据库 * 使用cloudflare缓存html来降低KV的读写 @@ -12,32 +28,24 @@ * 一键发布(页面重构+缓存清理) # 承载能力 + * KV基本不存在瓶颈,因为使用了缓存,读写很少 * 唯一瓶颈是 workers的日访问量10w,大约能承受2万IP /日 * 文章数:1G存储空间,几万篇问题不大 # 部署步骤 - 这里没有实时预览真难受,一系列坑会慢慢填到博客,敬请关注 [https://blog.gezhong.vip](https://blog.gezhong.vip "") -# 更新日志 + [CFBlog-Plus搭建教程](https://blog.arrontg.cf/article/000004/.html) -> [持续更新地址https://blog.gezhong.vip/article/009000/update-log.html](https://blog.gezhong.vip/article/009000/update-log.html "更新日志") - -## 最近更新(2020-12-31) -* 2020-12-31:加入sitemap.xml -* 2020-12-24:本次更新,主要针对seo和阅读次数,以及多项细节优化 +# 更新日志 +[CFBLOG-PLUS更新日志](https://blog.arrontg.cf/article/000006/.html) +[CFBLOG更新日志](https://blog.gezhong.vip/article/009000/update-log.html) -### 前端演示:[https://blog.gezhong.vip](https://blog.gezhong.vip "演示站点") +### 前端演示: ![](https://s3.ax1x.com/2020/12/22/rrP81S.png) ### 后端演示: ![](https://s3.ax1x.com/2020/12/22/rrAWrD.png) - -## 捐赠 - -如果你觉的本项目帮到你了,还请资持一下作者 - -* [捐赠](https://afdian.net/@zhaopp "爱发电") diff --git a/index_decrypt.js b/index_decrypt.js new file mode 100644 index 00000000..fa8a992b --- /dev/null +++ b/index_decrypt.js @@ -0,0 +1,603 @@ +!function(t){ + var e={}; + function r(n){ + if(e[n]) + return e[n].exports; + var a=e[n]={i:n,l:!1,exports:{}}; + return t[n].call(a.exports,a,a.exports,r),a.l=!0,a.exports + } + r.m=t,r.c=e, + r.d=function(t,e,n){ + r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n}) + } + ,r.r=function(t){ + "undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0}) + } + ,r.t=function(t,e){ + if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var a in t)r.d(n,a,function(e){return t[e]}.bind(null,a));return n + } + ,r.n=function(t){ + var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e + } + ,r.o=function(t,e){ + return Object.prototype.hasOwnProperty.call(t,e) + } + ,r.p="",r(r.s=0) +} +([ + function(t,e,r){t.exports=r(1)} + + //处理请求 + ,function(t,e,r){ + "use strict"; + const n=r(2); + + //博客前端主页 + async function a(t,e,r){ + e=decodeURI(e); + //获取主页模板源码 + let a=await g("index"), + //KV中读取导航栏、分类目录、标签、链接、近期文章等配置信息 + s=await l("SYSTEM_VALUE_WidgetMenu",!0), + o=await l("SYSTEM_VALUE_WidgetCategory",!0), + c=await l("SYSTEM_VALUE_WidgetTags",!0), + u=await l("SYSTEM_VALUE_WidgetLink",!0), + p=(await l("SYSTEM_INDEX_LIST",!0)).slice(0,OPT.recentlySize); + + for(var h=0;h-1||n[i].category.indexOf(t)>-1)&&a.push(n[i]);a=p(a,"id"); + let o=!(a.length>r*e),c=[]; + for(i=(e-1)*r,s=Math.min(e*r,a.length);ie*t),a=[]; + for(var i=(t-1)*e,s=Math.min(t*e,r.length);i=0&&t<=9?"0"+t:t + } + //获取主题指定页的模板源码 + async function g(t){ + return t=t.replace(".html",""),(await fetch(OPT.themeURL+t+".html",{cf:{cacheTtl:600}})).text() + } + //排序 + function p(t,e,r=!0){ + return t.sort((function(t,n){var a=t[e],i=n[e];return r?a>i?-1:ai?1:0})) + } + //判断是否为对象,若为字符串,则尝试转json后再判断 + function h(t){ + if("string"==typeof t)try{var e=JSON.parse(t);return!("object"!=typeof e||!e)}catch(t){return!1}return!("object"!=typeof t||!t) + } + //获取标签、分类列表? + async function f(t){ + const{headers:e}=t,r=e.get("content-type")||""; + if(r.includes("application/json")){ + let e=JSON.stringify(await t.json()),r=JSON.parse(e),a={category:[]}; + for(var n=0;n{ + t.respondWith(async function(t){ + let e=t.request, + //获取url请求对象 + r=new URL(t.request.url); + //默认为非私密博客 + null==OPT.privateBlog&&(OPT.privateBlog=!1); + //解析请求路径,按/分组 + /* + 【后台】 + 域名/admin 后台主页 + 域名/admin/export 后台导出 + + 【前台】 + 域名/ 前台主页 + 域名/category/xxx 分类页 + 域名/tags/xxx 标签页 + 域名/page/xxx 文章列表翻页 + 域名/article/文章id/文章url.html 文章详情页 + */ + let i=r.pathname.trim("/").split("/"); + + //访问管理后台或私密博客,则进行Base Auth + if(("admin"===i[0]||!0===OPT.privateBlog)&&!function(t){ + const e=t.headers.get("Authorization"); + if(!e||!/^Basic [A-Za-z0-9._~+/-]+=*$/i.test(e)) + return!1; + const[r,n]=function(t){ + try{ + return atob(t.split(" ").pop()).split(":") + }catch(t){ + return[] + } + }(e); + return console.log("-----parseBasicAuth----- ",r,n),r===OPT.user&&n===OPT.password + }(t.request))//Base Auth校验失败,返回401 + return new Response("Unauthorized",{ + headers:{ + "WWW-Authenticate":'Basic realm="cfblog"', + "Access-Control-Allow-Origin":"*" + } + ,status:401 + }); + + //导出文章 + if("admin"===i[0]&&"export"===i[1]){ + console.log("开始导出"); + let t=await async function t(e=[],r="",n=1){ + const a=await CFBLOG.list({limit:n,cursor:r}); + if(!1 in a)return{}; + if(e=e.concat(a.keys),console.log("导出: ",typeof a,JSON.stringify(a)),a.list_complete){ + let t={OPT:OPT}; + for(let r=0;r",e+="\n\t\t"+t[r].createDate.substr(0,10)+"",e+="\n\t\t"+(void 0===t[r].changefreq?"daily":t[r].changefreq)+"",e+="\n\t\t"+(void 0===t[r].priority?"0.5":t[r].priority)+"",e+="\n\t"; + return e+="\n",e + }(),{ + headers:{ + "content-type":"text/xml;charset=UTF-8" + } + ,status:200 + }); + + else{ + + //非sitemap.xml + let e=await async function(t){ + //解析请求的url,并用/分割 + let e=new URL(t.url).pathname.trim("/").split("/"),r="", //一级路径::category/tags/page/article,默认page + i="", //二级路径,默认page的第1页 + u=""; //三级路径,目前只有文章详情页的url + 0==e.length||""==e[0]?(r="page",i="1"):(r=e[0],i=void 0===e[1]?1:e[1],u=void 0===e[2]?1:e[2]); + + //分页 + if("page"==r&&parseInt(i)>0) + return await async function(t,e){ + //读取主题的index.html源码 + let r=await g("index"), + //KV中读取导航栏、分类目录、标签、链接、近期文章等配置信息 + a=await l("SYSTEM_VALUE_WidgetMenu",!0), + i=await l("SYSTEM_VALUE_WidgetCategory",!0), + s=await l("SYSTEM_VALUE_WidgetTags",!0), + o=await l("SYSTEM_VALUE_WidgetLink",!0), + c=await l("SYSTEM_INDEX_LIST",!0), + u=c.slice(0,OPT.recentlySize); + + for(var p=0;p=c.length&&(d=[]); + //文章标题、关键字 + let w=(e>1?"page "+e+" - ":"")+OPT.siteName,y=OPT.keyWords,m={}; + m.widgetMenuList=a,//导航 + m.widgetCategoryList=i,//分类目录 + m.widgetTagsList=s,//标签 + m.widgetLinkList=o,//链接 + m.widgetRecentlyList=u,//近期文章 + m.articleList=h,//当前页文章列表 + m.pageNewer=f,//上翻页链接 + m.pageOlder=d,//下翻页链接 + m.title=w,//网页title + m.keyWords=y;//SEO关键字 + + //使用mustache.js进行页面渲染(参数替换) + let S=Object.assign({},OPT); + return S.password="",S.user="",S.cacheToken="",S.cacheZoneId="",m.OPT=S,n.render(r,m) + + }(0,parseInt(i)); + + //当前r:一级路径,i:二级路径,u:三级路径 + + //分类页 + if("category"==r&&i.length>0) + return await a(r,i,parseInt(u)); + + //标签页 + if("tags"==r&&i.length>0) + return await a(r,i,parseInt(u)); + + //文章详情页 + if("article"==r&&i.length>0) + return await async function(t,e,r){ + //读取主题的index.html源码 + let a=await g("article"), + //KV中读取导航栏、分类目录、标签、链接、近期文章等配置信息 + i=await l("SYSTEM_VALUE_WidgetMenu",!0), + o=await l("SYSTEM_VALUE_WidgetCategory",!0), + c=await l("SYSTEM_VALUE_WidgetTags",!0), + u=await l("SYSTEM_VALUE_WidgetLink",!0),p=(await l("SYSTEM_INDEX_LIST",!0)).slice(0,OPT.recentlySize); + + for(var h=0;h格式的参数 + return t.r("categoryJson",JSON.stringify(e)) + .r("menuJson",JSON.stringify(r)) + .r("linkJson",JSON.stringify(n)) + + } + + //发布 + if("publish"==e[1]){ + + //KV中获取文章列表 + let t=await l("SYSTEM_INDEX_LIST",!0),e=[]; + + //遍历所有文章 + for(var r=0;r格式的参数 + return r.r("categoryJson",n) + .r("articleJson",a.replaceAll("script>","script>")) + } + + //保存配置 + if("saveConfig"==e[1]){ + const e=await f(t); + let r=e.WidgetCategory,//分类 + n=e.WidgetMenu,//导航 + a=e.WidgetLink;//链接 + + //判断格式,写入分类、导航、链接到KV中 + return h(r)&&h(n)?(await c("SYSTEM_VALUE_WidgetCategory",r),await c("SYSTEM_VALUE_WidgetMenu",n),await c("SYSTEM_VALUE_WidgetLink",a),'{"msg":"saved","rst":true}'):'{"msg":"Not a JSON object","rst":false}' + } + + //导入 + if("import"==e[1]){ + let e=(await f(t)).importJson; + if(console.log("开始导入",typeof e),h(e)){ + let t=JSON.parse(e),r=Object.keys(t); + for(let e=0;e0&&i.length>0&&s.length>0&&h.length>0&&d.length>0){ + // + y=await async function(){//KV中读取文章数量(初始化为1),并格式化为6位,不足6位前面补零 + let t=await l("SYSTEM_INDEX_NUM"); + return""===t||null===t||"[]"===t||void 0===t?(await c("SYSTEM_INDEX_NUM",1),"000001"):(await c("SYSTEM_INDEX_NUM",parseInt(t)+1),("00000"+(parseInt(t)+1)).substr(-6)) + }(), + w=d.replace(/<\/?[^>]*>/g,"").trim().substring(0,OPT.readMoreLength);//摘要 + //组装文章json + let t={id:y,title:r,img:n,link:a,createDate:i,category:s,tags:o,contentMD:h,contentHtml:d,contentText:w,priority:u,changefreq:g}; + + //将文章json写入KV(key为文章id,value为文章json字符串) + await c(y,JSON.stringify(t)); + + //组装文章json + let e={id:y,title:r,img:n,link:a,createDate:i,category:s,tags:o,contentText:w,priority:u,changefreq:g}, + + //读取文章列表 + f=await l("SYSTEM_INDEX_LIST",!0),m=[]; + + //将最新的文章写入文章列表中,并按id排序后,再次回写到KV中 + return m.push(e),m=m.concat(f),m=p(m,"id"),await c("SYSTEM_INDEX_LIST",JSON.stringify(m)),'{"msg":"added OK","rst":true,"id":"'+y+'"}' + } + return'{"msg":"信息不全","rst":false}' + } + + //删除 + if("delete"==e[1]){ + let t=e[2];if(6==t.length){await CFBLOG.delete(t);let e=await l("SYSTEM_INDEX_LIST",!0);for(r=0;r0&&s.length>0&&o.length>0&&g.length>0&&h.length>0){ + y=h.replace(/<\/?[^>]*>/g,"").trim().substring(0,OPT.readMoreLength);let t={id:m,title:n,img:a,link:i,createDate:s,category:o,tags:u,contentMD:g,contentHtml:h,contentText:y,priority:d,changefreq:w};await c(m,JSON.stringify(t));let e={id:m,title:n,img:a,link:i,createDate:s,category:o,tags:u,contentText:y,priority:d,changefreq:w},f=await l("SYSTEM_INDEX_LIST",!0);for(r=0;r":">",'"':""","'":"'","/":"/","`":"`","=":"="},c=/\s*/,u=/\s+/,g=/\s*=/,p=/\s*\}/,h=/#|\^|\/|>|\{|&|=|!/;function f(t){this.string=t,this.tail=t,this.pos=0}function d(t,e){this.view=t,this.cache={".":this.view},this.parent=e}function w(){this.templateCache={_cache:{},set:function(t,e){this._cache[t]=e},get:function(t){return this._cache[t]},clear:function(){this._cache={}}}}f.prototype.eos=function(){return""===this.tail},f.prototype.scan=function(t){var e=this.tail.match(t);if(!e||0!==e.index)return"";var r=e[0];return this.tail=this.tail.substring(r.length),this.pos+=r.length,r},f.prototype.scanUntil=function(t){var e,r=this.tail.search(t);switch(r){case-1:e=this.tail,this.tail="";break;case 0:e="";break;default:e=this.tail.substring(0,r),this.tail=this.tail.substring(r)}return this.pos+=e.length,e},d.prototype.push=function(t){return new d(t,this)},d.prototype.lookup=function(t){var e,n,i,s=this.cache;if(s.hasOwnProperty(t))e=s[t];else{for(var o,l,c,u=this,g=!1;u;){if(t.indexOf(".")>0)for(o=u.view,l=t.split("."),c=0;null!=o&&c0?a[a.length-1][4]:r;break;default:n.push(e)}return r}(function(t){for(var e,r,n=[],a=0,i=t.length;a"===s?o=this.renderPartial(i,e,r,a):"&"===s?o=this.unescapedValue(i,e):"name"===s?o=this.escapedValue(i,e,a):"text"===s&&(o=this.rawValue(i)),void 0!==o&&(l+=o);return l},w.prototype.renderSection=function(t,n,a,i,s){var o=this,l="",c=n.lookup(t[1]);if(c){if(e(c))for(var u=0,g=c.length;u0||!r)&&(a[i]=n+a[i]);return a.join("\n")},w.prototype.renderPartial=function(t,e,n,a){if(n){var i=this.getConfigTags(a),s=r(n)?n(t[1]):n[t[1]];if(null!=s){var o=t[6],l=t[5],c=t[4],u=s;0==l&&c&&(u=this.indentPartial(s,c,o));var g=this.parse(u,i);return this.renderTokens(g,e,n,u,a)}}},w.prototype.unescapedValue=function(t,e){var r=e.lookup(t[1]);if(null!=r)return r},w.prototype.escapedValue=function(t,e,r){var n=this.getConfigEscape(r)||y.escape,a=e.lookup(t[1]);if(null!=a)return"number"==typeof a&&n===y.escape?String(a):n(a)},w.prototype.rawValue=function(t){return t[1]},w.prototype.getConfigTags=function(t){return e(t)?t:t&&"object"==typeof t?t.tags:void 0},w.prototype.getConfigEscape=function(t){return t&&"object"==typeof t&&!e(t)?t.escape:void 0};var y={name:"mustache.js",version:"4.1.0",tags:["{{","}}"],clearCache:void 0,escape:void 0,parse:void 0,render:void 0,Scanner:void 0,Context:void 0,Writer:void 0,set templateCache(t){m.templateCache=t},get templateCache(){return m.templateCache}},m=new w;return y.clearCache=function(){return m.clearCache()},y.parse=function(t,e){return m.parse(t,e)},y.render=function(t,r,n,a){if("string"!=typeof t)throw new TypeError('Invalid template! Template should be a "string" but "'+(e(i=t)?"array":typeof i)+'" was given as the first argument for mustache#render(template, view, partials)');var i;return m.render(t,r,n,a)},y.escape=function(t){return String(t).replace(/[&<>"'`=\/]/g,(function(t){return l[t]}))},y.Scanner=f,y.Context=d,y.Writer=w,y}()} + ]); + diff --git a/index_plus.js b/index_plus.js new file mode 100644 index 00000000..2ae5a633 --- /dev/null +++ b/index_plus.js @@ -0,0 +1,898 @@ +'use strict'; +const ACCOUNT = { //账号相关,安全性更高 + + "user" : "admin", //博客后台用户名 + "password" : "cfblog-plus", //博客后台密码 + "cacheZoneId":"935xxxxxxxxxxxx",//区域 ID + "cacheToken":"AQxxxxxxxx",//API token + + "kv_var": this['CFBLOG'],//workers绑定kv时用的变量名 +} + +const OPT = { //网站配置 + "siteDomain" : "域名",// 域名(不带https 也不带/) + "siteName" : "CFBLOG-Plus",//博客名称 + "siteDescription":"CFBLOG-Plus" ,//博客描述 + "keyWords":"cloudflare,KV,workers,blog",//关键字 + "logo":"//cdn.jsdelivr.net/gh/Arronlong/cfblog-plus@master/themes/JustNews/files/logo2.png",//JustNews主题的logo + + //主题路径 + "theme_github_path":"//cdn.jsdelivr.net/gh/Arronlong/cfblog-plus@master/themes/", + "editor_page_scripts": ` + //关闭email匹配和@匹配,否则图片使用jsdelivr的cdn,如果有版本号会匹配成“mailto:xxx”从而导致显示异常 + mdEditor.settings.emailLink=false; + mdEditor.settings.atLink=false; + //开启html标签解析 + mdEditor.settings.htmlDecode=false; + //默认图片,工具:https://tool.lu/imageholder/ + if($('#img').val()=="")$('#img').val('https://cdn.jsdelivr.net/gh/Arronlong/cdn@master/cfblog/cfblog-plus.png'); + //默认时间设置为当前时间 + if($('#createDate').val()=="")$('#createDate').val(new Date(new Date().getTime()+8*60*60*1000).toJSON().substr(0,16)); + `, //后台编辑页面脚本 + + "pageSize" : 5,//每页文章数 + "recentlySize" : 6,//最近文章数 + "readMoreLength":150,//阅读更多截取长度 + "cacheTime" : 60*60*24*2, //网页缓存时长(秒),建议=文章更新频率 + "themeURL" : "https://raw.githubusercontent.com/Arronlong/cfblog-plus/master/themes/JustNews/", // 模板地址,以 "/"" 结尾 + "html404" : `404`,//404页面代码 + "codeBeforHead":` + + `,//其他代码,显示在前 + "codeBeforBody":``,//其他代码,显示在前 + "commentCode":` + `,//评论区代码 + "widgetOther":``,//20201224新增参数,用于右侧 小部件扩展 + "otherCodeA":`热度`,//模板开发用的其他自定义变量 + "otherCodeB":``,// + "otherCodeC":``,// + "otherCodeD":``,// + "otherCodeE":``,// + "copyRight" :`Powered by Cloudflare & CFBlog-Plus & CF-Blog `,//自定义版权信息,建议保留大公无私的 Coudflare 和 作者 的链接 + "robots":`User-agent: * +Disallow: /admin`//robots.txt设置 +}; + + +//CFBLOG 通用变量 +this.CFBLOG = ACCOUNT.kv_var; +//默认为非私密博客 +if(null==OPT.privateBlog){ + OPT.privateBlog=false; +} +//处理themeURL、theme_github_path参数设定 +if(OPT.themeURL.substr(-1)!='/'){ + OPT.themeURL=OPT.themeURL+'/'; +} +if(OPT.theme_github_path.substr(-1)!='/'){ + OPT.theme_github_path=OPT.theme_github_path+'/'; +} + +//引入mustache.js,4.1.0:https://cdn.bootcdn.net/ajax/libs/mustache.js/4.1.0/mustache.min.js +(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):(global=global||self,global.Mustache=factory())})(this,function(){"use strict";var objectToString=Object.prototype.toString;var isArray=Array.isArray||function isArrayPolyfill(object){return objectToString.call(object)==="[object Array]"};function isFunction(object){return typeof object==="function"}function typeStr(obj){return isArray(obj)?"array":typeof obj}function escapeRegExp(string){return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function hasProperty(obj,propName){return obj!=null&&typeof obj==="object"&&propName in obj}function primitiveHasOwnProperty(primitive,propName){return primitive!=null&&typeof primitive!=="object"&&primitive.hasOwnProperty&&primitive.hasOwnProperty(propName)}var regExpTest=RegExp.prototype.test;function testRegExp(re,string){return regExpTest.call(re,string)}var nonSpaceRe=/\S/;function isWhitespace(string){return!testRegExp(nonSpaceRe,string)}var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};function escapeHtml(string){return String(string).replace(/[&<>"'`=\/]/g,function fromEntityMap(s){return entityMap[s]})}var whiteRe=/\s*/;var spaceRe=/\s+/;var equalsRe=/\s*=/;var curlyRe=/\s*\}/;var tagRe=/#|\^|\/|>|\{|&|=|!/;function parseTemplate(template,tags){if(!template)return[];var lineHasNonSpace=false;var sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;var indentation="";var tagIndex=0;function stripSpace(){if(hasTag&&!nonSpace){while(spaces.length)delete tokens[spaces.pop()]}else{spaces=[]}hasTag=false;nonSpace=false}var openingTagRe,closingTagRe,closingCurlyRe;function compileTags(tagsToCompile){if(typeof tagsToCompile==="string")tagsToCompile=tagsToCompile.split(spaceRe,2);if(!isArray(tagsToCompile)||tagsToCompile.length!==2)throw new Error("Invalid tags: "+tagsToCompile);openingTagRe=new RegExp(escapeRegExp(tagsToCompile[0])+"\\s*");closingTagRe=new RegExp("\\s*"+escapeRegExp(tagsToCompile[1]));closingCurlyRe=new RegExp("\\s*"+escapeRegExp("}"+tagsToCompile[1]))}compileTags(tags||mustache.tags);var scanner=new Scanner(template);var start,type,value,chr,token,openSection;while(!scanner.eos()){start=scanner.pos;value=scanner.scanUntil(openingTagRe);if(value){for(var i=0,valueLength=value.length;i"){token=[type,value,start,scanner.pos,indentation,tagIndex,lineHasNonSpace]}else{token=[type,value,start,scanner.pos]}tagIndex++;tokens.push(token);if(type==="#"||type==="^"){sections.push(token)}else if(type==="/"){openSection=sections.pop();if(!openSection)throw new Error('Unopened section "'+value+'" at '+start);if(openSection[1]!==value)throw new Error('Unclosed section "'+openSection[1]+'" at '+start)}else if(type==="name"||type==="{"||type==="&"){nonSpace=true}else if(type==="="){compileTags(value)}}stripSpace();openSection=sections.pop();if(openSection)throw new Error('Unclosed section "'+openSection[1]+'" at '+scanner.pos);return nestTokens(squashTokens(tokens))}function squashTokens(tokens){var squashedTokens=[];var token,lastToken;for(var i=0,numTokens=tokens.length;i0?sections[sections.length-1][4]:nestedTokens;break;default:collector.push(token)}}return nestedTokens}function Scanner(string){this.string=string;this.tail=string;this.pos=0}Scanner.prototype.eos=function eos(){return this.tail===""};Scanner.prototype.scan=function scan(re){var match=this.tail.match(re);if(!match||match.index!==0)return"";var string=match[0];this.tail=this.tail.substring(string.length);this.pos+=string.length;return string};Scanner.prototype.scanUntil=function scanUntil(re){var index=this.tail.search(re),match;switch(index){case-1:match=this.tail;this.tail="";break;case 0:match="";break;default:match=this.tail.substring(0,index);this.tail=this.tail.substring(index)}this.pos+=match.length;return match};function Context(view,parentContext){this.view=view;this.cache={".":this.view};this.parent=parentContext}Context.prototype.push=function push(view){return new Context(view,this)};Context.prototype.lookup=function lookup(name){var cache=this.cache;var value;if(cache.hasOwnProperty(name)){value=cache[name]}else{var context=this,intermediateValue,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){intermediateValue=context.view;names=name.split(".");index=0;while(intermediateValue!=null&&index")value=this.renderPartial(token,context,partials,config);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context,config);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate,config){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials,config)}if(!value)return;if(isArray(value)){for(var j=0,valueLength=value.length;j0||!lineHasNonSpace)){partialByNl[i]=filteredIndentation+partialByNl[i]}}return partialByNl.join("\n")};Writer.prototype.renderPartial=function renderPartial(token,context,partials,config){if(!partials)return;var tags=this.getConfigTags(config);var value=isFunction(partials)?partials(token[1]):partials[token[1]];if(value!=null){var lineHasNonSpace=token[6];var tagIndex=token[5];var indentation=token[4];var indentedValue=value;if(tagIndex==0&&indentation){indentedValue=this.indentPartial(value,indentation,lineHasNonSpace)}var tokens=this.parse(indentedValue,tags);return this.renderTokens(tokens,context,partials,indentedValue,config)}};Writer.prototype.unescapedValue=function unescapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return value};Writer.prototype.escapedValue=function escapedValue(token,context,config){var escape=this.getConfigEscape(config)||mustache.escape;var value=context.lookup(token[1]);if(value!=null)return typeof value==="number"&&escape===mustache.escape?String(value):escape(value)};Writer.prototype.rawValue=function rawValue(token){return token[1]};Writer.prototype.getConfigTags=function getConfigTags(config){if(isArray(config)){return config}else if(config&&typeof config==="object"){return config.tags}else{return undefined}};Writer.prototype.getConfigEscape=function getConfigEscape(config){if(config&&typeof config==="object"&&!isArray(config)){return config.escape}else{return undefined}};var mustache={name:"mustache.js",version:"4.1.0",tags:["{{","}}"],clearCache:undefined,escape:undefined,parse:undefined,render:undefined,Scanner:undefined,Context:undefined,Writer:undefined,set templateCache(cache){defaultWriter.templateCache=cache},get templateCache(){return defaultWriter.templateCache}};var defaultWriter=new Writer;mustache.clearCache=function clearCache(){return defaultWriter.clearCache()};mustache.parse=function parse(template,tags){return defaultWriter.parse(template,tags)};mustache.render=function render(template,view,partials,config){if(typeof template!=="string"){throw new TypeError('Invalid template! Template should be a "string" '+'but "'+typeStr(template)+'" was given as the first '+"argument for mustache#render(template, view, partials)")}return defaultWriter.render(template,view,partials,config)};mustache.escape=escapeHtml;mustache.Scanner=Scanner;mustache.Context=Context;mustache.Writer=Writer;return mustache}); + +//扩展String的方法: +//trim清除前后空格 +String.prototype.trim=function(t){ + return t?this.replace(new RegExp("^\\"+t+"+|\\"+t+"+$","g"),""):this.replace(/^\s+|\s+$/g,"") +} +//replaceHtmlPara替换 +String.prototype.replaceHtmlPara=function(t,e){ + return null!=e&&(e=e.replace(new RegExp("[$]","g"),"$$$$")),this.replace(new RegExp("\x3c!--{"+t+"}--\x3e","g"),e) +} +//replaceAll 替换全部 +String.prototype.replaceAll=function(t,e){ + return this.replace(new RegExp(t,"g"),e) +} + +//小于2位,前面补个0 +function pad(t){ + return t>=0&&t<=9?"0"+t:t +} + +//排序(默认倒序) +function sort(arr, field, desc=true){ + return arr.sort((function(m,n){ + var a=m[field], + b=n[field]; + return desc?(a>b?-1:(ab?1:0)) + })) +} + +//判断格式:字符串是否为json,或者参数是否为对象 +function checkFormat(t){ + if("string"==typeof t){ + try{ + var e=JSON.parse(t); + return !("object"!=typeof e||!e) + }catch(t){ + return false + } + } + return !("object"!=typeof t||!t) +} + +/**------【猎杀时刻】-----**/ + + +//获取主题指定页的模板源码, template_path:模板的相对路径 +async function getThemeHtml(template_path){ + template_path=template_path.replace(".html","") + let html = await (await fetch(OPT.themeURL+template_path+".html",{cf:{cacheTtl:600}})).text(); + + //对后台编辑页下手 + if("admin/index|admin/editor".includes(template_path)){ + html = html.replace("$('#WidgetCategory').val(JSON.stringify(categoryJson))",OPT.editor_page_scripts+"$('#WidgetCategory').val(JSON.stringify(categoryJson))") + } + + return html +} + +/* 【KV的Key的含义】 + SYSTEM_VALUE_WidgetMenu 导航栏 + SYSTEM_VALUE_WidgetCategory 分类目录 + SYSTEM_VALUE_WidgetTags 标签 + SYSTEM_VALUE_WidgetLink 链接 + SYSTEM_INDEX_LIST 文章列表(不包含内容) + SYSTEM_INDEX_NUM 文章数量 +*/ +//KV读取,toJson是否转为json,默认false +async function getKV(key, toJson=false){ + console.log("------------KV读取------------key,toJson:", key, toJson); + let value=await CFBLOG.get(key); + if(!toJson) + return null==value?"[]":value; + try{ + return null==value?[]:JSON.parse(value) + }catch(e){ + return[] + } +} + +//写入kv,value如果未对象类型(数组或者json对象)需要序列化为字符串 +async function saveKV(key,value){ + if(null!=value){ + if("object"==typeof value){ + value=JSON.stringify(value) + } + await CFBLOG.put(key,value) + return true + } + return false; +} + +//根据文章id,返回上篇、下篇文章 +async function getSiblingArticle(id){ + id=("00000"+parseInt(id)).substr(-6); + //读取文章列表,查找指定id的文章 + let articles_all=await getKV("SYSTEM_INDEX_LIST", true), + article_idx=-1; + for(var i=0,len=articles_all.length;i", + e+="\n\t\t"+articles_all[i].createDate.substr(0,10)+"", + e+="\n\t\t"+(void 0===articles_all[i].changefreq?"daily":articles_all[i].changefreq)+"", + e+="\n\t\t"+(void 0===articles_all[i].priority?"0.5":articles_all[i].priority)+"", + e+="\n\t"; + } + return e+="\n",e +} + +//访问: favicon.ico +async function handle_favicon(request){ + /* + 想要自定义,或者用指定的ico,可将此请求置为404,并在codeBeforHead中自行添加类似代码: + + + */ + //return new Response("404",{ + // headers:{ + // "content-type":"text/plain;charset=UTF-8" + // }, + // status:404 + //}); + let url = new URL(request.url) + url.host="dash.cloudflare.com" + return await fetch(new Request(url, request)); +} +//访问: robots.txt +async function handle_robots(request){ + return new Response(OPT.robots+"\nSitemap: https://"+OPT.siteDomain+"/sitemap.xml",{ + headers:{ + "content-type":"text/plain;charset=UTF-8" + }, + status:200 + }); +} +//访问: sitemap.xml +async function handle_sitemap(request){ + //读取文章列表,并按照特定的xml格式进行组装 + let articles_all=await getKV("SYSTEM_INDEX_LIST", true) + let xml='\n'; + for(var i=0;i", + xml+="\n\t\t"+articles_all[i].createDate.substr(0,10)+"", + xml+="\n\t\t"+(void 0===articles_all[i].changefreq?"daily":articles_all[i].changefreq)+"", + xml+="\n\t\t"+(void 0===articles_all[i].priority?"0.5":articles_all[i].priority)+"", + xml+="\n\t"; + } + xml+="\n" + return new Response(xml,{ + headers:{ + "content-type":"text/xml;charset=UTF-8" + }, + status:200 + }); +} +//渲染前端博客:指定一级路径page\tags\category,二级路径value,以及页码,默认第一页 +async function renderBlog(url){ + console.log("---进入renderBlog函数---,path=", url.href.substr(url.origin.length)) + + //处理主题预览及分页 + let theme=url.searchParams.get("theme"), + pageSize=url.searchParams.get("pageSize"); + if(theme){ + OPT.themeURL=OPT.theme_github_path+theme+"/"; + } + if(pageSize){ + OPT.pageSize=parseInt(pageSize); + } + //如果采用默认default主题,则改为加载default2.0主题 + if(OPT.theme_github_path+"default/"==OPT.themeURL){ + OPT.themeURL=OPT.theme_github_path+"default2.0/"; + } + console.log("theme pageSize",OPT.pageSize,OPT.themeURL) + + //获取主页模板源码 + let theme_html=await getThemeHtml("index"), + //KV中读取导航栏、分类目录、标签、链接、所有文章、近期文章等配置信息 + menus=await getKV("SYSTEM_VALUE_WidgetMenu",true), + categories=await getKV("SYSTEM_VALUE_WidgetCategory",true), + tags=await getKV("SYSTEM_VALUE_WidgetTags",true), + links=await getKV("SYSTEM_VALUE_WidgetLink",true), + articles_all=await getKV("SYSTEM_INDEX_LIST", true), + articles_recently=articles_all.slice(0,OPT.recentlySize); + + for(var i=0;i3 && paths.includes("page")){ + pageNo = paths[paths.indexOf("page")+1] //分页的页码 + category_tag = paths.slice(1, paths.lastIndexOf("page")-1).join("") //tags、category后,分页前的为标签、分类名 + } + category_tag = decodeURIComponent(category_tag) + articles = articles_all.filter(a => a[paths[0]].includes(category_tag)) + break; + } + pageNo = parseInt(pageNo) + // console.log(pageNo) + // console.log(articles) + + //获取当页要显示文章列表 + let articles_show = articles.slice((pageNo-1)*OPT.pageSize,pageNo*OPT.pageSize); + // console.log(articles_show) + for(i=0;i=articles.length){ + older=[]; + } + // console.log(newer) + // console.log(older) + + //文章标题、关键字 + let title=(pageNo>1 ? "page "+pageNo+" - " : "")+OPT.siteName, + keyWord=OPT.keyWords, + cfg={}; + cfg.widgetMenuList=menus,//导航 + cfg.widgetCategoryList=categories,//分类目录 + cfg.widgetTagsList=tags,//标签 + cfg.widgetLinkList=links,//链接 + cfg.widgetRecentlyList=articles_recently,//近期文章 + cfg.articleList=articles_show,//当前页文章列表 + cfg.pageNewer=newer,//上翻页链接 + cfg.pageOlder=older,//下翻页链接 + cfg.title=title,//网页title + cfg.keyWords=keyWord;//SEO关键字 + + //使用mustache.js进行页面渲染(参数替换) + cfg.OPT=OPT + + let html = Mustache.render(theme_html,cfg) + + return new Response(html,{ + headers:{ + "content-type":"text/html;charset=UTF-8" + }, + status:200 + }) +} +//文章内容页 +async function handle_article(id){ + //获取内容页模板源码 + let theme_html=await getThemeHtml("article"), + //KV中读取导航栏、分类目录、标签、链接、近期文章等配置信息 + menus=await getKV("SYSTEM_VALUE_WidgetMenu",true), + categories=await getKV("SYSTEM_VALUE_WidgetCategory",true), + tags=await getKV("SYSTEM_VALUE_WidgetTags",true), + links=await getKV("SYSTEM_VALUE_WidgetLink",true), + articles_recently=(await getKV("SYSTEM_INDEX_LIST", true)).slice(0,OPT.recentlySize); + + for(var i=0;i格式的参数 + html = theme_html.replaceHtmlPara("categoryJson",JSON.stringify(categoryJson)) + .replaceHtmlPara("menuJson",JSON.stringify(menuJson)) + .replaceHtmlPara("linkJson",JSON.stringify(linkJson)) + } + + //发布 + if("publish"==paths[1]){ + //KV中获取文章列表 + let articles_all=await getKV("SYSTEM_INDEX_LIST", true), + tags=[]; //操作标签 + + //遍历所有文章,汇集所有的tag + for(var i=0;i0 + && -1==tags.indexOf(articles_all[i].tags[j])){ + tags.push(articles_all[i].tags[j]); + } + } + } + } + console.log(articles_all) + //将所有标签一次性写入到KV中,并清除缓存 + await saveKV("SYSTEM_VALUE_WidgetTags",JSON.stringify(tags)) + + json = await purge()?'{"msg":"published ,purge Cache true","rst":true}':'{"msg":"published ,buuuuuuuuuuuut purge Cache false !!!!!!","rst":true}' + + } + + //文章列表 + if("getList"==paths[1]){ + //默认取第一页,每页20篇 + let pageNo=(undefined===paths[2]) ? 1 : parseInt(paths[2]), + list=await admin_nextPage(pageNo, 20);//每次加载20个 + json = JSON.stringify(list) + } + + //修改文章 + if("edit"==paths[1]){ + let id=paths[2], + //获取主题admin/edit源码 + theme_html=await getThemeHtml("admin/edit"), + //KV中读取分类 + categoryJson=await getKV("SYSTEM_VALUE_WidgetCategory"), + //KV中读取文章内容 + articleJson=await getKV(id); + + //手动替换格式的参数 + html = theme_html.replaceHtmlPara("categoryJson",categoryJson).replaceHtmlPara("articleJson",articleJson.replaceAll("script>","script>")) + } + + //保存配置 + if("saveConfig"==paths[1]){ + const ret=await parseReq(request); + let widgetCategory=ret.WidgetCategory,//分类 + widgetMenu=ret.WidgetMenu,//导航 + widgetLink=ret.WidgetLink;//链接 + + + //判断格式,写入分类、导航、链接到KV中 + if(checkFormat(widgetCategory) && checkFormat(widgetMenu) && checkFormat(widgetLink)){ + let success = await saveKV("SYSTEM_VALUE_WidgetCategory", widgetCategory) + success = success && await saveKV("SYSTEM_VALUE_WidgetMenu", widgetMenu) + success = success && await saveKV("SYSTEM_VALUE_WidgetLink", widgetLink) + json = success ? '{"msg":"saved","rst":true}' : '{"msg":"Save Faild!!!","ret":false}' + }else{ + json = '{"msg":"Not a JSON object","rst":false}' + } + } + + //导入 + if("import"==paths[1]){ + let importJsone=(await parseReq(request)).importJson; + console.log("开始导入",typeof importJson) + + if(checkFormat(importJson)){ + let importJson=JSON.parse(importJson), + keys=Object.keys(importJson); + for(let i=0;i0 + && createDate.length>0 + && category.length>0 + && contentMD.length>0 + && contentHtml.length>0){ + + id=await generateId(), + contentText=contentHtml.replace(/<\/?[^>]*>/g,"").trim().substring(0,OPT.readMoreLength);//摘要 + //组装文章json + let article={ + id:id, + title:title, + img:img, + link:link, + createDate:createDate, + category:category, + tags:tags, + contentMD:contentMD, + contentHtml:contentHtml, + contentText:contentText, + priority:priority, + changefreq:changefreq + }; + + //将文章json写入KV(key为文章id,value为文章json字符串) + await saveKV(id,JSON.stringify(article)); + + //组装文章json + let articleWithoutHtml={ + id:id, + title:title, + img:img, + link:link, + createDate:createDate, + category:category, + tags:tags, + contentText:contentText, + priority:priority, + changefreq:changefreq + }, + articles_all_old=await getKV("SYSTEM_INDEX_LIST", true),//读取文章列表 + articles_all=[]; + + //将最新的文章写入文章列表中,并按id排序后,再次回写到KV中 + articles_all.push(articleWithoutHtml), + articles_all=articles_all.concat(articles_all_old), + articles_all=sort(articles_all,"id"), + await saveKV("SYSTEM_INDEX_LIST",JSON.stringify(articles_all)) + + json = '{"msg":"added OK","rst":true,"id":"'+id+'"}' + }else{ + json = '{"msg":"信息不全","rst":false}' + } + } + + //删除 + if("delete"==paths[1]){ + let t=paths[2]; + if(6==t.length){ + await CFBLOG.delete(t); + let e=await getKV("SYSTEM_INDEX_LIST", true); + for(r=0;r0 + && createDate.length>0 + && category.length>0 + && contentMD.length>0 + && contentHtml.length>0){ + + contentText=contentHtml.replace(/<\/?[^>]*>/g,"").trim().substring(0,OPT.readMoreLength);//摘要 + //组装文章json + let article={ + id:id, + title:title, + img:img, + link:link, + createDate:createDate, + category:category, + tags:tags, + contentMD:contentMD, + contentHtml:contentHtml, + contentText:contentText, + priority:priority, + changefreq:changefreq + }; + + //将文章json写入KV(key为文章id,value为文章json字符串) + await saveKV(id,JSON.stringify(article)); + + //组装文章json + let articleWithoutHtml={ + id:id, + title:title, + img:img, + link:link, + createDate:createDate, + category:category, + tags:tags, + contentText:contentText, + priority:priority, + changefreq:changefreq + }, + articles_all=await getKV("SYSTEM_INDEX_LIST", true);//读取文章列表 + console.log(articles_all) + //将原对象删掉,将最新的文章加入文章列表中,并重新按id排序后,再次回写到KV中 + for(var i=articles_all.length-1;i>=0;i--){//按索引删除,要倒序,否则索引值会变 + if(articles_all[i].id == id){ + articles_all.splice(i,1); + } + } + articles_all.push(articleWithoutHtml), + articles_all=sort(articles_all,"id"), + await saveKV("SYSTEM_INDEX_LIST",JSON.stringify(articles_all)) + json = '{"msg":"Edit OK","rst":true,"id":"'+id+'"}' + }else{ + json = '{"msg":"信息不全","rst":false}' + } + } + + //返回结果 + if(!json &&!html){ + json = '{"msg":"some errors","rst":false}' + } + if(html){ + return new Response(html,{ + headers:{ + "content-type":"text/html;charset=UTF-8" + }, + status:200 + }) + } + if(json){ + return new Response(json ,{ + headers:{ + "content-type":"application/json;charset=UTF-8" + }, + status:200 + }) + } +} +// 处理请求 +async function handlerRequest(event){ + let request = event.request + //获取url请求对象 + let url=new URL(request.url) + let paths=url.pathname.trim("/").split("/") + + //校验权限 + if(("admin"==paths[0]||true===OPT.privateBlog) &&!parseBasicAuth(request)){ + return new Response("Unauthorized",{ + headers:{ + "WWW-Authenticate":'Basic realm="cfblog"', + "Access-Control-Allow-Origin":"*" + }, + status:401 + }); + } + + //组装请求url,查看是否有缓存 + const D=caches.default, + M="https://"+OPT.siteDomain+url.pathname, + x=new Request(M, request); + console.log("cacheFullPath:",M); + let k=await D.match(x); + if(k){ + console.log("hit cache!") + return k; + } + + switch(paths[0]){ + case "favicon.ico": //图标 + k= await handle_favicon(request); + break; + case "robots.txt": + k= await handle_robots(request); + break; + case "sitemap.xml": + k= await handle_sitemap(request); + break; + case "admin": //后台 + k = await handle_admin(request); + break; + case "article": //文章内容页 + k = await handle_article(paths[1]); + break; + case "": //文章 首页 + case "page": //文章 分页 + case "category": //分类 分页 + case "tags": //标签 分页 + k = await renderBlog(url); + break; + default: + //其他页面返回404 + k= new Response(OPT.html404,{ + headers:{ + "content-type":"text/html;charset=UTF-8" + }, + status:200 + }) + break; + } + //设置浏览器缓存时间:后台不缓存、只缓存前台 + try{ + if("admin"==paths[0]){ + k.headers.set("Cache-Control","no-store") + }else{ + k.headers.set("Cache-Control","public, max-age="+OPT.cacheTime), + event.waitUntil(D.put(M,k.clone())) + } + }catch(e){} + + return k +} + +//监听请求 +addEventListener("fetch",event=>{ + //处理请求 + event.respondWith(handlerRequest(event)) +}) \ No newline at end of file diff --git a/themes/JustNews/article.html b/themes/JustNews/article.html index 9e170f16..126571cb 100644 --- a/themes/JustNews/article.html +++ b/themes/JustNews/article.html @@ -9,8 +9,8 @@ - - + + @@ -42,7 +42,7 @@ {{ /OPT.logo }} {{ ^OPT.logo }} - 请自定义OPT.logo + 请自定义OPT.logo {{ /OPT.logo }} @@ -210,19 +210,19 @@

- + - + - - + + @@ -231,7 +231,7 @@

var fifuImageVars = {"fifu_lazy":"1","fifu_woo_lbox_enabled":"1","fifu_woo_zoom":"inline","fifu_is_product":"","fifu_is_flatsome_active":"","fifu_rest_url":"","fifu_nonce":"96a15ffec7"}; /* ]]> */ - + diff --git a/themes/JustNews/index.html b/themes/JustNews/index.html index fddc206a..90c010e7 100644 --- a/themes/JustNews/index.html +++ b/themes/JustNews/index.html @@ -9,8 +9,8 @@ - - + + @@ -41,7 +41,7 @@ {{ /OPT.logo }} {{ ^OPT.logo }} - 请自定义OPT.logo + 请自定义OPT.logo {{ /OPT.logo }} @@ -206,12 +206,12 @@

- + - + - - + + @@ -258,7 +258,7 @@

}; /* ]]> */ - + - - - + + + {{ &OPT.codeBeforHead }} @@ -29,7 +29,7 @@

{{ &articleSingle.title }}

- + - - - + + + {{ &OPT.codeBeforHead }} @@ -59,7 +59,7 @@ {{ &OPT.codeBeforBody }} - + + `,//其他代码,显示在前 + "codeBeforBody":` + `,//其他代码,显示在前 + "commentCode":` + + `,//评论区代码 + "widgetOther":` + `,//20201224新增参数,用于右侧 小部件扩展 + "otherCodeA":`热度`,//模板开发用的其他自定义变量 + "otherCodeB":``,// + "otherCodeC":``,// + "otherCodeD":``,// + "otherCodeE":``,// + "copyRight" :`Powered by Cloudflare & CFBlog-Plus & CF-Blog `,//自定义版权信息,建议保留大公无私的 Coudflare 和 作者 的链接 + "robots":`User-agent: * +Disallow: /admin`,//robots.txt设置 + + /*--前后台共用参数--*/ + + "top_flag":`[置顶]`,//置顶标志 + "top_flag_style":``,//置顶标志的样式 + + + /*--后台参数--*/ + + "hidden_flag":`[隐藏]`,//隐藏标志 + "hidden_flag_style":``,//隐藏标志的样式 + "admin_home_idx": 1, //后台首页tab索引设置:1-我的文章,2-新建,3-设置,4-发布 "editor_page_scripts": ` //置顶设置 @@ -40,6 +80,19 @@ const OPT = { //网站配置 $("#top_timestamp").val(articleJson.top_timestamp?articleJson.top_timestamp:0); } $("#istop").trigger('change') + //隐藏设置 + let hidden_setting=\` +
+ + +
\` + $('div.form-group').last().after(hidden_setting);//添加隐藏设置 + if(location.pathname.startsWith('/admin/edit')){//修改文章页面,自动设置隐藏 + $("#hidden").val(articleJson.hidden?1:0); + } //关闭email匹配和@匹配,否则图片使用jsdelivr的cdn,如果有版本号会匹配成“mailto:xxx”从而导致显示异常 mdEditor.settings.emailLink=false; mdEditor.settings.atLink=false; @@ -83,30 +136,6 @@ const OPT = { //网站配置 if($('#createDate').val()=="")$('#createDate').val(new Date(new Date().getTime()+8*60*60*1000).toJSON().substr(0,16)); `, //后台编辑页面脚本 - "pageSize" : 5,//每页文章数 - "recentlySize" : 6,//最近文章数 - "readMoreLength":150,//阅读更多截取长度 - "cacheTime" : 60*60*24*2, //网页缓存时长(秒),建议=文章更新频率 - "themeURL" : "https://raw.githubusercontent.com/Arronlong/cfblog-plus/master/themes/JustNews/", // 模板地址,以 "/"" 结尾 - "html404" : `404`,//404页面代码 - "codeBeforHead":` - - `,//其他代码,显示在前 - "codeBeforBody":``,//其他代码,显示在前 - "commentCode":` - `,//评论区代码 - "widgetOther":``,//20201224新增参数,用于右侧 小部件扩展 - "otherCodeA":`热度`,//模板开发用的其他自定义变量 - "otherCodeB":``,// - "otherCodeC":``,// - "otherCodeD":``,// - "otherCodeE":``,// - "copyRight" :`Powered by Cloudflare & CFBlog-Plus & CF-Blog `,//自定义版权信息,建议保留大公无私的 Coudflare 和 作者 的链接 - "robots":`User-agent: * -Disallow: /admin`//robots.txt设置 }; //CFBLOG 通用变量 @@ -122,6 +151,10 @@ if(OPT.themeURL.substr(-1)!='/'){ if(OPT.theme_github_path.substr(-1)!='/'){ OPT.theme_github_path=OPT.theme_github_path+'/'; } +//置顶样式对于前台来说,与codeBeforHead结合即可 +if(OPT.top_flag_style){ + OPT.codeBeforHead += OPT.top_flag_style +} //引入mustache.js,4.1.0:https://cdn.bootcdn.net/ajax/libs/mustache.js/4.1.0/mustache.min.js (function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):(global=global||self,global.Mustache=factory())})(this,function(){"use strict";var objectToString=Object.prototype.toString;var isArray=Array.isArray||function isArrayPolyfill(object){return objectToString.call(object)==="[object Array]"};function isFunction(object){return typeof object==="function"}function typeStr(obj){return isArray(obj)?"array":typeof obj}function escapeRegExp(string){return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function hasProperty(obj,propName){return obj!=null&&typeof obj==="object"&&propName in obj}function primitiveHasOwnProperty(primitive,propName){return primitive!=null&&typeof primitive!=="object"&&primitive.hasOwnProperty&&primitive.hasOwnProperty(propName)}var regExpTest=RegExp.prototype.test;function testRegExp(re,string){return regExpTest.call(re,string)}var nonSpaceRe=/\S/;function isWhitespace(string){return!testRegExp(nonSpaceRe,string)}var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};function escapeHtml(string){return String(string).replace(/[&<>"'`=\/]/g,function fromEntityMap(s){return entityMap[s]})}var whiteRe=/\s*/;var spaceRe=/\s+/;var equalsRe=/\s*=/;var curlyRe=/\s*\}/;var tagRe=/#|\^|\/|>|\{|&|=|!/;function parseTemplate(template,tags){if(!template)return[];var lineHasNonSpace=false;var sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;var indentation="";var tagIndex=0;function stripSpace(){if(hasTag&&!nonSpace){while(spaces.length)delete tokens[spaces.pop()]}else{spaces=[]}hasTag=false;nonSpace=false}var openingTagRe,closingTagRe,closingCurlyRe;function compileTags(tagsToCompile){if(typeof tagsToCompile==="string")tagsToCompile=tagsToCompile.split(spaceRe,2);if(!isArray(tagsToCompile)||tagsToCompile.length!==2)throw new Error("Invalid tags: "+tagsToCompile);openingTagRe=new RegExp(escapeRegExp(tagsToCompile[0])+"\\s*");closingTagRe=new RegExp("\\s*"+escapeRegExp(tagsToCompile[1]));closingCurlyRe=new RegExp("\\s*"+escapeRegExp("}"+tagsToCompile[1]))}compileTags(tags||mustache.tags);var scanner=new Scanner(template);var start,type,value,chr,token,openSection;while(!scanner.eos()){start=scanner.pos;value=scanner.scanUntil(openingTagRe);if(value){for(var i=0,valueLength=value.length;i"){token=[type,value,start,scanner.pos,indentation,tagIndex,lineHasNonSpace]}else{token=[type,value,start,scanner.pos]}tagIndex++;tokens.push(token);if(type==="#"||type==="^"){sections.push(token)}else if(type==="/"){openSection=sections.pop();if(!openSection)throw new Error('Unopened section "'+value+'" at '+start);if(openSection[1]!==value)throw new Error('Unclosed section "'+openSection[1]+'" at '+start)}else if(type==="name"||type==="{"||type==="&"){nonSpace=true}else if(type==="="){compileTags(value)}}stripSpace();openSection=sections.pop();if(openSection)throw new Error('Unclosed section "'+openSection[1]+'" at '+scanner.pos);return nestTokens(squashTokens(tokens))}function squashTokens(tokens){var squashedTokens=[];var token,lastToken;for(var i=0,numTokens=tokens.length;i0?sections[sections.length-1][4]:nestedTokens;break;default:collector.push(token)}}return nestedTokens}function Scanner(string){this.string=string;this.tail=string;this.pos=0}Scanner.prototype.eos=function eos(){return this.tail===""};Scanner.prototype.scan=function scan(re){var match=this.tail.match(re);if(!match||match.index!==0)return"";var string=match[0];this.tail=this.tail.substring(string.length);this.pos+=string.length;return string};Scanner.prototype.scanUntil=function scanUntil(re){var index=this.tail.search(re),match;switch(index){case-1:match=this.tail;this.tail="";break;case 0:match="";break;default:match=this.tail.substring(0,index);this.tail=this.tail.substring(index)}this.pos+=match.length;return match};function Context(view,parentContext){this.view=view;this.cache={".":this.view};this.parent=parentContext}Context.prototype.push=function push(view){return new Context(view,this)};Context.prototype.lookup=function lookup(name){var cache=this.cache;var value;if(cache.hasOwnProperty(name)){value=cache[name]}else{var context=this,intermediateValue,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){intermediateValue=context.view;names=name.split(".");index=0;while(intermediateValue!=null&&index")value=this.renderPartial(token,context,partials,config);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context,config);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate,config){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials,config)}if(!value)return;if(isArray(value)){for(var j=0,valueLength=value.length;j0||!lineHasNonSpace)){partialByNl[i]=filteredIndentation+partialByNl[i]}}return partialByNl.join("\n")};Writer.prototype.renderPartial=function renderPartial(token,context,partials,config){if(!partials)return;var tags=this.getConfigTags(config);var value=isFunction(partials)?partials(token[1]):partials[token[1]];if(value!=null){var lineHasNonSpace=token[6];var tagIndex=token[5];var indentation=token[4];var indentedValue=value;if(tagIndex==0&&indentation){indentedValue=this.indentPartial(value,indentation,lineHasNonSpace)}var tokens=this.parse(indentedValue,tags);return this.renderTokens(tokens,context,partials,indentedValue,config)}};Writer.prototype.unescapedValue=function unescapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return value};Writer.prototype.escapedValue=function escapedValue(token,context,config){var escape=this.getConfigEscape(config)||mustache.escape;var value=context.lookup(token[1]);if(value!=null)return typeof value==="number"&&escape===mustache.escape?String(value):escape(value)};Writer.prototype.rawValue=function rawValue(token){return token[1]};Writer.prototype.getConfigTags=function getConfigTags(config){if(isArray(config)){return config}else if(config&&typeof config==="object"){return config.tags}else{return undefined}};Writer.prototype.getConfigEscape=function getConfigEscape(config){if(config&&typeof config==="object"&&!isArray(config)){return config.escape}else{return undefined}};var mustache={name:"mustache.js",version:"4.1.0",tags:["{{","}}"],clearCache:undefined,escape:undefined,parse:undefined,render:undefined,Scanner:undefined,Context:undefined,Writer:undefined,set templateCache(cache){defaultWriter.templateCache=cache},get templateCache(){return defaultWriter.templateCache}};var defaultWriter=new Writer;mustache.clearCache=function clearCache(){return defaultWriter.clearCache()};mustache.parse=function parse(template,tags){return defaultWriter.parse(template,tags)};mustache.render=function render(template,view,partials,config){if(typeof template!=="string"){throw new TypeError('Invalid template! Template should be a "string" '+'but "'+typeStr(template)+'" was given as the first '+"argument for mustache#render(template, view, partials)")}return defaultWriter.render(template,view,partials,config)};mustache.escape=escapeHtml;mustache.Scanner=Scanner;mustache.Context=Context;mustache.Writer=Writer;return mustache}); @@ -207,6 +240,15 @@ function sortArticle(articles){ return sort(sort(articles,'id'),'top_timestamp'); } async function getArticlesList(){ + let articles_all = await getAllArticlesList(); + + for(var i=0;i=1 && OPT.admin_home_idx<=4){ html = html.replace("$('#myTab li:eq(0) 1').tab('show')","$('#myTab a:eq("+OPT.admin_home_idx+")').tab('show')") } + //添加置顶样式 + if(OPT.top_flag_style){ + html += OPT.top_flag_style + } + //添加隐藏样式 + if(OPT.hidden_flag_style){ + html += OPT.hidden_flag_style + } } //发布 if("publish"==paths[1]){ //KV中获取文章列表 - let articles_all=await getArticlesList(), + let articles_all=await getAllArticlesList(), tags=[]; //操作标签 //遍历所有文章,汇集所有的tag @@ -764,6 +817,7 @@ async function handle_admin(request){ contentHtml=ret["content-html-code"],//文章内容-html格式 contentText="",//文章摘要 top_timestamp=ret.top_timestamp*1,//置顶时间戳,不置顶时为0 + hidden=ret.hidden*1,//是否隐藏 id="";//文章id //校验参数完整性 @@ -789,6 +843,7 @@ async function handle_admin(request){ contentText:contentText, priority:priority, top_timestamp:top_timestamp, + hidden:hidden, changefreq:changefreq }; @@ -807,9 +862,10 @@ async function handle_admin(request){ contentText:contentText, priority:priority, top_timestamp:top_timestamp, + hidden:hidden, changefreq:changefreq }, - articles_all_old=await getArticlesList(),//读取文章列表 + articles_all_old=await getAllArticlesList(),//读取文章列表 articles_all=[]; //将最新的文章写入文章列表中,并按id排序后,再次回写到KV中 @@ -829,13 +885,15 @@ async function handle_admin(request){ let id=paths[2] if(6==id.length){ await CFBLOG.delete(id); - let e=await getArticlesList(); + let e=await getAllArticlesList(); for(r=0;r