@jjlmoya/utils-babies 1.1.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 +69 -0
- package/src/category/i18n/en.ts +48 -0
- package/src/category/i18n/es.ts +48 -0
- package/src/category/i18n/fr.ts +48 -0
- package/src/category/index.ts +24 -0
- package/src/category/seo.astro +15 -0
- package/src/components/PreviewNavSidebar.astro +116 -0
- package/src/components/PreviewToolbar.astro +143 -0
- package/src/data.ts +30 -0
- package/src/env.d.ts +5 -0
- package/src/index.ts +19 -0
- package/src/layouts/PreviewLayout.astro +117 -0
- package/src/pages/[locale]/[slug].astro +146 -0
- package/src/pages/[locale].astro +251 -0
- package/src/pages/index.astro +4 -0
- package/src/tests/faq_count.test.ts +19 -0
- package/src/tests/locale_completeness.test.ts +42 -0
- package/src/tests/mocks/astro_mock.js +2 -0
- package/src/tests/no_h1_in_components.test.ts +48 -0
- package/src/tests/seo_length.test.ts +23 -0
- package/src/tests/tool_validation.test.ts +17 -0
- package/src/tool/baby-feeding-calculator/bibliography.astro +7 -0
- package/src/tool/baby-feeding-calculator/component.astro +210 -0
- package/src/tool/baby-feeding-calculator/i18n/en.ts +162 -0
- package/src/tool/baby-feeding-calculator/i18n/es.ts +162 -0
- package/src/tool/baby-feeding-calculator/i18n/fr.ts +162 -0
- package/src/tool/baby-feeding-calculator/index.ts +47 -0
- package/src/tool/baby-feeding-calculator/logic.ts +85 -0
- package/src/tool/baby-feeding-calculator/seo.astro +58 -0
- package/src/tool/baby-feeding-calculator/style.css +329 -0
- package/src/tool/baby-percentile-calculator/bibliography.astro +7 -0
- package/src/tool/baby-percentile-calculator/component.astro +388 -0
- package/src/tool/baby-percentile-calculator/i18n/en.ts +244 -0
- package/src/tool/baby-percentile-calculator/i18n/es.ts +244 -0
- package/src/tool/baby-percentile-calculator/i18n/fr.ts +244 -0
- package/src/tool/baby-percentile-calculator/index.ts +54 -0
- package/src/tool/baby-percentile-calculator/lmsData.ts +80 -0
- package/src/tool/baby-percentile-calculator/logic.ts +85 -0
- package/src/tool/baby-percentile-calculator/seo.astro +36 -0
- package/src/tool/baby-percentile-calculator/style.css +393 -0
- package/src/tool/baby-size-converter/bibliography.astro +7 -0
- package/src/tool/baby-size-converter/component.astro +289 -0
- package/src/tool/baby-size-converter/data.json +11 -0
- package/src/tool/baby-size-converter/i18n/en.ts +203 -0
- package/src/tool/baby-size-converter/i18n/es.ts +203 -0
- package/src/tool/baby-size-converter/i18n/fr.ts +203 -0
- package/src/tool/baby-size-converter/index.ts +53 -0
- package/src/tool/baby-size-converter/logic.ts +44 -0
- package/src/tool/baby-size-converter/seo.astro +36 -0
- package/src/tool/baby-size-converter/style.css +394 -0
- package/src/tool/fertile-days-estimator/bibliography.astro +7 -0
- package/src/tool/fertile-days-estimator/component.astro +265 -0
- package/src/tool/fertile-days-estimator/i18n/en.ts +258 -0
- package/src/tool/fertile-days-estimator/i18n/es.ts +262 -0
- package/src/tool/fertile-days-estimator/i18n/fr.ts +258 -0
- package/src/tool/fertile-days-estimator/index.ts +47 -0
- package/src/tool/fertile-days-estimator/logic.ts +58 -0
- package/src/tool/fertile-days-estimator/seo.astro +36 -0
- package/src/tool/fertile-days-estimator/style.css +419 -0
- package/src/tool/pregnancy-calculator/bibliography.astro +7 -0
- package/src/tool/pregnancy-calculator/calculator.ts +41 -0
- package/src/tool/pregnancy-calculator/component.astro +432 -0
- package/src/tool/pregnancy-calculator/i18n/en.ts +315 -0
- package/src/tool/pregnancy-calculator/i18n/es.ts +319 -0
- package/src/tool/pregnancy-calculator/i18n/fr.ts +315 -0
- package/src/tool/pregnancy-calculator/index.ts +55 -0
- package/src/tool/pregnancy-calculator/milestones.ts +153 -0
- package/src/tool/pregnancy-calculator/seo.astro +36 -0
- package/src/tool/pregnancy-calculator/store.ts +60 -0
- package/src/tool/pregnancy-calculator/style.css +807 -0
- package/src/tool/vaccination-calendar/bibliography.astro +7 -0
- package/src/tool/vaccination-calendar/component.astro +286 -0
- package/src/tool/vaccination-calendar/i18n/en.ts +170 -0
- package/src/tool/vaccination-calendar/i18n/es.ts +174 -0
- package/src/tool/vaccination-calendar/i18n/fr.ts +170 -0
- package/src/tool/vaccination-calendar/index.ts +47 -0
- package/src/tool/vaccination-calendar/logic.ts +59 -0
- package/src/tool/vaccination-calendar/seo.astro +36 -0
- package/src/tool/vaccination-calendar/style.css +316 -0
- package/src/tool/vaccination-calendar/vaccinationData.ts +21 -0
- package/src/tools.ts +17 -0
- package/src/types.ts +72 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
---
|
|
2
|
+
import './style.css';
|
|
3
|
+
import type { BabySizeConverterUI } from './index';
|
|
4
|
+
import brandsData from './data.json';
|
|
5
|
+
|
|
6
|
+
interface Props { ui: BabySizeConverterUI; }
|
|
7
|
+
const { ui } = Astro.props;
|
|
8
|
+
|
|
9
|
+
const brands = brandsData.brands;
|
|
10
|
+
---
|
|
11
|
+
<div
|
|
12
|
+
id="baby-size-converter-root"
|
|
13
|
+
class="baby-size-converter"
|
|
14
|
+
data-ui={JSON.stringify(ui)}
|
|
15
|
+
data-brands={JSON.stringify(brands)}
|
|
16
|
+
>
|
|
17
|
+
<div class="baby-size-converter-main">
|
|
18
|
+
<div class="baby-size-converter-left">
|
|
19
|
+
<div class="baby-size-converter-section-marker">{ui.labelInput}</div>
|
|
20
|
+
|
|
21
|
+
<div class="baby-size-converter-unit-nav">
|
|
22
|
+
<button class="baby-size-converter-unit-tab active" data-unit="metric">{ui.unitMetric}</button>
|
|
23
|
+
<button class="baby-size-converter-unit-tab" data-unit="imperial">{ui.unitImperial}</button>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="baby-size-converter-num-ctrl">
|
|
27
|
+
<div class="baby-size-converter-num-label" id="bsc-height-label">{ui.labelHeight} ({ui.labelCm})</div>
|
|
28
|
+
<div class="baby-size-converter-stepper-box">
|
|
29
|
+
<button class="baby-size-converter-btn-step" id="bsc-height-dec" aria-label="Reducir altura">−</button>
|
|
30
|
+
<div class="baby-size-converter-val-view">
|
|
31
|
+
<span class="baby-size-converter-val-big" id="bsc-height-val">68</span>
|
|
32
|
+
<span class="baby-size-converter-val-sub" id="bsc-height-unit">{ui.labelCm}</span>
|
|
33
|
+
</div>
|
|
34
|
+
<button class="baby-size-converter-btn-step" id="bsc-height-inc" aria-label="Aumentar altura">+</button>
|
|
35
|
+
</div>
|
|
36
|
+
<input class="baby-size-converter-slider-line" type="range" id="bsc-height-slider" min="45" max="100" value="68" />
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div class="baby-size-converter-num-ctrl">
|
|
40
|
+
<div class="baby-size-converter-num-label" id="bsc-weight-label">{ui.labelWeight} ({ui.labelKg})</div>
|
|
41
|
+
<div class="baby-size-converter-stepper-box">
|
|
42
|
+
<button class="baby-size-converter-btn-step" id="bsc-weight-dec" aria-label="Reducir peso">−</button>
|
|
43
|
+
<div class="baby-size-converter-val-view">
|
|
44
|
+
<span class="baby-size-converter-val-big" id="bsc-weight-val">8.0</span>
|
|
45
|
+
<span class="baby-size-converter-val-sub" id="bsc-weight-unit">{ui.labelKg}</span>
|
|
46
|
+
</div>
|
|
47
|
+
<button class="baby-size-converter-btn-step" id="bsc-weight-inc" aria-label="Aumentar peso">+</button>
|
|
48
|
+
</div>
|
|
49
|
+
<input class="baby-size-converter-slider-line" type="range" id="bsc-weight-slider" min="2" max="20" step="0.1" value="8" />
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div class="baby-size-converter-num-ctrl">
|
|
53
|
+
<div class="baby-size-converter-num-label">{ui.labelPresets}</div>
|
|
54
|
+
<div class="baby-size-converter-age-rack">
|
|
55
|
+
<button class="baby-size-converter-age-tile" data-height="56" data-weight="4.5">0-1m</button>
|
|
56
|
+
<button class="baby-size-converter-age-tile" data-height="62" data-weight="6">1-3m</button>
|
|
57
|
+
<button class="baby-size-converter-age-tile" data-height="68" data-weight="8">3-6m</button>
|
|
58
|
+
<button class="baby-size-converter-age-tile" data-height="74" data-weight="9">6-9m</button>
|
|
59
|
+
<button class="baby-size-converter-age-tile" data-height="80" data-weight="10">9-12m</button>
|
|
60
|
+
<button class="baby-size-converter-age-tile" data-height="86" data-weight="11.5">12-18m</button>
|
|
61
|
+
<button class="baby-size-converter-age-tile" data-height="92" data-weight="13">18-24m</button>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="baby-size-converter-num-ctrl">
|
|
66
|
+
<div class="baby-size-converter-num-label">{ui.labelBrandFit}</div>
|
|
67
|
+
<select class="baby-size-converter-select-box" id="bsc-brand-select">
|
|
68
|
+
{brands.map((b) => (
|
|
69
|
+
<option value={b.id}>{b.name}</option>
|
|
70
|
+
))}
|
|
71
|
+
</select>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div class="baby-size-converter-right">
|
|
76
|
+
<div class="baby-size-converter-section-marker">{ui.labelResults}</div>
|
|
77
|
+
|
|
78
|
+
<div class="baby-size-converter-res-header">
|
|
79
|
+
<div class="baby-size-converter-res-size-main" id="bsc-size-label">68</div>
|
|
80
|
+
<div class="baby-size-converter-res-brand-hint" id="bsc-brand-hint">Zara</div>
|
|
81
|
+
<span class="baby-size-converter-fit-label" id="bsc-fit-label">{ui.fitRegular}</span>
|
|
82
|
+
<button class="baby-size-converter-share-btn" id="bsc-share-btn" aria-label={ui.shareAriaLabel}>
|
|
83
|
+
⇧
|
|
84
|
+
</button>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div class="baby-size-converter-clothes-meta">
|
|
88
|
+
<div class="baby-size-converter-meta-title">{ui.labelGarmentMeasures}</div>
|
|
89
|
+
<div class="baby-size-converter-meta-vals">
|
|
90
|
+
<div class="baby-size-converter-meta-cell">
|
|
91
|
+
<span class="baby-size-converter-num-label">{ui.labelChest}</span>
|
|
92
|
+
<span class="baby-size-converter-val-big" id="bsc-chest-val">44 cm</span>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="baby-size-converter-meta-cell">
|
|
95
|
+
<span class="baby-size-converter-num-label">{ui.labelWaist}</span>
|
|
96
|
+
<span class="baby-size-converter-val-big" id="bsc-waist-val">43 cm</span>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div class="baby-size-converter-equivalents-grid-box">
|
|
102
|
+
<div class="baby-size-converter-eq-head-row">
|
|
103
|
+
<span class="baby-size-converter-eq-col-name">{ui.labelBrandFit}</span>
|
|
104
|
+
<span>{ui.labelSuggested}</span>
|
|
105
|
+
</div>
|
|
106
|
+
<div id="bsc-eq-list"></div>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<div class="baby-size-converter-pro-tip-footer">
|
|
110
|
+
<span class="baby-size-converter-footer-icon">ⓘ</span>
|
|
111
|
+
<span class="baby-size-converter-footer-text">{ui.tipText}</span>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<script is:inline>
|
|
118
|
+
(function () {
|
|
119
|
+
const root = document.getElementById('baby-size-converter-root');
|
|
120
|
+
if (!root) return;
|
|
121
|
+
const ui = JSON.parse(root.dataset.ui);
|
|
122
|
+
const brands = JSON.parse(root.dataset.brands);
|
|
123
|
+
|
|
124
|
+
let heightCm = 68;
|
|
125
|
+
let weightKg = 8.0;
|
|
126
|
+
let unitMode = 'metric';
|
|
127
|
+
let activeBrandId = brands[0].id;
|
|
128
|
+
|
|
129
|
+
const heightSlider = root.querySelector('#bsc-height-slider');
|
|
130
|
+
const weightSlider = root.querySelector('#bsc-weight-slider');
|
|
131
|
+
const heightValEl = root.querySelector('#bsc-height-val');
|
|
132
|
+
const weightValEl = root.querySelector('#bsc-weight-val');
|
|
133
|
+
const heightLabelEl = root.querySelector('#bsc-height-label');
|
|
134
|
+
const weightLabelEl = root.querySelector('#bsc-weight-label');
|
|
135
|
+
const heightUnitEl = root.querySelector('#bsc-height-unit');
|
|
136
|
+
const weightUnitEl = root.querySelector('#bsc-weight-unit');
|
|
137
|
+
const brandSelect = root.querySelector('#bsc-brand-select');
|
|
138
|
+
const sizeLabelEl = root.querySelector('#bsc-size-label');
|
|
139
|
+
const brandHintEl = root.querySelector('#bsc-brand-hint');
|
|
140
|
+
const fitLabelEl = root.querySelector('#bsc-fit-label');
|
|
141
|
+
const chestValEl = root.querySelector('#bsc-chest-val');
|
|
142
|
+
const waistValEl = root.querySelector('#bsc-waist-val');
|
|
143
|
+
const eqList = root.querySelector('#bsc-eq-list');
|
|
144
|
+
const shareBtn = root.querySelector('#bsc-share-btn');
|
|
145
|
+
|
|
146
|
+
function findBestSize(brand, height, weight) {
|
|
147
|
+
let best = brand.sizes[0];
|
|
148
|
+
let diff = Infinity;
|
|
149
|
+
brand.sizes.forEach(function (s) {
|
|
150
|
+
const d = Math.abs(s.height - height) + Math.abs(s.weight - weight) * 8;
|
|
151
|
+
if (d < diff) {
|
|
152
|
+
diff = d;
|
|
153
|
+
best = s;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
return best;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function getFitLabel(fit) {
|
|
160
|
+
if (fit === 'large') return ui.fitLarge;
|
|
161
|
+
if (fit === 'small') return ui.fitSmall;
|
|
162
|
+
return ui.fitRegular;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function getFitClass(fit) {
|
|
166
|
+
if (fit === 'large') return 'baby-size-converter-fit-large';
|
|
167
|
+
if (fit === 'small') return 'baby-size-converter-fit-small';
|
|
168
|
+
return '';
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function displayHeight() {
|
|
172
|
+
if (unitMode === 'imperial') return (heightCm / 2.54).toFixed(1);
|
|
173
|
+
return heightCm.toString();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function displayWeight() {
|
|
177
|
+
if (unitMode === 'imperial') return (weightKg * 2.20462).toFixed(1);
|
|
178
|
+
return weightKg.toFixed(1);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function updateDisplay() {
|
|
182
|
+
const activeBrand = brands.find(function (b) { return b.id === activeBrandId; }) || brands[0];
|
|
183
|
+
const best = findBestSize(activeBrand, heightCm, weightKg);
|
|
184
|
+
const measureUnit = unitMode === 'imperial' ? ui.labelIn : ui.labelCm;
|
|
185
|
+
const weightUnit = unitMode === 'imperial' ? ui.labelLb : ui.labelKg;
|
|
186
|
+
|
|
187
|
+
heightValEl.textContent = displayHeight();
|
|
188
|
+
weightValEl.textContent = displayWeight();
|
|
189
|
+
heightUnitEl.textContent = measureUnit;
|
|
190
|
+
weightUnitEl.textContent = weightUnit;
|
|
191
|
+
heightLabelEl.textContent = ui.labelHeight + ' (' + measureUnit + ')';
|
|
192
|
+
weightLabelEl.textContent = ui.labelWeight + ' (' + weightUnit + ')';
|
|
193
|
+
|
|
194
|
+
heightSlider.value = heightCm;
|
|
195
|
+
weightSlider.value = weightKg;
|
|
196
|
+
|
|
197
|
+
sizeLabelEl.textContent = best.label;
|
|
198
|
+
brandHintEl.textContent = activeBrand.name;
|
|
199
|
+
fitLabelEl.textContent = getFitLabel(activeBrand.fit);
|
|
200
|
+
fitLabelEl.className = 'baby-size-converter-fit-label ' + getFitClass(activeBrand.fit);
|
|
201
|
+
|
|
202
|
+
const chestDisplay = unitMode === 'imperial'
|
|
203
|
+
? (best.chest / 2.54).toFixed(1) + ' ' + ui.labelIn
|
|
204
|
+
: best.chest + ' ' + ui.labelCm;
|
|
205
|
+
const waistDisplay = unitMode === 'imperial'
|
|
206
|
+
? (best.waist / 2.54).toFixed(1) + ' ' + ui.labelIn
|
|
207
|
+
: best.waist + ' ' + ui.labelCm;
|
|
208
|
+
chestValEl.textContent = chestDisplay;
|
|
209
|
+
waistValEl.textContent = waistDisplay;
|
|
210
|
+
|
|
211
|
+
const rows = brands.map(function (b) {
|
|
212
|
+
const s = findBestSize(b, heightCm, weightKg);
|
|
213
|
+
const isActive = b.id === activeBrandId;
|
|
214
|
+
return '<div class="baby-size-converter-eq-data-row' + (isActive ? ' baby-size-converter-eq-active' : '') + '">'
|
|
215
|
+
+ '<span class="baby-size-converter-eq-brand-v">' + b.name + '</span>'
|
|
216
|
+
+ '<span class="baby-size-converter-eq-size-v">' + s.label + '</span>'
|
|
217
|
+
+ '</div>';
|
|
218
|
+
}).join('');
|
|
219
|
+
eqList.innerHTML = rows;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
root.querySelectorAll('.baby-size-converter-unit-tab').forEach(function (btn) {
|
|
223
|
+
btn.addEventListener('click', function () {
|
|
224
|
+
unitMode = btn.dataset.unit;
|
|
225
|
+
root.querySelectorAll('.baby-size-converter-unit-tab').forEach(function (b) { b.classList.remove('active'); });
|
|
226
|
+
btn.classList.add('active');
|
|
227
|
+
updateDisplay();
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
root.querySelectorAll('.baby-size-converter-age-tile').forEach(function (btn) {
|
|
232
|
+
btn.addEventListener('click', function () {
|
|
233
|
+
heightCm = Number(btn.dataset.height);
|
|
234
|
+
weightKg = Number(btn.dataset.weight);
|
|
235
|
+
updateDisplay();
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
root.querySelector('#bsc-height-dec').addEventListener('click', function () {
|
|
240
|
+
if (heightCm > 45) { heightCm -= 1; updateDisplay(); }
|
|
241
|
+
});
|
|
242
|
+
root.querySelector('#bsc-height-inc').addEventListener('click', function () {
|
|
243
|
+
if (heightCm < 100) { heightCm += 1; updateDisplay(); }
|
|
244
|
+
});
|
|
245
|
+
heightSlider.addEventListener('input', function () {
|
|
246
|
+
heightCm = Number(heightSlider.value);
|
|
247
|
+
updateDisplay();
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
root.querySelector('#bsc-weight-dec').addEventListener('click', function () {
|
|
251
|
+
if (weightKg > 2) { weightKg = Math.round((weightKg - 0.1) * 10) / 10; updateDisplay(); }
|
|
252
|
+
});
|
|
253
|
+
root.querySelector('#bsc-weight-inc').addEventListener('click', function () {
|
|
254
|
+
if (weightKg < 20) { weightKg = Math.round((weightKg + 0.1) * 10) / 10; updateDisplay(); }
|
|
255
|
+
});
|
|
256
|
+
weightSlider.addEventListener('input', function () {
|
|
257
|
+
weightKg = Number(weightSlider.value);
|
|
258
|
+
updateDisplay();
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
brandSelect.addEventListener('change', function () {
|
|
262
|
+
activeBrandId = brandSelect.value;
|
|
263
|
+
updateDisplay();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
shareBtn.addEventListener('click', function () {
|
|
267
|
+
const params = new URLSearchParams();
|
|
268
|
+
params.set('h', heightCm.toString());
|
|
269
|
+
params.set('w', weightKg.toString());
|
|
270
|
+
params.set('b', activeBrandId);
|
|
271
|
+
const url = window.location.pathname + '?' + params.toString();
|
|
272
|
+
if (navigator.share) {
|
|
273
|
+
navigator.share({ url: url });
|
|
274
|
+
} else {
|
|
275
|
+
navigator.clipboard.writeText(window.location.origin + url);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
280
|
+
if (urlParams.get('h')) heightCm = Number(urlParams.get('h'));
|
|
281
|
+
if (urlParams.get('w')) weightKg = Number(urlParams.get('w'));
|
|
282
|
+
if (urlParams.get('b')) {
|
|
283
|
+
activeBrandId = urlParams.get('b');
|
|
284
|
+
brandSelect.value = activeBrandId;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
updateDisplay();
|
|
288
|
+
})();
|
|
289
|
+
</script>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"brands": [
|
|
3
|
+
{"id":"zara","name":"Zara","fit":"regular","sizes":[{"label":"0-1 m","age":1,"height":56,"weight":4.5,"chest":38,"waist":38},{"label":"1-3 m","age":3,"height":62,"weight":6,"chest":41,"waist":41},{"label":"3-6 m","age":6,"height":68,"weight":8,"chest":44,"waist":43},{"label":"6-9 m","age":9,"height":74,"weight":9,"chest":47,"waist":46},{"label":"9-12 m","age":12,"height":80,"weight":10,"chest":49,"waist":48},{"label":"12-18 m","age":18,"height":86,"weight":11.5,"chest":51,"waist":50},{"label":"18-24 m","age":24,"height":92,"weight":13,"chest":53,"waist":52}]},
|
|
4
|
+
{"id":"hm","name":"H&M","fit":"large","sizes":[{"label":"50","age":0.5,"height":50,"weight":3.5,"chest":37,"waist":36},{"label":"56","age":2,"height":56,"weight":4.5,"chest":39,"waist":38},{"label":"62","age":4,"height":62,"weight":6,"chest":42,"waist":40},{"label":"68","age":6,"height":68,"weight":8,"chest":45,"waist":43},{"label":"74","age":9,"height":74,"weight":9,"chest":48,"waist":46},{"label":"80","age":12,"height":80,"weight":10.5,"chest":50,"waist":48},{"label":"86","age":18,"height":86,"weight":12,"chest":52,"waist":50},{"label":"92","age":24,"height":92,"weight":14,"chest":54,"waist":52}]},
|
|
5
|
+
{"id":"primark","name":"Primark","fit":"large","sizes":[{"label":"Up to 1m","age":1,"height":56,"weight":4.5,"chest":38.5,"waist":37},{"label":"0-3 m","age":3,"height":62,"weight":6,"chest":41.5,"waist":40},{"label":"3-6 m","age":6,"height":68,"weight":8,"chest":44.5,"waist":43},{"label":"6-9 m","age":9,"height":74,"weight":9.5,"chest":47.5,"waist":46},{"label":"9-12 m","age":12,"height":80,"weight":11,"chest":49.5,"waist":48},{"label":"12-18 m","age":18,"height":86,"weight":12.5,"chest":51.5,"waist":50},{"label":"18-24 m","age":24,"height":92,"weight":14.5,"chest":53.5,"waist":52}]},
|
|
6
|
+
{"id":"carters","name":"Carter's","fit":"small","sizes":[{"label":"NB","age":0.5,"height":55,"weight":3.6,"chest":36,"waist":35},{"label":"3m","age":3,"height":61,"weight":5.7,"chest":40,"waist":39},{"label":"6m","age":6,"height":67,"weight":7.5,"chest":43,"waist":42},{"label":"9m","age":9,"height":72,"weight":9.3,"chest":46,"waist":45},{"label":"12m","age":12,"height":78,"weight":11.1,"chest":48,"waist":47},{"label":"18m","age":18,"height":83,"weight":12.7,"chest":50,"waist":49},{"label":"24m","age":24,"height":86,"weight":13.6,"chest":52,"waist":51}]},
|
|
7
|
+
{"id":"kiabi","name":"Kiabi","fit":"regular","sizes":[{"label":"50cm","age":0.5,"height":50,"weight":3.5,"chest":37,"waist":36},{"label":"56cm","age":1,"height":56,"weight":4.5,"chest":39,"waist":38},{"label":"62cm","age":3,"height":62,"weight":6,"chest":42,"waist":41},{"label":"68cm","age":6,"height":68,"weight":8,"chest":45,"waist":44},{"label":"74cm","age":9,"height":74,"weight":9.5,"chest":48,"waist":46},{"label":"80cm","age":12,"height":80,"weight":11,"chest":50,"waist":48},{"label":"86cm","age":18,"height":86,"weight":12.5,"chest":52,"waist":50},{"label":"92cm","age":24,"height":92,"weight":14,"chest":54,"waist":52}]},
|
|
8
|
+
{"id":"mango","name":"Mango Kids","fit":"regular","sizes":[{"label":"0-1 m","age":1,"height":56,"weight":4.5,"chest":38,"waist":38},{"label":"1-3 m","age":3,"height":62,"weight":6,"chest":41,"waist":41},{"label":"3-6 m","age":6,"height":68,"weight":8,"chest":44,"waist":43},{"label":"6-9 m","age":9,"height":74,"weight":9.5,"chest":47,"waist":46},{"label":"9-12 m","age":12,"height":80,"weight":11,"chest":49,"waist":48},{"label":"12-18 m","age":18,"height":86,"weight":13,"chest":51,"waist":50},{"label":"18-24 m","age":24,"height":92,"weight":15,"chest":53,"waist":52}]},
|
|
9
|
+
{"id":"mayoral","name":"Mayoral","fit":"small","sizes":[{"label":"50","age":0.5,"height":50,"weight":3.3,"chest":36,"waist":35},{"label":"56","age":1,"height":56,"weight":4.3,"chest":38,"waist":37},{"label":"62","age":2,"height":62,"weight":5.8,"chest":41,"waist":40},{"label":"68","age":4,"height":68,"weight":7.8,"chest":44,"waist":43},{"label":"74","age":9,"height":74,"weight":9.2,"chest":47,"waist":46},{"label":"80","age":12,"height":80,"weight":10.8,"chest":49,"waist":48},{"label":"86","age":18,"height":86,"weight":12.3,"chest":51,"waist":50},{"label":"92","age":24,"height":92,"weight":13.8,"chest":53,"waist":52}]}
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import type { BabySizeConverterLocaleContent } from '../index';
|
|
2
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
3
|
+
|
|
4
|
+
const slug = 'baby-size-converter';
|
|
5
|
+
const title = 'Baby Size Converter';
|
|
6
|
+
const description = "Convert baby clothing sizes between Zara, H&M, Primark, Carter's, Kiabi, Mango, and Mayoral. Enter your baby's height and weight to get the exact size for each brand.";
|
|
7
|
+
const faq = [
|
|
8
|
+
{
|
|
9
|
+
question: "How do I know what clothing size my baby needs?",
|
|
10
|
+
answer: "The most reliable approach is to use your baby's height as the main reference. European sizes (50, 56, 62...) correspond directly to height in centimeters. Enter the baby's height and weight in the converter to get the recommended size for each brand.",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
question: 'Why do sizes vary so much between brands?',
|
|
14
|
+
answer: "Each brand has its own cut pattern. H&M and Primark tend to run large, while Carter's and Mayoral run slim. Always use the baby's measurements, not just their age.",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
question: 'What should I do if the baby is between two sizes?',
|
|
18
|
+
answer: 'Always choose the larger size. Babies grow very quickly and a larger size ensures better durability and comfort.',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
question: 'Do inch-based sizes work the same way?',
|
|
22
|
+
answer: "American brands like Carter's use inches and weight as their primary reference. The converter automatically shows equivalents in the imperial system when you activate it.",
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
const howTo = [
|
|
26
|
+
{
|
|
27
|
+
name: "Enter the baby's height",
|
|
28
|
+
text: "Use the slider or buttons to adjust the baby's current height in centimeters or inches.",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: "Enter the baby's weight",
|
|
32
|
+
text: 'Adjust the weight in kg or pounds to refine results, as some brands use weight as a complementary reference.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'Select a brand',
|
|
36
|
+
text: 'Choose the clothing brand to see the suggested size and estimated garment measurements.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Review equivalents',
|
|
40
|
+
text: 'The right panel shows equivalent sizes for all available brands at a glance.',
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
45
|
+
'@context': 'https://schema.org',
|
|
46
|
+
'@type': 'FAQPage',
|
|
47
|
+
mainEntity: faq.map((item) => ({
|
|
48
|
+
'@type': 'Question',
|
|
49
|
+
name: item.question,
|
|
50
|
+
acceptedAnswer: { '@type': 'Answer', text: item.answer },
|
|
51
|
+
})),
|
|
52
|
+
};
|
|
53
|
+
const howToSchema: WithContext<HowTo> = {
|
|
54
|
+
'@context': 'https://schema.org',
|
|
55
|
+
'@type': 'HowTo',
|
|
56
|
+
name: title,
|
|
57
|
+
description,
|
|
58
|
+
step: howTo.map((step) => ({
|
|
59
|
+
'@type': 'HowToStep',
|
|
60
|
+
name: step.name,
|
|
61
|
+
text: step.text,
|
|
62
|
+
})),
|
|
63
|
+
};
|
|
64
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
65
|
+
'@context': 'https://schema.org',
|
|
66
|
+
'@type': 'SoftwareApplication',
|
|
67
|
+
name: title,
|
|
68
|
+
description,
|
|
69
|
+
applicationCategory: 'UtilitiesApplication',
|
|
70
|
+
operatingSystem: 'Web',
|
|
71
|
+
offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
|
|
72
|
+
inLanguage: 'en',
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const content: BabySizeConverterLocaleContent = {
|
|
76
|
+
slug,
|
|
77
|
+
title,
|
|
78
|
+
description,
|
|
79
|
+
ui: {
|
|
80
|
+
labelInput: 'Baby measurements',
|
|
81
|
+
labelResults: 'Estimated equivalents',
|
|
82
|
+
labelHeight: "Baby's height",
|
|
83
|
+
labelWeight: "Baby's current weight",
|
|
84
|
+
labelPresets: 'Presets by typical age',
|
|
85
|
+
unitMetric: 'Metric (cm/kg)',
|
|
86
|
+
unitImperial: 'Imperial (in/lb)',
|
|
87
|
+
labelCm: 'cm',
|
|
88
|
+
labelKg: 'kg',
|
|
89
|
+
labelIn: 'in',
|
|
90
|
+
labelLb: 'lb',
|
|
91
|
+
labelBrandFit: 'Brand & Fit',
|
|
92
|
+
labelSuggested: 'Suggested size',
|
|
93
|
+
labelChest: 'Chest',
|
|
94
|
+
labelWaist: 'Waist',
|
|
95
|
+
labelGarmentMeasures: 'Estimated garment measurements',
|
|
96
|
+
fitRegular: 'Regular fit',
|
|
97
|
+
fitLarge: 'Large fit',
|
|
98
|
+
fitSmall: 'Slim fit',
|
|
99
|
+
tipTitle: 'Expert tip',
|
|
100
|
+
tipText: 'Babies grow in very rapid development spurts. If the result is at the upper limit of a size, always choose the next size up to ensure durability and comfort for your baby.',
|
|
101
|
+
shareAriaLabel: 'Share size',
|
|
102
|
+
faqTitle: 'Frequently asked questions',
|
|
103
|
+
bibliographyTitle: 'References',
|
|
104
|
+
},
|
|
105
|
+
seo: [
|
|
106
|
+
{ type: 'title', text: 'Baby Size Guide: Zara, H&M, Primark and International Brands', level: 2 },
|
|
107
|
+
{ type: 'stats', columns: 3, items: [
|
|
108
|
+
{ value: '2.5 cm', label: 'Monthly growth' },
|
|
109
|
+
{ value: '3 months', label: 'Duration per size' },
|
|
110
|
+
{ value: '95%', label: 'Reliability by height' },
|
|
111
|
+
]},
|
|
112
|
+
{ type: 'tip', html: 'Always use height as the primary reference for choosing a size, not age. Two babies of the same age can differ by up to 8–10 cm, which means jumping a full size.' },
|
|
113
|
+
{ type: 'title', text: 'Sizes by age, height and weight', level: 3 },
|
|
114
|
+
{ type: 'table', headers: ['Approx. age', 'Height (cm)', 'Weight (kg)', 'Usual size', 'Estimated use'], rows: [
|
|
115
|
+
['Newborn', '50–56', '3–4.5', '50 / NB', '4–6 weeks'],
|
|
116
|
+
['1–3 months', '56–62', '4.5–6', '56–62', '6–8 weeks'],
|
|
117
|
+
['3–6 months', '62–68', '6–8', '62–68', '6–8 weeks'],
|
|
118
|
+
['6–9 months', '68–74', '8–9.5', '68–74', '6–8 weeks'],
|
|
119
|
+
['9–12 months', '74–80', '9.5–11', '74–80', '6–8 weeks'],
|
|
120
|
+
['12–18 months', '80–86', '11–13', '80–86', '3–4 months'],
|
|
121
|
+
['18–24 months', '86–92', '13–15', '86–92', '3–4 months'],
|
|
122
|
+
]},
|
|
123
|
+
{ type: 'title', text: 'Brands that run large vs. slim', level: 3 },
|
|
124
|
+
{ type: 'comparative', columns: 2, items: [
|
|
125
|
+
{
|
|
126
|
+
title: 'Run large (size down)',
|
|
127
|
+
description: 'These brands use wider cuts; go one size smaller than usual.',
|
|
128
|
+
points: [
|
|
129
|
+
'H&M: typically runs one size larger',
|
|
130
|
+
'Primark: generally wide cut',
|
|
131
|
+
'Lupilu (Lidl): loose fit overall',
|
|
132
|
+
'Recommended for babies in lower percentiles',
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
title: 'Run slim (size up)',
|
|
137
|
+
description: 'These brands use narrower cuts; go one size larger than usual.',
|
|
138
|
+
points: [
|
|
139
|
+
"Carter's: American slim cut",
|
|
140
|
+
'Mayoral: fitted European cut',
|
|
141
|
+
'Neck & Neck: reduced sizing',
|
|
142
|
+
'Recommended for babies in higher percentiles',
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
]},
|
|
146
|
+
{ type: 'title', text: 'Keys to getting the right size', level: 3 },
|
|
147
|
+
{ type: 'list', items: [
|
|
148
|
+
'Always measure the baby before buying — do not rely solely on age',
|
|
149
|
+
'If the result falls between two sizes, always choose the larger one',
|
|
150
|
+
'Account for nappy room in bodysuits and all-in-ones',
|
|
151
|
+
'European sizes (50, 56, 62...) correspond to height in cm',
|
|
152
|
+
'Always wash before use: cotton can shrink up to 5%',
|
|
153
|
+
]},
|
|
154
|
+
{ type: 'glossary', items: [
|
|
155
|
+
{
|
|
156
|
+
term: 'Size 50 / Newborn',
|
|
157
|
+
definition: 'Designed for babies up to 50 cm tall and around 3.5 kg. Many babies outgrow it very quickly, even within the first weeks.',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
term: 'Crotch length (rise)',
|
|
161
|
+
definition: 'Distance from the crotch to the waist. Critical in bodysuits and rompers: a short rise restricts the baby\'s movement even if the rest of the garment fits well.',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
term: 'Weight-based sizing',
|
|
165
|
+
definition: "American brands like Carter's use weight as the primary reference. Useful for babies with proportions outside the standard percentile.",
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
term: 'Envelope neckline',
|
|
169
|
+
definition: 'Neckline design on bodysuits and T-shirts that allows dressing the baby by sliding the garment downward rather than over the head. Essential in the first months.',
|
|
170
|
+
},
|
|
171
|
+
]},
|
|
172
|
+
{ type: 'summary', title: 'What to remember', items: [
|
|
173
|
+
'Height is the most reliable indicator for choosing size, above age.',
|
|
174
|
+
"H&M and Primark tend to run large; Carter's and Mayoral run slim.",
|
|
175
|
+
'Numerical European sizes (50, 56, 62...) correspond to height in cm.',
|
|
176
|
+
'When between sizes, choosing the larger one ensures better durability.',
|
|
177
|
+
'Envelope necklines and a generous rise are the key comfort details.',
|
|
178
|
+
]},
|
|
179
|
+
],
|
|
180
|
+
faqTitle: "Frequently asked questions",
|
|
181
|
+
faq,
|
|
182
|
+
bibliographyTitle: "References",
|
|
183
|
+
bibliography: [
|
|
184
|
+
{
|
|
185
|
+
name: 'Zara - Children\'s size guide',
|
|
186
|
+
url: 'https://www.zara.com/en/size-guide.html',
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: 'H&M - Baby size guide',
|
|
190
|
+
url: 'https://www2.hm.com/en_gb/customer-service/sizeguide.html',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: 'WHO - Child growth standards',
|
|
194
|
+
url: 'https://www.who.int/tools/child-growth-standards',
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: "Carter's - Size guide",
|
|
198
|
+
url: 'https://www.carters.com/size-chart',
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
howTo,
|
|
202
|
+
schemas: [faqSchema as any, howToSchema as any, appSchema],
|
|
203
|
+
};
|