简单修改
This commit is contained in:
parent
12dd13a76f
commit
6725a02592
5 changed files with 83 additions and 12 deletions
|
|
@ -10,7 +10,7 @@ set -euo pipefail
|
||||||
|
|
||||||
# ====== 配置区(与 deploy.sh 保持一致,ssh 不通时 REMOTE_HOST 填服务器 IP) ======
|
# ====== 配置区(与 deploy.sh 保持一致,ssh 不通时 REMOTE_HOST 填服务器 IP) ======
|
||||||
REMOTE_USER="root" # SSH 用户(服务器是 ubuntu 用户的话改成 ubuntu)
|
REMOTE_USER="root" # SSH 用户(服务器是 ubuntu 用户的话改成 ubuntu)
|
||||||
REMOTE_HOST="sausagetoast.cloud" # VPS 地址(备案期间建议填服务器 IP)
|
REMOTE_HOST="106.54.37.223" # VPS 地址(备案期间用 IP;备案完成后改回 sausagetoast.cloud)
|
||||||
REMOTE_DIR="/var/www/yukun" # 博客站点根目录
|
REMOTE_DIR="/var/www/yukun" # 博客站点根目录
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
|
|
@ -20,6 +20,15 @@ SSH_OPTS="-o StrictHostKeyChecking=accept-new"
|
||||||
|
|
||||||
echo "==> [1/3] 构建站点 (astro build)..."
|
echo "==> [1/3] 构建站点 (astro build)..."
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
# 备案期间评论区用 IP 直连(无需子域名):
|
||||||
|
# REMOTE_HOST 是 IPv4 时自动注入评论后端地址 http://<IP>:8080
|
||||||
|
# 如需自定义(比如端口不同),可提前手动 export PUBLIC_ARTALK_SERVER 覆盖
|
||||||
|
if [[ "$REMOTE_HOST" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] && [ -z "${PUBLIC_ARTALK_SERVER:-}" ]; then
|
||||||
|
export PUBLIC_ARTALK_SERVER="http://${REMOTE_HOST}:8080"
|
||||||
|
echo " 评论服务地址: ${PUBLIC_ARTALK_SERVER} (deploy/artalk/)"
|
||||||
|
fi
|
||||||
|
|
||||||
npm run build
|
npm run build
|
||||||
[ -d "$ROOT_DIR/dist" ] || { echo "✗ 构建失败:dist 不存在"; exit 1; }
|
[ -d "$ROOT_DIR/dist" ] || { echo "✗ 构建失败:dist 不存在"; exit 1; }
|
||||||
|
|
||||||
|
|
@ -94,5 +103,5 @@ $SUDO systemctl reload nginx || $SUDO systemctl restart nginx
|
||||||
REMOTE
|
REMOTE
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "✓ 完成!访问 http://<服务器IP>:8321"
|
echo "✓ 完成!访问 http://${REMOTE_HOST}:8321"
|
||||||
echo " 备案完成后:ssh 到服务器执行 sudo rm /etc/nginx/conf.d/ip-preview.conf && sudo systemctl reload nginx 即可移除"
|
echo " 备案完成后:ssh 到服务器执行 sudo rm /etc/nginx/conf.d/ip-preview.conf && sudo systemctl reload nginx 即可移除"
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,24 @@ const range = year - startYear;
|
||||||
<a href="/about">关于</a>
|
<a href="/about">关于</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="footer-bottom">
|
<div class="footer-bottom">
|
||||||
<span>© {startYear}{range > 0 ? `–${year}` : ''} Yukun · sausagetoast.cloud</span>
|
<div class="footer-meta">
|
||||||
|
<span>© {startYear}{range > 0 ? `–${year}` : ''} Yukun · sausagetoast.cloud</span>
|
||||||
|
<a
|
||||||
|
class="footer-icp"
|
||||||
|
href="https://beian.miit.gov.cn/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
title="工信部 ICP 备案查询"
|
||||||
|
>沪ICP备2026041530号-1</a>
|
||||||
|
<a
|
||||||
|
class="footer-icp"
|
||||||
|
href="https://beian.mps.gov.cn/#/query/webSearch?code=31011402022267"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
title="全国互联网安全管理服务平台"
|
||||||
|
><img src="/beian-mps.png" alt="公安备案图标" class="beian-icon" width="14" height="16" loading="lazy" />沪公网安备31011402022267号</a>
|
||||||
|
<a href="https://icp.gov.moe/?keyword=20269977" target="_blank">萌ICP备20269977号</a>
|
||||||
|
</div>
|
||||||
<span class="built">由 Astro 静态生成 · 喵~</span>
|
<span class="built">由 Astro 静态生成 · 喵~</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -65,6 +82,26 @@ const range = year - startYear;
|
||||||
color: var(--ink-faint);
|
color: var(--ink-faint);
|
||||||
font-size: 0.82rem;
|
font-size: 0.82rem;
|
||||||
}
|
}
|
||||||
|
.footer-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px 14px;
|
||||||
|
}
|
||||||
|
.footer-icp {
|
||||||
|
color: var(--ink-faint);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
transition: color .2s;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
.footer-icp:hover { color: var(--blue-600); }
|
||||||
|
.beian-icon {
|
||||||
|
width: 14px;
|
||||||
|
height: 16px;
|
||||||
|
vertical-align: -3px;
|
||||||
|
}
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.footer-nav { gap: 6px 14px; }
|
.footer-nav { gap: 6px 14px; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@ import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
<span class="link-ico">⌂</span>
|
<span class="link-ico">⌂</span>
|
||||||
<span>sausagetoast.cloud</span>
|
<span>sausagetoast.cloud</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="mailto:zhangyukunhh@gmail.com" class="link-item glass">
|
<a href="mailto:2553712@tongji.edu.cn" class="link-item glass">
|
||||||
<span class="link-ico">✉</span>
|
<span class="link-ico">✉</span>
|
||||||
<span>给我写信(Google)</span>
|
<span>给我写信(学校)</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="mailto:3385587900@qq.com" class="link-item glass">
|
<a href="mailto:3385587900@qq.com" class="link-item glass">
|
||||||
<span class="link-ico">✉</span>
|
<span class="link-ico">✉</span>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { render } from 'astro:content';
|
||||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||||
import { getPublishedPosts, formatDate, readingTime, heroCss } from '../../lib/utils';
|
import { getPublishedPosts, formatDate, readingTime, heroCss } from '../../lib/utils';
|
||||||
import Toc from '../../components/Toc.astro';
|
import Toc from '../../components/Toc.astro';
|
||||||
|
import Comments from '../../components/Comments.astro';
|
||||||
import '../../styles/prose.css';
|
import '../../styles/prose.css';
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
|
|
@ -65,6 +66,9 @@ const updated = post.data.updatedDate ? formatDate(post.data.updatedDate) : null
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 评论区(自托管 Artalk)-->
|
||||||
|
<Comments pageKey={`/posts/${post.id.replace(/\/index$/, '')}`} pageTitle={post.data.title} />
|
||||||
|
|
||||||
<!-- 上下篇 -->
|
<!-- 上下篇 -->
|
||||||
{(prev || next) && (
|
{(prev || next) && (
|
||||||
<nav class="pager reveal">
|
<nav class="pager reveal">
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
import { visit, SKIP } from 'unist-util-visit';
|
import { visit, SKIP } from 'unist-util-visit';
|
||||||
import GithubSlugger, { slug } from 'github-slugger';
|
import GithubSlugger, { slug } from 'github-slugger';
|
||||||
|
|
||||||
// Obsidian wikilink → 普通链接
|
// Obsidian wikilink → 普通链接 / 图片
|
||||||
// [[#锚点]] → 页内跳转 #锚点
|
// ![[图片.png]] → <img src="/images/图片.png">(图片放 public/images/)
|
||||||
// [[笔记名]] → /posts/笔记名
|
// ![[图片.png|题注]] → <img alt="题注">
|
||||||
// [[笔记名#锚点]] → /posts/笔记名#锚点
|
// [[#锚点]] → 页内跳转 #锚点
|
||||||
// [[x|显示文字]] → 显示文字
|
// [[笔记名]] → /posts/笔记名
|
||||||
|
// [[笔记名#锚点]] → /posts/笔记名#锚点
|
||||||
|
// [[x|显示文字]] → 显示文字
|
||||||
// 注意:Astro 内容集合的 id 会用 github-slugger 处理(大写转小写等),
|
// 注意:Astro 内容集合的 id 会用 github-slugger 处理(大写转小写等),
|
||||||
// 所以笔记名部分必须用同样的 slug 规则,否则生成的路由与构建产物不一致(404)。
|
// 所以笔记名部分必须用同样的 slug 规则,否则生成的路由与构建产物不一致(404)。
|
||||||
|
// 图片:Obsidian 用 ![[..]],remark 会把它解析成 text 节点(含 ![[..]] 字面量),
|
||||||
|
// 所以图片与链接必须用「前缀 !」区分,统一在同一段文本里处理。
|
||||||
export default function remarkWikilinks() {
|
export default function remarkWikilinks() {
|
||||||
return (tree) => {
|
return (tree) => {
|
||||||
const slugger = new GithubSlugger();
|
const slugger = new GithubSlugger();
|
||||||
|
|
@ -17,14 +21,17 @@ export default function remarkWikilinks() {
|
||||||
slugger.reset();
|
slugger.reset();
|
||||||
return slugger.slug(anchor);
|
return slugger.slug(anchor);
|
||||||
};
|
};
|
||||||
|
// 取文件名(去掉目录前缀),Obsidian 图片名通常是纯文件名
|
||||||
|
const basename = (name) => name.split(/[/\\]/).pop() || name;
|
||||||
visit(tree, 'text', (node, index, parent) => {
|
visit(tree, 'text', (node, index, parent) => {
|
||||||
if (!parent || index === null) return;
|
if (!parent || index === null) return;
|
||||||
// 不动代码块里的文本
|
// 不动代码块里的文本
|
||||||
if (parent.type === 'code' || parent.type === 'inlineCode') return;
|
if (parent.type === 'code' || parent.type === 'inlineCode') return;
|
||||||
const value = node.value;
|
const value = node.value;
|
||||||
|
// 同时匹配图片 ![[..]] 和普通链接 [[..]],用捕获组 1 的 '!' 区分
|
||||||
if (!value.includes('[[')) return;
|
if (!value.includes('[[')) return;
|
||||||
|
|
||||||
const re = /\[\[([^\]]+)\]\]/g;
|
const re = /(!?)\[\[([^\]]+)\]\]/g;
|
||||||
const parts = [];
|
const parts = [];
|
||||||
let last = 0;
|
let last = 0;
|
||||||
let m;
|
let m;
|
||||||
|
|
@ -32,7 +39,8 @@ export default function remarkWikilinks() {
|
||||||
while ((m = re.exec(value)) !== null) {
|
while ((m = re.exec(value)) !== null) {
|
||||||
matched = true;
|
matched = true;
|
||||||
if (m.index > last) parts.push({ type: 'text', value: value.slice(last, m.index) });
|
if (m.index > last) parts.push({ type: 'text', value: value.slice(last, m.index) });
|
||||||
const inner = m[1];
|
const isImage = m[1] === '!';
|
||||||
|
const inner = m[2];
|
||||||
let target, alias;
|
let target, alias;
|
||||||
const pipe = inner.indexOf('|');
|
const pipe = inner.indexOf('|');
|
||||||
if (pipe >= 0) {
|
if (pipe >= 0) {
|
||||||
|
|
@ -43,6 +51,19 @@ export default function remarkWikilinks() {
|
||||||
alias = '';
|
alias = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isImage) {
|
||||||
|
// 图片:![[文件名.png]] 或 ![[文件名.png|题注]]
|
||||||
|
const file = basename(target);
|
||||||
|
parts.push({
|
||||||
|
type: 'image',
|
||||||
|
url: '/images/' + file,
|
||||||
|
alt: alias || file,
|
||||||
|
title: null,
|
||||||
|
});
|
||||||
|
last = m.index + m[0].length;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let href;
|
let href;
|
||||||
let text;
|
let text;
|
||||||
if (target.startsWith('#')) {
|
if (target.startsWith('#')) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue