@lynxflow/seo-engine 1.8.30 → 2.0.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 (96) hide show
  1. package/README.md +47 -93
  2. package/dist/ai-copilot-client.d.ts +2 -0
  3. package/dist/built-in-locations.d.ts +18 -0
  4. package/dist/content-ai-arsenal.d.ts +28 -0
  5. package/dist/existing-media-harvester.d.ts +33 -0
  6. package/dist/extended-schemas.d.ts +84 -0
  7. package/dist/features-knowledge-harvester.d.ts +56 -0
  8. package/dist/geo-citation-scorer.d.ts +34 -0
  9. package/dist/i18n-detector.d.ts +1 -1
  10. package/dist/index.d.ts +32 -7
  11. package/dist/index.js +538 -82
  12. package/dist/index.mjs +2028 -163
  13. package/dist/internal-pagerank-graph.d.ts +59 -0
  14. package/dist/knowledge-bank-builder.d.ts +91 -0
  15. package/dist/marketing-skills-engine.d.ts +74 -0
  16. package/dist/matrix-engine.d.ts +26 -0
  17. package/dist/power-words-psychology.d.ts +27 -15
  18. package/dist/public-manifest-engine.d.ts +58 -0
  19. package/dist/rag-knowledge-engine.d.ts +50 -0
  20. package/dist/rate-limited-translator.d.ts +19 -0
  21. package/dist/token-quota-manager.d.ts +4 -0
  22. package/package.json +11 -3
  23. package/TUTORIEL_INTEGRATION_SITE.md +0 -283
  24. package/connectors/cloudflare-worker/worker.js +0 -106
  25. package/connectors/laravel/LynxSeoController.php +0 -37
  26. package/connectors/wordpress/lynxseo-admin-app.js +0 -2611
  27. package/connectors/wordpress/lynxseo-connector.php +0 -1712
  28. package/connectors/wordpress/lynxseo-connector.zip +0 -0
  29. package/lynxflow-seo-engine-1.2.0.tgz +0 -0
  30. package/src/ad-intelligence-cro.ts +0 -140
  31. package/src/ai-bots-log-analyzer.ts +0 -127
  32. package/src/ai-copilot-client.ts +0 -99
  33. package/src/analytics-client.ts +0 -315
  34. package/src/auth-key.ts +0 -262
  35. package/src/backlinks-client.ts +0 -85
  36. package/src/brand-dna-calendar.ts +0 -120
  37. package/src/brand-icons.ts +0 -138
  38. package/src/built-in-locations.ts +0 -170
  39. package/src/content-ai-arsenal.ts +0 -268
  40. package/src/copy-frameworks-master.ts +0 -89
  41. package/src/cro-copywriting-engine.ts +0 -105
  42. package/src/crosslink-scorer.ts +0 -101
  43. package/src/embeddable-seo-widget.ts +0 -57
  44. package/src/engine.test.ts +0 -386
  45. package/src/engine.ts +0 -813
  46. package/src/existing-media-harvester.ts +0 -98
  47. package/src/extended-schemas.ts +0 -589
  48. package/src/features-knowledge-harvester.ts +0 -190
  49. package/src/free-public-tools.ts +0 -224
  50. package/src/geo-mesh-linking.ts +0 -93
  51. package/src/google-business-profile.ts +0 -280
  52. package/src/i18n-detector.ts +0 -98
  53. package/src/i18n-dictionary.ts +0 -422
  54. package/src/index.ts +0 -164
  55. package/src/indexnow-client.ts +0 -94
  56. package/src/instant-matrix-search.ts +0 -48
  57. package/src/isr-cache-manager.ts +0 -78
  58. package/src/keyword-permutator.ts +0 -118
  59. package/src/knowledge-bank-builder.ts +0 -299
  60. package/src/knowledge-graph-linker.ts +0 -81
  61. package/src/lago-token-meter.ts +0 -120
  62. package/src/legal-disclaimers.ts +0 -407
  63. package/src/llm-content-cleaner.ts +0 -64
  64. package/src/llm-prompt.ts +0 -323
  65. package/src/master-marketing-engine.ts +0 -314
  66. package/src/matrix-engine.ts +0 -1204
  67. package/src/mcp-seo-server.ts +0 -108
  68. package/src/ngram-density-analyzer.ts +0 -108
  69. package/src/og-image-generator.ts +0 -109
  70. package/src/power-words-psychology.ts +0 -369
  71. package/src/public-manifest-engine.ts +0 -109
  72. package/src/rag-knowledge-engine.ts +0 -163
  73. package/src/rank-math-parity.ts +0 -235
  74. package/src/rate-limited-translator.ts +0 -110
  75. package/src/real-reviews-sync.ts +0 -207
  76. package/src/rss-syndication-feed.ts +0 -56
  77. package/src/schema-builder.ts +0 -134
  78. package/src/seo-opportunities-decay.ts +0 -154
  79. package/src/serp-client.ts +0 -89
  80. package/src/serp-history-alerts.ts +0 -75
  81. package/src/site-auditor.ts +0 -83
  82. package/src/site-crawler.ts +0 -406
  83. package/src/slug-engine.ts +0 -183
  84. package/src/social-ads-seo.ts +0 -211
  85. package/src/social-growth-suite.ts +0 -310
  86. package/src/social-trend-seo.ts +0 -103
  87. package/src/social-video-seo.ts +0 -100
  88. package/src/team-rbac.ts +0 -61
  89. package/src/technical-rules-auditor.ts +0 -171
  90. package/src/token-quota-manager.ts +0 -91
  91. package/src/types.ts +0 -143
  92. package/src/ui-icons.ts +0 -134
  93. package/src/urlytics-engine.ts +0 -97
  94. package/src/video-youtube-analyzer.ts +0 -81
  95. package/src/yoast-parity.ts +0 -161
  96. package/tsconfig.json +0 -15
