@matinfo/vitepress-plugin-quiz 0.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +122 -0
- package/dist/index.d.ts +2 -0
- package/dist/src/QuizPage.vue.d.ts +17 -0
- package/dist/src/QuizQuestion.vue.d.ts +12 -0
- package/dist/src/__tests__/locales.test.d.ts +1 -0
- package/dist/src/__tests__/mdPlugin.test.d.ts +1 -0
- package/dist/src/__tests__/richText.test.d.ts +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/locales.d.ts +7 -0
- package/dist/src/md-plugin.d.ts +9 -0
- package/dist/src/styleManager.d.ts +1 -0
- package/dist/src/types/quiz.d.ts +37 -0
- package/dist/src/utils.d.ts +12 -0
- package/dist/vite.config.d.ts +2 -0
- package/dist/vitepress-plugin-quiz.js +451 -0
- package/dist/vitepress-plugin-quiz.js.map +1 -0
- package/dist/vitepress-plugin-quiz.umd.cjs +5 -0
- package/dist/vitepress-plugin-quiz.umd.cjs.map +1 -0
- package/package.json +96 -0
package/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# vitepress-plugin-quiz
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/vitepress-plugin-quiz)
|
|
4
|
+
[](https://www.npmjs.com/package/vitepress-plugin-quiz)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://matinfo.github.io/vitepress-plugin-quiz/)
|
|
7
|
+
|
|
8
|
+
A VitePress plugin that adds interactive quizzes to your Markdown pages using a simple `:::quiz` fenced block syntax.
|
|
9
|
+
|
|
10
|
+
**Features:**
|
|
11
|
+
- 📝 Single-choice, multiple-choice, and fill-in-the-blank questions
|
|
12
|
+
- 💾 Session persistence — answers survive page navigation
|
|
13
|
+
- 🌍 i18n: English, French, German, Italian, Spanish (or bring your own)
|
|
14
|
+
- ♿ ARIA roles, keyboard navigation, screen-reader announcements
|
|
15
|
+
- 🎨 VitePress CSS variables — dark mode and custom themes work out of the box
|
|
16
|
+
- 🚀 Zero runtime dependencies beyond Vue
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
### 1. Install
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
# bun
|
|
26
|
+
bun add vitepress-plugin-quiz
|
|
27
|
+
|
|
28
|
+
# npm
|
|
29
|
+
npm install vitepress-plugin-quiz
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Register the markdown plugin
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
// .vitepress/config.ts
|
|
36
|
+
import { defineConfig } from "vitepress"
|
|
37
|
+
import { quizMarkdownPlugin } from "vitepress-plugin-quiz"
|
|
38
|
+
|
|
39
|
+
export default defineConfig({
|
|
40
|
+
markdown: {
|
|
41
|
+
config(md) {
|
|
42
|
+
md.use(quizMarkdownPlugin)
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 3. Register Vue components + auto-inject styles
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
// .vitepress/theme/index.ts
|
|
52
|
+
import DefaultTheme from "vitepress/theme"
|
|
53
|
+
import { enhanceAppWithQuiz } from "vitepress-plugin-quiz"
|
|
54
|
+
import type { Theme } from "vitepress"
|
|
55
|
+
|
|
56
|
+
export default {
|
|
57
|
+
extends: DefaultTheme,
|
|
58
|
+
enhanceApp({ app }) {
|
|
59
|
+
enhanceAppWithQuiz(app) // English by default; pass "fr", "de", "it", or "es"
|
|
60
|
+
},
|
|
61
|
+
} satisfies Theme
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 4. Write quizzes in Markdown
|
|
65
|
+
|
|
66
|
+
```md
|
|
67
|
+
:::quiz
|
|
68
|
+
question: What does CSS stand for?
|
|
69
|
+
answer: Computer Style Sheets
|
|
70
|
+
answer-correct: Cascading Style Sheets
|
|
71
|
+
answer: Creative Style Sheets
|
|
72
|
+
explanation: CSS = **Cascading Style Sheets** — the language that styles web pages.
|
|
73
|
+
shuffle: true
|
|
74
|
+
:::
|
|
75
|
+
|
|
76
|
+
:::quiz
|
|
77
|
+
question: What CSS property controls text color?
|
|
78
|
+
answer-input: color
|
|
79
|
+
explanation: The `color` property sets the foreground text colour.
|
|
80
|
+
:::
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Documentation
|
|
86
|
+
|
|
87
|
+
Full guide, syntax reference, i18n docs, and live examples at:
|
|
88
|
+
**[https://matinfo.github.io/vitepress-plugin-quiz/](https://matinfo.github.io/vitepress-plugin-quiz/)**
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## API
|
|
93
|
+
|
|
94
|
+
### `quizMarkdownPlugin(md)`
|
|
95
|
+
|
|
96
|
+
markdown-it plugin. Use in `.vitepress/config.ts` under `markdown.config`.
|
|
97
|
+
|
|
98
|
+
### `enhanceAppWithQuiz(app, lang?)`
|
|
99
|
+
|
|
100
|
+
Registers `<QuizQuestion>` and `<QuizPage>` on the Vue app, provides the locale, and auto-injects styles. `lang` defaults to `"en"`.
|
|
101
|
+
|
|
102
|
+
### `getLocale(lang?)` / `locales`
|
|
103
|
+
|
|
104
|
+
Access locale strings directly. `getLocale` falls back to English for unknown codes.
|
|
105
|
+
|
|
106
|
+
### Types
|
|
107
|
+
|
|
108
|
+
All TypeScript interfaces are re-exported from the main entry:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import type { QuizData, QuizAnswer, QuizLocale, QuizState } from "vitepress-plugin-quiz"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Contributing
|
|
117
|
+
|
|
118
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
[GPL-3.0](LICENSE)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare function __VLS_template(): {
|
|
2
|
+
attrs: Partial<{}>;
|
|
3
|
+
slots: {
|
|
4
|
+
default?(_: {}): any;
|
|
5
|
+
};
|
|
6
|
+
refs: {};
|
|
7
|
+
rootEl: HTMLDivElement;
|
|
8
|
+
};
|
|
9
|
+
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
|
|
10
|
+
declare const __VLS_component: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
|
|
11
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
12
|
+
export default _default;
|
|
13
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
14
|
+
new (): {
|
|
15
|
+
$slots: S;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
|
|
2
|
+
dataQuiz: {
|
|
3
|
+
type: StringConstructor;
|
|
4
|
+
required: true;
|
|
5
|
+
};
|
|
6
|
+
}>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
|
|
7
|
+
dataQuiz: {
|
|
8
|
+
type: StringConstructor;
|
|
9
|
+
required: true;
|
|
10
|
+
};
|
|
11
|
+
}>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { App } from 'vue';
|
|
2
|
+
import { default as QuizQuestion } from './QuizQuestion.vue';
|
|
3
|
+
import { default as QuizPage } from './QuizPage.vue';
|
|
4
|
+
export { quizMarkdownPlugin } from './md-plugin';
|
|
5
|
+
export { getLocale, locales } from './locales';
|
|
6
|
+
export type { QuizData, QuizAnswer, QuizLocale, QuizState, SavedAnswer } from './types/quiz';
|
|
7
|
+
export { QuizQuestion, QuizPage };
|
|
8
|
+
/**
|
|
9
|
+
* Register quiz components and locale in a VitePress `enhanceApp` hook.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // .vitepress/theme/index.ts
|
|
13
|
+
* import { enhanceAppWithQuiz } from 'vitepress-plugin-quiz'
|
|
14
|
+
* export default {
|
|
15
|
+
* enhanceApp({ app }) {
|
|
16
|
+
* enhanceAppWithQuiz(app) // English (default)
|
|
17
|
+
* enhanceAppWithQuiz(app, 'fr') // French
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
export declare function enhanceAppWithQuiz(app: App, lang?: string): void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { QuizLocale } from './types/quiz';
|
|
2
|
+
export declare const locales: Record<string, QuizLocale>;
|
|
3
|
+
/**
|
|
4
|
+
* Get locale strings for a given language code.
|
|
5
|
+
* Falls back to English if the language is not found.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getLocale(lang?: string): QuizLocale;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { default as MarkdownIt } from 'markdown-it';
|
|
2
|
+
import { QuizData } from './types/quiz';
|
|
3
|
+
/**
|
|
4
|
+
* Register the quiz block rule on a markdown-it instance.
|
|
5
|
+
* Use in VitePress config:
|
|
6
|
+
* markdown: { config(md) { md.use(quizMarkdownPlugin) } }
|
|
7
|
+
*/
|
|
8
|
+
export declare function quizMarkdownPlugin(md: MarkdownIt): void;
|
|
9
|
+
export declare function parseQuizBlock(lines: string[]): QuizData | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ensureStylesInjected(): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface QuizAnswer {
|
|
2
|
+
text: string;
|
|
3
|
+
correct: boolean;
|
|
4
|
+
originalIndex?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface QuizData {
|
|
7
|
+
question: string;
|
|
8
|
+
type: "choice" | "input";
|
|
9
|
+
answers: QuizAnswer[];
|
|
10
|
+
expected: string[];
|
|
11
|
+
explanation: string;
|
|
12
|
+
shuffle: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface QuizLocale {
|
|
15
|
+
answered: string;
|
|
16
|
+
validate: string;
|
|
17
|
+
reset: string;
|
|
18
|
+
correctAnswers: (n: number) => string;
|
|
19
|
+
multipleHint: string;
|
|
20
|
+
explanation: string;
|
|
21
|
+
inputHint: string;
|
|
22
|
+
inputPlaceholder: string;
|
|
23
|
+
expectedAnswer: string;
|
|
24
|
+
}
|
|
25
|
+
export interface QuizState {
|
|
26
|
+
answered: boolean;
|
|
27
|
+
isCorrect: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface SavedChoiceAnswer {
|
|
30
|
+
type: "choice";
|
|
31
|
+
selected: number[];
|
|
32
|
+
}
|
|
33
|
+
export interface SavedInputAnswer {
|
|
34
|
+
type: "input";
|
|
35
|
+
input: string;
|
|
36
|
+
}
|
|
37
|
+
export type SavedAnswer = SavedChoiceAnswer | SavedInputAnswer;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline markdown part — result of {@link parseRichText}.
|
|
3
|
+
*/
|
|
4
|
+
export type RichPart = {
|
|
5
|
+
type: "text" | "bold" | "italic" | "code";
|
|
6
|
+
value: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Parse inline markdown subsets: **bold**, *italic*, `code` → typed parts array.
|
|
10
|
+
* Used for question titles, answer text, and explanations.
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseRichText(text: string): RichPart[];
|