最可靠方式是调用 github/gitlab rest api 获取 json 目录结构,需处理认证、分页、content-type 分流、路径安全过滤、树形渲染、大文件截断、url 状态同步及错误边界。

用 fetch 加载 Git 仓库的 raw JSON 目录结构最可靠
GitHub、GitLab 等平台不直接提供 HTML 文件列表接口,但都支持通过 API 获取仓库目录的 JSON 描述(如 GitHub 的 /repos/{owner}/{repo}/contents/)。直接请求 raw HTML 页面会触发重定向或登录跳转,且结构不可靠。必须走 REST API,并处理认证与分页。
常见错误:用 iframe 嵌入 GitHub 页面 —— 会被 X-Frame-Options: deny 拦截;用 XMLHttpRequest 请求 HTML 路径 —— 返回 404 或登录页 HTML,解析失败。
- GitHub 免登录可读公开仓库,但限速(60次/小时),需加
Accept: application/vnd.github.v3+json - 私有仓库必须传
Authorization: Bearer <token></token>,Token 权限至少含repo(非public_repo) - 目录项中
type === "dir"才能递归请求,type === "file"且size > 0才显示下载/预览链接 - 注意
git_url和download_url区别:前者是 Git 内部引用,后者才是 raw 内容直链
渲染文件树时必须区分 dir 和 file 并处理缩进与图标
纯靠 JSON 数据生成树形结构,不能依赖 CSS margin-left 硬缩进 —— 层级深了会溢出或错位。推荐用嵌套 <ul></ul> + display: none/block 控制展开,但注意:HTML 规范禁止在 <p></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill7365" title="Digital Labour"><img
src="https://img.php.cn/upload/skill/000/000/081/179144481562155.jpg" alt="Digital Labour" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill7365" title="Digital Labour" class="overflowclass">Digital Labour</a>
<p class="overflowclass">24个商业自动化AI助手,覆盖销售拓展、获客、内容创作、SEO、广告文案、记账、提案、市场调研及商业计划等</p>
</div>
<a rel="nofollow" href="/xiazai/skill7365" title="Digital Labour" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div> 内放 <ul></ul>,所以容器必须用 <div> 或语义化 <code><section></section>。
- 每个节点渲染前检查
node.name是否含非法字符(如/、..),防止路径穿越 —— 即使服务端安全,前端也应过滤显示 - 图标用内联 SVG 而非字体图标:避免加载失败导致文字错位,且可直接控制颜色和尺寸
- 文件名过长时用
text-overflow: ellipsis,但必须设white-space: nowrap和固定宽度,否则无效 - 点击目录时,先清空子节点 DOM,再发新请求,避免旧数据残留
预览代码文件要按 MIME 类型做分流,不能全塞进 <pre class="brush:php;toolbar:false;"><code></code></pre>
GitHub raw 接口返回的不是带 Content-Type: text/plain 的响应,而是根据文件扩展名自动设置(如 .js 是 text/plain,.png 是 image/png)。直接用 fetch().then(r => r.text()) 加载图片会报解析错误。
- 先 HEAD 请求获取
Content-Type,再决定后续逻辑:text/*或application/json→r.text();image/*→r.blob()→URL.createObjectURL();application/pdf→ 单独用<embed></embed> - 代码高亮不要用服务端渲染,前端选轻量库如
highlight.js,只在<pre class="brush:php;toolbar:false;"></pre>内调用hljs.highlightElement(el) - 大文件(>1MB)要限制:显示“文件过大,仅显示前 200 行”,用
ReadableStream流式读取并截断 - 避免把
response.text()结果直接 innerHTML —— 会执行其中的 script 标签,必须用textContent或createTextNode
路由状态必须同步到 URL,否则刷新就丢当前路径
单页浏览仓库时,用户复制链接分享、或刷新页面,应该回到原目录/文件。不能只靠内存变量存 currentPath。
- 用
history.pushState({path}, "", `?path=${encodeURIComponent(path)}`)更新地址栏,不触发刷新 - 监听
popstate事件,在用户点浏览器后退/前进时恢复视图 - 初始加载时从
new URL(window.location).searchParams.get("path")读取,为空则默认""(根目录) - 注意:GitHub 的路径是相对仓库根的,如
src/utils/index.ts,不能带开头斜杠,否则 API 会 404
最易被忽略的是错误边界的处理:API 失败时没 fallback UI,用户看到空白页;文件类型判断漏掉 text/x-shell 这类非标准 type 导致 shell 脚本无法高亮;还有跨域代理配置遗漏,本地开发时直接请求 GitHub API 被 CORS 拦截却没看 console 报错。这些不写进 try/catch 或没显式提示,问题就卡死在用户侧。










