@symbo.ls/connect 3.2.7
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/build.js +205 -0
- package/dist/assets/1024x1024.png +0 -0
- package/dist/assets/128x128.png +0 -0
- package/dist/assets/144x144.png +0 -0
- package/dist/assets/192x192.png +0 -0
- package/dist/assets/48x48.png +0 -0
- package/dist/assets/512x512.png +0 -0
- package/dist/assets/72x72.png +0 -0
- package/dist/assets/96x96.png +0 -0
- package/dist/assets/active_cursor.png +0 -0
- package/dist/assets/favicon.svg +6 -0
- package/dist/assets/old/144x144.png +0 -0
- package/dist/assets/old/192x192.png +0 -0
- package/dist/assets/old/48x48.png +0 -0
- package/dist/assets/old/48x48_faint.png +0 -0
- package/dist/assets/old/512x512.png +0 -0
- package/dist/assets/old/72x72.png +0 -0
- package/dist/assets/old/96x96.png +0 -0
- package/dist/auth.js +373 -0
- package/dist/content.css +46 -0
- package/dist/content.js +1171 -0
- package/dist/content.js.map +7 -0
- package/dist/devtools.html +7 -0
- package/dist/devtools.js +5 -0
- package/dist/manifest.json +87 -0
- package/dist/page-agent.js +727 -0
- package/dist/panel.css +2239 -0
- package/dist/panel.html +235 -0
- package/dist/panel.js +4973 -0
- package/dist/picker.html +111 -0
- package/dist/picker.js +300 -0
- package/dist/service_worker.js +219 -0
- package/dist/service_worker.js.map +7 -0
- package/dist/settings.css +128 -0
- package/dist/settings.html +26 -0
- package/dist/settings_ui.js +57 -0
- package/dist/settings_ui.js.map +7 -0
- package/package.json +20 -0
- package/src/content.js +104 -0
- package/src/grabber/clean.js +605 -0
- package/src/grabber/computed.js +78 -0
- package/src/grabber/parse.js +268 -0
- package/src/grabber/stylesheets.js +117 -0
- package/src/grabber/utils.js +238 -0
- package/src/service_worker.js +246 -0
- package/src/settings/settings_ui.js +52 -0
- package/src/settings/settings_utils.js +70 -0
- package/static/assets/1024x1024.png +0 -0
- package/static/assets/128x128.png +0 -0
- package/static/assets/144x144.png +0 -0
- package/static/assets/192x192.png +0 -0
- package/static/assets/48x48.png +0 -0
- package/static/assets/512x512.png +0 -0
- package/static/assets/72x72.png +0 -0
- package/static/assets/96x96.png +0 -0
- package/static/assets/active_cursor.png +0 -0
- package/static/assets/favicon.svg +6 -0
- package/static/assets/old/144x144.png +0 -0
- package/static/assets/old/192x192.png +0 -0
- package/static/assets/old/48x48.png +0 -0
- package/static/assets/old/48x48_faint.png +0 -0
- package/static/assets/old/512x512.png +0 -0
- package/static/assets/old/72x72.png +0 -0
- package/static/assets/old/96x96.png +0 -0
- package/static/auth.js +373 -0
- package/static/content.css +46 -0
- package/static/devtools.html +7 -0
- package/static/devtools.js +5 -0
- package/static/manifest.json +56 -0
- package/static/page-agent.js +727 -0
- package/static/panel.css +2239 -0
- package/static/panel.html +235 -0
- package/static/panel.js +4973 -0
- package/static/picker.html +111 -0
- package/static/picker.js +300 -0
- package/static/settings.css +128 -0
- package/static/settings.html +26 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
* {
|
|
2
|
+
margin: 0;
|
|
3
|
+
padding: 0;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
--bg: #141416;
|
|
9
|
+
--bg-alt: #242428;
|
|
10
|
+
--bg-hover: #34343a;
|
|
11
|
+
--border: #34343a;
|
|
12
|
+
--text: #bcbcc2;
|
|
13
|
+
--text-dim: #65656f;
|
|
14
|
+
--text-bright: #e0e0e2;
|
|
15
|
+
--accent: #0085FF;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
body {
|
|
19
|
+
background: var(--bg);
|
|
20
|
+
color: var(--text);
|
|
21
|
+
font-family: 'DmSansVariable', 'Helvetica Neue', 'Helvetica', system-ui, sans-serif;
|
|
22
|
+
font-size: 14px;
|
|
23
|
+
line-height: 1.5;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.main-container {
|
|
27
|
+
margin: 0 auto;
|
|
28
|
+
max-width: 700px;
|
|
29
|
+
padding: 40px 24px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
header {
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
gap: 12px;
|
|
36
|
+
margin-bottom: 8px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.logo {
|
|
40
|
+
width: 32px;
|
|
41
|
+
height: 32px;
|
|
42
|
+
fill: var(--accent);
|
|
43
|
+
flex-shrink: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
h1 {
|
|
47
|
+
font-size: 20px;
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
color: var(--text-bright);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
section p {
|
|
53
|
+
color: var(--text-dim);
|
|
54
|
+
font-size: 13px;
|
|
55
|
+
margin-bottom: 24px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.separator {
|
|
59
|
+
margin: 0 0 24px;
|
|
60
|
+
width: 100%;
|
|
61
|
+
height: 1px;
|
|
62
|
+
background: var(--border);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
#settings-container {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
gap: 12px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.setting {
|
|
72
|
+
position: relative;
|
|
73
|
+
background: var(--bg-alt);
|
|
74
|
+
border: 1px solid var(--border);
|
|
75
|
+
border-radius: 10px;
|
|
76
|
+
transition: border-color 0.15s;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.setting:hover {
|
|
80
|
+
border-color: var(--accent);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.setting label {
|
|
84
|
+
color: var(--text-bright);
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
justify-content: space-between;
|
|
89
|
+
font-size: 14px;
|
|
90
|
+
line-height: 1;
|
|
91
|
+
padding: 16px 20px;
|
|
92
|
+
border-radius: 10px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.setting input[type='checkbox'] {
|
|
96
|
+
appearance: none;
|
|
97
|
+
-webkit-appearance: none;
|
|
98
|
+
width: 40px;
|
|
99
|
+
height: 22px;
|
|
100
|
+
background: var(--bg-hover);
|
|
101
|
+
border-radius: 11px;
|
|
102
|
+
position: relative;
|
|
103
|
+
cursor: pointer;
|
|
104
|
+
flex-shrink: 0;
|
|
105
|
+
margin: 0;
|
|
106
|
+
transition: background 0.2s;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.setting input[type='checkbox']::after {
|
|
110
|
+
content: '';
|
|
111
|
+
position: absolute;
|
|
112
|
+
top: 3px;
|
|
113
|
+
left: 3px;
|
|
114
|
+
width: 16px;
|
|
115
|
+
height: 16px;
|
|
116
|
+
background: var(--text-dim);
|
|
117
|
+
border-radius: 50%;
|
|
118
|
+
transition: transform 0.2s, background 0.2s;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.setting input[type='checkbox']:checked {
|
|
122
|
+
background: var(--accent);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.setting input[type='checkbox']:checked::after {
|
|
126
|
+
transform: translateX(18px);
|
|
127
|
+
background: #fff;
|
|
128
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Symbols Connect — Settings</title>
|
|
7
|
+
<link rel="icon" href="assets/favicon.svg" />
|
|
8
|
+
<link rel="stylesheet" href="settings.css" />
|
|
9
|
+
<script type="module" src="settings_ui.js" defer></script>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div class="main-container">
|
|
13
|
+
<header>
|
|
14
|
+
<svg class="logo" viewBox="0 0 24 24"><path d="M13.843 2.7C19.063 2.7 23 6.366 23 11.228c0 3.754-2.862 6.584-6.658 6.584-3.287 0-5.007-2.318-5.007-4.609 0-2.395 1.923-4.344 4.287-4.344.566 0 1.023.12 1.309.223a.212.212 0 01.137.229l-.016.058-.514 1.18a.223.223 0 01-.245.13 2.965 2.965 0 00-.506-.046c-1.245 0-2.258 1.027-2.258 2.288 0 1.33 1.165 2.373 2.651 2.373 2.195 0 3.913-1.777 3.913-4.046 0-3.024-2.294-5.135-5.58-5.135-4.076 0-7.393 3.36-7.393 7.491a7.519 7.519 0 002.871 5.924l-4.96 3.18A12.042 12.042 0 012 14.7c0-6.617 5.313-12 11.843-12z" fill-rule="evenodd"/></svg>
|
|
15
|
+
<h1>Symbols Connect — Settings</h1>
|
|
16
|
+
</header>
|
|
17
|
+
<main>
|
|
18
|
+
<section>
|
|
19
|
+
<p>Adjust preferences for the Symbols extension. Changes take effect immediately.</p>
|
|
20
|
+
<div class="separator"></div>
|
|
21
|
+
<div id="settings-container"></div>
|
|
22
|
+
</section>
|
|
23
|
+
</main>
|
|
24
|
+
</div>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// src/settings/settings_utils.js
|
|
2
|
+
var storageKey = "settings";
|
|
3
|
+
var settingsDefinitions = [
|
|
4
|
+
{
|
|
5
|
+
key: "useStylesheets",
|
|
6
|
+
name: "Use Stylesheets",
|
|
7
|
+
type: "checkbox",
|
|
8
|
+
default: true
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
key: "useComputed",
|
|
12
|
+
name: "Use Computed",
|
|
13
|
+
type: "checkbox",
|
|
14
|
+
default: false
|
|
15
|
+
}
|
|
16
|
+
];
|
|
17
|
+
var getSettings = async () => (await chrome.storage.local.get(storageKey)).settings;
|
|
18
|
+
async function updateSettings(updates) {
|
|
19
|
+
const cur = await getSettings();
|
|
20
|
+
chrome.storage.local.set({ [storageKey]: { ...cur, ...updates } }).catch((reason) => console.error(`failed to update settings : ${reason}`));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/settings/settings_ui.js
|
|
24
|
+
var container = document.getElementById("settings-container");
|
|
25
|
+
var curSettings = await getSettings();
|
|
26
|
+
settingsDefinitions.forEach(({ key, name, type, default: defValue }) => {
|
|
27
|
+
const input = document.createElement("input");
|
|
28
|
+
input.id = key;
|
|
29
|
+
input.type = type;
|
|
30
|
+
if (!(key in curSettings)) {
|
|
31
|
+
console.error(`Setting ${key} missing value`, curSettings);
|
|
32
|
+
}
|
|
33
|
+
const value = curSettings[key] ?? defValue ?? null;
|
|
34
|
+
if ((defValue ?? null) !== null) {
|
|
35
|
+
input.defaultValue = defValue;
|
|
36
|
+
}
|
|
37
|
+
if ((value ?? null) !== null) {
|
|
38
|
+
if (type === "checkbox") {
|
|
39
|
+
input.checked = value;
|
|
40
|
+
} else {
|
|
41
|
+
input.value = value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const label = document.createElement("label");
|
|
45
|
+
label.htmlFor = key;
|
|
46
|
+
label.textContent = name;
|
|
47
|
+
const wrapper = document.createElement("div");
|
|
48
|
+
wrapper.classList.add("setting");
|
|
49
|
+
wrapper.append(label);
|
|
50
|
+
wrapper.append(input);
|
|
51
|
+
container.append(wrapper);
|
|
52
|
+
input.addEventListener("change", (event) => {
|
|
53
|
+
const val = type === "checkbox" ? event.target.checked : event.target.value;
|
|
54
|
+
updateSettings({ [key]: val });
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=settings_ui.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/settings/settings_utils.js", "../src/settings/settings_ui.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * @typedef {Object} Settings\n * @property {boolean} useComputed\n * @property {boolean} useStylesheets\n */\n\nconst storageKey = 'settings'\n\n/**\n * @typedef {Object} SettingDefinition\n * @property {string} type\n * @property {String} name\n * @property {string} [key]\n * @property {any} [default]\n * @property {value} [any]\n */\n\n/**\n * @type {SettingDefinition[]}\n */\nexport const settingsDefinitions = [\n {\n key: 'useStylesheets',\n name: 'Use Stylesheets',\n type: 'checkbox',\n default: true\n },\n {\n key: 'useComputed',\n name: 'Use Computed',\n type: 'checkbox',\n default: false\n }\n]\n\n/**\n * @returns {Promise<Settings>}\n */\nexport const getSettings = async () =>\n (await chrome.storage.local.get(storageKey)).settings\n\n/**\n * @param {Partial<Settings>} updates\n */\nexport async function updateSettings(updates) {\n const cur = await getSettings()\n chrome.storage.local\n .set({ [storageKey]: { ...cur, ...updates } })\n .catch((reason) => console.error(`failed to update settings : ${reason}`))\n}\n\nexport async function initSettings() {\n const curSettings = (await getSettings()) ?? {}\n\n // construct default settings from definitions\n const defaultSettings = {}\n settingsDefinitions.forEach(({ key, default: defValue }) => {\n defaultSettings[key] = defValue\n })\n\n // override defaults with any existing settings\n Object.keys(curSettings).forEach((key) => {\n // only include settings within the current defined set\n if (key in defaultSettings) {\n defaultSettings[key] = curSettings[key]\n }\n })\n\n updateSettings(defaultSettings)\n}\n", "import {\n getSettings,\n updateSettings,\n settingsDefinitions\n} from './settings_utils'\n\nconst container = document.getElementById('settings-container')\n\nconst curSettings = await getSettings()\n\n// Build settings UI from definitions\nsettingsDefinitions.forEach(({ key, name, type, default: defValue }) => {\n const input = document.createElement('input')\n input.id = key\n input.type = type\n\n if (!(key in curSettings)) {\n console.error(`Setting ${key} missing value`, curSettings)\n }\n\n const value = curSettings[key] ?? defValue ?? null\n\n if ((defValue ?? null) !== null) {\n input.defaultValue = defValue\n }\n\n if ((value ?? null) !== null) {\n if (type === 'checkbox') {\n input.checked = value\n } else {\n input.value = value\n }\n }\n\n const label = document.createElement('label')\n label.htmlFor = key\n label.textContent = name\n\n const wrapper = document.createElement('div')\n wrapper.classList.add('setting')\n\n wrapper.append(label)\n wrapper.append(input)\n\n container.append(wrapper)\n\n input.addEventListener('change', (event) => {\n const val = type === 'checkbox' ? event.target.checked : event.target.value\n\n updateSettings({ [key]: val })\n })\n})\n"],
|
|
5
|
+
"mappings": ";AAMA,IAAM,aAAa;AAcZ,IAAM,sBAAsB;AAAA,EACjC;AAAA,IACE,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AACF;AAKO,IAAM,cAAc,aACxB,MAAM,OAAO,QAAQ,MAAM,IAAI,UAAU,GAAG;AAK/C,eAAsB,eAAe,SAAS;AAC5C,QAAM,MAAM,MAAM,YAAY;AAC9B,SAAO,QAAQ,MACZ,IAAI,EAAE,CAAC,UAAU,GAAG,EAAE,GAAG,KAAK,GAAG,QAAQ,EAAE,CAAC,EAC5C,MAAM,CAAC,WAAW,QAAQ,MAAM,+BAA+B,MAAM,EAAE,CAAC;AAC7E;;;AC3CA,IAAM,YAAY,SAAS,eAAe,oBAAoB;AAE9D,IAAM,cAAc,MAAM,YAAY;AAGtC,oBAAoB,QAAQ,CAAC,EAAE,KAAK,MAAM,MAAM,SAAS,SAAS,MAAM;AACtE,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,KAAK;AACX,QAAM,OAAO;AAEb,MAAI,EAAE,OAAO,cAAc;AACzB,YAAQ,MAAM,WAAW,GAAG,kBAAkB,WAAW;AAAA,EAC3D;AAEA,QAAM,QAAQ,YAAY,GAAG,KAAK,YAAY;AAE9C,OAAK,YAAY,UAAU,MAAM;AAC/B,UAAM,eAAe;AAAA,EACvB;AAEA,OAAK,SAAS,UAAU,MAAM;AAC5B,QAAI,SAAS,YAAY;AACvB,YAAM,UAAU;AAAA,IAClB,OAAO;AACL,YAAM,QAAQ;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,UAAU;AAChB,QAAM,cAAc;AAEpB,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,UAAU,IAAI,SAAS;AAE/B,UAAQ,OAAO,KAAK;AACpB,UAAQ,OAAO,KAAK;AAEpB,YAAU,OAAO,OAAO;AAExB,QAAM,iBAAiB,UAAU,CAAC,UAAU;AAC1C,UAAM,MAAM,SAAS,aAAa,MAAM,OAAO,UAAU,MAAM,OAAO;AAEtE,mBAAe,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC;AAAA,EAC/B,CAAC;AACH,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@symbo.ls/connect",
|
|
3
|
+
"version": "3.2.7",
|
|
4
|
+
"description": "Symbols Connect — Chrome extension for DOMQL inspection and element grabbing",
|
|
5
|
+
"main": "dist/content.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "node ./build.js",
|
|
8
|
+
"build:watch": "node ./build.js --watch",
|
|
9
|
+
"build:local": "node ./build.js --local",
|
|
10
|
+
"build:watch:local": "node ./build.js --watch --local",
|
|
11
|
+
"build:prod": "node ./build.js --prod"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"esbuild": "^0.25.0",
|
|
15
|
+
"chokidar": "^3.5.3"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@domql/utils": "^2.29.81"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/content.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { parseElement } from './grabber/parse'
|
|
2
|
+
|
|
3
|
+
// ============================================================
|
|
4
|
+
// DOMQL Inspector: inject page-agent for DevTools panel access
|
|
5
|
+
// ============================================================
|
|
6
|
+
function injectPageAgent () {
|
|
7
|
+
const script = document.createElement('script')
|
|
8
|
+
script.src = chrome.runtime.getURL('page-agent.js')
|
|
9
|
+
script.onload = () => script.remove()
|
|
10
|
+
;(document.head || document.documentElement).appendChild(script)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
injectPageAgent()
|
|
14
|
+
|
|
15
|
+
// ============================================================
|
|
16
|
+
// Symbols Grabber: click-to-capture element mode
|
|
17
|
+
// ============================================================
|
|
18
|
+
async function addToLibrary (node) {
|
|
19
|
+
const rootStyles = window.getComputedStyle(document.documentElement)
|
|
20
|
+
const obj = await parseElement(node, rootStyles)
|
|
21
|
+
|
|
22
|
+
const store = { domqlStr: JSON.stringify(obj) }
|
|
23
|
+
console.log('%c[Symbols] saving domql', 'color: green', store)
|
|
24
|
+
|
|
25
|
+
chrome.storage.local.set(store)
|
|
26
|
+
chrome.runtime.sendMessage({ type: 'open_platform' })
|
|
27
|
+
|
|
28
|
+
return obj
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const focusNodeClass = 'symbols-grabber-hovered'
|
|
32
|
+
let isListenerActive = false
|
|
33
|
+
let focusedNode = null
|
|
34
|
+
|
|
35
|
+
document.body.addEventListener(
|
|
36
|
+
'mouseover',
|
|
37
|
+
(event) => {
|
|
38
|
+
const { target } = event
|
|
39
|
+
if (target && isListenerActive) {
|
|
40
|
+
if (focusedNode && focusedNode !== target) {
|
|
41
|
+
focusedNode.classList.remove(focusNodeClass)
|
|
42
|
+
}
|
|
43
|
+
focusedNode = target
|
|
44
|
+
focusedNode.classList.add(focusNodeClass)
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
true
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
chrome.runtime.onMessage.addListener((msg, sender, respond) => {
|
|
51
|
+
if (sender.id === chrome.runtime.id) {
|
|
52
|
+
const { type, state } = msg
|
|
53
|
+
|
|
54
|
+
if (type === 'toggle' && typeof state === 'number') {
|
|
55
|
+
console.log(
|
|
56
|
+
`%c[Symbols] grabber ${state ? 'enabled' : 'disabled'}`,
|
|
57
|
+
`color: ${state ? 'green' : 'red'}`
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
isListenerActive = Boolean(state)
|
|
61
|
+
document.body.classList.toggle('symbols-grabber-active', isListenerActive)
|
|
62
|
+
|
|
63
|
+
if (!state) {
|
|
64
|
+
document.querySelectorAll(`.${focusNodeClass}`).forEach((el) => {
|
|
65
|
+
el.classList.remove(focusNodeClass)
|
|
66
|
+
})
|
|
67
|
+
focusedNode = null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
document.body.addEventListener(
|
|
71
|
+
'click',
|
|
72
|
+
(event) => {
|
|
73
|
+
const { target } = event
|
|
74
|
+
if (target && isListenerActive) {
|
|
75
|
+
event.preventDefault()
|
|
76
|
+
event.stopImmediatePropagation()
|
|
77
|
+
|
|
78
|
+
if (target.classList.contains(focusNodeClass)) {
|
|
79
|
+
target.classList.remove(focusNodeClass)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
addToLibrary(target).then(
|
|
83
|
+
(domql) => {
|
|
84
|
+
target.classList.add(focusNodeClass)
|
|
85
|
+
respond({ success: true, domql })
|
|
86
|
+
},
|
|
87
|
+
(error) => {
|
|
88
|
+
console.error('[Symbols] error adding to library', error)
|
|
89
|
+
respond({ success: false, error: error.message || error })
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
isListenerActive = false
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
{ capture: true, once: true }
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return true
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
console.log('[Symbols] Content script loaded (inspector + grabber)')
|