@jjlmoya/utils-drones 1.14.0 → 1.16.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 (93) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -1
  3. package/src/entries.ts +4 -1
  4. package/src/index.ts +1 -0
  5. package/src/pages/[locale]/[slug].astro +30 -14
  6. package/src/tests/locale_completeness.test.ts +4 -22
  7. package/src/tests/shared-test-helpers.ts +56 -0
  8. package/src/tests/tool_exports.test.ts +34 -0
  9. package/src/tests/tool_validation.test.ts +2 -2
  10. package/src/tool/antenna-length-calculator/bibliography.astro +3 -11
  11. package/src/tool/antenna-length-calculator/bibliography.ts +6 -0
  12. package/src/tool/antenna-length-calculator/i18n/de.ts +2 -8
  13. package/src/tool/antenna-length-calculator/i18n/en.ts +2 -8
  14. package/src/tool/antenna-length-calculator/i18n/es.ts +2 -8
  15. package/src/tool/antenna-length-calculator/i18n/fr.ts +2 -8
  16. package/src/tool/antenna-length-calculator/i18n/id.ts +2 -8
  17. package/src/tool/antenna-length-calculator/i18n/it.ts +2 -8
  18. package/src/tool/antenna-length-calculator/i18n/ja.ts +2 -8
  19. package/src/tool/antenna-length-calculator/i18n/ko.ts +2 -8
  20. package/src/tool/antenna-length-calculator/i18n/nl.ts +2 -8
  21. package/src/tool/antenna-length-calculator/i18n/pl.ts +2 -8
  22. package/src/tool/antenna-length-calculator/i18n/pt.ts +2 -8
  23. package/src/tool/antenna-length-calculator/i18n/ru.ts +2 -8
  24. package/src/tool/antenna-length-calculator/i18n/sv.ts +2 -8
  25. package/src/tool/antenna-length-calculator/i18n/tr.ts +2 -8
  26. package/src/tool/antenna-length-calculator/i18n/zh.ts +2 -8
  27. package/src/tool/antenna-length-calculator/seo.astro +2 -26
  28. package/src/tool/drone-flight-time/bibliography.astro +3 -11
  29. package/src/tool/drone-flight-time/bibliography.ts +7 -0
  30. package/src/tool/drone-flight-time/i18n/de.ts +2 -9
  31. package/src/tool/drone-flight-time/i18n/en.ts +2 -9
  32. package/src/tool/drone-flight-time/i18n/es.ts +2 -9
  33. package/src/tool/drone-flight-time/i18n/fr.ts +2 -9
  34. package/src/tool/drone-flight-time/i18n/id.ts +2 -9
  35. package/src/tool/drone-flight-time/i18n/it.ts +2 -9
  36. package/src/tool/drone-flight-time/i18n/ja.ts +2 -9
  37. package/src/tool/drone-flight-time/i18n/ko.ts +2 -9
  38. package/src/tool/drone-flight-time/i18n/nl.ts +2 -9
  39. package/src/tool/drone-flight-time/i18n/pl.ts +2 -9
  40. package/src/tool/drone-flight-time/i18n/pt.ts +2 -9
  41. package/src/tool/drone-flight-time/i18n/ru.ts +2 -9
  42. package/src/tool/drone-flight-time/i18n/sv.ts +2 -9
  43. package/src/tool/drone-flight-time/i18n/tr.ts +2 -9
  44. package/src/tool/drone-flight-time/i18n/zh.ts +2 -9
  45. package/src/tool/drone-flight-time/seo.astro +2 -18
  46. package/src/tool/drone-power-analyzer/bibliography.astro +6 -0
  47. package/src/tool/drone-power-analyzer/bibliography.ts +7 -0
  48. package/src/tool/drone-power-analyzer/component.astro +210 -0
  49. package/src/tool/drone-power-analyzer/components/FlightProfile.astro +37 -0
  50. package/src/tool/drone-power-analyzer/components/MotorConfig.astro +46 -0
  51. package/src/tool/drone-power-analyzer/components/PowerGauge.astro +48 -0
  52. package/src/tool/drone-power-analyzer/components/WeightConfig.astro +49 -0
  53. package/src/tool/drone-power-analyzer/drone-power-analyzer.css +535 -0
  54. package/src/tool/drone-power-analyzer/entry.ts +29 -0
  55. package/src/tool/drone-power-analyzer/i18n/de.ts +203 -0
  56. package/src/tool/drone-power-analyzer/i18n/en.ts +203 -0
  57. package/src/tool/drone-power-analyzer/i18n/es.ts +203 -0
  58. package/src/tool/drone-power-analyzer/i18n/fr.ts +203 -0
  59. package/src/tool/drone-power-analyzer/i18n/id.ts +203 -0
  60. package/src/tool/drone-power-analyzer/i18n/it.ts +203 -0
  61. package/src/tool/drone-power-analyzer/i18n/ja.ts +203 -0
  62. package/src/tool/drone-power-analyzer/i18n/ko.ts +203 -0
  63. package/src/tool/drone-power-analyzer/i18n/nl.ts +203 -0
  64. package/src/tool/drone-power-analyzer/i18n/pl.ts +203 -0
  65. package/src/tool/drone-power-analyzer/i18n/pt.ts +203 -0
  66. package/src/tool/drone-power-analyzer/i18n/ru.ts +203 -0
  67. package/src/tool/drone-power-analyzer/i18n/sv.ts +203 -0
  68. package/src/tool/drone-power-analyzer/i18n/tr.ts +203 -0
  69. package/src/tool/drone-power-analyzer/i18n/zh.ts +203 -0
  70. package/src/tool/drone-power-analyzer/index.ts +8 -0
  71. package/src/tool/drone-power-analyzer/seo.astro +15 -0
  72. package/src/tool/gps-coordinates-converter/bibliography.astro +3 -11
  73. package/src/tool/gps-coordinates-converter/bibliography.ts +12 -0
  74. package/src/tool/gps-coordinates-converter/components/GpsMap.astro +3 -2
  75. package/src/tool/gps-coordinates-converter/gps-coordinates-converter.css +196 -188
  76. package/src/tool/gps-coordinates-converter/i18n/de.ts +35 -36
  77. package/src/tool/gps-coordinates-converter/i18n/en.ts +4 -14
  78. package/src/tool/gps-coordinates-converter/i18n/es.ts +4 -14
  79. package/src/tool/gps-coordinates-converter/i18n/fr.ts +4 -14
  80. package/src/tool/gps-coordinates-converter/i18n/id.ts +36 -37
  81. package/src/tool/gps-coordinates-converter/i18n/it.ts +35 -36
  82. package/src/tool/gps-coordinates-converter/i18n/ja.ts +19 -20
  83. package/src/tool/gps-coordinates-converter/i18n/ko.ts +20 -21
  84. package/src/tool/gps-coordinates-converter/i18n/nl.ts +33 -36
  85. package/src/tool/gps-coordinates-converter/i18n/pl.ts +19 -20
  86. package/src/tool/gps-coordinates-converter/i18n/pt.ts +19 -20
  87. package/src/tool/gps-coordinates-converter/i18n/ru.ts +19 -20
  88. package/src/tool/gps-coordinates-converter/i18n/sv.ts +19 -20
  89. package/src/tool/gps-coordinates-converter/i18n/tr.ts +19 -20
  90. package/src/tool/gps-coordinates-converter/i18n/zh.ts +20 -21
  91. package/src/tool/gps-coordinates-converter/seo.astro +2 -26
  92. package/src/tools.ts +3 -0
  93. package/src/types.ts +1 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjlmoya/utils-drones",
