@emailens/engine 0.5.1 → 0.6.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/README.md +113 -1
- package/dist/{chunk-W4SPWESS.js → chunk-3NDQOTPM.js} +2 -2
- package/dist/{chunk-SZ5O5PDZ.js → chunk-OY3DGZVU.js} +2 -2
- package/dist/{chunk-PX25W7YG.js → chunk-URZ4XPST.js} +48 -20
- package/dist/chunk-URZ4XPST.js.map +1 -0
- package/dist/{chunk-PFONR3YC.js → chunk-ZQF2XUIJ.js} +1 -8
- package/dist/{chunk-PFONR3YC.js.map → chunk-ZQF2XUIJ.js.map} +1 -1
- package/dist/compile/index.cjs +45 -16
- package/dist/compile/index.cjs.map +1 -1
- package/dist/compile/index.js +7 -7
- package/dist/index.cjs +152 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +106 -1
- package/dist/index.d.ts +106 -1
- package/dist/index.js +152 -58
- package/dist/index.js.map +1 -1
- package/dist/maizzle-Y2CLJ7GB.js +8 -0
- package/dist/mjml-D7IOYXXK.js +8 -0
- package/dist/react-email-4TW6IDAA.js +8 -0
- package/package.json +25 -9
- package/dist/chunk-PX25W7YG.js.map +0 -1
- package/dist/maizzle-YDSYDVSM.js +0 -8
- package/dist/mjml-IYGC6AOM.js +0 -8
- package/dist/react-email-QRL5KZ4Y.js +0 -8
- /package/dist/{chunk-W4SPWESS.js.map → chunk-3NDQOTPM.js.map} +0 -0
- /package/dist/{chunk-SZ5O5PDZ.js.map → chunk-OY3DGZVU.js.map} +0 -0
- /package/dist/{maizzle-YDSYDVSM.js.map → maizzle-Y2CLJ7GB.js.map} +0 -0
- /package/dist/{mjml-IYGC6AOM.js.map → mjml-D7IOYXXK.js.map} +0 -0
- /package/dist/{react-email-QRL5KZ4Y.js.map → react-email-4TW6IDAA.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -223,9 +223,114 @@ interface AuditReport {
|
|
|
223
223
|
* Returns a unified report with compatibility warnings + scores,
|
|
224
224
|
* spam analysis, link validation, accessibility audit, and image analysis.
|
|
225
225
|
* Use the `skip` option to omit checks you don't need.
|
|
226
|
+
*
|
|
227
|
+
* Internally parses the HTML once and shares the parsed DOM across
|
|
228
|
+
* all analyzers to avoid redundant parsing overhead.
|
|
226
229
|
*/
|
|
227
230
|
declare function auditEmail(html: string, options?: AuditOptions): AuditReport;
|
|
228
231
|
|
|
232
|
+
interface CreateSessionOptions {
|
|
233
|
+
/** Framework for fix snippets (applies to analyze/audit/transform). */
|
|
234
|
+
framework?: Framework;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* A pre-parsed email session.
|
|
238
|
+
*
|
|
239
|
+
* Analysis methods (`analyze`, `audit`, `analyzeSpam`, `validateLinks`,
|
|
240
|
+
* `checkAccessibility`, `analyzeImages`) share a single Cheerio DOM
|
|
241
|
+
* parse, eliminating redundant parsing overhead.
|
|
242
|
+
*
|
|
243
|
+
* Transformation methods (`transformForClient`, `transformForAllClients`,
|
|
244
|
+
* `simulateDarkMode`) parse internally since they mutate the DOM per
|
|
245
|
+
* client. They still benefit from having the session hold the HTML and
|
|
246
|
+
* framework so you don't need to pass them repeatedly.
|
|
247
|
+
*/
|
|
248
|
+
interface EmailSession {
|
|
249
|
+
/** The original HTML string. */
|
|
250
|
+
readonly html: string;
|
|
251
|
+
/** The framework set at session creation. */
|
|
252
|
+
readonly framework: Framework | undefined;
|
|
253
|
+
/**
|
|
254
|
+
* Run all analysis checks in one call (shares pre-parsed DOM).
|
|
255
|
+
*
|
|
256
|
+
* Equivalent to `auditEmail()` but avoids re-parsing the HTML.
|
|
257
|
+
*/
|
|
258
|
+
audit(options?: Omit<AuditOptions, "framework">): AuditReport;
|
|
259
|
+
/**
|
|
260
|
+
* Analyze CSS compatibility warnings (shares pre-parsed DOM).
|
|
261
|
+
*
|
|
262
|
+
* Equivalent to `analyzeEmail()` but avoids re-parsing the HTML.
|
|
263
|
+
*/
|
|
264
|
+
analyze(): CSSWarning[];
|
|
265
|
+
/** Generate per-client compatibility scores from warnings. */
|
|
266
|
+
score(warnings: CSSWarning[]): Record<string, {
|
|
267
|
+
score: number;
|
|
268
|
+
errors: number;
|
|
269
|
+
warnings: number;
|
|
270
|
+
info: number;
|
|
271
|
+
}>;
|
|
272
|
+
/** Analyze spam indicators (shares pre-parsed DOM). */
|
|
273
|
+
analyzeSpam(options?: SpamAnalysisOptions): SpamReport;
|
|
274
|
+
/** Validate links (shares pre-parsed DOM). */
|
|
275
|
+
validateLinks(): LinkReport;
|
|
276
|
+
/** Check accessibility (shares pre-parsed DOM). */
|
|
277
|
+
checkAccessibility(): AccessibilityReport;
|
|
278
|
+
/** Analyze images (shares pre-parsed DOM). */
|
|
279
|
+
analyzeImages(): ImageReport;
|
|
280
|
+
/**
|
|
281
|
+
* Transform HTML for a specific client.
|
|
282
|
+
*
|
|
283
|
+
* Creates an isolated DOM copy per call (transforms mutate the DOM).
|
|
284
|
+
*/
|
|
285
|
+
transformForClient(clientId: string): TransformResult;
|
|
286
|
+
/**
|
|
287
|
+
* Transform HTML for all 12 email clients.
|
|
288
|
+
*
|
|
289
|
+
* Creates an isolated DOM copy per client (transforms mutate the DOM).
|
|
290
|
+
*/
|
|
291
|
+
transformForAllClients(): TransformResult[];
|
|
292
|
+
/**
|
|
293
|
+
* Simulate dark mode for a specific client.
|
|
294
|
+
*
|
|
295
|
+
* Creates an isolated DOM copy per call (simulation mutates the DOM).
|
|
296
|
+
* Operates on the **original** HTML — if you need dark mode on
|
|
297
|
+
* already-transformed HTML, use the standalone `simulateDarkMode()` instead.
|
|
298
|
+
*/
|
|
299
|
+
simulateDarkMode(clientId: string): {
|
|
300
|
+
html: string;
|
|
301
|
+
warnings: CSSWarning[];
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Create a session that pre-parses the HTML once and shares the parsed
|
|
306
|
+
* DOM across all read-only analysis operations.
|
|
307
|
+
*
|
|
308
|
+
* Use this when you need to call multiple analysis functions on the
|
|
309
|
+
* same HTML — it eliminates redundant `cheerio.load()` calls.
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```typescript
|
|
313
|
+
* import { createSession } from "@emailens/engine";
|
|
314
|
+
*
|
|
315
|
+
* const session = createSession(html, { framework: "jsx" });
|
|
316
|
+
*
|
|
317
|
+
* // These all share a single DOM parse:
|
|
318
|
+
* const warnings = session.analyze();
|
|
319
|
+
* const scores = session.score(warnings);
|
|
320
|
+
* const spam = session.analyzeSpam();
|
|
321
|
+
* const links = session.validateLinks();
|
|
322
|
+
* const a11y = session.checkAccessibility();
|
|
323
|
+
* const images = session.analyzeImages();
|
|
324
|
+
*
|
|
325
|
+
* // Or run everything at once:
|
|
326
|
+
* const report = session.audit();
|
|
327
|
+
*
|
|
328
|
+
* // Transforms still work (parse internally per client):
|
|
329
|
+
* const transforms = session.transformForAllClients();
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
declare function createSession(html: string, options?: CreateSessionOptions): EmailSession;
|
|
333
|
+
|
|
229
334
|
/**
|
|
230
335
|
* Shared constants used across the engine.
|
|
231
336
|
*/
|
|
@@ -270,4 +375,4 @@ declare function wcagGrade(ratio: number): WcagGrade;
|
|
|
270
375
|
*/
|
|
271
376
|
declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [number, number, number];
|
|
272
377
|
|
|
273
|
-
export { AI_FIX_SYSTEM_PROMPT, AccessibilityReport, AiFixResult, AiProvider, type AuditOptions, type AuditReport, CSSWarning, CodeFix, DiffResult, EMAIL_CLIENTS, EmailClient, ExportPromptOptions, Framework, GENERIC_LINK_TEXT, type GenerateAiFixOptions, ImageReport, LinkReport, MAX_HTML_SIZE, type RGBA, STRUCTURAL_FIX_PROPERTIES, SpamAnalysisOptions, SpamReport, TransformResult, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, checkAccessibility, contrastRatio, diffResults, errorWarnings, generateAiFix, generateCompatibilityScore, getClient, getCodeFix, getSuggestion, parseColor, relativeLuminance, simulateDarkMode, structuralWarnings, transformForAllClients, transformForClient, validateLinks, warningsForClient, wcagGrade };
|
|
378
|
+
export { AI_FIX_SYSTEM_PROMPT, AccessibilityReport, AiFixResult, AiProvider, type AuditOptions, type AuditReport, CSSWarning, CodeFix, type CreateSessionOptions, DiffResult, EMAIL_CLIENTS, EmailClient, type EmailSession, ExportPromptOptions, Framework, GENERIC_LINK_TEXT, type GenerateAiFixOptions, ImageReport, LinkReport, MAX_HTML_SIZE, type RGBA, STRUCTURAL_FIX_PROPERTIES, SpamAnalysisOptions, SpamReport, TransformResult, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, checkAccessibility, contrastRatio, createSession, diffResults, errorWarnings, generateAiFix, generateCompatibilityScore, getClient, getCodeFix, getSuggestion, parseColor, relativeLuminance, simulateDarkMode, structuralWarnings, transformForAllClients, transformForClient, validateLinks, warningsForClient, wcagGrade };
|
package/dist/index.d.ts
CHANGED
|
@@ -223,9 +223,114 @@ interface AuditReport {
|
|
|
223
223
|
* Returns a unified report with compatibility warnings + scores,
|
|
224
224
|
* spam analysis, link validation, accessibility audit, and image analysis.
|
|
225
225
|
* Use the `skip` option to omit checks you don't need.
|
|
226
|
+
*
|
|
227
|
+
* Internally parses the HTML once and shares the parsed DOM across
|
|
228
|
+
* all analyzers to avoid redundant parsing overhead.
|
|
226
229
|
*/
|
|
227
230
|
declare function auditEmail(html: string, options?: AuditOptions): AuditReport;
|
|
228
231
|
|
|
232
|
+
interface CreateSessionOptions {
|
|
233
|
+
/** Framework for fix snippets (applies to analyze/audit/transform). */
|
|
234
|
+
framework?: Framework;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* A pre-parsed email session.
|
|
238
|
+
*
|
|
239
|
+
* Analysis methods (`analyze`, `audit`, `analyzeSpam`, `validateLinks`,
|
|
240
|
+
* `checkAccessibility`, `analyzeImages`) share a single Cheerio DOM
|
|
241
|
+
* parse, eliminating redundant parsing overhead.
|
|
242
|
+
*
|
|
243
|
+
* Transformation methods (`transformForClient`, `transformForAllClients`,
|
|
244
|
+
* `simulateDarkMode`) parse internally since they mutate the DOM per
|
|
245
|
+
* client. They still benefit from having the session hold the HTML and
|
|
246
|
+
* framework so you don't need to pass them repeatedly.
|
|
247
|
+
*/
|
|
248
|
+
interface EmailSession {
|
|
249
|
+
/** The original HTML string. */
|
|
250
|
+
readonly html: string;
|
|
251
|
+
/** The framework set at session creation. */
|
|
252
|
+
readonly framework: Framework | undefined;
|
|
253
|
+
/**
|
|
254
|
+
* Run all analysis checks in one call (shares pre-parsed DOM).
|
|
255
|
+
*
|
|
256
|
+
* Equivalent to `auditEmail()` but avoids re-parsing the HTML.
|
|
257
|
+
*/
|
|
258
|
+
audit(options?: Omit<AuditOptions, "framework">): AuditReport;
|
|
259
|
+
/**
|
|
260
|
+
* Analyze CSS compatibility warnings (shares pre-parsed DOM).
|
|
261
|
+
*
|
|
262
|
+
* Equivalent to `analyzeEmail()` but avoids re-parsing the HTML.
|
|
263
|
+
*/
|
|
264
|
+
analyze(): CSSWarning[];
|
|
265
|
+
/** Generate per-client compatibility scores from warnings. */
|
|
266
|
+
score(warnings: CSSWarning[]): Record<string, {
|
|
267
|
+
score: number;
|
|
268
|
+
errors: number;
|
|
269
|
+
warnings: number;
|
|
270
|
+
info: number;
|
|
271
|
+
}>;
|
|
272
|
+
/** Analyze spam indicators (shares pre-parsed DOM). */
|
|
273
|
+
analyzeSpam(options?: SpamAnalysisOptions): SpamReport;
|
|
274
|
+
/** Validate links (shares pre-parsed DOM). */
|
|
275
|
+
validateLinks(): LinkReport;
|
|
276
|
+
/** Check accessibility (shares pre-parsed DOM). */
|
|
277
|
+
checkAccessibility(): AccessibilityReport;
|
|
278
|
+
/** Analyze images (shares pre-parsed DOM). */
|
|
279
|
+
analyzeImages(): ImageReport;
|
|
280
|
+
/**
|
|
281
|
+
* Transform HTML for a specific client.
|
|
282
|
+
*
|
|
283
|
+
* Creates an isolated DOM copy per call (transforms mutate the DOM).
|
|
284
|
+
*/
|
|
285
|
+
transformForClient(clientId: string): TransformResult;
|
|
286
|
+
/**
|
|
287
|
+
* Transform HTML for all 12 email clients.
|
|
288
|
+
*
|
|
289
|
+
* Creates an isolated DOM copy per client (transforms mutate the DOM).
|
|
290
|
+
*/
|
|
291
|
+
transformForAllClients(): TransformResult[];
|
|
292
|
+
/**
|
|
293
|
+
* Simulate dark mode for a specific client.
|
|
294
|
+
*
|
|
295
|
+
* Creates an isolated DOM copy per call (simulation mutates the DOM).
|
|
296
|
+
* Operates on the **original** HTML — if you need dark mode on
|
|
297
|
+
* already-transformed HTML, use the standalone `simulateDarkMode()` instead.
|
|
298
|
+
*/
|
|
299
|
+
simulateDarkMode(clientId: string): {
|
|
300
|
+
html: string;
|
|
301
|
+
warnings: CSSWarning[];
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Create a session that pre-parses the HTML once and shares the parsed
|
|
306
|
+
* DOM across all read-only analysis operations.
|
|
307
|
+
*
|
|
308
|
+
* Use this when you need to call multiple analysis functions on the
|
|
309
|
+
* same HTML — it eliminates redundant `cheerio.load()` calls.
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```typescript
|
|
313
|
+
* import { createSession } from "@emailens/engine";
|
|
314
|
+
*
|
|
315
|
+
* const session = createSession(html, { framework: "jsx" });
|
|
316
|
+
*
|
|
317
|
+
* // These all share a single DOM parse:
|
|
318
|
+
* const warnings = session.analyze();
|
|
319
|
+
* const scores = session.score(warnings);
|
|
320
|
+
* const spam = session.analyzeSpam();
|
|
321
|
+
* const links = session.validateLinks();
|
|
322
|
+
* const a11y = session.checkAccessibility();
|
|
323
|
+
* const images = session.analyzeImages();
|
|
324
|
+
*
|
|
325
|
+
* // Or run everything at once:
|
|
326
|
+
* const report = session.audit();
|
|
327
|
+
*
|
|
328
|
+
* // Transforms still work (parse internally per client):
|
|
329
|
+
* const transforms = session.transformForAllClients();
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
declare function createSession(html: string, options?: CreateSessionOptions): EmailSession;
|
|
333
|
+
|
|
229
334
|
/**
|
|
230
335
|
* Shared constants used across the engine.
|
|
231
336
|
*/
|
|
@@ -270,4 +375,4 @@ declare function wcagGrade(ratio: number): WcagGrade;
|
|
|
270
375
|
*/
|
|
271
376
|
declare function alphaBlend(fg: RGBA, bgR: number, bgG: number, bgB: number): [number, number, number];
|
|
272
377
|
|
|
273
|
-
export { AI_FIX_SYSTEM_PROMPT, AccessibilityReport, AiFixResult, AiProvider, type AuditOptions, type AuditReport, CSSWarning, CodeFix, DiffResult, EMAIL_CLIENTS, EmailClient, ExportPromptOptions, Framework, GENERIC_LINK_TEXT, type GenerateAiFixOptions, ImageReport, LinkReport, MAX_HTML_SIZE, type RGBA, STRUCTURAL_FIX_PROPERTIES, SpamAnalysisOptions, SpamReport, TransformResult, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, checkAccessibility, contrastRatio, diffResults, errorWarnings, generateAiFix, generateCompatibilityScore, getClient, getCodeFix, getSuggestion, parseColor, relativeLuminance, simulateDarkMode, structuralWarnings, transformForAllClients, transformForClient, validateLinks, warningsForClient, wcagGrade };
|
|
378
|
+
export { AI_FIX_SYSTEM_PROMPT, AccessibilityReport, AiFixResult, AiProvider, type AuditOptions, type AuditReport, CSSWarning, CodeFix, type CreateSessionOptions, DiffResult, EMAIL_CLIENTS, EmailClient, type EmailSession, ExportPromptOptions, Framework, GENERIC_LINK_TEXT, type GenerateAiFixOptions, ImageReport, LinkReport, MAX_HTML_SIZE, type RGBA, STRUCTURAL_FIX_PROPERTIES, SpamAnalysisOptions, SpamReport, TransformResult, type WcagGrade, alphaBlend, analyzeEmail, analyzeImages, analyzeSpam, auditEmail, checkAccessibility, contrastRatio, createSession, diffResults, errorWarnings, generateAiFix, generateCompatibilityScore, getClient, getCodeFix, getSuggestion, parseColor, relativeLuminance, simulateDarkMode, structuralWarnings, transformForAllClients, transformForClient, validateLinks, warningsForClient, wcagGrade };
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
__objRest,
|
|
4
4
|
__spreadProps,
|
|
5
5
|
__spreadValues
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ZQF2XUIJ.js";
|
|
7
7
|
|
|
8
8
|
// src/clients.ts
|
|
9
9
|
var EMAIL_CLIENTS = [
|
|
@@ -2747,6 +2747,14 @@ var GENERIC_LINK_TEXT = /* @__PURE__ */ new Set([
|
|
|
2747
2747
|
"tap here",
|
|
2748
2748
|
"this"
|
|
2749
2749
|
]);
|
|
2750
|
+
var EMPTY_SPAM = { score: 100, level: "low", issues: [] };
|
|
2751
|
+
var EMPTY_LINKS = {
|
|
2752
|
+
totalLinks: 0,
|
|
2753
|
+
issues: [],
|
|
2754
|
+
breakdown: { https: 0, http: 0, mailto: 0, tel: 0, anchor: 0, javascript: 0, protocolRelative: 0, other: 0 }
|
|
2755
|
+
};
|
|
2756
|
+
var EMPTY_ACCESSIBILITY = { score: 100, issues: [] };
|
|
2757
|
+
var EMPTY_IMAGES = { total: 0, totalDataUriBytes: 0, issues: [], images: [] };
|
|
2750
2758
|
|
|
2751
2759
|
// src/transform.ts
|
|
2752
2760
|
function inlineStyles($) {
|
|
@@ -3255,15 +3263,8 @@ function transformForAllClients(html, framework) {
|
|
|
3255
3263
|
// src/analyze.ts
|
|
3256
3264
|
import * as cheerio2 from "cheerio";
|
|
3257
3265
|
import * as csstree2 from "css-tree";
|
|
3258
|
-
function
|
|
3266
|
+
function analyzeEmailFromDom($, framework) {
|
|
3259
3267
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
3260
|
-
if (!html || !html.trim()) {
|
|
3261
|
-
return [];
|
|
3262
|
-
}
|
|
3263
|
-
if (html.length > MAX_HTML_SIZE) {
|
|
3264
|
-
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
3265
|
-
}
|
|
3266
|
-
const $ = cheerio2.load(html);
|
|
3267
3268
|
const warnings = [];
|
|
3268
3269
|
const seenWarnings = /* @__PURE__ */ new Set();
|
|
3269
3270
|
function addWarning(w) {
|
|
@@ -3508,6 +3509,16 @@ function analyzeEmail(html, framework) {
|
|
|
3508
3509
|
warnings.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
|
|
3509
3510
|
return warnings;
|
|
3510
3511
|
}
|
|
3512
|
+
function analyzeEmail(html, framework) {
|
|
3513
|
+
if (!html || !html.trim()) {
|
|
3514
|
+
return [];
|
|
3515
|
+
}
|
|
3516
|
+
if (html.length > MAX_HTML_SIZE) {
|
|
3517
|
+
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
3518
|
+
}
|
|
3519
|
+
const $ = cheerio2.load(html);
|
|
3520
|
+
return analyzeEmailFromDom($, framework);
|
|
3521
|
+
}
|
|
3511
3522
|
function getFixType(prop) {
|
|
3512
3523
|
return STRUCTURAL_FIX_PROPERTIES.has(prop) ? "structural" : "css";
|
|
3513
3524
|
}
|
|
@@ -4634,14 +4645,7 @@ function checkAllCapsTitle($) {
|
|
|
4634
4645
|
}
|
|
4635
4646
|
return null;
|
|
4636
4647
|
}
|
|
4637
|
-
function
|
|
4638
|
-
if (!html || !html.trim()) {
|
|
4639
|
-
return { score: 100, level: "low", issues: [] };
|
|
4640
|
-
}
|
|
4641
|
-
if (html.length > MAX_HTML_SIZE) {
|
|
4642
|
-
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
4643
|
-
}
|
|
4644
|
-
const $ = cheerio4.load(html);
|
|
4648
|
+
function analyzeSpamFromDom($, options) {
|
|
4645
4649
|
const text = extractVisibleText($);
|
|
4646
4650
|
const issues = [];
|
|
4647
4651
|
const capsIssue = checkCapsRatio(text);
|
|
@@ -4679,6 +4683,16 @@ function analyzeSpam(html, options) {
|
|
|
4679
4683
|
const level = score >= 70 ? "low" : score >= 40 ? "medium" : "high";
|
|
4680
4684
|
return { score, level, issues };
|
|
4681
4685
|
}
|
|
4686
|
+
function analyzeSpam(html, options) {
|
|
4687
|
+
if (!html || !html.trim()) {
|
|
4688
|
+
return { score: 100, level: "low", issues: [] };
|
|
4689
|
+
}
|
|
4690
|
+
if (html.length > MAX_HTML_SIZE) {
|
|
4691
|
+
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
4692
|
+
}
|
|
4693
|
+
const $ = cheerio4.load(html);
|
|
4694
|
+
return analyzeSpamFromDom($, options);
|
|
4695
|
+
}
|
|
4682
4696
|
|
|
4683
4697
|
// src/link-validator.ts
|
|
4684
4698
|
import * as cheerio5 from "cheerio";
|
|
@@ -4698,18 +4712,7 @@ function isPlaceholderHref(href) {
|
|
|
4698
4712
|
const h = href.trim().toLowerCase();
|
|
4699
4713
|
return h === "#" || h === "" || h === "javascript:void(0)" || h === "javascript:;";
|
|
4700
4714
|
}
|
|
4701
|
-
function
|
|
4702
|
-
if (!html || !html.trim()) {
|
|
4703
|
-
return {
|
|
4704
|
-
totalLinks: 0,
|
|
4705
|
-
issues: [],
|
|
4706
|
-
breakdown: { https: 0, http: 0, mailto: 0, tel: 0, anchor: 0, javascript: 0, protocolRelative: 0, other: 0 }
|
|
4707
|
-
};
|
|
4708
|
-
}
|
|
4709
|
-
if (html.length > MAX_HTML_SIZE) {
|
|
4710
|
-
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
4711
|
-
}
|
|
4712
|
-
const $ = cheerio5.load(html);
|
|
4715
|
+
function validateLinksFromDom($) {
|
|
4713
4716
|
const issues = [];
|
|
4714
4717
|
const breakdown = { https: 0, http: 0, mailto: 0, tel: 0, anchor: 0, javascript: 0, protocolRelative: 0, other: 0 };
|
|
4715
4718
|
const links = $("a");
|
|
@@ -4860,6 +4863,20 @@ function validateLinks(html) {
|
|
|
4860
4863
|
}
|
|
4861
4864
|
return { totalLinks, issues, breakdown };
|
|
4862
4865
|
}
|
|
4866
|
+
function validateLinks(html) {
|
|
4867
|
+
if (!html || !html.trim()) {
|
|
4868
|
+
return {
|
|
4869
|
+
totalLinks: 0,
|
|
4870
|
+
issues: [],
|
|
4871
|
+
breakdown: { https: 0, http: 0, mailto: 0, tel: 0, anchor: 0, javascript: 0, protocolRelative: 0, other: 0 }
|
|
4872
|
+
};
|
|
4873
|
+
}
|
|
4874
|
+
if (html.length > MAX_HTML_SIZE) {
|
|
4875
|
+
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
4876
|
+
}
|
|
4877
|
+
const $ = cheerio5.load(html);
|
|
4878
|
+
return validateLinksFromDom($);
|
|
4879
|
+
}
|
|
4863
4880
|
|
|
4864
4881
|
// src/accessibility-checker.ts
|
|
4865
4882
|
import * as cheerio6 from "cheerio";
|
|
@@ -5108,14 +5125,7 @@ function checkSemanticStructure($) {
|
|
|
5108
5125
|
}
|
|
5109
5126
|
return issues;
|
|
5110
5127
|
}
|
|
5111
|
-
function
|
|
5112
|
-
if (!html || !html.trim()) {
|
|
5113
|
-
return { score: 100, issues: [] };
|
|
5114
|
-
}
|
|
5115
|
-
if (html.length > MAX_HTML_SIZE) {
|
|
5116
|
-
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
5117
|
-
}
|
|
5118
|
-
const $ = cheerio6.load(html);
|
|
5128
|
+
function checkAccessibilityFromDom($) {
|
|
5119
5129
|
const issues = [];
|
|
5120
5130
|
const langIssue = checkLangAttribute($);
|
|
5121
5131
|
if (langIssue) issues.push(langIssue);
|
|
@@ -5148,6 +5158,16 @@ function checkAccessibility(html) {
|
|
|
5148
5158
|
const score = Math.max(0, 100 - penalty);
|
|
5149
5159
|
return { score, issues };
|
|
5150
5160
|
}
|
|
5161
|
+
function checkAccessibility(html) {
|
|
5162
|
+
if (!html || !html.trim()) {
|
|
5163
|
+
return { score: 100, issues: [] };
|
|
5164
|
+
}
|
|
5165
|
+
if (html.length > MAX_HTML_SIZE) {
|
|
5166
|
+
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
5167
|
+
}
|
|
5168
|
+
const $ = cheerio6.load(html);
|
|
5169
|
+
return checkAccessibilityFromDom($);
|
|
5170
|
+
}
|
|
5151
5171
|
|
|
5152
5172
|
// src/image-analyzer.ts
|
|
5153
5173
|
import * as cheerio7 from "cheerio";
|
|
@@ -5181,14 +5201,7 @@ function truncateSrc(src, max = 60) {
|
|
|
5181
5201
|
}
|
|
5182
5202
|
return src.length > max ? src.slice(0, max - 3) + "..." : src;
|
|
5183
5203
|
}
|
|
5184
|
-
function
|
|
5185
|
-
if (!html || !html.trim()) {
|
|
5186
|
-
return { total: 0, totalDataUriBytes: 0, issues: [], images: [] };
|
|
5187
|
-
}
|
|
5188
|
-
if (html.length > MAX_HTML_SIZE) {
|
|
5189
|
-
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
5190
|
-
}
|
|
5191
|
-
const $ = cheerio7.load(html);
|
|
5204
|
+
function analyzeImagesFromDom($) {
|
|
5192
5205
|
const issues = [];
|
|
5193
5206
|
const images = [];
|
|
5194
5207
|
let totalDataUriBytes = 0;
|
|
@@ -5314,16 +5327,19 @@ function analyzeImages(html) {
|
|
|
5314
5327
|
}
|
|
5315
5328
|
return { total: images.length, totalDataUriBytes, issues, images };
|
|
5316
5329
|
}
|
|
5330
|
+
function analyzeImages(html) {
|
|
5331
|
+
if (!html || !html.trim()) {
|
|
5332
|
+
return { total: 0, totalDataUriBytes: 0, issues: [], images: [] };
|
|
5333
|
+
}
|
|
5334
|
+
if (html.length > MAX_HTML_SIZE) {
|
|
5335
|
+
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
5336
|
+
}
|
|
5337
|
+
const $ = cheerio7.load(html);
|
|
5338
|
+
return analyzeImagesFromDom($);
|
|
5339
|
+
}
|
|
5317
5340
|
|
|
5318
5341
|
// src/audit.ts
|
|
5319
|
-
|
|
5320
|
-
var EMPTY_LINKS = {
|
|
5321
|
-
totalLinks: 0,
|
|
5322
|
-
issues: [],
|
|
5323
|
-
breakdown: { https: 0, http: 0, mailto: 0, tel: 0, anchor: 0, javascript: 0, protocolRelative: 0, other: 0 }
|
|
5324
|
-
};
|
|
5325
|
-
var EMPTY_ACCESSIBILITY = { score: 100, issues: [] };
|
|
5326
|
-
var EMPTY_IMAGES = { total: 0, totalDataUriBytes: 0, issues: [], images: [] };
|
|
5342
|
+
import * as cheerio8 from "cheerio";
|
|
5327
5343
|
function auditEmail(html, options) {
|
|
5328
5344
|
var _a;
|
|
5329
5345
|
if (!html || !html.trim()) {
|
|
@@ -5340,14 +5356,91 @@ function auditEmail(html, options) {
|
|
|
5340
5356
|
}
|
|
5341
5357
|
const framework = options == null ? void 0 : options.framework;
|
|
5342
5358
|
const skip = new Set((_a = options == null ? void 0 : options.skip) != null ? _a : []);
|
|
5343
|
-
const
|
|
5359
|
+
const $ = cheerio8.load(html);
|
|
5360
|
+
const warnings = skip.has("compatibility") ? [] : analyzeEmailFromDom($, framework);
|
|
5344
5361
|
const scores = skip.has("compatibility") ? {} : generateCompatibilityScore(warnings);
|
|
5345
|
-
const spam = skip.has("spam") ? EMPTY_SPAM :
|
|
5346
|
-
const links = skip.has("links") ? EMPTY_LINKS :
|
|
5347
|
-
const accessibility = skip.has("accessibility") ? EMPTY_ACCESSIBILITY :
|
|
5348
|
-
const images = skip.has("images") ? EMPTY_IMAGES :
|
|
5362
|
+
const spam = skip.has("spam") ? EMPTY_SPAM : analyzeSpamFromDom($, options == null ? void 0 : options.spam);
|
|
5363
|
+
const links = skip.has("links") ? EMPTY_LINKS : validateLinksFromDom($);
|
|
5364
|
+
const accessibility = skip.has("accessibility") ? EMPTY_ACCESSIBILITY : checkAccessibilityFromDom($);
|
|
5365
|
+
const images = skip.has("images") ? EMPTY_IMAGES : analyzeImagesFromDom($);
|
|
5349
5366
|
return { compatibility: { warnings, scores }, spam, links, accessibility, images };
|
|
5350
5367
|
}
|
|
5368
|
+
|
|
5369
|
+
// src/session.ts
|
|
5370
|
+
import * as cheerio9 from "cheerio";
|
|
5371
|
+
function createSession(html, options) {
|
|
5372
|
+
if (!html || !html.trim()) {
|
|
5373
|
+
const fw = options == null ? void 0 : options.framework;
|
|
5374
|
+
return {
|
|
5375
|
+
html: html || "",
|
|
5376
|
+
framework: fw,
|
|
5377
|
+
audit: () => ({
|
|
5378
|
+
compatibility: { warnings: [], scores: {} },
|
|
5379
|
+
spam: EMPTY_SPAM,
|
|
5380
|
+
links: EMPTY_LINKS,
|
|
5381
|
+
accessibility: EMPTY_ACCESSIBILITY,
|
|
5382
|
+
images: EMPTY_IMAGES
|
|
5383
|
+
}),
|
|
5384
|
+
analyze: () => [],
|
|
5385
|
+
score: () => ({}),
|
|
5386
|
+
analyzeSpam: () => EMPTY_SPAM,
|
|
5387
|
+
validateLinks: () => EMPTY_LINKS,
|
|
5388
|
+
checkAccessibility: () => EMPTY_ACCESSIBILITY,
|
|
5389
|
+
analyzeImages: () => EMPTY_IMAGES,
|
|
5390
|
+
transformForClient: (clientId) => ({ clientId, html: html || "", warnings: [] }),
|
|
5391
|
+
transformForAllClients: () => [],
|
|
5392
|
+
simulateDarkMode: (clientId) => ({ html: html || "", warnings: [] })
|
|
5393
|
+
};
|
|
5394
|
+
}
|
|
5395
|
+
if (html.length > MAX_HTML_SIZE) {
|
|
5396
|
+
throw new Error(`HTML input exceeds ${MAX_HTML_SIZE / 1024}KB limit.`);
|
|
5397
|
+
}
|
|
5398
|
+
const $ = cheerio9.load(html);
|
|
5399
|
+
const framework = options == null ? void 0 : options.framework;
|
|
5400
|
+
return {
|
|
5401
|
+
html,
|
|
5402
|
+
framework,
|
|
5403
|
+
audit(opts) {
|
|
5404
|
+
var _a;
|
|
5405
|
+
const skip = new Set((_a = opts == null ? void 0 : opts.skip) != null ? _a : []);
|
|
5406
|
+
const warnings = skip.has("compatibility") ? [] : analyzeEmailFromDom($, framework);
|
|
5407
|
+
const scores = skip.has("compatibility") ? {} : generateCompatibilityScore(warnings);
|
|
5408
|
+
const spam = skip.has("spam") ? EMPTY_SPAM : analyzeSpamFromDom($, opts == null ? void 0 : opts.spam);
|
|
5409
|
+
const links = skip.has("links") ? EMPTY_LINKS : validateLinksFromDom($);
|
|
5410
|
+
const accessibility = skip.has("accessibility") ? EMPTY_ACCESSIBILITY : checkAccessibilityFromDom($);
|
|
5411
|
+
const images = skip.has("images") ? EMPTY_IMAGES : analyzeImagesFromDom($);
|
|
5412
|
+
return { compatibility: { warnings, scores }, spam, links, accessibility, images };
|
|
5413
|
+
},
|
|
5414
|
+
analyze() {
|
|
5415
|
+
return analyzeEmailFromDom($, framework);
|
|
5416
|
+
},
|
|
5417
|
+
score(warnings) {
|
|
5418
|
+
return generateCompatibilityScore(warnings);
|
|
5419
|
+
},
|
|
5420
|
+
analyzeSpam(opts) {
|
|
5421
|
+
return analyzeSpamFromDom($, opts);
|
|
5422
|
+
},
|
|
5423
|
+
validateLinks() {
|
|
5424
|
+
return validateLinksFromDom($);
|
|
5425
|
+
},
|
|
5426
|
+
checkAccessibility() {
|
|
5427
|
+
return checkAccessibilityFromDom($);
|
|
5428
|
+
},
|
|
5429
|
+
analyzeImages() {
|
|
5430
|
+
return analyzeImagesFromDom($);
|
|
5431
|
+
},
|
|
5432
|
+
// Transforms create isolated copies since they mutate the DOM
|
|
5433
|
+
transformForClient(clientId) {
|
|
5434
|
+
return transformForClient(html, clientId, framework);
|
|
5435
|
+
},
|
|
5436
|
+
transformForAllClients() {
|
|
5437
|
+
return transformForAllClients(html, framework);
|
|
5438
|
+
},
|
|
5439
|
+
simulateDarkMode(clientId) {
|
|
5440
|
+
return simulateDarkMode(html, clientId);
|
|
5441
|
+
}
|
|
5442
|
+
};
|
|
5443
|
+
}
|
|
5351
5444
|
export {
|
|
5352
5445
|
AI_FIX_SYSTEM_PROMPT,
|
|
5353
5446
|
CompileError,
|
|
@@ -5362,6 +5455,7 @@ export {
|
|
|
5362
5455
|
auditEmail,
|
|
5363
5456
|
checkAccessibility,
|
|
5364
5457
|
contrastRatio,
|
|
5458
|
+
createSession,
|
|
5365
5459
|
diffResults,
|
|
5366
5460
|
errorWarnings,
|
|
5367
5461
|
estimateAiFixTokens,
|