@@ -1,81 +0,0 @@
1
- /**
2
- * 🧠 Google Knowledge Graph Entity Linker (Inspiration: advertools/knowledge_graph.py)
3
- *
4
- * Resolves official Google Entity IDs (`kgmid`), entity types, and Wikidata URIs
5
- * to maximize semantic authority and Knowledge Panel recognition (Entity SEO).
6
- */
7
-
8
- export interface KnowledgeGraphEntity {
9
- name: string;
10
- kgmid: string; // e.g. "/m/02zsn" or "kg:/g/11b6t4q7k"
11
- types: string[]; // e.g. ["Organization", "Corporation", "SoftwareApplication"]
12
- description?: string;
13
- detailedDescriptionUrl?: string;
14
- wikidataUri?: string;
15
- resultScore: number;
16
- }
17
-
18
- export class KnowledgeGraphLinker {
19
- /**
20
- * Constructs search query parameters for the Google Knowledge Graph Search API.
21
- */
22
- static buildSearchUrl(query: string, apiKey: string, limit = 5, languages = ["fr", "en"]): string {
23
- const params = new URLSearchParams({
24
- query,
25
- key: apiKey,
26
- limit: String(limit),
27
- indent: "true",
28
- languages: languages.join(","),
29
- });
30
- return `https://kgsearch.googleapis.com/v1/entities:search?${params.toString()}`;
31
- }
32
-
33
- /**
34
- * Parses Google Knowledge Graph JSON-LD response items into normalized entities.
35
- */
36
- static parseApiResponse(jsonResponse: any): KnowledgeGraphEntity[] {
37
- if (!jsonResponse || !Array.isArray(jsonResponse.itemListElement)) {
38
- return [];
39
- }
40
-
41
- return jsonResponse.itemListElement.map((item: any) => {
42
- const result = item.result || {};
43
- const kgmid = result["@id"] || "";
44
- const types = Array.isArray(result["@type"]) ? result["@type"] : [result["@type"] || "Thing"];
45
- const detailed = result.detailedDescription || {};
46
-
47
- let wikidataUri: string | undefined;
48
- if (detailed.url && detailed.url.includes("wikipedia.org")) {
49
- wikidataUri = detailed.url;
50
- }
51
-
52
- return {
53
- name: result.name || "",
54
- kgmid,
55
- types,
56
- description: detailed.articleBody || result.description,
57
- detailedDescriptionUrl: detailed.url,
58
- wikidataUri,
59
- resultScore: item.resultScore || 0,
60
- };
61
- });
62
- }
63
-
64
- /**
65
- * Generates Schema.org `sameAs` entity triples combining Google kgmid and Wikipedia/Wikidata.
66
- */
67
- static generateEntitySameAsLinks(entity: KnowledgeGraphEntity, customUrls: string[] = []): string[] {
68
- const links: string[] = [...customUrls];
69
-
70
- if (entity.kgmid) {
71
- const cleanMid = entity.kgmid.replace(/^kg:/, "");
72
- links.push(`https://www.google.com/search?kgmid=${encodeURIComponent(cleanMid)}`);
73
- }
74
-
75
- if (entity.wikidataUri) {
76
- links.push(entity.wikidataUri);
77
- }
78
-
79
- return Array.from(new Set(links));
80
- }
81
- }
@@ -1,120 +0,0 @@
1
- /**
2
- * 🦩 Lago Metered Token Billing & Hyperswitch Payment Bridge
3
- *
4
- * Reports live `ai_tokens` consumption events to Lago and initiates
5
- * checkout / subscription sessions through Hyperswitch universal payment router.
6
- */
7
-
8
- declare const process: any;
9
-
10
- export interface LagoUsageEvent {
11
- transactionId: string;
12
- externalCustomerId: string;
13
- code: "ai_tokens" | "pseo_pages_generated" | "serp_scrapes";
14
- units: number;
15
- timestamp: number; // Unix timestamp
16
- properties?: Record<string, unknown>;
17
- }
18
-
19
- export interface HyperswitchCheckoutConfig {
20
- apiKey: string;
21
- baseUrl?: string;
22
- profileId?: string;
23
- }
24
-
25
- export class LagoTokenMeter {
26
- private lagoApiUrl: string;
27
- private apiKey: string;
28
-
29
- constructor(
30
- apiKey = (typeof process !== "undefined" && process.env && process.env.LAGO_API_KEY) || "",
31
- lagoApiUrl = (typeof process !== "undefined" && process.env && process.env.LAGO_API_URL) || "http://localhost:3000/api/v1"
32
- ) {
33
- this.apiKey = apiKey;
34
- this.lagoApiUrl = lagoApiUrl;
35
- }
36
-
37
- /**
38
- * Sends a real-time token metering event to Lago.
39
- */
40
- async trackTokenUsage(externalCustomerId: string, tokenCount: number, model: string): Promise<boolean> {
41
- if (!this.apiKey) {
42
- // Local fallback mode
43
- return true;
44
- }
45
-
46
- const event: LagoUsageEvent = {
47
- transactionId: `tx_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
48
- externalCustomerId,
49
- code: "ai_tokens",
50
- units: tokenCount,
51
- timestamp: Math.floor(Date.now() / 1000),
52
- properties: { model },
53
- };
54
-
55
- try {
56
- const res = await fetch(`${this.lagoApiUrl}/events`, {
57
- method: "POST",
58
- headers: {
59
- "Content-Type": "application/json",
60
- Authorization: `Bearer ${this.apiKey}`,
61
- },
62
- body: JSON.stringify({ event }),
63
- });
64
- return res.ok;
65
- } catch {
66
- return false;
67
- }
68
- }
69
- }
70
-
71
- export class HyperswitchGateway {
72
- private config: HyperswitchCheckoutConfig;
73
-
74
- constructor(config: HyperswitchCheckoutConfig) {
75
- this.config = {
76
- baseUrl: "https://sandbox.hyperswitch.io",
77
- ...config,
78
- };
79
- }
80
-
81
- /**
82
- * Creates a payment intent routed through Hyperswitch.
83
- */
84
- async createPaymentIntent(amountCents: number, currency: string, customerId: string, metadata: Record<string, string> = {}) {
85
- if (!this.config.apiKey) {
86
- return {
87
- paymentId: `hyp_mock_${Date.now()}`,
88
- status: "succeeded",
89
- amount: amountCents,
90
- currency,
91
- clientSecret: "mock_secret",
92
- };
93
- }
94
-
95
- try {
96
- const res = await fetch(`${this.config.baseUrl}/payments`, {
97
- method: "POST",
98
- headers: {
99
- "Content-Type": "application/json",
100
- "api-key": this.config.apiKey,
101
- },
102
- body: JSON.stringify({
103
- amount: amountCents,
104
- currency: currency.toUpperCase(),
105
- customer_id: customerId,
106
- metadata,
107
- }),
108
- });
109
-
110
- if (!res.ok) throw new Error(`Hyperswitch HTTP ${res.status}`);
111
- return await res.json();
112
- } catch (err: any) {
113
- return {
114
- error: err.message,
115
- paymentId: `hyp_fallback_${Date.now()}`,
116
- status: "requires_payment_method",
117
- };
118
- }
119
- }
120
- }
@@ -1,407 +0,0 @@
1
- /**
2
- * Global Legal Compliance & Editorial Disclaimer Engine for B2B pSEO
3
- * Multilingual compliance and anti-disparagement verification across 10+ languages.
4
- */
5
-
6
- export type DisclaimerType =
7
- | "comparison"
8
- | "pricing"
9
- | "feature"
10
- | "exclusivity"
11
- | "statistics"
12
- | "alternative"
13
- | "listicle";
14
-
15
- export interface DisclaimerTemplate {
16
- type: DisclaimerType;
17
- label: string;
18
- templateText: string;
19
- }
20
-
21
- /**
22
- * Multilingual Disclaimer Templates (English Default + Localized Fallbacks)
23
- */
24
- export const MULTILINGUAL_DISCLAIMERS: Record<string, Record<DisclaimerType, DisclaimerTemplate>> = {
25
- // 🇬🇧 English (Default)
26
- en: {
27
- comparison: {
28
- type: "comparison",
29
- label: "Standard Comparison Notice",
30
- templateText:
31
- "Editorial note: We research and verify all claims in our comparison articles using publicly available documentation. Pricing and features are subject to change by each provider. Report any inaccuracies to {correctionsEmail}.",
32
- },
33
- pricing: {
34
- type: "pricing",
35
- label: "Pricing Transparency Disclaimer",
36
- templateText:
37
- "Pricing disclaimer: All competitor pricing and plan details were verified on {lastVerifiedDate}. Providers may update their rates at any time without notice. Please verify current rates on the official provider website before making purchasing decisions.",
38
- },
39
- feature: {
40
- type: "feature",
41
- label: "Feature Capability Note",
42
- templateText:
43
- "Feature comparison note: Feature availability and tier limits were verified on {lastVerifiedDate}. Software updates occur continuously; consult each vendor's documentation for live specifications.",
44
- },
45
- exclusivity: {
46
- type: "exclusivity",
47
- label: "Exclusivity Distinction Claim",
48
- templateText:
49
- "Distinction note: To the best of our knowledge as of {lastVerifiedDate}, this architectural capability distinction is accurate based on public benchmarks.",
50
- },
51
- statistics: {
52
- type: "statistics",
53
- label: "Public Data & Statistics Note",
54
- templateText:
55
- "Data note: Statistics and benchmarks cited in this article are derived from public industry reports and official platform metrics as of {lastVerifiedDate}.",
56
- },
57
- alternative: {
58
- type: "alternative",
59
- label: "Alternative Directory Notice",
60
- templateText:
61
- "Editorial note: This page compares software alternatives objectively based on public specifications, user feedback, and architectural differences to help buyers make informed decisions.",
62
- },
63
- listicle: {
64
- type: "listicle",
65
- label: "Curated Directory & Review Notice",
66
- templateText:
67
- "Editorial note: Rankings and software evaluations reflect our objective editorial criteria and testing methodology. Inaccuracies can be flagged to {correctionsEmail}.",
68
- },
69
- },
70
-
71
- // 🇫🇷 French
72
- fr: {
73
- comparison: {
74
- type: "comparison",
75
- label: "Note Éditoriale de Comparatif",
76
- templateText:
77
- "Note éditoriale : Nous vérifions scrupuleusement les informations sur la base des documentations publiques. Les fonctionnalités et tarifs évoluent régulièrement. Signalez toute inexactitude à {correctionsEmail}.",
78
- },
79
- pricing: {
80
- type: "pricing",
81
- label: "Avertissement sur les Tarifs",
82
- templateText:
83
- "Avertissement tarifaire : Les prix et offres ont été relevés le {lastVerifiedDate}. Les éditeurs peuvent modifier leurs conditions sans préavis. Vérifiez les tarifs officiels avant toute souscription.",
84
- },
85
- feature: {
86
- type: "feature",
87
- label: "Vérification des Fonctionnalités",
88
- templateText:
89
- "Note sur les fonctionnalités : La disponibilité des options a été vérifiée le {lastVerifiedDate}. Consultez les sites éditeurs pour les spécifications en direct.",
90
- },
91
- exclusivity: {
92
- type: "exclusivity",
93
- label: "Revendication d'Exclusivité",
94
- templateText:
95
- "Note d'exclusivité : Selon nos informations vérifiées au {lastVerifiedDate}, cette capacité technique est exclusive à notre plateforme.",
96
- },
97
- statistics: {
98
- type: "statistics",
99
- label: "Données et Statistiques Publiques",
100
- templateText:
101
- "Source des données : Les métriques citées proviennent de rapports sectoriels publics au {lastVerifiedDate}.",
102
- },
103
- alternative: {
104
- type: "alternative",
105
- label: "Annuaire des Alternatives",
106
- templateText:
107
- "Note éditoriale : Cette sélection compare objectivement les solutions du marché pour éclairer le choix des décideurs.",
108
- },
109
- listicle: {
110
- type: "listicle",
111
- label: "Méthodologie de Classement",
112
- templateText:
113
- "Note éditoriale : Ce classement reflète notre analyse technique indépendante. Contact : {correctionsEmail}.",
114
- },
115
- },
116
-
117
- // 🇩🇪 German
118
- de: {
119
- comparison: {
120
- type: "comparison",
121
- label: "Redaktioneller Vergleichshinweis",
122
- templateText:
123
- "Redaktioneller Hinweis: Wir recherchieren und prüfen alle Angaben anhand öffentlich zugänglicher Dokumentationen. Preise und Funktionen können sich ändern. Bitte melden Sie Unstimmigkeiten an {correctionsEmail}.",
124
- },
125
- pricing: {
126
- type: "pricing",
127
- label: "Preistransparenz-Hinweis",
128
- templateText:
129
- "Preishinweis: Alle Preisangaben wurden am {lastVerifiedDate} überprüft. Anbieter können ihre Preise jederzeit anpassen. Bitte prüfen Sie die offiziellen Anbieterseiten.",
130
- },
131
- feature: {
132
- type: "feature",
133
- label: "Funktionshinweis",
134
- templateText:
135
- "Funktionshinweis: Die Verfügbarkeit von Funktionen wurde am {lastVerifiedDate} verifiziert.",
136
- },
137
- exclusivity: {
138
- type: "exclusivity",
139
- label: "Exklusivitätsangabe",
140
- templateText:
141
- "Hinweis: Nach unserem Kenntnisstand vom {lastVerifiedDate} ist dieses Merkmal eine spezifische Eigenschaft unserer Lösung.",
142
- },
143
- statistics: {
144
- type: "statistics",
145
- label: "Statistikhinweis",
146
- templateText:
147
- "Datenhinweis: Die genannten Statistiken basieren auf öffentlich zugänglichen Branchenberichten mit Stand vom {lastVerifiedDate}.",
148
- },
149
- alternative: {
150
- type: "alternative",
151
- label: "Alternativen-Verzeichnis",
152
- templateText:
153
- "Redaktioneller Hinweis: Dieser Vergleich bietet eine objektive Gegenüberstellung moderner Software-Alternativen.",
154
- },
155
- listicle: {
156
- type: "listicle",
157
- label: "Bewertungshinweis",
158
- templateText:
159
- "Redaktioneller Hinweis: Bewertungen basieren auf unserer unabhängigen Testmethodik. Feedback an {correctionsEmail}.",
160
- },
161
- },
162
-
163
- // 🇪🇸 Spanish
164
- es: {
165
- comparison: {
166
- type: "comparison",
167
- label: "Nota Editorial Comparativa",
168
- templateText:
169
- "Nota editorial: Investigamos y verificamos la información con datos públicos. Los precios y funciones pueden variar. Notifique cualquier error a {correctionsEmail}.",
170
- },
171
- pricing: {
172
- type: "pricing",
173
- label: "Aviso sobre Precios",
174
- templateText:
175
- "Aviso de precios: Toda la información de precios fue verificada el {lastVerifiedDate}. Los proveedores pueden cambiar sus tarifas sin previo aviso.",
176
- },
177
- feature: {
178
- type: "feature",
179
- label: "Nota de Funcionalidades",
180
- templateText:
181
- "Nota de funciones: La disponibilidad de funciones fue verificada el {lastVerifiedDate}.",
182
- },
183
- exclusivity: {
184
- type: "exclusivity",
185
- label: "Distinción Exclusiva",
186
- templateText:
187
- "Nota de exclusividad: Según los datos verificados al {lastVerifiedDate}, esta capacidad es única de nuestra plataforma.",
188
- },
189
- statistics: {
190
- type: "statistics",
191
- label: "Datos Estadísticos",
192
- templateText:
193
- "Nota de datos: Las estadísticas provienen de informes sectoriales públicos al {lastVerifiedDate}.",
194
- },
195
- alternative: {
196
- type: "alternative",
197
- label: "Directorio de Alternativas",
198
- templateText:
199
- "Nota editorial: Esta página compara alternativas de software de forma objetiva para ayudar en la toma de decisiones.",
200
- },
201
- listicle: {
202
- type: "listicle",
203
- label: "Metodología del Ranking",
204
- templateText:
205
- "Nota editorial: Las recomendaciones se basan en nuestro análisis objetivo. Contacto: {correctionsEmail}.",
206
- },
207
- },
208
- };
209
-
210
- /**
211
- * Multilingual Banned & Disparaging Words Dictionary across 10 Languages
212
- */
213
- export const MULTILINGUAL_BANNED_DISPARAGING_WORDS: Record<string, string[]> = {
214
- // 🇬🇧 English
215
- en: [
216
- "is a scam",
217
- "fraudulent",
218
- "worst software",
219
- "useless product",
220
- "terrible company",
221
- "don't trust",
222
- "rip-off",
223
- "garbage software",
224
- "incompetent",
225
- ],
226
-
227
- // 🇫🇷 French
228
- fr: [
229
- "est une arnaque",
230
- "frauduleux",
231
- "pire logiciel",
232
- "produit inutile",
233
- "entreprise malhonnête",
234
- "ne faites pas confiance",
235
- "escroquerie",
236
- "logiciel poubelle",
237
- "incompétent",
238
- ],
239
-
240
- // 🇩🇪 German
241
- de: [
242
- "ist ein betrug",
243
- "betrügerisch",
244
- "schlechteste software",
245
- "nutzloses produkt",
246
- "unseriöse firma",
247
- "nicht vertrauen",
248
- "abzocke",
249
- "müll software",
250
- "inkompetent",
251
- ],
252
-
253
- // 🇪🇸 Spanish
254
- es: [
255
- "es una estafa",
256
- "fraudulento",
257
- "peor software",
258
- "producto inutil",
259
- "empresa deshonesta",
260
- "no confie",
261
- "timo",
262
- "software basura",
263
- "incompetente",
264
- ],
265
-
266
- // 🇮🇹 Italian
267
- it: [
268
- "e una truffa",
269
- "fraudolento",
270
- "peggior software",
271
- "prodotto inutile",
272
- "azienda disonesta",
273
- "non fidarti",
274
- "fregatura",
275
- "software spazzatura",
276
- ],
277
-
278
- // 🇵🇹 Portuguese
279
- pt: [
280
- "e um golpe",
281
- "fraudulento",
282
- "pior software",
283
- "produto inutil",
284
- "empresa desonesta",
285
- "nao confie",
286
- "engranacao",
287
- "software lixo",
288
- ],
289
-
290
- // 🇳🇱 Dutch
291
- nl: [
292
- "is oplichterij",
293
- "frauduleus",
294
- "slechtste software",
295
- "nutteloos product",
296
- "onbetrouwbaar bedrijf",
297
- "niet vertrouwen",
298
- ],
299
-
300
- // 🇷🇺 Russian (Latinized)
301
- ru: [
302
- "eto moshennichestvo",
303
- "hudshiy soft",
304
- "bespoleznyy produkt",
305
- "obman",
306
- ],
307
-
308
- // 🇸🇪 Swedish
309
- sv: [
310
- "ar en bluff",
311
- "bedraglig",
312
- "samsta mjukvaran",
313
- "vardelos produkt",
314
- "lita inte pa",
315
- ],
316
-
317
- // 🇵🇱 Polish
318
- pl: [
319
- "to oszustwo",
320
- "najgorsze oprogramowanie",
321
- "bezuzyteczny produkt",
322
- "nie ufaj",
323
- ],
324
- };
325
-
326
- export interface LegalEngineOptions {
327
- companyName?: string;
328
- correctionsEmail?: string;
329
- dataStalenessDays?: number;
330
- language?: string;
331
- }
332
-
333
- export class LegalDisclaimerEngine {
334
- private companyName: string;
335
- private correctionsEmail: string;
336
- private dataStalenessDays: number;
337
- private defaultLanguage: string;
338
-
339
- constructor(options: LegalEngineOptions = {}) {
340
- this.companyName = options.companyName || "Our Platform";
341
- this.correctionsEmail = options.correctionsEmail || "compliance@platform.com";
342
- this.dataStalenessDays = options.dataStalenessDays ?? 90;
343
- this.defaultLanguage = options.language || "en";
344
- }
345
-
346
- /**
347
- * Generates a fully resolved disclaimer note in the target language (defaults to English).
348
- */
349
- getDisclaimer(type: DisclaimerType, lastVerifiedDate?: string, language?: string): string {
350
- const lang = language || this.defaultLanguage;
351
- const langTemplates = MULTILINGUAL_DISCLAIMERS[lang] || MULTILINGUAL_DISCLAIMERS.en;
352
- const template = langTemplates[type]?.templateText || MULTILINGUAL_DISCLAIMERS.en.comparison.templateText;
353
- const dateStr = lastVerifiedDate || new Date().toISOString().split("T")[0];
354
-
355
- return template
356
- .replace(/{companyName}/g, this.companyName)
357
- .replace(/{correctionsEmail}/g, this.correctionsEmail)
358
- .replace(/{lastVerifiedDate}/g, dateStr);
359
- }
360
-
361
- /**
362
- * Evaluates if competitor pricing or feature claim data is older than the allowed staleness window (default: 90 days).
363
- */
364
- isDataStale(lastVerifiedDateStr?: string): boolean {
365
- if (!lastVerifiedDateStr) return true;
366
- const verified = new Date(lastVerifiedDateStr).getTime();
367
- if (isNaN(verified)) return true;
368
-
369
- const diffDays = (Date.now() - verified) / (1000 * 60 * 60 * 24);
370
- return diffDays > this.dataStalenessDays;
371
- }
372
-
373
- /**
374
- * Validates content against disparaging or legally hazardous statements across all supported languages.
375
- */
376
- validateCompliance(content: string, competitorName: string, language: string = "all"): { isCompliant: boolean; warnings: string[] } {
377
- const warnings: string[] = [];
378
- const lowerContent = content.toLowerCase();
379
- const lowerComp = competitorName.toLowerCase();
380
-
381
- // Check banned phrases in target language or across all languages
382
- const activeLanguages = language === "all"
383
- ? Object.keys(MULTILINGUAL_BANNED_DISPARAGING_WORDS)
384
- : [language];
385
-
386
- for (const lang of activeLanguages) {
387
- const phrases = MULTILINGUAL_BANNED_DISPARAGING_WORDS[lang] || [];
388
- for (const phrase of phrases) {
389
- if (lowerContent.includes(phrase)) {
390
- warnings.push(`[${lang.toUpperCase()}] Hazardous disparaging claim detected: "${phrase}". Maintain objective technical framing.`);
391
- }
392
- }
393
- }
394
-
395
- // Mention frequency check (prevent trademark keyword stuffing)
396
- const regex = new RegExp(`\\b${lowerComp}\\b`, "gi");
397
- const count = (lowerContent.match(regex) || []).length;
398
- if (count > 25) {
399
- warnings.push(`Excessive competitor trademark mentions (${count} times). Reduce to under 20 to avoid trademark dilution flags.`);
400
- }
401
-
402
- return {
403
- isCompliant: warnings.length === 0,
404
- warnings,
405
- };
406
- }
407
- }
@@ -1,64 +0,0 @@
1
- /**
2
- * 🧹 Boilerplate Stripper & Clean Markdown Extractor for LLMs (Inspiration: openserp/extract)
3
- *
4
- * Strips navigation, headers, footers, cookie banners, and advertisements from raw HTML
5
- * to produce clean, high-density markdown text for AI search ingestion (/llms.txt & ChatGPT).
6
- */
7
-
8
- export class LlmContentCleaner {
9
- /**
10
- * Alias: Cleans text or markdown for LLMs.
11
- */
12
- static cleanForLlm(content: string): string {
13
- return this.htmlToCleanMarkdown(content);
14
- }
15
-
16
- /**
17
- * Cleans raw HTML and returns pure readable markdown content.
18
- */
19
- static htmlToCleanMarkdown(rawHtml: string): string {
20
- if (!rawHtml) return "";
21
-
22
- let cleaned = rawHtml
23
- // Remove scripts, styles, iframes, SVGs
24
- .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, " ")
25
- .replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, " ")
26
- .replace(/<svg\b[^<]*(?:(?!<\/svg>)<[^<]*)*<\/svg>/gi, " ")
27
- .replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, " ")
28
- // Remove navigation, headers, footers, modals, cookie banners
29
- .replace(/<nav\b[^<]*(?:(?!<\/nav>)<[^<]*)*<\/nav>/gi, " ")
30
- .replace(/<footer\b[^<]*(?:(?!<\/footer>)<[^<]*)*<\/footer>/gi, " ")
31
- .replace(/<header\b[^<]*(?:(?!<\/header>)<[^<]*)*<\/header>/gi, " ")
32
- .replace(/<aside\b[^<]*(?:(?!<\/aside>)<[^<]*)*<\/aside>/gi, " ")
33
- // Convert headings
34
- .replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, "\n# $1\n")
35
- .replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, "\n## $1\n")
36
- .replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, "\n### $1\n")
37
- .replace(/<h4[^>]*>([\s\S]*?)<\/h4>/gi, "\n#### $1\n")
38
- // Convert lists
39
- .replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, "\n* $1")
40
- // Convert paragraphs and line breaks
41
- .replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, "\n$1\n")
42
- .replace(/<br\s*[\/]?>/gi, "\n")
43
- // Convert links
44
- .replace(/<a[^>]*href=["']([^"']*)["'][^>]*>([\s\S]*?)<\/a>/gi, "[$2]($1)")
45
- // Strip remaining HTML tags
46
- .replace(/<[^>]+>/g, " ")
47
- // Decode basic HTML entities
48
- .replace(/&nbsp;/g, " ")
49
- .replace(/&amp;/g, "&")
50
- .replace(/&lt;/g, "<")
51
- .replace(/&gt;/g, ">")
52
- .replace(/&quot;/g, '"')
53
- .replace(/&#39;/g, "'");
54
-
55
- // Clean whitespace and repeated linebreaks
56
- cleaned = cleaned
57
- .split("\n")
58
- .map((line) => line.trim())
59
- .filter((line, i, arr) => line !== "" || (i > 0 && arr[i - 1] !== ""))
60
- .join("\n");
61
-
62
- return cleaned.trim();
63
- }
64
- }