@jjlmoya/utils-drones 1.30.0 → 1.32.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.
Files changed (67) hide show
  1. package/package.json +1 -1
  2. package/src/category/i18n/en.ts +1 -1
  3. package/src/category/i18n/fr.ts +1 -1
  4. package/src/category/index.ts +2 -0
  5. package/src/components/PreviewNavSidebar.astro +116 -116
  6. package/src/components/PreviewToolbar.astro +143 -143
  7. package/src/data.ts +1 -1
  8. package/src/entries.ts +4 -0
  9. package/src/env.d.ts +1 -1
  10. package/src/index.ts +1 -1
  11. package/src/layouts/PreviewLayout.astro +118 -118
  12. package/src/pages/[locale].astro +251 -251
  13. package/src/pages/index.astro +4 -4
  14. package/src/tests/faq_count.test.ts +1 -1
  15. package/src/tests/locale_completeness.test.ts +1 -2
  16. package/src/tests/mocks/astro_mock.js +1 -1
  17. package/src/tests/no_h1_in_components.test.ts +1 -1
  18. package/src/tests/tool_validation.test.ts +17 -17
  19. package/src/tool/antenna-length-calculator/bibliography.astro +6 -6
  20. package/src/tool/antenna-length-calculator/component.astro +329 -329
  21. package/src/tool/antenna-length-calculator/seo.astro +15 -15
  22. package/src/tool/drone-battery-c-rating-calculator/i18n/de.ts +192 -192
  23. package/src/tool/drone-battery-c-rating-calculator/i18n/en.ts +192 -192
  24. package/src/tool/drone-battery-c-rating-calculator/i18n/es.ts +192 -192
  25. package/src/tool/drone-battery-c-rating-calculator/i18n/id.ts +192 -192
  26. package/src/tool/drone-battery-c-rating-calculator/i18n/ja.ts +192 -192
  27. package/src/tool/drone-battery-c-rating-calculator/i18n/ko.ts +192 -192
  28. package/src/tool/drone-battery-c-rating-calculator/i18n/nl.ts +192 -192
  29. package/src/tool/drone-battery-c-rating-calculator/i18n/pl.ts +192 -192
  30. package/src/tool/drone-battery-c-rating-calculator/i18n/ru.ts +192 -192
  31. package/src/tool/drone-battery-c-rating-calculator/i18n/sv.ts +192 -192
  32. package/src/tool/drone-battery-c-rating-calculator/i18n/tr.ts +192 -192
  33. package/src/tool/drone-battery-c-rating-calculator/i18n/zh.ts +192 -192
  34. package/src/tool/drone-flight-time/component.astro +187 -187
  35. package/src/tool/drone-flight-time/seo.astro +15 -15
  36. package/src/tool/drone-motor-propeller-calculator/bibliography.astro +6 -0
  37. package/src/tool/drone-motor-propeller-calculator/bibliography.ts +12 -0
  38. package/src/tool/drone-motor-propeller-calculator/component.astro +109 -0
  39. package/src/tool/drone-motor-propeller-calculator/controller.ts +174 -0
  40. package/src/tool/drone-motor-propeller-calculator/dom-views.ts +78 -0
  41. package/src/tool/drone-motor-propeller-calculator/drone-motor-propeller-calculator.css +562 -0
  42. package/src/tool/drone-motor-propeller-calculator/entry.ts +27 -0
  43. package/src/tool/drone-motor-propeller-calculator/evaluator.ts +14 -0
  44. package/src/tool/drone-motor-propeller-calculator/i18n/de.ts +202 -0
  45. package/src/tool/drone-motor-propeller-calculator/i18n/en.ts +202 -0
  46. package/src/tool/drone-motor-propeller-calculator/i18n/es.ts +202 -0
  47. package/src/tool/drone-motor-propeller-calculator/i18n/fr.ts +202 -0
  48. package/src/tool/drone-motor-propeller-calculator/i18n/id.ts +192 -0
  49. package/src/tool/drone-motor-propeller-calculator/i18n/it.ts +192 -0
  50. package/src/tool/drone-motor-propeller-calculator/i18n/ja.ts +192 -0
  51. package/src/tool/drone-motor-propeller-calculator/i18n/ko.ts +192 -0
  52. package/src/tool/drone-motor-propeller-calculator/i18n/nl.ts +192 -0
  53. package/src/tool/drone-motor-propeller-calculator/i18n/pl.ts +192 -0
  54. package/src/tool/drone-motor-propeller-calculator/i18n/pt.ts +192 -0
  55. package/src/tool/drone-motor-propeller-calculator/i18n/ru.ts +192 -0
  56. package/src/tool/drone-motor-propeller-calculator/i18n/sv.ts +192 -0
  57. package/src/tool/drone-motor-propeller-calculator/i18n/tr.ts +192 -0
  58. package/src/tool/drone-motor-propeller-calculator/i18n/zh.ts +192 -0
  59. package/src/tool/drone-motor-propeller-calculator/index.ts +11 -0
  60. package/src/tool/drone-motor-propeller-calculator/logic.test.ts +56 -0
  61. package/src/tool/drone-motor-propeller-calculator/logic.ts +108 -0
  62. package/src/tool/drone-motor-propeller-calculator/seo.astro +15 -0
  63. package/src/tool/drone-motor-propeller-calculator/storage.ts +26 -0
  64. package/src/tool/drone-motor-propeller-calculator/ui.ts +55 -0
  65. package/src/tool/gps-coordinates-converter/component.astro +275 -275
  66. package/src/tool/gps-coordinates-converter/seo.astro +15 -15
  67. package/src/tools.ts +3 -0
