Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/scripts/prune-zh-duplicates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3
"""Delete the zh duplicate site_libs/ and images/ trees after refs were
rewritten to the root trees by rewrite-zh-site-refs.py.

Safety: aborts if any zh HTML reference still resolves inside the
duplicate trees (resolution-based, so refs pointing at the root trees
do not trigger a false abort).
"""
import os
import re
import shutil
import sys

site = sys.argv[1] if len(sys.argv) > 1 else "_site"
zh_root = os.path.join(site, "zh")

if not os.path.isdir(zh_root):
print(f"No zh directory at {zh_root}; nothing to prune")
sys.exit(0)

# Any relative site_libs/ or images/ reference that resolves INSIDE the zh
# tree means the rewrite step did not cover it — refuse to delete.
ref_re = re.compile(r'["\'(=]\s*((?:\.\./)*)(?:site_libs|images)/[^"\'()\s>]+')
leftover = 0
for dirpath, _dirnames, filenames in os.walk(zh_root):
for fname in filenames:
if not fname.endswith(".html"):
continue
fpath = os.path.join(dirpath, fname)
with open(fpath, encoding="utf-8") as fh:
content = fh.read()
for match in ref_re.finditer(content):
full_ref = match.group(0).lstrip("\"'(= ")
resolved = os.path.normpath(
os.path.join(os.path.dirname(fpath), match.group(1) + full_ref)
)
if os.path.commonpath([resolved, zh_root]) == zh_root:
leftover += 1
print(f"LEFTOVER: {fpath} -> {full_ref}")
break

if leftover:
print(f"ERROR: {leftover} zh page(s) still reference the duplicate trees; refusing to delete")
sys.exit(1)

removed = 0
for tree in ("site_libs", "images"):
tree_path = os.path.join(zh_root, tree)
if os.path.isdir(tree_path):
size_mb = sum(
os.path.getsize(os.path.join(dp, fn))
for dp, _, fns in os.walk(tree_path)
for fn in fns
) // (1024 * 1024)
print(f"Deleting {tree} ({size_mb} MB)")
shutil.rmtree(tree_path)
removed += 1

print(f"Pruned {removed} duplicate tree(s) from zh/")
74 changes: 74 additions & 0 deletions .github/scripts/rewrite-zh-site-refs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
"""Rewrite zh-page asset references to share the root site trees.

Background: babelquarto renders the zh pass into _site/zh/ and copies the
shared site_libs/ and images/ trees into _site/zh/ as byte-identical
duplicates of the root copies (_site/site_libs/, _site/images/), roughly
94 MB per deploy. This script rewrites every zh HTML reference that
resolves under zh/site_libs/ or zh/images/ to the root-tree equivalent,
so both zh duplicate trees can be deleted afterwards.

Only references whose root-tree target exists are rewritten; anything
else is left untouched and reported. Run BEFORE deleting the duplicate
trees (deletion is done by prune-zh-duplicates.sh).
"""
import os
import re
import sys

SITE = sys.argv[1] if len(sys.argv) > 1 else "_site"
ZH_ROOT = os.path.join(SITE, "zh")
# Matches a relative reference whose first segment is site_libs/ or images/
# (optionally preceded by ../). Absolute, scheme-relative and srcset-less
# attributes only; url(...) inside CSS also covered via the ( prefix.
REF_RE = re.compile(
r'(?P<prefix>["\'(=])\s*(?P<dots>(?:\.\./)*)?(?P<path>(?:site_libs|images)/[^"\'()\s>]+)'
)

rewritten = 0
missing = 0
files_touched = 0


def repl(match, rel_dir):
global rewritten, missing
dots = match.group("dots") or ""
path = match.group("path")
# Resolve the reference against the page directory (zh-relative).
zh_target = os.path.normpath(os.path.join(SITE, rel_dir, dots + path))
rel_to_zh_root = os.path.relpath(zh_target, ZH_ROOT)
if rel_to_zh_root.startswith(os.pardir):
missing += 1
return match.group(0)
root_target = os.path.join(SITE, rel_to_zh_root)
if not os.path.isfile(root_target):
missing += 1
return match.group(0)
fixed = os.path.relpath(root_target, os.path.join(SITE, rel_dir))
rewritten += 1
return match.group("prefix") + fixed


for dirpath, _dirnames, filenames in os.walk(ZH_ROOT):
for fname in filenames:
if not fname.endswith(".html"):
continue
fpath = os.path.join(dirpath, fname)
with open(fpath, encoding="utf-8") as fh:
content = fh.read()
# Directory of the zh page, relative to _site, e.g. "zh" or "zh/Omics"
rel_dir = os.path.relpath(dirpath, SITE)

def sub(match):
return repl(match, rel_dir)

