@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.
Files changed (148) hide show
  1. package/.prettierignore +35 -0
  2. package/README.md +77 -71
  3. package/dist/cli/scripts/init/dev-registration.d.ts +1 -1
  4. package/dist/cli/scripts/init/dev-registration.js +4 -4
  5. package/dist/cli/scripts/init/main.js +1 -1
  6. package/dist/cli/scripts/init/package-setup.d.ts +1 -1
  7. package/dist/cli/scripts/init/package-setup.js +3 -3
  8. package/dist/cli/scripts/init/router-transformer.js +19 -12
  9. package/dist/cli/scripts/init/vite-config.d.ts +2 -2
  10. package/dist/cli/scripts/init/vite-config.js +2 -2
  11. package/dist/cli/scripts/release/release-config-upload.js +9 -9
  12. package/dist/cli/scripts/release/release-db-update.d.ts +1 -1
  13. package/dist/cli/scripts/release/release-db-update.js +9 -9
  14. package/dist/cli/scripts/release/release-file-upload.js +2 -2
  15. package/dist/cli/scripts/release/release.js +2 -2
  16. package/dist/cli/types/DatabaseTypes.d.ts +2 -2
  17. package/dist/components/CRUDModal.d.ts +1 -1
  18. package/dist/components/CRUDModal.js +3 -3
  19. package/dist/components/MarkdownEditor.js +16 -16
  20. package/dist/components/Spinner.js +2 -2
  21. package/dist/components/ai/Assistant.js +7 -8
  22. package/dist/components/ai/Avatar.d.ts +2 -2
  23. package/dist/components/ai/Avatar.js +14 -7
  24. package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +5 -6
  25. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +1 -1
  26. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -2
  27. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -2
  28. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +4 -2
  29. package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +1 -1
  30. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +2 -3
  31. package/dist/components/audio/Playbutton.js +10 -7
  32. package/dist/components/components/ContextMenu.d.ts +1 -1
  33. package/dist/components/components/ContextMenu.js +19 -16
  34. package/dist/components.d.ts +10 -10
  35. package/dist/components.js +10 -10
  36. package/dist/core/controller/AIController.d.ts +2 -2
  37. package/dist/core/controller/AIController.js +20 -18
  38. package/dist/core/controller/ExerciseController.d.ts +52 -0
  39. package/dist/core/controller/ExerciseController.js +73 -0
  40. package/dist/core/controller/ObjectController.js +5 -5
  41. package/dist/core/controller/SettingsController.d.ts +22 -7
  42. package/dist/core/controller/SettingsController.js +73 -8
  43. package/dist/core/controller/SharedContentController.d.ts +3 -3
  44. package/dist/core/controller/SharedContentController.js +38 -20
  45. package/dist/core/controller/VoiceController.js +6 -4
  46. package/dist/core/core.d.ts +15 -14
  47. package/dist/core/core.js +7 -7
  48. package/dist/fromRimori/EventBus.js +23 -23
  49. package/dist/fromRimori/PluginTypes.d.ts +4 -4
  50. package/dist/hooks/UseChatHook.d.ts +3 -3
  51. package/dist/hooks/UseChatHook.js +9 -3
  52. package/dist/index.d.ts +10 -10
  53. package/dist/index.js +9 -9
  54. package/dist/plugin/AccomplishmentHandler.d.ts +5 -5
  55. package/dist/plugin/AccomplishmentHandler.js +31 -27
  56. package/dist/plugin/AudioController.d.ts +1 -1
  57. package/dist/plugin/AudioController.js +6 -6
  58. package/dist/plugin/Logger.d.ts +5 -0
  59. package/dist/plugin/Logger.js +65 -13
  60. package/dist/plugin/PluginController.d.ts +7 -1
  61. package/dist/plugin/PluginController.js +32 -27
  62. package/dist/plugin/RimoriClient.d.ts +39 -14
  63. package/dist/plugin/RimoriClient.js +60 -31
  64. package/dist/plugin/StandaloneClient.d.ts +1 -1
  65. package/dist/plugin/StandaloneClient.js +35 -16
  66. package/dist/plugin/ThemeSetter.js +4 -4
  67. package/dist/providers/PluginProvider.js +44 -14
  68. package/dist/utils/Language.js +57 -57
  69. package/dist/utils/PluginUtils.js +3 -3
  70. package/dist/utils/difficultyConverter.d.ts +1 -1
  71. package/dist/utils/difficultyConverter.js +1 -1
  72. package/dist/utils/endpoint.js +2 -2
  73. package/dist/worker/WorkerSetup.d.ts +1 -1
  74. package/dist/worker/WorkerSetup.js +6 -6
  75. package/eslint.config.js +53 -0
  76. package/example/docs/devdocs.md +50 -40
  77. package/example/docs/overview.md +1 -1
  78. package/example/docs/userdocs.md +4 -1
  79. package/example/rimori.config.ts +51 -49
  80. package/example/worker/vite.config.ts +3 -3
  81. package/example/worker/worker.ts +2 -2
  82. package/package.json +17 -4
  83. package/prettier.config.js +8 -0
  84. package/src/cli/scripts/init/dev-registration.ts +5 -8
  85. package/src/cli/scripts/init/env-setup.ts +1 -1
  86. package/src/cli/scripts/init/file-operations.ts +1 -1
  87. package/src/cli/scripts/init/html-cleaner.ts +2 -5
  88. package/src/cli/scripts/init/main.ts +16 -13
  89. package/src/cli/scripts/init/package-setup.ts +11 -15
  90. package/src/cli/scripts/init/router-transformer.ts +40 -37
  91. package/src/cli/scripts/init/tailwind-config.ts +17 -26
  92. package/src/cli/scripts/init/vite-config.ts +3 -3
  93. package/src/cli/scripts/release/release-config-upload.ts +11 -11
  94. package/src/cli/scripts/release/release-db-update.ts +12 -12
  95. package/src/cli/scripts/release/release-file-upload.ts +3 -3
  96. package/src/cli/scripts/release/release.ts +4 -4
  97. package/src/cli/types/DatabaseTypes.ts +7 -8
  98. package/src/components/CRUDModal.tsx +64 -48
  99. package/src/components/MarkdownEditor.tsx +58 -27
  100. package/src/components/Spinner.tsx +24 -17
  101. package/src/components/ai/Assistant.tsx +70 -70
  102. package/src/components/ai/Avatar.tsx +20 -16
  103. package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +63 -54
  104. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +14 -5
  105. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +75 -74
  106. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +177 -178
  107. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +109 -94
  108. package/src/components/ai/utils.ts +4 -4
  109. package/src/components/audio/Playbutton.tsx +101 -93
  110. package/src/components/components/ContextMenu.tsx +47 -35
  111. package/src/components.ts +10 -10
  112. package/src/core/controller/AIController.ts +62 -50
  113. package/src/core/controller/ExerciseController.ts +98 -0
  114. package/src/core/controller/ObjectController.ts +15 -10
  115. package/src/core/controller/SettingsController.ts +89 -16
  116. package/src/core/controller/SharedContentController.ts +80 -44
  117. package/src/core/controller/VoiceController.ts +10 -8
  118. package/src/core/core.ts +15 -15
  119. package/src/fromRimori/EventBus.ts +76 -47
  120. package/src/fromRimori/PluginTypes.ts +26 -17
  121. package/src/fromRimori/readme.md +2 -2
  122. package/src/hooks/UseChatHook.ts +25 -15
  123. package/src/index.ts +10 -10
  124. package/src/plugin/AccomplishmentHandler.ts +53 -35
  125. package/src/plugin/AudioController.ts +18 -12
  126. package/src/plugin/Logger.ts +77 -19
  127. package/src/plugin/PluginController.ts +60 -44
  128. package/src/plugin/RimoriClient.ts +133 -69
  129. package/src/plugin/StandaloneClient.ts +51 -24
  130. package/src/plugin/ThemeSetter.ts +5 -5
  131. package/src/providers/PluginProvider.tsx +90 -36
  132. package/src/style.scss +3 -3
  133. package/src/utils/Language.ts +58 -58
  134. package/src/utils/PluginUtils.ts +16 -20
  135. package/src/utils/difficultyConverter.ts +2 -2
  136. package/src/utils/endpoint.ts +3 -2
  137. package/src/worker/WorkerSetup.ts +8 -9
  138. package/tsconfig.json +2 -4
  139. package/dist/components/LoggerExample.d.ts +0 -6
  140. package/dist/components/LoggerExample.js +0 -79
  141. package/dist/core/controller/AudioController.d.ts +0 -0
  142. package/dist/core/controller/AudioController.js +0 -1
  143. package/dist/hooks/UseLogger.d.ts +0 -30
  144. package/dist/hooks/UseLogger.js +0 -122
  145. package/dist/plugin/LoggerExample.d.ts +0 -16
  146. package/dist/plugin/LoggerExample.js +0 -140
  147. package/dist/utils/audioFormats.d.ts +0 -26
  148. package/dist/utils/audioFormats.js +0 -67
