Skip to content

Commit

Permalink
feat: playground (#80)
Browse files Browse the repository at this point in the history
  • Loading branch information
ikkz authored Feb 9, 2025
1 parent 974925f commit e5eda3e
Show file tree
Hide file tree
Showing 39 changed files with 3,552 additions and 454 deletions.
4 changes: 3 additions & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
custom: https://afdian.com/a/leoly
custom:
- https://ko-fi.com/M4M212WUCI
- https://afdian.com/a/leoly
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: CI

on: [push, pull_request]
on:
push:
branches: [main]
pull_request:
types: [opened, reopened, synchronize]

jobs:
build:
Expand All @@ -25,6 +29,8 @@ jobs:
version: '0.4.27'
- name: Package Test
run: pnpm run package
- name: Build playground
run: pnpm run pg-build

- name: Upload APKGs
uses: actions/[email protected]
Expand Down
44 changes: 44 additions & 0 deletions .github/workflows/playground.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Playground

on:
push:
branches: [main]

jobs:
build:
if: |
!startsWith(github.event.head_commit.message , 'chore: release')
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write

steps:
- uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js 23
uses: actions/setup-node@v4
with:
node-version: '23.6'
cache: 'pnpm'
- run: pnpm install
- run: pnpm test
- run: pnpm run build

- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: '0.4.27'
- name: Package Test
run: pnpm run package
- name: Build playground
run: pnpm run pg-build
- name: Publish
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: 'anki-template'
directory: 'playground/dist'
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps
- name: Run Playwright tests
run: pnpm exec playwright test
run: pnpm e2e-test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
Expand Down
120 changes: 10 additions & 110 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,123 +1,23 @@
# ikkz Templates

For the directly usable version, please download it from the [release](https://github.com/ikkz/anki-template/releases).

> [!TIP]
> Each template has multiple variants available for download, with the filename format being `{template}.{locale}.{field}.apkg`
>
> Be sure to read the specific instructions and tips for each template below before use
```
template:
- mcq : Multiple choice question (6 options)
- mcq_10: Multiple choice question (10 options)
- tf : True or false
- basic : Basic Q&A
- match : Drag and drop interactive matching
locale:
- zh: 中文
- en: English
- ja: Japanese
field:
- native : The native Anki field
- markdown: With markdown support, but larger size
```
For the directly usable version, please download it from the [here](https://template.ikkz.fun).

For suggestions and feedback, please submit them [here](https://github.com/ikkz/anki-template/issues).

## Templates

| Template | Description | Links |
| -------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| mcq | Multiple choice question (6 options) | [Preview](https://template.ikkz.fun/?template=mcq.en.native) [Docs](https://template.ikkz.fun/docs/mcq) |
| mcq_10 | Multiple choice question (10 options) | [Preview](https://template.ikkz.fun/?template=mcq_10.en.native) [Docs](https://template.ikkz.fun/docs/mcq_10) |
| match | Drag and drop interactive matching | [Preview](https://template.ikkz.fun/?template=match.en.native) [Docs](https://template.ikkz.fun/docs/match) |
| tf | True or false | [Preview](https://template.ikkz.fun/?template=tf.en.native) [Docs](https://template.ikkz.fun/docs/tf) |
| basic | Basic Q&A | [Preview](https://template.ikkz.fun/?template=basic.en.native) [Docs](https://template.ikkz.fun/docs/basic) |

All of the templates have the following common features:

- Markdown support: see [here](/docs/markdown.md) for details
- Markdown support: see [here](https://template.ikkz.fun/docs/markdown) for details
- After selecting text, you can directly click to ask gpt, search or translate the corresponding text, and customization is also supported
- Support larger question text.
- Support dark mode and light mode.
- Countdown: Give you motivation to learn.

### Multiple Choice

- Support hiding options to avoid potential answer hints
- Support single choice and multiple choice.
- Scrambled question options are restored after showing the answer.
- Obvious answer markers.

#### Fields

Note: When all options are empty, the template will behave as a basic Q&A template

| Field name | Description |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| question | This is the stem of the question. It supports various content formats in Anki, including bold, formulas, etc. |
| optionA...F | This is the content of the question options. Options that are not filled in will not be displayed, and various formats are also supported. |
| answer | This is the answer to the question. For multiple-choice questions, please write the uppercase letter of the correct answer, for example, A. For multiple-choice questions, write all the correct answer letters, such as ABC. |
| note | You can fill in detailed explanations, notes, etc., here. |
| noteA...F | You can fill in detailed explanations, notes for every option |

### Match

Drag and drop interactive matching question template.

> [!TIP]
> It is best to disable all swipe gesture controls in Anki's review settings.
#### Fields

Notes for `items`

- Each line starts with a category, followed by two colons separating it from the items under that category
- Each item is separated by two commas

An example:

```
Mammals::Tiger,,Elephant
Birds::Penguin,,Parrot
Reptiles::Cobra,,Crocodile
```

| Field name | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| question | This is the stem of the question. It supports various content formats in Anki, including bold, formulas, etc. |
| items | The category and items |
| note | You can fill in detailed explanations, notes, etc., here. |

### True or False

#### Fields

Notes for `items`

- All sub-questions should meet the format constriant
- Each sub-question must begin with a line "T===" or "F===", indicating whether the sub-question is true or false
- Pay special attention to ensuring "T/F" is followed by three or more equal signs

| Field name | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| question | This is the stem of the question. It supports various content formats in Anki, including bold, formulas, etc. |
| items | The sub-questions |
| note | You can fill in detailed explanations, notes, etc., here. |

### Basic

A Simple Q&A Template

#### Fields

| Field name | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| question | This is the stem of the question. It supports various content formats in Anki, including bold, formulas, etc. |
| answer | This is the answer to the question, and various formats are also supported |
| note | You can fill in detailed explanations, notes, etc., here. |

## Screenshots

<img width="632" alt="image" src="https://github.com/user-attachments/assets/edce65fd-2560-47db-a6e5-ffe7dcd00a02">

<img width="609" alt="图片" src="https://github.com/user-attachments/assets/143df030-a8d7-4fdc-9566-927b70aa4921" />

<img width="552" alt="图片" src="https://github.com/user-attachments/assets/b70ee32f-6ad3-4374-9224-8b6d54d57f9a" />

<img width="552" alt="图片" src="https://github.com/user-attachments/assets/3bfadeee-1876-4e3c-90ee-1c6ad53d71d3" />
8 changes: 7 additions & 1 deletion build/entries.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BuildConfig } from './config';
import type { BuildConfig } from './config.ts';

export interface Note<F extends string> {
config: Partial<BuildConfig>;
Expand All @@ -7,6 +7,7 @@ export interface Note<F extends string> {

interface Entry<F extends readonly string[]> {
fields: F;
desc: string;
notes: Note<F[number]>[];
}

Expand All @@ -20,6 +21,7 @@ const mdQuestion =
"## Markdown Basic Syntax<br><br>I just love **bold text**. Italicized text is the _cat's meow_. At the command prompt, type `nano`.<br><br>My favorite markdown editor is [ByteMD](https://github.com/bytedance/bytemd).<br><br>1. First item<br>2. Second item<br>3. Third item<br><br>&gt; Dorothy followed her through many of the beautiful rooms in her castle.<br><br>```js<br>import gfm from '@bytemd/plugin-gfm'<br>import { Editor, Viewer } from 'bytemd'<br><br>const plugins = [<br>&nbsp; gfm(),<br>&nbsp; // Add more plugins here<br>]<br><br>const editor = new Editor({<br>&nbsp; target: document.body, // DOM to render<br>&nbsp; props: {<br>&nbsp;&nbsp;&nbsp; value: '',<br>&nbsp;&nbsp;&nbsp; plugins,<br>&nbsp; },<br>})<br><br>editor.on('change', (e) =&gt; {<br>&nbsp; editor.$set({ value: e.detail.value })<br>})<br>```<br><br>## GFM Extended Syntax<br><br>Automatic URL Linking: <a href=\"https://github.com/bytedance/bytemd\">https://github.com/bytedance/bytemd</a><br><br>~~The world is flat.~~ We now know that the world is round.<br><br>- [x] Write the press release<br>- [ ] Update the website<br>- [ ] Contact the media<br><br>| Syntax&nbsp;&nbsp;&nbsp; | Description |<br>| --------- | ----------- |<br>| Header&nbsp;&nbsp;&nbsp; | Title&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br>| Paragraph | Text&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br><br>## Math Equation<br><br>Inline math equation: $a+b$<br><br>$$<br>\\displaystyle \\left( \\sum_{k=1}^n a_k b_k \\right)^2 \\leq \\left( \\sum_{k=1}^n a_k^2 \\right) \\left( \\sum_{k=1}^n b_k^2 \\right)<br>$$<br><br>## Mermaid Diagrams<br><br>```mermaid<br><div>mindmap<br>&nbsp; root((mindmap))<br>&nbsp;&nbsp;&nbsp; Origins<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Long history<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ::icon(fa fa-book)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Popularisation<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; British popular psychology author Tony Buzan<br>&nbsp;&nbsp;&nbsp; Research<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; On effectiveness&lt;br/&gt;and features<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; On Automatic creation<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uses<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Creative techniques<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Strategic planning<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Argument mapping<br>&nbsp;&nbsp;&nbsp; Tools<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pen and paper<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Mermaid<br><br></div>```";

const mcq = defineEntry({
desc: 'Multiple choice question (6 options)',
fields: [
'question',
'optionA',
Expand Down Expand Up @@ -74,6 +76,7 @@ const mcq = defineEntry({
});

const mcq_10 = defineEntry({
desc: 'Multiple choice question (10 options)',
fields: [
'question',
'optionA',
Expand Down Expand Up @@ -107,6 +110,7 @@ const entries = {
mcq,
mcq_10,
basic: defineEntry({
desc: 'Basic Q&A',
fields: ['question', 'answer', 'note', 'Tags'],
notes: [
{
Expand All @@ -133,6 +137,7 @@ const entries = {
],
}),
tf: defineEntry({
desc: 'True or false',
fields: ['question', 'items', 'note', 'Tags'],
notes: [
{
Expand Down Expand Up @@ -161,6 +166,7 @@ const entries = {
],
}),
match: defineEntry({
desc: 'Drag and drop interactive matching',
fields: ['question', 'items', 'note', 'Tags'],
notes: [
{
Expand Down
3 changes: 1 addition & 2 deletions build/plugins/generate-template.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { BuildConfig } from '../config.ts';
import { entries, type Note } from '../entries.ts';
import { findMatchNote } from '../utils.ts';
import { extname } from 'node:path';
import * as R from 'remeda';
import type { Plugin } from 'rollup';

Expand All @@ -26,7 +25,7 @@ export default (config: BuildConfig) =>
name: 'generate-template',
generateBundle(_, bundle) {
Object.keys(bundle)
.filter((fileName) => extname(fileName) !== '.html')
.filter((fileName) => fileName.split('.').pop() !== 'html')
.forEach((fileName) => {
delete bundle[fileName];
});
Expand Down
9 changes: 6 additions & 3 deletions build/rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { BuildConfig } from './config.ts';
import { entries } from './entries.ts';
import devServer from './plugins/dev-server/index.ts';
import generateTemplate from './plugins/generate-template.ts';
import { readJson, ensureValue, findMatchNote } from './utils.ts';
import { ensureValue, findMatchNote } from './utils.ts';
import alias from '@rollup/plugin-alias';
import commonjs from '@rollup/plugin-commonjs';
import html from '@rollup/plugin-html';
Expand All @@ -25,10 +25,13 @@ import type {
import nodePolyfills from 'rollup-plugin-polyfill-node';
import postcss from 'rollup-plugin-postcss';
import { swc, minify } from 'rollup-plugin-swc3';
// import { visualizer } from 'rollup-plugin-visualizer';
import tailwindcss from 'tailwindcss';

const packageJson = await readJson('./package.json');
const packageJson = JSON.parse(
await fs.readFile(path.resolve(import.meta.dirname, '../package.json'), {
encoding: 'utf8',
}),
);

export async function rollupOptions(
config: BuildConfig,
Expand Down
18 changes: 8 additions & 10 deletions build/utils.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import type { BuildConfig } from './config';
import type { BuildConfig } from './config.ts';
import { entries } from './entries.ts';
import fs from 'node:fs/promises';
import { template } from 'lodash-es';

export function ensureValue<T>(value: T): T extends () => infer R ? R : T {
return typeof value === 'function' ? value() : value;
}

export async function readJson(path: string) {
return JSON.parse(
await fs.readFile(path, {
encoding: 'utf-8',
}),
);
}

export function configMatch(
pattern: Partial<BuildConfig>,
config: BuildConfig,
Expand All @@ -29,3 +21,9 @@ export function findMatchNote(config: BuildConfig) {
configMatch(noteConfig, config),
);
}

export function renderTemplate(html: string, data: object) {
return template(html, {
interpolate: /{{([\s\S]+?)}}/g,
})(data);
}
11 changes: 11 additions & 0 deletions docs/basic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Basic

A Simple Q&A Template

## Fields

| Field name | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| question | This is the stem of the question. It supports various content formats in Anki, including bold, formulas, etc. |
| answer | This is the answer to the question, and various formats are also supported |
| note | You can fill in detailed explanations, notes, etc., here. |
27 changes: 27 additions & 0 deletions docs/match.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Match

Drag and drop interactive matching question template.

> [!TIP]
> It is best to disable all swipe gesture controls in Anki's review settings.
## Fields

Notes for `items`

- Each line starts with a category, followed by two colons separating it from the items under that category
- Each item is separated by two commas

An example:

```
Mammals::Tiger,,Elephant
Birds::Penguin,,Parrot
Reptiles::Cobra,,Crocodile
```

| Field name | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| question | This is the stem of the question. It supports various content formats in Anki, including bold, formulas, etc. |
| items | The category and items |
| note | You can fill in detailed explanations, notes, etc., here. |
Loading

0 comments on commit e5eda3e

Please sign in to comment.