@rimori/client 1.3.1 → 1.4.3
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/.prettierignore +35 -0
- package/README.md +77 -71
- package/dist/cli/scripts/init/dev-registration.d.ts +1 -1
- package/dist/cli/scripts/init/dev-registration.js +4 -4
- package/dist/cli/scripts/init/main.js +1 -1
- package/dist/cli/scripts/init/package-setup.d.ts +1 -1
- package/dist/cli/scripts/init/package-setup.js +3 -3
- package/dist/cli/scripts/init/router-transformer.js +19 -12
- package/dist/cli/scripts/init/vite-config.d.ts +2 -2
- package/dist/cli/scripts/init/vite-config.js +2 -2
- package/dist/cli/scripts/release/release-config-upload.js +9 -9
- package/dist/cli/scripts/release/release-db-update.d.ts +1 -1
- package/dist/cli/scripts/release/release-db-update.js +9 -9
- package/dist/cli/scripts/release/release-file-upload.js +2 -2
- package/dist/cli/scripts/release/release.js +2 -2
- package/dist/cli/types/DatabaseTypes.d.ts +2 -2
- package/dist/components/CRUDModal.d.ts +1 -1
- package/dist/components/CRUDModal.js +3 -3
- package/dist/components/MarkdownEditor.js +16 -16
- package/dist/components/Spinner.js +2 -2
- package/dist/components/ai/Assistant.js +7 -8
- package/dist/components/ai/Avatar.d.ts +2 -2
- package/dist/components/ai/Avatar.js +14 -7
- package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +5 -6
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +1 -1
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +4 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +1 -1
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +2 -3
- package/dist/components/audio/Playbutton.js +10 -7
- package/dist/components/components/ContextMenu.d.ts +1 -1
- package/dist/components/components/ContextMenu.js +19 -16
- package/dist/components.d.ts +10 -10
- package/dist/components.js +10 -10
- package/dist/core/controller/AIController.d.ts +2 -2
- package/dist/core/controller/AIController.js +20 -18
- package/dist/core/controller/ExerciseController.d.ts +52 -0
- package/dist/core/controller/ExerciseController.js +73 -0
- package/dist/core/controller/ObjectController.js +5 -5
- package/dist/core/controller/SettingsController.d.ts +22 -7
- package/dist/core/controller/SettingsController.js +73 -8
- package/dist/core/controller/SharedContentController.d.ts +3 -3
- package/dist/core/controller/SharedContentController.js +38 -20
- package/dist/core/controller/VoiceController.js +6 -4
- package/dist/core/core.d.ts +15 -14
- package/dist/core/core.js +7 -7
- package/dist/fromRimori/EventBus.js +23 -23
- package/dist/fromRimori/PluginTypes.d.ts +4 -4
- package/dist/hooks/UseChatHook.d.ts +3 -3
- package/dist/hooks/UseChatHook.js +9 -3
- package/dist/index.d.ts +10 -10
- package/dist/index.js +9 -9
- package/dist/plugin/AccomplishmentHandler.d.ts +5 -5
- package/dist/plugin/AccomplishmentHandler.js +31 -27
- package/dist/plugin/AudioController.d.ts +1 -1
- package/dist/plugin/AudioController.js +6 -6
- package/dist/plugin/Logger.d.ts +5 -0
- package/dist/plugin/Logger.js +65 -13
- package/dist/plugin/PluginController.d.ts +7 -1
- package/dist/plugin/PluginController.js +32 -27
- package/dist/plugin/RimoriClient.d.ts +39 -14
- package/dist/plugin/RimoriClient.js +60 -31
- package/dist/plugin/StandaloneClient.d.ts +1 -1
- package/dist/plugin/StandaloneClient.js +35 -16
- package/dist/plugin/ThemeSetter.js +4 -4
- package/dist/providers/PluginProvider.js +44 -14
- package/dist/utils/Language.js +57 -57
- package/dist/utils/PluginUtils.js +3 -3
- package/dist/utils/difficultyConverter.d.ts +1 -1
- package/dist/utils/difficultyConverter.js +1 -1
- package/dist/utils/endpoint.js +2 -2
- package/dist/worker/WorkerSetup.d.ts +1 -1
- package/dist/worker/WorkerSetup.js +6 -6
- package/eslint.config.js +53 -0
- package/example/docs/devdocs.md +50 -40
- package/example/docs/overview.md +1 -1
- package/example/docs/userdocs.md +4 -1
- package/example/rimori.config.ts +51 -49
- package/example/worker/vite.config.ts +3 -3
- package/example/worker/worker.ts +2 -2
- package/package.json +17 -4
- package/prettier.config.js +8 -0
- package/src/cli/scripts/init/dev-registration.ts +5 -8
- package/src/cli/scripts/init/env-setup.ts +1 -1
- package/src/cli/scripts/init/file-operations.ts +1 -1
- package/src/cli/scripts/init/html-cleaner.ts +2 -5
- package/src/cli/scripts/init/main.ts +16 -13
- package/src/cli/scripts/init/package-setup.ts +11 -15
- package/src/cli/scripts/init/router-transformer.ts +40 -37
- package/src/cli/scripts/init/tailwind-config.ts +17 -26
- package/src/cli/scripts/init/vite-config.ts +3 -3
- package/src/cli/scripts/release/release-config-upload.ts +11 -11
- package/src/cli/scripts/release/release-db-update.ts +12 -12
- package/src/cli/scripts/release/release-file-upload.ts +3 -3
- package/src/cli/scripts/release/release.ts +4 -4
- package/src/cli/types/DatabaseTypes.ts +7 -8
- package/src/components/CRUDModal.tsx +64 -48
- package/src/components/MarkdownEditor.tsx +58 -27
- package/src/components/Spinner.tsx +24 -17
- package/src/components/ai/Assistant.tsx +70 -70
- package/src/components/ai/Avatar.tsx +20 -16
- package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +63 -54
- package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +14 -5
- package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +75 -74
- package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +177 -178
- package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +109 -94
- package/src/components/ai/utils.ts +4 -4
- package/src/components/audio/Playbutton.tsx +101 -93
- package/src/components/components/ContextMenu.tsx +47 -35
- package/src/components.ts +10 -10
- package/src/core/controller/AIController.ts +62 -50
- package/src/core/controller/ExerciseController.ts +98 -0
- package/src/core/controller/ObjectController.ts +15 -10
- package/src/core/controller/SettingsController.ts +89 -16
- package/src/core/controller/SharedContentController.ts +80 -44
- package/src/core/controller/VoiceController.ts +10 -8
- package/src/core/core.ts +15 -15
- package/src/fromRimori/EventBus.ts +76 -47
- package/src/fromRimori/PluginTypes.ts +26 -17
- package/src/fromRimori/readme.md +2 -2
- package/src/hooks/UseChatHook.ts +25 -15
- package/src/index.ts +10 -10
- package/src/plugin/AccomplishmentHandler.ts +53 -35
- package/src/plugin/AudioController.ts +18 -12
- package/src/plugin/Logger.ts +77 -19
- package/src/plugin/PluginController.ts +60 -44
- package/src/plugin/RimoriClient.ts +133 -69
- package/src/plugin/StandaloneClient.ts +51 -24
- package/src/plugin/ThemeSetter.ts +5 -5
- package/src/providers/PluginProvider.tsx +90 -36
- package/src/style.scss +3 -3
- package/src/utils/Language.ts +58 -58
- package/src/utils/PluginUtils.ts +16 -20
- package/src/utils/difficultyConverter.ts +2 -2
- package/src/utils/endpoint.ts +3 -2
- package/src/worker/WorkerSetup.ts +8 -9
- package/tsconfig.json +2 -4
- package/dist/components/LoggerExample.d.ts +0 -6
- package/dist/components/LoggerExample.js +0 -79
- package/dist/core/controller/AudioController.d.ts +0 -0
- package/dist/core/controller/AudioController.js +0 -1
- package/dist/hooks/UseLogger.d.ts +0 -30
- package/dist/hooks/UseLogger.js +0 -122
- package/dist/plugin/LoggerExample.d.ts +0 -16
- package/dist/plugin/LoggerExample.js +0 -140
- package/dist/utils/audioFormats.d.ts +0 -26
- package/dist/utils/audioFormats.js +0 -67
package/eslint.config.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import js from '@eslint/js';
|
|
2
|
+
import globals from 'globals';
|
|
3
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
4
|
+
import reactRefresh from 'eslint-plugin-react-refresh';
|
|
5
|
+
import tseslint from 'typescript-eslint';
|
|
6
|
+
import prettier from 'eslint-plugin-prettier';
|
|
7
|
+
import prettierConfig from 'eslint-config-prettier';
|
|
8
|
+
|
|
9
|
+
export default [
|
|
10
|
+
{ ignores: ['dist', 'node_modules', 'build', '*.js'] },
|
|
11
|
+
js.configs.recommended,
|
|
12
|
+
...tseslint.configs.recommended,
|
|
13
|
+
prettierConfig,
|
|
14
|
+
{
|
|
15
|
+
files: ['**/*.{ts,tsx,js,jsx}'],
|
|
16
|
+
languageOptions: {
|
|
17
|
+
ecmaVersion: 2020,
|
|
18
|
+
globals: {
|
|
19
|
+
...globals.browser,
|
|
20
|
+
...globals.node,
|
|
21
|
+
...globals.jest,
|
|
22
|
+
},
|
|
23
|
+
sourceType: 'module',
|
|
24
|
+
parserOptions: {
|
|
25
|
+
projectService: true,
|
|
26
|
+
tsconfigRootDir: import.meta.dirname,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
plugins: {
|
|
30
|
+
'react-hooks': reactHooks,
|
|
31
|
+
'react-refresh': reactRefresh,
|
|
32
|
+
prettier: prettier,
|
|
33
|
+
},
|
|
34
|
+
rules: {
|
|
35
|
+
...reactHooks.configs.recommended.rules,
|
|
36
|
+
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
|
|
37
|
+
'@typescript-eslint/no-unused-vars': 'warn',
|
|
38
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
39
|
+
'@typescript-eslint/no-floating-promises': 'warn',
|
|
40
|
+
'@typescript-eslint/no-unsafe-argument': 'warn',
|
|
41
|
+
'@typescript-eslint/explicit-function-return-type': 'warn',
|
|
42
|
+
'@typescript-eslint/explicit-module-boundary-types': 'warn',
|
|
43
|
+
'@typescript-eslint/no-unsafe-assignment': 'warn',
|
|
44
|
+
'@typescript-eslint/no-unsafe-member-access': 'warn',
|
|
45
|
+
'@typescript-eslint/no-unsafe-call': 'warn',
|
|
46
|
+
'@typescript-eslint/no-unsafe-return': 'warn',
|
|
47
|
+
'@typescript-eslint/no-inferrable-types': 'warn',
|
|
48
|
+
'@typescript-eslint/no-non-null-assertion': 'warn',
|
|
49
|
+
'@typescript-eslint/ban-ts-comment': 'warn',
|
|
50
|
+
'prettier/prettier': 'error',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
];
|
package/example/docs/devdocs.md
CHANGED
|
@@ -13,41 +13,44 @@ All communication uses the Rimori event bus with the pattern: `<plugin_id>.<area
|
|
|
13
13
|
### 1. Create Flashcards
|
|
14
14
|
|
|
15
15
|
#### Basic Creation
|
|
16
|
+
|
|
16
17
|
```javascript
|
|
17
18
|
// Create a simple flashcard
|
|
18
|
-
plugin.event.emit(
|
|
19
|
-
front:
|
|
20
|
-
back:
|
|
21
|
-
deckId:
|
|
22
|
-
frontTags: [
|
|
23
|
-
backTags: [
|
|
19
|
+
plugin.event.emit('pl123456789.flashcard.create', {
|
|
20
|
+
front: 'Hello',
|
|
21
|
+
back: 'Hola',
|
|
22
|
+
deckId: 'deck-123', // optional, uses default deck if omitted
|
|
23
|
+
frontTags: ['lang:en'],
|
|
24
|
+
backTags: ['lang:es'],
|
|
24
25
|
});
|
|
25
26
|
```
|
|
26
27
|
|
|
27
28
|
#### Language-based Creation
|
|
29
|
+
|
|
28
30
|
```javascript
|
|
29
31
|
// Create flashcard with automatic lookup
|
|
30
|
-
plugin.event.emit(
|
|
31
|
-
word:
|
|
32
|
-
language:
|
|
33
|
-
deckId:
|
|
32
|
+
plugin.event.emit('pl123456789.flashcard.createLangCard', {
|
|
33
|
+
word: 'perro',
|
|
34
|
+
language: 'es', // optional, uses user's mother tongue if omitted
|
|
35
|
+
deckId: 'spanish-nouns', // optional
|
|
34
36
|
});
|
|
35
37
|
```
|
|
36
38
|
|
|
37
39
|
### 2. Lookup Requests
|
|
38
40
|
|
|
39
41
|
#### Basic Translation
|
|
42
|
+
|
|
40
43
|
```javascript
|
|
41
44
|
// Request word translation
|
|
42
|
-
const translation = await plugin.event.request(
|
|
43
|
-
word:
|
|
44
|
-
language:
|
|
45
|
+
const translation = await plugin.event.request('pl123456789.lookup.requestBasic', {
|
|
46
|
+
word: 'laufen',
|
|
47
|
+
language: 'de', // optional
|
|
45
48
|
});
|
|
46
49
|
|
|
47
50
|
// Returns:
|
|
48
51
|
// {
|
|
49
52
|
// input: "laufen",
|
|
50
|
-
// language: "de",
|
|
53
|
+
// language: "de",
|
|
51
54
|
// type: "verb",
|
|
52
55
|
// swedish_translation: "att springa",
|
|
53
56
|
// translation: "to run"
|
|
@@ -55,11 +58,12 @@ const translation = await plugin.event.request("pl123456789.lookup.requestBasic"
|
|
|
55
58
|
```
|
|
56
59
|
|
|
57
60
|
#### Advanced Lookup
|
|
61
|
+
|
|
58
62
|
```javascript
|
|
59
63
|
// Get detailed word information
|
|
60
|
-
const details = await plugin.event.request(
|
|
61
|
-
word:
|
|
62
|
-
language:
|
|
64
|
+
const details = await plugin.event.request('pl123456789.lookup.request', {
|
|
65
|
+
word: 'laufen',
|
|
66
|
+
language: 'de',
|
|
63
67
|
});
|
|
64
68
|
|
|
65
69
|
// Returns extended object with grammar, examples, tenses, etc.
|
|
@@ -68,14 +72,15 @@ const details = await plugin.event.request("pl123456789.lookup.request", {
|
|
|
68
72
|
### 3. Deck Management
|
|
69
73
|
|
|
70
74
|
#### Get Available Decks
|
|
75
|
+
|
|
71
76
|
```javascript
|
|
72
|
-
const decks = await plugin.event.request(
|
|
77
|
+
const decks = await plugin.event.request('pl123456789.deck.requestOpenToday');
|
|
73
78
|
|
|
74
79
|
// Returns:
|
|
75
80
|
// [
|
|
76
81
|
// {
|
|
77
82
|
// id: "deck-123",
|
|
78
|
-
// name: "Spanish Vocabulary",
|
|
83
|
+
// name: "Spanish Vocabulary",
|
|
79
84
|
// total_new: 5,
|
|
80
85
|
// total_learning: 12,
|
|
81
86
|
// total_review: 8
|
|
@@ -84,9 +89,10 @@ const decks = await plugin.event.request("pl123456789.deck.requestOpenToday");
|
|
|
84
89
|
```
|
|
85
90
|
|
|
86
91
|
#### Create New Deck
|
|
92
|
+
|
|
87
93
|
```javascript
|
|
88
|
-
const newDeck = await plugin.event.request(
|
|
89
|
-
name:
|
|
94
|
+
const newDeck = await plugin.event.request('pl123456789.deck.create', {
|
|
95
|
+
name: 'German Verbs',
|
|
90
96
|
});
|
|
91
97
|
|
|
92
98
|
// Returns: { id: "deck-456", name: "German Verbs", last_used: "2025-01-06T..." }
|
|
@@ -95,35 +101,37 @@ const newDeck = await plugin.event.request("pl123456789.deck.create", {
|
|
|
95
101
|
### 4. Trigger Training
|
|
96
102
|
|
|
97
103
|
#### Open Flashcard Training
|
|
104
|
+
|
|
98
105
|
```javascript
|
|
99
106
|
// Open training in main panel
|
|
100
|
-
plugin.event.emit(
|
|
101
|
-
pluginId:
|
|
102
|
-
actionKey:
|
|
103
|
-
deck:
|
|
104
|
-
total_amount: 20 // or "default"
|
|
107
|
+
plugin.event.emit('global.mainPanel.triggerAction', {
|
|
108
|
+
pluginId: 'pl123456789',
|
|
109
|
+
actionKey: 'flashcards',
|
|
110
|
+
deck: 'latest', // or "random", "oldest", "mix", deck ID
|
|
111
|
+
total_amount: 20, // or "default"
|
|
105
112
|
});
|
|
106
113
|
```
|
|
107
114
|
|
|
108
115
|
## Worker Function Example
|
|
109
116
|
|
|
110
117
|
### Background Deck Sync
|
|
118
|
+
|
|
111
119
|
```javascript
|
|
112
120
|
// worker/listeners/deck-sync.ts
|
|
113
121
|
import { WorkerEventListener } from '@rimori/client';
|
|
114
122
|
|
|
115
123
|
export const deckSyncListener: WorkerEventListener = {
|
|
116
124
|
eventName: 'pl123456789.deck.syncProgress',
|
|
117
|
-
|
|
125
|
+
|
|
118
126
|
async handler(data: { userId: string; deckId: string }) {
|
|
119
127
|
const { userId, deckId } = data;
|
|
120
|
-
|
|
128
|
+
|
|
121
129
|
// Calculate learning statistics
|
|
122
130
|
const stats = await calculateDeckProgress(deckId, userId);
|
|
123
|
-
|
|
131
|
+
|
|
124
132
|
// Update user's learning streak
|
|
125
133
|
await updateLearningStreak(userId, stats);
|
|
126
|
-
|
|
134
|
+
|
|
127
135
|
// Send progress update to main thread
|
|
128
136
|
self.postMessage({
|
|
129
137
|
type: 'progress-updated',
|
|
@@ -143,10 +151,10 @@ async function calculateDeckProgress(deckId: string, userId: string) {
|
|
|
143
151
|
.select('*')
|
|
144
152
|
.eq('deck_id', deckId)
|
|
145
153
|
.eq('user_id', userId);
|
|
146
|
-
|
|
154
|
+
|
|
147
155
|
const reviewed = cards.filter(c => c.last_review_date >= getTodayStart());
|
|
148
156
|
const accuracy = reviewed.reduce((acc, c) => acc + c.ease_factor, 0) / reviewed.length;
|
|
149
|
-
|
|
157
|
+
|
|
150
158
|
return {
|
|
151
159
|
reviewed: reviewed.length,
|
|
152
160
|
accuracy: Math.round(accuracy * 100),
|
|
@@ -185,6 +193,7 @@ interface Deck {
|
|
|
185
193
|
## Integration Examples
|
|
186
194
|
|
|
187
195
|
### Dictionary Plugin → Flashcards
|
|
196
|
+
|
|
188
197
|
```javascript
|
|
189
198
|
// When user looks up a word in dictionary
|
|
190
199
|
function onWordLookup(word: string, translation: string) {
|
|
@@ -198,15 +207,16 @@ function onWordLookup(word: string, translation: string) {
|
|
|
198
207
|
}
|
|
199
208
|
```
|
|
200
209
|
|
|
201
|
-
### Study Planner → Flashcards
|
|
210
|
+
### Study Planner → Flashcards
|
|
211
|
+
|
|
202
212
|
```javascript
|
|
203
213
|
// Trigger daily flashcard session
|
|
204
214
|
function scheduleDailyReview() {
|
|
205
|
-
plugin.event.emit(
|
|
206
|
-
pluginId:
|
|
207
|
-
actionKey:
|
|
208
|
-
deck:
|
|
209
|
-
total_amount: 30
|
|
215
|
+
plugin.event.emit('global.mainPanel.triggerAction', {
|
|
216
|
+
pluginId: 'pl123456789',
|
|
217
|
+
actionKey: 'flashcards',
|
|
218
|
+
deck: 'mix',
|
|
219
|
+
total_amount: 30,
|
|
210
220
|
});
|
|
211
221
|
}
|
|
212
222
|
```
|
|
@@ -215,9 +225,9 @@ function scheduleDailyReview() {
|
|
|
215
225
|
|
|
216
226
|
```javascript
|
|
217
227
|
try {
|
|
218
|
-
await plugin.event.request(
|
|
228
|
+
await plugin.event.request('pl123456789.flashcard.create', cardData);
|
|
219
229
|
} catch (error) {
|
|
220
|
-
console.error(
|
|
230
|
+
console.error('Failed to create flashcard:', error);
|
|
221
231
|
// Handle error appropriately
|
|
222
232
|
}
|
|
223
233
|
```
|
package/example/docs/overview.md
CHANGED
|
@@ -9,7 +9,7 @@ Simple Flashcards uses proven spaced repetition algorithms to help you memorize
|
|
|
9
9
|
## 🎯 Perfect for
|
|
10
10
|
|
|
11
11
|
- **Language learners** building vocabulary with audio pronunciation
|
|
12
|
-
- **Students** memorizing facts, formulas, and definitions
|
|
12
|
+
- **Students** memorizing facts, formulas, and definitions
|
|
13
13
|
- **Professionals** learning technical terms and concepts
|
|
14
14
|
- **Anyone** who wants to remember information long-term
|
|
15
15
|
|
package/example/docs/userdocs.md
CHANGED
|
@@ -62,7 +62,7 @@ Speed up your review sessions with keyboard shortcuts that eliminate the need fo
|
|
|
62
62
|
- **Spacebar** - Reveal the answer when studying the front of a card
|
|
63
63
|
- **Number keys 1-4** - Rate your recall (Again, Hard, Good, Easy respectively)
|
|
64
64
|
- **5 key** - Play audio for the front of the card (if language tags are present)
|
|
65
|
-
- **h key** - Play audio for the back of the card (if language tags are present)
|
|
65
|
+
- **h key** - Play audio for the back of the card (if language tags are present)
|
|
66
66
|
- **v key** - Edit the current flashcard during review
|
|
67
67
|
|
|
68
68
|
These shortcuts allow you to maintain focus and rhythm during your learning sessions.
|
|
@@ -109,15 +109,18 @@ To get the most out of your flashcard learning:
|
|
|
109
109
|
## Troubleshooting Common Issues
|
|
110
110
|
|
|
111
111
|
**Audio not playing when expected?**
|
|
112
|
+
|
|
112
113
|
- Verify that your device volume is turned up and not muted
|
|
113
114
|
- Check that the flashcard has proper language tags (e.g., `lang:en` for English)
|
|
114
115
|
- Try refreshing the page if audio features seem unresponsive
|
|
115
116
|
|
|
116
117
|
**Flashcards not saving properly?**
|
|
118
|
+
|
|
117
119
|
- Ensure you have a stable internet connection for data synchronization
|
|
118
120
|
- Verify you clicked the save icon after entering card content
|
|
119
121
|
- Try creating the card again if the first attempt failed
|
|
120
122
|
|
|
121
123
|
**Progress not updating correctly?**
|
|
124
|
+
|
|
122
125
|
- Refresh the page to ensure you're seeing the latest data
|
|
123
126
|
- Check that you're rating cards rather than just viewing them
|
package/example/rimori.config.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RimoriPluginConfig } from
|
|
1
|
+
import { RimoriPluginConfig } from '@rimori/client';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* This is an example of a Rimori plugin configuration file. It is based on the Rimori Flashcards plugin.
|
|
@@ -6,84 +6,86 @@ import { RimoriPluginConfig } from "@rimori/client";
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const config: RimoriPluginConfig = {
|
|
9
|
-
id:
|
|
9
|
+
id: 'pl1234567890', // This is the plugin id. You can find it in the plugin's package.json file.
|
|
10
10
|
info: {
|
|
11
|
-
title:
|
|
12
|
-
description:
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
title: 'Flashcards',
|
|
12
|
+
description:
|
|
13
|
+
"The Rimori Flashcards Plugin is a powerful tool for learning and memorization using spaced repetition. It helps you efficiently review information, whether you're learning a language, preparing for exams, or mastering new skills. The plugin uses advanced algorithms to schedule your reviews at optimal intervals, maximizing retention while minimizing study time.",
|
|
14
|
+
logo: 'logo.png',
|
|
15
|
+
website: 'https://rimori.se',
|
|
15
16
|
},
|
|
16
17
|
pages: {
|
|
17
18
|
main: [
|
|
18
19
|
{
|
|
19
|
-
id:
|
|
20
|
-
url:
|
|
20
|
+
id: '1',
|
|
21
|
+
url: '#/',
|
|
21
22
|
show: true,
|
|
22
|
-
name:
|
|
23
|
-
root:
|
|
24
|
-
description:
|
|
23
|
+
name: 'Flashcards',
|
|
24
|
+
root: 'vocabulary',
|
|
25
|
+
description: 'Quickly memorizing info by using flashcards.',
|
|
25
26
|
},
|
|
26
|
-
{
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
{
|
|
28
|
+
// This is a page that is not shown in the navbar. It is used to trigger the flashcards action.
|
|
29
|
+
id: '2',
|
|
30
|
+
url: '#/deck/custom',
|
|
29
31
|
show: false,
|
|
30
|
-
root:
|
|
31
|
-
name:
|
|
32
|
-
description:
|
|
32
|
+
root: 'vocabulary',
|
|
33
|
+
name: 'Latest flashcard deck training',
|
|
34
|
+
description: 'Training the latest flashcards.',
|
|
33
35
|
action: {
|
|
34
|
-
key:
|
|
36
|
+
key: 'flashcards',
|
|
35
37
|
parameters: {
|
|
36
38
|
total_amount: {
|
|
37
39
|
type: 'number',
|
|
38
|
-
description: 'Number of flashcards to practice. Default is 70 (10 new + 20 reviewed + 40 forgotten).'
|
|
40
|
+
description: 'Number of flashcards to practice. Default is 70 (10 new + 20 reviewed + 40 forgotten).',
|
|
39
41
|
},
|
|
40
42
|
deck: {
|
|
41
43
|
type: 'string',
|
|
42
44
|
enum: ['latest', 'random', 'oldest', 'mix', 'best_known'],
|
|
43
|
-
description: 'Type of deck to practice from'
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
45
|
+
description: 'Type of deck to practice from',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
48
50
|
],
|
|
49
51
|
sidebar: [
|
|
50
52
|
{
|
|
51
|
-
id:
|
|
52
|
-
url:
|
|
53
|
-
name:
|
|
54
|
-
icon:
|
|
55
|
-
description:
|
|
53
|
+
id: 'translate',
|
|
54
|
+
url: '#/sidebar/translate',
|
|
55
|
+
name: 'Translate',
|
|
56
|
+
icon: 'translate.png',
|
|
57
|
+
description: 'Translate words.',
|
|
56
58
|
},
|
|
57
59
|
{
|
|
58
|
-
id:
|
|
59
|
-
url:
|
|
60
|
-
name:
|
|
61
|
-
icon:
|
|
62
|
-
description:
|
|
63
|
-
}
|
|
60
|
+
id: 'flashcard_quick_add',
|
|
61
|
+
url: '#/sidebar/add',
|
|
62
|
+
name: 'Quick add',
|
|
63
|
+
icon: 'logo.png',
|
|
64
|
+
description: 'Quickly add a word to your flashcards.',
|
|
65
|
+
},
|
|
64
66
|
],
|
|
65
|
-
settings:
|
|
67
|
+
settings: '/settings',
|
|
66
68
|
},
|
|
67
69
|
context_menu_actions: [
|
|
68
70
|
{
|
|
69
|
-
text:
|
|
70
|
-
plugin_id:
|
|
71
|
-
action_key:
|
|
71
|
+
text: 'Translate',
|
|
72
|
+
plugin_id: 'pl1234567890',
|
|
73
|
+
action_key: 'translate',
|
|
72
74
|
},
|
|
73
75
|
{
|
|
74
|
-
text:
|
|
75
|
-
plugin_id:
|
|
76
|
-
action_key:
|
|
77
|
-
}
|
|
76
|
+
text: 'Quick add',
|
|
77
|
+
plugin_id: 'pl1234567890',
|
|
78
|
+
action_key: 'flashcard_quick_add',
|
|
79
|
+
},
|
|
78
80
|
],
|
|
79
81
|
documentation: {
|
|
80
|
-
overview_path:
|
|
81
|
-
user_path:
|
|
82
|
-
developer_path:
|
|
82
|
+
overview_path: 'docs/overview.md',
|
|
83
|
+
user_path: 'docs/userdocs.md',
|
|
84
|
+
developer_path: 'docs/devdocs.md',
|
|
83
85
|
},
|
|
84
86
|
worker: {
|
|
85
|
-
url:
|
|
86
|
-
}
|
|
87
|
+
url: 'web-worker.js',
|
|
88
|
+
},
|
|
87
89
|
};
|
|
88
90
|
|
|
89
|
-
export default config;
|
|
91
|
+
export default config;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineConfig } from 'vite'
|
|
2
|
-
import path from 'path'
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import path from 'path';
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
5
|
root: __dirname,
|
|
@@ -20,4 +20,4 @@ export default defineConfig({
|
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
|
-
})
|
|
23
|
+
});
|
package/example/worker/worker.ts
CHANGED
|
@@ -4,8 +4,8 @@ setupWorker(async (client: RimoriClient) => {
|
|
|
4
4
|
console.log('[Worker] initialized');
|
|
5
5
|
|
|
6
6
|
// listening to events for this plugin to create flashcards
|
|
7
|
-
client.event.respond<{ front: string
|
|
7
|
+
client.event.respond<{ front: string; back: string }>('flashcards.create', ({ data }) => {
|
|
8
8
|
console.log('[Worker] creating flashcards in database', data);
|
|
9
9
|
return { success: true };
|
|
10
10
|
});
|
|
11
|
-
});
|
|
11
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rimori/client",
|
|
3
|
-
"version": "1.3
|
|
3
|
+
"version": "1.4.3",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"bin": {
|
|
@@ -25,7 +25,12 @@
|
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsc && sass src/style.scss:dist/style.css",
|
|
27
27
|
"dev": "tsc -w --preserveWatchOutput",
|
|
28
|
-
"css-dev": "sass --watch src/style.scss:dist/style.css"
|
|
28
|
+
"css-dev": "sass --watch src/style.scss:dist/style.css",
|
|
29
|
+
"lint": "eslint .",
|
|
30
|
+
"lint:fix": "eslint . --fix",
|
|
31
|
+
"format": "prettier --write .",
|
|
32
|
+
"format:check": "prettier --check .",
|
|
33
|
+
"check": "yarn lint && yarn format:check"
|
|
29
34
|
},
|
|
30
35
|
"peerDependencies": {
|
|
31
36
|
"react": "^18.0.0",
|
|
@@ -39,12 +44,20 @@
|
|
|
39
44
|
"html2canvas": "1.4.1",
|
|
40
45
|
"react-icons": "5.4.0",
|
|
41
46
|
"react-markdown": "10.1.0",
|
|
42
|
-
"tiptap-markdown": "0.8.10"
|
|
47
|
+
"tiptap-markdown": "0.8.10",
|
|
48
|
+
"prettier": "^3.6.2"
|
|
43
49
|
},
|
|
44
50
|
"devDependencies": {
|
|
45
51
|
"form-data": "^4.0.2",
|
|
46
52
|
"node-fetch": "^3.3.2",
|
|
47
53
|
"sass": "^1.82.0",
|
|
48
|
-
"typescript": "^5.7.2"
|
|
54
|
+
"typescript": "^5.7.2",
|
|
55
|
+
"@eslint/js": "^9.37.0",
|
|
56
|
+
"eslint-plugin-react-hooks": "^7.0.0",
|
|
57
|
+
"eslint-plugin-react-refresh": "^0.4.23",
|
|
58
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
59
|
+
"eslint-config-prettier": "^10.1.8",
|
|
60
|
+
"globals": "^16.4.0",
|
|
61
|
+
"typescript-eslint": "^8.46.0"
|
|
49
62
|
}
|
|
50
63
|
}
|
|
@@ -31,7 +31,7 @@ export async function askForCredentials(): Promise<UserCredentials> {
|
|
|
31
31
|
const passwordRl = readline.createInterface({
|
|
32
32
|
input: process.stdin,
|
|
33
33
|
output: process.stdout,
|
|
34
|
-
terminal: false
|
|
34
|
+
terminal: false,
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
process.stdout.write('Enter your password: ');
|
|
@@ -113,10 +113,7 @@ export async function askForPort(): Promise<number> {
|
|
|
113
113
|
* @returns Promise resolving to JWT access token.
|
|
114
114
|
* @throws {Error} if authentication fails.
|
|
115
115
|
*/
|
|
116
|
-
export async function authenticateWithSupabase({
|
|
117
|
-
email,
|
|
118
|
-
password,
|
|
119
|
-
}: UserCredentials): Promise<string> {
|
|
116
|
+
export async function authenticateWithSupabase({ email, password }: UserCredentials): Promise<string> {
|
|
120
117
|
console.log('🔐 Authenticating with Supabase...');
|
|
121
118
|
|
|
122
119
|
// Initialize Supabase client (you may need to adjust the URL and key)
|
|
@@ -159,13 +156,13 @@ export async function registerDeveloper(jwtToken: string, port: number): Promise
|
|
|
159
156
|
try {
|
|
160
157
|
const currentFolderName = path.basename(process.cwd());
|
|
161
158
|
const body: any = { port, pluginName: currentFolderName };
|
|
162
|
-
const backendUrl = process.env.RIMORI_BACKEND_URL ||
|
|
159
|
+
const backendUrl = process.env.RIMORI_BACKEND_URL || 'https://api.rimori.se';
|
|
163
160
|
|
|
164
161
|
const response = await fetch(backendUrl + '/developer/register', {
|
|
165
162
|
method: 'POST',
|
|
166
163
|
headers: {
|
|
167
164
|
'Content-Type': 'application/json',
|
|
168
|
-
|
|
165
|
+
Authorization: `Bearer ${jwtToken}`,
|
|
169
166
|
},
|
|
170
167
|
body: JSON.stringify(body),
|
|
171
168
|
});
|
|
@@ -189,4 +186,4 @@ export async function registerDeveloper(jwtToken: string, port: number): Promise
|
|
|
189
186
|
console.error(error);
|
|
190
187
|
throw new Error(`Developer registration failed: ${error}`);
|
|
191
188
|
}
|
|
192
|
-
}
|
|
189
|
+
}
|
|
@@ -8,10 +8,7 @@ import * as path from 'path';
|
|
|
8
8
|
*/
|
|
9
9
|
function removeUnwantedMetaTags(htmlContent: string): string {
|
|
10
10
|
// Remove all meta tags except those with name="viewport" or charset attribute
|
|
11
|
-
let cleanedContent = htmlContent.replace(
|
|
12
|
-
/<meta\s+(?![^>]*(?:name\s*=\s*["']viewport["']|charset\s*=))[^>]*>/gi,
|
|
13
|
-
''
|
|
14
|
-
);
|
|
11
|
+
let cleanedContent = htmlContent.replace(/<meta\s+(?![^>]*(?:name\s*=\s*["']viewport["']|charset\s*=))[^>]*>/gi, '');
|
|
15
12
|
|
|
16
13
|
// Remove empty lines left behind
|
|
17
14
|
cleanedContent = cleanedContent.replace(/^\s*[\r\n]/gm, '');
|
|
@@ -45,4 +42,4 @@ export function cleanHtmlMetaTags(): void {
|
|
|
45
42
|
} catch (error) {
|
|
46
43
|
console.error(`Error processing HTML file ${filePath}:`, error);
|
|
47
44
|
}
|
|
48
|
-
}
|
|
45
|
+
}
|
|
@@ -2,12 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import * as path from 'path';
|
|
5
|
-
import {
|
|
6
|
-
askForCredentials,
|
|
7
|
-
askForPort,
|
|
8
|
-
authenticateWithSupabase,
|
|
9
|
-
registerDeveloper,
|
|
10
|
-
} from './dev-registration.js';
|
|
5
|
+
import { askForCredentials, askForPort, authenticateWithSupabase, registerDeveloper } from './dev-registration.js';
|
|
11
6
|
import { setupEnvFile, updateGitignore } from './env-setup.js';
|
|
12
7
|
import { copyPluginFiles } from './file-operations.js';
|
|
13
8
|
import { cleanHtmlMetaTags } from './html-cleaner.js';
|
|
@@ -42,8 +37,12 @@ async function main(): Promise<void> {
|
|
|
42
37
|
console.log('❌ Plugin is already initialized!');
|
|
43
38
|
console.log(`Plugin ID: ${packageJson.r_id}`);
|
|
44
39
|
console.log('');
|
|
45
|
-
console.log(
|
|
46
|
-
|
|
40
|
+
console.log(
|
|
41
|
+
'If you want to reinitialize the plugin, please remove the "r_id" field from package.json first.',
|
|
42
|
+
);
|
|
43
|
+
console.log(
|
|
44
|
+
'Or use the --upgrade flag to upgrade the plugin configuration without changing the plugin ID.',
|
|
45
|
+
);
|
|
47
46
|
process.exit(0);
|
|
48
47
|
}
|
|
49
48
|
} catch (error) {
|
|
@@ -83,7 +82,6 @@ async function main(): Promise<void> {
|
|
|
83
82
|
|
|
84
83
|
// Update gitignore
|
|
85
84
|
updateGitignore();
|
|
86
|
-
|
|
87
85
|
} else {
|
|
88
86
|
// Step 1: Get user credentials
|
|
89
87
|
const credentials = await askForCredentials();
|
|
@@ -125,7 +123,9 @@ async function main(): Promise<void> {
|
|
|
125
123
|
updateViteConfigBase();
|
|
126
124
|
console.log('✅ Vite config base updated');
|
|
127
125
|
} catch (error) {
|
|
128
|
-
console.warn(
|
|
126
|
+
console.warn(
|
|
127
|
+
`Warning: Could not update vite.config.ts base property: ${error instanceof Error ? error.message : error}`,
|
|
128
|
+
);
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
// Clean meta tags from index.html after vite adaptation
|
|
@@ -152,13 +152,16 @@ async function main(): Promise<void> {
|
|
|
152
152
|
console.log('Next steps:');
|
|
153
153
|
console.log('1. Check out ./rimori/readme.md for more information about how to make the most out of the plugin.');
|
|
154
154
|
console.log('2. Adapt the ./rimori/rimori.config.ts file to your needs.');
|
|
155
|
-
console.log(
|
|
155
|
+
console.log(
|
|
156
|
+
'3. Under ./public/docs/ you can find the documentation for an example flashcard plugin to get started easier.',
|
|
157
|
+
);
|
|
156
158
|
console.log('4. Start development with: yarn dev');
|
|
157
159
|
console.log('');
|
|
158
160
|
console.log(`The plugin should now be accessible at: http://localhost:${3000}`);
|
|
159
161
|
console.log('');
|
|
160
|
-
console.log(
|
|
161
|
-
|
|
162
|
+
console.log(
|
|
163
|
+
'If you want to release the plugin, simply run: "yarn release:<alpha|beta|stable>" (details are available in ./rimori/readme.md)',
|
|
164
|
+
);
|
|
162
165
|
} catch (error) {
|
|
163
166
|
console.error(`❌ Error: ${error instanceof Error ? error.message : error}`);
|
|
164
167
|
console.error('');
|