Google Slides API client for OCaml
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

OCaml 97.2%
Dune 0.9%
Other 1.9%
2 1 0

Clone this repository

https://tangled.org/gazagnaire.org/ocaml-gslides https://tangled.org/did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-gslides
git@git.recoil.org:gazagnaire.org/ocaml-gslides git@git.recoil.org:did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-gslides

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

gslides#

Google Slides API client for OCaml.

gslides implements a small, opinionated read-only slice of the Google Slides v1 REST API: fetching a presentation's structure (slides, text, bullets, speaker notes, images) and rendering it to either Marp-flavored markdown or polylux-flavored Typst, both intended for version-control. Authentication is delegated to gauth; reading requires the .../auth/presentations.readonly OAuth scope (plus drive.readonly if you want comments).

Installation#

Install with opam:

$ opam install gslides

If opam cannot find the package, it may not yet be released in the public opam-repository. Add the overlay repository, then install it:

$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install gslides

Usage#

The main entry points are Gslides.get, Gslides.Marp.of_presentation, and Gslides.Typst.of_presentation:

let fetch_md http ~token ~presentation_id =
  match Gslides.get http ~token presentation_id with
  | Error (`Msg m) -> Error m
  | Ok p -> Ok (Gslides.Marp.of_presentation p)

Wire it up with gauth and Eio for a full flow:

let run env ~key_path ~presentation_id =
  Eio.Switch.run @@ fun sw ->
  let http = Requests.v ~sw env in
  let clock = Eio.Stdenv.clock env in
  match Gauth.Service_account.of_file key_path with
  | Error (`Msg m) -> failwith m
  | Ok key ->
      match
        Gauth.Service_account.token http ~clock
          ~scopes:[ Gslides.scope_readonly ] key
      with
      | Error (`Msg m) -> failwith m
      | Ok token ->
          match Gslides.get http ~token presentation_id with
          | Ok p -> Fmt.pr "%s" (Gslides.Marp.of_presentation p)
          | Error (`Msg m) -> Fmt.pr "fetch failed: %s@." m

Markdown vs Typst#

Two renderers consume the same parsed Presentation.t:

  • Marp (Gslides.Marp.of_presentation) emits markdown with a YAML frontmatter, --- between slides, level-1 headings as slide titles, native bullet/numbered lists, and HTML escape hatches (<u>, <sup>, <span style="color: ...">) for features without a CommonMark form. Best for "review the deck in a PR diff".
  • Typst (Gslides.Typst.of_presentation) emits Typst source using polylux: #slide[...], #text(weight: "bold")[...], #table(...), #image("url"), #speaker-note[...]. Best for "compile to a typeset PDF".
let to_typst http ~token ~presentation_id =
  match Gslides.get http ~token presentation_id with
  | Error (`Msg m) -> Error m
  | Ok p -> Ok (Gslides.Typst.of_presentation p)

The polylux import is version-pinned (currently 0.4.0); the value is exposed as Gslides.Typst.polylux_version so callers can confirm the dependency they emit.

Comments#

Slides comments live on the underlying Drive file, so fetching them needs the drive.readonly scope in addition to the Slides scope. Both renderers accept an optional ~comments argument and emit them as footnotes, anchored to the slide they reference:

let to_md_with_comments http ~token ~presentation_id =
  match Gslides.get http ~token presentation_id with
  | Error (`Msg m) -> Error m
  | Ok p ->
      match Gslides.Comments.list http ~token presentation_id with
      | Error (`Msg m) -> Error m
      | Ok cs -> Ok (Gslides.Marp.of_presentation ~comments:cs p)

Comments whose anchor doesn't reference any slide land in a trailing ## Comments section.

Scopes#

let readonly = Gslides.scope_readonly
let readwrite = Gslides.scope_readwrite
let comments_scope = Gslides.Comments.scope

HTTP errors surface with the response status in the Msg payload: 401 for invalid/expired tokens, 403 for missing scopes or no access, 404 for unknown presentation IDs. Oversized error bodies (e.g. a CDN's 502 HTML) are truncated before being included.

CLI#

The package installs a gslides binary mirroring the gdocs/gsheets CLI shape:

$ gslides install                  # one-time OAuth client setup
$ gslides login                    # authorize your Google account
$ gslides get  <presentation-id>
$ gslides md   <presentation-id> [--comments]
$ gslides typst <presentation-id> [--comments]

What's not exported#

Slides is a layout engine; markdown and Typst are text engines. The renderer captures structure (slides, titles, bullets, speaker notes), inline style (bold/italic/strike/link/color/sup/sub), and image references. It drops spatial information (positions, sizes, rotations), shape-as-decoration (callouts, flowchart shapes, connector lines), and animations (which the Slides API doesn't expose anyway). Image bytes are not exported -- the Slides API gives short-lived contentUrls; stable image references are a follow-up.

Licence#

MIT