@@ -1,251 +1,251 @@
1
- ---
2
- import PreviewLayout from '../layouts/PreviewLayout.astro';
3
- import PreviewNavSidebar from '../components/PreviewNavSidebar.astro';
4
- import { dronesCategory, ALL_TOOLS } from '../index';
5
- import { Icon } from 'astro-icon/components';
6
- import type { KnownLocale, ToolLocaleContent } from '../types';
7
-
8
- export async function getStaticPaths() {
9
- const locales = ['en', 'es', 'fr'] as KnownLocale[];
10
- return locales.map(locale => ({ params: { locale } }));
11
- }
12
-
13
- const { locale: currentLocale } = Astro.params as { locale: KnownLocale };
14
-
15
- const categoryContent = await dronesCategory.i18n[currentLocale]!();
16
-
17
- const tools = ALL_TOOLS || [];
18
-
19
- const toolsWithContent = tools.length > 0
20
- ? await Promise.all(
21
- tools.map(async ({ entry, Component }) => {
22
- const languages = Object.keys(entry.i18n);
23
- const localeEntries = await Promise.all(
24
- languages.map(async (l) => {
25
- const content = await entry.i18n[l as KnownLocale]!();
26
- return [l, content];
27
- })
28
- );
29
-
30
- const localeContents = Object.fromEntries(localeEntries) as Record<string, ToolLocaleContent<Record<string, string>>>;
31
-
32
- const currentLocaleContent = localeContents[currentLocale] || localeContents['en'] || localeContents['es'];
33
- const availableLocales: Record<string, string> = {};
34
-
35
- for (const l of languages) {
36
- const lCont = localeContents[l];
37
- if (lCont) {
38
- availableLocales[l] = `/${l}/${lCont.slug}`;
39
- }
40
- }
41
-
42
- return { entry, Component, locale: currentLocaleContent, availableLocales };
43
- })
44
- )
45
- : [];
46
- ---
47
-
48
- <PreviewLayout
49
- title={categoryContent.title}
50
- currentLocale={currentLocale}
51
- hasSidebar={true}
52
- >
53
- <PreviewNavSidebar
54
- slot="sidebar"
55
- categoryTitle={categoryContent.title}
56
- tools={toolsWithContent.map(({ entry, locale, availableLocales }) => {
57
- const href = availableLocales[currentLocale] || (locale ? `/${currentLocale}/${locale.slug}` : '#');
58
- return {
59
- id: entry.id,
60
- title: locale?.title || entry.id,
61
- href: href,
62
- };
63
- })}
64
- />
65
- <div class="dashboard">
66
- <header class="preview-header">
67
- <span class="badge">preview · @jjlmoya/utils-template</span>
68
- <h1>{categoryContent.title}</h1>
69
- <p>{categoryContent.description}</p>
70
- </header>
71
-
72
- <div class="tool-list">
73
- {toolsWithContent?.map(({ entry, locale, availableLocales }) => (
74
- <article class="tool-card">
75
- <a href={availableLocales?.[currentLocale] || (locale ? `/${currentLocale}/${locale.slug}` : '#')} class="tool-card-link">
76
- <div class="tool-icons">
77
- <div class="icon-wrapper bg">
78
- <Icon name={entry.icons.bg} />
79
- </div>
80
- <div class="icon-wrapper fg">
81
- <Icon name={entry.icons.fg} />
82
- </div>
83
- </div>
84
- <div class="tool-card-content">
85
- <h2 class="tool-title">{locale?.title}</h2>
86
- <p class="tool-description">{locale?.description}</p>
87
- </div>
88
- <div class="tool-card-meta">
89
- <span class="tool-id">{entry.id}</span>
90
- </div>
91
- </a>
92
-
93
- {availableLocales && Object.keys(availableLocales).length > 1 && (
94
- <div class="tool-locales">
95
- {Object.entries(availableLocales).map(([l, url]) => (
96
- <a href={url} class="locale-badge" title={`Ver en ${l.toUpperCase()}`} class:list={{ active: l === currentLocale }}>
97
- {l.toUpperCase()}
98
- </a>
99
- ))}
100
- </div>
101
- )}
102
- </article>
103
- ))}
104
- </div>
105
- </div>
106
- </PreviewLayout>
107
-
108
- <style>
109
- .dashboard {
110
- display: flex;
111
- flex-direction: column;
112
- gap: 5rem;
113
- }
114
- .preview-header {
115
- text-align: center;
116
- padding-bottom: 3rem;
117
- border-bottom: 1px solid var(--border-color);
118
- }
119
- .badge {
120
- display: inline-block;
121
- padding: 0.25rem 0.75rem;
122
- background: var(--accent);
123
- border-radius: 99px;
124
- font-size: 0.7rem;
125
- font-weight: 800;
126
- margin-bottom: 1.5rem;
127
- color: var(--text-base);
128
- letter-spacing: 0.05em;
129
- }
130
- h1 {
131
- font-size: clamp(2rem, 6vw, 3.5rem);
132
- font-weight: 900;
133
- margin: 0 0 1rem;
134
- background: linear-gradient(to bottom, var(--text-base), var(--text-muted));
135
- -webkit-background-clip: text;
136
- -webkit-text-fill-color: transparent;
137
- background-clip: text;
138
- }
139
- .preview-header p {
140
- color: var(--text-muted);
141
- font-size: 1.1rem;
142
- margin: 0;
143
- }
144
- .tool-list {
145
- display: grid;
146
- grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
147
- gap: 2rem;
148
- }
149
- .tool-card {
150
- display: flex;
151
- flex-direction: column;
152
- gap: 1rem;
153
- }
154
- .tool-card-link {
155
- flex: 1;
156
- display: flex;
157
- flex-direction: column;
158
- padding: 1.5rem;
159
- background: var(--bg-surface);
160
- border: 1px solid var(--border-color);
161
- border-radius: 0.75rem;
162
- text-decoration: none;
163
- transition: all 0.2s ease;
164
- }
165
- .tool-card-link:hover {
166
- border-color: var(--accent);
167
- background: rgba(244, 63, 94, 0.05);
168
- transform: translateY(-2px);
169
- }
170
- .tool-icons {
171
- display: flex;
172
- align-items: center;
173
- gap: 1rem;
174
- margin-bottom: 1.25rem;
175
- }
176
- .icon-wrapper {
177
- display: flex;
178
- align-items: center;
179
- justify-content: center;
180
- width: 3rem;
181
- height: 3rem;
182
- border-radius: 0.5rem;
183
- font-size: 1.5rem;
184
- }
185
- .icon-wrapper.bg {
186
- background: var(--accent);
187
- color: var(--text-base);
188
- }
189
- .icon-wrapper.fg {
190
- background: var(--bg-page);
191
- border: 1px solid var(--border-color);
192
- color: var(--accent);
193
- }
194
- .tool-card-content {
195
- flex: 1;
196
- display: flex;
197
- flex-direction: column;
198
- }
199
- .tool-title {
200
- font-size: 1.25rem;
201
- font-weight: 700;
202
- margin: 0 0 0.5rem;
203
- color: var(--text-base);
204
- }
205
- .tool-description {
206
- font-size: 0.9375rem;
207
- color: var(--text-muted);
208
- line-height: 1.5;
209
- margin: 0;
210
- }
211
- .tool-card-meta {
212
- padding-top: 1rem;
213
- border-top: 1px solid var(--border-color);
214
- margin-top: 1.5rem;
215
- }
216
- .tool-id {
217
- display: inline-block;
218
- font-size: 0.7rem;
219
- background: var(--bg-page);
220
- border: 1px solid var(--border-color);
221
- padding: 0.35rem 0.75rem;
222
- border-radius: 0.4rem;
223
- color: var(--accent);
224
- font-weight: 600;
225
- }
226
- .tool-locales {
227
- display: flex;
228
- gap: 0.5rem;
229
- flex-wrap: wrap;
230
- }
231
- .locale-badge {
232
- display: inline-block;
233
- padding: 0.4rem 0.85rem;
234
- background: var(--bg-page);
235
- border: 1px solid var(--border-color);
236
- border-radius: 0.4rem;
237
- color: var(--text-muted);
238
- text-decoration: none;
239
- font-size: 0.75rem;
240
- font-weight: 600;
241
- text-transform: uppercase;
242
- letter-spacing: 0.05em;
243
- transition: all 0.15s ease;
244
- }
245
- .locale-badge:hover,
246
- .locale-badge.active {
247
- color: var(--accent);
248
- border-color: var(--accent);
249
- background: rgba(244, 63, 94, 0.1);
250
- }
251
- </style>
1
+ ---
2
+ import PreviewLayout from '../layouts/PreviewLayout.astro';
3
+ import PreviewNavSidebar from '../components/PreviewNavSidebar.astro';
4
+ import { dronesCategory, ALL_TOOLS } from '../index';
5
+ import { Icon } from 'astro-icon/components';
6
+ import type { KnownLocale, ToolLocaleContent } from '../types';
7
+
8
+ export async function getStaticPaths() {
9
+ const locales = ['en', 'es', 'fr'] as KnownLocale[];
10
+ return locales.map(locale => ({ params: { locale } }));
11
+ }
12
+
13
+ const { locale: currentLocale } = Astro.params as { locale: KnownLocale };
14
+
15
+ const categoryContent = await dronesCategory.i18n[currentLocale]!();
16
+
17
+ const tools = ALL_TOOLS || [];
18
+
19
+ const toolsWithContent = tools.length > 0
20
+ ? await Promise.all(
21
+ tools.map(async ({ entry, Component }) => {
22
+ const languages = Object.keys(entry.i18n);
23
+ const localeEntries = await Promise.all(
24
+ languages.map(async (l) => {
25
+ const content = await entry.i18n[l as KnownLocale]!();
26
+ return [l, content];
27
+ })
28
+ );
29
+
30
+ const localeContents = Object.fromEntries(localeEntries) as Record<string, ToolLocaleContent<Record<string, string>>>;
31
+
32
+ const currentLocaleContent = localeContents[currentLocale] || localeContents['en'] || localeContents['es'];
33
+ const availableLocales: Record<string, string> = {};
34
+
35
+ for (const l of languages) {
36
+ const lCont = localeContents[l];
37
+ if (lCont) {
38
+ availableLocales[l] = `/${l}/${lCont.slug}`;
39
+ }
40
+ }
41
+
42
+ return { entry, Component, locale: currentLocaleContent, availableLocales };
43
+ })
44
+ )
45
+ : [];
46
+ ---
47
+
48
+ <PreviewLayout
49
+ title={categoryContent.title}
50
+ currentLocale={currentLocale}
51
+ hasSidebar={true}
52
+ >
53
+ <PreviewNavSidebar
54
+ slot="sidebar"
55
+ categoryTitle={categoryContent.title}
56
+ tools={toolsWithContent.map(({ entry, locale, availableLocales }) => {
57
+ const href = availableLocales[currentLocale] || (locale ? `/${currentLocale}/${locale.slug}` : '#');
58
+ return {
59
+ id: entry.id,
60
+ title: locale?.title || entry.id,
61
+ href: href,
62
+ };
63
+ })}
64
+ />
65
+ <div class="dashboard">
66
+ <header class="preview-header">
67
+ <span class="badge">preview · @jjlmoya/utils-template</span>
68
+ <h1>{categoryContent.title}</h1>
69
+ <p>{categoryContent.description}</p>
70
+ </header>
71
+
72
+ <div class="tool-list">
73
+ {toolsWithContent?.map(({ entry, locale, availableLocales }) => (
74
+ <article class="tool-card">
75
+ <a href={availableLocales?.[currentLocale] || (locale ? `/${currentLocale}/${locale.slug}` : '#')} class="tool-card-link">
76
+ <div class="tool-icons">
77
+ <div class="icon-wrapper bg">
78
+ <Icon name={entry.icons.bg} />
79
+ </div>
80
+ <div class="icon-wrapper fg">
81
+ <Icon name={entry.icons.fg} />
82
+ </div>
83
+ </div>
84
+ <div class="tool-card-content">
85
+ <h2 class="tool-title">{locale?.title}</h2>
86
+ <p class="tool-description">{locale?.description}</p>
87
+ </div>
88
+ <div class="tool-card-meta">
89
+ <span class="tool-id">{entry.id}</span>
90
+ </div>
91
+ </a>
92
+
93
+ {availableLocales && Object.keys(availableLocales).length > 1 && (
94
+ <div class="tool-locales">
95
+ {Object.entries(availableLocales).map(([l, url]) => (
96
+ <a href={url} class="locale-badge" title={`Ver en ${l.toUpperCase()}`} class:list={{ active: l === currentLocale }}>
97
+ {l.toUpperCase()}
98
+ </a>
99
+ ))}
100
+ </div>
101
+ )}
102
+ </article>
103
+ ))}
104
+ </div>
105
+ </div>
106
+ </PreviewLayout>
107
+
108
+ <style>
109
+ .dashboard {
110
+ display: flex;
111
+ flex-direction: column;
112
+ gap: 5rem;
113
+ }
114
+ .preview-header {
115
+ text-align: center;
116
+ padding-bottom: 3rem;
117
+ border-bottom: 1px solid var(--border-color);
118
+ }
119
+ .badge {
120
+ display: inline-block;
121
+ padding: 0.25rem 0.75rem;
122
+ background: var(--accent);
123
+ border-radius: 99px;
124
+ font-size: 0.7rem;
125
+ font-weight: 800;
126
+ margin-bottom: 1.5rem;
127
+ color: var(--text-base);
128
+ letter-spacing: 0.05em;
129
+ }
130
+ h1 {
131
+ font-size: clamp(2rem, 6vw, 3.5rem);
132
+ font-weight: 900;
133
+ margin: 0 0 1rem;
134
+ background: linear-gradient(to bottom, var(--text-base), var(--text-muted));
135
+ -webkit-background-clip: text;
136
+ -webkit-text-fill-color: transparent;
137
+ background-clip: text;
138
+ }
139
+ .preview-header p {
140
+ color: var(--text-muted);
141
+ font-size: 1.1rem;
142
+ margin: 0;
143
+ }
144
+ .tool-list {
145
+ display: grid;
146
+ grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
147
+ gap: 2rem;
148
+ }
149
+ .tool-card {
150
+ display: flex;
151
+ flex-direction: column;
152
+ gap: 1rem;
153
+ }
154
+ .tool-card-link {
155
+ flex: 1;
156
+ display: flex;
157
+ flex-direction: column;
158
+ padding: 1.5rem;
159
+ background: var(--bg-surface);
160
+ border: 1px solid var(--border-color);
161
+ border-radius: 0.75rem;
162
+ text-decoration: none;
163
+ transition: all 0.2s ease;
164
+ }
165
+ .tool-card-link:hover {
166
+ border-color: var(--accent);
167
+ background: rgba(244, 63, 94, 0.05);
168
+ transform: translateY(-2px);
169
+ }
170
+ .tool-icons {
171
+ display: flex;
172
+ align-items: center;
173
+ gap: 1rem;
174
+ margin-bottom: 1.25rem;
175
+ }
176
+ .icon-wrapper {
177
+ display: flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ width: 3rem;
181
+ height: 3rem;
182
+ border-radius: 0.5rem;
183
+ font-size: 1.5rem;
184
+ }
185
+ .icon-wrapper.bg {
186
+ background: var(--accent);
187
+ color: var(--text-base);
188
+ }
189
+ .icon-wrapper.fg {
190
+ background: var(--bg-page);
191
+ border: 1px solid var(--border-color);
192
+ color: var(--accent);
193
+ }
194
+ .tool-card-content {
195
+ flex: 1;
196
+ display: flex;
197
+ flex-direction: column;
198
+ }
199
+ .tool-title {
200
+ font-size: 1.25rem;
201
+ font-weight: 700;
202
+ margin: 0 0 0.5rem;
203
+ color: var(--text-base);
204
+ }
205
+ .tool-description {
206
+ font-size: 0.9375rem;
207
+ color: var(--text-muted);
208
+ line-height: 1.5;
209
+ margin: 0;
210
+ }
211
+ .tool-card-meta {
212
+ padding-top: 1rem;
213
+ border-top: 1px solid var(--border-color);
214
+ margin-top: 1.5rem;
215
+ }
216
+ .tool-id {
217
+ display: inline-block;
218
+ font-size: 0.7rem;
219
+ background: var(--bg-page);
220
+ border: 1px solid var(--border-color);
221
+ padding: 0.35rem 0.75rem;
222
+ border-radius: 0.4rem;
223
+ color: var(--accent);
224
+ font-weight: 600;
225
+ }
226
+ .tool-locales {
227
+ display: flex;
228
+ gap: 0.5rem;
229
+ flex-wrap: wrap;
230
+ }
231
+ .locale-badge {
232
+ display: inline-block;
233
+ padding: 0.4rem 0.85rem;
234
+ background: var(--bg-page);
235
+ border: 1px solid var(--border-color);
236
+ border-radius: 0.4rem;
237
+ color: var(--text-muted);
238
+ text-decoration: none;
239
+ font-size: 0.75rem;
240
+ font-weight: 600;
241
+ text-transform: uppercase;
242
+ letter-spacing: 0.05em;
243
+ transition: all 0.15s ease;
244
+ }
245
+ .locale-badge:hover,
246
+ .locale-badge.active {
247
+ color: var(--accent);
248
+ border-color: var(--accent);
249
+ background: rgba(244, 63, 94, 0.1);
250
+ }
251
+ </style>
@@ -1,4 +1,4 @@
1
- ---
2
- ---
3
- <meta http-equiv="refresh" content="0;url=/es" />
4
-
1
+ ---
2
+ ---
3
+ <meta http-equiv="refresh" content="0;url=/es" />
4
+
@@ -16,4 +16,4 @@ describe('FAQ Content Validation', () => {
16
16
  expect(TOOLS.length).toBe(0);
17
17
  });