3
- "version": "1.14.0",
3
+ "version": "1.16.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -2,10 +2,11 @@ import type { DronesCategoryEntry } from '../types';
2
2
  import { droneFlightTime } from '../tool/drone-flight-time/index';
3
3
  import { antennaLengthCalculator } from '../tool/antenna-length-calculator/index';
4
4
  import { gpsCoordinatesConverter } from '../tool/gps-coordinates-converter/index';
5
+ import { dronePowerAnalyzer } from '../tool/drone-power-analyzer/index';
5
6
 
6
7
  export const dronesCategory: DronesCategoryEntry = {
7
8
  icon: 'mdi:drone',
8
- tools: [droneFlightTime, antennaLengthCalculator, gpsCoordinatesConverter],
9
+ tools: [droneFlightTime, antennaLengthCalculator, gpsCoordinatesConverter, dronePowerAnalyzer],
9
10
  i18n: {
10
11
  es: () => import('./i18n/es').then((m) => m.content),
11
12
  en: () => import('./i18n/en').then((m) => m.content),
package/src/entries.ts CHANGED
@@ -4,8 +4,11 @@ export { droneFlightTime } from './tool/drone-flight-time/entry';
4
4
  export type { DroneFlightTimeUI, DroneFlightTimeLocaleContent } from './tool/drone-flight-time/entry';
5
5
  export { gpsCoordinatesConverter } from './tool/gps-coordinates-converter/entry';
6
6
  export type { GpsCoordinatesConverterUI, GpsCoordinatesConverterLocaleContent } from './tool/gps-coordinates-converter/entry';
7
+ export { dronePowerAnalyzer } from './tool/drone-power-analyzer/entry';
8
+ export type { DronePowerAnalyzerUI, DronePowerAnalyzerLocaleContent } from './tool/drone-power-analyzer/entry';
7
9
  export { dronesCategory } from './category';
8
10
  import { antennaLengthCalculator } from './tool/antenna-length-calculator/entry';
9
11
  import { droneFlightTime } from './tool/drone-flight-time/entry';
10
12
  import { gpsCoordinatesConverter } from './tool/gps-coordinates-converter/entry';
11
- export const ALL_ENTRIES = [antennaLengthCalculator, droneFlightTime, gpsCoordinatesConverter];
13
+ import { dronePowerAnalyzer } from './tool/drone-power-analyzer/entry';
14
+ export const ALL_ENTRIES = [antennaLengthCalculator, droneFlightTime, gpsCoordinatesConverter, dronePowerAnalyzer];
package/src/index.ts CHANGED
@@ -19,4 +19,5 @@ export { ALL_ENTRIES, ALL_TOOLS } from './tools';
19
19
  export { DRONE_FLIGHT_TIME_TOOL } from './tool/drone-flight-time/index';
20
20
  export { ANTENNA_LENGTH_CALCULATOR_TOOL } from './tool/antenna-length-calculator/index';
21
21
  export { GPS_COORDINATES_CONVERTER_TOOL } from './tool/gps-coordinates-converter/index';
22
+ export { DRONE_POWER_ANALYZER_TOOL } from './tool/drone-power-analyzer/index';
22
23
 
@@ -34,18 +34,28 @@ export async function getStaticPaths() {
34
34
  ]),
35
35
  ) as Partial<Record<KnownLocale, string>>;
