Render Sudoku puzzles directly inside Obsidian notes. Write a board as a fenced sudoku code block — the plugin renders a styled 9×9 grid with thick palace borders, optional row/column labels, and per-cell typography for givens, answers, wrong attempts, and pencil candidates.
mermaid processor. Just use ```sudoku fences.#key: value lines at the top of the block.small (26px cells), medium (38px, default), large (52px), each with proportional fonts and border weights.{123} as a 3×3 mini-grid with each digit in its natural position (1 top-left, 9 bottom-right).npm install
npm run build
Copy main.js, manifest.json, and styles.css into <vault>/.obsidian/plugins/sudoku/, then enable the plugin in Settings → Community plugins.
Insert a code block with the sudoku language tag. The command palette item "Insert sudoku code block template" (the name localizes to the Obsidian app language, e.g. "插入数独代码块模板" in 简体中文) drops a complete example.
| Key | Description | Default | Shown above board |
|---|---|---|---|
#title |
Board title | — | Yes |
#difficulty |
Difficulty label (label localized to Obsidian's language) | — | Yes |
#note |
Free-form note (label localized to Obsidian's language; line breaks preserved) | — | Yes |
#size |
small / medium / large |
medium |
No |
#show-background |
true / false — shade even palaces |
false |
No |
Empty values are ignored. Unknown keys are ignored.
The difficulty and note field labels adapt to the Obsidian app language (Settings → General → Language). The language list mirrors Obsidian's:
| Obsidian language | difficulty label | note label |
|---|---|---|
| English | Difficulty | Note |
| العربية | الصعوبة | ملاحظة |
| Català | Dificultat | Nota |
| Čeština | Obtížnost | Poznámka |
| Dansk | Sværhedsgrad | Note |
| Deutsch | Schwierigkeit | Notiz |
| Ελληνικά | Δυσκολία | Σημείωση |
| Español | Dificultad | Nota |
| Français | Difficulté | Note |
| עברית | קושי | הערה |
| हिन्दी | कठिनाई | टिप |
| Bahasa Indonesia | Kesulitan | Catatan |
| Italiano | Difficoltà | Nota |
| 日本語 | 難易度 | メモ |
| 한국어 | 난이도 | 메모 |
| मराठी | कठीणता | टीप |
| Nederlands | Moeilijkheid | Notitie |
| Norsk | Vanskelighet | Notat |
| Polski | Poziom | Notatka |
| Português | Dificuldade | Nota |
| Português Brasileiro | Dificuldade | Nota |
| Română | Dificultate | Notă |
| Русский | Сложность | Заметка |
| Slovenčina | Náročnosť | Poznámka |
| Српски | Тежина | Напомена |
| Svenska | Svårighet | Notering |
| Türkçe | Zorluk | Not |
| Українська | Складність | Примітка |
| Tiếng Việt | Độ khó | Ghi chú |
| 简体中文 | 难度 | 说明 |
| 繁體中文 | 難度 | 說明 |
Unsupported languages fall back to English.
Each cell is one whitespace-separated token. Prefixes can be combined in any order.
| Token | Meaning |
|---|---|
5 |
Given clue (black) |
*5 |
Correct answer (blue) |
!5 |
Wrong attempt (red) |
$5 |
Highlighted cell (orange background) |
$*5 |
Highlighted correct answer |
. |
Empty cell |
{123} |
Empty cell with candidates 1, 2, 3 (rendered as a 3×3 grid) |
${123} |
Highlighted empty cell with candidates |
* and ! together → the cell is treated as wrong (! wins), regardless of prefix order. *!5 and !*5 both render as a red 5.
Digit and {candidates} together → if the token contains * or !, the digit is ignored and candidates are shown. Otherwise, candidates are ignored and the digit is shown.
| Token | Renders as |
|---|---|
5{123} |
Given 5 (candidates dropped) |
*5{123} |
Candidates 1, 2, 3 (digit dropped) |
!5{123} |
Candidates 1, 2, 3 (digit dropped) |
*!5{123} |
Candidates 1, 2, 3 (digit dropped) |
Candidates — digits inside {} are deduplicated and sorted. {99112} is equivalent to {129}.
Unrecognized tokens are treated as empty cells.
Lines starting with - (e.g. ------+-------+------) are ignored, so you can keep the traditional Sudoku board layout for readability.
```sudoku
#title: Example Puzzle
#difficulty: Easy
#size: medium
#show-background: true
#note: * = answer, ! = wrong, $ = highlight, {} = candidates
5 3 . | . 7 . | . . .
6 . . | *1 9 5 | . . .
. 9 8 | . . . | . 6 .
------+-------+------
8 . . | . 6 . | . . !3
4 . . | 8 . 3 | . . 1
7 . . | . 2 . | . . 6
------+-------+------
. 6 . | . . . | $2 8 .
. . . | 4 1 9 | . . 5
. . . | . 8 . | . 7 9
```
npm run dev # esbuild watch mode
npm run build # type-check + production build
Project layout:
src/main.ts — parser, metadata extraction, and HTML rendererstyles.css — all styling, driven by CSS variables under .sudoku-wrapperesbuild.config.mjs — bundler configtsconfig.json — TypeScript configAll sizing is driven by CSS variables declared on .sudoku-wrapper. To add a new size variant, declare a class like .sudoku-wrapper.size-xlarge and override --cell, --label-size, --num-size, --cand-size, --thick. See the in-repo skill .trae/skills/obsidian-plugin-css-wrapper/SKILL.md for the wrapper-isolation pattern used here.
MIT