@iasiv5/dsh-quota-watch 0.0.17 → 0.0.18

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/lib/client.js CHANGED
@@ -363,7 +363,7 @@ function mountQuotaCard({
363
363
  container.dataset.dshQuotaWatchCard = "";
364
364
  container.dataset.dshPlugin = "quota-watch";
365
365
  container.dataset.dshPart = "sidebar-card";
366
- const style = text(doc, "style", "", STYLE_TEXT);
366
+ let style = text(doc, "style", "", STYLE_TEXT);
367
367
  const card = doc.createElement("section");
368
368
  card.className = "dqw-card";
369
369
  card.setAttribute("aria-label", copy.title);
@@ -383,6 +383,25 @@ function mountQuotaCard({
383
383
  body.append(lastUpdated);
384
384
  card.append(body);
385
385
  container.append(style, card, railTrigger);
386
+ const supportsAdopted = Array.isArray(doc.adoptedStyleSheets) && typeof win.CSSStyleSheet === "function";
387
+ let adoptedSheet = null;
388
+ if (supportsAdopted) {
389
+ try {
390
+ adoptedSheet = new win.CSSStyleSheet();
391
+ adoptedSheet.replaceSync(STYLE_TEXT);
392
+ doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, adoptedSheet];
393
+ } catch {
394
+ adoptedSheet = null;
395
+ }
396
+ }
397
+ let styleAlive = () => doc.contains(style) && style.sheet !== null && style.sheet.cssRules.length > 0;
398
+ let ensureStyleAlive = () => {
399
+ if (styleAlive()) return;
400
+ const fresh = text(doc, "style", "", STYLE_TEXT);
401
+ if (doc.contains(style)) style.replaceWith(fresh);
402
+ else container.prepend(fresh);
403
+ style = fresh;
404
+ };
386
405
  const pop = doc.createElement("div");
387
406
  pop.className = "dqw-pop";
388
407
  pop.id = "dqw-quota-watch-pop";
@@ -659,6 +678,7 @@ function mountQuotaCard({
659
678
  positionPop();
660
679
  };
661
680
  const renderAll = () => {
681
+ ensureStyleAlive();
662
682
  const providers = snapshot?.providers ?? [];
663
683
  const glm = providers.find((provider) => provider?.key === "glm");
664
684
  const copilot = providers.find((provider) => provider?.key === "copilot");
@@ -840,6 +860,9 @@ function mountQuotaCard({
840
860
  pop.removeEventListener("click", onPopClick);
841
861
  container.remove();
842
862
  pop.remove();
863
+ if (adoptedSheet !== null && Array.isArray(doc.adoptedStyleSheets)) {
864
+ doc.adoptedStyleSheets = doc.adoptedStyleSheets.filter((sheet) => sheet !== adoptedSheet);
865
+ }
843
866
  };
844
867
  }
845
868
  function apply(ctx) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iasiv5/dsh-quota-watch",
3
- "version": "0.0.17",
3
+ "version": "0.0.18",
4
4
  "description": "DSH Web sidebar monitor for GLM Coding Plan quotas and GitHub Copilot credits",
5
5
  "type": "module",
6
6
  "main": "./src/host.mjs",
package/src/client.mjs CHANGED
@@ -304,7 +304,7 @@ export function mountQuotaCard({
304
304
  container.dataset.dshQuotaWatchCard = ''
305
305
  container.dataset.dshPlugin = 'quota-watch'
306
306
  container.dataset.dshPart = 'sidebar-card'
307
- const style = text(doc, 'style', '', STYLE_TEXT)
307
+ let style = text(doc, 'style', '', STYLE_TEXT)
308
308
  const card = doc.createElement('section')
309
309
  card.className = 'dqw-card'
310
310
  card.setAttribute('aria-label', copy.title)
@@ -325,6 +325,34 @@ export function mountQuotaCard({
325
325
  body.append(lastUpdated)
326
326
  card.append(body)
327
327
  container.append(style, card, railTrigger)
328
+ // The card carries its stylesheet in a <style> tag next to its DOM. External
329
+ // actors (browser extensions, aggressive theming) have been observed to strip
330
+ // or neuter foreign style tags while the page's styles churn (theme switches,
331
+ // plugin reloads, service restarts); the card then renders unstyled until a
332
+ // full page refresh. Two defenses:
333
+ // 1. mirror the rules into a constructable stylesheet (adoptedStyleSheets),
334
+ // which those actors do not touch;
335
+ // 2. re-create the tag on every render pass that finds it dead or missing.
336
+ const supportsAdopted =
337
+ Array.isArray(doc.adoptedStyleSheets) && typeof win.CSSStyleSheet === 'function'
338
+ let adoptedSheet = null
339
+ if (supportsAdopted) {
340
+ try {
341
+ adoptedSheet = new win.CSSStyleSheet()
342
+ adoptedSheet.replaceSync(STYLE_TEXT)
343
+ doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, adoptedSheet]
344
+ } catch {
345
+ adoptedSheet = null
346
+ }
347
+ }
348
+ let styleAlive = () => doc.contains(style) && style.sheet !== null && style.sheet.cssRules.length > 0
349
+ let ensureStyleAlive = () => {
350
+ if (styleAlive()) return
351
+ const fresh = text(doc, 'style', '', STYLE_TEXT)
352
+ if (doc.contains(style)) style.replaceWith(fresh)
353
+ else container.prepend(fresh)
354
+ style = fresh
355
+ }
328
356
  // Details and collapsed-rail summaries open in a viewport-level panel.
329
357
  const pop = doc.createElement('div')
330
358
  pop.className = 'dqw-pop'
@@ -620,6 +648,7 @@ export function mountQuotaCard({
620
648
  }
621
649
 
622
650
  const renderAll = () => {
651
+ ensureStyleAlive()
623
652
  const providers = snapshot?.providers ?? []
624
653
  const glm = providers.find((provider) => provider?.key === 'glm')
625
654
  const copilot = providers.find((provider) => provider?.key === 'copilot')
@@ -806,6 +835,9 @@ export function mountQuotaCard({
806
835
  pop.removeEventListener('click', onPopClick)
807
836
  container.remove()
808
837
  pop.remove()
838
+ if (adoptedSheet !== null && Array.isArray(doc.adoptedStyleSheets)) {
839
+ doc.adoptedStyleSheets = doc.adoptedStyleSheets.filter((sheet) => sheet !== adoptedSheet)
840
+ }
809
841
  }
810
842
  }
811
843