new_content = REF_RE.sub(sub, content)
if new_content != content:
files_touched += 1
with open(fpath, "w", encoding="utf-8") as fh:
fh.write(new_content)

print(
f"Rewrote {rewritten} reference(s) across {files_touched} zh page(s); "
f"{missing} unresolved left as-is"
)
10 changes: 10 additions & 0 deletions .github/workflows/quarto-publish-update-cache.yml
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,16 @@ jobs:
- name: Point zh figure references at shared English figures
run: python3 .github/scripts/rewrite-zh-figure-refs.py _site

# ── Deduplicate zh site_libs/ and images/ trees ──────────
# See quarto-publish.yml for full explanation. babelquarto copies
# the shared site_libs/ and images/ trees into _site/zh/ as
# byte-identical duplicates of the root copies (~94 MB). Rewrite zh
# HTML references to the root trees, then delete the duplicates.
- name: Deduplicate zh site_libs and images against root trees
run: |
python3 .github/scripts/rewrite-zh-site-refs.py _site
python3 .github/scripts/prune-zh-duplicates.py _site

# ── Lazy-load images ─────────────────────────────────────
# See quarto-publish.yml for full explanation. Native
# loading="lazy" defers offscreen figure fetches, with
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/quarto-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,18 @@ jobs:
- name: Point zh figure references at shared English figures
run: python3 .github/scripts/rewrite-zh-figure-refs.py _site

# ── Deduplicate zh site_libs/ and images/ trees ──────────
# babelquarto copies the shared site_libs/ and images/ trees into
# _site/zh/ as byte-identical duplicates of the root copies (~94 MB
# per deploy). Rewrite every zh HTML reference that resolves under
# zh/site_libs/ or zh/images/ to the root-tree equivalent, then
# delete the duplicate trees. The prune script refuses to delete if
# any zh page still resolves a reference inside the zh trees.
- name: Deduplicate zh site_libs and images against root trees
run: |
python3 .github/scripts/rewrite-zh-site-refs.py _site
python3 .github/scripts/prune-zh-duplicates.py _site

# ── Lazy-load images ─────────────────────────────────────
# Figures dominate every page's payload. Native loading="lazy"
# defers offscreen fetches (no JS, no layout shift - Quarto emits
Expand Down
24 changes: 20 additions & 4 deletions Omics/CellChatCirclePlot.zh.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ cellchat <- aggregateNet(cellchat)

整体圈图汇总所有推断的通讯交互。每个节点代表一种细胞类型;节点大小与该细胞类型参与的交互数量成正比。弧宽编码通讯强度。

```{r fig1-overall-circle, fig.width=9, fig.height=5, warning=FALSE}
```{r}
#| label: fig-1-overall-circle
#| fig-width: 9
#| fig-height: 5
#| warning: false
#| fig-cap: "整体细胞-细胞通讯圈图"
#| out.width: "95%"

Expand Down Expand Up @@ -143,7 +147,11 @@ par(mfrow = c(1, 1))

逐行对权重矩阵进行子集化,分别展示每种细胞类型的输出信号。

```{r fig2-individual-circle, fig.width=10, fig.height=10, warning=FALSE}
```{r}
#| label: fig-2-individual-circle
#| fig-width: 10
#| fig-height: 10
#| warning: false
#| fig-cap: "各细胞类型输出通讯圈图"
#| out.width: "95%"

Expand Down Expand Up @@ -174,7 +182,11 @@ par(mfrow = c(1, 1))

弦图使用 `circlize` 提供了另一种圆形视图,清晰展示细胞类型对之间的双向通讯量。

```{r fig3-chord, fig.width=7, fig.height=7, warning=FALSE}
```{r}
#| label: fig-3-chord
#| fig-width: 7
#| fig-height: 7
#| warning: false
#| fig-cap: "细胞-细胞通讯弦图"
#| out.width: "80%"

Expand Down Expand Up @@ -209,7 +221,11 @@ circos.clear()

热图视图可快速识别主要的发送者-接收者细胞对及不对称通讯模式。

```{r fig4-heatmap, fig.width=7, fig.height=6, warning=FALSE}
```{r}
#| label: fig-4-heatmap
#| fig-width: 7
#| fig-height: 6
#| warning: false
#| fig-cap: "细胞-细胞通讯热图"
#| out.width: "80%"

Expand Down
2 changes: 1 addition & 1 deletion Omics/ManhattanPlot.zh.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ ggplot()+
由于ggplot2绘图是将一张张图叠加起来,因此可以将筛选后的SNP用geom_point叠加到原图上:

```{r}
#| label: fig-2.3Hlight
#| label: fig-2.3Highlight
#| fig-cap: "高亮或标记snp"
#| out.width: "95%"
#| warning: false
Expand Down
Loading