@@ -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
+ ];
@@ -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("pl123456789.flashcard.create", {
19
- front: "Hello",
20
- back: "Hola",
21
- deckId: "deck-123", // optional, uses default deck if omitted
22
- frontTags: ["lang:en"],
23
- backTags: ["lang:es"]
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("pl123456789.flashcard.createLangCard", {
31
- word: "perro",
32
- language: "es", // optional, uses user's mother tongue if omitted
33
- deckId: "spanish-nouns" // optional
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("pl123456789.lookup.requestBasic", {
43
- word: "laufen",
44
- language: "de" // optional
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("pl123456789.lookup.request", {
61
- word: "laufen",
62
- language: "de"
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("pl123456789.deck.requestOpenToday");
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("pl123456789.deck.create", {
89
- name: "German Verbs"
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("global.mainPanel.triggerAction", {
101
- pluginId: "pl123456789",
102
- actionKey: "flashcards",
103
- deck: "latest", // or "random", "oldest", "mix", deck ID
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("global.mainPanel.triggerAction", {
206
- pluginId: "pl123456789",
207
- actionKey: "flashcards",
208
- deck: "mix",
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("pl123456789.flashcard.create", cardData);
228
+ await plugin.event.request('pl123456789.flashcard.create', cardData);
219
229
  } catch (error) {
220
- console.error("Failed to create flashcard:", error);
230
+ console.error('Failed to create flashcard:', error);
221
231
  // Handle error appropriately
222
232
  }
223
233
  ```
@@ -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
 
@@ -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
@@ -1,4 +1,4 @@
1
- import { RimoriPluginConfig } from "@rimori/client";
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: "pl1234567890", // This is the plugin id. You can find it in the plugin's package.json file.
9
+ id: 'pl1234567890', // This is the plugin id. You can find it in the plugin's package.json file.
10
10
  info: {
11
- title: "Flashcards",
12
- description: "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.",
13
- logo: "logo.png",
14
- website: "https://rimori.se",
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: "1",
20
- url: "#/",
20
+ id: '1',
21
+ url: '#/',
21
22
  show: true,
22
- name: "Flashcards",
23
- root: "vocabulary",
24
- description: "Quickly memorizing info by using flashcards."
23
+ name: 'Flashcards',
24
+ root: 'vocabulary',
25
+ description: 'Quickly memorizing info by using flashcards.',
25
26
  },
26
- { // This is a page that is not shown in the navbar. It is used to trigger the flashcards action.
27
- id: "2",
28
- url: "#/deck/custom",
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: "vocabulary",
31
- name: "Latest flashcard deck training",
32
- description: "Training the latest flashcards.",
32
+ root: 'vocabulary',
33
+ name: 'Latest flashcard deck training',
34
+ description: 'Training the latest flashcards.',
33
35
  action: {
34
- key: "flashcards",
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: "translate",
52
- url: "#/sidebar/translate",
53
- name: "Translate",
54
- icon: "translate.png",
55
- description: "Translate words."
53
+ id: 'translate',
54
+ url: '#/sidebar/translate',
55
+ name: 'Translate',
56
+ icon: 'translate.png',
57
+ description: 'Translate words.',
56
58
  },
57
59
  {
58
- id: "flashcard_quick_add",
59
- url: "#/sidebar/add",
60
- name: "Quick add",
61
- icon: "logo.png",
62
- description: "Quickly add a word to your flashcards."
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: "/settings",
67
+ settings: '/settings',
66
68
  },
67
69
  context_menu_actions: [
68
70
  {
69
- text: "Translate",
70
- plugin_id: "pl1234567890",
71
- action_key: "translate"
71
+ text: 'Translate',
72
+ plugin_id: 'pl1234567890',
73
+ action_key: 'translate',
72
74
  },
73
75
  {
74
- text: "Quick add",
75
- plugin_id: "pl1234567890",
76
- action_key: "flashcard_quick_add"
77
- }
76
+ text: 'Quick add',
77
+ plugin_id: 'pl1234567890',
78
+ action_key: 'flashcard_quick_add',
79
+ },
78
80
  ],
79
81
  documentation: {
80
- overview_path: "docs/overview.md",
81
- user_path: "docs/userdocs.md",
82
- developer_path: "docs/devdocs.md"
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: "web-worker.js",
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
+ });
@@ -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, back: string }>('flashcards.create', ({ data }) => {
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.1",
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
  }
@@ -0,0 +1,8 @@
1
+ export default {
2
+ printWidth: 120,
3
+ singleQuote: true,
4
+ trailingComma: 'all',
5
+ semi: true,
6
+ tabWidth: 2,
7
+ useTabs: false,
8
+ };
@@ -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 || "https://api.rimori.se";
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
- 'Authorization': `Bearer ${jwtToken}`,
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
+ }
@@ -41,4 +41,4 @@ export function updateGitignore(): void {
41
41
  } else {
42
42
  console.log('.env already in .gitignore, skipping update');
43
43
  }
44
- }
44
+ }
@@ -55,4 +55,4 @@ export function copyPluginFiles(): void {
55
55
  }
56
56
 
57
57
  console.log('Plugin file copying completed.');
58
- }
58
+ }
@@ -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('If you want to reinitialize the plugin, please remove the "r_id" field from package.json first.');
46
- console.log('Or use the --upgrade flag to upgrade the plugin configuration without changing the plugin ID.');
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(`Warning: Could not update vite.config.ts base property: ${error instanceof Error ? error.message : error}`);
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('3. Under ./public/docs/ you can find the documentation for an example flashcard plugin to get started easier.');
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('If you want to release the plugin, simply run: "yarn release:<alpha|beta|stable>" (details are available in ./rimori/readme.md)');
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('');