figranium 0.9.2 → 0.9.6

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.
@@ -1,197 +1,204 @@
1
- const { JSDOM } = require('jsdom');
2
- const vm = require('vm');
3
-
4
- // Safe Proxy Implementation
5
- const proxyMap = new WeakMap();
6
- const targetMap = new WeakMap();
7
-
8
- const unwrap = (obj) => {
9
- return proxyMap.get(obj) || obj;
10
- };
11
-
12
- const createSafeProxy = (target) => {
13
- if (target === null || (typeof target !== 'object' && typeof target !== 'function')) {
14
- return target;
15
- }
16
- if (targetMap.has(target)) {
17
- return targetMap.get(target);
18
- }
19
-
20
- const proxy = new Proxy(target, {
21
- get: (obj, prop) => {
22
- if (prop === 'constructor' || prop === '__proto__') {
23
- return undefined;
24
- }
25
- const value = obj[prop];
26
- return createSafeProxy(value);
27
- },
28
- apply: (target, thisArg, args) => {
29
- const unproxiedArgs = args.map(arg => {
30
- const raw = unwrap(arg);
31
- if (typeof raw === 'function') {
32
- return function (...hostArgs) {
33
- const proxiedCbArgs = hostArgs.map(hostArg => createSafeProxy(hostArg));
34
- const proxiedThis = createSafeProxy(this);
35
- return raw.apply(proxiedThis, proxiedCbArgs);
36
- };
37
- }
38
- return raw;
39
- });
40
- const result = target.apply(unwrap(thisArg), unproxiedArgs);
41
- return createSafeProxy(result);
42
- },
43
- construct: (target, args) => {
44
- const unproxiedArgs = args.map(arg => {
45
- const raw = unwrap(arg);
46
- if (typeof raw === 'function') {
47
- return function (...hostArgs) {
48
- const proxiedCbArgs = hostArgs.map(hostArg => createSafeProxy(hostArg));
49
- const proxiedThis = createSafeProxy(this);
50
- return raw.apply(proxiedThis, proxiedCbArgs);
51
- };
52
- }
53
- return raw;
54
- });
55
- const result = new target(...unproxiedArgs);
56
- return createSafeProxy(result);
57
- },
58
- has: (target, prop) => {
59
- if (prop === 'constructor' || prop === '__proto__') return false;
60
- return prop in target;
61
- },
62
- getOwnPropertyDescriptor: (target, prop) => {
63
- if (prop === 'constructor' || prop === '__proto__') {
64
- return undefined;
65
- }
66
- const descriptor = Object.getOwnPropertyDescriptor(target, prop);
67
- if (!descriptor) return undefined;
68
-
69
- if (descriptor.configurable === false && 'value' in descriptor && typeof descriptor.value === 'object') {
70
- return descriptor;
71
- }
72
-
73
- if (descriptor.value) {
74
- descriptor.value = createSafeProxy(descriptor.value);
75
- }
76
- if (descriptor.get) {
77
- descriptor.get = createSafeProxy(descriptor.get);
78
- }
79
- if (descriptor.set) {
80
- descriptor.set = createSafeProxy(descriptor.set);
81
- }
82
- return descriptor;
83
- },
84
- getPrototypeOf: (target) => {
85
- return createSafeProxy(Object.getPrototypeOf(target));
86
- }
87
- });
88
-
89
- targetMap.set(target, proxy);
90
- proxyMap.set(proxy, target);
91
- return proxy;
92
- };
93
-
94
- const runExtraction = async (data) => {
95
- const { script, html, url, includeShadowDom } = data;
96
- if (!script || typeof script !== 'string') return { result: undefined, logs: [] };
97
-
98
- try {
99
- const dom = new JSDOM(html || '');
100
- const { window } = dom;
101
- const logBuffer = [];
102
- const consoleProxy = {
103
- log: (...args) => logBuffer.push(args.join(' ')),
104
- warn: (...args) => logBuffer.push(args.join(' ')),
105
- error: (...args) => logBuffer.push(args.join(' '))
106
- };
107
-
108
- const shadowHelpers = (() => {
109
- const shadowQueryAll = (selector, root = window.document) => {
110
- const results = [];
111
- const walk = (node) => {
112
- if (!node) return;
113
- if (node.nodeType === 1) {
114
- const el = node;
115
- if (selector && el.matches && el.matches(selector)) results.push(el);
116
- if (el.tagName === 'TEMPLATE' && el.hasAttribute('data-shadowroot')) {
117
- walk(el.content);
118
- }
119
- } else if (node.nodeType === 11) {
120
- // DocumentFragment
121
- }
122
- if (node.childNodes) {
123
- node.childNodes.forEach((child) => walk(child));
124
- }
125
- };
126
- walk(root);
127
- return results;
128
- };
129
-
130
- const shadowText = (root = window.document) => {
131
- const texts = [];
132
- const walk = (node) => {
133
- if (!node) return;
134
- if (node.nodeType === 3) {
135
- const text = node.nodeValue ? node.nodeValue.trim() : '';
136
- if (text) texts.push(text);
137
- return;
138
- }
139
- if (node.nodeType === 1) {
140
- const el = node;
141
- if (el.tagName === 'TEMPLATE' && el.hasAttribute('data-shadowroot')) {
142
- walk(el.content);
143
- }
144
- }
145
- if (node.childNodes) {
146
- node.childNodes.forEach((child) => walk(child));
147
- }
148
- };
149
- walk(root);
150
- return texts;
151
- };
152
-
153
- return { shadowQueryAll, shadowText };
154
- })();
155
-
156
- const sandbox = Object.create(null);
157
- Object.assign(sandbox, {
158
- $$data: createSafeProxy({
159
- html: () => html || '',
160
- url: () => url || '',
161
- window,
162
- document: window.document,
163
- shadowQueryAll: includeShadowDom ? shadowHelpers.shadowQueryAll : undefined,
164
- shadowText: includeShadowDom ? shadowHelpers.shadowText : undefined
165
- }),
166
- window: createSafeProxy(window),
167
- document: createSafeProxy(window.document),
168
- DOMParser: createSafeProxy(window.DOMParser),
169
- console: createSafeProxy(consoleProxy)
170
- });
171
-
172
- const context = vm.createContext(sandbox);
173
- const code = `"use strict"; (async () => { ${script}\n})();`;
174
-
175
- const scriptObj = new vm.Script(code);
176
- const result = await scriptObj.runInContext(context, { timeout: 1000 });
177
-
178
- return { result, logs: logBuffer };
179
- } catch (e) {
180
- return { result: `Extraction script error: ${e.message}`, logs: [] };
181
- }
182
- };
183
-
184
- let inputData = '';
185
- process.stdin.setEncoding('utf8');
186
- process.stdin.on('data', (chunk) => {
187
- inputData += chunk;
188
- });
189
- process.stdin.on('end', async () => {
190
- try {
191
- const data = JSON.parse(inputData);
192
- const output = await runExtraction(data);
193
- console.log(JSON.stringify(output));
194
- } catch (e) {
195
- console.log(JSON.stringify({ result: `Worker error: ${e.message}`, logs: [] }));
196
- }
197
- });
1
+ const { JSDOM } = require('jsdom');
2
+ const vm = require('vm');
3
+
4
+ // Safe Proxy Implementation
5
+ const proxyMap = new WeakMap();
6
+ const targetMap = new WeakMap();
7
+
8
+ const unwrap = (obj) => {
9
+ return proxyMap.get(obj) || obj;
10
+ };
11
+
12
+ const createSafeProxy = (target) => {
13
+ if (target === null || (typeof target !== 'object' && typeof target !== 'function')) {
14
+ return target;
15
+ }
16
+ if (targetMap.has(target)) {
17
+ return targetMap.get(target);
18
+ }
19
+
20
+ const proxy = new Proxy(target, {
21
+ get: (obj, prop) => {
22
+ if (prop === 'constructor' || prop === '__proto__') {
23
+ return undefined;
24
+ }
25
+ const value = obj[prop];
26
+ return createSafeProxy(value);
27
+ },
28
+ apply: (target, thisArg, args) => {
29
+ const unproxiedArgs = args.map(arg => {
30
+ const raw = unwrap(arg);
31
+ if (typeof raw === 'function') {
32
+ return function (...hostArgs) {
33
+ const proxiedCbArgs = hostArgs.map(hostArg => createSafeProxy(hostArg));
34
+ const proxiedThis = createSafeProxy(this);
35
+ return raw.apply(proxiedThis, proxiedCbArgs);
36
+ };
37
+ }
38
+ return raw;
39
+ });
40
+ const result = target.apply(unwrap(thisArg), unproxiedArgs);
41
+ return createSafeProxy(result);
42
+ },
43
+ construct: (target, args) => {
44
+ const unproxiedArgs = args.map(arg => {
45
+ const raw = unwrap(arg);
46
+ if (typeof raw === 'function') {
47
+ return function (...hostArgs) {
48
+ const proxiedCbArgs = hostArgs.map(hostArg => createSafeProxy(hostArg));
49
+ const proxiedThis = createSafeProxy(this);
50
+ return raw.apply(proxiedThis, proxiedCbArgs);
51
+ };
52
+ }
53
+ return raw;
54
+ });
55
+ const result = new target(...unproxiedArgs);
56
+ return createSafeProxy(result);
57
+ },
58
+ has: (target, prop) => {
59
+ if (prop === 'constructor' || prop === '__proto__') return false;
60
+ return prop in target;
61
+ },
62
+ getOwnPropertyDescriptor: (target, prop) => {
63
+ if (prop === 'constructor' || prop === '__proto__') {
64
+ return undefined;
65
+ }
66
+ const descriptor = Object.getOwnPropertyDescriptor(target, prop);
67
+ if (!descriptor) return undefined;
68
+
69
+ if (descriptor.configurable === false && 'value' in descriptor && typeof descriptor.value === 'object') {
70
+ return descriptor;
71
+ }
72
+
73
+ if (descriptor.value) {
74
+ descriptor.value = createSafeProxy(descriptor.value);
75
+ }
76
+ if (descriptor.get) {
77
+ descriptor.get = createSafeProxy(descriptor.get);
78
+ }
79
+ if (descriptor.set) {
80
+ descriptor.set = createSafeProxy(descriptor.set);
81
+ }
82
+ return descriptor;
83
+ },
84
+ getPrototypeOf: (target) => {
85
+ return createSafeProxy(Object.getPrototypeOf(target));
86
+ }
87
+ });
88
+
89
+ targetMap.set(target, proxy);
90
+ proxyMap.set(proxy, target);
91
+ return proxy;
92
+ };
93
+
94
+ const runExtraction = async (data) => {
95
+ const { script, html, url, includeShadowDom } = data;
96
+ if (!script || typeof script !== 'string') return { result: undefined, logs: [] };
97
+
98
+ try {
99
+ const dom = new JSDOM(html || '');
100
+ const { window } = dom;
101
+ const logBuffer = [];
102
+ const consoleProxy = {
103
+ log: (...args) => logBuffer.push(args.join(' ')),
104
+ warn: (...args) => logBuffer.push(args.join(' ')),
105
+ error: (...args) => logBuffer.push(args.join(' '))
106
+ };
107
+
108
+ const shadowHelpers = (() => {
109
+ const shadowQueryAll = (selector, root = window.document) => {
110
+ const results = [];
111
+ const walk = (node) => {
112
+ if (!node) return;
113
+ if (node.nodeType === 1) {
114
+ const el = node;
115
+ if (selector && el.matches && el.matches(selector)) results.push(el);
116
+ if (el.tagName === 'TEMPLATE' && el.hasAttribute('data-shadowroot')) {
117
+ walk(el.content);
118
+ }
119
+ } else if (node.nodeType === 11) {
120
+ // DocumentFragment
121
+ }
122
+ if (node.childNodes) {
123
+ node.childNodes.forEach((child) => walk(child));
124
+ }
125
+ };
126
+ walk(root);
127
+ return results;
128
+ };
129
+
130
+ const shadowText = (root = window.document) => {
131
+ const texts = [];
132
+ const walk = (node) => {
133
+ if (!node) return;
134
+ if (node.nodeType === 3) {
135
+ const text = node.nodeValue ? node.nodeValue.trim() : '';
136
+ if (text) texts.push(text);
137
+ return;
138
+ }
139
+ if (node.nodeType === 1) {
140
+ const el = node;
141
+ if (el.tagName === 'TEMPLATE' && el.hasAttribute('data-shadowroot')) {
142
+ walk(el.content);
143
+ }
144
+ }
145
+ if (node.childNodes) {
146
+ node.childNodes.forEach((child) => walk(child));
147
+ }
148
+ };
149
+ walk(root);
150
+ return texts;
151
+ };
152
+
153
+ return { shadowQueryAll, shadowText };
154
+ })();
155
+
156
+ const sandbox = Object.create(null);
157
+ Object.assign(sandbox, {
158
+ $$data: createSafeProxy({
159
+ html: () => html || '',
160
+ url: () => url || '',
161
+ window,
162
+ document: window.document,
163
+ shadowQueryAll: includeShadowDom ? shadowHelpers.shadowQueryAll : undefined,
164
+ shadowText: includeShadowDom ? shadowHelpers.shadowText : undefined
165
+ }),
166
+ window: createSafeProxy(window),
167
+ document: createSafeProxy(window.document),
168
+ DOMParser: createSafeProxy(window.DOMParser),
169
+ console: createSafeProxy(consoleProxy)
170
+ });
171
+
172
+ sandbox.$$userScript = script;
173
+ const context = vm.createContext(sandbox);
174
+ const scriptCode = `
175
+ "use strict";
176
+ (async () => {
177
+ const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
178
+ const fn = new AsyncFunction('$$data', 'window', 'document', 'DOMParser', 'console', $$userScript);
179
+ return fn($$data, window, document, DOMParser, console);
180
+ })();
181
+ `;
182
+
183
+ const result = await vm.runInContext(scriptCode, context, { timeout: 1000 });
184
+
185
+ return { result, logs: logBuffer };
186
+ } catch (e) {
187
+ return { result: `Extraction script error: ${e.message}`, logs: [] };
188
+ }
189
+ };
190
+
191
+ let inputData = '';
192
+ process.stdin.setEncoding('utf8');
193
+ process.stdin.on('data', (chunk) => {
194
+ inputData += chunk;
195
+ });
196
+ process.stdin.on('end', async () => {
197
+ try {
198
+ const data = JSON.parse(inputData);
199
+ const output = await runExtraction(data);
200
+ console.log(JSON.stringify(output));
201
+ } catch (e) {
202
+ console.log(JSON.stringify({ result: `Worker error: ${e.message}`, logs: [] }));
203
+ }
204
+ });