@jjlmoya/utils-finance 1.15.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/pages/[locale]/[slug].astro +29 -13
- package/src/tests/locale_completeness.test.ts +6 -16
- package/src/tests/shared-test-helpers.ts +56 -0
- package/src/tests/tool_exports.test.ts +34 -0
- package/src/tool/compoundInterest/bibliography.ts +20 -0
- package/src/tool/compoundInterest/entry.ts +2 -0
- package/src/tool/compoundInterest/i18n/de.ts +3 -16
- package/src/tool/compoundInterest/i18n/en.ts +3 -20
- package/src/tool/compoundInterest/i18n/es.ts +2 -20
- package/src/tool/compoundInterest/i18n/fr.ts +3 -20
- package/src/tool/compoundInterest/i18n/id.ts +3 -16
- package/src/tool/compoundInterest/i18n/it.ts +3 -16
- package/src/tool/compoundInterest/i18n/ja.ts +3 -16
- package/src/tool/compoundInterest/i18n/ko.ts +3 -16
- package/src/tool/compoundInterest/i18n/nl.ts +3 -16
- package/src/tool/compoundInterest/i18n/pl.ts +2 -16
- package/src/tool/compoundInterest/i18n/pt.ts +3 -16
- package/src/tool/compoundInterest/i18n/ru.ts +3 -16
- package/src/tool/compoundInterest/i18n/sv.ts +3 -16
- package/src/tool/compoundInterest/i18n/tr.ts +3 -16
- package/src/tool/compoundInterest/i18n/zh.ts +3 -16
- package/src/tool/compoundInterest/seo.astro +2 -1
- package/src/tool/courtFeeCalculator/bibliography.ts +16 -0
- package/src/tool/courtFeeCalculator/entry.ts +2 -0
- package/src/tool/courtFeeCalculator/i18n/de.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/en.ts +2 -22
- package/src/tool/courtFeeCalculator/i18n/es.ts +2 -22
- package/src/tool/courtFeeCalculator/i18n/fr.ts +2 -22
- package/src/tool/courtFeeCalculator/i18n/id.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/it.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/ja.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/ko.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/nl.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/pl.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/pt.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/ru.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/sv.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/tr.ts +2 -18
- package/src/tool/courtFeeCalculator/i18n/zh.ts +2 -18
- package/src/tool/courtFeeCalculator/seo.astro +2 -1
- package/src/tool/debtSnowball/bibliography.ts +12 -0
- package/src/tool/debtSnowball/entry.ts +2 -0
- package/src/tool/debtSnowball/i18n/de.ts +2 -14
- package/src/tool/debtSnowball/i18n/en.ts +2 -14
- package/src/tool/debtSnowball/i18n/es.ts +2 -14
- package/src/tool/debtSnowball/i18n/fr.ts +2 -14
- package/src/tool/debtSnowball/i18n/id.ts +2 -14
- package/src/tool/debtSnowball/i18n/it.ts +2 -14
- package/src/tool/debtSnowball/i18n/ja.ts +2 -14
- package/src/tool/debtSnowball/i18n/ko.ts +2 -14
- package/src/tool/debtSnowball/i18n/nl.ts +2 -14
- package/src/tool/debtSnowball/i18n/pl.ts +2 -14
- package/src/tool/debtSnowball/i18n/pt.ts +2 -14
- package/src/tool/debtSnowball/i18n/ru.ts +2 -14
- package/src/tool/debtSnowball/i18n/sv.ts +2 -14
- package/src/tool/debtSnowball/i18n/tr.ts +2 -14
- package/src/tool/debtSnowball/i18n/zh.ts +2 -14
- package/src/tool/debtSnowball/seo.astro +2 -1
- package/src/tool/fireCalculator/bibliography.ts +20 -0
- package/src/tool/fireCalculator/entry.ts +2 -0
- package/src/tool/fireCalculator/i18n/de.ts +2 -22
- package/src/tool/fireCalculator/i18n/en.ts +2 -22
- package/src/tool/fireCalculator/i18n/es.ts +2 -22
- package/src/tool/fireCalculator/i18n/fr.ts +2 -22
- package/src/tool/fireCalculator/i18n/id.ts +2 -22
- package/src/tool/fireCalculator/i18n/it.ts +2 -22
- package/src/tool/fireCalculator/i18n/ja.ts +2 -22
- package/src/tool/fireCalculator/i18n/ko.ts +2 -22
- package/src/tool/fireCalculator/i18n/nl.ts +2 -22
- package/src/tool/fireCalculator/i18n/pl.ts +2 -22
- package/src/tool/fireCalculator/i18n/pt.ts +2 -22
- package/src/tool/fireCalculator/i18n/ru.ts +2 -22
- package/src/tool/fireCalculator/i18n/sv.ts +2 -22
- package/src/tool/fireCalculator/i18n/tr.ts +2 -22
- package/src/tool/fireCalculator/i18n/zh.ts +2 -22
- package/src/tool/fireCalculator/seo.astro +2 -1
- package/src/tool/ibanBicSwiftConverter/bibliography.ts +12 -0
- package/src/tool/ibanBicSwiftConverter/entry.ts +2 -0
- package/src/tool/ibanBicSwiftConverter/i18n/de.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/en.ts +2 -18
- package/src/tool/ibanBicSwiftConverter/i18n/es.ts +2 -18
- package/src/tool/ibanBicSwiftConverter/i18n/fr.ts +2 -18
- package/src/tool/ibanBicSwiftConverter/i18n/id.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/it.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/ja.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/ko.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/nl.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/pl.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/pt.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/ru.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/sv.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/tr.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/i18n/zh.ts +2 -14
- package/src/tool/ibanBicSwiftConverter/seo.astro +2 -1
- package/src/tool/inflation/bibliography.ts +20 -0
- package/src/tool/inflation/entry.ts +2 -0
- package/src/tool/inflation/i18n/de.ts +3 -16
- package/src/tool/inflation/i18n/en.ts +3 -20
- package/src/tool/inflation/i18n/es.ts +3 -20
- package/src/tool/inflation/i18n/fr.ts +3 -20
- package/src/tool/inflation/i18n/id.ts +3 -16
- package/src/tool/inflation/i18n/it.ts +3 -16
- package/src/tool/inflation/i18n/ja.ts +3 -16
- package/src/tool/inflation/i18n/ko.ts +3 -16
- package/src/tool/inflation/i18n/nl.ts +3 -16
- package/src/tool/inflation/i18n/pl.ts +3 -16
- package/src/tool/inflation/i18n/pt.ts +3 -16
- package/src/tool/inflation/i18n/ru.ts +3 -16
- package/src/tool/inflation/i18n/sv.ts +3 -16
- package/src/tool/inflation/i18n/tr.ts +3 -16
- package/src/tool/inflation/i18n/zh.ts +3 -16
- package/src/tool/inflation/seo.astro +2 -1
- package/src/tool/lateInterest/bibliography.ts +16 -0
- package/src/tool/lateInterest/entry.ts +2 -0
- package/src/tool/lateInterest/i18n/de.ts +3 -16
- package/src/tool/lateInterest/i18n/en.ts +3 -16
- package/src/tool/lateInterest/i18n/es.ts +3 -16
- package/src/tool/lateInterest/i18n/fr.ts +3 -16
- package/src/tool/lateInterest/i18n/id.ts +3 -16
- package/src/tool/lateInterest/i18n/it.ts +3 -16
- package/src/tool/lateInterest/i18n/ja.ts +3 -16
- package/src/tool/lateInterest/i18n/ko.ts +3 -16
- package/src/tool/lateInterest/i18n/nl.ts +3 -16
- package/src/tool/lateInterest/i18n/pl.ts +3 -16
- package/src/tool/lateInterest/i18n/pt.ts +3 -16
- package/src/tool/lateInterest/i18n/ru.ts +3 -16
- package/src/tool/lateInterest/i18n/sv.ts +3 -16
- package/src/tool/lateInterest/i18n/tr.ts +3 -16
- package/src/tool/lateInterest/i18n/zh.ts +3 -16
- package/src/tool/lateInterest/seo.astro +2 -1
- package/src/tool/legalInterestRate/bibliography.ts +16 -0
- package/src/tool/legalInterestRate/entry.ts +2 -0
- package/src/tool/legalInterestRate/i18n/de.ts +2 -18
- package/src/tool/legalInterestRate/i18n/en.ts +2 -22
- package/src/tool/legalInterestRate/i18n/es.ts +2 -22
- package/src/tool/legalInterestRate/i18n/fr.ts +2 -22
- package/src/tool/legalInterestRate/i18n/id.ts +2 -18
- package/src/tool/legalInterestRate/i18n/it.ts +2 -18
- package/src/tool/legalInterestRate/i18n/ja.ts +2 -18
- package/src/tool/legalInterestRate/i18n/ko.ts +2 -18
- package/src/tool/legalInterestRate/i18n/nl.ts +2 -18
- package/src/tool/legalInterestRate/i18n/pl.ts +2 -18
- package/src/tool/legalInterestRate/i18n/pt.ts +2 -18
- package/src/tool/legalInterestRate/i18n/ru.ts +2 -18
- package/src/tool/legalInterestRate/i18n/sv.ts +2 -18
- package/src/tool/legalInterestRate/i18n/tr.ts +2 -18
- package/src/tool/legalInterestRate/i18n/zh.ts +2 -18
- package/src/tool/legalInterestRate/seo.astro +2 -1
- package/src/tool/lotteryOptimizer/bibliography.ts +16 -0
- package/src/tool/lotteryOptimizer/entry.ts +2 -0
- package/src/tool/lotteryOptimizer/i18n/de.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/en.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/es.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/fr.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/id.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/it.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/ja.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/ko.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/nl.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/pl.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/pt.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/ru.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/sv.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/tr.ts +2 -18
- package/src/tool/lotteryOptimizer/i18n/zh.ts +2 -18
- package/src/tool/lotteryOptimizer/seo.astro +2 -1
- package/src/tool/mortgage/bibliography.ts +20 -0
- package/src/tool/mortgage/entry.ts +2 -0
- package/src/tool/mortgage/i18n/de.ts +3 -16
- package/src/tool/mortgage/i18n/en.ts +3 -20
- package/src/tool/mortgage/i18n/es.ts +3 -20
- package/src/tool/mortgage/i18n/fr.ts +3 -20
- package/src/tool/mortgage/i18n/id.ts +3 -12
- package/src/tool/mortgage/i18n/it.ts +3 -16
- package/src/tool/mortgage/i18n/ja.ts +3 -12
- package/src/tool/mortgage/i18n/ko.ts +3 -12
- package/src/tool/mortgage/i18n/nl.ts +3 -12
- package/src/tool/mortgage/i18n/pl.ts +3 -12
- package/src/tool/mortgage/i18n/pt.ts +3 -12
- package/src/tool/mortgage/i18n/ru.ts +3 -12
- package/src/tool/mortgage/i18n/sv.ts +3 -12
- package/src/tool/mortgage/i18n/tr.ts +3 -12
- package/src/tool/mortgage/i18n/zh.ts +3 -12
- package/src/tool/mortgage/seo.astro +2 -1
- package/src/tool/percentageCalculator/bibliography.ts +16 -0
- package/src/tool/percentageCalculator/entry.ts +2 -0
- package/src/tool/percentageCalculator/i18n/de.ts +3 -12
- package/src/tool/percentageCalculator/i18n/en.ts +3 -16
- package/src/tool/percentageCalculator/i18n/es.ts +3 -16
- package/src/tool/percentageCalculator/i18n/fr.ts +3 -16
- package/src/tool/percentageCalculator/i18n/id.ts +3 -12
- package/src/tool/percentageCalculator/i18n/it.ts +3 -12
- package/src/tool/percentageCalculator/i18n/ja.ts +3 -12
- package/src/tool/percentageCalculator/i18n/ko.ts +3 -12
- package/src/tool/percentageCalculator/i18n/nl.ts +3 -12
- package/src/tool/percentageCalculator/i18n/pl.ts +3 -12
- package/src/tool/percentageCalculator/i18n/pt.ts +3 -12
- package/src/tool/percentageCalculator/i18n/ru.ts +3 -12
- package/src/tool/percentageCalculator/i18n/sv.ts +3 -12
- package/src/tool/percentageCalculator/i18n/tr.ts +3 -12
- package/src/tool/percentageCalculator/i18n/zh.ts +3 -12
- package/src/tool/percentageCalculator/seo.astro +2 -1
- package/src/tool/rentIncreaseCalculator/bibliography.ts +16 -0
- package/src/tool/rentIncreaseCalculator/entry.ts +2 -0
- package/src/tool/rentIncreaseCalculator/i18n/de.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/en.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/es.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/fr.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/id.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/it.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/ja.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/ko.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/nl.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/pl.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/pt.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/ru.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/sv.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/tr.ts +2 -18
- package/src/tool/rentIncreaseCalculator/i18n/zh.ts +2 -18
- package/src/tool/rentIncreaseCalculator/seo.astro +2 -1
- package/src/types.ts +0 -2
package/package.json
CHANGED
|
@@ -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"
|
|
@@ -120,7 +136,7 @@ const titleBase = words.slice(1).join(" ") || "";
|
|
|
120
136
|
</section>
|
|
121
137
|
|
|
122
138
|
<section class="section-bibliography">
|
|
123
|
-
<Bibliography links={content.bibliography}
|
|
139
|
+
<Bibliography links={content.bibliography} />
|
|
124
140
|
</section>
|
|
125
141
|
</div>
|
|
126
142
|
</PreviewLayout>
|
|
@@ -7,28 +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('
|
|
10
|
+
it('should have faq items', 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
|
-
|
|
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
|
-
}
|
|
13
|
+
expect(content.faq).toBeDefined();
|
|
14
|
+
expect(Array.isArray(content.faq)).toBe(true);
|
|
20
15
|
});
|
|
21
16
|
|
|
22
|
-
it('
|
|
17
|
+
it('should have bibliography items', async () => {
|
|
23
18
|
const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
|
|
24
19
|
const content = (await loader?.()) as ToolLocaleContent;
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
}
|
|
20
|
+
expect(content.bibliography).toBeDefined();
|
|
21
|
+
expect(Array.isArray(content.bibliography)).toBe(true);
|
|
32
22
|
});
|
|
33
23
|
});
|
|
34
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
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { BibliographyEntry } from '../../types';
|
|
2
|
+
|
|
3
|
+
export const bibliography: BibliographyEntry[] = [
|
|
4
|
+
{
|
|
5
|
+
name: 'Investopedia: Compound Interest Definition',
|
|
6
|
+
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
name: 'Investopedia: Rule of 72',
|
|
10
|
+
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'Khan Academy: Interest and Debt',
|
|
14
|
+
url: 'https://www.khanacademy.org/economics-finance-domain/core-finance/interest-tutorial',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: 'Banco de España: Portal del Cliente Bancario',
|
|
18
|
+
url: 'https://www.bde.es/bde/es/secciones/servicios/Particulares_y_e/Clientesbancarios/',
|
|
19
|
+
},
|
|
20
|
+
];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Häufig gestellte Fragen',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Khan Academy: Interest and Debt',
|
|
104
|
-
url: 'https://www.khanacademy.org/economics-finance-domain/core-finance/interest-tutorial',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
107
94
|
howTo: howToData,
|
|
108
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,27 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Frequently Asked Questions',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Khan Academy: Interest and Debt',
|
|
104
|
-
url: 'https://www.khanacademy.org/economics-finance-domain/core-finance/interest-tutorial',
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: 'Investopedia: Time Value of Money',
|
|
108
|
-
url: 'https://www.investopedia.com/terms/t/timevalueofmoney.asp',
|
|
109
|
-
},
|
|
110
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
111
94
|
howTo: howToData,
|
|
112
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
113
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,27 +88,8 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Preguntas Frecuentes',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Khan Academy: Interest and Debt',
|
|
104
|
-
url: 'https://www.khanacademy.org/economics-finance-domain/core-finance/interest-tutorial',
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: 'Banco de España: Portal del Cliente Bancario',
|
|
108
|
-
url: 'https://www.bde.es/bde/es/secciones/servicios/Particulares_y_e/Clientesbancarios/',
|
|
109
|
-
},
|
|
110
|
-
],
|
|
92
|
+
bibliography,
|
|
111
93
|
howTo: howToData,
|
|
112
94
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
113
95
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,27 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Questions Fréquentes',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Khan Academy: Interest and Debt',
|
|
104
|
-
url: 'https://www.khanacademy.org/economics-finance-domain/core-finance/interest-tutorial',
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: 'Banque de France : Éducation financière',
|
|
108
|
-
url: 'https://www.banque-france.fr/fr/la-banque-de-france/notre-mission/education-economique-financiere-et-statistique',
|
|
109
|
-
},
|
|
110
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
111
94
|
howTo: howToData,
|
|
112
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
113
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Pertanyaan Umum',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Khan Academy: Bunga dan Hutang',
|
|
104
|
-
url: 'https://id.khanacademy.org/economics-finance-domain/core-finance/interest-tutorial',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
107
94
|
howTo: howToData,
|
|
108
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Domande Frequenti',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Khan Academy: Interest and Debt',
|
|
104
|
-
url: 'https://it.khanacademy.org/economics-finance-domain/core-finance/interest-tutorial',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
107
94
|
howTo: howToData,
|
|
108
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'よくある質問',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: '複利の計算 - Wikipedia',
|
|
104
|
-
url: 'https://ja.wikipedia.org/wiki/複利',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
107
94
|
howTo: howToData,
|
|
108
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: '자주 묻는 질문',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: '복리의 개념 - 위키백과',
|
|
104
|
-
url: 'https://ko.wikipedia.org/wiki/복리',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
107
94
|
howTo: howToData,
|
|
108
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Veelgestelde vragen',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Samengestelde interest - Wikipedia',
|
|
104
|
-
url: 'https://nl.wikipedia.org/wiki/Samengestelde_interest',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
107
94
|
howTo: howToData,
|
|
108
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,8 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Często zadawane pytania',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
bibliography: [
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Procent składany - Wikipedia',
|
|
104
|
-
url: 'https://pl.wikipedia.org/wiki/Procent_składany',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
107
93
|
howTo: howToData,
|
|
108
94
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
95
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Perguntas Frequentes',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Juros compostos - Wikipédia',
|
|
104
|
-
url: 'https://pt.wikipedia.org/wiki/Juros_compostos',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
107
94
|
howTo: howToData,
|
|
108
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Часто задаваемые вопросы',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Сложный процент — Википедия',
|
|
104
|
-
url: 'https://ru.wikipedia.org/wiki/Сложный_процент',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
107
94
|
howTo: howToData,
|
|
108
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
96
|
seo: [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography'
|
|
1
2
|
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
3
|
import type { ToolLocaleContent } from '../../../types';
|
|
3
4
|
import type { CompoundInterestUI } from '../ui';
|
|
@@ -87,23 +88,9 @@ export const content: ToolLocaleContent<CompoundInterestUI> = {
|
|
|
87
88
|
slug,
|
|
88
89
|
title,
|
|
89
90
|
description,
|
|
90
|
-
faqTitle: 'Vanliga frågor',
|
|
91
91
|
faq: faqData,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: 'Investopedia: Compound Interest Definition',
|
|
96
|
-
url: 'https://www.investopedia.com/terms/c/compoundinterest.asp',
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
name: 'Investopedia: Rule of 72',
|
|
100
|
-
url: 'https://www.investopedia.com/terms/r/ruleof72.asp',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'Ränta på ränta - Wikipedia',
|
|
104
|
-
url: 'https://sv.wikipedia.org/wiki/Ränta_på_ränta',
|
|
105
|
-
},
|
|
106
|
-
],
|
|
92
|
+
bibliography,
|
|
93
|
+
|
|
107
94
|
howTo: howToData,
|
|
108
95
|
schemas: [faqSchema, howToSchema, appSchema],
|
|
109
96
|
seo: [
|