@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.js CHANGED
@@ -10915,6 +10915,54 @@ function locOfAttr(el, attr) {
10915
10915
  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];
10916
10916
  return attrLoc ? toLoc(attrLoc) : locOfElement(el);
10917
10917
  }
10918
+ function locInAttr(attrLoc, source, property, occurrence = 0) {
10919
+ if (!attrLoc || !source) return void 0;
10920
+ const raw = source.slice(attrLoc.offset, attrLoc.offset + attrLoc.length);
10921
+ const open = raw.search(/["']/);
10922
+ const close = raw.lastIndexOf(raw[open]);
10923
+ if (open === -1 || close <= open) return void 0;
10924
+ const found = declarationsIn(raw.slice(open + 1, close), property);
10925
+ const hit = found[occurrence];
10926
+ if (!hit) return void 0;
10927
+ const start = attrLoc.offset + open + 1 + hit.start;
10928
+ const end = attrLoc.offset + open + 1 + hit.end;
10929
+ const from = positionOf(source, start);
10930
+ const to = positionOf(source, end);
10931
+ return {
10932
+ line: from.line,
10933
+ column: from.column,
10934
+ endLine: to.line,
10935
+ endColumn: to.column,
10936
+ offset: start,
10937
+ length: end - start
10938
+ };
10939
+ }
10940
+ function declarationsIn(value, property) {
10941
+ const wanted = property.toLowerCase();
10942
+ const found = [];
10943
+ let depth = 0;
10944
+ let start = 0;
10945
+ const consider = (from, to) => {
10946
+ const text = value.slice(from, to);
10947
+ const colon = text.indexOf(":");
10948
+ if (colon === -1) return;
10949
+ if (text.slice(0, colon).trim().toLowerCase() !== wanted) return;
10950
+ const lead = text.length - text.trimStart().length;
10951
+ const trail = text.length - text.trimEnd().length;
10952
+ if (from + lead < to - trail) found.push({ start: from + lead, end: to - trail });
10953
+ };
10954
+ for (let i = 0; i < value.length; i++) {
10955
+ const c = value[i];
10956
+ if (c === "(") depth++;
10957
+ else if (c === ")") depth = Math.max(0, depth - 1);
10958
+ else if (c === ";" && depth === 0) {
10959
+ consider(start, i);
10960
+ start = i + 1;
10961
+ }
10962
+ }
10963
+ consider(start, value.length);
10964
+ return found;
10965
+ }
10918
10966
  function locOfFirst($, selector) {
10919
10967
  const el = $(selector).first()[0];
10920
10968
  return el ? locOfElement(el) : void 0;
@@ -11180,7 +11228,7 @@ function describeSelector($, el) {
11180
11228
  if (cls) return `${tag}.${cls.split(/\s+/)[0]}`;
11181
11229
  return tag;
11182
11230
  }
11183
- function checkDarkModeFromDom($) {
11231
+ function checkDarkModeFromDom($, source) {
11184
11232
  var _a, _b;
11185
11233
  const darkBlock = collectDarkBlocks($);
11186
11234
  if (!darkBlock) return [];
@@ -11207,7 +11255,7 @@ function checkDarkModeFromDom($) {
11207
11255
  const coveredByAny = matchedElements($, darkBlock.any);
11208
11256
  let uncovered = 0;
11209
11257
  $("[bgcolor], [style]").each((_, el) => {
11210
- var _a2;
11258
+ var _a2, _b2;
11211
11259
  if (uncovered >= MAX_UNCOVERED_ELEMENTS) return false;
11212
11260
  const $el = $(el);
11213
11261
  const style = parseInlineStyle($el.attr("style") || "");
@@ -11217,7 +11265,8 @@ function checkDarkModeFromDom($) {
11217
11265
  if (inline ? coveredByImportant.has(el) : coveredByAny.has(el)) return;
11218
11266
  uncovered++;
11219
11267
  const selector = describeSelector($, el);
11220
- const loc = locOfAttr(el, inline ? "style" : "bgcolor");
11268
+ const attrLoc = locOfAttr(el, inline ? "style" : "bgcolor");
11269
+ const loc = inline ? (_b2 = locInAttr(attrLoc, source, style.get("background-color") !== void 0 ? "background-color" : "background")) != null ? _b2 : attrLoc : attrLoc;
11221
11270
  for (const clientId of PREFERS_COLOR_SCHEME_CLIENTS) {
11222
11271
  warnings.push(__spreadValues({
11223
11272
  severity: "warning",
@@ -11482,18 +11531,37 @@ function analyzeEmailFromDom($, framework, source) {
11482
11531
  const style = $(el).attr("style") || "";
11483
11532
  const props = parseStyleProperties(style);
11484
11533
  const selector = describeSelector2(el);
11485
- const locs = elementLocs(locOfAttr(el, "style"));
11534
+ const attrLoc = locOfAttr(el, "style");
11535
+ const declarationLocs = (prop, occurrence = 0) => {
11536
+ var _a;
11537
+ return (_a = elementLocs(locInAttr(attrLoc, source, prop, occurrence))) != null ? _a : elementLocs(attrLoc);
11538
+ };
11539
+ const locs = elementLocs(attrLoc);
11486
11540
  for (const prop of props) {
11487
11541
  for (const det of COMPOUND_DETECTORS) {
11488
11542
  if (prop === det.property) {
11489
11543
  const value2 = getStyleValue(style, prop);
11490
11544
  if (value2 == null ? void 0 : value2.toLowerCase().includes(det.valueIncludes)) {
11491
- checkPropertySupport(det.key, addWarning, framework, selector, void 0, void 0, locs);
11545
+ checkPropertySupport(
11546
+ det.key,
11547
+ addWarning,
11548
+ framework,
11549
+ selector,
11550
+ void 0,
11551
+ void 0,
11552
+ declarationLocs(prop)
11553
+ );
11492
11554
  }
11493
11555
  }
11494
11556
  }
11495
11557
  if (cssPropertiesToCheck.includes(prop)) {
11496
11558
  const declared = getStyleValues(style, prop);
11559
+ const placed = [];
11560
+ declared.forEach((value2, i) => {
11561
+ const at = locInAttr(attrLoc, source, prop, i);
11562
+ if (at) placed.push({ value: value2, loc: at });
11563
+ });
11564
+ const occurrences = placed.length === declared.length && placed.length > 0 ? { locs: placed.map((p) => p.loc), values: placed.map((p) => p.value) } : locs;
11497
11565
  checkPropertySupport(
11498
11566
  prop,
11499
11567
  addWarning,
@@ -11501,14 +11569,22 @@ function analyzeEmailFromDom($, framework, source) {
11501
11569
  selector,
11502
11570
  void 0,
11503
11571
  declared.length ? declared : void 0,
11504
- locs
11572
+ occurrences
11505
11573
  );
11506
11574
  }
11507
11575
  const value = getStyleValue(style, prop);
11508
11576
  if (value) {
11509
11577
  for (const fn of CSS_FUNCTION_DETECTORS) {
11510
11578
  if (value.includes(fn.pattern)) {
11511
- checkPropertySupport(fn.key, addWarning, framework, selector, void 0, void 0, locs);
11579
+ checkPropertySupport(
11580
+ fn.key,
11581
+ addWarning,
11582
+ framework,
11583
+ selector,
11584
+ void 0,
11585
+ void 0,
11586
+ declarationLocs(prop)
11587
+ );
11512
11588
  }
11513
11589
  }
11514
11590
  }
@@ -11547,7 +11623,7 @@ function analyzeEmailFromDom($, framework, source) {
11547
11623
  for (const fn of detectedCssFunctions) {
11548
11624
  checkPropertySupport(fn, addWarning, framework, void 0, propertyLines.get(fn), void 0, propertyLocs.get(fn));
11549
11625
  }
11550
- for (const w of checkDarkModeFromDom($)) addWarning(w);
11626
+ for (const w of checkDarkModeFromDom($, source)) addWarning(w);
11551
11627
  const severityOrder = { error: 0, warning: 1, info: 2 };
11552
11628
  warnings.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
11553
11629
  return warnings;