@makano/rew 1.2.2 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,7 +22,8 @@ function tokenizeCoffeeScript(code) {
22
22
  type: 'COMMENT',
23
23
  value: char + code.substring(i + 1).split('\n')[0] + '\n',
24
24
  });
25
- i = code.indexOf('\n', i);
25
+ const ind = code.indexOf('\n', i);
26
+ i = ind < 0 ? code.length-1 : ind;
26
27
  } else if (char === '"' || char === "'") {
27
28
  // String
28
29
  let string = char;
@@ -56,11 +57,11 @@ function tokenizeCoffeeScript(code) {
56
57
  } else {
57
58
  tokens.push({ type: 'WHITESPACE', value: char });
58
59
  }
59
- } else if (/[a-zA-Z_$]/.test(char)) {
60
+ } else if (/[a-zA-Z\._$]/.test(char)) {
60
61
  // Identifier
61
62
  let identifier = char;
62
63
  i++;
63
- while (i < code.length && /[a-zA-Z0-9_$]/.test(code[i])) {
64
+ while (i < code.length && /[a-zA-Z0-9\._$]/.test(code[i])) {
64
65
  identifier += code[i];
65
66
  i++;
66
67
  }
@@ -176,7 +177,7 @@ function compileRewStuff(content, options) {
176
177
  } else if (nextToken) {
177
178
  const nameToken = fnextToken(ind, tokens, 'STRING');
178
179
  defaultName = nextToken.value;
179
- let { nextToken: nextNextToken, n: n2 } = gnextToken(i + 2, 1, tokens) || {};
180
+ let { token: nextNextToken, n: n2 } = gnextToken(i + 2, 1, tokens) || {};
180
181
  if (nextNextToken?.type == 'OTHER' && nextNextToken?.value == ',') {
181
182
  const closingBraceToken = fnextToken(ind, tokens, 'OTHER', '}');
182
183
  if (closingBraceToken) {
@@ -235,12 +236,13 @@ function compileRewStuff(content, options) {
235
236
  }
236
237
 
237
238
  const cpl = (module.exports.compile = function (file, options = {}) {
238
- let c = compile(compileRewStuff(file.content, options), {
239
+ let c = options.type == 'js' || options.compile == false ? file.content : compile(compileRewStuff(file.content, options), {
239
240
  ...options,
240
241
  filename: file.path,
241
242
  bare: false,
242
243
  inlineMap: false,
243
244
  });
245
+ // console.log(c);
244
246
  if (execOptions.jsx || options.jsx) {
245
247
  c = babel.transformSync(c, {
246
248
  presets: [[babelReact, { pragma: execOptions.jsxPragma }]],
@@ -254,10 +256,10 @@ module.exports.compileFile = function (filepath, options = {}) {
254
256
  const f = getFile(filepath);
255
257
 
256
258
  if(options.qrew || path.extname(filepath) == '.qrew') {
257
- f.content = from_qrew(readFileSync(f.path), options.package || findAppInfo(filepath)?.config.package || path.basename(filepath).split('.').slice(0, -1).join('.')).toString();
259
+ f.content = from_qrew(readFileSync(f.path), options.package || findAppInfo(filepath)?.config.manifest.package || path.basename(filepath).split('.').slice(0, -1).join('.')).toString();
258
260
  }
259
261
 
260
- let compiled_code = options.compile == false ? f.content : cpl(f, { ...options });
262
+ let compiled_code = cpl(f, { ...options });
261
263
 
262
264
  return {
263
265
  compiled_code,
@@ -42,30 +42,18 @@ module.exports.prepareContext = function (
42
42
  ...defaultContext,
43
43
  ...pathLib(filepath),
44
44
  ...execLib(filepath),
45
- require: (package) => {
46
- try {
47
- return execOptions.nativeRequire || package.startsWith("node:")
48
- ? require(
49
- package.startsWith("node:")
50
- ? package.split("node:")[1]
51
- : package,
52
- )
53
- : customRequire(package, filepath);
54
- } catch (e) {
55
- throw new Error("Module " + package + " not found");
56
- }
57
- },
58
45
  ...custom_context,
59
46
  };
60
47
  }
61
48
  if (!context.process)
62
49
  context.process = {
63
- argv: process.argv,
50
+ argv: options.argv || process.argv,
64
51
  target: {
65
52
  on: (event, listener) => process.on(event, listener),
66
53
  off: (event, listener) => process.off(event, listener),
67
54
  emit: (event, code) => process.emit(event, code),
68
55
  },
56
+ __execFile: global.fileName,
69
57
  env: process.env,
70
58
  cwd: () => process.cwd(),
71
59
  arch: process.arch,
@@ -74,6 +62,21 @@ module.exports.prepareContext = function (
74
62
  context.global = context;
75
63
  context.imports.assert = options.import ?? {};
76
64
  context.imp = imp(runPath, context);
65
+ context.require = (package) => {
66
+ try {
67
+ const search = execOptions.nativeRequire || package.startsWith("node:")
68
+ ? require(
69
+ package.startsWith("node:")
70
+ ? package.split("node:")[1]
71
+ : package,
72
+ )
73
+ : customRequire(package, filepath);
74
+ if(!search) throw new Error("Module " + package + " not found");
75
+ return search;
76
+ } catch (e) {
77
+ throw e;
78
+ }
79
+ };
77
80
  context.inc = (package, asserts) => {
78
81
  try {
79
82
  if (package.startsWith("node:") || package.startsWith("pkg:"))
@@ -1,22 +1,41 @@
1
1
  const vm = require('vm');
2
2
  const { compileFile } = require('./compiler');
3
3
  const { prepareContext } = require('./context');
4
+ const { existsSync, readFileSync } = require('fs');
5
+ const { CONFIG_PATH } = require('../const/config_path');
6
+ const path = require('path');
7
+
8
+ const preScript = readFileSync(path.join(__dirname, '../const/pre-exec.js'), { encoding: 'utf-8' });
4
9
 
5
10
  const exec = (module.exports.exec = function (code, context) {
6
11
  return vm.runInNewContext(code, vm.createContext(context), {
7
12
  filename: context.module.filepath,
8
- lineOffset: 0,
13
+ lineOffset: -1 - preScript.split('\n').length,
9
14
  displayErrors: true,
10
15
  });
11
16
  });
12
17
 
13
18
  module.exports.runPath = function runPath(filepath, options = {}, custom_context = {}) {
14
- const { compiled_code, file } = compileFile(filepath, options);
19
+ if(filepath.endsWith('.js')) options.type = 'js';
20
+ let { compiled_code, file } = compileFile(filepath, options);
15
21
  const context = prepareContext(custom_context, options, file.path, runPath);
16
22
 
17
23
  context.module.compiled = compiled_code;
18
24
  context.process.exit = (int) => process.exit(int);
19
25
 
26
+ if(context.app){
27
+ const p = path.join(CONFIG_PATH, context.app.config.manifest.package, 'app');
28
+ if(existsSync(p) && context.app.path !== p){
29
+ console.log("App with the same package name has been installed. Conflicts happened. \nTo fix this, change your app's package name or remove the app making the conflict.");
30
+ return {
31
+ context: { exports: null },
32
+ returns: null
33
+ }
34
+ }
35
+ }
36
+
37
+ compiled_code = preScript+compiled_code;
38
+
20
39
  return {
21
40
  context,
22
41
  returns: exec(compiled_code, context),
@@ -22,7 +22,7 @@ function yamlFile(file) {
22
22
  }),
23
23
  ]);
24
24
 
25
- return yaml.load(file.content, { schema });
25
+ return file.content.startsWith('---') ? yaml.loadAll(file.content, { schema })[0] : yaml.load(file.content, { schema });
26
26
  }
27
27
 
28
28
  const importYaml = (module.exports.importYaml = function importYaml(filepath, file) {
@@ -14,7 +14,7 @@ module.exports = (context) => ({
14
14
  CONFIG_PATH,
15
15
  _onImport() {
16
16
  if (context.app) {
17
- return this.create(context.app.config.package);
17
+ return this.create(context.app.config.manifest.package);
18
18
  } else {
19
19
  return this.create(seededID(path.basename(context.module.filepath).replace(/[-_/\.]/g, '')));
20
20
  }
@@ -49,9 +49,16 @@ module.exports = (context) => ({
49
49
  const fileRoot = path.join(rootPath, name);
50
50
  const exists = fs.existsSync(fileRoot);
51
51
  return {
52
- create(value) {
52
+ write(value, ifExists) {
53
53
  if (!fs.existsSync(path.dirname(fileRoot))) fs.mkdirSync(path.dirname(fileRoot), { recursive: true });
54
+ if(ifExists && fs.existsSync(fileRoot)) return this;
54
55
  fs.writeFileSync(fileRoot, value || defaultValue);
56
+ return this;
57
+ },
58
+ read(s){
59
+ let file = fs.readFileSync(fileRoot);
60
+ return typeof s == "string" ? file.toString() :
61
+ typeof s == "object" ? file.toJSON() : file;
55
62
  },
56
63
  fileRoot,
57
64
  exists,
@@ -94,6 +101,7 @@ module.exports = (context) => ({
94
101
  remove: (key) => defaultCenter.remove(key),
95
102
  root: rootPath,
96
103
  package: packageName,
104
+ loadYaml: (file) => jsYaml.load(fs.readFileSync(file, { encoding: 'utf-8' }))
97
105
  };
98
106
  },
99
107
  });
@@ -347,7 +347,10 @@ const createDB = (dbName, dirname, dbData = {}, encryptionKey) => {
347
347
 
348
348
  const remove = (key) => {
349
349
  if (!fs.existsSync(mapFilePath)) return false;
350
- const data = readDataFile(mapFilePath);
350
+ let data = {};
351
+ if (fs.existsSync(mapFilePath)) {
352
+ data = readDataFile(mapFilePath);
353
+ }
351
354
  if (data[key]) {
352
355
  delete data[key];
353
356
  writeDataFile(mapFilePath, data);
@@ -356,8 +359,11 @@ const createDB = (dbName, dirname, dbData = {}, encryptionKey) => {
356
359
  return false;
357
360
  };
358
361
 
359
- const transform = (cb, mutate = false) => {
360
- const data = readDataFile(mapFilePath);
362
+ const transform = (cb, mutate = true) => {
363
+ let data = {};
364
+ if (fs.existsSync(mapFilePath)) {
365
+ data = readDataFile(mapFilePath);
366
+ }
361
367
  const transformedData = cb(data);
362
368
  if (mutate) {
363
369
  writeDataFile(mapFilePath, transformedData);
@@ -386,7 +392,7 @@ module.exports = (context) => ({
386
392
  },
387
393
  db(dbname, data = {}, encryptionKey) {
388
394
  if (!context.app) throw new Error('rune can only be used in apps');
389
- const pkg = path.join(CONFIG_PATH, context.app.config.package, 'db');
395
+ const pkg = path.join(CONFIG_PATH, context.app.config.manifest.package, 'db');
390
396
  if (!fs.existsSync(pkg)) fs.mkdirSync(pkg, { recursive: true });
391
397
  return createDB(dbname, pkg, data, encryptionKey || ENCRYPTION_KEY);
392
398
  },
@@ -394,7 +400,7 @@ module.exports = (context) => ({
394
400
  return gen_key(secret);
395
401
  },
396
402
  makeRef,
397
- runePop,
398
- runePush,
403
+ push: runePush,
404
+ pop: runePop,
399
405
  createDB,
400
406
  });
package/main.js ADDED
@@ -0,0 +1,13 @@
1
+
2
+ const utils = require("./lib/rew/cli/utils");
3
+ const { run } = require("./lib/rew/main");
4
+ const { compileFile, compile } = require("./lib/rew/modules/compiler");
5
+ const pkgs = require("./lib/rew/pkgs/pkgs");
6
+
7
+ module.exports = {
8
+ compile,
9
+ compileFile,
10
+ run,
11
+ pkgs,
12
+ utils
13
+ };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@makano/rew",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "A simple coffescript runtime and app manager",
5
- "main": "lib/rew/main.js",
5
+ "main": "main.js",
6
6
  "directories": {
7
7
  "lib": "lib"
8
8
  },
@@ -11,10 +11,7 @@
11
11
  },
12
12
  "files": [
13
13
  "lib/",
14
- "cpp/",
15
- "bin/",
16
- "meson.build",
17
- "build.sh",
14
+ "main.js",
18
15
  "README.md"
19
16
  ],
20
17
  "bin": {
@@ -34,10 +31,12 @@
34
31
  "dependencies": {
35
32
  "@babel/core": "^7.24.6",
36
33
  "@babel/preset-react": "^7.24.6",
34
+ "@babel/preset-typescript": "^7.24.7",
37
35
  "axios": "^1.7.2",
38
36
  "babel-plugin-jsx": "^1.2.0",
39
37
  "chokidar": "^3.6.0",
40
38
  "colors": "^1.4.0",
39
+ "deasync": "^0.1.30",
41
40
  "js-yaml": "^4.1.0",
42
41
  "tiny-msgpack": "^2.2.0",
43
42
  "uuid": "^9.0.1",
package/bin/ui DELETED
Binary file
package/bin/ui_ws DELETED
Binary file
package/bin/webkit_app DELETED
Binary file
package/build.sh DELETED
@@ -1,8 +0,0 @@
1
- #!/bin/sh
2
- opath=./bin/ui
3
- if [ $1 ]; then
4
- opath=$1
5
- fi
6
- # g++ ./cpp/ui.cpp -o $opath `pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.0 libwebsockets jsoncpp`
7
- meson build
8
- cd build && ninja && mv ./ui $opath && cd ../ && rm -r ./build
package/cpp/ui.cpp DELETED
@@ -1,217 +0,0 @@
1
- #include <gtk/gtk.h>
2
- #include <webkit2/webkit2.h>
3
- #include <json/json.h>
4
- #include <iostream>
5
- #include <sstream>
6
- #include <string>
7
- #include <fstream>
8
- #include <thread>
9
- #include <sys/inotify.h>
10
- #include <unistd.h>
11
- #include <vector>
12
-
13
- struct AppData
14
- {
15
- GtkWidget *window;
16
- WebKitWebView *web_view;
17
- WebKitUserContentManager *content_manager;
18
- };
19
-
20
- static void handle_json_message(const Json::Value &json, AppData *user_data)
21
- {
22
- if (json.isMember("action") && json.isMember("data"))
23
- {
24
- std::string action = json["action"].asString();
25
- std::string data = json["data"].asString();
26
-
27
- // std::cout << action << std::endl;
28
-
29
- if (action == "setTitle")
30
- {
31
- gtk_window_set_title(GTK_WINDOW(user_data->window), data.c_str());
32
- }
33
- else if (action == "log")
34
- {
35
- g_print("%s\n", data.c_str());
36
- }
37
- else if (action == "HTML")
38
- {
39
- webkit_web_view_load_html(user_data->web_view, data.c_str(), NULL);
40
- g_print("SETUP::HTML");
41
- }
42
- else if (action == "JS")
43
- {
44
- webkit_web_view_run_javascript(user_data->web_view, data.c_str(), NULL, NULL, NULL);
45
- }
46
- else if (action == "JS2")
47
- {
48
- const char *js_code = g_strdup_printf("%s;", data.c_str());
49
- WebKitUserScript *user_script = webkit_user_script_new(js_code,
50
- WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
51
- WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START,
52
- NULL, NULL);
53
- webkit_user_content_manager_add_script(user_data->content_manager, user_script);
54
- }
55
- }
56
- else
57
- {
58
- g_print("Invalid JSON format: 'action' and 'data' fields are required\n");
59
- }
60
- }
61
-
62
- static void js_callback(WebKitUserContentManager *manager,
63
- WebKitJavascriptResult *js_result,
64
- gpointer user_data)
65
- {
66
- JSCValue *value = webkit_javascript_result_get_js_value(js_result);
67
- if (jsc_value_is_string(value))
68
- {
69
- char *str_value = jsc_value_to_string(value);
70
-
71
- Json::Value root;
72
- Json::CharReaderBuilder builder;
73
- std::string errors;
74
- std::istringstream json_stream(str_value);
75
- bool success = Json::parseFromStream(builder, json_stream, &root, &errors);
76
-
77
- if (success)
78
- {
79
- handle_json_message(root, static_cast<AppData *>(user_data));
80
- }
81
- else
82
- {
83
- g_print("%s", str_value);
84
- }
85
-
86
- g_free(str_value);
87
- }
88
- }
89
-
90
- void watch_file(const std::string &file_path, AppData *app_data)
91
- {
92
- int inotify_fd = inotify_init();
93
- if (inotify_fd < 0)
94
- {
95
- perror("inotify_init");
96
- return;
97
- }
98
-
99
- int watch_fd = inotify_add_watch(inotify_fd, file_path.c_str(), IN_MODIFY);
100
- if (watch_fd < 0)
101
- {
102
- perror("inotify_add_watch");
103
- close(inotify_fd);
104
- return;
105
- }
106
-
107
- const size_t event_size = sizeof(struct inotify_event);
108
- const size_t buf_len = 1024 * (event_size + 16);
109
- std::vector<char> buffer(buf_len);
110
-
111
- while (true)
112
- {
113
- int length = read(inotify_fd, buffer.data(), buf_len);
114
- if (length < 0)
115
- {
116
- perror("read");
117
- break;
118
- }
119
-
120
- for (int i = 0; i < length;)
121
- {
122
- struct inotify_event *event = reinterpret_cast<struct inotify_event *>(&buffer[i]);
123
- if (event->mask & IN_MODIFY)
124
- {
125
- std::ifstream file(file_path);
126
- std::stringstream buffer;
127
- buffer << file.rdbuf();
128
- std::string content = buffer.str();
129
- file.close();
130
-
131
- if (!content.empty())
132
- {
133
- Json::Value root;
134
- Json::CharReaderBuilder builder;
135
- std::string errors;
136
- std::istringstream json_stream(content);
137
- bool success = Json::parseFromStream(builder, json_stream, &root, &errors);
138
-
139
- // std::cout << "CONTENT DETECTED" << std::endl;
140
-
141
- if (success)
142
- {
143
- handle_json_message(root, app_data);
144
- }
145
- else
146
- {
147
- g_print("Failed to parse JSON string: %s\n", errors.c_str());
148
- }
149
-
150
- std::ofstream clear_file(file_path, std::ofstream::out | std::ofstream::trunc);
151
- clear_file.close();
152
- }
153
- }
154
- i += event_size + event->len;
155
- }
156
- }
157
-
158
- close(watch_fd);
159
- close(inotify_fd);
160
- }
161
-
162
- int main(int argc, char **argv)
163
- {
164
- if (argc != 2)
165
- {
166
- g_print("Usage: %s <RUNID>\n", argv[0]);
167
- return 1;
168
- }
169
-
170
- const char *rid = argv[1];
171
- std::string file_path = "/tmp/" + std::string(rid) + ".ruw.ui.socket";
172
-
173
- AppData app_data;
174
-
175
- gtk_init(&argc, &argv);
176
-
177
- GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
178
- gtk_window_set_title(GTK_WINDOW(window), "WebKit Example");
179
- gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
180
-
181
- app_data.window = window;
182
-
183
- WebKitUserContentManager *content_manager = webkit_user_content_manager_new();
184
- webkit_user_content_manager_register_script_message_handler(content_manager, "external");
185
- g_signal_connect(content_manager, "script-message-received::external", G_CALLBACK(js_callback), &app_data);
186
- app_data.content_manager = content_manager;
187
-
188
- const char *js_code = g_strdup_printf("window.RUNID = \"%s\";", rid);
189
- WebKitUserScript *user_script = webkit_user_script_new(js_code,
190
- WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
191
- WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START,
192
- NULL, NULL);
193
- webkit_user_content_manager_add_script(content_manager, user_script);
194
-
195
- WebKitWebView *web_view = WEBKIT_WEB_VIEW(webkit_web_view_new_with_user_content_manager(content_manager));
196
- gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(web_view));
197
- app_data.web_view = web_view;
198
-
199
- webkit_web_view_load_html(web_view, "Loading...", NULL);
200
-
201
- GIOChannel *channel = g_io_channel_unix_new(fileno(stdin));
202
- GIOFlags flags = static_cast<GIOFlags>(g_io_channel_get_flags(channel) | G_IO_FLAG_NONBLOCK);
203
- g_io_channel_set_flags(channel, flags, NULL);
204
-
205
- g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
206
-
207
- std::thread watch_thread(watch_file, file_path, &app_data);
208
-
209
- g_print("INIT::READY");
210
-
211
- gtk_widget_show_all(window);
212
- gtk_main();
213
-
214
- watch_thread.detach();
215
-
216
- return 0;
217
- }
package/cpp/ui1.cpp DELETED
@@ -1,101 +0,0 @@
1
- #include <gtk/gtk.h>
2
- #include <webkit2/webkit2.h>
3
- #include <json/json.h>
4
-
5
- struct AppData {
6
- const char* url;
7
- GtkWidget* window;
8
- };
9
-
10
- static void handle_json_message(const Json::Value& json, AppData* user_data) {
11
- // Check if the JSON object has the "action" and "data" fields
12
- if (json.isMember("action") && json.isMember("data")) {
13
- std::string action = json["action"].asString();
14
- std::string data = json["data"].asString();
15
-
16
- // Perform actions based on the received data
17
- if (action == "setTitle") {
18
- // Set the GTK window's title
19
- gtk_window_set_title(GTK_WINDOW(user_data->window), data.c_str());
20
- } else if (action == "log") {
21
- // Set the GTK window's title
22
- g_print("%s\n", data.c_str());
23
- } else {
24
- // Handle other actions as needed
25
- }
26
- } else {
27
- // Invalid JSON format
28
- g_print("Invalid JSON format: 'action' and 'data' fields are required\n");
29
- }
30
- }
31
-
32
- static void js_callback(WebKitUserContentManager* manager,
33
- WebKitJavascriptResult* js_result,
34
- gpointer user_data) {
35
- JSCValue* value = webkit_javascript_result_get_js_value(js_result);
36
- if (jsc_value_is_string(value)) {
37
- char* str_value = jsc_value_to_string(value);
38
-
39
- Json::Value root;
40
- Json::CharReaderBuilder builder;
41
- std::string errors;
42
- std::istringstream json_stream(str_value);
43
- bool success = Json::parseFromStream(builder, json_stream, &root, &errors);
44
-
45
- if (success) {
46
- // Handle the incoming JSON message
47
- handle_json_message(root, static_cast<AppData*>(user_data));
48
- } else {
49
- g_print("%s", str_value);
50
- // g_print("Failed to parse JSON string: %s\n", errors.c_str());
51
- }
52
-
53
- g_free(str_value);
54
- }
55
- }
56
-
57
-
58
- int main(int argc, char** argv) {
59
- if (argc != 3) {
60
- g_print("Usage: %s <URL> <RUNID>\n", argv[0]);
61
- return 1;
62
- }
63
-
64
- const char* url = argv[1];
65
- const char* rid = argv[2];
66
-
67
- AppData app_data;
68
- app_data.url = url;
69
-
70
- gtk_init(&argc, &argv);
71
-
72
- GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
73
- gtk_window_set_title(GTK_WINDOW(window), "WebKit Example");
74
- gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
75
-
76
- app_data.window = window;
77
-
78
- WebKitUserContentManager* content_manager = webkit_user_content_manager_new();
79
- webkit_user_content_manager_register_script_message_handler(content_manager, "external");
80
- g_signal_connect(content_manager, "script-message-received::external", G_CALLBACK(js_callback), &app_data);
81
-
82
- const char* js_code = g_strdup_printf("window.RUNID = \"%s\";", rid);
83
- WebKitUserScript* user_script = webkit_user_script_new(js_code,
84
- WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
85
- WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START,
86
- NULL, NULL);
87
- webkit_user_content_manager_add_script(content_manager, user_script);
88
-
89
- WebKitWebView* web_view = WEBKIT_WEB_VIEW(webkit_web_view_new_with_user_content_manager(content_manager));
90
- gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(web_view));
91
-
92
- webkit_web_view_load_uri(web_view, url);
93
-
94
- g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
95
-
96
- gtk_widget_show_all(window);
97
-
98
- gtk_main();
99
-
100
- return 0;
101
- }