Obsidian 刷题插件 / CSV-based Quiz Plugin for Obsidian
基于 CSV 文件 / 图片文件夹的 Obsidian 刷题插件。将题库写入 CSV,或把图片放进 vault 文件夹(文件名即答案),然后在 Obsidian 中刷题、标记、筛选、统计正确率;支持将 CSV 题库编译为 .cqv 产物分发给使用者。
A CSV/image-folder-based quiz practice plugin for Obsidian. Write your question bank in a CSV, or put images in a vault folder (filename = answer), then practice with filtering, tagging, and progress tracking; compile CSV banks into .cqv artifacts for distribution.
准备题库来源:一个 .csv / .cqv 文件、一个图片文件夹,或含 manifest.json 的复合题库文件夹
Prepare a source: a .csv / .cqv file, an image folder, or a composite bank folder containing manifest.json
在设置页选择「来源类型」和对应路径 Choose the source type and path in settings
点击左侧 ribbon 的图书图标,或执行命令 打开刷题面板
Click the book icon in the left ribbon, or run the command 打开刷题面板
开始刷题 Start practicing
CSV 文件必须为 BOM 前缀的 UTF-8 编码。普通选择题为 15 列;简答题在末尾增加可选第 16 列 简答题方向:
The CSV file must be BOM-prefixed UTF-8. Choice questions use 15 columns; short-answer questions may append an optional 16th column, 简答题方向:
序号,题干,选项A,选项B,选项C,选项D,正确答案,标签,一级分类,二级分类,三级分类,收藏,掌握,重复,错题,简答题方向
| 列 / Column | 说明 / Description |
|---|---|
| 序号 / ID | 题目的唯一标识,必须非空且不重复(空或重复题号将拒绝加载)/ Unique non-empty ID (empty/duplicate IDs are rejected) |
| 题干 / Stem | 支持 Markdown 渲染 / Supports Markdown rendering |
| 选项A~D / Options A-D | 四个选项 / Four answer options |
| 正确答案 / Correct Answer | 选择题填 A、B、C 或 D;简答题填答案原文(支持完整 Obsidian Markdown/HTML,保留大小写与换行)/ Choice: A-D; short answer: the answer text (full Obsidian Markdown/HTML, case and line breaks preserved) |
| 标签 / Tags | 空格分隔,如 #数学 #代数 / Space-separated, e.g. #Math #Algebra |
| 一级~三级分类 / Categories | 三级分类体系,用于筛选 / 3-level category hierarchy for filtering |
| 收藏/掌握/错题 / Favorite/Mastered/Wrong | 初始标记:1 = 是 / yes, 0 = 否 / no。运行中的变更保存在状态文件,不再写回 CSV / Initial flags; runtime changes go to the sidecar state file, not the CSV |
| 重复 / Repeat | 作者标记的重复题(有发布价值)/ Author-marked duplicate questions (published with the bank) |
1,1+1=?,1,2,3,4,B,#数学 #加法,#数学,,,1,,,
#简答题,且选项 A/B/C/D 全为空;第 7 列填答案原文。
The tags column must contain the exact token #简答题, options A-D must be empty, and the 7th column holds the answer text.::,会整库拒绝。
15-column CSVs are supported too: without the 16th column, direction defaults to forward. The 16th column must be empty on choice rows; more than 16 columns, or any row ID containing ::, rejects the whole bank.简答题方向:> 单向、< 仅反向、<> 双向、空值等同 >;其它值整库拒绝。
Direction: > forward, < reverse-only, <> both, empty = >; other values reject the whole bank.< 只生成反向卡;<> 生成正向卡和反向卡(正向卡 id 为原题号,反向卡 id 为 原题号::rev,顺序正向紧跟反向)。反向卡的题干是原答案,答案是原题干。
< produces only the reverse card; <> produces forward then reverse cards (reverse id = id::rev). The reverse card swaps stem and answer.==高亮==、HTML 表格、数学、代码、wikilink/嵌入等);答案在点击「展示答案」前不会进入 DOM。
Stem and answer use the full Obsidian Markdown renderer; the answer is not inserted into the DOM before “展示答案”.#简答题 是保留标签:简答题不能删除,普通题不能添加。
The edit panel only edits tags/categories; edit answers and direction in the source CSV. #简答题 is reserved: short answers cannot remove it, choice questions cannot add it.设置页显式选择来源类型:
csv:CSV/CQV 文件;sidecar 为同名文件加 .sidecar.json,不扫描图片。image:图片文件夹;递归扫描 png/jpg/jpeg/webp/gif/bmp,根目录用 /。manifest:含 manifest.json 的复合题库文件夹,CSV/CQV 与图片由 manifest 绑定。复合题库清单:
{
"type": "csvquiz-bank",
"version": 1,
"content": "题库.csv",
"contents": ["补充题库.csv", "另一份.cqv"],
"imageFolder": "图片题"
}
content 是主内容文件,必填;contents 是额外内容文件数组,可选;加载顺序为 content 后接 contents。
content is the required primary file; optional contents lists additional files, loaded after content.content / contents 支持 .csv / .cqv;imageFolder 可省略(省略表示无图片)。
content / contents accept .csv / .cqv; imageFolder may be omitted for a text-only manifest... 和绝对路径;content/contents 归一化后重复、文件缺失或扩展名非法 → 整库失败。
Paths are relative to the manifest directory; .., absolute paths, duplicates, missing files or bad extensions fail the whole bank.imageFolder 存在时仍要求至少一张受支持图片;根目录用 "."。
When present, imageFolder must contain at least one supported image; use "." for the vault root.type 不匹配 → 当作无关 manifest 忽略;JSON 损坏、版本不是 1、content 缺失 → 报错不加载。
Type mismatch is ignored as an unrelated manifest; bad JSON, version other than 1, or missing content is a hard error.content + imageFolder。
Manifests are created manually; the legacy migration only writes content + imageFolder.Choose an explicit source type in settings:
csv: CSV/CQV file; sidecar is the file path + .sidecar.json; images are not scanned.image: image folder; recursive png/jpg/jpeg/webp/gif/bmp; / for vault root.manifest: a composite bank folder containing manifest.json; CSV/CQV and images are bound by the manifest.题库状态文件按来源类型命名:
manifest.json):manifest.sidecar.json(与 manifest 同目录)<content>.sidecar.json(例如 题库.csv.sidecar.json)<图片文件夹>.sidecar.json(与图片文件夹同级)每个状态文件保存答题记录、统计、记忆卡片(FSRS)、筛选、收藏/掌握/错题、标签与分类的修改等。切换题库时各题库状态相互独立、自动恢复,不会互相覆盖。
content、contents、imageFolder 各自旧 sidecar 的答题/FSRS/meta/累计统计合并到 manifest.sidecar.json;旧 sidecar 保留作回退。合并是幂等的(每次载入比对,无变化不写盘,重复运行不会翻倍)。重置进度时会记录锚点级重置时间戳,重置前写入的组成 sidecar 不再被自动并回;重置后单独使用组成来源产生的新进度仍会并入。
On first use of a composite bank, progress from the sidecars of content, contents, and imageFolder is merged into manifest.sidecar.json; the old sidecars are kept for rollback. The merge is idempotent (compared on every load, no write when unchanged, no double counting). Resetting progress records a per-anchor reset timestamp; component sidecars written before the reset are no longer merged back, while new progress written afterwards still merges.State files are named by source type:
manifest.json): manifest.sidecar.json next to the manifest<content>.sidecar.json (e.g. 题库.csv.sidecar.json)<image-folder>.sidecar.json next to the image folderEach state file holds answer records, statistics, FSRS cards, filters, favorite/mastered/wrong flags, and tag/category edits. Switching banks restores each bank's own progress automatically — no overwriting.
dailyAnswers/对错计数按增量合并,写后会校验字节数并在并发覆盖时重读合并一次
Saves use mtime + size gated read-modify-write: if the file is unchanged, the memory snapshot is written directly; if another device changed it, a base/memory/disk three-way merge runs before writing. Deletions use tombstones, daily/correct counters merge by delta, and the written byte size is verified with one re-read/merge retry on concurrent overwrite.bak);状态文件损坏或缺失时自动从备份恢复
State writes are atomic (temp file + rename) with a 30-minute backup (.bak); corrupted or missing state files are auto-recovered from backup.merged(不删除)。若需要把归档里的进度重新并入当前题库,执行命令 从已归档冲突副本恢复进度;归档会改名为 .recovered 保留备查,重复执行不会重复叠加
Merged conflict copies are archived as .merged (never deleted). To merge those archived snapshots back into the current bank, run the command 从已归档冲突副本恢复进度 (Recover progress from archived conflict copies); archives are renamed to .recovered and repeated runs do not double countdata.json 备份为 data.json.bak(如需回滚可手工恢复)
When upgrading from older versions, legacy progress is migrated automatically and data.json is backed up as data.json.bak for manual rollbackimage(图片文件夹)或 manifest(复合题库);复合题库通过 manifest.json 绑定图片文件夹。支持递归扫描子文件夹,格式为 png/jpg/jpeg/webp/gif/bmp;根图片库可用 /
Choose source type image (image folder) or manifest (composite bank); a composite bank binds its image folder via manifest.json. Recursive subfolder scan; formats png/jpg/jpeg/webp/gif/bmp; / for a vault-root image bank识图/一级子文件夹/二级子文件夹(不足或更深为 其它),标签固定为 #图片题
Filename without extension = answer; the image is the stem. Categories are 识图/first-level subfolder/second-level subfolder (missing/deeper = 其它), tag is #图片题<> 的正向/反向卡各占一张
Practice set = due reviews (sorted by urgency) + daily new questions (configurable quota, per-day, per-bank). The due/new pool ignores the answered/unanswered filter (other filters still apply), so reviewed cards cannot be silently excluded forever. Image questions participate in due/new selection too; after revealing the answer, the chosen four-level rating updates FSRS简答题方向 请在源 CSV 中修改。#简答题 是保留标签:简答题不能删除,普通题不能添加
Short answers only allow tag/category edits; edit the answer and direction in the source CSV. #简答题 is reserved: short answers cannot remove it, choice questions cannot add it<> 的正向/反向卡共享标签、分类与标记;修改任一卡会同步到同一 CSV 行
Forward/reverse cards share tags, categories and flags; editing either card updates the same CSV row.cqv 源跳过。导出清理的 B 类字段会跨 manifest 刷新保持清除,组件旧字段不会回填
Export changes to CSV (for bank authors): write tag/category/repeat edits back to each question's source CSV and clear the overrides; multi-CSV manifests are written per file, .cqv sources are skipped.cqv 二进制产物(校验题号质量,可附一句备注),随产物分发
Settings page "Optimize Bank": compile the CSV into a .cqv binary artifact next to it (ID quality validated, optional note), for distribution.cqv 时拒编。使用者把 .cqv 设为来源即可使用:产物只读、解析更快、不会被误改;产物更新后状态按题号自动对齐
Compilation requires all sources to be CSV; a manifest mixing .cqv sources is rejected. Consumers can set the .cqv as the source: read-only, faster, safe from accidental edits; state stays aligned by question ID.cqv 与同名 CSV 的状态文件相互独立(同题库换格式 = 换状态)
The .cqv and its CSV counterpart keep separate state files (switching format = separate state).cqv)
Security note: stems and short-answer answers are rendered as Markdown (embedded HTML included) — only open banks (CSV or .cqv) from trusted sources| 设置 / Setting | 说明 / Description |
|---|---|
| 来源类型 / Source Type | csv(CSV/CQV 文件)/ image(图片文件夹)/ manifest(含 manifest.json 的复合题库)/ CSV/CQV file, image folder, or composite manifest folder |
| 来源路径 / Source Path | 文件路径或文件夹路径;根部图片/复合题库可用 / / File or folder path; / = vault root |
| 刷新题库 / Refresh Bank | 重新解析当前来源(manifest/CSV/图片的新增、删除或替换),保留答题与 FSRS 状态 / Re-resolve the current source while keeping answers and FSRS state |
| 随机题目顺序 / Random Order | 每次加载时随机排列题目 |
| 随机选项顺序 / Random Options | 每题选项顺序随机 |
| 随机考试题数 / Random Exam Count | 随机考试从当前筛选范围抽取的题数(默认 100,不足时取全部) |
| 答对自动跳转延迟 / Auto-Advance Delay | 答对后等待秒数,0 = 不自动(秒 / seconds) |
| 默认展开筛选栏 / Filter Panel Open | 打开面板时筛选栏默认展开 |
| 默认展开编辑栏 / Edit Panel Open | 打开面板时编辑栏默认展开 |
| 标记筛选默认值 / Default Filter Values | 各标记筛选的默认状态 |
| 左右滑动切题 / Swipe Navigation | 移动端面板内左右滑动切换题目(默认开启) |
| 记忆练习 / Memory Practice | 启用基于记忆曲线(FSRS)的练习 |
| 每日新题数 / Daily New Questions | 记忆练习每天引入的新题数量上限(默认 20,每题库独立配额) |
| 到期提醒 / Due Reminder | 状态栏显示今日待复习题数提醒 |
| 掌握参与评分 / Mastery-aware Rating | 掌握答对=Easy、其余=Good;收藏不参与评分(默认开启) |
| 优化题库 / Optimize Bank | 把 CSV 编译为 .cqv 产物(需面板已打开) |
| 导出修改到 CSV / Export Changes to CSV | 把状态文件中的标签/分类/重复修改写回 CSV(需面板已打开) |
| 重置刷题进度 / Reset Progress | 分项清理:仅刷题记录 / 仅记忆卡片 / 重置题目顺序 / 全部重置 |
Obsidian 设置 → 社区插件 → 浏览 → 搜索 "csv quiz practice" Obsidian Settings → Community plugins → Browse → Search "csv quiz practice"
或手动安装:将 main.js + manifest.json + styles.css 复制到 vault 的 .obsidian/plugins/csv-quiz-practice/,然后重载 Obsidian
Or install manually: copy main.js, manifest.json, and styles.css to your vault's .obsidian/plugins/csv-quiz-practice/ and reload Obsidian