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