{"id":15648175,"url":"https://github.com/sonnyp/troll","last_synced_at":"2025-05-12T15:03:24.085Z","repository":{"id":44449680,"uuid":"210328322","full_name":"sonnyp/troll","owner":"sonnyp","description":"Libraries for GNOME JavaScript (GJS)","archived":false,"fork":false,"pushed_at":"2025-03-28T09:20:50.000Z","size":628,"stargazers_count":47,"open_issues_count":12,"forks_count":8,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-31T23:36:27.099Z","etag":null,"topics":["gjs","gnome","gtk","javascript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sonnyp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-23T10:32:54.000Z","updated_at":"2025-03-28T09:20:55.000Z","dependencies_parsed_at":"2024-10-03T12:24:04.732Z","dependency_job_id":"4d45dbc1-0bcf-45e2-9b7c-7e06b61bff0b","html_url":"https://github.com/sonnyp/troll","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonnyp%2Ftroll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonnyp%2Ftroll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonnyp%2Ftroll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonnyp%2Ftroll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sonnyp","download_url":"https://codeload.github.com/sonnyp/troll/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253762075,"owners_count":21960277,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gjs","gnome","gtk","javascript"],"created_at":"2024-10-03T12:23:59.320Z","updated_at":"2025-05-12T15:03:24.028Z","avatar_url":"https://github.com/sonnyp.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# troll\n\ntroll is an implementation of common JavaScript APIs for [gjs](https://gitlab.gnome.org/GNOME/gjs) and some helpers.\n\nSee [this gjs issue](https://gitlab.gnome.org/GNOME/gjs/-/issues/265) for context.\n\nThis is not API stable and no release were made. Use at your own risk.\nContributions welcome.\n\n## Status\n\n- WebSocket [src](src/std/WebSocket.js)\n- fetch [src](src/std/fetch.js)\n  - request\n    - method/url\n    - headers\n    - text body\n  - response\n    - status/statusText/ok\n    - text() / json()\n- base64\n  - atob [src](src/std/base64.js)\n  - btoa [src](src/std/base64.js)\n- ~~timers~~ builtin gjs 1.72\n- ~~console~~ builtin gjs 1.70\n- ~~TextDecoder/TextEncoder~~ builtin gjs 1.70\n\n## Goals\n\n1. Provide a familiar environment for building GNOME applications\n2. Allow application developers to use third party libraries\n3. Encourage Shell extension developers to make flatpak apps instead\n\n## Tested with\n\n- [xmpp.js](https://github.com/xmppjs/xmpp.js)\n- [aria2.js](https://github.com/sonnyp/aria2.js)\n\n## globals\n\nYou can register all globals with\n\n```js\nimport \"./troll/src/globals.js\";\n\n// fetch(...)\n// new WebSocket(...)\n// atob(...)\n// btoa(...)\n```\n\n## resolve\n\nArguments\n\n- `base` [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) a base uri\n- `uri` [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) a path or uri, can be absolute or relative\n\nReturns [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) the resolved uri\n\nSimilar to `import.meta.resolve` or `new URL(url, base)`.\n\n```js\nimport { resolve } from \"./troll/src/main.js\";\n\nconsole.log(resolve(import.meta.url, \"./xml.js\"));\n// resource:///some/path/xml.js\n// or\n// file:///some/path/xml.js\n\nconsole.log(resolve(\"http://foo.example\", \"http://bar.example\"));\n// http://bar.example\n```\n\n## resolveParse\n\nArguments\n\n- `base` [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) a base uri\n- `uri` [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) a path or uri, can be absolute or relative\n\nReturns [\\\u003cGLib.Uri\\\u003e](https://gjs-docs.gnome.org/glib20~2.0/glib.uri) the resolved uri\n\nSame as `resolve` but returns a `GLib.Uri` instead of a `string`.\n\n## promiseTask\n\nArguments\n\n- `target` [\\\u003cGObject.object\\\u003e](https://gjs-docs.gnome.org/gobject20/gobject.object)\n- `method` [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type)\n- `finish` [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type)\n- `...args` the list of arguments to pass to `method`\n\nReturns [\\\u003cPromise\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) resolves or rejects with the result of the finish function\n\nRun a Gio async operation and return a promise that resolve with the result of finish method or rejects.\n\nSee also [Gio.\\_promisify](https://gjs.guide/guides/gjs/asynchronous-programming.html#promisify-helper)\n\nExamples\n\n```js\nimport { promiseTask } from \"./troll/src/main.js\";\nimport Gio from \"gi://Gio\";\n\n(async () =\u003e {\n  const file = Gio.File.new_for_path(\"/tmp/foobar\");\n\n  // see https://developer.gnome.org/gio/stable/GFile.html#g-file-replace-readwrite-async\n  const stream = await promisetask(file, \"readwrite_async\", \"readwrite_finish\");\n  log(stream);\n})().catch(logError);\n```\n\n\u003c!-- ## once(target, signal[, errorSignal])\n\n- `target` [\\\u003cGObject.object\\\u003e](https://gjs-docs.gnome.org/gobject20/gobject.object)\n- `signal` [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type)\n- `errorSignal` [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type)\n- Returns: [\\\u003cPromise\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)\n\nRegister a signal handler and remove it as soon as the signal is emitted. See also [connect](https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-connect).\n\nResolves with an array of params emitted by the signal.\n\nIf `errorSignal` is specified, an handler for it will be registered and the promise will rejects.\n\nExamples\n\n```js\nimport { once } from \"./troll/src/util.js\";\n\n(async () =\u003e {\n  const Button = new Gtk.Button({ label: \"Click Me\" });\n  await once(Button, \"clicked\");\n  console.log(\"clicked!\");\n})().catch(logError);\n``` --\u003e\n\n## build\n\nArguments\n\n- `uri` [\\\u003cstring\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type)\n- `params` [\\\u003cObject\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)\n\nReturns [\\\u003cObject\\\u003e](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)\n\nA helper function to easily load, build and bind a GTK XML interface. Here is an example\n\n\u003cdetails\u003e\n  \u003csummary\u003ewindow.js\u003c/summary\u003e\n\n```js\n#!/usr/bin/env -S gjs -m\n\nimport Gtk from \"gi://Gtk?version=4.0\";\nimport { build, resolve } from \"./troll/src/main.js\";\n\nconst app = new Gtk.Application({\n  application_id: \"hello.world\",\n});\n\napp.connect(\"activate\", () =\u003e {\n  const { window, button } = build(resolve(import.meta.url, \"./window.xml\"), {\n    onclicked,\n    app,\n  });\n  button.label = \"World\";\n  window.present();\n});\n\napp.runAsync(null);\n\nfunction onclicked(button) {\n  console.log(\"Hello\", button.label);\n  app.activeWindow?.close();\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ewindow.xml\u003c/summary\u003e\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e\n\u003cinterface\u003e\n  \u003crequires lib=\"gtk\" version=\"4.0\" /\u003e\n  \u003cobject class=\"GtkApplicationWindow\" id=\"window\"\u003e\n    \u003cproperty\n      name=\"title\"\n      bind-source=\"app\"\n      bind-property=\"application-id\"\n      bind-flags=\"sync-create\"\n    /\u003e\n    \u003cbinding name=\"application\"\u003e\n      \u003cconstant\u003eapp\u003c/constant\u003e\n    \u003c/binding\u003e\n    \u003cproperty name=\"default-width\"\u003e400\u003c/property\u003e\n    \u003cproperty name=\"default-height\"\u003e400\u003c/property\u003e\n    \u003cchild\u003e\n      \u003cobject class=\"GtkButton\" id=\"button\"\u003e\n        \u003csignal name=\"clicked\" handler=\"onclicked\" /\u003e\n      \u003c/object\u003e\n    \u003c/child\u003e\n  \u003c/object\u003e\n\u003c/interface\u003e\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003ewindow.blp\u003c/summary\u003e\n\n```css\nusing Gtk 4.0;\n\nApplicationWindow window {\n  title: bind-property app.application-id;\n  application: bind app;\n  default-width: 400;\n  default-height: 400;\n\n  Button button {\n    clicked =\u003e $onclicked();\n  }\n}\n```\n\n\u003c/details\u003e\n\n---\n\nℹ️ `build` is for `\u003cinterface/\u003e` only, for `\u003ctemplate/\u003e`, use [`GObject.registerClass`](https://gjs.guide/guides/gtk/3/14-templates.html#loading-the-template)\n\n## gsx\n\ngsx is a small function to write Gtk.\n\nSee [gsx-demo](./gsx-demo) for setup and instructions with Babel.\n\nYou can use it as a jsx pragma with [babel](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx), [TypeScript](https://www.typescriptlang.org/tsconfig#jsxFactory), [SWC](https://swc.rs/) or [Rome](https://rome.tools/) like so:\n\n```jsx\nimport Gtk from \"gi://Gtk?version=4.0\";\nimport gsx from \"./troll/src/main.js\";\n\n/** @jsx gsx.h */\n/** @jsxFrag gsx.Fragment */\n\nexport default function MyButton() {\n  return (\n    \u003cGtk.Button connect-clicked={() =\u003e log(\"clicked\")} halign={Gtk.Align.END}\u003e\n      \u003cGtk.Image icon-name=\"folder-open-symbolic\" pixel-size={48} /\u003e\n    \u003c/Gtk.Button\u003e\n  );\n}\n```\n\nGJS doesn't support source map yet. We recommend babel as it is the only option capable of [retaining line numbers](https://babeljs.io/docs/options#retainlines).\n\n\u003cdetails\u003e\n    \u003csummary\u003eEquivalent without gsx\u003c/summary\u003e\n\n```js\nimport Gtk from \"gi://Gtk?version=4.0\";\n\nexport default function MyButton() {\n  const image = new Gtk.Image({\n    \"icon-name\": \"folder-open-synbolic\",\n    \"pixel-size\": 48,\n  });\n\n  const button = new Gtk.Button({\n    halign: Gtk.Align.END,\n  });\n  button.connect(\"signal\", () =\u003e {\n    log(\"clicked!\");\n  });\n\n  button.add(image);\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eUsage without a compiler\u003c/summary\u003e\n\n```js\nimport Gtk from \"gi://Gtk?version=4.0\";\nimport gsx from \"./troll/src/main.js\";\n\nconst { Button, Align, Image } = Gtk;\n\nexport default function MyButton() {\n  return gsx(\n    Button,\n    {\n      \"connect-clicked\": () =\u003e log(\"clicked\"),\n      halign: Align.END,\n    },\n    gsx(Image, {\n      \"icon-name\": \"folder-open-synbolic\",\n      \"pixel-size\": 48,\n    }),\n  );\n}\n```\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsonnyp%2Ftroll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsonnyp%2Ftroll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsonnyp%2Ftroll/lists"}