@jjlmoya/utils-textiles 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/category/i18n/de.ts +2 -2
- package/src/category/i18n/en.ts +2 -2
- package/src/category/i18n/es.ts +2 -2
- package/src/category/i18n/fr.ts +9 -9
- package/src/category/i18n/id.ts +2 -2
- package/src/category/i18n/it.ts +2 -2
- package/src/category/i18n/nl.ts +2 -2
- package/src/category/i18n/pl.ts +3 -3
- package/src/category/i18n/pt.ts +2 -2
- package/src/category/i18n/ru.ts +5 -5
- package/src/category/i18n/sv.ts +3 -3
- package/src/category/i18n/zh.ts +2 -2
- package/src/layouts/PreviewLayout.astro +1 -0
- package/src/tests/diacritics_density.test.ts +118 -0
- package/src/tests/inverted_punctuation.test.ts +84 -0
- package/src/tests/no_en_dash.test.ts +70 -0
- package/src/tests/script_density.test.ts +94 -0
- package/src/tool/burnTest/i18n/de.ts +3 -3
- package/src/tool/burnTest/i18n/fr.ts +3 -3
- package/src/tool/burnTest/i18n/pl.ts +3 -3
- package/src/tool/burnTest/i18n/ru.ts +6 -6
- package/src/tool/burnTest/i18n/zh.ts +3 -3
- package/src/tool/clothingSizeConverter/i18n/en.ts +1 -1
- package/src/tool/clothingSizeConverter/i18n/fr.ts +6 -6
- package/src/tool/clothingSizeConverter/i18n/pl.ts +1 -1
- package/src/tool/clothingSizeConverter/i18n/ru.ts +2 -2
- package/src/tool/clothingSizeConverter/i18n/zh.ts +1 -1
- package/src/tool/fabricProjectCalculator/component.astro +4 -5
- package/src/tool/fabricProjectCalculator/fabric-project-calculator.css +474 -502
- package/src/tool/fabricProjectCalculator/i18n/ru.ts +2 -2
- package/src/tool/fabricProjectCalculator/i18n/zh.ts +1 -1
- package/src/tool/fabricTruth/i18n/de.ts +1 -1
- package/src/tool/fabricTruth/i18n/en.ts +1 -1
- package/src/tool/fabricTruth/i18n/es.ts +1 -1
- package/src/tool/fabricTruth/i18n/fr.ts +13 -13
- package/src/tool/fabricTruth/i18n/id.ts +1 -1
- package/src/tool/fabricTruth/i18n/it.ts +1 -1
- package/src/tool/fabricTruth/i18n/ja.ts +1 -1
- package/src/tool/fabricTruth/i18n/ko.ts +1 -1
- package/src/tool/fabricTruth/i18n/nl.ts +1 -1
- package/src/tool/fabricTruth/i18n/pl.ts +1 -1
- package/src/tool/fabricTruth/i18n/pt.ts +1 -1
- package/src/tool/fabricTruth/i18n/ru.ts +11 -11
- package/src/tool/fabricTruth/i18n/sv.ts +1 -1
- package/src/tool/fabricTruth/i18n/tr.ts +1 -1
- package/src/tool/fabricTruth/i18n/zh.ts +9 -9
- package/src/tool/fiberPrep/fiber-preparation-natural-dyeing.css +130 -11
- package/src/tool/fiberPrep/i18n/fr.ts +4 -4
- package/src/tool/fiberPrep/i18n/ru.ts +3 -3
- package/src/tool/fiberPrep/i18n/zh.ts +2 -2
- package/src/tool/knittingGauge/i18n/ru.ts +6 -6
- package/src/tool/knittingGauge/i18n/zh.ts +1 -1
- package/src/tool/laundryGuide/i18n/de.ts +1 -1
- package/src/tool/laundryGuide/i18n/en.ts +1 -1
- package/src/tool/laundryGuide/i18n/es.ts +1 -1
- package/src/tool/laundryGuide/i18n/fr.ts +12 -12
- package/src/tool/laundryGuide/i18n/id.ts +1 -1
- package/src/tool/laundryGuide/i18n/it.ts +1 -1
- package/src/tool/laundryGuide/i18n/nl.ts +1 -1
- package/src/tool/laundryGuide/i18n/pl.ts +2 -2
- package/src/tool/laundryGuide/i18n/pt.ts +1 -1
- package/src/tool/laundryGuide/i18n/ru.ts +6 -6
- package/src/tool/laundryGuide/i18n/sv.ts +1 -1
- package/src/tool/laundryGuide/i18n/zh.ts +2 -2
- package/src/tool/needleConverter/i18n/fr.ts +5 -5
- package/src/tool/needleConverter/i18n/ru.ts +4 -4
- package/src/tool/sewingPatternScaler/i18n/fr.ts +2 -2
- package/src/tool/sewingPatternScaler/i18n/pl.ts +2 -2
- package/src/tool/sewingPatternScaler/i18n/ru.ts +7 -7
- package/src/tool/sewingPatternScaler/i18n/zh.ts +3 -3
- package/src/tool/shoeSizeConverter/i18n/fr.ts +1 -1
- package/src/tool/shoeSizeConverter/i18n/ru.ts +4 -4
- package/src/tool/shoeSizeConverter/i18n/zh.ts +3 -3
- package/src/tool/stainChemistry/bibliography.ts +2 -2
- package/src/tool/stainChemistry/i18n/de.ts +3 -3
- package/src/tool/stainChemistry/i18n/en.ts +3 -3
- package/src/tool/stainChemistry/i18n/es.ts +3 -3
- package/src/tool/stainChemistry/i18n/fr.ts +6 -6
- package/src/tool/stainChemistry/i18n/id.ts +3 -3
- package/src/tool/stainChemistry/i18n/it.ts +3 -3
- package/src/tool/stainChemistry/i18n/ja.ts +3 -3
- package/src/tool/stainChemistry/i18n/ko.ts +3 -3
- package/src/tool/stainChemistry/i18n/nl.ts +3 -3
- package/src/tool/stainChemistry/i18n/pl.ts +3 -3
- package/src/tool/stainChemistry/i18n/pt.ts +3 -3
- package/src/tool/stainChemistry/i18n/ru.ts +7 -7
- package/src/tool/stainChemistry/i18n/sv.ts +3 -3
- package/src/tool/stainChemistry/i18n/tr.ts +3 -3
- package/src/tool/stainChemistry/i18n/zh.ts +7 -7
- package/src/tool/yarnCalculator/i18n/fr.ts +4 -4
- package/src/tool/yarnCalculator/i18n/ru.ts +7 -7
- package/src/tool/yarnCalculator/i18n/zh.ts +5 -5
package/package.json
CHANGED
package/src/category/i18n/de.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'Die Modeindustrie nutzt ausgefeilte Marketingtechniken, um mittelmäßige Kleidungsstücke zu Premiumpreisen zu verkaufen. Unser Werkzeug für textile Wahrheit analysiert die tatsächliche Zusammensetzung der Kleidung
|
|
24
|
+
html: 'Die Modeindustrie nutzt ausgefeilte Marketingtechniken, um mittelmäßige Kleidungsstücke zu Premiumpreisen zu verkaufen. Unser Werkzeug für textile Wahrheit analysiert die tatsächliche Zusammensetzung der Kleidung - die auf dem Etikett aufgeführten Faseranteile -, um Ihnen unangenehme Wahrheiten zu offenbaren: Ist es wirklich Baumwolle oder "teures Plastik"? Enthält es echte Seide oder nur 3 % als Werbegag? Es verwendet einen Algorithmus, der auf europäischen und nordamerikanischen Industriestandards basiert und Atmungsaktivität, Haltbarkeit und thermische Effizienz bewertet.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'Unsere Werkzeuge befähigen Sie dazu, intelligentere Einkäufe zu tätigen, Ihre Kleidung besser zu pflegen und ihre Lebensdauer zu verlängern
|
|
73
|
+
html: 'Unsere Werkzeuge befähigen Sie dazu, intelligentere Einkäufe zu tätigen, Ihre Kleidung besser zu pflegen und ihre Lebensdauer zu verlängern - der nachhaltigste Akt überhaupt.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/en.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'The fashion industry uses sophisticated marketing techniques to sell mediocre garments at premium prices. Our Fabric Truthfulness tool analyzes the real composition of garments
|
|
24
|
+
html: 'The fashion industry uses sophisticated marketing techniques to sell mediocre garments at premium prices. Our Fabric Truthfulness tool analyzes the real composition of garments - the fiber percentages listed on the label - to reveal uncomfortable truths: Is it truly cotton or "expensive plastic"? Does it contain real silk or just 3% as a publicity hook? It uses an algorithm based on European and North American industrial standards that evaluates breathability, durability, and thermal efficiency.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'Our tools empower you to make smarter purchases, better care for your garments, and extend their lifespan
|
|
73
|
+
html: 'Our tools empower you to make smarter purchases, better care for your garments, and extend their lifespan - the most sustainable act possible.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/es.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'La industria de la moda utiliza técnicas sofisticadas de marketing para vender prendas mediocres a precios premium. Nuestra herramienta de Veracidad Textil analiza la composición real de las prendas
|
|
24
|
+
html: 'La industria de la moda utiliza técnicas sofisticadas de marketing para vender prendas mediocres a precios premium. Nuestra herramienta de Veracidad Textil analiza la composición real de las prendas - los porcentajes de fibras listados en la etiqueta - para revelarte verdades incómodas: ¿es realmente algodón o es "plástico caro"? ¿Contiene seda real o solo un 3% como gancho publicitario? Utiliza un algoritmo basado en estándares industriales europeos y norteamericanos que evalúa transpirabilidad, durabilidad y eficiencia térmica.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'Nuestras herramientas te capacitan para hacer compras más inteligentes, cuidar mejor tus prendas y alargar su vida útil
|
|
73
|
+
html: 'Nuestras herramientas te capacitan para hacer compras más inteligentes, cuidar mejor tus prendas y alargar su vida útil - el acto más sostenible posible.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/fr.ts
CHANGED
|
@@ -7,7 +7,7 @@ export const content: CategoryLocaleContent = {
|
|
|
7
7
|
seo: [
|
|
8
8
|
{
|
|
9
9
|
type: 'title',
|
|
10
|
-
text: 'Science Textile
|
|
10
|
+
text: 'Science Textile: Analyse des Fibres et Composition des Vêtements',
|
|
11
11
|
level: 2,
|
|
12
12
|
},
|
|
13
13
|
{
|
|
@@ -17,16 +17,16 @@ export const content: CategoryLocaleContent = {
|
|
|
17
17
|
{
|
|
18
18
|
type: 'title',
|
|
19
19
|
level: 2,
|
|
20
|
-
text: 'Vérité Textile
|
|
20
|
+
text: 'Vérité Textile: Détectez le Plastique Déguisé en Mode',
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'L\'industrie de la mode utilise des techniques de marketing sophistiquées pour vendre des vêtements médiocres à des prix premium. Notre outil Vérité Textile analyse la composition réelle des vêtements
|
|
24
|
+
html: 'L\'industrie de la mode utilise des techniques de marketing sophistiquées pour vendre des vêtements médiocres à des prix premium. Notre outil Vérité Textile analyse la composition réelle des vêtements - les pourcentages de fibres listés sur l\'étiquette - pour vous révéler des vérités inconfortables: est-ce vraiment du coton ou du "plastique cher" ? Contient-il de la vraie soie ou seulement 3 % comme appât publicitaire ? Il utilise un algorithme basé sur les normes industrielles européennes et nord-américaines qui évalue la respirabilité, la durabilité et l\'efficacité thermique.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
28
28
|
level: 2,
|
|
29
|
-
text: 'Maîtrise Textile
|
|
29
|
+
text: 'Maîtrise Textile: Guide Scientifique du Lavage et de l\'Entretien',
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
type: 'paragraph',
|
|
@@ -35,7 +35,7 @@ export const content: CategoryLocaleContent = {
|
|
|
35
35
|
{
|
|
36
36
|
type: 'title',
|
|
37
37
|
level: 2,
|
|
38
|
-
text: 'Chimie des Taches
|
|
38
|
+
text: 'Chimie des Taches: Protocoles par Type de Fibre',
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
type: 'paragraph',
|
|
@@ -44,11 +44,11 @@ export const content: CategoryLocaleContent = {
|
|
|
44
44
|
{
|
|
45
45
|
type: 'title',
|
|
46
46
|
level: 2,
|
|
47
|
-
text: 'Test de Combustion
|
|
47
|
+
text: 'Test de Combustion: Identifiez les Fibres en les Brûlant',
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
type: 'paragraph',
|
|
51
|
-
html: 'Historiquement, les experts en textiles ont utilisé des tests de combustion pour identifier les fibres
|
|
51
|
+
html: 'Historiquement, les experts en textiles ont utilisé des tests de combustion pour identifier les fibres: le comportement de la flamme, l\'odeur et les résidus révèlent la nature chimique de la fibre. Les fibres naturelles (cellulose, protéine) ont des caractéristiques distinctes des fibres synthétiques (plastiques dérivés du pétrole).',
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
type: 'title',
|
|
@@ -57,7 +57,7 @@ export const content: CategoryLocaleContent = {
|
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
type: 'paragraph',
|
|
60
|
-
html: 'Si vous êtes un amateur de couture, de tricot ou de crochet, nous disposons de calculatrices avancées
|
|
60
|
+
html: 'Si vous êtes un amateur de couture, de tricot ou de crochet, nous disposons de calculatrices avancées: des convertisseurs d\'aiguilles aux calculs de consommation de tissu, des changeurs d\'échelle de motif qui respectent les proportions et des utilitaires de tension (gauge) qui assurent que votre projet final a exactement les dimensions souhaitées.',
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'Nos outils vous permettent de faire des achats plus intelligents, de mieux entretenir vos vêtements et de prolonger leur durée de vie
|
|
73
|
+
html: 'Nos outils vous permettent de faire des achats plus intelligents, de mieux entretenir vos vêtements et de prolonger leur durée de vie - l\'acte le plus durable possible.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/id.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'Industri fashion menggunakan teknik pemasaran yang canggih untuk menjual pakaian berkualitas biasa dengan harga premium. Alat Kebenaran Tekstil kami menganalisis komposisi asli pakaian
|
|
24
|
+
html: 'Industri fashion menggunakan teknik pemasaran yang canggih untuk menjual pakaian berkualitas biasa dengan harga premium. Alat Kebenaran Tekstil kami menganalisis komposisi asli pakaian - persentase serat yang tercantum pada label - untuk mengungkapkan kebenaran yang tidak nyaman: apakah itu benar-benar katun atau "plastik mahal"? Apakah mengandung sutra asli atau hanya 3% sebagai pemikat iklan? Alat ini menggunakan algoritme berdasarkan standar industri Eropa dan Amerika Utara yang mengevaluasi daya napas, daya tahan, dan efisiensi termal.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'Alat kami memberdayakan Anda untuk berbelanja lebih cerdas, merawat pakaian dengan lebih baik, dan memperpanjang masa pakainya
|
|
73
|
+
html: 'Alat kami memberdayakan Anda untuk berbelanja lebih cerdas, merawat pakaian dengan lebih baik, dan memperpanjang masa pakainya - tindakan paling berkelanjutan yang mungkin dilakukan.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/it.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'L\'industria della moda utilizza sofisticate tecniche di marketing per vendere capi mediocri a prezzi premium. Il nostro strumento Verità Tessile analizza la reale composizione dei capi
|
|
24
|
+
html: 'L\'industria della moda utilizza sofisticate tecniche di marketing per vendere capi mediocri a prezzi premium. Il nostro strumento Verità Tessile analizza la reale composizione dei capi - le percentuali di fibre elencate sull\'etichetta - per rivelarti verità scomode: è davvero cotone o "plastica costosa"? Contiene vera seta o solo un 3% come esca pubblicitaria? Utilizza un algoritmo basato su standard industriali europei e nordamericani che valuta traspirabilità, durata ed efficienza termica.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'I nostri strumenti ti permettono di fare acquisti più intelligenti, prenderti cura meglio dei tuoi capi e prolungarne la vita utile
|
|
73
|
+
html: 'I nostri strumenti ti permettono di fare acquisti più intelligenti, prenderti cura meglio dei tuoi capi e prolungarne la vita utile - l\'atto più sostenibile possibile.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/nl.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'De mode-industrie maakt gebruik van geavanceerde marketingtechnieken om middelmatige kledingstukken tegen premiumprijzen te verkopen. Onze Textiele Waarheid-tool analyseert de werkelijke samenstelling van kledingstukken
|
|
24
|
+
html: 'De mode-industrie maakt gebruik van geavanceerde marketingtechnieken om middelmatige kledingstukken tegen premiumprijzen te verkopen. Onze Textiele Waarheid-tool analyseert de werkelijke samenstelling van kledingstukken - de vezelpercentages die op het etiket staan - om ongemakkelijke waarheden te onthullen: is het echt katoen of "duur plastic"? Bevat het echte zijde of slechts 3% als reclamepraatje? De tool maakt gebruik van een algoritme gebaseerd op Europese en Noord-Amerikaanse industriestandaarden dat ademend vermogen, duurzaamheid en thermische efficiëntie evalueert.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'Onze hulpmiddelen stellen je in staat om slimmere aankopen te doen, je kleding beter te verzorgen en de levensduur ervan te verlengen
|
|
73
|
+
html: 'Onze hulpmiddelen stellen je in staat om slimmere aankopen te doen, je kleding beter te verzorgen en de levensduur ervan te verlengen - de meest duurzame handeling die mogelijk is.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/pl.ts
CHANGED
|
@@ -12,7 +12,7 @@ export const content: CategoryLocaleContent = {
|
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
type: 'paragraph',
|
|
15
|
-
html: 'Świat tekstyliów to fascynujące połączenie chemii, fizyki i inżynierii. W tej sekcji oferujemy specjalistyczne narzędzia, dzięki którym naprawdę zrozumiesz, co nosisz. Od analizy składu po obliczenia zużycia tkanin i skalowanie wykrojów
|
|
15
|
+
html: 'Świat tekstyliów to fascynujące połączenie chemii, fizyki i inżynierii. W tej sekcji oferujemy specjalistyczne narzędzia, dzięki którym naprawdę zrozumiesz, co nosisz. Od analizy składu po obliczenia zużycia tkanin i skalowanie wykrojów - te narzędzia są przeznaczone dla profesjonalistów, pasjonatów DIY oraz świadomych konsumentów, którzy chcą podejmować przemyślane decyzje dotyczące swojej garderoby.',
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
type: 'title',
|
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'Przemysł modowy wykorzystuje wyrafinowane techniki marketingowe, aby sprzedawać przeciętną odzież w cenach premium. Nasze narzędzie Prawda o Tekstyliach analizuje rzeczywisty skład odzieży
|
|
24
|
+
html: 'Przemysł modowy wykorzystuje wyrafinowane techniki marketingowe, aby sprzedawać przeciętną odzież w cenach premium. Nasze narzędzie Prawda o Tekstyliach analizuje rzeczywisty skład odzieży - procentową zawartość włókien podaną na metce - aby ujawnić niewygodną prawdę: czy to naprawdę bawełna, czy "drogi plastik"? Czy zawiera prawdziwy jedwab, czy tylko 3% jako chwyt reklamowy? Wykorzystuje algorytm oparty na europejskich i północnoamerykańskich standardach przemysłowych, który ocenia oddychalność, trwałość i wydajność termiczną.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'Nasze narzędzia pozwalają na dokonywanie mądrzejszych zakupów, lepszą pielęgnację odzieży i wydłużenie jej żywotności
|
|
73
|
+
html: 'Nasze narzędzia pozwalają na dokonywanie mądrzejszych zakupów, lepszą pielęgnację odzieży i wydłużenie jej żywotności - co jest najbardziej zrównoważonym działaniem, jakie można podjąć.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/pt.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'A indústria da moda utiliza técnicas sofisticadas de marketing para vender peças medíocres a preços premium. A nossa ferramenta de Veracidade Têxtil analisa a composição real das peças
|
|
24
|
+
html: 'A indústria da moda utiliza técnicas sofisticadas de marketing para vender peças medíocres a preços premium. A nossa ferramenta de Veracidade Têxtil analisa a composição real das peças - as percentagens de fibras listadas na etiqueta - para lhe revelar verdades desconfortáveis: é realmente algodão ou é "plástico caro"? Contém seda real ou apenas 3% como isco publicitário? Utiliza um algoritmo baseado em padrões industriais europeus e norte-americanos que avalia a respirabilidade, durabilidade e eficiência térmica.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'As nossas ferramentas capacitam-no para fazer compras mais inteligentes, cuidar melhor das suas peças e prolongar a sua vida útil
|
|
73
|
+
html: 'As nossas ferramentas capacitam-no para fazer compras mais inteligentes, cuidar melhor das suas peças e prolongar a sua vida útil - o ato mais sustentável possível.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/ru.ts
CHANGED
|
@@ -12,7 +12,7 @@ export const content: CategoryLocaleContent = {
|
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
type: 'paragraph',
|
|
15
|
-
html: 'Мир текстиля
|
|
15
|
+
html: 'Мир текстиля - это захватывающее пересечение химии, физики и инженерии. В этом разделе мы предлагаем специализированные инструменты, которые помогут вам действительно понять, что вы носите. От анализа состава до расчета расхода ткани и масштабирования выкроек - эти утилиты разработаны для профессионалов, любителей DIY и сознательных потребителей, желающих принимать обоснованные решения о своей одежде.',
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
type: 'title',
|
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'Индустрия моды использует сложные маркетинговые приемы, чтобы продавать заурядную одежду по премиальным ценам. Наш инструмент
|
|
24
|
+
html: 'Индустрия моды использует сложные маркетинговые приемы, чтобы продавать заурядную одежду по премиальным ценам. Наш инструмент "Текстильная правда" анализирует реальный состав вещей - процентное содержание волокон, указанное на этикетке, - чтобы раскрыть неудобную правду: действительно ли это хлопок или "дорогой пластик"? Содержит ли вещь настоящий шелк или только 3% для рекламной приманки? Мы используем алгоритм, основанный на европейских и североамериканских промышленных стандартах, который оценивает воздухопроницаемость, долговечность и тепловую эффективность.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -39,7 +39,7 @@ export const content: CategoryLocaleContent = {
|
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
type: 'paragraph',
|
|
42
|
-
html: 'Пятно от вина на льне требует иного протокола, чем то же пятно на шелке. Жирные пятна на полиэстере требуют растворителей; на шерсти
|
|
42
|
+
html: 'Пятно от вина на льне требует иного протокола, чем то же пятно на шелке. Жирные пятна на полиэстере требуют растворителей; на шерсти - более деликатных методов. Этот инструмент сопоставляет пятна, типы волокон и химические средства, чтобы предложить вам лучшую стратегию удаления без повреждения ткани.',
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
type: 'title',
|
|
@@ -66,11 +66,11 @@ export const content: CategoryLocaleContent = {
|
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
type: 'paragraph',
|
|
69
|
-
html: 'Каждая покупка одежды
|
|
69
|
+
html: 'Каждая покупка одежды - это решение, имеющее экологические и социальные последствия. Понимание текстильного состава - первый шаг к осознанному потреблению. Натуральные разлагаемые волокна (хлопок, лен, шерсть) оказывают совершенно иное воздействие на окружающую среду, чем синтетика (полиэстер, акрил), которая разлагается 200 лет.',
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'Наши инструменты позволяют вам делать более разумные покупки, лучше заботиться о своих вещах и продлевать их жизнь
|
|
73
|
+
html: 'Наши инструменты позволяют вам делать более разумные покупки, лучше заботиться о своих вещах и продлевать их жизнь - это самый экологичный поступок из возможных.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/sv.ts
CHANGED
|
@@ -12,7 +12,7 @@ export const content: CategoryLocaleContent = {
|
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
type: 'paragraph',
|
|
15
|
-
html: 'Världen av textilier är en fascinerande skärningspunkt mellan kemi, fysik och ingenjörskonst. I den här sektionen erbjuder vi specialiserade verktyg för att du verkligen ska förstå vad du bär. Från sammansättningsanalys till beräkningar av tygåtgång och mönsterskalning
|
|
15
|
+
html: 'Världen av textilier är en fascinerande skärningspunkt mellan kemi, fysik och ingenjörskonst. I den här sektionen erbjuder vi specialiserade verktyg för att du verkligen ska förstå vad du bär. Från sammansättningsanalys till beräkningar av tygåtgång och mönsterskalning - dessa verktyg är designade för proffs, DIY-entusiaster och medvetna konsumenter som vill fatta välgrundade beslut om sina plagg.',
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
type: 'title',
|
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: 'Modeindustrin använder sofistikerade marknadsföringstekniker för att sälja mediokra plagg till premiumpriser. Vårt verktyg för textil sanning analyserar plaggens verkliga sammansättning
|
|
24
|
+
html: 'Modeindustrin använder sofistikerade marknadsföringstekniker för att sälja mediokra plagg till premiumpriser. Vårt verktyg för textil sanning analyserar plaggens verkliga sammansättning - de fiberprocent som anges på etiketten - för att avslöja obekväma sanningar: är det verkligen bomull eller är det "dyr plast"? Innehåller det äkta silke eller bara 3 % som ett reklamknep? Det använder en algoritm baserad på europeiska och nordamerikanska industristandarder som utvärderar andningsförmåga, hållbarhet och termisk effektivitet.',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: 'Våra verktyg ger dig möjlighet att göra smartare inköp, ta bättre hand om dina plagg och förlänga deras livslängd
|
|
73
|
+
html: 'Våra verktyg ger dig möjlighet att göra smartare inköp, ta bättre hand om dina plagg och förlänga deras livslängd - den mest hållbara handlingen som är möjlig.',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
package/src/category/i18n/zh.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const content: CategoryLocaleContent = {
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
type: 'paragraph',
|
|
24
|
-
html: '
|
|
24
|
+
html: '时尚行业利用成熟的营销技术,以溢价销售平庸的服装。我们的"纺织真相"工具分析服装的真实成分(标签上列出的纤维百分比),为您揭开令人不安的真相:它真的是棉,还是"昂贵的塑料"?它含有真丝,还是仅仅为了广告噱头而添加了 3%?它采用基于欧洲和北美工业标准的算法,评估透气性、耐用性和热效率。',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'title',
|
|
@@ -70,7 +70,7 @@ export const content: CategoryLocaleContent = {
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
type: 'paragraph',
|
|
73
|
-
html: '
|
|
73
|
+
html: '我们的工具使您能够进行更明智的购买,更好地护理衣服并延长其使用寿命 - - 这是最可持续的行为。',
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { ALL_TOOLS } from '../tools';
|
|
3
|
+
|
|
4
|
+
type LocaleWithDiacritics = keyof typeof DIACRITIC_RULES;
|
|
5
|
+
|
|
6
|
+
const DIACRITIC_RULES = {
|
|
7
|
+
de: {
|
|
8
|
+
language: 'German',
|
|
9
|
+
expectedCharacters: 'ä ö ü ß',
|
|
10
|
+
characters: /[äöüÄÖÜß]/g,
|
|
11
|
+
minPerThousandLetters: 0.1,
|
|
12
|
+
},
|
|
13
|
+
es: {
|
|
14
|
+
language: 'Spanish',
|
|
15
|
+
expectedCharacters: 'á é í ó ú ü ñ',
|
|
16
|
+
characters: /[áéíóúüñÁÉÍÓÚÜÑ]/g,
|
|
17
|
+
minPerThousandLetters: 0.1,
|
|
18
|
+
},
|
|
19
|
+
fr: {
|
|
20
|
+
language: 'French',
|
|
21
|
+
expectedCharacters: 'à â æ ç é è ê ë î ï ô œ ù û ü ÿ',
|
|
22
|
+
characters: /[àâæçéèêëîïôœùûüÿÀÂÆÇÉÈÊËÎÏÔŒÙÛÜŸ]/g,
|
|
23
|
+
minPerThousandLetters: 0.1,
|
|
24
|
+
},
|
|
25
|
+
it: {
|
|
26
|
+
language: 'Italian',
|
|
27
|
+
expectedCharacters: 'à è é ì í î ò ó ù ú',
|
|
28
|
+
characters: /[àèéìíîòóùúÀÈÉÌÍÎÒÓÙÚ]/g,
|
|
29
|
+
minPerThousandLetters: 0.1,
|
|
30
|
+
},
|
|
31
|
+
pl: {
|
|
32
|
+
language: 'Polish',
|
|
33
|
+
expectedCharacters: 'ą ć ę ł ń ó ś ź ż',
|
|
34
|
+
characters: /[ąćęłńóśźżĄĆĘŁŃÓŚŹŻ]/g,
|
|
35
|
+
minPerThousandLetters: 0.1,
|
|
36
|
+
},
|
|
37
|
+
pt: {
|
|
38
|
+
language: 'Portuguese',
|
|
39
|
+
expectedCharacters: 'á â ã à ç é ê í ó ô õ ú ü',
|
|
40
|
+
characters: /[áâãàçéêíóôõúüÁÂÃÀÇÉÊÍÓÔÕÚÜ]/g,
|
|
41
|
+
minPerThousandLetters: 0.1,
|
|
42
|
+
},
|
|
43
|
+
sv: {
|
|
44
|
+
language: 'Swedish',
|
|
45
|
+
expectedCharacters: 'å ä ö',
|
|
46
|
+
characters: /[åäöÅÄÖ]/g,
|
|
47
|
+
minPerThousandLetters: 0.1,
|
|
48
|
+
},
|
|
49
|
+
tr: {
|
|
50
|
+
language: 'Turkish',
|
|
51
|
+
expectedCharacters: 'ç ğ ı İ ö ş ü',
|
|
52
|
+
characters: /[çğıöşüÇĞİÖŞÜ]/g,
|
|
53
|
+
minPerThousandLetters: 0.1,
|
|
54
|
+
},
|
|
55
|
+
} as const;
|
|
56
|
+
|
|
57
|
+
const LETTERS = /\p{L}/gu;
|
|
58
|
+
const TRANSLATABLE_KEYS = ['title', 'description', 'ui', 'seo', 'faq', 'howTo'] as const;
|
|
59
|
+
|
|
60
|
+
function collectStrings(value: unknown): string[] {
|
|
61
|
+
if (typeof value === 'string') return [value];
|
|
62
|
+
if (!value || typeof value !== 'object') return [];
|
|
63
|
+
if (Array.isArray(value)) return value.flatMap(collectStrings);
|
|
64
|
+
return Object.values(value).flatMap(collectStrings);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function normalizeText(value: unknown): string {
|
|
68
|
+
return collectStrings(value).join(' ').normalize('NFC');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function translatableContent(content: Record<string, unknown>) {
|
|
72
|
+
return TRANSLATABLE_KEYS.map((key) => content[key]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function letterCount(text: string): number {
|
|
76
|
+
return text.match(LETTERS)?.length ?? 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function diacriticCount(text: string, locale: LocaleWithDiacritics): number {
|
|
80
|
+
return text.match(DIACRITIC_RULES[locale].characters)?.length ?? 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function diacriticsPerThousandLetters(text: string, locale: LocaleWithDiacritics): number {
|
|
84
|
+
const letters = letterCount(text);
|
|
85
|
+
if (letters === 0) return 0;
|
|
86
|
+
return diacriticCount(text, locale) / letters * 1000;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
describe('Diacritics density validation', () => {
|
|
90
|
+
ALL_TOOLS.forEach((tool) => {
|
|
91
|
+
describe(`Tool: ${tool.entry.id}`, () => {
|
|
92
|
+
Object.keys(DIACRITIC_RULES).forEach((locale) => {
|
|
93
|
+
it(`${locale} keeps the expected accent and special-letter set`, async () => {
|
|
94
|
+
const typedLocale = locale as LocaleWithDiacritics;
|
|
95
|
+
const loader = tool.entry.i18n[typedLocale];
|
|
96
|
+
if (!loader) return;
|
|
97
|
+
|
|
98
|
+
const content = await loader();
|
|
99
|
+
const text = normalizeText(translatableContent(content as Record<string, unknown>));
|
|
100
|
+
const rule = DIACRITIC_RULES[typedLocale];
|
|
101
|
+
const letters = letterCount(text);
|
|
102
|
+
const matches = diacriticCount(text, typedLocale);
|
|
103
|
+
const density = diacriticsPerThousandLetters(text, typedLocale);
|
|
104
|
+
|
|
105
|
+
expect(
|
|
106
|
+
density,
|
|
107
|
+
[
|
|
108
|
+
`Possible spelling or encoding issue detected in ${tool.entry.id}/${typedLocale} (${rule.language}).`,
|
|
109
|
+
`The text has ${matches} special characters (${density.toFixed(2)} per 1000 letters, ${letters} letters analyzed).`,
|
|
110
|
+
`This locale should include some of these characters: ${rule.expectedCharacters}.`,
|
|
111
|
+
'If the count is 0 or near 0, accents, tildes, or special letters were probably stripped by encoding or normalization.',
|
|
112
|
+
].join(' '),
|
|
113
|
+
).toBeGreaterThanOrEqual(rule.minPerThousandLetters);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { ALL_TOOLS } from '../tools';
|
|
3
|
+
|
|
4
|
+
const INVERTED_PUNCTUATION_LOCALES = {
|
|
5
|
+
es: {
|
|
6
|
+
language: 'Spanish',
|
|
7
|
+
questionStart: '¿',
|
|
8
|
+
questionEnd: '?',
|
|
9
|
+
exclamationStart: '¡',
|
|
10
|
+
exclamationEnd: '!',
|
|
11
|
+
},
|
|
12
|
+
} as const;
|
|
13
|
+
|
|
14
|
+
type InvertedPunctuationLocale = keyof typeof INVERTED_PUNCTUATION_LOCALES;
|
|
15
|
+
|
|
16
|
+
const TRANSLATABLE_KEYS = ['title', 'description', 'ui', 'seo', 'faq', 'howTo'] as const;
|
|
17
|
+
|
|
18
|
+
function collectStrings(value: unknown): string[] {
|
|
19
|
+
if (typeof value === 'string') return [value];
|
|
20
|
+
if (!value || typeof value !== 'object') return [];
|
|
21
|
+
if (Array.isArray(value)) return value.flatMap(collectStrings);
|
|
22
|
+
return Object.values(value).flatMap(collectStrings);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function translatableStrings(content: Record<string, unknown>): string[] {
|
|
26
|
+
return TRANSLATABLE_KEYS.flatMap((key) => collectStrings(content[key]));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function sentenceStart(text: string, endIndex: number): string {
|
|
30
|
+
const beforeMark = text.slice(0, endIndex).trimEnd();
|
|
31
|
+
const boundary = Math.max(
|
|
32
|
+
beforeMark.lastIndexOf('.'),
|
|
33
|
+
beforeMark.lastIndexOf(':'),
|
|
34
|
+
beforeMark.lastIndexOf(';'),
|
|
35
|
+
beforeMark.lastIndexOf('\n'),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return beforeMark.slice(boundary + 1).trimStart();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function findMissingInvertedMarks(
|
|
42
|
+
text: string,
|
|
43
|
+
startMark: string,
|
|
44
|
+
endMark: string,
|
|
45
|
+
): string[] {
|
|
46
|
+
return [...text.matchAll(new RegExp(`\\${endMark}`, 'g'))]
|
|
47
|
+
.map((match) => sentenceStart(text, match.index ?? 0))
|
|
48
|
+
.filter((segment) => segment.length > 0 && !segment.includes(startMark))
|
|
49
|
+
.map((segment) => `${segment}${endMark}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe('Inverted punctuation validation', () => {
|
|
53
|
+
ALL_TOOLS.forEach((tool) => {
|
|
54
|
+
describe(`Tool: ${tool.entry.id}`, () => {
|
|
55
|
+
Object.keys(INVERTED_PUNCTUATION_LOCALES).forEach((locale) => {
|
|
56
|
+
it(`${locale} uses opening punctuation marks for questions and exclamations`, async () => {
|
|
57
|
+
const typedLocale = locale as InvertedPunctuationLocale;
|
|
58
|
+
const loader = tool.entry.i18n[typedLocale];
|
|
59
|
+
if (!loader) return;
|
|
60
|
+
|
|
61
|
+
const rule = INVERTED_PUNCTUATION_LOCALES[typedLocale];
|
|
62
|
+
const content = await loader();
|
|
63
|
+
const strings = translatableStrings(content as Record<string, unknown>);
|
|
64
|
+
const missingQuestions = strings.flatMap((text) =>
|
|
65
|
+
findMissingInvertedMarks(text, rule.questionStart, rule.questionEnd)
|
|
66
|
+
);
|
|
67
|
+
const missingExclamations = strings.flatMap((text) =>
|
|
68
|
+
findMissingInvertedMarks(text, rule.exclamationStart, rule.exclamationEnd)
|
|
69
|
+
);
|
|
70
|
+
const failures = [...missingQuestions, ...missingExclamations];
|
|
71
|
+
|
|
72
|
+
expect(
|
|
73
|
+
failures,
|
|
74
|
+
[
|
|
75
|
+
`Missing opening punctuation marks in ${tool.entry.id}/${typedLocale} (${rule.language}).`,
|
|
76
|
+
`Questions must use ${rule.questionStart}...${rule.questionEnd} and exclamations must use ${rule.exclamationStart}...${rule.exclamationEnd}.`,
|
|
77
|
+
`Examples: ${failures.slice(0, 5).join(' | ')}`,
|
|
78
|
+
].join(' '),
|
|
79
|
+
).toHaveLength(0);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
function getFiles(dir: string): string[] {
|
|
6
|
+
const results: string[] = [];
|
|
7
|
+
if (!fs.existsSync(dir)) {
|
|
8
|
+
return results;
|
|
9
|
+
}
|
|
10
|
+
const list = fs.readdirSync(dir);
|
|
11
|
+
for (const file of list) {
|
|
12
|
+
const fullPath = path.join(dir, file);
|
|
13
|
+
const stat = fs.statSync(fullPath);
|
|
14
|
+
if (stat && stat.isDirectory()) {
|
|
15
|
+
if (file !== 'tests' && file !== 'node_modules' && file !== '.astro') {
|
|
16
|
+
results.push(...getFiles(fullPath));
|
|
17
|
+
}
|
|
18
|
+
} else {
|
|
19
|
+
results.push(fullPath);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return results;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function isContentFile(filePath: string): boolean {
|
|
26
|
+
return /\\i18n\\/.test(filePath) || filePath.endsWith('bibliography.ts');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
30
|
+
const scriptsDir = path.join(process.cwd(), 'scripts');
|
|
31
|
+
const filesToTest = [
|
|
32
|
+
...getFiles(srcDir).filter(isContentFile),
|
|
33
|
+
...getFiles(scriptsDir).filter(isContentFile),
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const aiTypographyGarbage = [
|
|
37
|
+
'\u2013',
|
|
38
|
+
'\u2014',
|
|
39
|
+
'\u2026',
|
|
40
|
+
'\u201C',
|
|
41
|
+
'\u201D',
|
|
42
|
+
'\u2018',
|
|
43
|
+
'\u2019',
|
|
44
|
+
'\u00AB',
|
|
45
|
+
'\u00BB',
|
|
46
|
+
'\u200B',
|
|
47
|
+
'\u201E',
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
describe('Typography Garbage Character Validation', () => {
|
|
51
|
+
filesToTest.forEach((filePath) => {
|
|
52
|
+
const relativePath = path.relative(process.cwd(), filePath);
|
|
53
|
+
it(`should not contain typography garbage characters in ${relativePath}`, () => {
|
|
54
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
55
|
+
const hasAiPatterns = aiTypographyGarbage.some(char => content.includes(char));
|
|
56
|
+
expect(hasAiPatterns).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it(`should not contain space before colon in ${relativePath}`, () => {
|
|
60
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
61
|
+
const spaceBeforeColon = / : /.test(content);
|
|
62
|
+
expect(spaceBeforeColon).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it(`should not contain double hyphen in ${relativePath}`, () => {
|
|
66
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
67
|
+
expect(content).not.toContain('--');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|