@emailens/engine 0.10.2 → 0.10.3

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/dist/index.cjs CHANGED
@@ -11021,6 +11021,54 @@ function locOfAttr(el, attr) {
11021
11021
  const attrLoc = (_d = (_a = raw.attrs) == null ? void 0 : _a[attr]) != null ? _d : (_c = (_b = raw.startTag) == null ? void 0 : _b.attrs) == null ? void 0 : _c[attr];
11022
11022
  return attrLoc ? toLoc(attrLoc) : locOfElement(el);
11023
11023
  }
11024
+ function locInAttr(attrLoc, source, property, occurrence = 0) {
11025
+ if (!attrLoc || !source) return void 0;
11026
+ const raw = source.slice(attrLoc.offset, attrLoc.offset + attrLoc.length);
11027
+ const open = raw.search(/["']/);
11028
+ const close = raw.lastIndexOf(raw[open]);
11029
+ if (open === -1 || close <= open) return void 0;
11030
+ const found = declarationsIn(raw.slice(open + 1, close), property);
11031
+ const hit = found[occurrence];
11032
+ if (!hit) return void 0;
11033
+ const start = attrLoc.offset + open + 1 + hit.start;
11034
+ const end = attrLoc.offset + open + 1 + hit.end;
11035
+ const from = positionOf(source, start);
11036
+ const to = positionOf(source, end);
11037
+ return {
11038
+ line: from.line,
11039
+ column: from.column,
11040
+ endLine: to.line,
11041
+ endColumn: to.column,
11042
+ offset: start,
11043
+ length: end - start
11044
+ };
11045
+ }
11046
+ function declarationsIn(value, property) {
11047
+ const wanted = property.toLowerCase();
11048
+ const found = [];
11049
+ let depth = 0;
11050
+ let start = 0;
11051
+ const consider = (from, to) => {
11052
+ const text = value.slice(from, to);
11053
+ const colon = text.indexOf(":");
11054
+ if (colon === -1) return;
11055
+ if (text.slice(0, colon).trim().toLowerCase() !== wanted) return;
11056
+ const lead = text.length - text.trimStart().length;
11057
+ const trail = text.length - text.trimEnd().length;
11058
+ if (from + lead < to - trail) found.push({ start: from + lead, end: to - trail });
11059
+ };
11060
+ for (let i = 0; i < value.length; i++) {
11061
+ const c = value[i];
11062
+ if (c === "(") depth++;
11063
+ else if (c === ")") depth = Math.max(0, depth - 1);
11064
+ else if (c === ";" && depth === 0) {
11065
+ consider(start, i);
11066
+ start = i + 1;
11067
+ }
11068
+ }
11069
+ consider(start, value.length);
11070
+ return found;
11071
+ }
11024
11072
  function locOfFirst($, selector) {
11025
11073
  const el = $(selector).first()[0];
11026
11074
  return el ? locOfElement(el) : void 0;
@@ -11286,7 +11334,7 @@ function describeSelector($, el) {
11286
11334
  if (cls) return `${tag}.${cls.split(/\s+/)[0]}`;
11287
11335
  return tag;
11288
11336
  }
11289
- function checkDarkModeFromDom($) {
11337
+ function checkDarkModeFromDom($, source) {
11290
11338
  var _a, _b;
11291
11339
  const darkBlock = collectDarkBlocks($);
11292
11340
  if (!darkBlock) return [];
@@ -11313,7 +11361,7 @@ function checkDarkModeFromDom($) {
11313
11361
  const coveredByAny = matchedElements($, darkBlock.any);
11314
11362
  let uncovered = 0;
11315
11363
  $("[bgcolor], [style]").each((_, el) => {
11316
- var _a2;
11364
+ var _a2, _b2;
11317
11365
  if (uncovered >= MAX_UNCOVERED_ELEMENTS) return false;
11318
11366
  const $el = $(el);
11319
11367
  const style = parseInlineStyle($el.attr("style") || "");
@@ -11323,7 +11371,8 @@ function checkDarkModeFromDom($) {
11323
11371
  if (inline ? coveredByImportant.has(el) : coveredByAny.has(el)) return;
11324
11372
  uncovered++;
11325
11373
  const selector = describeSelector($, el);
11326
- const loc = locOfAttr(el, inline ? "style" : "bgcolor");
11374
+ const attrLoc = locOfAttr(el, inline ? "style" : "bgcolor");
11375
+ const loc = inline ? (_b2 = locInAttr(attrLoc, source, style.get("background-color") !== void 0 ? "background-color" : "background")) != null ? _b2 : attrLoc : attrLoc;
11327
11376
  for (const clientId of PREFERS_COLOR_SCHEME_CLIENTS) {
11328
11377
  warnings.push(__spreadValues({
11329
11378
  severity: "warning",
@@ -11588,18 +11637,37 @@ function analyzeEmailFromDom($, framework, source) {
11588
11637
  const style = $(el).attr("style") || "";
11589
11638
  const props = parseStyleProperties(style);
11590
11639
  const selector = describeSelector2(el);
11591
- const locs = elementLocs(locOfAttr(el, "style"));
11640
+ const attrLoc = locOfAttr(el, "style");
11641
+ const declarationLocs = (prop, occurrence = 0) => {
11642
+ var _a;
11643
+ return (_a = elementLocs(locInAttr(attrLoc, source, prop, occurrence))) != null ? _a : elementLocs(attrLoc);
11644
+ };
11645
+ const locs = elementLocs(attrLoc);
11592
11646
  for (const prop of props) {
11593
11647
  for (const det of COMPOUND_DETECTORS) {
11594
11648
  if (prop === det.property) {
11595
11649
  const value2 = getStyleValue(style, prop);
11596
11650
  if (value2 == null ? void 0 : value2.toLowerCase().includes(det.valueIncludes)) {
11597
- checkPropertySupport(det.key, addWarning, framework, selector, void 0, void 0, locs);
11651
+ checkPropertySupport(
11652
+ det.key,
11653
+ addWarning,
11654
+ framework,
11655
+ selector,
11656
+ void 0,
11657
+ void 0,
11658
+ declarationLocs(prop)
11659
+ );
11598
11660
  }
11599
11661
  }
11600
11662
  }
11601
11663
  if (cssPropertiesToCheck.includes(prop)) {
11602
11664
  const declared = getStyleValues(style, prop);
11665
+ const placed = [];
11666
+ declared.forEach((value2, i) => {
11667
+ const at = locInAttr(attrLoc, source, prop, i);
11668
+ if (at) placed.push({ value: value2, loc: at });
11669
+ });
11670
+ const occurrences = placed.length === declared.length && placed.length > 0 ? { locs: placed.map((p) => p.loc), values: placed.map((p) => p.value) } : locs;
11603
11671
  checkPropertySupport(
11604
11672
  prop,
11605
11673
  addWarning,
@@ -11607,14 +11675,22 @@ function analyzeEmailFromDom($, framework, source) {
11607
11675
  selector,
11608
11676
  void 0,
11609
11677
  declared.length ? declared : void 0,
11610
- locs
11678
+ occurrences
11611
11679
  );
11612
11680
  }
11613
11681
  const value = getStyleValue(style, prop);
11614
11682
  if (value) {
11615
11683
  for (const fn of CSS_FUNCTION_DETECTORS) {
11616
11684
  if (value.includes(fn.pattern)) {
11617
- checkPropertySupport(fn.key, addWarning, framework, selector, void 0, void 0, locs);
11685
+ checkPropertySupport(
11686
+ fn.key,
11687
+ addWarning,
11688
+ framework,
11689
+ selector,
11690
+ void 0,
11691
+ void 0,
11692
+ declarationLocs(prop)
11693
+ );
11618
11694
  }
11619
11695
  }
11620
11696
  }
@@ -11653,7 +11729,7 @@ function analyzeEmailFromDom($, framework, source) {
11653
11729
  for (const fn of detectedCssFunctions) {
11654
11730
  checkPropertySupport(fn, addWarning, framework, void 0, propertyLines.get(fn), void 0, propertyLocs.get(fn));
11655
11731
  }
11656
- for (const w of checkDarkModeFromDom($)) addWarning(w);
11732
+ for (const w of checkDarkModeFromDom($, source)) addWarning(w);
11657
11733
  const severityOrder = { error: 0, warning: 1, info: 2 };
11658
11734
  warnings.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
11659
11735
  return warnings;