From b15a4163d8354feaafe6529c6a344e2b5f614f82 Mon Sep 17 00:00:00 2001
From: Jakob L. Kreuze
Date: Sun, 26 Oct 2025 16:57:18 -0400
Subject: Add custom card types
---
README.md | 39 +++++++++++++++++++++++++++++++++++++
example-cards.json | 12 ++++++++++++
srs-anywhere.html | 1 +
srs-anywhere.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++-------
4 files changed, 102 insertions(+), 7 deletions(-)
create mode 100644 example-cards.json
diff --git a/README.md b/README.md
index f2c843c..043d1c7 100644
--- a/README.md
+++ b/README.md
@@ -39,3 +39,42 @@ Keys generated and modified by SRS Anywhere are prefixed by the `_` character.
}
]
```
+
+### Custom Cards
+
+Custom card types can be defined in a `srs-anywhere-custom-card-types.js` file.
+To register a new card type, add it as a new entry to the `CARD_TYPES` object, where the key is the the name of the card type.
+A card type should be an object containing at least the following keys: `validate`, `front`, and `back`.
+`validate` takes the card and throws an `Error` if it is malformed.
+`front` returns the desired HTML code for the front of the card.
+`back` returns the desired HTML code for the back of the card.
+Optionally, `showFront` and `showBack` are functions that are evaluted when the front or back of the card are shown, respectively.
+
+For example, to define a card type for a [cloze deletion test](https://en.wikipedia.org/wiki/Cloze_test):
+
+```javascript
+const CLOZE_REGEX = /\[.*?\]/ig;
+CARD_TYPES["clozeAll"] = {
+ "validate": function (card) {
+ if (typeof card.back !== "string") {
+ throw new Error(`malformed card ${card.id}: invalid back (should be string)`)
+ }
+ if (!CLOZE_REGEX.test(card.back)) {
+ throw new Error(`malformed card ${card.id}: contains no cloze;
+please enclose deletion in brackets (e.g., [...])`)
+ }
+ },
+ "front": (card) => card.back.replaceAll(CLOZE_REGEX, '[...]'),
+ "back": (card) => card.back
+};
+```
+
+The `type` key in the cards JSON file associates an entry with the custom card type.
+
+```javascript
+{
+ "id": "cca013c4-450a-41a1-abed-28abdc73413a",
+ "type": "clozeAll",
+ "back": "This is a card containing a [cloze deletion]!"
+}
+```
diff --git a/example-cards.json b/example-cards.json
new file mode 100644
index 0000000..9b856f0
--- /dev/null
+++ b/example-cards.json
@@ -0,0 +1,12 @@
+[
+ {
+ "id": "d8968711-cd50-42e3-9360-f17a35cc944a",
+ "front": "This is the front of a card.",
+ "back": "And this is the back of a card"
+ },
+ {
+ "id": "a8942790-aea7-41d1-afd1-3cc3c3ecb664",
+ "front": "Cards can contain arbitrary HTML.",
+ "back": "Back."
+ }
+]
diff --git a/srs-anywhere.html b/srs-anywhere.html
index 1e4aa4e..06101ce 100644
--- a/srs-anywhere.html
+++ b/srs-anywhere.html
@@ -74,5 +74,6 @@
+