36
36
 
37
+ const firstLoader = entry.i18n.en ?? Object.values(entry.i18n)[0];
38
+ const englishSlug = firstLoader ? (await firstLoader()).slug : entry.id;
39
+
37
40
  for (const { locale, content } of localeContents) {
38
- const allToolsNav = await Promise.all(
39
- ALL_TOOLS.map(async ({ entry: navEntry }) => ({
40
- id: navEntry.id,
41
- title: (await navEntry.i18n[locale]!()).title,
42
- href: `/${locale}/${(await navEntry.i18n[locale]!()).slug}`,
43
- isActive: navEntry.id === entry.id,
44
- })),
45
- );
41
+ const allToolsNav = (
42
+ await Promise.all(
43
+ ALL_TOOLS.map(async ({ entry: navEntry }) => {
44
+ const loader = navEntry.i18n[locale] ?? navEntry.i18n.en;
45
+ if (!loader) return null;
46
+ const navContent = await loader();
47
+ return {
48
+ id: navEntry.id,
49
+ title: navContent.title,
50
+ href: `/${locale}/${navContent.slug}`,
51
+ isActive: navEntry.id === entry.id,
52
+ };
53
+ }),
54
+ )
55
+ ).filter(Boolean) as NavItem[];
46
56
  paths.push({
47
57
  params: { locale, slug: content.slug },
48
- props: { Component, locale, content, localeUrls, allToolsNav },
58
+ props: { Component, locale, content, localeUrls, allToolsNav, englishSlug },
49
59
  });
50
60
  }
51
61
  }
@@ -66,11 +76,16 @@ interface Props {
66
76
  content: ToolLocaleContent;
67
77
  localeUrls: Partial<Record<KnownLocale, string>>;
68
78
  allToolsNav: NavItem[];
79
+ englishSlug: string;
69
80
  }
70
81
 
71
- const { Component, locale, content, localeUrls, allToolsNav } = Astro.props;
82
+ const { Component, locale, content, localeUrls, allToolsNav, englishSlug } = Astro.props;
83
+
84
+ const cssFiles = import.meta.glob("../../tool/*/*.css", { query: "?raw", import: "default" });
85
+ const cssKey = Object.keys(cssFiles).find((k) => k.endsWith(`/${englishSlug}.css`));
86
+ const toolCss = cssKey ? await cssFiles[cssKey]() as string : "";
72
87
 
