@jjlmoya/utils-cooking 1.11.0 → 1.12.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 CHANGED
@@ -1,60 +1,60 @@
1
1
  {
2
- "name": "@jjlmoya/utils-cooking",
3
- "version": "1.11.0",
4
- "type": "module",
5
- "main": "./src/index.ts",
6
- "types": "./src/index.ts",
7
- "exports": {
8
- ".": "./src/index.ts",
9
- "./data": "./src/data.ts"
10
- },
11
- "files": [
12
- "src"
13
- ],
14
- "publishConfig": {
15
- "access": "public"
16
- },
17
- "scripts": {
18
- "dev": "astro dev",
19
- "start": "astro dev",
20
- "build": "astro build",
21
- "preview": "astro preview",
22
- "astro": "astro",
23
- "lint": "eslint src/ --max-warnings 0 && stylelint \"src/**/*.{css,astro}\"",
24
- "check": "astro check",
25
- "type-check": "astro check",
26
- "test": "vitest run",
27
- "preversion": "npm run lint && npm run test",
28
- "postversion": "git push && git push --tags",
29
- "patch": "npm version patch",
30
- "minor": "npm version minor",
31
- "major": "npm version major"
32
- },
33
- "lint-staged": {
34
- "*.{ts,tsx,astro}": [
35
- "eslint --fix"
36
- ]
37
- },
38
- "dependencies": {
39
- "@iconify-json/mdi": "^1.2.3",
40
- "@jjlmoya/utils-shared": "^1.1.0",
41
- "astro": "^6.1.2",
42
- "astro-icon": "^1.1.0"
43
- },
44
- "devDependencies": {
45
- "@astrojs/check": "^0.9.8",
46
- "eslint": "^9.39.4",
47
- "eslint-plugin-astro": "^1.6.0",
48
- "eslint-plugin-no-comments": "^1.1.10",
49
- "husky": "^9.1.7",
50
- "lint-staged": "^16.4.0",
51
- "postcss-html": "^1.8.1",
52
- "schema-dts": "^1.1.2",
53
- "stylelint": "^17.6.0",
54
- "stylelint-config-standard": "^40.0.0",
55
- "stylelint-declaration-strict-value": "^1.11.1",
56
- "typescript": "^5.4.0",
57
- "typescript-eslint": "^8.58.0",
58
- "vitest": "^4.1.2"
59
- }
2
+ "name": "@jjlmoya/utils-cooking",
3
+ "version": "1.12.0",
4
+ "type": "module",
5
+ "main": "./src/index.ts",
6
+ "types": "./src/index.ts",
7
+ "exports": {
8
+ ".": "./src/index.ts",
9
+ "./data": "./src/data.ts"
10
+ },
11
+ "files": [
12
+ "src"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "scripts": {
18
+ "dev": "astro dev",
19
+ "start": "astro dev",
20
+ "build": "astro build",
21
+ "preview": "astro preview",
22
+ "astro": "astro",
23
+ "lint": "eslint src/ --max-warnings 0 && stylelint \"src/**/*.{css,astro}\"",
24
+ "check": "astro check",
25
+ "type-check": "astro check",
26
+ "test": "vitest run",
27
+ "preversion": "npm run lint && npm run test",
28
+ "postversion": "git push && git push --tags",
29
+ "patch": "npm version patch",
30
+ "minor": "npm version minor",
31
+ "major": "npm version major"
32
+ },
33
+ "lint-staged": {
34
+ "*.{ts,tsx,astro}": [
35
+ "eslint --fix"
36
+ ]
37
+ },
38
+ "dependencies": {
39
+ "@iconify-json/mdi": "^1.2.3",
40
+ "@jjlmoya/utils-shared": "1.2.0",
41
+ "astro": "^6.1.2",
42
+ "astro-icon": "^1.1.0"
43
+ },
44
+ "devDependencies": {
45
+ "@astrojs/check": "^0.9.8",
46
+ "eslint": "^9.39.4",
47
+ "eslint-plugin-astro": "^1.6.0",
48
+ "eslint-plugin-no-comments": "^1.1.10",
49
+ "husky": "^9.1.7",
50
+ "lint-staged": "^16.4.0",
51
+ "postcss-html": "^1.8.1",
52
+ "schema-dts": "^1.1.2",
53
+ "stylelint": "^17.6.0",
54
+ "stylelint-config-standard": "^40.0.0",
55
+ "stylelint-declaration-strict-value": "^1.11.1",
56
+ "typescript": "^5.4.0",
57
+ "typescript-eslint": "^8.58.0",
58
+ "vitest": "^4.1.2"
59
+ }
60
60
  }
@@ -0,0 +1,23 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ALL_TOOLS } from '../tools';
3
+ import type { ToolLocaleContent } from '../types';
4
+
5
+ describe('Schemas Fulfillment Validation', () => {
6
+ ALL_TOOLS.forEach((tool) => {
7
+ describe(`Tool: ${tool.entry.id}`, () => {
8
+ Object.keys(tool.entry.i18n).forEach((locale) => {
9
+ it(`Locale: ${locale} should have faqSchema, appSchema and howToSchema`, async () => {
10
+ const loader = tool.entry.i18n[locale as keyof typeof tool.entry.i18n];
11
+ if (!loader) return;
12
+ const content = (await loader()) as ToolLocaleContent;
13
+
14
+ const schemaTypes = content.schemas.map((s: any) => s['@type']);
15
+
16
+ expect(schemaTypes, `Tool "${tool.entry.id}" locale "${locale}" is missing FAQPage schema`).toContain('FAQPage');
17
+ expect(schemaTypes, `Tool "${tool.entry.id}" locale "${locale}" is missing SoftwareApplication schema`).toContain('SoftwareApplication');
18
+ expect(schemaTypes, `Tool "${tool.entry.id}" locale "${locale}" is missing HowTo schema`).toContain('HowTo');
19
+ });
20
+ });
21
+ });
22
+ });
23
+ });
@@ -0,0 +1,55 @@
1
+ import { describe, it } from 'vitest';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ function getFiles(dir: string, ext: string[]): string[] {
6
+ const results: string[] = [];
7
+ if (!fs.existsSync(dir)) return results;
8
+ const list = fs.readdirSync(dir);
9
+ for (const file of list) {
10
+ const fullPath = path.join(dir, file);
11
+ const stat = fs.statSync(fullPath);
12
+ if (stat && stat.isDirectory()) {
13
+ results.push(...getFiles(fullPath, ext));
14
+ } else if (ext.some((e) => file.endsWith(e))) {
15
+ results.push(fullPath);
16
+ }
17
+ }
18
+ return results;
19
+ }
20
+
21
+ const SRC_DIR = path.join(process.cwd(), 'src');
22
+
23
+ describe('Project Titles - Separator Validation', () => {
24
+ const files = [
25
+ ...getFiles(path.join(SRC_DIR, 'tool'), ['.ts']),
26
+ ...getFiles(path.join(SRC_DIR, 'category'), ['.ts']),
27
+ ].filter(f => f.includes('i18n'));
28
+
29
+ it.each(files)('Verify that titles in %s do not contain | or -', (filePath) => {
30
+ const content = fs.readFileSync(filePath, 'utf-8');
31
+ const relativePath = path.relative(process.cwd(), filePath);
32
+
33
+ const titlePatterns = [
34
+ /const\s+title\s*=\s*['"]([^'"]+)['"]/g,
35
+ /title\s*:\s*['"]([^'"]+)['"]/g,
36
+ ];
37
+
38
+ const findings: string[] = [];
39
+
40
+ for (const pattern of titlePatterns) {
41
+ let match;
42
+ while ((match = pattern.exec(content)) !== null) {
43
+ const title = match[1]!;
44
+ if (title.includes('|') || title.includes('-')) {
45
+ findings.push(title);
46
+ }
47
+ }
48
+ }
49
+
50
+ if (findings.length > 0) {
51
+ const list = findings.map((f) => ` - "${f}"`).join('\n');
52
+ throw new Error(`Forbidden separators (| or -) found in titles in ${relativePath}:\n${list}`);
53
+ }
54
+ });
55
+ });
@@ -324,7 +324,7 @@ export const content: ToolLocaleContent = {
324
324
  {
325
325
  type: "diagnostic",
326
326
  variant: "warning",
327
- title: "Votre Gâteau est-il trop sec ?",
327
+ title: "Votre Gâteau est il trop sec ?",
328
328
  html: "L'erreur classique avec les cups est de plonger la tasse dans le sac de farine. Cela tasse la poudre et vous risquez d'ajouter 40g de farine excédentaire. La solution est de <strong>toujours convertir en grammes</strong>.",
329
329
  },
330
330
  {
@@ -1,6 +1,6 @@
1
1
  import type { ToolLocaleContent } from '../../../types';
2
2
 
3
- const title = "Smart Cookware Selector | Kitchen Utensils Guide";
3
+ const title = "Smart Cookware Selector: Kitchen Utensils Guide";
4
4
  const description = "Interactive guide to choose the best pan or pot based on your cooking style. Iron vs Stainless Steel vs Teflon. Find your perfect tool.";
5
5
  const faq = [
6
6
  {
@@ -73,7 +73,7 @@ const appSchema = {
73
73
 
74
74
  export const content: ToolLocaleContent = {
75
75
  slug: 'cookware-selector',
76
- title: 'Smart Cookware Selector | Kitchen Utensils Guide',
76
+ title: 'Smart Cookware Selector: Kitchen Utensils Guide',
77
77
  description: 'Interactive guide to choose the best pan or pot based on your cooking style. Iron vs Stainless Steel vs Teflon. Find your perfect tool.',
78
78
  faqTitle: 'Frequently Asked Questions',
79
79
  faq: [
@@ -1,6 +1,6 @@
1
1
  import type { ToolLocaleContent } from '../../../types';
2
2
 
3
- const title = "Selector de Sartenes Inteligente | Guía de Utensilios de Cocina";
3
+ const title = "Selector de Sartenes Inteligente: Guía de Utensilios de Cocina";
4
4
  const description = "Guía interactiva para elegir la mejor sartén u olla según tu estilo de cocina. Hierro vs Acero vs Teflón. Encuentra tu herramienta perfecta.";
5
5
  const faq = [
6
6
  {
@@ -72,8 +72,8 @@ const appSchema = {
72
72
  };
73
73
 
74
74
  export const content: ToolLocaleContent = {
75
- slug: 'selector-sartenes',
76
- title: 'Selector de Sartenes Inteligente | Guía de Utensilios de Cocina',
75
+ slug: 'guia-sartenes',
76
+ title: 'Selector de Sartenes Inteligente: Guía de Utensilios de Cocina',
77
77
  description: 'Guía interactiva para elegir la mejor sartén u olla según tu estilo de cocina. Hierro vs Acero vs Teflón. Encuentra tu herramienta perfecta.',
78
78
  faqTitle: 'Preguntas Frecuentes',
79
79
  faq: [
@@ -1,10 +1,78 @@
1
1
  import type { ToolLocaleContent } from '../../../types';
2
2
 
3
+ const title = 'Professional Recipe Ingredient Scaler';
4
+ const description =
5
+ 'Automatically scale your recipes based on serving count. Calculate exact ingredient amounts to multiply or reduce any recipe with professional precision.';
6
+
7
+ const faq = [
8
+ {
9
+ question: 'Why does my conversion factor include decimals?',
10
+ answer: 'Because culinary proportions aren\'t always whole numbers. If you scale a 4-person recipe for 7 people, the factor is exactly 1.75. Multiplying by this specific ratio is more accurate than arbitrary rounding.',
11
+ },
12
+ {
13
+ question: 'How do I handle fractions like \'1/2 tsp\'?',
14
+ answer: 'The parser automatically identifies numbers. It will read \'1/2\' as \'0.5\' and scale it accordingly. For maximum clarity, you can also enter decimals directly.',
15
+ },
16
+ {
17
+ question: 'Should I round the final results?',
18
+ answer: 'It depends on the ingredient. For flours and liquids, yes. For potent spices or yeast, we recommend scaling to about 75% of the calculated total to avoid overpowering the dish.',
19
+ },
20
+ {
21
+ question: 'Does it work with cups and ounces?',
22
+ answer: 'Yes, the tool scales any numerical value. However, we strongly recommend converting to grams first for professional-grade consistency across larger batches.',
23
+ },
24
+ ];
25
+
26
+ const howTo = [
27
+ {
28
+ name: 'Enter your servings count',
29
+ text: 'Define how many people the recipe was originally for, and how many you want to cook for now.',
30
+ },
31
+ {
32
+ name: 'Paste your ingredient list',
33
+ text: 'Copy and paste your entire list. Our tool recognizes numbers at the start of each line (e.g., 500g, 1/2, 2.5) and scales them instantly.',
34
+ },
35
+ {
36
+ name: 'Apply professional adjustments',
37
+ text: 'Math is exact, but cooking is situational. Scale spices to 75%. Don\'t scale cooking times. Use your chef\'s intuition for the final touch.',
38
+ },
39
+ ];
40
+
41
+ const faqSchema = {
42
+ '@context': 'https://schema.org',
43
+ '@type': 'FAQPage',
44
+ mainEntity: faq.map((item) => ({
45
+ '@type': 'Question',
46
+ name: item.question,
47
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
48
+ })),
49
+ };
50
+
51
+ const howToSchema = {
52
+ '@context': 'https://schema.org',
53
+ '@type': 'HowTo',
54
+ name: title,
55
+ description,
56
+ step: howTo.map((step) => ({
57
+ '@type': 'HowToStep',
58
+ name: step.name,
59
+ text: step.text,
60
+ })),
61
+ };
62
+
63
+ const appSchema = {
64
+ '@context': 'https://schema.org',
65
+ '@type': 'SoftwareApplication',
66
+ name: title,
67
+ description,
68
+ applicationCategory: 'UtilitiesApplication',
69
+ operatingSystem: 'All',
70
+ };
71
+
3
72
  export const content: ToolLocaleContent = {
4
73
  slug: "recipe-ingredient-scaler-converter-servings",
5
- title: "Professional Recipe Ingredient Scaler",
6
- description:
7
- "Automatically scale your recipes based on serving count. Calculate exact ingredient amounts to multiply or reduce any recipe with professional precision.",
74
+ title,
75
+ description,
8
76
  ui: {
9
77
  servings: "Servings",
10
78
  original: "Original",
@@ -25,24 +93,7 @@ export const content: ToolLocaleContent = {
25
93
  defaultIngredient3: "2 Eggs",
26
94
  },
27
95
  faqTitle: "Frequently Asked Questions",
28
- faq: [
29
- {
30
- question: "Why does my conversion factor include decimals?",
31
- answer: "Because culinary proportions aren't always whole numbers. If you scale a 4-person recipe for 7 people, the factor is exactly 1.75. Multiplying by this specific ratio is more accurate than arbitrary rounding.",
32
- },
33
- {
34
- question: "How do I handle fractions like '1/2 tsp'?",
35
- answer: "The parser automatically identifies numbers. It will read '1/2' as '0.5' and scale it accordingly. For maximum clarity, you can also enter decimals directly.",
36
- },
37
- {
38
- question: "Should I round the final results?",
39
- answer: "It depends on the ingredient. For flours and liquids, yes. For potent spices or yeast, we recommend scaling to about 75% of the calculated total to avoid overpowering the dish.",
40
- },
41
- {
42
- question: "Does it work with cups and ounces?",
43
- answer: "Yes, the tool scales any numerical value. However, we strongly recommend converting to grams first for professional-grade consistency across larger batches.",
44
- },
45
- ],
96
+ faq,
46
97
  bibliographyTitle: "Bibliography & Resources",
47
98
  bibliography: [
48
99
  {
@@ -58,20 +109,7 @@ export const content: ToolLocaleContent = {
58
109
  url: "https://www.modernistcuisine.com/",
59
110
  },
60
111
  ],
61
- howTo: [
62
- {
63
- name: "Enter your servings count",
64
- text: "Define how many people the recipe was originally for, and how many you want to cook for now.",
65
- },
66
- {
67
- name: "Paste your ingredient list",
68
- text: "Copy and paste your entire list. Our tool recognizes numbers at the start of each line (e.g., 500g, 1/2, 2.5) and scales them instantly.",
69
- },
70
- {
71
- name: "Apply professional adjustments",
72
- text: "Math is exact, but cooking is situational. Scale spices to 75%. Don't scale cooking times. Use your chef's intuition for the final touch.",
73
- },
74
- ],
112
+ howTo,
75
113
  seo: [
76
114
  {
77
115
  type: "title",
@@ -200,66 +238,5 @@ export const content: ToolLocaleContent = {
200
238
  },
201
239
  ],
202
240
 
203
- schemas: [
204
- {
205
- '@context': 'https://schema.org',
206
- '@type': 'WebApplication',
207
- name: 'Ingredient Rescaler',
208
- description: 'Scale recipes automatically based on the number of servings. Calculate exact ingredient quantities by multiplying or reducing your recipe without complications.',
209
- url: 'https://jjlmoya.es/en/ingredient-rescaler',
210
- applicationCategory: 'Utilities',
211
- inLanguage: 'en-US',
212
- offers: {
213
- '@type': 'Offer',
214
- price: '0',
215
- priceCurrency: 'EUR',
216
- },
217
- },
218
- {
219
- '@context': 'https://schema.org',
220
- '@type': 'Article',
221
- headline: 'Ingredient Rescaler - Scale Your Recipes Easily',
222
- description: 'Scale recipes automatically based on the number of servings. Calculate exact ingredient quantities by multiplying or reducing your recipe without complications.',
223
- author: {
224
- '@type': 'Person',
225
- name: 'jjlmoya',
226
- },
227
- inLanguage: 'en-US',
228
- isPartOf: {
229
- '@type': 'WebSite',
230
- name: 'jjlmoya Utilities',
231
- url: 'https://jjlmoya.es',
232
- },
233
- },
234
- {
235
- '@context': 'https://schema.org',
236
- '@type': 'BreadcrumbList',
237
- itemListElement: [
238
- {
239
- '@type': 'ListItem',
240
- position: 1,
241
- name: 'Home',
242
- item: 'https://jjlmoya.es/en',
243
- },
244
- {
245
- '@type': 'ListItem',
246
- position: 2,
247
- name: 'Utilities',
248
- item: 'https://jjlmoya.es/en/utilities',
249
- },
250
- {
251
- '@type': 'ListItem',
252
- position: 3,
253
- name: 'Cooking',
254
- item: 'https://jjlmoya.es/en/cooking',
255
- },
256
- {
257
- '@type': 'ListItem',
258
- position: 4,
259
- name: 'Ingredient Rescaler',
260
- item: 'https://jjlmoya.es/en/ingredient-rescaler',
261
- },
262
- ],
263
- },
264
- ],
241
+ schemas: [appSchema, faqSchema, howToSchema],
265
242
  };
@@ -1,9 +1,81 @@
1
1
  import type { ToolLocaleContent } from '../../../types';
2
2
 
3
+ const title = 'Escalador de Ingredientes Ajuste de Recetas';
4
+ const description = 'Escala recetas automáticamente según el número de raciones. Calcula las cantidades exactas de ingredientes multiplicando o reduciendo tu receta sin complicaciones.';
5
+
6
+ const faq = [
7
+ {
8
+ question: '¿Por qué mi factor de conversión incluye decimales?',
9
+ answer: 'Porque las proporciones culinarias no siempre son redondas. Si escalas una receta para 4 personas a 7, el factor es 1.75 exactamente. Los ingredientes se multiplican por ese número, aunque encuentres fracciones. Es más exacto que redondear arbitrariamente.',
10
+ },
11
+ {
12
+ question: '¿Qué pasa si ingreso "1/2 cucharadita de sal"?',
13
+ answer: 'El parser busca el número primero. Reconocerá "1" como cantidad, luego "/2" como parte de la unidad. El resultado será "0.5", y al escalar se multiplicará correctamente. Para fracciones como "1/2", ingresa "0.5" directamente (más claro) o la herramienta las interpreta como división.',
14
+ },
15
+ {
16
+ question: '¿Debo redondear los resultados finales?',
17
+ answer: 'Depende del ingrediente. Para harinas, sí. Para levaduras o especias, la precisión importa menos (escala al 75% de lo indicado). Para huevos: si obtienes 2.3, usa 2 completos + parte de un tercero (pesada), o redondea a 2 si el plato lo permite.',
18
+ },
19
+ {
20
+ question: '¿Por qué no cambia el resultado cuando cambio las raciones?',
21
+ answer: 'Asegúrate de que el campo de ingredientes tenga contenido. Si está vacío, no hay nada que escalar. También verifica que los números en tus ingredientes sean reconocibles (ej: "500g", "1/2 cucharadita").',
22
+ },
23
+ {
24
+ question: '¿Funciona con medidas imperiales (onzas, tazas)?',
25
+ answer: 'Técnicamente sí, la herramienta lee números y escala. Pero la precisión es limitada con tazas (volumen inconsistente). Se recomienda convertir a gramos antes de escalar.',
26
+ },
27
+ ];
28
+
29
+ const howTo = [
30
+ {
31
+ name: 'Ingresa tus raciones',
32
+ text: 'En el campo "Original", coloca el número de personas para el que la receta está diseñada. En "Deseado", coloca el número de personas que vas a cocinar.',
33
+ },
34
+ {
35
+ name: 'Pega tu lista de ingredientes',
36
+ text: 'Copia y pega tu lista tal cual. Cada ingrediente en una línea. La herramienta reconoce números al inicio (500g, 1/2, 2.5) y escala automáticamente.',
37
+ },
38
+ {
39
+ name: 'Ajusta según contexto',
40
+ text: 'Los resultados son matemáticamente exactos, pero la cocina es arte. Especias: escala al 75%. Levaduras: menos de lo teórico en grandes cantidades. Tiempos: no se escalan nunca.',
41
+ },
42
+ ];
43
+
44
+ const faqSchema = {
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
+
54
+ const howToSchema = {
55
+ '@context': 'https://schema.org',
56
+ '@type': 'HowTo',
57
+ name: title,
58
+ description,
59
+ step: howTo.map((step) => ({
60
+ '@type': 'HowToStep',
61
+ name: step.name,
62
+ text: step.text,
63
+ })),
64
+ };
65
+
66
+ const appSchema = {
67
+ '@context': 'https://schema.org',
68
+ '@type': 'SoftwareApplication',
69
+ name: title,
70
+ description,
71
+ applicationCategory: 'UtilitiesApplication',
72
+ operatingSystem: 'All',
73
+ };
74
+
3
75
  export const content: ToolLocaleContent = {
4
76
  slug: 'reescalador-ingredientes',
5
- title: 'Escalador de Ingredientes Ajuste de Recetas',
6
- description: 'Escala recetas automáticamente según el número de raciones. Calcula las cantidades exactas de ingredientes multiplicando o reduciendo tu receta sin complicaciones.',
77
+ title,
78
+ description,
7
79
  ui: {
8
80
  servings: 'Raciones',
9
81
  original: 'Original',
@@ -24,28 +96,7 @@ export const content: ToolLocaleContent = {
24
96
  defaultIngredient3: '2 Huevos',
25
97
  },
26
98
  faqTitle: 'Preguntas Frecuentes',
27
- faq: [
28
- {
29
- question: '¿Por qué mi factor de conversión incluye decimales?',
30
- answer: 'Porque las proporciones culinarias no siempre son redondas. Si escalas una receta para 4 personas a 7, el factor es 1.75 exactamente. Los ingredientes se multiplican por ese número, aunque encuentres fracciones. Es más exacto que redondear arbitrariamente.',
31
- },
32
- {
33
- question: '¿Qué pasa si ingreso "1/2 cucharadita de sal"?',
34
- answer: 'El parser busca el número primero. Reconocerá "1" como cantidad, luego "/2" como parte de la unidad. El resultado será "0.5", y al escalar se multiplicará correctamente. Para fracciones como "1/2", ingresa "0.5" directamente (más claro) o la herramienta las interpreta como división.',
35
- },
36
- {
37
- question: '¿Debo redondear los resultados finales?',
38
- answer: 'Depende del ingrediente. Para harinas, sí. Para levaduras o especias, la precisión importa menos (escala al 75% de lo indicado). Para huevos: si obtienes 2.3, usa 2 completos + parte de un tercero (pesada), o redondea a 2 si el plato lo permite.',
39
- },
40
- {
41
- question: '¿Por qué no cambia el resultado cuando cambio las raciones?',
42
- answer: 'Asegúrate de que el campo de ingredientes tenga contenido. Si está vacío, no hay nada que escalar. También verifica que los números en tus ingredientes sean reconocibles (ej: "500g", "1/2 cucharadita").',
43
- },
44
- {
45
- question: '¿Funciona con medidas imperiales (onzas, tazas)?',
46
- answer: 'Técnicamente sí, la herramienta lee números y escala. Pero la precisión es limitada con tazas (volumen inconsistente). Se recomienda convertir a gramos antes de escalar.',
47
- },
48
- ],
99
+ faq,
49
100
  bibliographyTitle: 'Bibliografía',
50
101
  bibliography: [
51
102
  {
@@ -61,20 +112,7 @@ export const content: ToolLocaleContent = {
61
112
  url: 'https://www.modernistcuisine.com/',
62
113
  },
63
114
  ],
64
- howTo: [
65
- {
66
- name: 'Ingresa tus raciones',
67
- text: 'En el campo "Original", coloca el número de personas para el que la receta está diseñada. En "Deseado", coloca el número de personas que vas a cocinar.',
68
- },
69
- {
70
- name: 'Pega tu lista de ingredientes',
71
- text: 'Copia y pega tu lista tal cual. Cada ingrediente en una línea. La herramienta reconoce números al inicio (500g, 1/2, 2.5) y escala automáticamente.',
72
- },
73
- {
74
- name: 'Ajusta según contexto',
75
- text: 'Los resultados son matemáticamente exactos, pero la cocina es arte. Especias: escala al 75%. Levaduras: menos de lo teórico en grandes cantidades. Tiempos: no se escalan nunca.',
76
- },
77
- ],
115
+ howTo,
78
116
  seo: [
79
117
  {
80
118
  type: 'title',
@@ -203,66 +241,5 @@ export const content: ToolLocaleContent = {
203
241
  },
204
242
  ],
205
243
 
206
- schemas: [
207
- {
208
- '@context': 'https://schema.org',
209
- '@type': 'WebApplication',
210
- name: 'Escalador de Ingredientes',
211
- description: 'Escala recetas automáticamente según el número de raciones. Calcula las cantidades exactas de ingredientes multiplicando o reduciendo tu receta sin complicaciones.',
212
- url: 'https://jjlmoya.es/utilidades/escalador-ingredientes',
213
- applicationCategory: 'Utilities',
214
- inLanguage: 'es-ES',
215
- offers: {
216
- '@type': 'Offer',
217
- price: '0',
218
- priceCurrency: 'EUR',
219
- },
220
- },
221
- {
222
- '@context': 'https://schema.org',
223
- '@type': 'Article',
224
- headline: 'Escalador de Ingredientes - Ajusta tus Recetas Fácilmente',
225
- description: 'Escala recetas automáticamente según el número de raciones. Calcula las cantidades exactas de ingredientes multiplicando o reduciendo tu receta sin complicaciones.',
226
- author: {
227
- '@type': 'Person',
228
- name: 'jjlmoya',
229
- },
230
- inLanguage: 'es-ES',
231
- isPartOf: {
232
- '@type': 'WebSite',
233
- name: 'Utilidades jjlmoya',
234
- url: 'https://jjlmoya.es',
235
- },
236
- },
237
- {
238
- '@context': 'https://schema.org',
239
- '@type': 'BreadcrumbList',
240
- itemListElement: [
241
- {
242
- '@type': 'ListItem',
243
- position: 1,
244
- name: 'Inicio',
245
- item: 'https://jjlmoya.es',
246
- },
247
- {
248
- '@type': 'ListItem',
249
- position: 2,
250
- name: 'Utilidades',
251
- item: 'https://jjlmoya.es/utilidades',
252
- },
253
- {
254
- '@type': 'ListItem',
255
- position: 3,
256
- name: 'Cocina',
257
- item: 'https://jjlmoya.es/utilidades/cocina',
258
- },
259
- {
260
- '@type': 'ListItem',
261
- position: 4,
262
- name: 'Escalador de Ingredientes',
263
- item: 'https://jjlmoya.es/utilidades/escalador-ingredientes',
264
- },
265
- ],
266
- },
267
- ],
244
+ schemas: [appSchema, faqSchema, howToSchema],
268
245
  };
@@ -262,7 +262,7 @@ export const content: ToolLocaleContent = {
262
262
  {
263
263
  type: "diagnostic",
264
264
  variant: "warning",
265
- title: "Votre Meringue rejette-t-elle du Liquide ?",
265
+ title: "Votre Meringue rejette t elle du Liquide ?",
266
266
  html: "Si vous voyez du sirop s'échapper (synérèse), c'est soit que le sucre n'était pas dissous, soit que l'humidité ambiante est trop forte. Pour l'italienne, versez le sirop en filet constant, jamais directement sur le fouet.",
267
267
  },
268
268
  {