@jjlmoya/utils-converters 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.
Files changed (172) hide show
  1. package/package.json +61 -0
  2. package/src/category/i18n/en.ts +90 -0
  3. package/src/category/i18n/es.ts +90 -0
  4. package/src/category/i18n/fr.ts +90 -0
  5. package/src/category/index.ts +39 -0
  6. package/src/category/seo.astro +15 -0
  7. package/src/components/PreviewNavSidebar.astro +116 -0
  8. package/src/components/PreviewToolbar.astro +152 -0
  9. package/src/data.ts +34 -0
  10. package/src/env.d.ts +5 -0
  11. package/src/index.ts +39 -0
  12. package/src/layouts/PreviewLayout.astro +117 -0
  13. package/src/pages/[locale]/[slug].astro +148 -0
  14. package/src/pages/[locale].astro +271 -0
  15. package/src/pages/index.astro +4 -0
  16. package/src/shared/ImageConverter.astro +237 -0
  17. package/src/shared/logic/converter.ts +167 -0
  18. package/src/shared/style.css +258 -0
  19. package/src/tests/faq_count.test.ts +10 -0
  20. package/src/tests/mocks/astro_mock.js +2 -0
  21. package/src/tests/seo_length.test.ts +22 -0
  22. package/src/tests/tool_validation.test.ts +17 -0
  23. package/src/tool/avifAJpg/bibliography.astro +14 -0
  24. package/src/tool/avifAJpg/component.astro +8 -0
  25. package/src/tool/avifAJpg/i18n/en.ts +123 -0
  26. package/src/tool/avifAJpg/i18n/es.ts +123 -0
  27. package/src/tool/avifAJpg/i18n/fr.ts +118 -0
  28. package/src/tool/avifAJpg/index.ts +29 -0
  29. package/src/tool/avifAJpg/seo.astro +14 -0
  30. package/src/tool/avifAPng/bibliography.astro +14 -0
  31. package/src/tool/avifAPng/component.astro +8 -0
  32. package/src/tool/avifAPng/i18n/en.ts +118 -0
  33. package/src/tool/avifAPng/i18n/es.ts +123 -0
  34. package/src/tool/avifAPng/i18n/fr.ts +118 -0
  35. package/src/tool/avifAPng/index.ts +29 -0
  36. package/src/tool/avifAPng/seo.astro +14 -0
  37. package/src/tool/avifAWebp/bibliography.astro +14 -0
  38. package/src/tool/avifAWebp/component.astro +8 -0
  39. package/src/tool/avifAWebp/i18n/en.ts +118 -0
  40. package/src/tool/avifAWebp/i18n/es.ts +123 -0
  41. package/src/tool/avifAWebp/i18n/fr.ts +118 -0
  42. package/src/tool/avifAWebp/index.ts +29 -0
  43. package/src/tool/avifAWebp/seo.astro +14 -0
  44. package/src/tool/bmpAJpg/bibliography.astro +14 -0
  45. package/src/tool/bmpAJpg/component.astro +8 -0
  46. package/src/tool/bmpAJpg/i18n/en.ts +123 -0
  47. package/src/tool/bmpAJpg/i18n/es.ts +123 -0
  48. package/src/tool/bmpAJpg/i18n/fr.ts +118 -0
  49. package/src/tool/bmpAJpg/index.ts +29 -0
  50. package/src/tool/bmpAJpg/seo.astro +14 -0
  51. package/src/tool/bmpAPng/bibliography.astro +14 -0
  52. package/src/tool/bmpAPng/component.astro +8 -0
  53. package/src/tool/bmpAPng/i18n/en.ts +123 -0
  54. package/src/tool/bmpAPng/i18n/es.ts +123 -0
  55. package/src/tool/bmpAPng/i18n/fr.ts +118 -0
  56. package/src/tool/bmpAPng/index.ts +29 -0
  57. package/src/tool/bmpAPng/seo.astro +14 -0
  58. package/src/tool/bmpAWebp/bibliography.astro +14 -0
  59. package/src/tool/bmpAWebp/component.astro +8 -0
  60. package/src/tool/bmpAWebp/i18n/en.ts +118 -0
  61. package/src/tool/bmpAWebp/i18n/es.ts +123 -0
  62. package/src/tool/bmpAWebp/i18n/fr.ts +118 -0
  63. package/src/tool/bmpAWebp/index.ts +29 -0
  64. package/src/tool/bmpAWebp/seo.astro +14 -0
  65. package/src/tool/gifAJpg/bibliography.astro +14 -0
  66. package/src/tool/gifAJpg/component.astro +8 -0
  67. package/src/tool/gifAJpg/i18n/en.ts +123 -0
  68. package/src/tool/gifAJpg/i18n/es.ts +123 -0
  69. package/src/tool/gifAJpg/i18n/fr.ts +118 -0
  70. package/src/tool/gifAJpg/index.ts +29 -0
  71. package/src/tool/gifAJpg/seo.astro +14 -0
  72. package/src/tool/gifAPng/bibliography.astro +14 -0
  73. package/src/tool/gifAPng/component.astro +8 -0
  74. package/src/tool/gifAPng/i18n/en.ts +123 -0
  75. package/src/tool/gifAPng/i18n/es.ts +123 -0
  76. package/src/tool/gifAPng/i18n/fr.ts +118 -0
  77. package/src/tool/gifAPng/index.ts +29 -0
  78. package/src/tool/gifAPng/seo.astro +14 -0
  79. package/src/tool/gifAWebp/bibliography.astro +14 -0
  80. package/src/tool/gifAWebp/component.astro +8 -0
  81. package/src/tool/gifAWebp/i18n/en.ts +123 -0
  82. package/src/tool/gifAWebp/i18n/es.ts +123 -0
  83. package/src/tool/gifAWebp/i18n/fr.ts +118 -0
  84. package/src/tool/gifAWebp/index.ts +29 -0
  85. package/src/tool/gifAWebp/seo.astro +14 -0
  86. package/src/tool/imagenBase64/bibliography.astro +14 -0
  87. package/src/tool/imagenBase64/component.astro +159 -0
  88. package/src/tool/imagenBase64/i18n/en.ts +137 -0
  89. package/src/tool/imagenBase64/i18n/es.ts +137 -0
  90. package/src/tool/imagenBase64/i18n/fr.ts +132 -0
  91. package/src/tool/imagenBase64/index.ts +43 -0
  92. package/src/tool/imagenBase64/seo.astro +14 -0
  93. package/src/tool/imagenBase64/style.css +299 -0
  94. package/src/tool/jpgAIco/bibliography.astro +14 -0
  95. package/src/tool/jpgAIco/component.astro +8 -0
  96. package/src/tool/jpgAIco/i18n/en.ts +123 -0
  97. package/src/tool/jpgAIco/i18n/es.ts +123 -0
  98. package/src/tool/jpgAIco/i18n/fr.ts +118 -0
  99. package/src/tool/jpgAIco/index.ts +29 -0
  100. package/src/tool/jpgAIco/seo.astro +14 -0
  101. package/src/tool/jpgAPng/bibliography.astro +14 -0
  102. package/src/tool/jpgAPng/component.astro +8 -0
  103. package/src/tool/jpgAPng/i18n/en.ts +128 -0
  104. package/src/tool/jpgAPng/i18n/es.ts +128 -0
  105. package/src/tool/jpgAPng/i18n/fr.ts +123 -0
  106. package/src/tool/jpgAPng/index.ts +29 -0
  107. package/src/tool/jpgAPng/seo.astro +14 -0
  108. package/src/tool/jpgAWebp/bibliography.astro +14 -0
  109. package/src/tool/jpgAWebp/component.astro +8 -0
  110. package/src/tool/jpgAWebp/i18n/en.ts +118 -0
  111. package/src/tool/jpgAWebp/i18n/es.ts +123 -0
  112. package/src/tool/jpgAWebp/i18n/fr.ts +118 -0
  113. package/src/tool/jpgAWebp/index.ts +29 -0
  114. package/src/tool/jpgAWebp/seo.astro +14 -0
  115. package/src/tool/pngAIco/bibliography.astro +14 -0
  116. package/src/tool/pngAIco/component.astro +8 -0
  117. package/src/tool/pngAIco/i18n/en.ts +123 -0
  118. package/src/tool/pngAIco/i18n/es.ts +123 -0
  119. package/src/tool/pngAIco/i18n/fr.ts +118 -0
  120. package/src/tool/pngAIco/index.ts +29 -0
  121. package/src/tool/pngAIco/seo.astro +14 -0
  122. package/src/tool/pngAJpg/bibliography.astro +14 -0
  123. package/src/tool/pngAJpg/component.astro +8 -0
  124. package/src/tool/pngAJpg/i18n/en.ts +133 -0
  125. package/src/tool/pngAJpg/i18n/es.ts +201 -0
  126. package/src/tool/pngAJpg/i18n/fr.ts +128 -0
  127. package/src/tool/pngAJpg/index.ts +29 -0
  128. package/src/tool/pngAJpg/seo.astro +14 -0
  129. package/src/tool/pngAWebp/bibliography.astro +14 -0
  130. package/src/tool/pngAWebp/component.astro +8 -0
  131. package/src/tool/pngAWebp/i18n/en.ts +127 -0
  132. package/src/tool/pngAWebp/i18n/es.ts +132 -0
  133. package/src/tool/pngAWebp/i18n/fr.ts +122 -0
  134. package/src/tool/pngAWebp/index.ts +29 -0
  135. package/src/tool/pngAWebp/seo.astro +14 -0
  136. package/src/tool/svgAJpg/bibliography.astro +14 -0
  137. package/src/tool/svgAJpg/component.astro +8 -0
  138. package/src/tool/svgAJpg/i18n/en.ts +118 -0
  139. package/src/tool/svgAJpg/i18n/es.ts +123 -0
  140. package/src/tool/svgAJpg/i18n/fr.ts +118 -0
  141. package/src/tool/svgAJpg/index.ts +29 -0
  142. package/src/tool/svgAJpg/seo.astro +14 -0
  143. package/src/tool/svgAPng/bibliography.astro +14 -0
  144. package/src/tool/svgAPng/component.astro +8 -0
  145. package/src/tool/svgAPng/i18n/en.ts +123 -0
  146. package/src/tool/svgAPng/i18n/es.ts +128 -0
  147. package/src/tool/svgAPng/i18n/fr.ts +118 -0
  148. package/src/tool/svgAPng/index.ts +29 -0
  149. package/src/tool/svgAPng/seo.astro +14 -0
  150. package/src/tool/webpAIco/bibliography.astro +14 -0
  151. package/src/tool/webpAIco/component.astro +8 -0
  152. package/src/tool/webpAIco/i18n/en.ts +123 -0
  153. package/src/tool/webpAIco/i18n/es.ts +123 -0
  154. package/src/tool/webpAIco/i18n/fr.ts +118 -0
  155. package/src/tool/webpAIco/index.ts +29 -0
  156. package/src/tool/webpAIco/seo.astro +14 -0
  157. package/src/tool/webpAJpg/bibliography.astro +14 -0
  158. package/src/tool/webpAJpg/component.astro +8 -0
  159. package/src/tool/webpAJpg/i18n/en.ts +122 -0
  160. package/src/tool/webpAJpg/i18n/es.ts +127 -0
  161. package/src/tool/webpAJpg/i18n/fr.ts +122 -0
  162. package/src/tool/webpAJpg/index.ts +29 -0
  163. package/src/tool/webpAJpg/seo.astro +14 -0
  164. package/src/tool/webpAPng/bibliography.astro +14 -0
  165. package/src/tool/webpAPng/component.astro +8 -0
  166. package/src/tool/webpAPng/i18n/en.ts +127 -0
  167. package/src/tool/webpAPng/i18n/es.ts +132 -0
  168. package/src/tool/webpAPng/i18n/fr.ts +122 -0
  169. package/src/tool/webpAPng/index.ts +29 -0
  170. package/src/tool/webpAPng/seo.astro +14 -0
  171. package/src/tools.ts +70 -0
  172. package/src/types.ts +69 -0
