Skip to content
/ troll Public

Libraries for GNOME JavaScript (GJS)

License

Notifications You must be signed in to change notification settings

sonnyp/troll

Repository files navigation

troll

troll is an implementation of common JavaScript APIs for gjs and some helpers.

See this gjs issue for context.

This is not API stable and no release were made. Use at your own risk. Contributions welcome.

Status

  • WebSocket src
  • fetch src
    • request
      • method/url
      • headers
      • text body
    • response
      • status/statusText/ok
      • text() / json()
  • base64
  • timers builtin gjs 1.72
  • console builtin gjs 1.70
  • TextDecoder/TextEncoder builtin gjs 1.70

Goals

  1. Provide a familiar environment for building GNOME applications
  2. Allow application developers to use third party libraries
  3. Encourage Shell extension developers to make flatpak apps instead

Tested with

globals

You can register all globals with

import "./troll/src/globals.js";

// fetch(...)
// new WebSocket(...)
// atob(...)
// btoa(...)

resolve

Arguments

  • base <string> a base uri
  • uri <string> a path or uri, can be absolute or relative

Returns <string> the resolved uri

Similar to import.meta.resolve or new URL(url, base).

import { resolve } from "./troll/src/main.js";

console.log(resolve(import.meta.url, "./xml.js"));
// resource:///some/path/xml.js
// or
// file:///some/path/xml.js

console.log(resolve("http://foo.example", "http://bar.example"));
// http://bar.example

resolveParse

Arguments

  • base <string> a base uri
  • uri <string> a path or uri, can be absolute or relative

Returns <GLib.Uri> the resolved uri

Same as resolve but returns a GLib.Uri instead of a string.

promiseTask

Arguments

Returns <Promise> resolves or rejects with the result of the finish function

Run a Gio async operation and return a promise that resolve with the result of finish method or rejects.

See also Gio._promisify

Examples

import { promiseTask } from "./troll/src/main.js";
import Gio from "gi://Gio";

(async () => {
  const file = Gio.File.new_for_path("/tmp/foobar");

  // see https://developer.gnome.org/gio/stable/GFile.html#g-file-replace-readwrite-async
  const stream = await promisetask(file, "readwrite_async", "readwrite_finish");
  log(stream);
})().catch(logError);

build

Arguments

Returns <Object>

A helper function to easily load, build and bind a GTK XML interface. Here is an example

window.js
#!/usr/bin/env -S gjs -m

import Gtk from "gi://Gtk?version=4.0";
import { build, resolve } from "./troll/src/main.js";

const app = new Gtk.Application({
  application_id: "hello.world",
});

app.connect("activate", () => {
  const { window, button } = build(resolve(import.meta.url, "./window.xml"), {
    onclicked,
    app,
  });
  button.label = "World";
  window.present();
});

app.runAsync(null);

function onclicked(button) {
  console.log("Hello", button.label);
  app.activeWindow?.close();
}
window.xml
<?xml version="1.0" encoding="UTF-8" ?>
<interface>
  <requires lib="gtk" version="4.0" />
  <object class="GtkApplicationWindow" id="window">
    <property
      name="title"
      bind-source="app"
      bind-property="application-id"
      bind-flags="sync-create"
    />
    <binding name="application">
      <constant>app</constant>
    </binding>
    <property name="default-width">400</property>
    <property name="default-height">400</property>
    <child>
      <object class="GtkButton" id="button">
        <signal name="clicked" handler="onclicked" />
      </object>
    </child>
  </object>
</interface>
window.blp
using Gtk 4.0;

ApplicationWindow window {
  title: bind-property app.application-id;
  application: bind app;
  default-width: 400;
  default-height: 400;

  Button button {
    clicked => $onclicked();
  }
}

ℹ️ build is for <interface/> only, for <template/>, use GObject.registerClass

gsx

gsx is a small function to write Gtk.

See gsx-demo for setup and instructions with Babel.

You can use it as a jsx pragma with babel, TypeScript, SWC or Rome like so:

import Gtk from "gi://Gtk?version=4.0";
import gsx from "./troll/src/main.js";

/** @jsx gsx.h */
/** @jsxFrag gsx.Fragment */

export default function MyButton() {
  return (
    <Gtk.Button connect-clicked={() => log("clicked")} halign={Gtk.Align.END}>
      <Gtk.Image icon-name="folder-open-symbolic" pixel-size={48} />
    </Gtk.Button>
  );
}

GJS doesn't support source map yet. We recommend babel as it is the only option capable of retaining line numbers.

Equivalent without gsx
import Gtk from "gi://Gtk?version=4.0";

export default function MyButton() {
  const image = new Gtk.Image({
    "icon-name": "folder-open-synbolic",
    "pixel-size": 48,
  });

  const button = new Gtk.Button({
    halign: Gtk.Align.END,
  });
  button.connect("signal", () => {
    log("clicked!");
  });

  button.add(image);
}
Usage without a compiler
import Gtk from "gi://Gtk?version=4.0";
import gsx from "./troll/src/main.js";

const { Button, Align, Image } = Gtk;

export default function MyButton() {
  return gsx(
    Button,
    {
      "connect-clicked": () => log("clicked"),
      halign: Align.END,
    },
    gsx(Image, {
      "icon-name": "folder-open-synbolic",
      "pixel-size": 48,
    }),
  );
}

About

Libraries for GNOME JavaScript (GJS)

Topics

Resources

License

Stars

Watchers

Forks

Languages