decant-core 1.2.5 → 1.3.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/ai/chatgpt.js CHANGED
@@ -716,10 +716,15 @@ export class ChatGPTParser extends ChatParser {
716
716
 
717
717
  const role = this.getMessageRole(container, roleElement);
718
718
  const noiseSelectors = [
719
- ".flex.gap-2",
719
+ ".flex.gap-2:not(.caption-panel):not(.caption-panel *)",
720
720
  "button",
721
721
  ".sr-only",
722
722
  '[role="button"]',
723
+ ".control-panel",
724
+ "[data-input-selector-group]",
725
+ "[data-input-selector-variable]",
726
+ '[role="slider"]',
727
+ ".AxvpHG_visualizationLayer",
723
728
  ];
724
729
  const contentParts = contentElements
725
730
  .map((contentElement) => {
@@ -14,11 +14,12 @@ export function sanitizeResponseContainer(container) {
14
14
  : [];
15
15
  unwanted.forEach((el) => el.remove());
16
16
 
17
- // 2. Remove base64 inline images to prevent megabyte-scale text walls in markdown exports
17
+ // 2. Remove base64 inline images to prevent megabyte-scale text walls in markdown exports,
18
+ // while preserving math LaTeX equation images marked with data-xpm-latex
18
19
  const images = clone.querySelectorAll ? clone.querySelectorAll("img") : [];
19
20
  images.forEach((img) => {
20
21
  const src = img.getAttribute("src") || "";
21
- if (src.startsWith("data:image/")) {
22
+ if (src.startsWith("data:image/") && !img.hasAttribute("data-xpm-latex")) {
22
23
  img.remove();
23
24
  }
24
25
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "decant-core",
3
- "version": "1.2.5",
3
+ "version": "1.3.0",
4
4
  "description": "Shared AI chat platform parsers and detection for Covai browser extensions.",
5
5
  "type": "module",
6
6
  "main": "ai/index.js",
@@ -164,7 +164,7 @@ export function convertToMarkdown(htmlContent, options = {}) {
164
164
  // Clone the element to avoid modifying the original
165
165
  const clone = htmlContent.cloneNode(true);
166
166
 
167
- // Convert math equations (KaTeX, data-math, and data-xpm-latex) to standard markdown math blocks
167
+ // Convert math equations (KaTeX, data-math, data-math-source, and data-xpm-latex) to standard markdown math blocks
168
168
  // Use alphanumeric placeholder tokens so Turndown text-escaping engine never corrupts LaTeX
169
169
  // 1. Process Gemini-style data-math attributes first (removes child .katex spans so they are not double-processed)
170
170
  clone.querySelectorAll("[data-math]").forEach((el) => {
@@ -175,7 +175,24 @@ export function convertToMarkdown(htmlContent, options = {}) {
175
175
  registerMath(el, latex, isBlock, clone.ownerDocument);
176
176
  });
177
177
 
178
- // 2. Process Google Search SGE LaTeX images with [data-xpm-latex]
178
+ // 2. Process ChatGPT data-math-source attributes
179
+ clone.querySelectorAll("[data-math-source]").forEach((el) => {
180
+ if (!clone.contains(el)) return;
181
+ const latex = el.getAttribute("data-math-source");
182
+ if (!latex) return;
183
+ const style = el.getAttribute("style") || "";
184
+ const isBlock =
185
+ el.classList.contains("katex-display") ||
186
+ el.querySelector(".katex-display") !== null ||
187
+ el.classList.contains("math-block") ||
188
+ el.classList.contains("AxvpHG_mathBlock") ||
189
+ el.closest?.(".AxvpHG_expandedDisplayContent") !== null ||
190
+ el.tagName === "DIV" ||
191
+ /display:\s*block/i.test(style);
192
+ registerMath(el, latex, isBlock, clone.ownerDocument);
193
+ });
194
+
195
+ // 3. Process Google Search SGE LaTeX images with [data-xpm-latex]
179
196
  clone.querySelectorAll("[data-xpm-latex]").forEach((el) => {
180
197
  if (!clone.contains(el)) return;
181
198
  const copyRoot = el.closest("[data-xpm-copy-root]");
@@ -198,7 +215,7 @@ export function convertToMarkdown(htmlContent, options = {}) {
198
215
  registerMath(container, latex, isBlock, clone.ownerDocument);
199
216
  });
200
217
 
201
- // 3. Process block display KaTeX (.katex-display)
218
+ // 4. Process block display KaTeX (.katex-display)
202
219
  clone.querySelectorAll(".katex-display").forEach((el) => {
203
220
  if (!clone.contains(el)) return;
204
221
  const annotation = el.querySelector(
@@ -206,11 +223,13 @@ export function convertToMarkdown(htmlContent, options = {}) {
206
223
  );
207
224
  const latex = annotation
208
225
  ? annotation.textContent.trim()
209
- : el.textContent.trim();
226
+ : el.getAttribute("data-math-source") ||
227
+ el.getAttribute("aria-label") ||
228
+ el.textContent.trim();
210
229
  registerMath(el, latex, true, clone.ownerDocument);
211
230
  });
212
231
 
213
- // 4. Process inline KaTeX (.katex)
232
+ // 5. Process inline KaTeX (.katex)
214
233
  clone.querySelectorAll(".katex").forEach((el) => {
215
234
  if (!clone.contains(el)) return;
216
235
  const annotation = el.querySelector(
@@ -218,7 +237,9 @@ export function convertToMarkdown(htmlContent, options = {}) {
218
237
  );
219
238
  const latex = annotation
220
239
  ? annotation.textContent.trim()
221
- : el.textContent.trim();
240
+ : el.getAttribute("data-math-source") ||
241
+ el.getAttribute("aria-label") ||
242
+ el.textContent.trim();
222
243
  registerMath(el, latex, false, clone.ownerDocument);
223
244
  });
224
245
 
@@ -358,6 +379,11 @@ export function convertToMarkdown(htmlContent, options = {}) {
358
379
  "aside.L9AUvd",
359
380
  "aside.UL0w9b",
360
381
  "div.qacuz",
382
+ ".control-panel",
383
+ "[data-input-selector-group]",
384
+ "[data-input-selector-variable]",
385
+ '[role="slider"]',
386
+ ".AxvpHG_visualizationLayer",
361
387
  ];
362
388
 
363
389
  noiseSelectors.forEach((selector) => {
package/web/article.js CHANGED
@@ -241,6 +241,14 @@ export class ArticleParser extends ChatParser {
241
241
  */
242
242
  isAvailable(url) {
243
243
  if (!url || typeof url !== "string") return false;
244
+ if (
245
+ typeof window !== "undefined" &&
246
+ window.self &&
247
+ window.top &&
248
+ window.self !== window.top
249
+ ) {
250
+ return false;
251
+ }
244
252
  return (
245
253
  url.startsWith("http://") ||
246
254
  url.startsWith("https://") ||