@@ -0,0 +1,29 @@
1
+ import type { ConvertersToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
2
+ import type { ImageConverterUI } from '../../shared/ImageConverter.astro';
3
+ import BmpAWebpCalculator from './component.astro';
4
+ import BmpAWebpSEO from './seo.astro';
5
+ import BmpAWebpBibliography from './bibliography.astro';
6
+
7
+ export type BmpAWebpLocaleContent = ToolLocaleContent<ImageConverterUI>;
8
+
9
+ export const bmpAWebp: ConvertersToolEntry<ImageConverterUI> = {
10
+ id: 'bmp-a-webp',
11
+ icons: {
12
+ bg: 'mdi:file-image',
13
+ fg: 'mdi:file-export',
14
+ },
15
+ i18n: {
16
+ es: () => import('./i18n/es').then((m) => m.content),
17
+ en: () => import('./i18n/en').then((m) => m.content),
18
+ fr: () => import('./i18n/fr').then((m) => m.content),
19
+ },
20
+ };
21
+
22
+ export { BmpAWebpCalculator, BmpAWebpSEO, BmpAWebpBibliography };
23
+
24
+ export const BMP_A_WEBP_TOOL: ToolDefinition = {
25
+ entry: bmpAWebp,
26
+ Component: BmpAWebpCalculator,
27
+ SEOComponent: BmpAWebpSEO,
28
+ BibliographyComponent: BmpAWebpBibliography,
29
+ };
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { bmpAWebp } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await bmpAWebp.i18n[locale]?.();
12
+ ---
13
+
14
+ {content && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
+ import { gifAJpg } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await gifAJpg.i18n[locale]?.();
12
+ ---
13
+
14
+ {content && <SharedBibliography links={content.bibliography} title={content.ui.bibliographyTitle} />}
@@ -0,0 +1,8 @@
1
+ ---
2
+ import SharedImageConverter from '../../shared/ImageConverter.astro';
3
+ import type { ImageConverterUI } from '../../shared/ImageConverter.astro';
4
+
5
+ interface Props { ui: ImageConverterUI }
6
+ const { ui } = Astro.props;
7
+ ---
8
+ <SharedImageConverter from="gif" to="jpg" ui={ui} />
@@ -0,0 +1,123 @@
1
+ import type { WithContext, SoftwareApplication } from 'schema-dts';
2
+ import type { ImageConverterUI } from '../../../shared/ImageConverter.astro';
3
+ import type { GifAJpgLocaleContent } from '../index';
4
+
5
+ const slug = 'gif-to-jpg-converter';
6
+ const title = 'Convert GIF to JPG Online | Turn Your Animations into Static Photos';
7
+ const description =
8
+ 'Extract the first frame of your GIFs and convert to JPG. No server. Processed locally in your browser. Free and unlimited.';
9
+
10
+ const ui: ImageConverterUI = {
11
+ dragText: 'Drag GIF files...',
12
+ convertText: 'To convert them to JPG instantly',
13
+ selectFiles: 'Select files',
14
+ processedFiles: 'Processed files',
15
+ downloadAll: 'Download All (.zip)',
16
+ pending: 'Pending',
17
+ bibliographyTitle: 'Bibliographic References',
18
+ faqTitle: 'Frequently Asked Questions',
19
+ };
20
+
21
+ const faq: GifAJpgLocaleContent['faq'] = [
22
+ {
23
+ question: 'What happens to animations when converting to JPG?',
24
+ answer:
25
+ 'JPG is strictly static and does not support multiple frames. Our converter extracts only the first image or frame appearing in the GIF sequence.',
26
+ },
27
+ {
28
+ question: 'Will I lose any special effects or transparent backgrounds?',
29
+ answer:
30
+ 'Yes, this is the natural behavior of the JPG standard. If you upload a GIF with a transparent background, we automatically insert a solid white underlying layer to avoid corrupted colors.',
31
+ },
32
+ {
33
+ question: 'Can I extract JPG photos from a GIF without the website saving my content?',
34
+ answer:
35
+ 'Absolutely yes. The tool is a Web App based on the HTML5 Canvas. All decoding is executed by the processor of your own physical device.',
36
+ },
37
+ ];
38
+
39
+ const howTo: GifAJpgLocaleContent['howTo'] = [
40
+ {
41
+ name: 'Drag your animated GIF files',
42
+ text: 'Place or drag from your folder that GIF into our processing box.',
43
+ },
44
+ {
45
+ name: 'Clean first-frame extraction',
46
+ text: 'In fractions of time the animation is extracted creating the solid white JPG without contacting servers.',
47
+ },
48
+ {
49
+ name: 'Download them in bulk ZIP',
50
+ text: 'Download via the buttons or using Zip if you processed a large number of files.',
51
+ },
52
+ ];
53
+
54
+ const bibliography: GifAJpgLocaleContent['bibliography'] = [
55
+ {
56
+ name: 'Joint Photographic Experts Group Technical Specification',
57
+ url: 'https://en.wikipedia.org/wiki/JPEG',
58
+ },
59
+ {
60
+ name: 'CompuServe GIF Information',
61
+ url: 'https://www.w3.org/Graphics/GIF/spec-gif89a.txt',
62
+ },
63
+ ];
64
+
65
+ const seo: GifAJpgLocaleContent['seo'] = [
66
+ {
67
+ type: 'title',
68
+ text: 'Free Online GIF to JPG Converter',
69
+ },
70
+ {
71
+ type: 'paragraph',
72
+ html:
73
+ 'GIF files are widely known for their ability to play short animations. However, there are situations where you need a static image from GIF content: to use it as a thumbnail, send it by email, or simply to get a high-quality version of a specific moment in the animation.',
74
+ },
75
+ {
76
+ type: 'paragraph',
77
+ html:
78
+ 'Converting GIF to JPG extracts the first frame of the animation and converts it into a static JPG image. During this process, any transparent areas in the original GIF are replaced with a solid white background, since JPG does not support transparency.',
79
+ },
80
+ {
81
+ type: 'tip',
82
+ html:
83
+ 'If you need to extract multiple frames from an animated GIF (not just the first), consider using a specialized GIF editing tool. This converter is optimized for quickly getting the static image of the first frame.',
84
+ },
85
+ {
86
+ type: 'paragraph',
87
+ html:
88
+ 'A 2 MB animated GIF can produce a JPG of the first frame of just 50-200 KB, depending on the resolution and complexity of the image.',
89
+ },
90
+ {
91
+ type: 'paragraph',
92
+ html:
93
+ 'Our converter loads the GIF into the browser\'s native Image element, draws it on an HTML5 canvas and exports it as JPG. This process is completely local: no data is sent to any server. You can convert GIFs with complete privacy.',
94
+ },
95
+ {
96
+ type: 'paragraph',
97
+ html:
98
+ 'Convert GIF to JPG by extracting the first frame. Free, private and local. Transparent backgrounds automatically replaced with white for full JPG compatibility.',
99
+ },
100
+ ];
101
+
102
+ const appSchema: WithContext<SoftwareApplication> = {
103
+ '@context': 'https://schema.org',
104
+ '@type': 'SoftwareApplication',
105
+ name: title,
106
+ description,
107
+ applicationCategory: 'UtilitiesApplication',
108
+ operatingSystem: 'Web',
109
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
110
+ inLanguage: 'en',
111
+ };
112
+
113
+ export const content: GifAJpgLocaleContent = {
114
+ slug,
115
+ title,
116
+ description,
117
+ ui,
118
+ seo,
119
+ faq,
120
+ bibliography,
121
+ howTo,
122
+ schemas: [appSchema as any],
123
+ };
@@ -0,0 +1,123 @@
1
+ import type { WithContext, SoftwareApplication } from 'schema-dts';
2
+ import type { ImageConverterUI } from '../../../shared/ImageConverter.astro';
3
+ import type { GifAJpgLocaleContent } from '../index';
4
+
5
+ const slug = 'convertidor-gif-a-jpg';
6
+ const title = 'Convertir GIF a JPG Online | Vuelve tus animaciones fotos estáticas';
7
+ const description =
8
+ 'Extrae el primer fotograma de tus GIF y conviértelo a JPG. Sin servidor. Procesado local en tu navegador. Gratis e ilimitado.';
9
+
10
+ const ui: ImageConverterUI = {
11
+ dragText: 'Arrastra archivos GIF...',
12
+ convertText: 'Para convertirlos a JPG al instante',
13
+ selectFiles: 'Seleccionar archivos',
14
+ processedFiles: 'Archivos procesados',
15
+ downloadAll: 'Descargar Todo (.zip)',
16
+ pending: 'Pendiente',
17
+ bibliographyTitle: 'Referencias Bibliográficas',
18
+ faqTitle: 'Preguntas Frecuentes',
19
+ };
20
+
21
+ const faq: GifAJpgLocaleContent['faq'] = [
22
+ {
23
+ question: '¿Qué ocurre con las animaciones cuando paso a JPG?',
24
+ answer:
25
+ 'El formato JPG es estrictamente estático y no soporta múltiples fotogramas. Nuestro convertidor extrae únicamente la primera imagen o fotograma que aparece en la secuencia del GIF.',
26
+ },
27
+ {
28
+ question: '¿Perderé algún efecto especial o fondo transparente?',
29
+ answer:
30
+ 'Sí, es el comportamiento natural del estándar JPG. Si subes un GIF con fondo libre, insertamos automáticamente una capa sólida blanca subyacente para evitar colores corruptos.',
31
+ },
32
+ {
33
+ question: '¿Puedo extraer fotos JPG de un GIF sin que la web guarde mi contenido?',
34
+ answer:
35
+ 'Absolutamente sí. La herramienta es una App Web basada en el Canvas del HTML5. Toda la decodificación la ejecuta el procesador de tu propio dispositivo físico.',
36
+ },
37
+ ];
38
+
39
+ const howTo: GifAJpgLocaleContent['howTo'] = [
40
+ {
41
+ name: 'Arrastra Archivos Pesados Movibles',
42
+ text: 'Sitúa o arrastra desde tu carpeta ese GIF hasta arrojarlo a nuestra caja de procesamiento.',
43
+ },
44
+ {
45
+ name: 'Cálculo Limpio de Fotograma Primero',
46
+ text: 'En fracciones de tiempo se extrae la animación creando el JPG blanco sólido sin contactar servidores.',
47
+ },
48
+ {
49
+ name: 'Captúralos Empaquetados en Masa ZIP',
50
+ text: 'Descarga a los botones o usando el Zip si procesaste un centenar largo de archivos.',
51
+ },
52
+ ];
53
+
54
+ const bibliography: GifAJpgLocaleContent['bibliography'] = [
55
+ {
56
+ name: 'Especificación Técnica Joint Photographic Experts Group',
57
+ url: 'https://en.wikipedia.org/wiki/JPEG',
58
+ },
59
+ {
60
+ name: 'CompuServe GIF Information',
61
+ url: 'https://www.w3.org/Graphics/GIF/spec-gif89a.txt',
62
+ },
63
+ ];
64
+
65
+ const seo: GifAJpgLocaleContent['seo'] = [
66
+ {
67
+ type: 'title',
68
+ text: 'Convertidor GIF a JPG Online Gratuito',
69
+ },
70
+ {
71
+ type: 'paragraph',
72
+ html:
73
+ 'Los archivos GIF son ampliamente conocidos por su capacidad de reproducir animaciones cortas. Sin embargo, hay situaciones en que necesitas una imagen estática del contenido de un GIF: para usarla como miniatura, para enviarla por correo, o simplemente para obtener una versión de alta calidad de un momento específico de la animación.',
74
+ },
75
+ {
76
+ type: 'paragraph',
77
+ html:
78
+ 'Convertir GIF a JPG extrae el primer fotograma de la animación y lo convierte en una imagen JPG estática. Durante este proceso, cualquier área transparente del GIF original (frecuente en GIFs animados con fondos transparentes) se sustituye por un fondo blanco sólido, ya que el formato JPG no soporta transparencias.',
79
+ },
80
+ {
81
+ type: 'paragraph',
82
+ html:
83
+ 'Nuestro convertidor carga el GIF en el elemento Image nativo del navegador, lo dibuja en un canvas HTML5 y lo exporta como JPG. Este proceso es completamente local: no se envían datos a ningún servidor. Puedes convertir GIFs con total privacidad.',
84
+ },
85
+ {
86
+ type: 'tip',
87
+ html:
88
+ 'Si necesitas extraer múltiples fotogramas de un GIF animado (no solo el primero), considera usar una herramienta especializada en edición de GIFs. Este convertidor está optimizado para obtener la imagen estática del primer fotograma de forma rápida.',
89
+ },
90
+ {
91
+ type: 'paragraph',
92
+ html:
93
+ 'Un GIF animado de 2 MB puede producir un JPG del primer fotograma de apenas 50-200 KB, dependiendo de la resolución y complejidad de la imagen.',
94
+ },
95
+ {
96
+ type: 'paragraph',
97
+ html:
98
+ 'Convierte GIF a JPG extrayendo el primer fotograma. Gratis, privado y local. Fondos transparentes sustituidos automáticamente por blanco para compatibilidad total con JPG.',
99
+ },
100
+ ];
101
+
102
+ const appSchema: WithContext<SoftwareApplication> = {
103
+ '@context': 'https://schema.org',
104
+ '@type': 'SoftwareApplication',
105
+ name: title,
106
+ description,
107
+ applicationCategory: 'UtilitiesApplication',
108
+ operatingSystem: 'Web',
109
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
110
+ inLanguage: 'es',
111
+ };
112
+
113
+ export const content: GifAJpgLocaleContent = {
114
+ slug,
115
+ title,
116
+ description,
117
+ ui,
118
+ seo,
119
+ faq,
120
+ bibliography,
121
+ howTo,
122
+ schemas: [appSchema as any],
123
+ };
@@ -0,0 +1,118 @@
1
+ import type { WithContext, SoftwareApplication } from 'schema-dts';
2
+ import type { ImageConverterUI } from '../../../shared/ImageConverter.astro';
3
+ import type { GifAJpgLocaleContent } from '../index';
4
+
5
+ const slug = 'convertisseur-gif-en-jpg';
6
+ const title = 'Convertir GIF en JPG en Ligne | Transformez vos Animations en Photos Statiques';
7
+ const description =
8
+ 'Extrayez la première image de vos GIF et convertissez en JPG. Sans serveur. Traitement local dans votre navigateur. Gratuit et illimité.';
9
+
10
+ const ui: ImageConverterUI = {
11
+ dragText: 'Faites glisser des fichiers GIF...',
12
+ convertText: 'Pour les convertir en JPG instantanément',
13
+ selectFiles: 'Sélectionner des fichiers',
14
+ processedFiles: 'Fichiers traités',
15
+ downloadAll: 'Tout télécharger (.zip)',
16
+ pending: 'En attente',
17
+ bibliographyTitle: 'Références Bibliographiques',
18
+ faqTitle: 'Questions Fréquentes',
19
+ };
20
+
21
+ const faq: GifAJpgLocaleContent['faq'] = [
22
+ {
23
+ question: 'Que se passe-t-il avec les animations lors de la conversion en JPG ?',
24
+ answer:
25
+ 'Le JPG est strictement statique et ne supporte pas plusieurs images. Notre convertisseur extrait uniquement la première image ou trame apparaissant dans la séquence GIF.',
26
+ },
27
+ {
28
+ question: 'Vais-je perdre des effets spéciaux ou des fonds transparents ?',
29
+ answer:
30
+ 'Oui, c\'est le comportement naturel du standard JPG. Si vous téléchargez un GIF avec fond transparent, nous insérons automatiquement une couche blanche sous-jacente solide pour éviter des couleurs corrompues.',
31
+ },
32
+ {
33
+ question: 'Puis-je extraire des photos JPG d\'un GIF sans que le site sauvegarde mon contenu ?',
34
+ answer:
35
+ 'Absolument oui. L\'outil est une application web basée sur le Canvas HTML5. Tout le décodage est exécuté par le processeur de votre propre appareil physique.',
36
+ },
37
+ ];
38
+
39
+ const howTo: GifAJpgLocaleContent['howTo'] = [
40
+ {
41
+ name: 'Faites glisser vos fichiers GIF animés',
42
+ text: 'Placez ou faites glisser depuis votre dossier ce GIF dans notre boîte de traitement.',
43
+ },
44
+ {
45
+ name: 'Extraction propre de la première image',
46
+ text: 'En fractions de temps, l\'animation est extraite créant le JPG blanc solide sans contacter de serveurs.',
47
+ },
48
+ {
49
+ name: 'Téléchargez-les en lot ZIP',
50
+ text: 'Téléchargez via les boutons ou en utilisant le Zip si vous avez traité un grand nombre de fichiers.',
51
+ },
52
+ ];
53
+
54
+ const bibliography: GifAJpgLocaleContent['bibliography'] = [
55
+ {
56
+ name: 'Spécification Technique Joint Photographic Experts Group',
57
+ url: 'https://en.wikipedia.org/wiki/JPEG',
58
+ },
59
+ {
60
+ name: 'Information GIF CompuServe',
61
+ url: 'https://www.w3.org/Graphics/GIF/spec-gif89a.txt',
62
+ },
63
+ ];
64
+
65
+ const seo: GifAJpgLocaleContent['seo'] = [
66
+ {
67
+ type: 'title',
68
+ text: 'Convertisseur GIF vers JPG en Ligne Gratuit',
69
+ },
70
+ {
71
+ type: 'paragraph',
72
+ html:
73
+ 'Les fichiers GIF sont largement connus pour leur capacité à jouer de courtes animations. Cependant, il y a des situations où vous avez besoin d\'une image statique du contenu GIF : pour l\'utiliser comme miniature, l\'envoyer par e-mail, ou simplement pour obtenir une version de haute qualité d\'un moment spécifique de l\'animation.',
74
+ },
75
+ {
76
+ type: 'paragraph',
77
+ html:
78
+ 'Convertir GIF en JPG extrait la première image de l\'animation et la convertit en une image JPG statique. Pendant ce processus, les zones transparentes du GIF original sont remplacées par un fond blanc solide, car le JPG ne supporte pas la transparence.',
79
+ },
80
+ {
81
+ type: 'tip',
82
+ html:
83
+ 'Si vous devez extraire plusieurs images d\'un GIF animé (pas seulement la première), envisagez d\'utiliser un outil spécialisé d\'édition GIF. Ce convertisseur est optimisé pour obtenir rapidement l\'image statique de la première trame.',
84
+ },
85
+ {
86
+ type: 'paragraph',
87
+ html:
88
+ 'Un GIF animé de 2 Mo peut produire un JPG de la première image de seulement 50-200 Ko, selon la résolution et la complexité de l\'image.',
89
+ },
90
+ {
91
+ type: 'paragraph',
92
+ html:
93
+ 'Convertissez GIF en JPG en extrayant la première image. Gratuit, privé et local. Fonds transparents automatiquement remplacés par du blanc pour une compatibilité JPG totale.',
94
+ },
95
+ ];
96
+
97
+ const appSchema: WithContext<SoftwareApplication> = {
98
+ '@context': 'https://schema.org',
99
+ '@type': 'SoftwareApplication',
100
+ name: title,
101
+ description,
102
+ applicationCategory: 'UtilitiesApplication',
103
+ operatingSystem: 'Web',
104
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
105
+ inLanguage: 'fr',
106
+ };
107
+
108
+ export const content: GifAJpgLocaleContent = {
109
+ slug,
110
+ title,
111
+ description,
112
+ ui,
113
+ seo,
114
+ faq,
115
+ bibliography,
116
+ howTo,
117
+ schemas: [appSchema as any],
118
+ };
@@ -0,0 +1,29 @@
1
+ import type { ConvertersToolEntry, ToolLocaleContent, ToolDefinition } from '../../types';
2
+ import type { ImageConverterUI } from '../../shared/ImageConverter.astro';
3
+ import GifAJpgCalculator from './component.astro';
4
+ import GifAJpgSEO from './seo.astro';
5
+ import GifAJpgBibliography from './bibliography.astro';
6
+
7
+ export type GifAJpgLocaleContent = ToolLocaleContent<ImageConverterUI>;
8
+
9
+ export const gifAJpg: ConvertersToolEntry<ImageConverterUI> = {
10
+ id: 'gif-a-jpg',
11
+ icons: {
12
+ bg: 'mdi:file-image',
13
+ fg: 'mdi:file-export',
14
+ },
15
+ i18n: {
16
+ es: () => import('./i18n/es').then((m) => m.content),
17
+ en: () => import('./i18n/en').then((m) => m.content),
18
+ fr: () => import('./i18n/fr').then((m) => m.content),
19
+ },
20
+ };
21
+
22
+ export { GifAJpgCalculator, GifAJpgSEO, GifAJpgBibliography };
23
+
24
+ export const GIF_A_JPG_TOOL: ToolDefinition = {
25
+ entry: gifAJpg,
26
+ Component: GifAJpgCalculator,
27
+ SEOComponent: GifAJpgSEO,
28
+ BibliographyComponent: GifAJpgBibliography,
29
+ };
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { gifAJpg } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await gifAJpg.i18n[locale]?.();
12
+ ---
13
+
14
+ {content && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
+ import { gifAPng } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await gifAPng.i18n[locale]?.();
12
+ ---
13
+
14
+ {content && <SharedBibliography links={content.bibliography} title={content.ui.bibliographyTitle} />}
@@ -0,0 +1,8 @@
1
+ ---
2
+ import SharedImageConverter from '../../shared/ImageConverter.astro';
3
+ import type { ImageConverterUI } from '../../shared/ImageConverter.astro';
4
+
5
+ interface Props { ui: ImageConverterUI }
6
+ const { ui } = Astro.props;
7
+ ---
8
+ <SharedImageConverter from="gif" to="png" ui={ui} />
@@ -0,0 +1,123 @@
1
+ import type { WithContext, SoftwareApplication } from 'schema-dts';
2
+ import type { ImageConverterUI } from '../../../shared/ImageConverter.astro';
3
+ import type { GifAPngLocaleContent } from '../index';
4
+
5
+ const slug = 'gif-to-png-converter';
6
+ const title = 'Convert GIF to PNG Online | Extract a Static Frame Without Loss';
7
+ const description =
8
+ 'Extract the first frame of your GIFs and convert to PNG preserving transparency. No server. Local processing. Free.';
9
+
10
+ const ui: ImageConverterUI = {
11
+ dragText: 'Drag GIF files...',
12
+ convertText: 'To convert them to PNG instantly',
13
+ selectFiles: 'Select files',
14
+ processedFiles: 'Processed files',
15
+ downloadAll: 'Download All (.zip)',
16
+ pending: 'Pending',
17
+ bibliographyTitle: 'Bibliographic References',
18
+ faqTitle: 'Frequently Asked Questions',
19
+ };
20
+
21
+ const faq: GifAPngLocaleContent['faq'] = [
22
+ {
23
+ question: 'Why convert an animated format like GIF to a static format like PNG?',
24
+ answer:
25
+ 'Many social networks or avatars do not accept changing photographs. Extracting the first frame of a complex GIF to a high-quality PNG solves compatibility barriers and reduces unnecessary file weight.',
26
+ },
27
+ {
28
+ question: 'Are the old GIF transparencies preserved in the resulting PNG?',
29
+ answer:
30
+ 'Yes, unlike JPG, the PNG format maintains the alpha channel. If the GIF had a transparent background, the PNG will preserve it with sharp edges.',
31
+ },
32
+ {
33
+ question: 'Do you keep my images on servers after processing?',
34
+ answer:
35
+ 'No server retains your GIF; all extraction is local thanks to the Canvas Web API. It is your PC processor that securely decodes your file without any network contact.',
36
+ },
37
+ ];
38
+
39
+ const howTo: GifAPngLocaleContent['howTo'] = [
40
+ {
41
+ name: 'Bring us the animation',
42
+ text: 'Drop the heavy GIF files in the insertion box.',
43
+ },
44
+ {
45
+ name: 'Perfect extracted photo',
46
+ text: 'The system will freeze at the exact origin of the movement, producing the impeccable copy in milliseconds.',
47
+ },
48
+ {
49
+ name: 'Save your static image',
50
+ text: 'Store in bulk ZIP all those volumes of static GIF avatars converted to PNG.',
51
+ },
52
+ ];
53
+
54
+ const bibliography: GifAPngLocaleContent['bibliography'] = [
55
+ {
56
+ name: 'World Wide Web Consortium: PNG format',
57
+ url: 'https://www.w3.org/TR/png/',
58
+ },
59
+ {
60
+ name: 'CompuServe GIF Information',
61
+ url: 'https://www.w3.org/Graphics/GIF/spec-gif89a.txt',
62
+ },
63
+ ];
64
+
65
+ const seo: GifAPngLocaleContent['seo'] = [
66
+ {
67
+ type: 'title',
68
+ text: 'Free Online GIF to PNG Converter',
69
+ },
70
+ {
71
+ type: 'paragraph',
72
+ html:
73
+ 'Converting GIF to PNG has a significant advantage over converting to JPG: transparency preservation. PNG, like some GIFs, supports the alpha channel. If your GIF has a transparent background, the resulting PNG will preserve it with complete fidelity. This is especially important for logos, avatars, icons and any graphic that will be used on different colored backgrounds.',
74
+ },
75
+ {
76
+ type: 'paragraph',
77
+ html:
78
+ 'Another advantage of PNG over JPG for this type of conversion is lossless quality. PNG uses lossless compression, meaning the image extracted from the GIF will maintain all its details without the compression artifacts that JPG format would introduce.',
79
+ },
80
+ {
81
+ type: 'tip',
82
+ html:
83
+ 'If you have an animated GIF avatar for Discord, Telegram or other platforms and need the static PNG version, this converter is the perfect tool to get it in seconds.',
84
+ },
85
+ {
86
+ type: 'paragraph',
87
+ html:
88
+ 'A 500 KB animated GIF can produce a PNG of the first frame between 50 KB and 200 KB, depending on image complexity and colors. If it has transparency, the PNG will preserve it perfectly.',
89
+ },
90
+ {
91
+ type: 'paragraph',
92
+ html:
93
+ 'The conversion is done entirely in the browser. The GIF is loaded into memory, the first frame is rendered on an HTML5 canvas and exported as PNG. No network connection is established throughout the process.',
94
+ },
95
+ {
96
+ type: 'paragraph',
97
+ html:
98
+ 'Convert GIF to PNG preserving transparency and without quality loss. First frame extraction for free, privately and locally in your browser.',
99
+ },
100
+ ];
101
+
102
+ const appSchema: WithContext<SoftwareApplication> = {
103
+ '@context': 'https://schema.org',
104
+ '@type': 'SoftwareApplication',
105
+ name: title,
106
+ description,
107
+ applicationCategory: 'UtilitiesApplication',
108
+ operatingSystem: 'Web',
109
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
110
+ inLanguage: 'en',
111
+ };
112
+
113
+ export const content: GifAPngLocaleContent = {
114
+ slug,
115
+ title,
116
+ description,
117
+ ui,
118
+ seo,
119
+ faq,
120
+ bibliography,
121
+ howTo,
122
+ schemas: [appSchema as any],
123
+ };