2025-02-02 11:45:23
MathJax
引擎是一个开源的JavaScript库,它允许Web开发者在网页中嵌入高质量的数学公式。通过利用Web的最新技术,MathJax引擎可以解析LaTeX、MathML和AsciiMath等数学标记语言,并将其渲染为可视化的数学公式,这些公式可以在各种浏览器和操作系统上流畅地显示。
使用MathJax引擎,网页作者可以轻松地编写包含数学内容的文档,而无需担心用户的浏览器或操作系统是否能够正确显示这些数学公式。因为MathJax引擎会自动处理这些兼容性问题,确保用户能够以清晰、准确的方式查看数学内容。
MathJax引擎的特点包括:
总的来说,MathJax引擎是一个功能强大、易于使用的工具,它为Web上的数学内容显示提供了高质量的解决方案。无论是科学论文、教育资料还是技术文档,都可以利用MathJax引擎来呈现复杂的数学公式,提升网页的可读性和专业性。
npm install mathjax@3
MathJax = {
tex: {
packages: ['base'], // 要使用的扩展
inlineMath: [ // 行内数学公式的开始/结束定界符对
['$', '$'],
['\\(', '\\)']
],
displayMath: [ // 显示数学公式的开始/结束定界符对
['$$', '$$'],
['\\[', '\\]']
],
processEscapes: true, // 使用 \$ 来产生一个字面意义上的美元符号
processEnvironments: true, // 在数学模式之外处理 \begin{xxx}...\end{xxx}
processRefs: true, // 在数学模式之外处理 \ref{...}
digits: /^(?:[0-9]+(?:\{,\}[0-9]{3})*(?:\.[0-9]*)?|\.[0-9]+)/, // 用于识别数字的模式
tags: 'none', // 标签类型,可选值为 'none'、'ams' 或 'all'
tagSide: 'right', // \tag 宏的位置
tagIndent: '0.8em', // 标签的缩进量
useLabelIds: true, // 使用标签名称而不是标签编号作为 ID
maxMacros: 10000, // 每个表达式允许的最大宏替换次数
maxBuffer: 5 * 1024, // 内部 TeX 字符串的最大大小(5K)
baseURL: (document.getElementsByTagName('base').length === 0) ? '' : String(document.location).replace(/#.*$/, '')), // 当存在 <base> 标签时,用于标签链接的 URL
formatError: (jax, err) => jax.formatError(err) // 当 TeX 语法错误发生时调用的函数
},
options: {
skipHtmlTags: [ 'script', 'noscript', 'style', 'textarea', 'pre', 'code', 'annotation', 'annotation-xml' ], // 不会搜索数学公式的 HTML 标签
includeHtmlTags: { br: '\n', wbr: '', '#comment': '' }, // 可以出现在数学公式内的 HTML 标签
ignoreHtmlClass: 'tex2jax_ignore', // 标记不进行搜索的标签的类名
processHtmlClass: 'tex2jax_process', // 标记应进行搜索的标签的类名
compileError: function (doc, math, err) {doc.compileError(math, err)}, // 编译错误处理函数
typesetError: function (doc, math, err) {doc.typesetError(math, err)}, // 排版错误处理函数
renderActions: {...} // 渲染操作
},
startup: {
elements: null, // 要进行排版的元素(默认是文档主体)
typeset: true, // 是否执行初始排版
ready: Startup.defaultReady.bind(Startup), // 组件加载完成时调用
pageReady: Startup.defaultPageReady.bind(Startup), // MathJax 和页面准备好时调用
document: document, // 要处理的文档(或片段或字符串)
invalidOption: 'warn', // 无效选项是致命错误还是产生警告
optionError: OPTIONS.optionError, // 用于报告无效选项的函数
input: [], // 要使用的输入引擎的名称(从已加载的引擎中选择)
output: null, // 要使用的输出引擎的名称(从已加载的引擎中选择)
handler: null, // 要注册的处理程序的名称(从已加载的处理程序中选择)
adaptor: null // 要使用的 DOM 适配器的名称(从已加载的适配器中选择)
},
svg: {
scale: 1, // 所有表达式的全局缩放因子
minScale: .5, // 要使用的最小缩放因子
mtextInheritFont: false, // 使 mtext 元素使用周围字体
merrorInheritFont: true, // 使 merror 文本使用周围字体
mathmlSpacing: false, // 为 true 时使用 MathML 间距规则,为 false 时使用 TeX 规则
skipAttributes: {}, // 不复制到输出的 RFDa 等属性
exFactor: .5, // ex 单位的默认大小(以 em 为单位)
displayAlign: 'center', // 当 indentalign 设置为 'auto' 时的默认值
displayIndent: '0', // 当 indentshift 设置为 'auto' 时的默认值
fontCache: 'local', // 字体缓存设置,可选值为 'local'、'global' 或 'none'
localID: null, // 用于本地字体缓存的 ID(用于单方程处理)
internalSpeechTitles: true, // 插入带有语音内容的 <title> 标签
titleID: 0 // 用于 aria-labeledby 标题的初始 ID 编号
}
};
按需配置,如果你都不需要,你可以什么也不配置
需要复制时,在对应公式部分点击 右键 -> Copy to Clipboard -> TeX Commands 即可完成复制
$a+b-c$
效果:$a+b-c$
$a\times b$ (注意\times和b之间要有空格)
效果:$a\times b$
$\frac{a}{b}$
效果:$\frac{a}{b}$
$(\frac{a}{b})$
$\left( \frac{a}{b} \right)$
$\left[ \frac{a}{b} \right]$
# 当使用\left和\right时,它们会根据所包含内容的大小自动调整括号的大小,使得括号能够合适地包围住内容,看起来更加美观和协调。而普通的小括号()不会自动调整大小,在一些复杂的公式中,可能会出现括号与内容大小不匹配的情况
效果:
$(\frac{a}{b})$
$\left( \frac{a}{b} \right)$
$\left[ \frac{a}{b} \right]$
$\frac{(a+b)\times c}{(d-e)\times f}$
效果:$\frac{(a+b)\times c}{(d-e)\times f}$
$a < b$
$a > b$
$a = b$
$a \not= b$
$a \leq b$
$a \geq b$
$a \equiv b$
效果:
$a < b$
$a > b$
$a = b$
$a \not= b$
$a \leq b$
$a \geq b$
$a \equiv b$
$x^a$, $x^{ab}$, $x^ab$
# 多个字符时,要用花括号代替,不过单个字符时有无花括号是等价的
效果:$x^a$, $x^{ab}$, $x^ab$
$a_n$, $a_{nm}$, $a_nm$
# 花括号原理同上
效果:$a_n$, $a_{nm}$, $a_nm$
$\sqrt a$, $\sqrt[n]a$, $\sqrt[nm]{ab}$
效果:$\sqrt a$, $\sqrt[n]a$, $\sqrt[nm]{ab}$
$a_i^2$, $C^2_{10}$
效果:$a_i^2$, $C^2_{10}$
$\left\\{
x_1,x_2
\right\\}$
# 不能直接打花括号,必须要有\left,\right
# 可以写成一行,这样仅为了方便查看
效果:$\left\{ x_1,x_2 \right\}$
$A \in B$ // 元素A 属于 集合B
$A \notin B$ // 元素A 不属于 集合B
效果:
$A \in B$
$A \notin B$
$A \subset B$ // 集合A是集合B的 真子集,意味着A的所有元素都在B中,但B中至少存在一个元素不在A中
$A \subseteq B$ // 集合A是集合B的 子集,即A的所有元素都在B中,A和B有可能相等
$A \supset B$ // 集合A 真包含 集合B,表明B的所有元素都在A中,但A中至少存在一个元素不在B中
$A \supseteq B$ // 集合A 包含 集合B,即B的所有元素都在A中,A和B有可能相等
效果:
$A \subset B$
$A \subseteq B$
$A \supset B$
$A \supseteq B$
$A \cap B$ // 集合A与集合B的 交集,由既属于A又属于B的所有元素共同组成
$A \cup B$ // 集合A与集合B的 并集,由属于A或者属于B的所有元素合并组成
$A \setminus B$ // 集合A与集合B的 差集,是由所有属于A但不属于B的元素构成的集合,也可表示为 A - B
$\complement_U A$ // 集合A在全集U中的 补集,即全集中所有不属于A的元素所组成的集合
效果:
$A \cap B$
$A \cup B$
$A \setminus B$ 或 $A - B$
$\complement_U A$
$ \cdot $ // 一个点
$ \cdots $ // 三个点
$ \mid $ // 分隔符
效果:
$ \cdot $
$ \cdots $
$ \mid $
$A = \left\\{ x_1,x_2,\cdots,x_n \right\\}$ // 定义集合A,集合A由元素x_1, x_2, ..., x_n组成
$A\cap \complement_{A\cup B}B=A - B$ // 集合A与集合B在A和B的并集中的补集的交集,等于集合A与集合B的差集
效果:
$A = \left\{ x_1,x_2,\cdots,x_n \right\}$
$A\cap \complement_{A\cup B}B=A - B$
$\sin x$, $\cos x$, $\tan x$, $\cot x$
# 注意中间的空格
效果:$\sin x$, $\cos x$, $\tan x$, $\cot x$
$\arcsin x$, $\arccos x$, $\arctan x$
效果:$\arcsin x$, $\arccos x$, $\arctan x$
$\sinh x$, $\cosh x$, $\tanh x$, $\coth x$
效果:$\sinh x$, $\cosh x$, $\tanh x$, $\coth x$
$\log_ax$, $\ln x$, $\lg x$
效果:$\log_ax$, $\ln x$, $\lg x$
$\sum$, $\sum_{i=1}^n$, $\sum_{i=1}^na_i$, $\sum_{i=1}^{na_i}$
效果:$\sum$, $\sum_{i=1}^n$, $\sum_{i=1}^na_i$, $\sum_{i=1}^{na_i}$
$\infty$, $+\infty$, $-\infty$
效果:$\infty$, $+\infty$, $-\infty$
$\rightarrow$, $\leftarrow$, $\uparrow$, $\downarrow$
效果:$\rightarrow$, $\leftarrow$, $\uparrow$, $\downarrow$
$\lim$, $\lim_{x\rightarrow 0}$, $\lim_{x\rightarrow \infty}$
效果:$\lim$, $\lim_{x\rightarrow 0}$, $\lim_{x\rightarrow \infty}$
$\int$, $\int_a^b$, \$int_{ab}^{cd}$
$ \int_a^b \left( -\frac{1}{x^2} \right) dx = \frac{1}{x}|_a^b = \frac{1}{b} - \frac{1}{a} $
效果:
$\int$, $\int_a^b$, $int_{ab}^{cd}$
$ \int_a^b \left( -\frac{1}{x^2} \right) dx = \frac{1}{x}|_a^b = \frac{1}{b} - \frac{1}{a} $
$\iint$, $\iint_D$
效果:$\iint$, $\iint_D$
$\iiint$, $\iiint_D$
# 以此类推,超过四重的积分不可用
效果:$\iiint$, $\iiint_D$
$\partial$
效果:$\partial$
$\nabla$
效果:$\nabla$
$ \star $ , $ \ast $, $ \oplus $, $ \circ $, $ \bullet $
效果:$ \star $ , $ \ast $, $ \oplus $, $ \circ $, $ \bullet $
$ \alpha $ // 阿尔法
$ \beta $ // 贝塔
$ \gamma $ // 伽马
$ \delta $ // 德尔塔,变化量
$ \epsilon $ // 伊普西龙
$ \zeta $ // 泽塔
$ \eta $ // 伊塔,机械效率
$ \lambda $ // 兰姆达,常数
$ \mu $ // 缪,摩擦系数
$ \pi $ // 派,圆周率
$ \rho $ // 柔,极径
$ \sigma $ // 西格马,方差
$ \tau $ // 陶,力矩
$ \phi $ // 斐,欧拉函数
$ \chi $ // 希,卡方分布
$ \omega $ // 欧米伽,电阻
效果:
$ \alpha $,
$ \beta $,
$ \gamma $,
$ \Delta $,
$ \epsilon $,
$ \zeta $,
$ \eta $,
$ \lambda $,
$ \mu $,
$ \pi $,
$ \rho $,
$ \sigma $,
$ \tau $,
$ \phi $,
$ \chi $,
$ \omega $
$$
\begin{aligned}
a \\
b,c \\
d
\end{aligned}
$$
# '\\'是换行
效果:
\(\begin{aligned}
a \\
b,c \\
d
\end{aligned}\)
$a \ b $
# '\'表示一空格
效果:$a \ b $
$$\begin{aligned}
[(n+1)!+k]\operatorname{mod}k &=(n+1)!\operatorname{mod}k+k\operatorname{mod}k
\\ &=0+0
\\ &=0
\end{aligned}$$
# '&'是对齐
效果:
\(\begin{aligned}
[(n+1)!+k]\operatorname{mod}k &=(n+1)!\operatorname{mod}k+k\operatorname{mod}k
\\ &=0+0
\\ &=0
\end{aligned}\)
$$ \begin{cases}
x_1+x_2=2
\\ x_1-x_2=0
\end{cases} $$
效果:
\(\begin{cases}
x_1+x_2=2
\\ x_1-x_2=0
\end{cases}\)
$$ \left(
\begin{matrix}
a &b
\\c &d
\end{matrix}
\right)
,
\left|
\begin{matrix}
a &b
\\c &d
\end{matrix}
\right| $$
效果:
\(\left(
\begin{matrix}
a &b
\\c &d
\end{matrix}
\right)
,
\left|
\begin{matrix}
a &b
\\c &d
\end{matrix}
\right|\)
$$\begin{array}{c|lcr} n & \text{左} & \text{中} & \text{右} \\ \hline 1 & 0.24 & 1 & 125 \\ 2 & -1 & 189 & -8 \\ 3 & -20 & 2000 & 1+10i \\ \end{array}$$
效果:
\(\begin{array}{c|lcr} n & \text{左} & \text{中} & \text{右} \\ \hline 1 & 0.24 & 1 & 125 \\ 2 & -1 & 189 & -8 \\ 3 & -20 & 2000 & 1+10i \\ \end{array}\)
2025-01-18 20:20:58
今天进行 时光本 macOS端 更新的时候,上传安装包到 App Store Connect 成功后,但是在 App Store Connect 一直无法看到相应的构架包,查看邮件后发现了一个警告邮件:Action needed: The uploaded build for 时光本-日记本·笔记本·记事本·备忘录 has one or more issues.
App Store Connect
Hello,
We noticed one or more issues with a recent delivery for the following app:
时光本-日记本·笔记本·记事本·备忘录 Version 1.2.9 Build 129 Please correct the following issues and upload a new binary to App Store Connect.
ITMS-91109: Invalid package contents - The package contains one or more files with the com.apple.quarantine extended file attribute, such as “com.gorpeln.xxx.pkg/Payload/GPNotesForMac.app/Contents/Resources/zh-Hans.lproj/Main.strings”. This attribute isn’t permitted in macOS apps distributed on TestFlight or the App Store. Please remove the attribute from all files within your app and upload again.
Apple Developer Relations
在网上查找这个错误提示表明,提交到 App Store 的 macOS 应用程序包中包含一个或多个带有com.apple.quarantine扩展文件属性的文件,比如com.gorpeln.xxx.pkg/Payload/GPNotesForMac.app/Contents/Resources/zh-Hans.lproj/Main.strings,而这种属性是不被允许的。
com.apple.quarantine属性是 macOS 的一个安全特性,用于标记从不受信任的来源获取的文件,例如通过互联网下载或 AirDrop 接收的文件,以防止潜在的恶意软件。要解决这个问题,需要移除应用程序中所有文件的 com.apple.quarantine 属性。
看到网上的结果后知道是安装包中某些文件被添加了com.apple.quarantine 属性,具体可能导致相关错误的原因也很多:
但是具体怎么被添加的就不得而知了,于是就进行了漫长的排查解决过程,最后结果让自己很无奈。
首先导出安装包,按照提示路径,找到对应文件,使用 xattr 查找该文件是否有 com.apple.quarantine ,查找结果显示的确有,并且有标记是keka解压软件,因为我是用的keka进行的安装包解压,想着keka的标记应该是该流程添加,并不是原来 com.apple.quarantine 属性添加的直接原因,于是就尝试其他方法解决该问题。
为什么要更新 Xcode 呢,因为在提交 macOS 版本前先提交了 iOS 版本,iOS 版本提交后,提交成功页面显示有警告内容,提示马上要强制使用 Xcode 16 进行开发发布了,所以就想着是不是当前 Xcode 版本太低了导致的呢,于是就进行了更新操作,经过漫长的下载安装,问题依然存在,使用新的 Mac 用户也不行,只能想其他方法了。
Xcode 更新不行,想着提示有具体的安装包错误内容路径,就操作删除相关内容的 com.apple.quarantine 属性,网上也有相应的操作流程xattr -rd com.apple.quarantine /path/to/YourApp.app
,操作后继续提交,还是不行,还是同样的错误。
分析这个步骤只是进行简单的安装包操作,没有对安装包里面的内容遍历操作,于是想着进行一下遍历删除操作,但是该操作又无法直接遍历安装包内部内容,于是就进行相应的解压,遍历删除相关属性,操作还算顺利,并且重新打包上传,上传直接就报错了,提示证书问题,确实重新打包没有使用证书,重新查找资料,配置相关重新打包证书,完成打包成功上传,但是苹果接着发来邮件提示证书还是有问题。
Hello,
We noticed one or more issues with a recent delivery for the following app:
时光本-日记本·笔记本·记事本·备忘录 Version 1.3.4 Build 134 Please correct the following issues and upload a new binary to App Store Connect.
ITMS-90237: The product archive package’s signature is invalid. Ensure that it is signed with your ‘3rd Party Mac Developer Installer’ certificate.
Apple Developer Relations
查找 ITMS-90237 问题的解决方法,正确配置相关证书后依然不行,感觉这个方法不太靠谱,虽然能够成功删除 com.apple.quarantine 属性,但是重新将解压的安装包打包十分复杂,想着还是换个方法。
该步骤相关操作代码:
import os
import subprocess
import shutil
def remove_quarantine_attribute(pkg_path):
extract_dir = os.path.expanduser('~/Desktop/unpacked_pkg')
if os.path.exists(extract_dir):
try:
shutil.rmtree(extract_dir)
print(f"已删除现有的 {extract_dir} 目录。")
except Exception as e:
print(f"删除 {extract_dir} 目录时出错: {e}")
return
try:
os.makedirs(extract_dir)
print(f"成功创建 {extract_dir} 目录。")
except Exception as e:
print(f"创建 {extract_dir} 目录时出错: {e}")
return
try:
# 尝试使用 xar 解压
print("尝试使用 xar 解压 pkg 文件...")
result = subprocess.run(['xar', '-xf', pkg_path, '-C', extract_dir], capture_output=True, text=True)
if result.returncode != 0:
print(f"使用 xar 解压失败: {result.stderr}")
return
else:
print("使用 xar 解压成功。")
# 打印解压后的目录内容,便于检查
print(f"解压后的目录 {extract_dir} 内容:")
for item in os.listdir(extract_dir):
print(item)
pkg_inner_dir = os.path.join(extract_dir, 'com.gorpeln.xxx.pkg')
payload_path = os.path.join(pkg_inner_dir, 'Payload')
if os.path.exists(pkg_inner_dir) and os.path.exists(payload_path):
# 进入 Payload 所在目录并进行进一步处理
os.chdir(pkg_inner_dir)
try:
# 执行 cat Payload | gunzip -dc | cpio -i 操作
print("正在对 Payload 进行进一步解压...")
command = 'cat Payload | gunzip -dc | cpio -i'
result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=60)
if result.returncode == 0:
print("Payload 进一步解压成功。")
else:
print(f"对 Payload 进一步解压时出错: {result.stderr}")
except subprocess.TimeoutExpired:
print("对 Payload 进一步解压时超时,请检查 Payload 文件是否正常。")
except subprocess.CalledProcessError as e:
print(f"对 Payload 进一步解压时出错: {e.stderr}")
finally:
# 切换回上级目录
os.chdir('..')
# 遍历所有文件并移除属性
for root, dirs, files in os.walk(extract_dir):
for file in files:
file_path = os.path.join(root, file)
try:
subprocess.run(['xattr', '-d', 'com.apple.quarantine', file_path], check=True)
print(f"成功移除 {file_path} 的 com.apple.quarantine 属性。")
except subprocess.CalledProcessError:
# 如果文件没有该属性,忽略错误
pass
# 找到 .app 文件
app_path = None
payload_extracted_dir = os.path.join(pkg_inner_dir)
for item in os.listdir(payload_extracted_dir):
if item.endswith('.app'):
app_path = os.path.join(payload_extracted_dir, item)
break
if app_path is None:
print("未找到有效的 .app 应用程序包。")
return
# 签名 .app 包内的所有文件
certificate_name_app = "3rd Party Mac Developer Application: xxxxxxxx (xxxxxxxxx)"
find_command = f'find "{app_path}" -type f -exec codesign --force --deep --sign "{certificate_name_app}" \{\{\}} \;'
subprocess.run(find_command, shell=True)
# 签名 .app 包本身
codesign_command = f'codesign --force --deep --sign "{certificate_name_app}" "{app_path}"'
subprocess.run(codesign_command, shell=True)
# 重新打包成 pkg 文件
new_pkg_path = pkg_path.replace('.pkg', '_cleaned.pkg')
install_path = '/Applications'
certificate_name_installer = "3rd Party Mac Developer Installer: xxxxxxxx (xxxxxxxxx)"
productbuild_command = [
'productbuild',
'--component', app_path, install_path,
'--sign', certificate_name_installer,
new_pkg_path
]
result = subprocess.run(productbuild_command, capture_output=True, text=True)
if result.returncode != 0:
print(f"重新打包并签名 pkg 文件时出错:{result.stderr}")
else:
print(f"处理完成,新的签名 pkg 文件已生成: {new_pkg_path}")
except Exception as e:
print(f"处理过程中出现错误: {e}")
finally:
if os.path.exists(extract_dir):
try:
shutil.rmtree(extract_dir)
print(f"已成功删除临时目录 {extract_dir}。")
except Exception as e:
print(f"删除临时目录 {extract_dir} 时出错: {e}")
# 使用示例
pkg_path = '/Users/gorpeln/Desktop/123/GPNotesForMac.pkg'
remove_quarantine_attribute(pkg_path)
怀疑是电脑上安装的某些破解软件导致的,于是进行删除操作,包括删除了keka解压软件,再次尝试打包,问题依然没有解决。想想上个版本到现在电脑上也没有新安装什么应用,应该不是这个原因,只能想其他方法。
尝试直接删除提示有问题的文件,该文件在项目中是语言适配文件,做本地化处理的,删除后虽然对应用体验有一定的影响,但是也没有好的办法,只能先删了提交后再慢慢看具体问题了。删除后提交,居然又发邮件提错误了。。。
App Store Connect
Hello,
We noticed one or more issues with a recent delivery for the following app:
时光本-日记本·笔记本·记事本·备忘录 Version 1.3.8 Build 138 Please correct the following issues and upload a new binary to App Store Connect.
ITMS-91109: Invalid package contents - The package contains one or more files with the com.apple.quarantine extended file attribute, such as “com.gorpeln.xxx.pkg/Payload/GPNotesForMac.app/Contents/Resources/MLHudAlertInfo.png”. This attribute isn’t permitted in macOS apps distributed on TestFlight or the App Store. Please remove the attribute from all files within your app and upload again.
Apple Developer Relations
看到这个错误后心凉半截,删除了一个文件,但是同样错误又显示了一个新的文件,肯定不能再删除了,因为还不知道到底有多少文件被标记了 com.apple.quarantine 属性,其中被标记的还可能是核心代码,删除后影响项目运行的。并且标记的这个文件应该是一个第三方库文件,想着应该是第三方库有问题,输入搜索后没有发现对应文件,猜想可能是pod导入导致的错误。
查看 Podfile 文件中第三方库都没有固定版本,想着可能是第三方库更新到新版本后出现了相关问题,于是就设置了所有库的对应版本并进行更新,提交上传,问题依旧。迷茫了,不知道该怎么办了。
脑子一昏,想着是不是 Xcode 版本高的问题,用比较旧的版本会不会好呢,于是就下载安装了。显而易见,并不会。因为在app上个版本到现在我除了这次升级,并没有操作 Xcode 版本,正常不会是 Xcode 版本问题的。
不知不觉,这个问题搞了一天了。没想法了,想着还是直接删除提示的对应文件吧,再次搜索提示的MLHudAlertInfo.png,居然看到了这个相关文件,进入查看具体内容,查找在Finder中的内容,确实存在MLHudAlertInfo.png文件。那这就好办了呀,直接查看这个文件是否包含 com.apple.quarantine 属性就行了呀,使用 xattr 查看后,的确存在,我感觉有点无语,基本确认是源码问题,直接使用 xattr 遍历删除项目文件夹下所有文件,重新提交上传,问题完美解决了。
具体该问题是怎么导致的呢?
总结这次问题,为什么耗费了这么长时间呢?
最后,如果感兴趣可以去查看使用一下【时光本】应用,是一款专注效率与记录的笔记工具。可以帮助你整理各种信息,包括便签、清单、图片、纪念日、地址、链接、银行卡、名片、账号、密码等
2024-12-21 15:56:22
想为你的博客增添浓浓的春节氛围吗?快来了解我们的独特功能!设定时间后,两个喜庆的灯笼将准时在博客右上角亮起,灯笼上 “新春快乐” 的祝福熠熠生辉,瞬间让你的博客充满节日的欢乐与温馨。这不仅是装饰,更是为访客送上真挚祝福的创意方式,快来探索如何让你的博客在春节别具一格吧。
效果 方法
<link rel="stylesheet" type="text/css" href="../assets/css/deng.css">
注意:将文件下载到自己博客使用
https://gorpeln.top/assets/css/deng.css
html代码
<!-- 春节灯笼 -->
<div style="display:none;" id="lanterns">
<div class="deng-box">
<div class="deng">
<div class="xian"></div>
<div class="deng-a">
<div class="deng-b">
<div class="deng-t">快乐</div>
</div>
</div>
<div class="shui shui-a">
<div class="shui-c"></div>
<div class="shui-b"></div>
</div>
</div>
</div>
<div class="deng-box1">
<div class="deng">
<div class="xian"></div>
<div class="deng-a">
<div class="deng-b">
<div class="deng-t">新春</div>
</div>
</div>
<div class="shui shui-a">
<div class="shui-c"></div>
<div class="shui-b"></div>
</div>
</div>
</div>
</div>
<!-- 春节灯笼 -->
<script>
document.addEventListener("DOMContentLoaded", function() {
// 获取当前日期
var currentDate = new Date();
// 定义开始日期和结束日期
var startDate = new Date('2025-01-22');//腊月廿三
var endDate = new Date('2025-02-12');//正月十五
// 获取 div 元素
var specialDiv = document.getElementById('lanterns');
// 检查当前日期是否在指定的日期范围内
if (currentDate >= startDate && currentDate <= endDate) {
// 如果在范围内,则显示 div
specialDiv.style.display = 'block';
} else {
// 否则,隐藏 div
specialDiv.style.display = 'none';
}
});
</script>
2024-12-21 15:32:27
飘舞的彩带,似灵动的画笔,在空中勾勒出绚丽色彩,为世界添一抹活力。
而烂漫樱花,如粉白的云霞,纷纷扬扬洒落,诉说着春日的温柔。彩带与樱花,在此交织出满是故事的奇妙天地,等你踏入探寻。
效果
方法
<!-- 樱花背景 -->
<script type="text/javascript" src="/assets/js/sakura.js"></script>
<!-- 丝带背景 -->
<script size="150" alpha="0.3" zindex="-2" src="/assets/js/ribbon.min.js"></script>
注意:将文件下载到自己博客使用
https://gorpeln.top/assets/js/sakura.js
https://gorpeln.top/assets/js/ribbon.min.js
2024-12-21 15:18:57
不仅能够精准显示距离特定节日的剩余时间,满足用户对重要节庆的期待与关注,还能直观展示今日、本周、本月乃至本年已悄然流逝的时间比例,帮助用户实时洞察时间的流转,让每一刻都能在时间的刻度中清晰呈现,实现对时间的高效感知与管理。
效果
方法
1、 countdown.html
<div class="countdownNav" id="countdownNav">
<div class="card-widget card-countdown">
<div class="item-headline"><i></i><span></span></div>
<div class="item-content">
<div class="cd-count-left">
<span class="cd-text">距离</span>
<span class="cd-name" id="eventName">节日</span>
<span class="cd-time" id="daysUntil">000</span>
<span class="cd-date" id="eventDate"></span>
</div>
<div id="countRight" class="cd-count-right">
<div id="countRight" class="cd-count-right">
<div class="cd-count-item">
<div class="cd-item-name">今日</div>
<div class="cd-item-progress"></div>
</div>
<div class="cd-count-item">
<div class="cd-item-name">本周</div>
<div class="cd-item-progress"></div>
</div>
<div class="cd-count-item">
<div class="cd-item-name">本月</div>
<div class="cd-item-progress"></div>
</div>
<div class="cd-count-item">
<div class="cd-item-name">本年</div>
<div class="cd-item-progress"></div>
</div>
</div>
</div>
</div>
</div>
</div>
2、 countdown-1.js
const CountdownTimer = (() => {
const config = {
targetDate: "2025-10-01",
targetName: "国庆",
units: {
day: { text: "今日", unit: "小时" },
week: { text: "本周", unit: "天" },
month: { text: "本月", unit: "天" },
year: { text: "本年", unit: "天" }
}
};
const calculators = {
day: () => {
const hours = new Date().getHours();
return {
remaining: 24 - hours,
percentage: (hours / 24) * 100
};
},
week: () => {
const day = new Date().getDay();
const passed = day === 0 ? 6 : day - 1;
return {
remaining: 6 - passed,
percentage: ((passed + 1) / 7) * 100
};
},
month: () => {
const now = new Date();
const total = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
const passed = now.getDate() - 1;
return {
remaining: total - passed,
percentage: (passed / total) * 100
};
},
year: () => {
const now = new Date();
const start = new Date(now.getFullYear(), 0, 1);
const total = 365 + (now.getFullYear() % 4 === 0 ? 1 : 0);
const passed = Math.floor((now - start) / 86400000);
return {
remaining: total - passed,
percentage: (passed / total) * 100
};
}
};
function updateCountdown() {
const elements = ['eventName', 'eventDate', 'daysUntil', 'countRight']
.map(id => document.getElementById(id));
if (elements.some(el => !el)) return;
const [eventName, eventDate, daysUntil, countRight] = elements;
const now = new Date();
const target = new Date(config.targetDate);
eventName.textContent = config.targetName;
eventDate.textContent = config.targetDate;
daysUntil.textContent = Math.round((target - now.setHours(0, 0, 0, 0)) / 86400000);
countRight.innerHTML = Object.entries(config.units)
.map(([key, { text, unit }]) => {
const { remaining, percentage } = calculators[key]();
return `
<div class="cd-count-item">
<div class="cd-item-name">${text}</div>
<div class="cd-item-progress">
<div class="cd-progress-bar" style="width: ${percentage}%; opacity: ${percentage}"></div>
<span class="cd-percentage ${percentage >= 46 ? 'cd-many' : ''}">${percentage.toFixed(2)}%</span>
<span class="cd-remaining ${percentage >= 60 ? 'cd-many' : ''}">
<span class="cd-tip">还剩</span>${remaining}<span class="cd-tip">${unit}</span>
</span>
</div>
</div>
`;
}).join('');
}
let timer;
const start = () => {
updateCountdown();
timer = setInterval(updateCountdown, 600000);
};
['pjax:complete', 'DOMContentLoaded'].forEach(event => document.addEventListener(event, start));
document.addEventListener('pjax:send', () => timer && clearInterval(timer));
return { start, stop: () => timer && clearInterval(timer) };
})();
优化后代码,实现倒计时包含多个时间,自动识别最近的期望时间,如果现在时间超过了所有的期望时间,就以最后一个期望时间为准。两个js二选一即可。
countdown-2.js
const CountdownTimer = (() => {
const config = {
events: [
{ targetDate: "2025-04-04", targetName: "清明节" },
{ targetDate: "2025-05-01", targetName: "劳动节" },
{ targetDate: "2025-05-31", targetName: "端午节" },
{ targetDate: "2025-10-01", targetName: "国庆节" },
{ targetDate: "2026-02-17", targetName: "春节" }
],
units: {
day: { text: "今日", unit: "小时" },
week: { text: "本周", unit: "天" },
month: { text: "本月", unit: "天" },
year: { text: "本年", unit: "天" }
}
};
const calculators = {
day: () => {
const hours = new Date().getHours();
return {
remaining: 24 - hours,
percentage: (hours / 24) * 100
};
},
week: () => {
const day = new Date().getDay();
const passed = day === 0 ? 6 : day - 1;
return {
remaining: 6 - passed,
percentage: ((passed + 1) / 7) * 100
};
},
month: () => {
const now = new Date();
const total = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
const passed = now.getDate() - 1;
return {
remaining: total - passed,
percentage: (passed / total) * 100
};
},
year: () => {
const now = new Date();
const start = new Date(now.getFullYear(), 0, 1);
const total = 365 + (now.getFullYear() % 4 === 0 ? 1 : 0);
const passed = Math.floor((now - start) / 86400000);
return {
remaining: total - passed,
percentage: (passed / total) * 100
};
}
};
function getNextEvent() {
const now = new Date();
for (let i = 0; i < config.events.length; i++) {
const eventDate = new Date(config.events[i].targetDate);
if (eventDate > now) {
return config.events[i];
}
}
return config.events[config.events.length - 1];
}
function updateCountdown() {
const elements = ['eventName', 'eventDate', 'daysUntil', 'countRight']
.map(id => document.getElementById(id));
if (elements.some(el => !el)) return;
const [eventName, eventDate, daysUntil, countRight] = elements;
const now = new Date();
const nextEvent = getNextEvent();
const target = new Date(nextEvent.targetDate);
eventName.textContent = nextEvent.targetName;
eventDate.textContent = nextEvent.targetDate;
daysUntil.textContent = Math.round((target - now.setHours(0, 0, 0, 0)) / 86400000);
countRight.innerHTML = Object.entries(config.units)
.map(([key, { text, unit }]) => {
const { remaining, percentage } = calculators[key]();
return `
<div class="cd-count-item">
<div class="cd-item-name">${text}</div>
<div class="cd-item-progress">
<div class="cd-progress-bar" style="width: ${percentage}%; opacity: ${percentage}"></div>
<span class="cd-percentage ${percentage >= 46 ? 'cd-many' : ''}">${percentage.toFixed(2)}%</span>
<span class="cd-remaining ${percentage >= 60 ? 'cd-many' : ''}">
<span class="cd-tip">还剩</span>${remaining}<span class="cd-tip">${unit}</span>
</span>
</div>
</div>
`;
}).join('');
}
let timer;
const start = () => {
updateCountdown();
timer = setInterval(updateCountdown, 600000);
};
['pjax:complete', 'DOMContentLoaded'].forEach(event => document.addEventListener(event, start));
document.addEventListener('pjax:send', () => timer && clearInterval(timer));
return { start, stop: () => timer && clearInterval(timer) };
})();
3、 style.css
/*倒计时*/
.countdownNav {
margin-top: 1em;
background-color: var(--box-color-light);
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
overflow: hidden;
width: 100%;
}
.card-countdown {
margin: 0.75em 1.5em;
}
.card-countdown .item-content {
display: flex;
}
.cd-count-left {
position: relative;
display: flex;
flex-direction: column;
margin-right: 0.8rem;
line-height: 1.5;
align-items: center;
justify-content: center;
}
.cd-count-left .cd-text {
font-size: 14px;
}
.cd-count-left .cd-name {
font-weight: bold;
font-size: 18px;
}
.cd-count-left .cd-time {
font-size: 30px;
font-weight: bold;
color: #dad9e6;
}
.cd-count-left .cd-date {
font-size: 12px;
opacity: 0.6;
}
.cd-count-left::after {
content: "";
position: absolute;
right: -0.8rem;
width: 2px;
height: 80%;
background-color: #dad9e6;
opacity: 0.5;
}
.cd-count-right {
flex: 1;
margin-left: .8rem;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.cd-count-item {
display: flex;
flex-direction: row;
align-items: center;
height: 24px;
}
.cd-item-name {
font-size: 14px;
margin-right: 0.8rem;
white-space: nowrap;
}
.cd-item-progress {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
height: 100%;
width: 100%;
border-radius: 8px;
background-color: var(--background-color-light);
overflow: hidden;
}
.cd-progress-bar {
height: 100%;
border-radius: 8px;
background-color: #dad9e6;
}
.cd-percentage,
.cd-remaining {
position: absolute;
font-size: 12px;
margin: 0 6px;
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
}
.cd-many {
color: #fff;
}
.cd-remaining {
opacity: 0;
transform: translateX(10px);
}
.card-countdown .item-content:hover .cd-remaining {
transform: translateX(0);
opacity: 1;
}
.card-countdown .item-content:hover .cd-percentage {
transform: translateX(-10px);
opacity: 0;
}
2024-11-08 16:03:43
管理友链时采取手动点击检验的方式,随着时间的推移,友链数量逐渐增加,这一做法显然已不再高效。于是就需要写了一项类似API的功能,输出所有友链数据的可达性。
博客中预览:https://friends.gorpeln.top/
部署教程:参考文章尾部的参考链接
友链相关的常见问题