73
- const seoContent: UtilitySEOContent = { locale, sections: content.seo };
88
+ const seoContent: UtilitySEOContent = { locale, sections: content.seo ?? [] };
74
89
 
75
90
  const words = content.title.split(" ");
76
91
  const titleHighlight = words[0] || "";
@@ -89,8 +104,9 @@ const titleBase = words.slice(1).join(" ") || "";
89
104
  tools={allToolsNav}
90
105
  />
91
106
  <Fragment slot="head">
107
+ {toolCss ? <Fragment set:html={`<style is:inline>${toolCss}</style>`} /> : null}
92
108
  {
93
- content.schemas.map((schema: unknown) => (
109
+ ( content.schemas ?? []).map((schema: unknown) => (
94
110
  <script
95
111
  is:inline
96
112
  type="application/ld+json"
@@ -116,11 +132,11 @@ const titleBase = words.slice(1).join(" ") || "";
116
132
  </section>
117
133
 
118
134
  <section class="section-faq">
119
- <FAQSection items={content.faq} title={content.ui.faqTitle} inLanguage={locale} />
135
+ <FAQSection items={content.faq} inLanguage={locale} />
120
136
  </section>
121
137
 
122
138
  <section class="section-bibliography">
123
- <Bibliography links={content.bibliography} title={content.ui.bibliographyTitle} />
139
+ <Bibliography links={content.bibliography} />
124
140
  </section>
125
141
  </div>
126
142
  </PreviewLayout>
@@ -7,36 +7,18 @@ describe('Locale Completeness Validation', () => {
7
7
  describe(`Tool: ${tool.entry.id}`, () => {
8
8
  Object.keys(tool.entry.i18n).forEach((locale) => {
9
9
  describe(`Locale: ${locale}`, () => {
10
- it('faqTitle should be defined when faq items exist', async () => {
10
+ it('content should load without errors', async () => {
11
11
  const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
12
12
  const content = (await loader?.()) as ToolLocaleContent;
13
-
14
- if (content.faq.length > 0) {
15
- expect(
16
- content.faqTitle,
17
- `Tool "${tool.entry.id}" locale "${locale}" has ${content.faq.length} FAQ items but is missing faqTitle`,
18
- ).toBeTruthy();
19
- }
20
- });
21
-
22
- it('bibliographyTitle should be defined when bibliography items exist', async () => {
23
- const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
24
- const content = (await loader?.()) as ToolLocaleContent;
25
-
26
- if (content.bibliography.length > 0) {
27
- expect(
28
- content.bibliographyTitle,
29
- `Tool "${tool.entry.id}" locale "${locale}" has ${content.bibliography.length} bibliography items but is missing bibliographyTitle`,
30
- ).toBeTruthy();
31
- }
13
+ expect(content).toBeDefined();
32
14
  });
33
15
  });
34
16
  });
35
17
  });
36
18
  });
37
19
 
38
- it('all 3 tools registered', () => {
39
- expect(ALL_TOOLS.length).toBe(3);
20
+ it('all 4 tools registered', () => {
21
+ expect(ALL_TOOLS.length).toBe(4);
40
22
  });
41
23
  });
42
24
 
@@ -0,0 +1,56 @@
1
+ import type { ToolDefinition } from '../types';
2
+
3
+ export interface ToolExportValidationResult {
4
+ passed: boolean;
5
+ failures: string[];
6
+ }
7
+
8
+ function validateComponentType(
9
+ toolId: string,
10
+ componentName: string,
11
+ component: unknown,
12
+ failures: string[],
13
+ ): void {
14
+ if (typeof component !== 'function') {
15
+ failures.push(`${toolId}: ${componentName} is not a function (${typeof component})`);
16
+ }
17
+ }
18
+
19
+ async function validateComponentExecution(
20
+ toolId: string,
21
+ componentName: string,
22
+ fn: () => Promise<unknown>,
23
+ failures: string[],
24
+ ): Promise<void> {
25
+ try {
26
+ const result = await fn();
27
+ if (!result || typeof result !== 'object') {
28
+ failures.push(`${toolId}: ${componentName} import returned invalid result`);
29
+ }
30
+ } catch (error) {
31
+ failures.push(`${toolId}: ${componentName} execution error - ${error instanceof Error ? error.message : 'unknown'}`);
32
+ }
33
+ }
34
+
35
+ export async function validateToolExports(tools: ToolDefinition[]): Promise<ToolExportValidationResult> {
36
+ const failures: string[] = [];
37
+
38
+ for (const tool of tools) {
39
+ validateComponentType(tool.entry.id, 'Component', tool.Component, failures);
40
+ validateComponentType(tool.entry.id, 'SEOComponent', tool.SEOComponent, failures);
41
+ validateComponentType(tool.entry.id, 'BibliographyComponent', tool.BibliographyComponent, failures);
42
+
43
+ const componentFn = tool.Component as () => Promise<unknown>;
44
+ const seoFn = tool.SEOComponent as () => Promise<unknown>;
45
+ const bibFn = tool.BibliographyComponent as () => Promise<unknown>;
46
+
47
+ await validateComponentExecution(tool.entry.id, 'Component', componentFn, failures);
48
+ await validateComponentExecution(tool.entry.id, 'SEOComponent', seoFn, failures);
49
+ await validateComponentExecution(tool.entry.id, 'BibliographyComponent', bibFn, failures);
50
+ }
51
+
52
+ return {
53
+ passed: failures.length === 0,
54
+ failures,
55
+ };
56
+ }
@@ -0,0 +1,34 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ALL_TOOLS } from '../tools';
3
+ import { validateToolExports } from './shared-test-helpers';
4
+
5
+ describe('Tool Exports Pattern Validation', () => {
6
+ describe('Component Exports Format', () => {
7
+ ALL_TOOLS.forEach((tool) => {
8
+ it(`${tool.entry.id}: Component should be a lazy-loaded function`, () => {
9
+ expect(typeof tool.Component).toBe('function');
10
+ expect(tool.Component).toBeInstanceOf(Function);
11
+ });
12
+
13
+ it(`${tool.entry.id}: SEOComponent should be a lazy-loaded function`, () => {
14
+ expect(typeof tool.SEOComponent).toBe('function');
15
+ expect(tool.SEOComponent).toBeInstanceOf(Function);
16
+ });
17
+
18
+ it(`${tool.entry.id}: BibliographyComponent should be a lazy-loaded function`, () => {
19
+ expect(typeof tool.BibliographyComponent).toBe('function');
20
+ expect(tool.BibliographyComponent).toBeInstanceOf(Function);
21
+ });
22
+ });
23
+ });
24
+
25
+ describe('Dynamic Import Validation', () => {
26
+ it('all tools must have functional dynamic imports', async () => {
27
+ const result = await validateToolExports(ALL_TOOLS);
28
+ if (!result.passed) {
29
+ throw new Error(`Tool export validation failed:\n${result.failures.join('\n')}`);
30
+ }
31
+ expect(result.passed).toBe(true);
32
+ });
33
+ });
34
+ });
@@ -4,8 +4,8 @@ import { dronesCategory } from '../data';
4
4
 
5
5
  describe('Tool Validation Suite', () => {
6
6
  describe('Library Registration', () => {
7
- it('should have 3 tools in ALL_TOOLS', () => {
8
- expect(ALL_TOOLS.length).toBe(3);
7
+ it('should have 4 tools in ALL_TOOLS', () => {
8
+ expect(ALL_TOOLS.length).toBe(4);
9
9
  });
10
10
 
11
11
  it('dronesCategory should be defined', () => {
@@ -1,14 +1,6 @@
1
1
  ---
2
- import { Bibliography } from '@jjlmoya/utils-shared';
3
- import { antennaLengthCalculator } from './index';
4
- import type { KnownLocale } from '../../types';
5
-
6
- interface Props {
7
- locale?: KnownLocale;
8
- }
9
-
10
- const { locale = 'es' } = Astro.props;
11
- const content = await antennaLengthCalculator.i18n[locale]?.();
2
+ import { Bibliography as BibliographyComponent } from '@jjlmoya/utils-shared';
3
+ import { bibliography } from './bibliography';
12
4
  ---
13
5
 
14
- {content && <Bibliography links={content.bibliography} />}
6
+ <BibliographyComponent links={bibliography} />
@@ -0,0 +1,6 @@
1
+ import type { BibliographyEntry } from '../../types';
2
+
3
+ export const bibliography: BibliographyEntry[] = [
4
+ { name: 'The Quarter-Wave Monopole', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
5
+ { name: 'Velocity Factor of Transmission Lines', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
6
+ ];
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'rf-antennenlaenge-rechner';
5
6
  const title = 'RF Antennenlaenge Rechner fur FPV Dipole und Peitschen';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'Häufig gestellte Fragen',
84
- bibliographyTitle: 'Literaturhinweise',
85
84
  ui: {
86
- faqTitle: 'Häufig gestellte Fragen',
87
- bibliographyTitle: 'Literaturhinweise',
88
85
  signalParameters: 'Signalparameter',
89
86
  antennaType: 'Antennentyp',
90
87
  dipole: 'Dipol (1/2 λ)',
@@ -250,10 +247,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
250
247
  answer: 'Dickere Drähte haben eine größere Bandbreite (sie sind weniger kritisch hinsichtlich der genauen Frequenz), aber ihr Verkürzungsfaktor ändert sich leicht. Für die meisten FPV-Drohnen ist handelsüblicher 20-22AWG-Draht ideal.',
251
248
  },
252
249
  ],
253
- bibliography: [
254
- { name: 'Der Viertelwellen-Monopol', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
255
- { name: 'Verkürzungsfaktor von Übertragungsleitungen', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
256
- ],
250
+ bibliography,
257
251
  howTo: [
258
252
  {
259
253
  name: 'Frequenz auswählen',
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'antenna-length-calculator';
5
6
  const title = 'RF Antenna Length Calculator for FPV Dipoles and Whips';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'Frequently Asked Questions',
84
- bibliographyTitle: 'Bibliographic References',
85
84
  ui: {
86
- faqTitle: 'Frequently Asked Questions',
87
- bibliographyTitle: 'Bibliographic References',
88
85
  signalParameters: 'Signal Parameters',
89
86
  antennaType: 'Antenna Type',
90
87
  dipole: 'Dipole (1/2 λ)',
@@ -233,10 +230,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
233
230
  },
234
231
  ],
235
232
  faq: faqItems,
236
- bibliography: [
237
- { name: 'The Quarter-Wave Monopole', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
238
- { name: 'Velocity Factor of Transmission Lines', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
239
- ],
233
+ bibliography,
240
234
  howTo: howToSteps,
241
235
  schemas,
242
236
  };
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'calculadora-longitud-antena';
5
6
  const title = 'Calculadora de Longitud de Antena RF para Dipolos y Látigos FPV';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'Preguntas Frecuentes',
84
- bibliographyTitle: 'Referencias Bibliográficas',
85
84
  ui: {
86
- faqTitle: 'Preguntas Frecuentes',
87
- bibliographyTitle: 'Referencias Bibliográficas',
88
85
  signalParameters: 'Parámetros de Señal',
89
86
  antennaType: 'Tipo de Antena',
90
87
  dipole: 'Dipolo (1/2 λ)',
@@ -233,10 +230,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
233
230
  },
234
231
  ],
235
232
  faq: faqItems,
236
- bibliography: [
237
- { name: 'The Quarter-Wave Monopole', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
238
- { name: 'Velocity Factor of Transmission Lines', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
239
- ],
233
+ bibliography,
240
234
  howTo: howToSteps,
241
235
  schemas,
242
236
  };
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'calculateur-longueur-antenne';
5
6
  const title = 'Calculateur de Longueur d\'Antenne RF pour Dipôles et Fouets FPV';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'Foire Aux Questions',
84
- bibliographyTitle: 'Références Bibliographiques',
85
84
  ui: {
86
- faqTitle: 'Foire Aux Questions',
87
- bibliographyTitle: 'Références Bibliographiques',
88
85
  signalParameters: 'Paramètres du Signal',
89
86
  antennaType: 'Type d\'Antenne',
90
87
  dipole: 'Dipôle (1/2 λ)',
@@ -233,10 +230,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
233
230
  },
234
231
  ],
235
232
  faq: faqItems,
236
- bibliography: [
237
- { name: 'Le Monopole Quart d\'Onde', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
238
- { name: 'Facteur de Vélocité des Lignes de Transmission', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
239
- ],
233
+ bibliography,
240
234
  howTo: howToSteps,
241
235
  schemas,
242
236
  };
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'kalkulator-panjang-antena';
5
6
  const title = 'Kalkulator Panjang Antena RF untuk FPV Dipol dan Whip';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'Pertanyaan yang Sering Diajukan',
84
- bibliographyTitle: 'Referensi Bibliografi',
85
84
  ui: {
86
- faqTitle: 'Pertanyaan yang Sering Diajukan',
87
- bibliographyTitle: 'Referensi Bibliografi',
88
85
  signalParameters: 'Parameter Sinyal',
89
86
  antennaType: 'Jenis Antena',
90
87
  dipole: 'Dipol (1/2 λ)',
@@ -233,10 +230,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
233
230
  },
234
231
  ],
235
232
  faq: faqItems,
236
- bibliography: [
237
- { name: 'The Quarter-Wave Monopole', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
238
- { name: 'Velocity Factor of Transmission Lines', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
239
- ],
233
+ bibliography,
240
234
  howTo: howToSteps,
241
235
  schemas,
242
236
  };
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'calcolatore-lunghezza-antenna';
5
6
  const title = 'Calcolatore di Lunghezza Antenna RF per Dipoli e Stili FPV';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'Domande Frequenti',
84
- bibliographyTitle: 'Riferimenti Bibliografici',
85
84
  ui: {
86
- faqTitle: 'Domande Frequenti',
87
- bibliographyTitle: 'Riferimenti Bibliografici',
88
85
  signalParameters: 'Parametri del Segnale',
89
86
  antennaType: 'Tipo di Antenna',
90
87
  dipole: 'Dipolo (1/2 λ)',
@@ -250,10 +247,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
250
247
  answer: 'I fili più spessi hanno una larghezza di banda maggiore (sono meno critici riguardo alla frequenza esatta), ma il loro fattore di velocità cambia leggermente. Per la maggior parte dei droni FPV, un filo standard da 20-22AWG è l\'ideale.',
251
248
  },
252
249
  ],
253
- bibliography: [
254
- { name: 'Il Monopolo Quarto d\'Onda', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
255
- { name: 'Fattore di Velocità nelle Linee di Trasmissione', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
256
- ],
250
+ bibliography,
257
251
  howTo: [
258
252
  {
259
253
  name: 'Seleziona Frequenza',
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'antenna-length-calculator';
5
6
  const title = 'FPVダイポールおよびホイップ用RFアンテナ長計算機';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'よくある質問',
84
- bibliographyTitle: '参考文献',
85
84
  ui: {
86
- faqTitle: 'よくある質問',
87
- bibliographyTitle: '参考文献',
88
85
  signalParameters: '信号パラメータ',
89
86
  antennaType: 'アンテナタイプ',
90
87
  dipole: 'ダイポール (1/2 λ)',
@@ -250,10 +247,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
250
247
  answer: '太い線は帯域幅が広くなります(より広い周波数で機能します)が、短縮率がわずかに変化します。ほとんどのFPVドローンにとっては、標準的な20-22AWGの線材が最適です。',
251
248
  },
252
249
  ],
253
- bibliography: [
254
- { name: '1/4波長モノポールアンテナ理論', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
255
- { name: '伝送路の速度係数(Velocity factor)', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
256
- ],
250
+ bibliography,
257
251
  howTo: [
258
252
  {
259
253
  name: '周波数を選択',
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'antenna-length-calculator';
5
6
  const title = 'FPV 다이폴 및 휩용 RF 안테나 길이 계산기';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: '자주 묻는 질문',
84
- bibliographyTitle: '참고 문헌',
85
84
  ui: {
86
- faqTitle: '자주 묻는 질문',
87
- bibliographyTitle: '참고 문헌',
88
85
  signalParameters: '신호 매개변수',
89
86
  antennaType: '안테나 유형',
90
87
  dipole: '다이폴 (1/2 λ)',
@@ -250,10 +247,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
250
247
  answer: '더 두꺼운 전선은 대역폭이 더 넓고(정확한 주파수 의존성이 덜 중요함) 단축 속도 계수가 약간 변경됩니다. 대부분의 FPV 드론에는 표준 20-22AWG 와이어가 이상적입니다.',
251
248
  },
252
249
  ],
253
- bibliography: [
254
- { name: '1/4 파장 모노폴 기초 지식', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
255
- { name: '전송선로의 속도 계수', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
256
- ],
250
+ bibliography,
257
251
  howTo: [
258
252
  {
259
253
  name: '주파수 선택',
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'rf-antenne-lengte-calculator';
5
6
  const title = 'RF Antenne Lengte Calculator voor FPV Dipolen en Zwepen';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'Veelgestelde Vragen',
84
- bibliographyTitle: 'Bibliografische Referenties',
85
84
  ui: {
86
- faqTitle: 'Veelgestelde Vragen',
87
- bibliographyTitle: 'Bibliografische Referenties',
88
85
  signalParameters: 'Signaalparameters',
89
86
  antennaType: 'Antenne Type',
90
87
  dipole: 'Dipool (1/2 λ)',
@@ -250,10 +247,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
250
247
  answer: 'Zeker weten, zo breder dan hoe meer een band kan uit rekken qua zending op het spectrum. Meeste mensen gaan in de racerij en vliegerij het meest courante vinden met een doorsnee 20 tot 22 Amerikaanse Gauge kabeling met wat bijgaande snelheid variabelen.',
251
248
  },
252
249
  ],
253
- bibliography: [
254
- { name: 'Kwartgolf antenne en Monopolen in de theorie', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
255
- { name: 'Impact en vertaling van kabel Snelheids factor op wiki.', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
256
- ],
250
+ bibliography,
257
251
  howTo: [
258
252
  {
259
253
  name: 'Stel jouw juiste Hertz ratio (Frequentie) in.',
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'kalkulator-dlugosci-anteny';
5
6
  const title = 'Kalkulator Dlugosci Anteny RF dla Dipoli i Batow FPV';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'Często Zadawane Pytania',
84
- bibliographyTitle: 'Bibliografia',
85
84
  ui: {
86
- faqTitle: 'Często Zadawane Pytania',
87
- bibliographyTitle: 'Bibliografia',
88
85
  signalParameters: 'Parametry Sygnału',
89
86
  antennaType: 'Typ Anteny',
90
87
  dipole: 'Dipol (1/2 λ)',
@@ -250,10 +247,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
250
247
  answer: 'Szerokość pomaga zatuszować niedokładną amatorkę w zrobionej długości , aczkolwiek spowalnia też w pewnych obszarach przepust w Velocity - a więc pożądana jakość wyrobienia by awg było w ramach w strefie u standart ok . 22.',
251
248
  },
252
249
  ],
253
- bibliography: [
254
- { name: 'Opracowanie Badawcze Należytego Odbicia, tzw. Ćwierćfalowa (1/4 ) jako monopol', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
255
- { name: 'Zależności Faktorów oraz Zmian o Velocity jako opór prędkość.', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
256
- ],
250
+ bibliography,
257
251
  howTo: [
258
252
  {
259
253
  name: 'Rzetelny Wybór Potrzeb',
@@ -1,5 +1,6 @@
1
1
  import type { AntennaLengthCalculatorLocaleContent } from '../index';
2
2
  import type { WithContext, SoftwareApplication, FAQPage, HowTo } from 'schema-dts';
3
+ import { bibliography } from '../bibliography';
3
4
 
4
5
  const slug = 'calculadora-comprimento-antena';
5
6
  const title = 'Calculadora de Comprimento de Antena RF para Dipolos e Chicotes FPV';
@@ -80,11 +81,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
80
81
  slug,
81
82
  title,
82
83
  description,
83
- faqTitle: 'Perguntas Frequentes',
84
- bibliographyTitle: 'Referências Bibliográficas',
85
84
  ui: {
86
- faqTitle: 'Perguntas Frequentes',
87
- bibliographyTitle: 'Referências Bibliográficas',
88
85
  signalParameters: 'Parâmetros de Sinal',
89
86
  antennaType: 'Tipo de Antena',
90
87
  dipole: 'Dipolo (1/2 λ)',
@@ -250,10 +247,7 @@ export const content: AntennaLengthCalculatorLocaleContent = {
250
247
  answer: 'Total e perfeitamente, dado ser cabos muito grossos ajudam sim no aumento tolerável numa faixa de transmissão ou canal do recetor... Não fujas das limitações do usual cabo awg em 22 de espessura.',
251
248
  },
252
249
  ],
253
- bibliography: [
254
- { name: 'Em prol do Estudo Cientifico - Antenna Theory', url: 'https://www.antenna-theory.com/antennas/monopole.php' },
255
- { name: 'Detalhes Acerca de Velocity ou do Fator', url: 'https://en.wikipedia.org/wiki/Velocity_factor' },
256
- ],
250
+ bibliography,
257
251
  howTo: [
258
252
  {
259
253
  name: 'Regulação por Defasagem na Casa Alvo das Medidas (Mhz)',