Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: playground #80

Merged
merged 1 commit into from
Feb 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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