Web Editor
A collection of 2 actions bundled together.

Code Snippet

1// ==========================================
2// ACTION GROUP (2 Actions)
3// ==========================================
4
5// ------------------------------------------
6// Action: Web Editor/Editor
7// Description: The UI for web editor
8// ------------------------------------------
9
10const currentTab = await browser.tabs.getCurrent();
11let domain = new URL(currentTab.url).hostname;
12const parts = domain.split('.');
13if (parts.length > 2) {
14    if (parts[parts.length-2].length <= 3 && parts[parts.length-1].length <= 3) {
15        domain = parts.slice(-3).join('.');
16    } else {
17        domain = parts.slice(-2).join('.');
18    }
19}
20const cssNoteTitle = `tee-css://${domain}`;
21
22const notesList = await notes.list();
23const existingCssNote = notesList.find(n => n.title === cssNoteTitle);
24
25// Handle legacy JSON format if present
26let savedContent = existingCssNote ? existingCssNote.content : "";
27try {
28    const jsonMap = JSON.parse(savedContent);
29    savedContent = `/* Converted from previous format */\n`;
30    for (const [selector, css] of Object.entries(jsonMap)) {
31        savedContent += `${selector} {\n  ${css}\n}\n\n`;
32    }
33} catch(e) {}
34
35const initialCss = savedContent || `/* Custom CSS for ${domain} */\n\n`;
36
37let cssRuleId = null;
38let finalCss = initialCss;
39
40// If we already have saved CSS, preview it immediately so the page reflects the note!
41if (initialCss.trim()) {
42    cssRuleId = await page.injectCSS(initialCss);
43}
44
45await widget.show([
46  { type: "text", text: `🎨 Theme: ${domain}`, size: "lg", weight: "bold" },
47  { type: "textarea", id: "editor-css", value: initialCss, rows: 14, placeholder: "e.g.\n.header { display: none !important; }\nh1 { color: red !important; }" },
48  { type: "button", id: "preview", text: "Preview Changes", variant: "ghost" },
49  { type: "button", id: "save", text: "Save Stylesheet", variant: "primary" }
50], "bottom-right");
51
52while (true) {
53  const ev = await Promise.race([
54    widget.waitForEvent("preview", "click").then(data => ({ action: "preview", data })),
55    widget.waitForEvent("save", "click").then(data => ({ action: "save", data })),
56    widget.waitForEvent("__widget_closed__", "click").then(() => ({ action: "close" }))
57  ]);
58
59  if (ev.action === "close") {
60    if (cssRuleId) await page.removeCSS(cssRuleId);
61    return;
62  }
63
64  // Retrieve whatever the user has typed so far
65  const currentCss = ev.data ? (ev.data["editor-css"] !== undefined ? ev.data["editor-css"] : initialCss) : initialCss;
66  finalCss = currentCss;
67
68  if (ev.action === "preview" || ev.action === "save") {
69      if (cssRuleId) await page.removeCSS(cssRuleId);
70      if (currentCss) {
71        cssRuleId = await page.injectCSS(currentCss);
72      }
73  }
74
75  if (ev.action === "save") break;
76}
77
78await widget.hide();
79await spinner.show("Saving stylesheet...");
80
81if (finalCss.trim()) {
82    if (existingCssNote) await notes.update(existingCssNote.id, { content: finalCss });
83    else await notes.create({ title: cssNoteTitle, content: finalCss, url: currentTab.url });
84} else if (existingCssNote) {
85    // If the user completely wiped the stylesheet, save the empty state
86    await notes.update(existingCssNote.id, { content: "" });
87}
88
89await spinner.hide();
90notify.show(`Saved stylesheet for ${domain}!`, "success");
91
92
93
94// ------------------------------------------
95// Action: Web Editor/Autoloader
96// Description: The autoloader that applies CSS to websites
97// ------------------------------------------
98
99const currentTab = await browser.tabs.getCurrent();
100if (!currentTab || !currentTab.url) return;
101
102let domain = new URL(currentTab.url).hostname;
103const parts = domain.split('.');
104if (parts.length > 2) {
105    if (parts[parts.length-2].length <= 3 && parts[parts.length-1].length <= 3) {
106        domain = parts.slice(-3).join('.');
107    } else {
108        domain = parts.slice(-2).join('.');
109    }
110}
111
112const notesList = await notes.list();
113
114const cssNote = notesList.find(n => n.title === `tee-css://${domain}`);
115if (cssNote && cssNote.content) {
116  let finalCssToInject = cssNote.content;
117  try {
118      const jsonMap = JSON.parse(finalCssToInject);
119      finalCssToInject = "";
120      for (const [selector, css] of Object.entries(jsonMap)) {
121          finalCssToInject += `${selector} { ${css} }\n`;
122      }
123  } catch(e) {}
124  
125  await page.injectCSS(finalCssToInject);
126}
127
Submitted on 7/11/2026