18
18
  });
19
-
19
+
@@ -18,7 +18,6 @@ describe('Locale Completeness Validation', () => {
18
18
  });
19
19
 
20
20
  it('all 7 tools registered', () => {
21
- expect(ALL_TOOLS.length).toBe(7);
21
+ expect(ALL_TOOLS.length).toBe(8);
22
22
  });
23
23
  });
24
-
@@ -1,2 +1,2 @@
1
1
  export default function () { return null; }
2
-
2
+
@@ -45,4 +45,4 @@ describe('No H1 in Components', () => {
45
45
  });
46
46
  });
47
47
  });
48
-
48
+
@@ -1,17 +1,17 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { ALL_TOOLS } from '../tools';
3
- import { dronesCategory } from '../data';
4
-
5
- describe('Tool Validation Suite', () => {
6
- describe('Library Registration', () => {
7
- it('should have 7 tools in ALL_TOOLS', () => {
8
- expect(ALL_TOOLS.length).toBe(7);
9
- });
10
-
11
- it('dronesCategory should be defined', () => {
12
- expect(dronesCategory).toBeDefined();
13
- expect(dronesCategory.i18n).toBeDefined();
14
- });
15
- });
16
- });
17
-
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ALL_TOOLS } from '../tools';
3
+ import { dronesCategory } from '../data';
4
+
5
+ describe('Tool Validation Suite', () => {
6
+ describe('Library Registration', () => {
7
+ it('should have 8 tools in ALL_TOOLS', () => {
8
+ expect(ALL_TOOLS.length).toBe(8);
9
+ });
10
+
11
+ it('dronesCategory should be defined', () => {
12
+ expect(dronesCategory).toBeDefined();
13
+ expect(dronesCategory.i18n).toBeDefined();
14
+ });
15
+ });
16
+ });
17
+
@@ -1,6 +1,6 @@
1
- ---
2
- import { Bibliography as BibliographyComponent } from '@jjlmoya/utils-shared';
3
- import { bibliography } from './bibliography';
4
- ---
5
-
6
- <BibliographyComponent links={bibliography} />
1
+ ---
2
+ import { Bibliography as BibliographyComponent } from '@jjlmoya/utils-shared';
3
+ import { bibliography } from './bibliography';
4
+ ---
5
+
6
+ <BibliographyComponent links={bibliography} />