加载中…
+diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index faac19a..db62343 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -32,4 +32,4 @@ assignees: ''
## 检查清单
- [ ] 我已经搜索过 [已有 Issue](https://github.com/shumengya/meme-api/issues?q=is%3Aissue) 确认没人提过
-- [ ] 我愿意按 [CONTRIBUTING.md](../../CONTRIBUTING.md) 提一个 PR(可选)
+
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 886860c..54e75ee 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -19,7 +19,6 @@ Closes #
- [ ] ⚡ 性能优化(perf)
- [ ] 📝 文档(docs)
- [ ] 🔧 构建 / 脚本 / 配置(chore)
-- [ ] 🖼 素材投稿(新表情包 / 新分类)
## 改动内容
@@ -34,32 +33,22 @@ Closes #
- [ ] `public/index.html`
-- [ ] `public/meme/...`(素材)
- [ ] `scripts/generate-manifest.mjs`
- [ ] `转化.py`
- [ ] `public/memes.json`(清单,由 `npm run build` 自动重生成)
- [ ] `dist/memes.json`(构建产物,请确认未手动修改)
-- [ ] 文档(README / CONTRIBUTING / CHANGELOG / 其他)
+- [ ] 文档(README / CHANGELOG / 其他)
- [ ] GitHub 配置(Issue 模板 / PR 模板 / .github 目录)
-## 素材来源声明(仅素材投稿必填)
-
-- **来源**:原创 / 转载自 `xxx` / 协议 `CC BY 4.0` / ...
-- **是否商用素材**:否
-- **是否涉及他人作品**:否 / 是,已附原始协议与作者
-- **协议确认**:我同意按 [CC BY-NC-SA 4.0](./ASSET_LICENSE.md) 发布
-
## 自检清单
-- [ ] 我已经读了 [CONTRIBUTING.md](./CONTRIBUTING.md)
- [ ] 本地 `npm run build` 通过,`public/memes.json` 已重生成
- [ ] 本地 `npm run dev` 跑过,浏览器实测没回归
- [ ] 移动端(DevTools 切到 375px)布局没崩
- [ ] 改动不引入新外部依赖
- [ ] 没有把 `dist/`、`node_modules/`、`__pycache__/`、`*.pyc`、`原图/` 里的源文件等 commit 进去
-- [ ] 素材若涉他人,已在 PR 描述里写明出处与原始协议
- [ ] 我已更新 [CHANGELOG.md](./CHANGELOG.md)(如适用)
## 截图 / 录屏
-
+
diff --git a/ASSET_LICENSE.md b/ASSET_LICENSE.md
index 1e0d259..662b98f 100644
--- a/ASSET_LICENSE.md
+++ b/ASSET_LICENSE.md
@@ -54,16 +54,6 @@ CC BY-NC-SA 的 **NC(NonCommercial)** 含义:
如确有商用需求(广告、表情商店、付费内容、商品等),请提 [Issue](https://github.com/shumengya/meme-api/issues) 或直接联系作者协商。
-## 关于投稿
-
-向本仓库提交 PR 投稿素材,即表示你:
-
-1. 确认你对所投稿素材拥有合法分发权利(自己原创 / 协议允许 / 来源已授权)
-2. 同意本仓库按 **CC BY-NC-SA 4.0** 协议发布你的投稿
-3. 同意其他人在遵守上述协议的前提下使用、改编、再分发你的投稿
-
-如果你的素材使用了**他人的原始素材**,请在 PR 描述里写明出处与原始协议。
-
## 侵权处理
如果你认为本仓库的某张表情包**侵犯了你的合法权益**(版权、肖像权、商标等),请:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8d8605..89e222b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,7 +17,7 @@
## [1.0.0] - 2026-06-04
### 新增
-- 仓库首次**公开**整理:补齐 README、LICENSE、CONTRIBUTING、CHANGELOG、Issue / PR 模板
+- 仓库首次**公开**整理:补齐 README、LICENSE、CHANGELOG、Issue / PR 模板
- 双协议声明:代码 MIT,表情包素材 CC BY-NC-SA 4.0
- 收录 **51 个分类、~2600+ 张**表情包(WebP / GIF)
- 图库前端(`public/index.html`):分类侧边栏 + 搜索 + 移动端 4 列 / 桌面 12 列网格
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 74a8116..0000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,232 +0,0 @@
-# 投稿指南 🤝
-
-非常欢迎你一起完善这个表情包图库!这份文档说明**怎么提交素材 / 修复 / 功能**才能又快又稳被合入。
-
-> 阅读前请先看一眼 [README](./README.md) 和 [ASSET_LICENSE](./ASSET_LICENSE.md),了解项目结构与协议。
-
-## 目录
-
-- [我能贡献什么?](#-我能贡献什么)
-- [我该 fork 哪个分支?](#-我该-fork-哪个分支)
-- [提 Issue](#-提-issue)
-- [素材投稿流程](#-素材投稿流程)
-- [代码 / 文档投稿](#-代码--文档投稿)
-- [约定与规范](#-约定与规范)
-- [本地自检](#-本地自检)
-- [PR 流程](#-pr-流程)
-- [审核标准](#-审核标准)
-- [行为准则](#-行为准则)
-
-## 🎁 我能贡献什么?
-
-| 类型 | 说明 |
-| --- | --- |
-| 🖼 新表情 / 新分类 | 投到 `public/meme/<新分类>/` 下 |
-| 🐛 修坏图 / 错图 | 替换、删除或重新分类 |
-| 🌐 图库前端改进 | 修改 `public/index.html`(单文件,无构建) |
-| ⚙️ 构建脚本改进 | 改 `scripts/generate-manifest.mjs` 或 `转化.py` |
-| 📝 文档 | 改进 `README.md`、本文件、API 说明页 |
-| 🧪 Bug 报告 / 体验建议 | 提 Issue |
-
-## 🌿 我该 fork 哪个分支?
-
-**默认 `main` 分支。** 任何 PR 都基于 `main`。
-
-预览分支 `preview` 是 wrangler 部署的临时产物,**不要**直接 PR 到那里。
-
-## 🐞 提 Issue
-
-- **Bug 报告**:用 [Bug 报告模板](.github/ISSUE_TEMPLATE/bug_report.md),按字段填好
-- **新功能 / 改进建议**:用 [功能建议模板](.github/ISSUE_TEMPLATE/feature_request.md)
-- **侵权 / 删除请求**:标题加 `[takedown]`,并附素材路径和说明
-
-## 🖼 素材投稿流程
-
-### 0. 先确认你有分发权
-
-只投**以下任一**的素材:
-
-- ✅ 你自己原创 / 自己画的表情包
-- ✅ 协议允许二次分发的素材(如 CC BY、CC BY-SA、公共领域)
-- ✅ 你已经获得作者明确授权
-
-**别投**:商用素材、明显盗图、官方美术资源(除非协议明确允许)。
-
-### 1. 处理素材(推荐)
-
-> `转化.py` 会帮你自动编号、缩放、转格式;**不要**手动起 `1.webp` 这样的名字,编号是脚本加的。
-
-```bash
-# 拿一个新分类举例
-mkdir -p 原图/我的新分类
-cp ~/Downloads/表情.png 原图/我的新分类/
-
-# 装 Pillow(一次性)
-python -m pip install pillow
-
-# 转换:自动编号、统一 webp/gif、最长边缩放到 250px
-python 转化.py
-
-# 把生成结果拷入发布目录
-cp -r 原图-已处理/我的新分类 public/meme/
-```
-
-参数说明:
-
-| 参数 | 作用 |
-| --- | --- |
-| `--delete-sources` | 处理完删除 `原图/` 里的源文件(默认保留) |
-| `--max-side 250` | 最长边像素,默认 250px |
-| `--jobs 10` | 并行线程数 |
-
-### 2. 直接投到 `public/meme/`
-
-如果你的素材**已经**是 `N.webp` / `N.gif` 命名,且最长边 ≤ 250px,可以**直接**放到 `public/meme/<分类>/`,不跑 `转化.py`。脚本在生成清单时会自动识别已编号的素材。
-
-### 3. 重新生成清单
-
-```bash
-npm run build
-```
-
-这一步会重写 `public/memes.json` 与 `dist/memes.json`,**请把这两个文件一起 commit**。
-
-### 4. 提交 PR
-
-- **PR 标题**:`feat(meme): 新增 xxx 分类` 或 `fix(meme): 删除损坏的 白色小人/123.webp`
-- **PR 描述**:
- - 素材来源(自己画 / 转载自 xxx / 协议 xxxx)
- - 大致数量和分类
- - 截图(可选)
-
-## 💻 代码 / 文档投稿
-
-### 前端
-
-- `public/index.html` 是**单文件**前端(HTML + 内联 CSS + 内联 JS,**无任何依赖**)
-- 改完**直接刷新本地预览**就能看效果:
- ```bash
- npm run dev
- # 浏览器打开 http://localhost:8788
- ```
-- 尽量保持:
- - 移动端优先 → 桌面端
- - 暗色模式自适应
- - 键盘可达(`Tab`、`Enter`、`Esc`)
- - 不引入外部依赖
-
-### 构建脚本
-
-- `scripts/generate-manifest.mjs` — Node 18+ ESM
-- `转化.py` — Python 3.8+,只依赖 Pillow
-- 改完跑 `npm run build` 验证 `memes.json` 生成正确
-
-### 文档
-
-- 写完后检查一下渲染效果:本地打开 `README.md` 看看排版
-- 文档用 **中文**;变量名、函数名、commit 标题用**英文**
-- 引用外部链接优先官方文档
-
-## 📐 约定与规范
-
-### Commit 消息
-
-遵循 [Conventional Commits](https://www.conventionalcommits.org/):
-
-```
-feat(meme): 新增 黄仁勋 分类
-fix(meme): 替换损坏的 滑稽/3.webp
-docs: 完善 README 的 API 文档
-style(frontend): 调整移动端栅格断点
-refactor(scripts): 拆分 generate-manifest.mjs
-chore: 升级 wrangler 到 4.7
-```
-
-允许类型:`feat` / `fix` / `docs` / `style` / `refactor` / `perf` / `test` / `chore` / `ci`
-
-### 分支名
-
-- `feat/<短描述>`:新功能 / 新分类
-- `fix/<短描述>`:修 bug
-- `docs/<短描述>`:文档
-- `chore/<短描述>`:杂项
-
-例:`feat/meme-add-minecraft-pack`、`fix/meme-broken-gifs`
-
-### 分类目录命名
-
-- 用**清晰的中文**,避免过长的字串
-- 不要带空格(用空格的话在 URL 里得编码,体验差)
-- 不要带特殊符号 `/`、`\`、`#`、`?`
-- 想拆同主题的子分类就再加一个目录,例如 `抹茶旦旦2`
-
-### 素材命名
-
-- **不要**自己命名;让 `转化.py` 续号
-- 已经手动起好的也 OK(`1.webp` / `2.gif` 这种),脚本会从已有最大编号续起
-
-### 文件格式
-
-- 静态图:`.webp`(默认 lossless,质量 + 体积兼顾)
-- 动图:`.gif`(Pillow 转码;WebP 动图也会被转成 GIF 提升兼容性)
-- 缩放:最长边 **250px**
-- 单张建议 ≤ **30KB**;动图 ≤ **100KB**
-
-## ✅ 本地自检
-
-提交前请跑一遍:
-
-```bash
-# 1. 构建通过、清单生成正常
-npm run build
-
-# 2. 本地预览,检查图库显示、复制/下载、侧边栏等
-npm run dev
-
-# 3. (可选)检查素材大小
-du -sh public/meme/<新分类>/
-ls -la public/meme/<新分类>/ | head
-```
-
-确认:
-
-- [ ] 新分类在侧边栏出现,编号连续无跳号
-- [ ] 点开任意一张能正常复制 URL / Markdown / HTML / 下载
-- [ ] 移动端(DevTools 切到 375px)布局没崩
-- [ ] 没有把 `dist/`、`node_modules/`、`__pycache__/`、`*.pyc` 等 commit 进去
-
-## 🔁 PR 流程
-
-1. Fork → 新分支 → 改代码 / 投素材
-2. `npm run build` 自检
-3. 提 PR 到 `main`
-4. 描述清楚改了什么;附截图(如有 UI 变化)
-5. 等 CI / 维护者 review
-6. 必要的话按 review 改一轮
-7. 合并后 Cloudflare Pages 会自动部署
-
-## 🧐 审核标准
-
-PR 被合的优先级:
-
-- ✅ 修复真实 bug
-- ✅ 引入来源清晰的新素材
-- ✅ 改进图库体验(无障碍 / 性能 / 暗色)
-- ✅ 改进文档可读性
-- ⚠️ 大批量素材(> 200 张)建议先开 Issue 沟通
-- ❌ 协议不清晰的素材
-- ❌ 引入外部依赖(CDN 库、构建工具)的"重"改动
-- ❌ 与项目无关的"小改"(拼写错误除外)
-
-## 🫶 行为准则
-
-- 友善、尊重、就事论事
-- 拒绝任何形式的骚扰、歧视、人身攻击
-- 提 Issue / 评论前先搜一下避免重复
-- 不确定时先问,错了就改
-
-违反行为准则的评论 / PR 会被关闭,屡次违反会被封禁。
-
----
-
-有任何问题,欢迎在 [Issue](https://github.com/shumengya/meme-api/issues) 里沟通。谢谢你的贡献!🌱
diff --git a/README.md b/README.md
index 5aea7d7..d6ae5e1 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
[](https://github.com/shumengya/meme-api/network)
[](https://github.com/shumengya/meme-api/commits/main)
-[在线浏览](https://meme.smyhub.com) · [API 文档](https://meme.smyhub.com/readme/) · [投稿](#-投稿指南) · [更新日志](./CHANGELOG.md)
+[在线浏览](https://meme.smyhub.com) · [API 文档](https://meme.smyhub.com/readme/) · [更新日志](./CHANGELOG.md)
@@ -235,15 +235,6 @@ meme-api/
如果想换 CDN 域名,可以在前端 JS 里给 `memes.json` 加 `baseUrl` 字段(详见脚本注释)。
-## 🤝 投稿指南
-
-欢迎补充新分类、修复坏图、改善图库体验!开始前请先看 **[CONTRIBUTING.md](./CONTRIBUTING.md)**,重点:
-
-- 素材需是 **你自己有权分发** 的,或来源已明确允许
-- 分类目录用清晰中文名;编号脚本会自动续号
-- 一张图只发一个分类;动图尽量保留动画
-- 提交 PR 前跑一次 `npm run build` 自检
-
## 📝 更新日志
见 [CHANGELOG.md](./CHANGELOG.md)。
@@ -258,12 +249,11 @@ meme-api/
| **表情包素材**(`public/meme/` 下的所有 `.webp` / `.gif` 文件) | CC BY-NC-SA 4.0 | [ASSET_LICENSE.md](./ASSET_LICENSE.md) |
简言之:代码随便用、商用随便;素材**署名 + 非商用 + 相同方式共享**。
-如果你投稿了素材,默认视为同意按 CC BY-NC-SA 4.0 发布;商用授权请单独联系。
## 🙏 致谢
-- 所有为这个图库添砖加瓦的[贡献者](https://github.com/shumengya/meme-api/graphs/contributors)
-- 各个表情包原图的原作者 / 出处方
+- [Cloudflare Pages](https://pages.cloudflare.com/) 提供静态托管
+- [Pillow](https://python-pillow.org/) 提供图片处理能力
- [Cloudflare Pages](https://pages.cloudflare.com/) 提供静态托管
- [Pillow](https://python-pillow.org/) 提供图片处理能力
diff --git a/blog-post.md b/blog-post.md
new file mode 100644
index 0000000..3a779ed
--- /dev/null
+++ b/blog-post.md
@@ -0,0 +1,186 @@
+# [萌芽妙妙工具] 萌芽表情包图库 —— 一个纯静态的表情包 API + 图库
+
+> 项目地址:[github.com/shumengya/meme-api](https://github.com/shumengya/meme-api)
+> 在线体验:[meme.smyhub.com](https://meme.smyhub.com)
+> 协议:MIT协议
+
+---
+
+## 这是做什么的
+
+平时在群里聊天、写博客、做项目文档的时候,经常需要找表情包。网上搜到的图要么带水印,要么链接失效,要么格式不统一,用起来很不顺手。
+
+所以我整理了一个表情包图库,做成纯静态站点部署在 Cloudflare Pages 上。打开网页就能翻、能搜、能一键复制链接,也对外提供 JSON API,方便在任何地方调用。
+
+目前一共收录了 **51 个分类、2600 多张** WebP / GIF 表情包,全部经过统一处理(最长边缩放到 250px,动图统一为 GIF),体积和兼容性都控制得比较好。
+
+---
+
+## 打开网页就能用
+
+图库本身是一个单文件 HTML 页面(`public/index.html`),没有任何前端框架、没有任何外部依赖,打开就是下面这样:
+
+- 左侧分类侧边栏,支持搜索过滤
+- 手机端自动变成 4 列网格,电脑端最多 12 列
+- 点击任意表情弹出操作面板,可以:
+ - 复制直链 URL
+ - 复制 Markdown 格式
+ - 复制 HTML 嵌入代码(宽度 96~400px 可选,会记住你的偏好)
+ - 直接下载原图
+
+整个页面加载完之后所有交互都是本地的,不需要后端服务。
+
+---
+
+## 也能当 API 用
+
+如果你不想打开网页,直接用接口拉数据也可以:
+
+```bash
+curl -sS "https://meme.smyhub.com/memes.json"
+```
+
+返回结构大概长这样:
+
+```json
+{
+ "generatedAt": "2026-05-19T13:01:45.229Z",
+ "categories": [
+ {
+ "id": "白色小人",
+ "name": "白色小人",
+ "items": [
+ { "file": "1.webp", "path": "白色小人/1.webp" },
+ { "file": "2.webp", "path": "白色小人/2.webp" }
+ ]
+ }
+ ]
+}
+```
+
+拿到清单之后,拼接一下就是直链:
+
+```
+https://meme.smyhub.com/meme/白色小人/1.webp
+```
+
+中文路径记得 URL 编码,图库里的「复制链接」按钮已经帮你编好了。
+
+接口还做了 CORS,任何网页、博客、脚本、聊天机器人都可以直接跨域调用。
+
+---
+
+## 引用单张表情
+
+在 Markdown 或 HTML 里直接贴:
+
+```markdown
+
+```
+
+```html
+
+```
+
+因为托管在 Cloudflare Pages,全球边缘节点都有缓存,国内访问速度也还可以。
+
+---
+
+## 技术结构
+
+整个项目非常轻,没有复杂架构:
+
+```
+meme-api/
+├── public/
+│ ├── index.html ← 图库前端(单文件,零依赖)
+│ ├── meme/ ← 处理后的表情包素材
+│ ├── memes.json ← 自动生成的清单
+│ ├── _headers ← CORS 响应头配置
+│ ├── _redirects ← 旧接口兼容
+│ └── readme/index.html ← API 说明页
+├── scripts/
+│ └── generate-manifest.mjs ← 生成 memes.json + 复制到 dist/
+├── 原图/ ← 原始素材
+├── 转化.py ← Python 一键处理脚本
+└── package.json
+```
+
+### 纯静态,没有后端
+
+所有内容都是静态文件。分类列表、搜索、复制、下载,全部在前端用原生 JS 完成。部署只需要把 `dist/` 丢到任意静态托管就行(Cloudflare Pages、Vercel、GitHub Pages、对象存储都可以)。
+
+### 零依赖前端
+
+`index.html` 是一个完整的单页面应用,内联了所有 CSS 和 JavaScript,没有引用任何外部 CDN。这意味着:
+
+- 内网环境、离线环境也能打开
+- 不用担心 CDN 挂掉导致页面崩
+- 审计和安全层面很干净
+
+### Python 处理脚本
+
+新素材丢进 `原图/<分类>/`,运行:
+
+```bash
+python 转化.py
+```
+
+会自动完成:
+
+- 未编号素材自动续号
+- 统一转成 WebP(静态)或 GIF(动图)
+- 最长边缩放到 250px
+- 多线程并行处理
+
+处理完的东西会输出到 `原图-已处理/`,再手动拷进 `public/meme/` 就可以上线。
+
+---
+
+## 协议说明
+
+这个仓库用了**双重许可**,代码和素材分开:
+
+| 内容 | 协议 |
+|------|------|
+| 代码(HTML / JS / Python / Node / 配置) | MIT,随便用,商用也行 |
+| 表情包素材(`public/meme/` 下的所有图片) | CC BY-NC-SA 4.0,署名 + 非商用 + 相同方式共享 |
+
+---
+
+## 部署方式
+
+### 方式一:连接 Git(推荐)
+
+在 Cloudflare Pages 创建项目,连接 GitHub 仓库的 `main` 分支:
+
+- 构建命令:`npm run build`
+- 构建输出目录:`dist`
+
+每次 push 会自动触发部署。
+
+### 方式二:CLI 直传
+
+```bash
+npm install
+npm run build
+npx wrangler pages deploy dist
+```
+
+---
+
+## 总结
+
+这个项目本质上就是一个**整理好的表情包文件夹 + 一个能用的前端 + 一个能读的 JSON 接口**。没有花里胡哨的功能,但刚好解决了"找表情、发链接、统一管理"这几个常见痛点。
+
+如果你平时也需要大量表情包,或者想给自己的项目搭一个简单的素材 API,可以试着部署一下这个项目。表情包内容会不定期整理更新。
+
+---
+
+**相关链接**
+
+- 🌐 在线图库:[meme.smyhub.com](https://meme.smyhub.com)
+- 📦 GitHub 仓库:[github.com/shumengya/meme-api](https://github.com/shumengya/meme-api)
+- 📖 API 文档:[meme.smyhub.com/readme/](https://meme.smyhub.com/readme/)
diff --git a/public/index.html b/public/index.html
index 06686dd..11fd981 100644
--- a/public/index.html
+++ b/public/index.html
@@ -3,48 +3,952 @@
静态站点(Cloudflare Pages)。在 原图/ 放未编号素材后运行 python 转化.py,输出到 原图-已处理/。将成品拷入 public/meme/ 后运行 npm run build:只生成 memes.json 并把 public/ 复制到 dist/,不会改写 public/meme/。清单默认按 public/meme/ 扫描;若尚未拷素材则回退扫描 原图-已处理/(无则 原图/)。需强制按源目录生成清单时用 npm run build:manifest-from-source。部署目录为 dist/。直链可外部引用;JSON 已配置 CORS。
GET /memes.json(与旧版兼容:GET /api/v1/memes,内部映射为同一份 JSON)
返回所有分类及文件相对路径;前端与脚本可用其拼接直链。
-curl -sS ""- -
站点根目录对应构建产物 dist/(本地从 public/ 同步而来);表情文件在 /meme/<分类>/,对应 URL:
GET /meme/<分类>/<文件名>.webp 或 .gif
https://example.com/meme/%E7%99%BD%E8%89%B2%E5%B0%8F%E4%BA%BA/1.webp-
中文或多段路径请使用编码后的 URL(浏览器会自动处理,图库「复制链接」亦为已编码地址)。
- -原图/<分类>/ 放入未编号素材;运行 python 转化.py,在 原图-已处理/ 生成编号 .webp/.gif 并限最长边(默认 300px);默认保留 原图/ 源文件,清理可加 --delete-sources。python 转化.py 转换流程中转为 GIF。npm run build:生成 dist/(含 dist/memes.json)。请先把 原图-已处理/ 拷入 public/meme/ 再构建;构建脚本不会覆盖 public/meme/。npm run build → git add/commit/push;仪表盘「构建命令」填 npm run build,「构建输出目录」填 dist。wrangler pages deploy dist 在 Git 项目里常显示为预览,属正常。
+ 说明
+ ·
+ memes.json
+ ·
+ GitHub
+
加载中…
++ 纯静态站点(Cloudflare Pages)。 + 所有接口都是 GET,JSON 接口已开启 CORS,可被任意网页 / 脚本调用。 +
+ +
+ GET
+ /memes.json
+ (旧版兼容:/api/v1/memes,内部 _redirects 映射为同一份 JSON)
+
返回所有分类及文件相对路径;前端与脚本可用其拼接直链。
+curl -sS ""
+ {
+ "generatedAt": "2026-05-19T13:01:45.229Z",
+ "categories": [
+ {
+ "id": "白色小人",
+ "name": "白色小人",
+ "items": [
+ { "file": "1.webp", "path": "白色小人/1.webp" },
+ { "file": "2.webp", "path": "白色小人/2.webp" }
+ ]
+ }
+ ]
+}
+ .webp / .gif{分类}/{文件名},拼接成 /meme/{path} 即直链站点根目录对应构建产物 dist/(本地从 public/ 同步而来);表情文件在 /meme/<分类>/,对应 URL:
+ GET
+ /meme/<分类>/<文件名>.webp
+ 或
+ .gif
+
https://meme.smyhub.com/meme/%E7%99%BD%E8%89%B2%E5%B0%8F%E4%BA%BA/1.webp
+ 中文或多段路径请使用编码后的 URL(浏览器会自动处理;图库「复制链接」按钮已帮你编好)。
+ +由 Cloudflare 边缘缓存,Cache-Control: public, max-age=...;按需可直接 ?v=<时间戳> 绕过缓存。
对 /memes.json 与 /api/v1/memes 已配置:
Access-Control-Allow-Origin: *
+Access-Control-Allow-Methods: GET, HEAD, OPTIONS
+Access-Control-Allow-Headers: Content-Type
+ 图片资源 /meme/... 无 CORS 限制(普通 <img> / <a> 引用即可)。
原图/<分类>/ 放入未编号素材;运行 python 转化.py,在 原图-已处理/ 生成编号 .webp / .gif 并限最长边(默认 250px)。默认保留 原图/ 源文件,清理可加 --delete-sources。python 转化.py 转换流程中转为 GIF。npm run build:生成 dist/(含 dist/memes.json)。请先把 原图-已处理/ 拷入 public/meme/ 再构建;构建脚本不会覆盖 public/meme/。npm run build → git add/commit/push;仪表盘「构建命令」填 npm run build,「构建输出目录」填 dist。wrangler pages deploy dist 在 Git 项目里常显示为预览,属正常。// 拉清单
+const r = await fetch("https://meme.smyhub.com/memes.json");
+const { categories } = await r.json();
+
+// 随机抽一张
+const cat = categories[Math.floor(Math.random() * categories.length)];
+const it = cat.items[Math.floor(Math.random() * cat.items.length)];
+const url = `https://meme.smyhub.com/meme/${encodeURIComponent(cat.id)}/${encodeURIComponent(it.file)}`;
+console.log(url);
+
+ import json, random, urllib.parse, urllib.request
+
+with urllib.request.urlopen("https://meme.smyhub.com/memes.json") as r:
+ data = json.load(r)
+
+cat = random.choice(data["categories"])
+it = random.choice(cat["items"])
+url = f"https://meme.smyhub.com/meme/{urllib.parse.quote(cat['id'])}/{urllib.parse.quote(it['file'])}"
+print(url)
+
+ 
+
+<img src="https://meme.smyhub.com/meme/%E7%99%BD%E8%89%B2%E5%B0%8F%E4%BA%BA/1.webp"
+ alt="哈哈" loading="lazy" width="240"
+ style="max-width:240px;width:100%;height:auto" />
+
+