pinokiod 2.15.7 → 2.15.9
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/kernel/api/index.js +21 -10
- package/kernel/bin/index.js +0 -7
- package/kernel/index.js +1 -1
- package/kernel/lproxy.js +76 -0
- package/kernel/shell.js +8 -5
- package/kernel/shells.js +125 -24
- package/kernel/sysinfo.js +5 -8
- package/kernel/util.js +27 -1
- package/package.json +2 -3
- package/server/index.js +84 -5
- package/server/public/mark.min.js +7 -0
- package/server/public/ollama.webp +0 -0
- package/server/public/style.css +45 -0
- package/server/views/browser-experimental.ejs +5 -7
- package/server/views/editor.ejs +29 -3
- package/server/views/fullscreen_editor.ejs +36 -5
- package/server/views/index.ejs +34 -21
- package/server/views/proxy.ejs +357 -0
package/kernel/api/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const path = require('path')
|
|
|
4
4
|
const _ = require('lodash')
|
|
5
5
|
const git = require('isomorphic-git')
|
|
6
6
|
const http = require('isomorphic-git/http/node')
|
|
7
|
-
const Lproxy = require('lproxy')
|
|
7
|
+
const Lproxy = require('../lproxy')
|
|
8
8
|
//const { glob, globSync, globStream, globStreamSync, Glob, } = require('glob')
|
|
9
9
|
const { glob, sync, hasMagic } = require('glob-gitignore')
|
|
10
10
|
const fastq = require('fastq')
|
|
@@ -104,8 +104,6 @@ class Api {
|
|
|
104
104
|
// 1. set the "stop" flag for the uri, so the next execution in the queue for the uri will NOT queue another task
|
|
105
105
|
// 2. stream a message closing the socket
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
109
107
|
let requestPath = this.filePath(req.params.uri)
|
|
110
108
|
|
|
111
109
|
|
|
@@ -715,6 +713,19 @@ class Api {
|
|
|
715
713
|
}
|
|
716
714
|
|
|
717
715
|
|
|
716
|
+
if (result && result.error) {
|
|
717
|
+
this.ondata({
|
|
718
|
+
id: request.path,
|
|
719
|
+
type: "error",
|
|
720
|
+
data: result.response,
|
|
721
|
+
event: result.error,
|
|
722
|
+
rpc,
|
|
723
|
+
rawrpc
|
|
724
|
+
})
|
|
725
|
+
return
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
|
|
718
729
|
|
|
719
730
|
if (result && rpc.returns) {
|
|
720
731
|
// set the scope variable from the return value
|
|
@@ -879,13 +890,13 @@ class Api {
|
|
|
879
890
|
for(let name in this.listeners) {
|
|
880
891
|
this.listeners[name](packet)
|
|
881
892
|
}
|
|
882
|
-
if (packet.type === 'error') {
|
|
883
|
-
this.stop({
|
|
884
|
-
params: {
|
|
885
|
-
uri: packet.id
|
|
886
|
-
}
|
|
887
|
-
})
|
|
888
|
-
}
|
|
893
|
+
// if (packet.type === 'error') {
|
|
894
|
+
// this.stop({
|
|
895
|
+
// params: {
|
|
896
|
+
// uri: packet.id
|
|
897
|
+
// }
|
|
898
|
+
// })
|
|
899
|
+
// }
|
|
889
900
|
}
|
|
890
901
|
listen(name, ondata) {
|
|
891
902
|
this.listeners[name] = ondata
|
package/kernel/bin/index.js
CHANGED
|
@@ -149,9 +149,6 @@ class Bin {
|
|
|
149
149
|
}
|
|
150
150
|
}).filter(x => x)
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
console.log("****** envs", JSON.stringify(envs, null, 2))
|
|
154
|
-
|
|
155
152
|
// 2. Merge module envs
|
|
156
153
|
let e = {}
|
|
157
154
|
for(let env of envs) {
|
|
@@ -175,8 +172,6 @@ class Bin {
|
|
|
175
172
|
return file.endsWith(".js") && file !== "index.js" && file !== "cmake.js"
|
|
176
173
|
})
|
|
177
174
|
|
|
178
|
-
console.log({ modfiles })
|
|
179
|
-
|
|
180
175
|
|
|
181
176
|
this.mods = []
|
|
182
177
|
for(let filename of modfiles) {
|
|
@@ -188,7 +183,6 @@ class Bin {
|
|
|
188
183
|
let name = path.basename(filename, ".js")
|
|
189
184
|
this.mods.push({ name, mod })
|
|
190
185
|
}
|
|
191
|
-
console.log(">> this.mods = ", this.mods)
|
|
192
186
|
// inject kernel
|
|
193
187
|
for(let i=0; i<this.mods.length; i++) {
|
|
194
188
|
this.mods[i].mod.kernel = this.kernel
|
|
@@ -203,7 +197,6 @@ class Bin {
|
|
|
203
197
|
}
|
|
204
198
|
this.mod[mod.name] = mod.mod
|
|
205
199
|
}
|
|
206
|
-
console.log(">> this.mod", this.mod)
|
|
207
200
|
|
|
208
201
|
|
|
209
202
|
|
package/kernel/index.js
CHANGED
package/kernel/lproxy.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*
|
|
2
|
+
const proxy = new Minproxy()
|
|
3
|
+
|
|
4
|
+
// 1. start the proxy for url
|
|
5
|
+
const generated_url = await proxy.start(url)
|
|
6
|
+
|
|
7
|
+
// 2. stop the proxy for url
|
|
8
|
+
proxy.stop(url)
|
|
9
|
+
|
|
10
|
+
// 3. get the proxy url for a given url
|
|
11
|
+
const proxy_url = proxy.url(url)
|
|
12
|
+
|
|
13
|
+
// 4. get all proxies
|
|
14
|
+
const proxies = proxy.all()
|
|
15
|
+
|
|
16
|
+
*/
|
|
17
|
+
const httpProxy = require('http-proxy');
|
|
18
|
+
const portfinder = require('portfinder-cp');
|
|
19
|
+
const os = require('os')
|
|
20
|
+
class Lproxy {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.proxies = {}
|
|
23
|
+
this.ip = this.local()
|
|
24
|
+
}
|
|
25
|
+
async start (url, options) {
|
|
26
|
+
let port
|
|
27
|
+
if (options && options.port) {
|
|
28
|
+
port = options.port
|
|
29
|
+
console.log("start proxy at port", port)
|
|
30
|
+
delete options.port
|
|
31
|
+
}
|
|
32
|
+
let o = Object.assign({
|
|
33
|
+
target: url,
|
|
34
|
+
ws: true,
|
|
35
|
+
localAddress: '0.0.0.0',
|
|
36
|
+
}, options)
|
|
37
|
+
console.log("proxy object", o)
|
|
38
|
+
const proxy = httpProxy.createProxyServer(o)
|
|
39
|
+
// get a new port
|
|
40
|
+
if (!port) {
|
|
41
|
+
port = await portfinder.getPortPromise({
|
|
42
|
+
//port: 42420
|
|
43
|
+
port: 44000
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
proxy.listen(port)
|
|
47
|
+
proxy.on('close', (res, socket, head) => {
|
|
48
|
+
console.log('Client disconnected');
|
|
49
|
+
});
|
|
50
|
+
proxy.on('error', (e) => {
|
|
51
|
+
console.log('Proxy Error', e)
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
this.proxies[url] = proxy
|
|
55
|
+
return `http://${this.ip}:${port}`
|
|
56
|
+
}
|
|
57
|
+
async stop (url) {
|
|
58
|
+
console.log("proxies", this.proxies, url)
|
|
59
|
+
let p = this.proxies[url]
|
|
60
|
+
if (p) {
|
|
61
|
+
p.close()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
local() {
|
|
65
|
+
const interfaces = Object.values(os.networkInterfaces())
|
|
66
|
+
let addr
|
|
67
|
+
for (let iface of interfaces) {
|
|
68
|
+
for (let alias of iface) {
|
|
69
|
+
if (alias.family === "IPv4" && alias.address !== "127.0.0.1" && !alias.internal) {
|
|
70
|
+
return alias.address
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
module.exports = Lproxy
|
package/kernel/shell.js
CHANGED
|
@@ -89,8 +89,6 @@ class Shell {
|
|
|
89
89
|
// 2. env
|
|
90
90
|
// default env
|
|
91
91
|
|
|
92
|
-
console.log(">>>>> process.env=", JSON.stringify(process.env, null, 2))
|
|
93
|
-
|
|
94
92
|
this.env = Object.assign({}, process.env)
|
|
95
93
|
// If the user has set PYTHONPATH, unset it.
|
|
96
94
|
if (this.env.PYTHONPATH) {
|
|
@@ -113,6 +111,7 @@ class Shell {
|
|
|
113
111
|
}
|
|
114
112
|
|
|
115
113
|
this.env.CMAKE_OBJECT_PATH_MAX = 1024
|
|
114
|
+
this.env.PYTORCH_ENABLE_MPS_FALLBACK = 1
|
|
116
115
|
|
|
117
116
|
// First override this.env with system env
|
|
118
117
|
let system_env = await Environment.get(this.kernel.homedir)
|
|
@@ -440,7 +439,13 @@ class Shell {
|
|
|
440
439
|
return params.message
|
|
441
440
|
} else if (Array.isArray(params.message)) {
|
|
442
441
|
// if params.message is empty, filter out
|
|
443
|
-
let delimiter = " && "
|
|
442
|
+
//let delimiter = " && "
|
|
443
|
+
let delimiter
|
|
444
|
+
if (this.platform === "win32") {
|
|
445
|
+
delimiter = " & ";
|
|
446
|
+
} else {
|
|
447
|
+
delimiter = " ; ";
|
|
448
|
+
}
|
|
444
449
|
return params.message.filter((m) => {
|
|
445
450
|
return m && !/^\s+$/.test(m)
|
|
446
451
|
}).join(delimiter)
|
|
@@ -656,8 +661,6 @@ class Shell {
|
|
|
656
661
|
|
|
657
662
|
config.env = this.env
|
|
658
663
|
|
|
659
|
-
console.log("CONFIG.ENV", JSON.stringify(config.env, null, 2))
|
|
660
|
-
|
|
661
664
|
if (!this.ptyProcess) {
|
|
662
665
|
// ptyProcess doesn't exist => create
|
|
663
666
|
this.done = false
|
package/kernel/shells.js
CHANGED
|
@@ -28,9 +28,7 @@ class Shells {
|
|
|
28
28
|
*/
|
|
29
29
|
async launch(params, options, ondata) {
|
|
30
30
|
// iterate through all the envs
|
|
31
|
-
console.log("------- params.env before", JSON.stringify(params.env, null, 2))
|
|
32
31
|
params.env = this.kernel.bin.envs(params.env)
|
|
33
|
-
console.log("------- params.env after", JSON.stringify(params.env, null, 2))
|
|
34
32
|
|
|
35
33
|
let exec_path = (params.path ? params.path : ".") // use the current path if not specified
|
|
36
34
|
let cwd = (options && options.cwd ? options.cwd : this.kernel.homedir) // if cwd exists, use it. Otherwise the cwd is pinokio home folder (~/pinokio)
|
|
@@ -39,7 +37,36 @@ class Shells {
|
|
|
39
37
|
if (options) params.group = options.group // set group
|
|
40
38
|
|
|
41
39
|
let m
|
|
40
|
+
|
|
41
|
+
// if error doesn't exist, add default "error:" event
|
|
42
|
+
if (!params.on) {
|
|
43
|
+
params.on = []
|
|
44
|
+
}
|
|
45
|
+
// default error
|
|
46
|
+
const defaultHandlers = [{
|
|
47
|
+
event: "/error:/i",
|
|
48
|
+
break: true
|
|
49
|
+
}, {
|
|
50
|
+
event: "/errno /i",
|
|
51
|
+
break: true
|
|
52
|
+
}, {
|
|
53
|
+
event: "/error:.*triton/i",
|
|
54
|
+
break: false
|
|
55
|
+
}]
|
|
56
|
+
params.on = params.on.concat(defaultHandlers)
|
|
42
57
|
let response = await sh.start(params, async (stream) => {
|
|
58
|
+
/*
|
|
59
|
+
{
|
|
60
|
+
method: "shell.run",
|
|
61
|
+
params: {
|
|
62
|
+
message,
|
|
63
|
+
on: [{
|
|
64
|
+
event: <regex>,
|
|
65
|
+
<done|kill|debug>: true
|
|
66
|
+
}],
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
*/
|
|
43
70
|
if (params.on && Array.isArray(params.on)) {
|
|
44
71
|
for(let handler of params.on) {
|
|
45
72
|
// regexify
|
|
@@ -67,33 +94,108 @@ class Shells {
|
|
|
67
94
|
sh.continue()
|
|
68
95
|
}
|
|
69
96
|
}
|
|
70
|
-
// } else if (handler.pattern === "url") {
|
|
71
|
-
// let re = /https?:\/\/[a-zA-Z0-9.:]+/g
|
|
72
|
-
// let line = stream.cleaned.replaceAll(/[\r\n]/g, "")
|
|
73
|
-
// let rendered_event = [...line.matchAll(re)]
|
|
74
|
-
// if (rendered_event.length > 0) {
|
|
75
|
-
// stream.matches = rendered_event
|
|
76
|
-
// if (handler.kill) {
|
|
77
|
-
// m = new URL(rendered_event[0])
|
|
78
|
-
// console.log("MM", m)
|
|
79
|
-
// sh.kill()
|
|
80
|
-
// }
|
|
81
|
-
// if (handler.done) {
|
|
82
|
-
// m = new URL(rendered_event[0])
|
|
83
|
-
// console.log("MM", m)
|
|
84
|
-
// sh.continue()
|
|
85
|
-
// }
|
|
86
|
-
// }
|
|
87
97
|
}
|
|
88
98
|
}
|
|
89
99
|
}
|
|
90
100
|
ondata(stream)
|
|
91
101
|
})
|
|
92
|
-
console.log("shell ended", { id: sh.id, response, stdout: response, event: m })
|
|
93
102
|
|
|
103
|
+
/*
|
|
104
|
+
{
|
|
105
|
+
method: "shell.run",
|
|
106
|
+
params: {
|
|
107
|
+
message,
|
|
108
|
+
on: [{
|
|
109
|
+
event: <regex>,
|
|
110
|
+
break: true|false
|
|
111
|
+
}],
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
- true: break with matched
|
|
116
|
+
- false: do not break (default)
|
|
117
|
+
- TEMPLATE: parse the template
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
let errors = new Set()
|
|
121
|
+
if (response) {
|
|
122
|
+
if (params.on && Array.isArray(params.on)) {
|
|
123
|
+
|
|
124
|
+
let line = response.replaceAll(/[\r\n]/g, "")
|
|
125
|
+
// 1. find all break event handlers
|
|
126
|
+
let breakPoints = params.on.filter((x) => {
|
|
127
|
+
return x.event && x.hasOwnProperty("break")
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// 2. first find the `break: false` handlers and replace the patterns with blank => so they won't be matched in the next step
|
|
131
|
+
//let line = response.replaceAll(/[\r\n]/g, "")
|
|
132
|
+
for(let handler of breakPoints) {
|
|
133
|
+
if (handler.event) {
|
|
134
|
+
let matches = /^\/(.+)\/([dgimsuy]*)$/gs.exec(handler.event)
|
|
135
|
+
if (!/g/.test(matches[2])) {
|
|
136
|
+
matches[2] += "g" // if g option is not included, include it (need it for matchAll)
|
|
137
|
+
}
|
|
138
|
+
let re = new RegExp(matches[1], matches[2])
|
|
139
|
+
|
|
140
|
+
// only the "break: false" ones => these need to be ignored
|
|
141
|
+
if (!handler.break) {
|
|
142
|
+
line = line.replaceAll(re, "")
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 3. Now with all the `break: false` (ignored patterns) gone, look for the `break: true` patterns
|
|
148
|
+
for(let handler of breakPoints) {
|
|
149
|
+
if (handler.event) {
|
|
150
|
+
let matches = /^\/(.+)\/([dgimsuy]*)$/gs.exec(handler.event)
|
|
151
|
+
if (!/g/.test(matches[2])) {
|
|
152
|
+
matches[2] += "g" // if g option is not included, include it (need it for matchAll)
|
|
153
|
+
}
|
|
154
|
+
let re = new RegExp(matches[1], matches[2])
|
|
155
|
+
|
|
156
|
+
// only the "break: true" ones
|
|
157
|
+
if (handler.break) {
|
|
158
|
+
|
|
159
|
+
let match;
|
|
160
|
+
// Keep executing the regex on the text until no more matches are found
|
|
161
|
+
while ((match = re.exec(line)) !== null) {
|
|
162
|
+
errors.add(match[0])
|
|
163
|
+
// errors.add(match.slice(1));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
if (errors.size > 0) {
|
|
173
|
+
// try replacing the shortest pattern from the text one by one and narrow down the errors
|
|
174
|
+
// so it doesn't accidently contain a very long match
|
|
175
|
+
|
|
176
|
+
let errs = Array.from(errors)
|
|
177
|
+
errs.sort((x, y) => {
|
|
178
|
+
return x.length - y.length
|
|
179
|
+
})
|
|
180
|
+
let line = response.replaceAll(/[\r\n]/g, "")
|
|
181
|
+
let shortened_errs = []
|
|
182
|
+
// at this point, errs is sorted in ascending order of length, so the shortest match is the first item
|
|
183
|
+
for(let err of errs) {
|
|
184
|
+
// 1. check the err still matches the line => The first time this is run, it will always be included. But from the next time it might not be
|
|
185
|
+
if (line.includes(err)) {
|
|
186
|
+
// 2. remove the first pattern
|
|
187
|
+
shortened_errs.push(err)
|
|
188
|
+
line = line.replaceAll(err, "")
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// don't return if there's an error
|
|
193
|
+
return { id: sh.id, response, stdout: response, event: m, error: shortened_errs }
|
|
194
|
+
} else {
|
|
195
|
+
// need to make a request
|
|
196
|
+
return { id: sh.id, response, stdout: response, event: m }
|
|
197
|
+
}
|
|
94
198
|
|
|
95
|
-
// need to make a request
|
|
96
|
-
return { id: sh.id, response, stdout: response, event: m }
|
|
97
199
|
}
|
|
98
200
|
async start(params, options, ondata) {
|
|
99
201
|
params.persistent = true
|
|
@@ -203,14 +305,13 @@ class Shells {
|
|
|
203
305
|
let info = this.shells.map((s) => {
|
|
204
306
|
return { id: s.id, group: s.group, cmd: s.cmd }
|
|
205
307
|
})
|
|
206
|
-
console.log("reset", this.shells.length, JSON.stringify(info, null, 2))
|
|
207
308
|
if (this.shells) {
|
|
208
309
|
let shells = []
|
|
209
310
|
for(let i=0; i<this.shells.length; i++) {
|
|
210
311
|
shells.push(this.shells[i])
|
|
211
312
|
}
|
|
212
313
|
for(let shell of shells) {
|
|
213
|
-
console.log("[Kill]", { id: shell.id, group: shell.group, cmd: shell.cmd })
|
|
314
|
+
console.log("[Kill Shell]", { id: shell.id, group: shell.group, cmd: shell.cmd })
|
|
214
315
|
shell.kill("", true)
|
|
215
316
|
}
|
|
216
317
|
}
|
package/kernel/sysinfo.js
CHANGED
|
@@ -101,14 +101,11 @@ class Sysinfo {
|
|
|
101
101
|
cmd = "env"
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
console.log(
|
|
109
|
-
console.log("############### DEBUGGING ENV FINISH")
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
// console.log("############### DEBUGGING ENV")
|
|
105
|
+
// let _res = await this.kernel.bin.exec({ message: cmd, conda: { skip: true } }, (stream) => {
|
|
106
|
+
// })
|
|
107
|
+
// console.log(_res)
|
|
108
|
+
// console.log("############### DEBUGGING ENV FINISH")
|
|
112
109
|
|
|
113
110
|
let res = await this.kernel.bin.exec({ message: cmd }, (stream) => {
|
|
114
111
|
})
|
package/kernel/util.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const os = require('os')
|
|
3
|
+
const net = require('node:net')
|
|
3
4
|
const path = require('path')
|
|
4
5
|
const dotenv = require('dotenv')
|
|
5
6
|
const child_process = require('node:child_process');
|
|
@@ -13,6 +14,31 @@ const h = "[^\\S\\r\\n]"; // simulate `\h`
|
|
|
13
14
|
const returnPattern = /\r/g;
|
|
14
15
|
const returnReplacement = "\\r";
|
|
15
16
|
|
|
17
|
+
|
|
18
|
+
const port_running = async (host, port) => {
|
|
19
|
+
const timeout = 1000
|
|
20
|
+
const promise = new Promise((resolve, reject) => {
|
|
21
|
+
const socket = new net.Socket();
|
|
22
|
+
const onError = (e) => {
|
|
23
|
+
socket.destroy();
|
|
24
|
+
reject();
|
|
25
|
+
};
|
|
26
|
+
socket.setTimeout(timeout);
|
|
27
|
+
socket.once('error', onError);
|
|
28
|
+
socket.once('timeout', onError);
|
|
29
|
+
socket.connect(port, host, () => {
|
|
30
|
+
socket.end();
|
|
31
|
+
resolve();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
try {
|
|
35
|
+
await promise;
|
|
36
|
+
return true
|
|
37
|
+
} catch (e) {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
16
42
|
const parse_env = async (filename) => {
|
|
17
43
|
try {
|
|
18
44
|
const buf = await fs.promises.readFile(filename)
|
|
@@ -142,5 +168,5 @@ const update_env = async (filepath, changes) => {
|
|
|
142
168
|
await fs.promises.writeFile(filepath, newval)
|
|
143
169
|
};
|
|
144
170
|
module.exports = {
|
|
145
|
-
parse_env, api_path, update_env, parse_env_detail, openfs
|
|
171
|
+
parse_env, api_path, update_env, parse_env_detail, openfs, port_running
|
|
146
172
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinokiod",
|
|
3
|
-
"version": "2.15.
|
|
3
|
+
"version": "2.15.9",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -31,16 +31,15 @@
|
|
|
31
31
|
"fs-extra": "^11.1.1",
|
|
32
32
|
"glob": "^10.3.3",
|
|
33
33
|
"glob-gitignore": "^1.0.14",
|
|
34
|
+
"http-proxy": "^1.18.1",
|
|
34
35
|
"http-proxy-middleware": "^3.0.0",
|
|
35
36
|
"http-terminator": "^3.2.0",
|
|
36
37
|
"isomorphic-git": "^1.23.0",
|
|
37
38
|
"jimini": "^0.0.6",
|
|
38
39
|
"jsdom": "^24.0.0",
|
|
39
|
-
"jsonpath-plus": "^7.2.0",
|
|
40
40
|
"key-store": "^1.2.0",
|
|
41
41
|
"kleur": "^4.1.5",
|
|
42
42
|
"lodash": "^4.17.21",
|
|
43
|
-
"lproxy": "^0.0.12",
|
|
44
43
|
"marked": "^5.0.1",
|
|
45
44
|
"mime-types": "^2.1.35",
|
|
46
45
|
"multer": "^1.4.5-lts.1",
|
package/server/index.js
CHANGED
|
@@ -71,7 +71,6 @@ class Server {
|
|
|
71
71
|
process.env[PATH_KEY]
|
|
72
72
|
].join(path.delimiter)
|
|
73
73
|
}
|
|
74
|
-
|
|
75
74
|
}
|
|
76
75
|
stop() {
|
|
77
76
|
this.server.close()
|
|
@@ -257,11 +256,11 @@ class Server {
|
|
|
257
256
|
|
|
258
257
|
await this.init_env("api/" + name)
|
|
259
258
|
|
|
259
|
+
|
|
260
260
|
let mode = "run"
|
|
261
261
|
if (req.query && req.query.mode) {
|
|
262
262
|
mode = req.query.mode
|
|
263
263
|
}
|
|
264
|
-
|
|
265
264
|
const env = await this.kernel.env("api/" + name)
|
|
266
265
|
|
|
267
266
|
//res.render("browser", {
|
|
@@ -1868,7 +1867,11 @@ class Server {
|
|
|
1868
1867
|
} else {
|
|
1869
1868
|
const primary_port = 80
|
|
1870
1869
|
const secondary_port = 42000
|
|
1871
|
-
const
|
|
1870
|
+
const running1 = await Util.port_running("localhost", primary_port)
|
|
1871
|
+
const running2 = await Util.port_running("127.0.0.1", primary_port)
|
|
1872
|
+
const running = running1 || running2
|
|
1873
|
+
const available = !running
|
|
1874
|
+
//const available = await portfinder.isAvailablePromise({ host: "0.0.0.0", port: primary_port })
|
|
1872
1875
|
console.log("check available", { primary_port, available })
|
|
1873
1876
|
if (available) {
|
|
1874
1877
|
this.port = primary_port
|
|
@@ -2105,7 +2108,83 @@ class Server {
|
|
|
2105
2108
|
Util.openfs(req.body.path)
|
|
2106
2109
|
res.json({ success: true })
|
|
2107
2110
|
}))
|
|
2111
|
+
this.app.get("/proxy", ex(async (req, res) => {
|
|
2112
|
+
let live_proxies = this.kernel.api.proxies["/proxy"]
|
|
2113
|
+
if (!live_proxies) live_proxies = []
|
|
2114
|
+
let proxies = [{
|
|
2115
|
+
icon: "ollama.webp",
|
|
2116
|
+
name: "Ollama",
|
|
2117
|
+
target: 'http://127.0.0.1:11434',
|
|
2118
|
+
port: 42420
|
|
2119
|
+
// }, {
|
|
2120
|
+
// name: "LMStudio",
|
|
2121
|
+
// target: 'http://127.0.0.1:1234',
|
|
2122
|
+
// port: 42421
|
|
2123
|
+
}]
|
|
2124
|
+
for(let i=0; i<proxies.length; i++) {
|
|
2125
|
+
proxies[i].running = false
|
|
2126
|
+
for(let live_proxy of live_proxies) {
|
|
2127
|
+
if (live_proxy.name === proxies[i].name) {
|
|
2128
|
+
proxies[i].running = true
|
|
2129
|
+
proxies[i].proxy = live_proxy.proxy
|
|
2130
|
+
proxies[i].qr = await QRCode.toDataURL(live_proxy.proxy)
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
let pinokio_proxy = this.kernel.api.proxies["/"]
|
|
2136
|
+
let pinokio_cloudflare = this.cloudflare_pub
|
|
2137
|
+
|
|
2138
|
+
let qr = null
|
|
2139
|
+
let qr_cloudflare = null
|
|
2140
|
+
let home_proxy = null
|
|
2141
|
+
if (pinokio_proxy && pinokio_proxy.length > 0) {
|
|
2142
|
+
qr = await QRCode.toDataURL(pinokio_proxy[0].proxy)
|
|
2143
|
+
home_proxy = pinokio_proxy[0]
|
|
2144
|
+
}
|
|
2108
2145
|
|
|
2146
|
+
let icon
|
|
2147
|
+
if (this.theme === "dark") {
|
|
2148
|
+
icon = "pinokio-white.png"
|
|
2149
|
+
} else {
|
|
2150
|
+
icon = "pinokio-black.png"
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
res.render("proxy", {
|
|
2154
|
+
agent: this.agent,
|
|
2155
|
+
theme: this.theme,
|
|
2156
|
+
items: proxies,
|
|
2157
|
+
qr,
|
|
2158
|
+
proxy: home_proxy,
|
|
2159
|
+
localhost: `http://localhost:${this.port}`,
|
|
2160
|
+
icon
|
|
2161
|
+
})
|
|
2162
|
+
}))
|
|
2163
|
+
this.app.post("/proxy", ex(async (req, res) => {
|
|
2164
|
+
/*
|
|
2165
|
+
req.body := {
|
|
2166
|
+
action: "start"|"stop",
|
|
2167
|
+
name: <name>,
|
|
2168
|
+
target: <target url>,
|
|
2169
|
+
port: <proxy port>
|
|
2170
|
+
}
|
|
2171
|
+
*/
|
|
2172
|
+
if (req.body && req.body.target && req.body.action && req.body.name) {
|
|
2173
|
+
//let port = new URL(req.body.target).port
|
|
2174
|
+
//let port = await this.kernel.port()
|
|
2175
|
+
if (req.body.action === "start") {
|
|
2176
|
+
let port = req.body.port
|
|
2177
|
+
console.log("start proxy")
|
|
2178
|
+
await this.kernel.api.startProxy("/proxy", req.body.target, req.body.name, { port })
|
|
2179
|
+
console.log(this.kernel.api.proxies)
|
|
2180
|
+
} else if (req.body.action === "stop") {
|
|
2181
|
+
await this.kernel.api.stopProxy({
|
|
2182
|
+
uri: req.body.target
|
|
2183
|
+
})
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
res.json({ success: true })
|
|
2187
|
+
}))
|
|
2109
2188
|
this.app.post("/unpublish", ex(async (req, res) => {
|
|
2110
2189
|
/*
|
|
2111
2190
|
req.body := {
|
|
@@ -2667,8 +2746,8 @@ class Server {
|
|
|
2667
2746
|
fs.uri("api", "https://github.com/cocktailpeanut/llamacpp.pinokio.git/icon.png")
|
|
2668
2747
|
fs.uri("bin", "python/bin")
|
|
2669
2748
|
|
|
2670
|
-
1. Git URI: http://localhost
|
|
2671
|
-
2. Local path: http://localhost
|
|
2749
|
+
1. Git URI: http://localhost/pinokio/fs?drive=api&path=https://github.com/cocktailpeanut/llamacpp.pinokio.git/icon.png
|
|
2750
|
+
2. Local path: http://localhost/pinokio/fs?drive=api&path=test/icon.png
|
|
2672
2751
|
*/
|
|
2673
2752
|
this.app.get("/pinokio/fs", ex((req, res) => {
|
|
2674
2753
|
// serve reaw files
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/*!***************************************************
|
|
2
|
+
* mark.js v8.6.0
|
|
3
|
+
* https://github.com/julmot/mark.js
|
|
4
|
+
* Copyright (c) 2014–2017, Julian Motz
|
|
5
|
+
* Released under the MIT license https://git.io/vwTVl
|
|
6
|
+
*****************************************************/
|
|
7
|
+
"use strict";function _classCallCheck(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}var _extends=Object.assign||function(a){for(var b=1;b<arguments.length;b++){var c=arguments[b];for(var d in c)Object.prototype.hasOwnProperty.call(c,d)&&(a[d]=c[d])}return a},_createClass=function(){function a(a,b){for(var c=0;c<b.length;c++){var d=b[c];d.enumerable=d.enumerable||!1,d.configurable=!0,"value"in d&&(d.writable=!0),Object.defineProperty(a,d.key,d)}}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}(),_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};!function(a,b,c){"function"==typeof define&&define.amd?define([],function(){return a(b,c)}):"object"===("undefined"==typeof module?"undefined":_typeof(module))&&module.exports?module.exports=a(b,c):a(b,c)}(function(a,b){var c=function(){function c(b){_classCallCheck(this,c),this.ctx=b,this.ie=!1;var d=a.navigator.userAgent;(d.indexOf("MSIE")>-1||d.indexOf("Trident")>-1)&&(this.ie=!0)}return _createClass(c,[{key:"log",value:function a(b){var c=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"debug",a=this.opt.log;this.opt.debug&&"object"===("undefined"==typeof a?"undefined":_typeof(a))&&"function"==typeof a[c]&&a[c]("mark.js: "+b)}},{key:"escapeStr",value:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}},{key:"createRegExp",value:function(a){return a=this.escapeStr(a),Object.keys(this.opt.synonyms).length&&(a=this.createSynonymsRegExp(a)),this.opt.ignoreJoiners&&(a=this.setupIgnoreJoinersRegExp(a)),this.opt.diacritics&&(a=this.createDiacriticsRegExp(a)),a=this.createMergedBlanksRegExp(a),this.opt.ignoreJoiners&&(a=this.createIgnoreJoinersRegExp(a)),a=this.createAccuracyRegExp(a)}},{key:"createSynonymsRegExp",value:function(a){var b=this.opt.synonyms,c=this.opt.caseSensitive?"":"i";for(var d in b)if(b.hasOwnProperty(d)){var e=b[d],f=this.escapeStr(d),g=this.escapeStr(e);a=a.replace(new RegExp("("+f+"|"+g+")","gm"+c),"("+f+"|"+g+")")}return a}},{key:"setupIgnoreJoinersRegExp",value:function(a){return a.replace(/[^(|)\\]/g,function(a,b,c){var d=c.charAt(b+1);return/[(|)\\]/.test(d)||""===d?a:a+"\0"})}},{key:"createIgnoreJoinersRegExp",value:function(a){return a.split("\0").join("[\\u00ad|\\u200b|\\u200c|\\u200d]?")}},{key:"createDiacriticsRegExp",value:function(a){var b=this.opt.caseSensitive?"":"i",c=this.opt.caseSensitive?["aàáâãäåāąă","AÀÁÂÃÄÅĀĄĂ","cçćč","CÇĆČ","dđď","DĐĎ","eèéêëěēę","EÈÉÊËĚĒĘ","iìíîïī","IÌÍÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóôõöøō","OÒÓÔÕÖØŌ","rř","RŘ","sšśș","SŠŚȘ","tťț","TŤȚ","uùúûüůū","UÙÚÛÜŮŪ","yÿý","YŸÝ","zžżź","ZŽŻŹ"]:["aÀÁÂÃÄÅàáâãäåĀāąĄăĂ","cÇçćĆčČ","dđĐďĎ","eÈÉÊËèéêëěĚĒēęĘ","iÌÍÎÏìíîïĪī","lłŁ","nÑñňŇńŃ","oÒÓÔÕÖØòóôõöøŌō","rřŘ","sŠšśŚșȘ","tťŤțȚ","uÙÚÛÜùúûüůŮŪū","yŸÿýÝ","zŽžżŻźŹ"],d=[];return a.split("").forEach(function(e){c.every(function(c){if(c.indexOf(e)!==-1){if(d.indexOf(c)>-1)return!1;a=a.replace(new RegExp("["+c+"]","gm"+b),"["+c+"]"),d.push(c)}return!0})}),a}},{key:"createMergedBlanksRegExp",value:function(a){return a.replace(/[\s]+/gim,"[\\s]+")}},{key:"createAccuracyRegExp",value:function(a){var b=this,c=this.opt.accuracy,d="string"==typeof c?c:c.value,e="string"==typeof c?[]:c.limiters,f="";switch(e.forEach(function(a){f+="|"+b.escapeStr(a)}),d){case"partially":default:return"()("+a+")";case"complementary":return"()([^\\s"+f+"]*"+a+"[^\\s"+f+"]*)";case"exactly":return"(^|\\s"+f+")("+a+")(?=$|\\s"+f+")"}}},{key:"getSeparatedKeywords",value:function(a){var b=this,c=[];return a.forEach(function(a){b.opt.separateWordSearch?a.split(" ").forEach(function(a){a.trim()&&c.indexOf(a)===-1&&c.push(a)}):a.trim()&&c.indexOf(a)===-1&&c.push(a)}),{keywords:c.sort(function(a,b){return b.length-a.length}),length:c.length}}},{key:"getTextNodes",value:function(a){var b=this,c="",d=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,function(a){d.push({start:c.length,end:(c+=a.textContent).length,node:a})},function(a){return b.matchesExclude(a.parentNode,!0)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},function(){a({value:c,nodes:d})})}},{key:"matchesExclude",value:function(a,b){var c=this.opt.exclude.concat(["script","style","title","head","html"]);return b&&(c=c.concat(["*[data-markjs='true']"])),d.matches(a,c)}},{key:"wrapRangeInTextNode",value:function(a,c,d){var e=this.opt.element?this.opt.element:"mark",f=a.splitText(c),g=f.splitText(d-c),h=b.createElement(e);return h.setAttribute("data-markjs","true"),this.opt.className&&h.setAttribute("class",this.opt.className),h.textContent=f.textContent,f.parentNode.replaceChild(h,f),g}},{key:"wrapRangeInMappedTextNode",value:function(a,b,c,d,e){var f=this;a.nodes.every(function(g,h){var i=a.nodes[h+1];if("undefined"==typeof i||i.start>b){var j=function(){var i=b-g.start,j=(c>g.end?g.end:c)-g.start;if(d(g.node)){g.node=f.wrapRangeInTextNode(g.node,i,j);var k=a.value.substr(0,g.start),l=a.value.substr(j+g.start);if(a.value=k+l,a.nodes.forEach(function(b,c){c>=h&&(a.nodes[c].start>0&&c!==h&&(a.nodes[c].start-=j),a.nodes[c].end-=j)}),c-=j,e(g.node.previousSibling,g.start),!(c>g.end))return{v:!1};b=g.end}}();if("object"===("undefined"==typeof j?"undefined":_typeof(j)))return j.v}return!0})}},{key:"wrapMatches",value:function(a,b,c,d,e){var f=this,g=0===b?0:b+1;this.getTextNodes(function(b){b.nodes.forEach(function(b){b=b.node;for(var e=void 0;null!==(e=a.exec(b.textContent))&&""!==e[g];)if(c(e[g],b)){var h=e.index;if(0!==g)for(var i=1;i<g;i++)h+=e[i].length;b=f.wrapRangeInTextNode(b,h,h+e[g].length),d(b.previousSibling),a.lastIndex=0}}),e()})}},{key:"wrapMatchesAcrossElements",value:function(a,b,c,d,e){var f=this,g=0===b?0:b+1;this.getTextNodes(function(b){for(var h=void 0;null!==(h=a.exec(b.value))&&""!==h[g];){var i=h.index;if(0!==g)for(var j=1;j<g;j++)i+=h[j].length;var k=i+h[g].length;f.wrapRangeInMappedTextNode(b,i,k,function(a){return c(h[g],a)},function(b,c){a.lastIndex=c,d(b)})}e()})}},{key:"unwrapMatches",value:function(a){for(var c=a.parentNode,d=b.createDocumentFragment();a.firstChild;)d.appendChild(a.removeChild(a.firstChild));c.replaceChild(d,a),this.ie?this.normalizeTextNode(c):c.normalize()}},{key:"normalizeTextNode",value:function(a){if(a){if(3===a.nodeType)for(;a.nextSibling&&3===a.nextSibling.nodeType;)a.nodeValue+=a.nextSibling.nodeValue,a.parentNode.removeChild(a.nextSibling);else this.normalizeTextNode(a.firstChild);this.normalizeTextNode(a.nextSibling)}}},{key:"markRegExp",value:function(a,b){var c=this;this.opt=b,this.log('Searching with expression "'+a+'"');var d=0,e="wrapMatches",f=function(a){d++,c.opt.each(a)};this.opt.acrossElements&&(e="wrapMatchesAcrossElements"),this[e](a,this.opt.ignoreGroups,function(a,b){return c.opt.filter(b,a,d)},f,function(){0===d&&c.opt.noMatch(a),c.opt.done(d)})}},{key:"mark",value:function(a,b){var c=this;this.opt=b;var d=0,e="wrapMatches",f=this.getSeparatedKeywords("string"==typeof a?[a]:a),g=f.keywords,h=f.length,i=this.opt.caseSensitive?"":"i",j=function a(b){var f=new RegExp(c.createRegExp(b),"gm"+i),j=0;c.log('Searching with expression "'+f+'"'),c[e](f,1,function(a,e){return c.opt.filter(e,b,d,j)},function(a){j++,d++,c.opt.each(a)},function(){0===j&&c.opt.noMatch(b),g[h-1]===b?c.opt.done(d):a(g[g.indexOf(b)+1])})};this.opt.acrossElements&&(e="wrapMatchesAcrossElements"),0===h?this.opt.done(d):j(g[0])}},{key:"unmark",value:function(a){var b=this;this.opt=a;var c=this.opt.element?this.opt.element:"*";c+="[data-markjs]",this.opt.className&&(c+="."+this.opt.className),this.log('Removal selector "'+c+'"'),this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,function(a){b.unwrapMatches(a)},function(a){var e=d.matches(a,c),f=b.matchesExclude(a,!1);return!e||f?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},this.opt.done)}},{key:"opt",set:function(b){this._opt=_extends({},{element:"",className:"",exclude:[],iframes:!1,separateWordSearch:!0,diacritics:!0,synonyms:{},accuracy:"partially",acrossElements:!1,caseSensitive:!1,ignoreJoiners:!1,ignoreGroups:0,each:function(){},noMatch:function(){},filter:function(){return!0},done:function(){},debug:!1,log:a.console},b)},get:function(){return this._opt}},{key:"iterator",get:function(){return this._iterator||(this._iterator=new d(this.ctx,this.opt.iframes,this.opt.exclude)),this._iterator}}]),c}(),d=function(){function a(b){var c=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],d=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];_classCallCheck(this,a),this.ctx=b,this.iframes=c,this.exclude=d}return _createClass(a,[{key:"getContexts",value:function(){var a=void 0,c=[];return a="undefined"!=typeof this.ctx&&this.ctx?NodeList.prototype.isPrototypeOf(this.ctx)?Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?this.ctx:"string"==typeof this.ctx?Array.prototype.slice.call(b.querySelectorAll(this.ctx)):[this.ctx]:[],a.forEach(function(a){var b=c.filter(function(b){return b.contains(a)}).length>0;c.indexOf(a)!==-1||b||c.push(a)}),c}},{key:"getIframeContents",value:function(a,b){var c=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},d=void 0;try{var e=a.contentWindow;if(d=e.document,!e||!d)throw new Error("iframe inaccessible")}catch(a){c()}d&&b(d)}},{key:"onIframeReady",value:function(a,b,c){var d=this;try{!function(){var e=a.contentWindow,f="about:blank",g="complete",h=function(){var b=a.getAttribute("src").trim(),c=e.location.href;return c===f&&b!==f&&b},i=function(){var e=function e(){try{h()||(a.removeEventListener("load",e),d.getIframeContents(a,b,c))}catch(a){c()}};a.addEventListener("load",e)};e.document.readyState===g?h()?i():d.getIframeContents(a,b,c):i()}()}catch(a){c()}}},{key:"waitForIframes",value:function(a,b){var c=this,d=0;this.forEachIframe(a,function(){return!0},function(a){d++,c.waitForIframes(a.querySelector("html"),function(){--d||b()})},function(a){a||b()})}},{key:"forEachIframe",value:function(b,c,d){var e=this,f=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},g=b.querySelectorAll("iframe"),h=g.length,i=0;g=Array.prototype.slice.call(g);var j=function(){--h<=0&&f(i)};h||j(),g.forEach(function(b){a.matches(b,e.exclude)?j():e.onIframeReady(b,function(a){c(b)&&(i++,d(a)),j()},j)})}},{key:"createIterator",value:function(a,c,d){return b.createNodeIterator(a,c,d,!1)}},{key:"createInstanceOnIframe",value:function(b){return new a(b.querySelector("html"),this.iframes)}},{key:"compareNodeIframe",value:function(a,b,c){var d=a.compareDocumentPosition(c),e=Node.DOCUMENT_POSITION_PRECEDING;if(d&e){if(null===b)return!0;var f=b.compareDocumentPosition(c),g=Node.DOCUMENT_POSITION_FOLLOWING;if(f&g)return!0}return!1}},{key:"getIteratorNode",value:function(a){var b=a.previousNode(),c=void 0;return c=null===b?a.nextNode():a.nextNode()&&a.nextNode(),{prevNode:b,node:c}}},{key:"checkIframeFilter",value:function(a,b,c,d){var e=!1,f=!1;return d.forEach(function(a,b){a.val===c&&(e=b,f=a.handled)}),this.compareNodeIframe(a,b,c)?(e!==!1||f?e===!1||f||(d[e].handled=!0):d.push({val:c,handled:!0}),!0):(e===!1&&d.push({val:c,handled:!1}),!1)}},{key:"handleOpenIframes",value:function(a,b,c,d){var e=this;a.forEach(function(a){a.handled||e.getIframeContents(a.val,function(a){e.createInstanceOnIframe(a).forEachNode(b,c,d)})})}},{key:"iterateThroughNodes",value:function(a,b,c,d,e){for(var f=this,g=this.createIterator(b,a,d),h=[],i=[],j=void 0,k=void 0,l=function(){var a=f.getIteratorNode(g);return k=a.prevNode,j=a.node};l();)this.iframes&&this.forEachIframe(b,function(a){return f.checkIframeFilter(j,k,a,h)},function(b){f.createInstanceOnIframe(b).forEachNode(a,c,d)}),i.push(j);i.forEach(function(a){c(a)}),this.iframes&&this.handleOpenIframes(h,a,c,d),e()}},{key:"forEachNode",value:function(a,b,c){var d=this,e=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},f=this.getContexts(),g=f.length;g||e(),f.forEach(function(f){var h=function(){d.iterateThroughNodes(a,f,b,c,function(){--g<=0&&e()})};d.iframes?d.waitForIframes(f,h):h()})}}],[{key:"matches",value:function(a,b){var c="string"==typeof b?[b]:b,d=a.matches||a.matchesSelector||a.msMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.webkitMatchesSelector;if(d){var e=!1;return c.every(function(b){return!d.call(a,b)||(e=!0,!1)}),e}return!1}}]),a}();return a.Mark=function(a){var b=this,d=new c(a);return this.mark=function(a,c){return d.mark(a,c),b},this.markRegExp=function(a,c){return d.markRegExp(a,c),b},this.unmark=function(a){return d.unmark(a),b},this},a.Mark},window,document);
|
|
Binary file
|