详细的介绍和说明在主题售价及购买方式后面
| 系列 | 售价 |
|---|---|
| Mirages For Typecho | 88元 |
支持使用支付宝扫码及微信扫码付款(支持花呗及信用卡)。
购买完成后即可下载主题,安装使用,无需人工介入。
作者联系方式:
278448087Namekuji[email protected]如果可以的话,建议使用 QQ,毕竟微信添加好友没有提醒。
购买主题后,您将获得主题的最新版本,后续所有的升级版本均为免费。主题需要绑定域名授权,一个订单最多可以自行绑定 3 个域名授权(超限后需要联系作者添加),授权可以在主题小商店中自行绑定。本主题购买后不得分发、转售。因主题是可复制的商品,在代码发出后不予退款,敬请谅解。
售后服务包括您在使用本主题时遇到的问题,但不包含主机及 Typecho 安装、Typecho 的使用教程,也不提供主题的个性化定制服务。
主题提供了两种样式的导航栏:顶部导航栏和侧边导航栏,可以根据喜好在设置中自由切换。
主题提供了两种样式的文章列表:卡片式文章列表和内容式文章列表,同样可以根据喜好在设置中自由切换。
以下为二者的区别:
功能与特性
当前博客使用的主题版本为「最新开发版」,博客中的所有功能均可通过设置实现。
开发版主题仅可通过插件自动更新的形式使用。如要更新开发版主题,您需要到插件中将「仅接受正式版更新」选项置为「否」,保存后执行插件里的「更新主题和插件至最新版」操作按钮即可。
所以,2020 年的今天,我为什么买了一个边框可以停航母的显示器呢,主要还是不想外接显示器以后,显示效果比原来的还差,如果新的显示器只有大这一个优点的话,那想想就觉得不香了。本来的话,老的 4K 版本尺寸过小,且必须要雷电 3 接口才能正常使用,所以综合还是考虑买 LG UltraFine 5K ,当然得换新款 MBP,所以才一直没下手去买。不过后来发现 4K 版本更新成常规 4K 分辨率了,这样我这台老古董配个雷电转换器也能用,然后尺寸的话,新版的 23.7 寸也比老版 4K 的 21.5 寸要好接受的多,虽然 PPI 降到了 186,但思考了半天最终决定还是先买它了。
话说这个箱子是真的大,体积大概是朋友 25 寸显示器包装箱的 2 倍左右,打开箱子以后,显示器是组装好的,掏出来接上电源就能用了。
因为我本子是 2015 款的,只有雷电二的接口,所以这里还要配上雷电三转雷电二的转接器,然后用雷电二的线连上就可以了。
完成版桌面图,手机直出(因为并没有其他设备🥺)凑活着看吧。
简单说下感受吧。
整体还是挺满意的
猫还活着。。。恩。。。
因为是做高铁回上海的,没办法带宠物,所以又上淘宝办了托运,到上海以后又去接的他,整体的话还算比较顺利,但对猫来说还是太受罪了。
刚到家里的时候,因为这货比较胆小,所以前几天都是躲起来的,完了还不停地叫,24 小时不间断的那种,嗓子都要哑了的那种,当时感觉真的是要绝望了哈哈
不过一起来看到他的样子就不想再说什么了,忍几天就差不多了。
然后差不多 3 天以后就不怎么叫了,然后玩具也到了,后面就一起愉快的玩耍了。
这么多天下来,每天给他喂食,换水,铲猫砂,最重要的还要陪他玩,教育他不要咬我什么的,感觉像养了个孩子一样,痛苦并快乐着。不过这家伙长得是真的丑,翻了一遍相册,就没一张拿得出手的::quyin:hematemesis::
一个月下来,感觉这货长的是真的快,长度翻了应该有一倍。虽然平时也有种「这货好像变大了」的感觉,不过今天翻相册的时候才发现,原来变化已经这么大了。。。
刚到家的时候,也有点小毛病,比如右眼发炎什么的,用点眼药水什么的就好了,后来有一天,发现他屁股那里有一块皮肤特别的硬,所以赶紧带着去医院看了下,小医生看完说是猫癣,过几天去打疫苗的时候,又让老医生看了一遍,说应该不是猫癣,可能是被什么虫子之类的咬了,那块皮肤发炎了,反正不管怎么说,这耻辱圈是摘不下来了🤣🤣🤣
然后今天又去了一趟医院,之前的伤口差不多已经好了,然后又发现了一处,好了,终于如愿以偿的得了猫癣了::quyin:fue::
本来以为能拿下来的耻辱圈又要继续戴一阵子了🤣🤣🤣
好了,没有了,憋看了
Error Preparing CommonHTML output (postProcess)文章中的数学公式也只渲染了一半,这个问题的可能的原因是 MathJax 渲染过程中,由外部修改了 DOM 导致的。
具体到我这边的话,主要是通过 AJAX 的方式加载一个表情列表,在加载完成后,会将文章中的占位符替换为相应的表情,而替换的时候 MathJax 还没有渲染完成,所以导致了报错。
解决方法:
将表情最终的替换过程加到 MathJax 的队列中:
MathJax.Hub.Queue(() => {
// 会操作 DOM 的代码
});
]]>不过随着主题的更新,云存储优化功能也越来越完善了,所以,趁着现在有空,刚好拉出来讲一讲。
先来说说这个功能是干什么的吧。
云存储是第三方托管的在线存储服务,其在全国乃至世界范围内都有大量的 CDN 节点,用户在访问相关资源时会被分配到就近的 CDN 节点,因此在访问速度上通常比我们单台服务器要好很多。常见的云存储服务有七牛云存储、又拍云存储、阿里 OSS、腾讯云存储等,鉴于本主题就支持这四个,所以其他的就当做不常见吧::quyin:1huaji::
到了主题这边,简单来说,云存储优化功能,就是可以把博客上除了页面的 HTML 以外的静态资源全都通过云存储进行加载,包括主题的 JS、CSS、字体、表情图片文件,以及文章正文内图片、头图等图片资源(第三方的插件里的资源文件不包含在内),通过云存储加载这些静态图片,可以加速网页的访问速度,特别是对于一些服务器在国外的朋友。
这是云存储优化最基本的功能。在此基础上,主题还提供了以下功能:
主题可以根据用户使用的设备,自动调整头图及文章内图片的大小,在保证图片质量不受影响的前提下,降低图片的尺寸,大大节约手机用户的流量,提高页面加载速度。
该功能可以在手机设备上加载小图,电脑设备上加载大图,因此,你在文章等其他地方使用图片时,丝毫不用在意图片尺寸对于页面加载速度及页面大小的影响,直接无脑上最大尺寸图片即可。什么?几 M 的原图?照样给你安排的明明白白。
「启用 WebP 图像格式」功能可以在支持 WebP 的浏览器上使用 WebP 格式的图片,可以以较小的图片大小获得相同质量的图片(相较于 JPEG),进一步提升页面加载速度,减少页面大小。
WebP 可以用于 Chrome 等浏览器下,详细的浏览器兼容情况可以到 CANIUSE 上查看:
关于 WebP 的更多介绍,可以参考这里:
图片加载动画就是图片在加载过程中的动画效果,包含了首页及文章主图、文章列表图片、文章内容图片等。
图片加载动画可以使图片在加载过程中也有较好的观感,在图片资源加载速度较慢时尤为明显。
另外文章内容图片在加载的过程中,可以根据图片大小生成占位,不会有图片在加载过程中导致的文章内容高度变化,避免了加载过程中的文章内容跳动等。
具体的效果可以看一下下面的视频:
好了,说了这么多废话,关键的地方到了。
镜像存储服务是一种快速的数据迁移和加速服务。可以帮助用户实现无缝数据迁移。它实现的功能是用户在访问镜像域名上的一个资源时,云存储会先检测该资源在云存储服务器上是否已经存储,如果有则直接返回,没有的话,会根据路径到源站(也就是你的博客)获取对应的资源,然后返回给用户。除了用户第一次访问时要回源速度稍慢,后面就会完整发挥 CDN 的优势,速度都会非常快。
举个栗子,假如我博客的域名是 https://get233.com,配置的镜像存储域名是 https://assets.get233.com,那么,在第一次访问下面这个链接时:
https://assets.get233.com/path/to/whatever/pig.jpg镜像存储就会到下面这个地址获取内容, 然后返回给用户:
https://get233.com/path/to/whatever/pig.jpg后面镜像存储已经存储了这张图片时,就会直接返回给用户,速度很快。
配置镜像存储的方法如下:
配置完成后,将配置的「CDN 镜像加速域名」复制然后准备填入后面的设置中。
后面的操作都非常简单,只要到主题外观设置里配置相应的设置就可以了。
前往 主题外观设置里 => CDN 镜像加速域名 ,配置 CDN 镜像加速域名:
这里的域名就填你第一步配置中的「CDN 镜像加速域名」。
前往插件设置中,配置如下选项:
其中,自定义 CDN 域名的是告诉 Mirages 哪个域名是云存储域名,然后他是七牛还是又拍什么的。参照说明配置即可。
如果你使用的是又拍云存储,且你变更了又拍云存储的间隔标识符,则配置第二个设置,否则,第二个设置保持默认即可。
前往 主题外观设置里 => 云存储优化 ,配置云存储优化功能:
这一步很简单,把需要的功能选项启用即可。
前往 主题外观设置里 => 图像加载动画 ,开启图像加载动画:
啊,同上。开启了这个功能,图片加载动画就可以用了。
最后就没有了,去试试功能好不好用吧::quyin:1huaji::
]]>如果是普通的去重,就用最常见的 HashSet 就好:
Set<Employee> employeeSet = new HashSet<>(employeeList);
employeeList.clear();
employeeList.addAll(employeeSet);或者使用 Java8 的 Stream API:
List<Employee> uniqueList = employeeList.stream().distinct().collect(Collectors.toList());Employee 类需要实现 hashCode 及 equals 方法。
例如:不重写 equals 方法的情况下,根据 Employee 的 id 字段进行去重处理
方式 1:
List<Employee> uniqueList = employeeList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparingLong(Employee::getId))
),
ArrayList::new
)
);如果是依照两个字段进行去重,则重写 Comparator 方法即可。
方式 2:
HashSet<Object> idSet = new HashSet<>();
employeeList.removeIf(employee -> !idSet.add(employee.getId()));prefers-color-scheme 的支持,该特性可以帮助我们的网页自动切换到深色模式以适配 Mac 中的 Dark Mode(深色模式)。prefers-color-scheme 可以检测到用户是否已请求操作系统使用浅色或深色主题,其有三个可选的选项:
no-preference:未能检测到用户的选择light:用户倾向于使用浅色的主题dark:用户倾向于使用深色的主题,例如用户开启了 Mac 中的深色模式所以,在这里我们可以使用 prefers-color-scheme: dark 来检测用户是否开启了 Dark Mode。
prefers-color-scheme 的使用很简单,和普通的 Media Query 一样:
/* 操作系统及浏览器未支持或用户未开启 Dark Mode */
body {
background-color: white;
color: black;
}
@media (prefers-color-scheme: dark) {
/* 操作系统及浏览器支持且用户开启了 Dark Mode */
body {
background-color: black;
color: white;
}
}这样,用户在平时看到的是白色背景,而开启了深色模式后,页面就会自动变为黑色背景。当然,夜间模式的适配需要做的工作还很多,需要你慢慢调整各元素的颜色等。
顺便说一下,目前版本中,如果使用 @supports (prefers-color-scheme: dark) 包裹上述 Media Query 代码,则可能不会生效,这个看上去应该是目前版本浏览器的 Bug。
很多网站已经有了夜间模式,使用 prefers-color-scheme 适配可能比较麻烦,那么可以使用 JS 获取用户是否开启了 Dark Mode (深色模式),然后按照旧的逻辑开启夜间模式。
这种模式有个缺点:无法像直接使用 Media Query 的情况一样,在用户开启深色模式的时候,已打开的浏览器页面会自动变为深色模式,只有刷新页面或新进入的用户才会使用深色模式,不过个人感觉体验上影响不大。
当然,JS Api 是没有的,这里只能通过迂回的方式通过 JS 获取。
评论区的大佬告诉我有![]()
用过 matchMedia 方法可以直接判断浏览器当前是否倾向于使用深色模式:
let prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (prefersDarkMode) {
// 搞事情
}通过监听 matchMedia 的 change 事件,可以在用户切换深色/浅色模式的时候,将浏览器中已打开的页面自动切换为系统对应的模式。
let media = window.matchMedia('(prefers-color-scheme: dark)');
let callback = (e) => {
let prefersDarkMode = e.matches;
if (prefersDarkMode) {
// 搞事情
}
};
if (typeof media.addEventListener === 'function') {
media.addEventListener('change', callback);
} else if (typeof media.addListener === 'function') {
media.addListener(callback);
}目前见到的编辑器基本都是输入与预览分离的设计,像 Mou、MWeb 等等。而 Typora 最明显的优点也在于此。它将编辑与预览合并了,就像那些所见即所得编辑器一样,但又使用着 Markdown 简洁的语法,从而使我们不需要像传统的所见即所得编辑器一样,经常需要使用鼠标点击来调整各种格式。「虽然看上去不像」,但它确实是一款 Markdown 编辑器,一款优秀的 Markdown 编辑器,甚至我觉得,这才应该是一款 Markdown 编辑器所应有的样子。
这是我当时的评价,毫不夸张的说,为了它,我放弃了很多功能更加强大的 Markdown 编辑器。
关于 Typora 的更多介绍可以百度 Google 或看我以前写的一篇:《Markdown 编辑器:Typora》
今天呢,放出来的是一款自用 N 久的皮肤,最开始的时候超懒,就只支持配备 Retina 显示器的 macOS,最近稍作修改,在 Windows 上效果也还可以,即便是低分屏。
皮肤风格的话,大概和 Mirages 主题很像,代码高亮什么风格都一样。所以这款皮肤的名字也叫 Mirages。
最初其实是有夜间模式的,但后面因为懒得更新,所以算是放弃了。
原谅我懒,用了 MWeb 的介绍哈哈,MWeb 也是款功能超级强大的 Markdown 编辑器,而且有 iOS 版。
以上。
下载解压后,将 mirages 文件夹和 mirages.css 文件丢进 Typora 的主题文件夹(可以在 Typora 的设置里找到)内,然后主题选择启用 Mirages 即可。
快捷键为: option + command + C
选中一个文件后,按下快捷键 option + command + C,然后按下 command + V 或者 粘贴 粘贴就可以了。
![]()
此外,还有另一种操作方法:
选中一个文件,按住 option 键, 右键选择「将 xxxxx 拷贝为路径名称」即可。
现在再补充这个快捷键是因为即使这个快捷键放出来两年多了,但感觉知道的人还是太少,刚刚尝试 Google 了一下,得到的答案基本还都是比较老的版本,很少有提到这个快捷键的,某乎上的问题也已经是很久以前的了(那个问题下有个两年前的我的回答😂😂😂),所以还是重新写一下,给小伙伴们再加深一下印象。
]]>瞎搞的东西本地开发一直没有问题,但做了反代以后发现 WebSocket 连接不上了,浏览器端连接请求是报 403,而且服务器会有如下错误:
Handshake failed due to invalid Upgrade header: null以及警告:
o.s.w.s.s.t.h.DefaultSockJsService: Origin check enabled but transport 'jsonp' does not support it.这个很好解决,搜索一下就会有解决方案 —— 只要添加如下配置就好了(然而还是某汪帮我加的):
在 nginx.conf 的 http 模块添加如下内容
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}在反代的 location 设置中添加如下内容:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";配置完以上内容即可正常访问websocket,经过测试没有发现问题。
再然后,项目准备对外开放之前,想了下是要加 HTTPS 证书的,然后让某汪帮我搞了下看首页没啥问题以为 OK 了,就没做啥测试,结果第二天发现 WebSocket 又特么崩了,访问直接返回403,还以为某汪又改配置了?我看了一下配置文件,没变,还是之前的样子,相关配置也都在,但浏览器访问就是返回 403,同时 SockJS 报下面的异常(后续找的,当时的完整的找不到了,也不想再试一遍了。。。):
in a frame because it set multiple 'x-frame-options' headers with conflicting values ('deny, sameorigin'). falling back to 'deny'.然后服务端报警告:
o.s.w.s.s.t.h.DefaultSockJsService: Origin check enabled but transport 'jsonp' does not support it.同时过几秒后 Freemarker 会大量抛出异常(这个可能是我异常处理的锅):
java.lang.IllegalStateException: getOutputStream() has already been called for this response最后经过测试发现是 HTTPS 的问题。HTTP 就木有问题,联想到反代以后 Tomcat 获取不到用户 IP 的问题,所以我觉得可能是 Tomcat 没有获取到正确的协议的问题,遂让某汪帮我加了X-Forwarded-Proto 头,为了避免后续的未知问题,把X-Forwarded-Port也加进来了。
Nginx 添加的配置如下:
proxy_set_header X-Forwarded-Port $Server_port;
proxy_set_header X-Forwarded-Proto $scheme;同时,Spring Boot 配置文件里也要加上如下配置:
server:
use-forward-headers: true这里多说几句,因为我用的是内嵌的 Tomcat 容器,所以只要在 Spring Boot 的配置文件里加上这个配置就好了,如果是打包成 War 包的形式,可以搜索并参考 Tomcat 在 Nginx 反代的情况下获取用户真实 IP 的做法。
如: Jetty/Tomcat + Nginx反向代理获取客户端真实IP、域名、协议、端口。
另外,这里添加这一句配置是使用默认的 Forward 请求头,如果有需要使用自定义请求头的情况,可以使用如下配置(根据情况自定义即可):
server:
tomcat:
remote-ip-header: X-Forwarded-For
port-header: X-Forwarded-Port
protocol-header: X-Forwarded-Proto
protocol-header-https-value: https配置完以后,WebSocket 就可以正常使用了😆
最后附上完整的 Nginx Location 配置:
location / {
proxy_set_header Host $Host;
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Port $Server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}以上。