@jjlmoya/utils-hardware 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.
- package/package.json +1 -1
- package/src/category/index.ts +2 -1
- package/src/entries.ts +4 -1
- package/src/index.ts +1 -0
- package/src/pages/[locale]/[slug].astro +28 -12
- package/src/tests/locale_completeness.test.ts +6 -20
- package/src/tests/shared-test-helpers.ts +56 -0
- package/src/tests/tool_exports.test.ts +34 -0
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/batteryHealthEstimator/bibliography.ts +13 -0
- package/src/tool/batteryHealthEstimator/i18n/de.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/en.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/es.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/fr.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/id.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/it.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/ja.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/ko.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/nl.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/pl.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/pt.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/ru.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/sv.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/tr.ts +2 -12
- package/src/tool/batteryHealthEstimator/i18n/zh.ts +2 -12
- package/src/tool/batteryHealthEstimator/lithium-battery-health-calculator.css +90 -3
- package/src/tool/batteryHealthEstimator/seo.astro +3 -2
- package/src/tool/deadPixelTest/bibliography.ts +13 -0
- package/src/tool/deadPixelTest/dead-pixel-tester.css +33 -6
- package/src/tool/deadPixelTest/i18n/de.ts +2 -12
- package/src/tool/deadPixelTest/i18n/en.ts +2 -12
- package/src/tool/deadPixelTest/i18n/es.ts +2 -12
- package/src/tool/deadPixelTest/i18n/fr.ts +2 -12
- package/src/tool/deadPixelTest/i18n/id.ts +2 -12
- package/src/tool/deadPixelTest/i18n/it.ts +2 -12
- package/src/tool/deadPixelTest/i18n/ja.ts +2 -12
- package/src/tool/deadPixelTest/i18n/ko.ts +2 -12
- package/src/tool/deadPixelTest/i18n/nl.ts +2 -12
- package/src/tool/deadPixelTest/i18n/pl.ts +2 -12
- package/src/tool/deadPixelTest/i18n/pt.ts +2 -12
- package/src/tool/deadPixelTest/i18n/ru.ts +2 -12
- package/src/tool/deadPixelTest/i18n/sv.ts +2 -12
- package/src/tool/deadPixelTest/i18n/tr.ts +2 -12
- package/src/tool/deadPixelTest/i18n/zh.ts +2 -12
- package/src/tool/deadPixelTest/seo.astro +3 -2
- package/src/tool/gamepadTest/bibliography.ts +12 -0
- package/src/tool/gamepadTest/gamepad-test.css +88 -3
- package/src/tool/gamepadTest/i18n/de.ts +2 -12
- package/src/tool/gamepadTest/i18n/en.ts +2 -12
- package/src/tool/gamepadTest/i18n/es.ts +2 -12
- package/src/tool/gamepadTest/i18n/fr.ts +2 -12
- package/src/tool/gamepadTest/i18n/id.ts +2 -12
- package/src/tool/gamepadTest/i18n/it.ts +2 -12
- package/src/tool/gamepadTest/i18n/ja.ts +2 -12
- package/src/tool/gamepadTest/i18n/ko.ts +2 -12
- package/src/tool/gamepadTest/i18n/nl.ts +2 -12
- package/src/tool/gamepadTest/i18n/pl.ts +2 -12
- package/src/tool/gamepadTest/i18n/pt.ts +2 -12
- package/src/tool/gamepadTest/i18n/ru.ts +2 -12
- package/src/tool/gamepadTest/i18n/sv.ts +2 -12
- package/src/tool/gamepadTest/i18n/tr.ts +2 -12
- package/src/tool/gamepadTest/i18n/zh.ts +2 -12
- package/src/tool/gamepadTest/seo.astro +3 -2
- package/src/tool/gamepadVibrationTester/bibliography.ts +13 -0
- package/src/tool/gamepadVibrationTester/gamepad-vibration-tester.css +124 -4
- package/src/tool/gamepadVibrationTester/i18n/de.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/en.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/es.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/fr.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/id.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/it.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/ja.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/ko.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/nl.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/pl.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/pt.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/ru.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/sv.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/tr.ts +2 -12
- package/src/tool/gamepadVibrationTester/i18n/zh.ts +2 -12
- package/src/tool/gamepadVibrationTester/seo.astro +3 -2
- package/src/tool/keyboardTest/bibliography.ts +13 -0
- package/src/tool/keyboardTest/i18n/de.ts +2 -12
- package/src/tool/keyboardTest/i18n/en.ts +2 -12
- package/src/tool/keyboardTest/i18n/es.ts +2 -12
- package/src/tool/keyboardTest/i18n/fr.ts +2 -12
- package/src/tool/keyboardTest/i18n/id.ts +2 -12
- package/src/tool/keyboardTest/i18n/it.ts +2 -12
- package/src/tool/keyboardTest/i18n/ja.ts +2 -12
- package/src/tool/keyboardTest/i18n/ko.ts +2 -12
- package/src/tool/keyboardTest/i18n/nl.ts +2 -12
- package/src/tool/keyboardTest/i18n/pl.ts +2 -12
- package/src/tool/keyboardTest/i18n/pt.ts +2 -12
- package/src/tool/keyboardTest/i18n/ru.ts +2 -12
- package/src/tool/keyboardTest/i18n/sv.ts +2 -12
- package/src/tool/keyboardTest/i18n/tr.ts +2 -12
- package/src/tool/keyboardTest/i18n/zh.ts +2 -12
- package/src/tool/keyboardTest/keyboard-test.css +46 -3
- package/src/tool/keyboardTest/seo.astro +3 -2
- package/src/tool/mousePollingTest/bibliography.ts +13 -0
- package/src/tool/mousePollingTest/i18n/de.ts +2 -12
- package/src/tool/mousePollingTest/i18n/en.ts +2 -12
- package/src/tool/mousePollingTest/i18n/es.ts +2 -12
- package/src/tool/mousePollingTest/i18n/fr.ts +2 -12
- package/src/tool/mousePollingTest/i18n/id.ts +2 -12
- package/src/tool/mousePollingTest/i18n/it.ts +2 -12
- package/src/tool/mousePollingTest/i18n/ja.ts +2 -12
- package/src/tool/mousePollingTest/i18n/ko.ts +2 -12
- package/src/tool/mousePollingTest/i18n/nl.ts +2 -12
- package/src/tool/mousePollingTest/i18n/pl.ts +2 -12
- package/src/tool/mousePollingTest/i18n/pt.ts +2 -12
- package/src/tool/mousePollingTest/i18n/ru.ts +2 -12
- package/src/tool/mousePollingTest/i18n/sv.ts +2 -12
- package/src/tool/mousePollingTest/i18n/tr.ts +2 -12
- package/src/tool/mousePollingTest/i18n/zh.ts +2 -12
- package/src/tool/mousePollingTest/mouse-polling-rate-test.css +27 -5
- package/src/tool/mousePollingTest/seo.astro +3 -2
- package/src/tool/refreshRateDetector/bibliography.astro +14 -0
- package/src/tool/refreshRateDetector/bibliography.ts +20 -0
- package/src/tool/refreshRateDetector/component.astro +206 -0
- package/src/tool/refreshRateDetector/entry.ts +29 -0
- package/src/tool/refreshRateDetector/i18n/de.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/en.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/es.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/fr.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/id.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/it.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/ja.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/ko.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/nl.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/pl.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/pt.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/ru.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/sv.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/tr.ts +196 -0
- package/src/tool/refreshRateDetector/i18n/zh.ts +196 -0
- package/src/tool/refreshRateDetector/index.ts +11 -0
- package/src/tool/refreshRateDetector/monitor-refresh-rate-detector.css +342 -0
- package/src/tool/refreshRateDetector/seo.astro +15 -0
- package/src/tool/refreshRateDetector/ui.ts +24 -0
- package/src/tool/toneGenerator/bibliography.ts +13 -0
- package/src/tool/toneGenerator/i18n/de.ts +2 -12
- package/src/tool/toneGenerator/i18n/en.ts +2 -12
- package/src/tool/toneGenerator/i18n/es.ts +2 -12
- package/src/tool/toneGenerator/i18n/fr.ts +2 -12
- package/src/tool/toneGenerator/i18n/id.ts +2 -12
- package/src/tool/toneGenerator/i18n/it.ts +2 -12
- package/src/tool/toneGenerator/i18n/ja.ts +2 -12
- package/src/tool/toneGenerator/i18n/ko.ts +2 -12
- package/src/tool/toneGenerator/i18n/nl.ts +2 -12
- package/src/tool/toneGenerator/i18n/pl.ts +2 -12
- package/src/tool/toneGenerator/i18n/pt.ts +2 -12
- package/src/tool/toneGenerator/i18n/ru.ts +2 -12
- package/src/tool/toneGenerator/i18n/sv.ts +2 -12
- package/src/tool/toneGenerator/i18n/tr.ts +2 -12
- package/src/tool/toneGenerator/i18n/zh.ts +2 -12
- package/src/tool/toneGenerator/seo.astro +3 -2
- package/src/tool/toneGenerator/tone-frequency-generator.css +25 -3
- package/src/tools.ts +2 -1
package/package.json
CHANGED
package/src/category/index.ts
CHANGED
|
@@ -6,10 +6,11 @@ import { probadorVibracionMando } from '../tool/gamepadVibrationTester/index';
|
|
|
6
6
|
import { testRaton } from '../tool/mousePollingTest/index';
|
|
7
7
|
import { estimadorSaludBateria } from '../tool/batteryHealthEstimator/index';
|
|
8
8
|
import { toneGenerator } from '../tool/toneGenerator/index';
|
|
9
|
+
import { refreshRateDetector } from '../tool/refreshRateDetector/index';
|
|
9
10
|
|
|
10
11
|
export const hardwareCategory: HardwareCategoryEntry = {
|
|
11
12
|
icon: 'mdi:memory',
|
|
12
|
-
tools: [pixelesPantalla, testTeclado, testMando, probadorVibracionMando, testRaton, estimadorSaludBateria, toneGenerator],
|
|
13
|
+
tools: [pixelesPantalla, testTeclado, testMando, probadorVibracionMando, testRaton, estimadorSaludBateria, toneGenerator, refreshRateDetector],
|
|
13
14
|
i18n: {
|
|
14
15
|
en: () => import('./i18n/en').then((m) => m.content),
|
|
15
16
|
es: () => import('./i18n/es').then((m) => m.content),
|
package/src/entries.ts
CHANGED
|
@@ -12,6 +12,8 @@ export { testRaton } from './tool/mousePollingTest/entry';
|
|
|
12
12
|
export type { TestRatonLocaleContent } from './tool/mousePollingTest/entry';
|
|
13
13
|
export { toneGenerator } from './tool/toneGenerator/entry';
|
|
14
14
|
export type { ToneGeneratorLocaleContent } from './tool/toneGenerator/entry';
|
|
15
|
+
export { refreshRateDetector } from './tool/refreshRateDetector/entry';
|
|
16
|
+
export type { RefreshRateDetectorLocaleContent } from './tool/refreshRateDetector/entry';
|
|
15
17
|
export { hardwareCategory } from './category';
|
|
16
18
|
import { estimadorSaludBateria } from './tool/batteryHealthEstimator/entry';
|
|
17
19
|
import { pixelesPantalla } from './tool/deadPixelTest/entry';
|
|
@@ -20,4 +22,5 @@ import { probadorVibracionMando } from './tool/gamepadVibrationTester/entry';
|
|
|
20
22
|
import { testTeclado } from './tool/keyboardTest/entry';
|
|
21
23
|
import { testRaton } from './tool/mousePollingTest/entry';
|
|
22
24
|
import { toneGenerator } from './tool/toneGenerator/entry';
|
|
23
|
-
|
|
25
|
+
import { refreshRateDetector } from './tool/refreshRateDetector/entry';
|
|
26
|
+
export const ALL_ENTRIES = [estimadorSaludBateria, pixelesPantalla, testMando, probadorVibracionMando, testTeclado, testRaton, toneGenerator, refreshRateDetector];
|
package/src/index.ts
CHANGED
|
@@ -24,3 +24,4 @@ export { PROBADOR_VIBRACION_MANDO_TOOL } from './tool/gamepadVibrationTester/ind
|
|
|
24
24
|
export { TEST_RATON_TOOL } from './tool/mousePollingTest/index';
|
|
25
25
|
export { ESTIMADOR_SALUD_BATERIA_TOOL } from './tool/batteryHealthEstimator/index';
|
|
26
26
|
export { TONE_GENERATOR_TOOL } from './tool/toneGenerator/index';
|
|
27
|
+
export { REFRESH_RATE_DETECTOR_TOOL } from './tool/refreshRateDetector/index';
|
|
@@ -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 =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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"
|
|
@@ -7,28 +7,14 @@ 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('
|
|
10
|
+
it('bibliography should be defined', async () => {
|
|
11
11
|
const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
|
|
12
12
|
const content = (await loader?.()) as ToolLocaleContent;
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
}
|
|
14
|
+
expect(
|
|
15
|
+
content.bibliography,
|
|
16
|
+
`Tool "${tool.entry.id}" locale "${locale}" is missing bibliography`,
|
|
17
|
+
).toBeDefined();
|
|
32
18
|
});
|
|
33
19
|
});
|
|
34
20
|
});
|
|
@@ -36,7 +22,7 @@ describe('Locale Completeness Validation', () => {
|
|
|
36
22
|
});
|
|
37
23
|
|
|
38
24
|
it('all 10 tools registered', () => {
|
|
39
|
-
expect(ALL_TOOLS.length).toBe(
|
|
25
|
+
expect(ALL_TOOLS.length).toBe(8);
|
|
40
26
|
});
|
|
41
27
|
});
|
|
42
28
|
|
|
@@ -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 { hardwareCategory } from '../data';
|
|
|
4
4
|
|
|
5
5
|
describe('Tool Validation Suite', () => {
|
|
6
6
|
describe('Library Registration', () => {
|
|
7
|
-
it('should have
|
|
8
|
-
expect(ALL_TOOLS.length).toBe(
|
|
7
|
+
it('should have 8 tools in ALL_TOOLS', () => {
|
|
8
|
+
expect(ALL_TOOLS.length).toBe(8);
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
it('hardwareCategory should be defined', () => {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BibliographyEntry } from '../../../types';
|
|
2
|
+
|
|
3
|
+
export const bibliography: BibliographyEntry[] = [
|
|
4
|
+
|
|
5
|
+
{
|
|
6
|
+
name: 'Journal of Power Sources',
|
|
7
|
+
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
11
|
+
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
12
|
+
},
|
|
13
|
+
];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'lithium-batterie-gesundheitsrechner';
|
|
6
7
|
const title = 'Rechner für den Zustand von Lithium Batterien';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Häufig gestellte Fragen',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'Referenzen',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'Die Chemie der Zeit: Warum Lithium Batterien sterben', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'lithium-battery-health-calculator';
|
|
6
7
|
const title = 'Lithium Battery Health Calculator';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Frequently Asked Questions',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'References',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'The chemistry of time: why lithium batteries die', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'estimador-salud-bateria';
|
|
6
7
|
const title = 'Calculadora de Salud de Batería de Litio';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Preguntas Frecuentes',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'Referencias',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'La química del tiempo: por qué mueren las baterías de litio', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'calculateur-sante-batterie-lithium';
|
|
6
7
|
const title = 'Calculateur de Santé de Batterie Lithium';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Questions Fréquentes',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'Références',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'La chimie du temps : pourquoi les batteries lithium meurent', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'kalkulator-kesehatan-baterai-lithium';
|
|
6
7
|
const title = 'Kalkulator Kesehatan Baterai Lithium';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Pertanyaan yang Sering Diajukan',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'Referensi',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'Kimia waktu: mengapa baterai lithium mati', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'calcolatore-salute-batteria-litio';
|
|
6
7
|
const title = 'Calcolatore Salute della Batteria al Litio';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Domande Frequenti',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'Riferimenti',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'La chimica del tempo: perché le batterie al litio muoiono', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'lithium-battery-health-calculator';
|
|
6
7
|
const title = 'リチウムイオン電池寿命診断ツール';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'よくある質問',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: '参考文献',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: '時間の化学:リチウム電池が寿命を迎える理由', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'lithium-battery-health-calculator';
|
|
6
7
|
const title = '리튬 배터리 수명 진단 계산기';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: '자주 묻는 질문',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: '참고 문헌',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: '시간의 화학: 리튬 배터리가 노화되는 이유', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'lithium-batterij-gezondheidscalculator';
|
|
6
7
|
const title = 'Lithium Batterij Gezondheidscalculator';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Veelgestelde Vragen',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'Referenties',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'De chemie van tijd: waarom lithiumbatterijen doodgaan', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'kalkulator-stanu-baterii-litowej';
|
|
6
7
|
const title = 'Kalkulator Stanu Baterii Litowej';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Często Zadawane Pytania',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'Referencje',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'Chemia czasu: dlaczego baterie litowe umierają', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'calculadora-saude-bateria-litio';
|
|
6
7
|
const title = 'Calculadora de Saúde da Bateria de Lítio';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Perguntas Frequentes',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'Referências',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'A química do tempo: por que as baterias de lítio morrem', level: 2 },
|
|
107
97
|
{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
2
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
3
|
import type { EstimadorSaludBateriaUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
4
5
|
|
|
5
6
|
const slug = 'kalkulyator-sostoyaniya-litievoj-batarei';
|
|
6
7
|
const title = 'Калькулятор Состояния Литиевой Батареи';
|
|
@@ -87,21 +88,10 @@ export const content: ToolLocaleContent<EstimadorSaludBateriaUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Часто задаваемые вопросы',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
bibliographyTitle: 'Ссылки',
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Journal of Power Sources',
|
|
96
|
-
url: 'https://www.sciencedirect.com/journal/journal-of-power-sources',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'IEEE Xplore — Lithium-Ion Battery Life Prediction',
|
|
100
|
-
url: 'https://ieeexplore.ieee.org/abstract/document/11090151',
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
92
|
howTo: howToData,
|
|
104
93
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
94
|
+
bibliography,
|
|
105
95
|
seo: [
|
|
106
96
|
{ type: 'title', text: 'Химия времени: почему умирают литиевые батареи', level: 2 },
|
|
107
97
|
{
|