@learnmd/core 0.0.1-beta.0
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 +21 -0
- package/README.md +30 -0
- package/dist/components/LearnMDProvider.d.ts +33 -0
- package/dist/components/LearnMDProvider.d.ts.map +1 -0
- package/dist/components/LearnMDProvider.js +16 -0
- package/dist/components/LearnMDProvider.js.map +1 -0
- package/dist/gamification/index.d.ts +77 -0
- package/dist/gamification/index.d.ts.map +1 -0
- package/dist/gamification/index.js +402 -0
- package/dist/gamification/index.js.map +1 -0
- package/dist/i18n/index.d.ts +119 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +261 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/index.d.ts +57 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +182 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/plugins/index.d.ts +150 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +291 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/pdf/index.d.ts +8 -0
- package/dist/plugins/pdf/index.d.ts.map +1 -0
- package/dist/plugins/pdf/index.js +53 -0
- package/dist/plugins/pdf/index.js.map +1 -0
- package/dist/router/index.d.ts +111 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +268 -0
- package/dist/router/index.js.map +1 -0
- package/dist/storage/index.d.ts +110 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +390 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/types/index.d.ts +283 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import matter from 'gray-matter';
|
|
2
|
+
import { marked } from 'marked';
|
|
3
|
+
/**
|
|
4
|
+
* Parse Markdown content with frontmatter
|
|
5
|
+
*/
|
|
6
|
+
export function parseMarkdown(content) {
|
|
7
|
+
const result = matter(content);
|
|
8
|
+
return {
|
|
9
|
+
data: result.data,
|
|
10
|
+
content: result.content,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Extract translated string based on current language
|
|
15
|
+
*/
|
|
16
|
+
export function getTranslatedString(value, lang) {
|
|
17
|
+
if (!value)
|
|
18
|
+
return '';
|
|
19
|
+
if (typeof value === 'string')
|
|
20
|
+
return value;
|
|
21
|
+
return value[lang] || value[Object.keys(value)[0]] || '';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse markdown to HTML
|
|
25
|
+
*/
|
|
26
|
+
export function markdownToHtml(markdown) {
|
|
27
|
+
return marked(markdown);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Extract sections (headings) from markdown content
|
|
31
|
+
*/
|
|
32
|
+
export function extractSections(markdown) {
|
|
33
|
+
const sections = [];
|
|
34
|
+
const headingRegex = /^(#{1,6})\s+([^\s\n\r][^\n\r]*?)\s*$/gm;
|
|
35
|
+
let match;
|
|
36
|
+
while ((match = headingRegex.exec(markdown)) !== null) {
|
|
37
|
+
const level = match[1].length;
|
|
38
|
+
const title = match[2].trim();
|
|
39
|
+
const id = title
|
|
40
|
+
.toLowerCase()
|
|
41
|
+
.replace(/[^\w\s-]/g, '')
|
|
42
|
+
.replace(/\s+/g, '-');
|
|
43
|
+
sections.push({
|
|
44
|
+
id,
|
|
45
|
+
title,
|
|
46
|
+
level,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return sections;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Extract quiz from markdown content using custom syntax
|
|
53
|
+
*/
|
|
54
|
+
export function extractQuiz(markdown, slug) {
|
|
55
|
+
const quizRegex = /<Quiz\s+question=["']([^"']*)["']\s+options=\{([^{}]*)\}\s+correct=\{([0-9]+)\}/g;
|
|
56
|
+
const questions = [];
|
|
57
|
+
let match;
|
|
58
|
+
while ((match = quizRegex.exec(markdown)) !== null) {
|
|
59
|
+
const question = match[1];
|
|
60
|
+
const optionsStr = match[2];
|
|
61
|
+
const correctIndex = parseInt(match[3], 10);
|
|
62
|
+
// Parse options array
|
|
63
|
+
const options = optionsStr
|
|
64
|
+
.split(',')
|
|
65
|
+
.map((opt) => opt.trim().replace(/["']/g, ''))
|
|
66
|
+
.map((label, index) => ({
|
|
67
|
+
id: `opt-${index}`,
|
|
68
|
+
label,
|
|
69
|
+
isCorrect: index === correctIndex,
|
|
70
|
+
}));
|
|
71
|
+
questions.push({
|
|
72
|
+
id: `question-${questions.length}`,
|
|
73
|
+
type: 'multiple-choice',
|
|
74
|
+
question,
|
|
75
|
+
options,
|
|
76
|
+
correctAnswer: `opt-${correctIndex}`,
|
|
77
|
+
points: 10,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (questions.length === 0) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
id: `quiz-${slug}`,
|
|
85
|
+
questions,
|
|
86
|
+
passingScore: 70,
|
|
87
|
+
allowRetry: true,
|
|
88
|
+
showCorrectAnswers: true,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Parse a complete lesson from markdown content
|
|
93
|
+
*/
|
|
94
|
+
export function parseLesson(slug, content, lang = 'en') {
|
|
95
|
+
const { data: frontmatter, content: markdownContent } = parseMarkdown(content);
|
|
96
|
+
const html = markdownToHtml(markdownContent);
|
|
97
|
+
const sections = extractSections(markdownContent);
|
|
98
|
+
const quiz = extractQuiz(markdownContent, slug);
|
|
99
|
+
// Handle i18n for title
|
|
100
|
+
const title = getTranslatedString(frontmatter.title, lang);
|
|
101
|
+
return {
|
|
102
|
+
slug,
|
|
103
|
+
frontmatter: {
|
|
104
|
+
...frontmatter,
|
|
105
|
+
title,
|
|
106
|
+
},
|
|
107
|
+
content: markdownContent,
|
|
108
|
+
html,
|
|
109
|
+
sections,
|
|
110
|
+
quiz,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export async function parseCourse(lessons, options) {
|
|
114
|
+
const { defaultLanguage = 'en' } = options;
|
|
115
|
+
const parsedLessons = lessons.map((lesson) => parseLesson(lesson.slug, lesson.content, defaultLanguage));
|
|
116
|
+
return {
|
|
117
|
+
lessons: parsedLessons,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get all code blocks from markdown content
|
|
122
|
+
*/
|
|
123
|
+
export function extractCodeBlocks(markdown) {
|
|
124
|
+
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
125
|
+
const blocks = [];
|
|
126
|
+
let match;
|
|
127
|
+
while ((match = codeBlockRegex.exec(markdown)) !== null) {
|
|
128
|
+
blocks.push({
|
|
129
|
+
language: match[1] || 'text',
|
|
130
|
+
code: match[2].trim(),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return blocks;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Extract embedded media from markdown content
|
|
137
|
+
*/
|
|
138
|
+
export function extractEmbeddedMedia(markdown) {
|
|
139
|
+
const media = [];
|
|
140
|
+
// Extract video embeds
|
|
141
|
+
const videoRegex = /<VideoEmbed\s+[^>]*?url=["']([^"']+)["'][^>]*>/g;
|
|
142
|
+
let match;
|
|
143
|
+
const isDomain = (urlStr, domains) => {
|
|
144
|
+
try {
|
|
145
|
+
const url = new URL(urlStr);
|
|
146
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:')
|
|
147
|
+
return false;
|
|
148
|
+
const hostname = url.hostname.toLowerCase();
|
|
149
|
+
return domains.some((d) => {
|
|
150
|
+
const domain = d.toLowerCase();
|
|
151
|
+
return hostname === domain || hostname.endsWith('.' + domain);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
while ((match = videoRegex.exec(markdown)) !== null) {
|
|
159
|
+
const url = match[1];
|
|
160
|
+
let provider;
|
|
161
|
+
if (isDomain(url, ['youtube.com', 'youtu.be'])) {
|
|
162
|
+
provider = 'youtube';
|
|
163
|
+
}
|
|
164
|
+
else if (isDomain(url, ['vimeo.com'])) {
|
|
165
|
+
provider = 'vimeo';
|
|
166
|
+
}
|
|
167
|
+
else if (isDomain(url, ['onedrive.live.com'])) {
|
|
168
|
+
provider = 'onedrive';
|
|
169
|
+
}
|
|
170
|
+
else if (isDomain(url, ['drive.google.com'])) {
|
|
171
|
+
provider = 'googledrive';
|
|
172
|
+
}
|
|
173
|
+
media.push({ type: 'video', url, provider });
|
|
174
|
+
}
|
|
175
|
+
// Extract images
|
|
176
|
+
const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
177
|
+
while ((match = imageRegex.exec(markdown)) !== null) {
|
|
178
|
+
media.push({ type: 'image', url: match[2] });
|
|
179
|
+
}
|
|
180
|
+
return media;
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { Plugin, PluginContext, PluginConfig, Course, StorageAdapter, I18nAdapter } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Plugin registry
|
|
4
|
+
*/
|
|
5
|
+
export declare class PluginRegistry {
|
|
6
|
+
private readonly plugins;
|
|
7
|
+
private readonly components;
|
|
8
|
+
private readonly hooks;
|
|
9
|
+
/**
|
|
10
|
+
* Register a plugin
|
|
11
|
+
*/
|
|
12
|
+
register(plugin: Plugin, context: PluginContext): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Unregister a plugin
|
|
15
|
+
*/
|
|
16
|
+
unregister(pluginName: string, context: PluginContext): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Get a registered plugin
|
|
19
|
+
*/
|
|
20
|
+
getPlugin(name: string): Plugin | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Get all registered plugins
|
|
23
|
+
*/
|
|
24
|
+
getAllPlugins(): Plugin[];
|
|
25
|
+
/**
|
|
26
|
+
* Register a component from a plugin
|
|
27
|
+
*/
|
|
28
|
+
registerComponent(name: string, component: unknown): void;
|
|
29
|
+
/**
|
|
30
|
+
* Get a registered component
|
|
31
|
+
*/
|
|
32
|
+
getComponent(name: string): unknown;
|
|
33
|
+
/**
|
|
34
|
+
* Get all registered components
|
|
35
|
+
*/
|
|
36
|
+
getAllComponents(): Map<string, unknown>;
|
|
37
|
+
/**
|
|
38
|
+
* Register a hook
|
|
39
|
+
*/
|
|
40
|
+
registerHook(hook: string, fn: (...args: unknown[]) => unknown): void;
|
|
41
|
+
/**
|
|
42
|
+
* Execute all hooks for a given event
|
|
43
|
+
*/
|
|
44
|
+
executeHook<T>(hook: string, ...args: unknown[]): Promise<T[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Check if a hook exists
|
|
47
|
+
*/
|
|
48
|
+
hasHook(hook: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Clear all plugins and hooks
|
|
51
|
+
*/
|
|
52
|
+
clear(): void;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create plugin context
|
|
56
|
+
*/
|
|
57
|
+
export declare function createPluginContext(course: Course, storage: StorageAdapter, i18n: I18nAdapter, registry: PluginRegistry, config?: PluginConfig): PluginContext;
|
|
58
|
+
/**
|
|
59
|
+
* Base plugin class for extending
|
|
60
|
+
*/
|
|
61
|
+
export declare abstract class BasePlugin implements Plugin {
|
|
62
|
+
name: string;
|
|
63
|
+
version: string;
|
|
64
|
+
config?: PluginConfig;
|
|
65
|
+
constructor(name: string, version: string, config?: PluginConfig);
|
|
66
|
+
abstract onLoad(ctx: PluginContext): void | Promise<void>;
|
|
67
|
+
onUnload?(ctx: PluginContext): void | Promise<void>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Analytics plugin interface
|
|
71
|
+
*/
|
|
72
|
+
export interface AnalyticsPlugin extends Plugin {
|
|
73
|
+
trackEvent(event: string, properties?: Record<string, unknown>): void;
|
|
74
|
+
trackPageView(page: string): void;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Auth plugin interface
|
|
78
|
+
*/
|
|
79
|
+
export interface AuthPlugin extends Plugin {
|
|
80
|
+
isAuthenticated(): boolean;
|
|
81
|
+
getUser(): unknown | null;
|
|
82
|
+
login(): Promise<void>;
|
|
83
|
+
logout(): Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Available hooks for plugins
|
|
87
|
+
*/
|
|
88
|
+
export declare const HOOKS: {
|
|
89
|
+
/**
|
|
90
|
+
* Called before a lesson is rendered
|
|
91
|
+
*/
|
|
92
|
+
BEFORE_LESSON_RENDER: string;
|
|
93
|
+
/**
|
|
94
|
+
* Called after a lesson is rendered
|
|
95
|
+
*/
|
|
96
|
+
AFTER_LESSON_RENDER: string;
|
|
97
|
+
/**
|
|
98
|
+
* Called before a quiz is submitted
|
|
99
|
+
*/
|
|
100
|
+
BEFORE_QUIZ_SUBMIT: string;
|
|
101
|
+
/**
|
|
102
|
+
* Called after a quiz is submitted
|
|
103
|
+
*/
|
|
104
|
+
AFTER_QUIZ_SUBMIT: string;
|
|
105
|
+
/**
|
|
106
|
+
* Called when a lesson is completed
|
|
107
|
+
*/
|
|
108
|
+
LESSON_COMPLETE: string;
|
|
109
|
+
/**
|
|
110
|
+
* Called when course progress is updated
|
|
111
|
+
*/
|
|
112
|
+
PROGRESS_UPDATE: string;
|
|
113
|
+
/**
|
|
114
|
+
* Called when language is changed
|
|
115
|
+
*/
|
|
116
|
+
LANGUAGE_CHANGE: string;
|
|
117
|
+
/**
|
|
118
|
+
* Called before build starts
|
|
119
|
+
*/
|
|
120
|
+
BEFORE_BUILD: string;
|
|
121
|
+
/**
|
|
122
|
+
* Called after build completes
|
|
123
|
+
*/
|
|
124
|
+
AFTER_BUILD: string;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Example: Analytics plugin implementation
|
|
128
|
+
*/
|
|
129
|
+
export declare class AnalyticsPluginImpl extends BasePlugin implements AnalyticsPlugin {
|
|
130
|
+
constructor(config?: PluginConfig);
|
|
131
|
+
onLoad(ctx: PluginContext): void;
|
|
132
|
+
trackEvent(event: string, properties?: Record<string, unknown>): void;
|
|
133
|
+
trackPageView(page: string): void;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Example: Search plugin implementation
|
|
137
|
+
*/
|
|
138
|
+
export declare class SearchPluginImpl extends BasePlugin {
|
|
139
|
+
constructor(config?: PluginConfig);
|
|
140
|
+
onLoad(ctx: PluginContext): void;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Load plugins from configuration
|
|
144
|
+
*/
|
|
145
|
+
export declare function loadPlugins(plugins: Array<Plugin | (() => Plugin)>, context: PluginContext): Promise<PluginRegistry>;
|
|
146
|
+
/**
|
|
147
|
+
* Create default plugin context with common utilities
|
|
148
|
+
*/
|
|
149
|
+
export declare function createDefaultPluginContext(course: Course, storage: StorageAdapter, i18n: I18nAdapter): PluginContext;
|
|
150
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin registry
|
|
3
|
+
*/
|
|
4
|
+
export class PluginRegistry {
|
|
5
|
+
constructor() {
|
|
6
|
+
Object.defineProperty(this, "plugins", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: new Map()
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(this, "components", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: new Map()
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(this, "hooks", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true,
|
|
22
|
+
value: new Map()
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Register a plugin
|
|
27
|
+
*/
|
|
28
|
+
async register(plugin, context) {
|
|
29
|
+
if (this.plugins.has(plugin.name)) {
|
|
30
|
+
console.warn(`Plugin "${plugin.name}" is already registered`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
await plugin.onLoad(context);
|
|
35
|
+
this.plugins.set(plugin.name, plugin);
|
|
36
|
+
console.log(`Plugin "${plugin.name}" loaded successfully`);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error(`Failed to load plugin "${plugin.name}":`, error);
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Unregister a plugin
|
|
45
|
+
*/
|
|
46
|
+
async unregister(pluginName, context) {
|
|
47
|
+
const plugin = this.plugins.get(pluginName);
|
|
48
|
+
if (!plugin) {
|
|
49
|
+
console.warn(`Plugin "${pluginName}" is not registered`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
if (plugin.onUnload) {
|
|
54
|
+
await plugin.onUnload(context);
|
|
55
|
+
}
|
|
56
|
+
this.plugins.delete(pluginName);
|
|
57
|
+
console.log(`Plugin "${pluginName}" unloaded successfully`);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error(`Failed to unload plugin "${pluginName}":`, error);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get a registered plugin
|
|
66
|
+
*/
|
|
67
|
+
getPlugin(name) {
|
|
68
|
+
return this.plugins.get(name);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get all registered plugins
|
|
72
|
+
*/
|
|
73
|
+
getAllPlugins() {
|
|
74
|
+
return Array.from(this.plugins.values());
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Register a component from a plugin
|
|
78
|
+
*/
|
|
79
|
+
registerComponent(name, component) {
|
|
80
|
+
this.components.set(name, component);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get a registered component
|
|
84
|
+
*/
|
|
85
|
+
getComponent(name) {
|
|
86
|
+
return this.components.get(name);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get all registered components
|
|
90
|
+
*/
|
|
91
|
+
getAllComponents() {
|
|
92
|
+
return this.components;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Register a hook
|
|
96
|
+
*/
|
|
97
|
+
registerHook(hook, fn) {
|
|
98
|
+
if (!this.hooks.has(hook)) {
|
|
99
|
+
this.hooks.set(hook, []);
|
|
100
|
+
}
|
|
101
|
+
this.hooks.get(hook).push(fn);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Execute all hooks for a given event
|
|
105
|
+
*/
|
|
106
|
+
async executeHook(hook, ...args) {
|
|
107
|
+
const hookFunctions = this.hooks.get(hook) || [];
|
|
108
|
+
const results = [];
|
|
109
|
+
for (const fn of hookFunctions) {
|
|
110
|
+
try {
|
|
111
|
+
const result = await fn(...args);
|
|
112
|
+
if (result !== undefined) {
|
|
113
|
+
results.push(result);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error(`Hook "${hook}" failed:`, error);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return results;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if a hook exists
|
|
124
|
+
*/
|
|
125
|
+
hasHook(hook) {
|
|
126
|
+
return this.hooks.has(hook) && this.hooks.get(hook).length > 0;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Clear all plugins and hooks
|
|
130
|
+
*/
|
|
131
|
+
clear() {
|
|
132
|
+
this.plugins.clear();
|
|
133
|
+
this.components.clear();
|
|
134
|
+
this.hooks.clear();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Create plugin context
|
|
139
|
+
*/
|
|
140
|
+
export function createPluginContext(course, storage, i18n, registry, config = {}) {
|
|
141
|
+
return {
|
|
142
|
+
course,
|
|
143
|
+
storage,
|
|
144
|
+
i18n,
|
|
145
|
+
registerComponent: (name, component) => registry.registerComponent(name, component),
|
|
146
|
+
registerHook: (hook, fn) => registry.registerHook(hook, fn),
|
|
147
|
+
config,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Base plugin class for extending
|
|
152
|
+
*/
|
|
153
|
+
export class BasePlugin {
|
|
154
|
+
constructor(name, version, config) {
|
|
155
|
+
Object.defineProperty(this, "name", {
|
|
156
|
+
enumerable: true,
|
|
157
|
+
configurable: true,
|
|
158
|
+
writable: true,
|
|
159
|
+
value: void 0
|
|
160
|
+
});
|
|
161
|
+
Object.defineProperty(this, "version", {
|
|
162
|
+
enumerable: true,
|
|
163
|
+
configurable: true,
|
|
164
|
+
writable: true,
|
|
165
|
+
value: void 0
|
|
166
|
+
});
|
|
167
|
+
Object.defineProperty(this, "config", {
|
|
168
|
+
enumerable: true,
|
|
169
|
+
configurable: true,
|
|
170
|
+
writable: true,
|
|
171
|
+
value: void 0
|
|
172
|
+
});
|
|
173
|
+
this.name = name;
|
|
174
|
+
this.version = version;
|
|
175
|
+
this.config = config;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Available hooks for plugins
|
|
180
|
+
*/
|
|
181
|
+
export const HOOKS = {
|
|
182
|
+
/**
|
|
183
|
+
* Called before a lesson is rendered
|
|
184
|
+
*/
|
|
185
|
+
BEFORE_LESSON_RENDER: 'before:lesson:render',
|
|
186
|
+
/**
|
|
187
|
+
* Called after a lesson is rendered
|
|
188
|
+
*/
|
|
189
|
+
AFTER_LESSON_RENDER: 'after:lesson:render',
|
|
190
|
+
/**
|
|
191
|
+
* Called before a quiz is submitted
|
|
192
|
+
*/
|
|
193
|
+
BEFORE_QUIZ_SUBMIT: 'before:quiz:submit',
|
|
194
|
+
/**
|
|
195
|
+
* Called after a quiz is submitted
|
|
196
|
+
*/
|
|
197
|
+
AFTER_QUIZ_SUBMIT: 'after:quiz:submit',
|
|
198
|
+
/**
|
|
199
|
+
* Called when a lesson is completed
|
|
200
|
+
*/
|
|
201
|
+
LESSON_COMPLETE: 'lesson:complete',
|
|
202
|
+
/**
|
|
203
|
+
* Called when course progress is updated
|
|
204
|
+
*/
|
|
205
|
+
PROGRESS_UPDATE: 'progress:update',
|
|
206
|
+
/**
|
|
207
|
+
* Called when language is changed
|
|
208
|
+
*/
|
|
209
|
+
LANGUAGE_CHANGE: 'language:change',
|
|
210
|
+
/**
|
|
211
|
+
* Called before build starts
|
|
212
|
+
*/
|
|
213
|
+
BEFORE_BUILD: 'before:build',
|
|
214
|
+
/**
|
|
215
|
+
* Called after build completes
|
|
216
|
+
*/
|
|
217
|
+
AFTER_BUILD: 'after:build',
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Example: Analytics plugin implementation
|
|
221
|
+
*/
|
|
222
|
+
export class AnalyticsPluginImpl extends BasePlugin {
|
|
223
|
+
constructor(config) {
|
|
224
|
+
super('analytics', '1.0.0', config);
|
|
225
|
+
}
|
|
226
|
+
onLoad(ctx) {
|
|
227
|
+
ctx.registerHook(HOOKS.LESSON_COMPLETE, async (data) => {
|
|
228
|
+
this.trackEvent('lesson_completed', data);
|
|
229
|
+
});
|
|
230
|
+
ctx.registerHook(HOOKS.AFTER_QUIZ_SUBMIT, async (data) => {
|
|
231
|
+
this.trackEvent('quiz_submitted', data);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
trackEvent(event, properties) {
|
|
235
|
+
const analyticsConfig = this.config;
|
|
236
|
+
// Google Analytics example
|
|
237
|
+
if (typeof window !== 'undefined' && analyticsConfig?.trackingId) {
|
|
238
|
+
const win = window;
|
|
239
|
+
win[`ga-${analyticsConfig.trackingId}`] = win[`ga-${analyticsConfig.trackingId}`] || [];
|
|
240
|
+
win[`ga-${analyticsConfig.trackingId}`].push(['event', event, properties]);
|
|
241
|
+
}
|
|
242
|
+
console.log(`[Analytics] ${event}:`, properties);
|
|
243
|
+
}
|
|
244
|
+
trackPageView(page) {
|
|
245
|
+
this.trackEvent('page_view', { page });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Example: Search plugin implementation
|
|
250
|
+
*/
|
|
251
|
+
export class SearchPluginImpl extends BasePlugin {
|
|
252
|
+
constructor(config) {
|
|
253
|
+
super('search', '1.0.0', config);
|
|
254
|
+
}
|
|
255
|
+
onLoad(ctx) {
|
|
256
|
+
// Register search component
|
|
257
|
+
ctx.registerComponent('SearchBar', SearchBarComponent);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Placeholder search bar component
|
|
262
|
+
*/
|
|
263
|
+
function SearchBarComponent() {
|
|
264
|
+
return { type: 'component', name: 'SearchBar' };
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Load plugins from configuration
|
|
268
|
+
*/
|
|
269
|
+
export async function loadPlugins(plugins, context) {
|
|
270
|
+
const registry = new PluginRegistry();
|
|
271
|
+
for (const plugin of plugins) {
|
|
272
|
+
const p = typeof plugin === 'function' ? plugin() : plugin;
|
|
273
|
+
await registry.register(p, context);
|
|
274
|
+
}
|
|
275
|
+
return registry;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Create default plugin context with common utilities
|
|
279
|
+
*/
|
|
280
|
+
export function createDefaultPluginContext(course, storage, i18n) {
|
|
281
|
+
const registry = new PluginRegistry();
|
|
282
|
+
return {
|
|
283
|
+
course,
|
|
284
|
+
storage,
|
|
285
|
+
i18n,
|
|
286
|
+
registerComponent: (name, component) => registry.registerComponent(name, component),
|
|
287
|
+
registerHook: (hook, fn) => registry.registerHook(hook, fn),
|
|
288
|
+
config: {},
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { UserProfile } from '../../types';
|
|
2
|
+
export interface CertificateOptions {
|
|
3
|
+
courseTitle: string;
|
|
4
|
+
completionDate?: Date;
|
|
5
|
+
signature?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function generateCertificate(profile: UserProfile, options: CertificateOptions): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/pdf/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6D1G"}
|