Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
bd89a19
cmarkit: Add possibility to offset locations
panglesd Feb 16, 2026
2b3b3e4
Move Ast helper out of compile
panglesd Feb 17, 2026
1ec94b0
Errors setup (and missing loc_offset)
panglesd Feb 17, 2026
2e3a91f
More setting up of errors (and more loc_offset)
panglesd Feb 17, 2026
e202571
Cmarkit: fix attributes line position
panglesd Feb 17, 2026
3b307f6
Implement "duplicated ID" and "Unreadable file" errors
panglesd Feb 17, 2026
16a0594
Subfile locations
panglesd Feb 17, 2026
944da13
WIP
panglesd Feb 17, 2026
99a0482
Actions: Splitting parsing and execution
panglesd Feb 20, 2026
85bb548
Warnings: Trying using grace
panglesd Feb 20, 2026
c0234cd
WIP
panglesd Feb 21, 2026
b902da0
Too many things:
panglesd Feb 22, 2026
a44b0b9
Fix locations of block quotes
panglesd Feb 23, 2026
3e14573
Move bol to ast and other check things
panglesd Feb 23, 2026
48205c9
Be more resistant to "no location" that makes grace raise
panglesd Feb 23, 2026
f13a31b
Less none locations
panglesd Feb 23, 2026
4f4764b
Check the remaining actions
panglesd Feb 23, 2026
cef8107
Fix some checks and do all checks
panglesd Feb 23, 2026
bbf802d
Fix `Attrs_span` location
panglesd Feb 23, 2026
248685f
Fix "Wrong type" error
panglesd Feb 23, 2026
a49dbb6
Improve the warning situation
panglesd Feb 24, 2026
aaa66b0
Adding warning for change-page action
panglesd Feb 24, 2026
671c728
More location info, and more warning
panglesd Feb 24, 2026
a0ad0a0
More loc and warning improvements
panglesd Feb 24, 2026
139ec19
Fix block quote marker loc issue mentioned by dbuenzli
panglesd Feb 24, 2026
670b023
More warnings, turn errors into warnings
panglesd Feb 24, 2026
cbc8283
NOT Finish diagnoses
panglesd Feb 25, 2026
0d4ef8e
Check non standard attributes presence
panglesd Feb 25, 2026
acb437a
Promote tests and fix some of those
panglesd Feb 25, 2026
037f7d0
Remove unreachable code path
panglesd Feb 25, 2026
d83fb78
Add grace dependency
panglesd Feb 25, 2026
1601f40
Include warnings in serve mode
panglesd Feb 25, 2026
e8b2b49
Compatibility code
panglesd Feb 25, 2026
7ff80e2
Added changelog entry for #213
panglesd Feb 25, 2026
3298ce4
Fix weak variable that was supposed to be sgroumphed
panglesd Feb 25, 2026
c1c2973
Include css in previewer
panglesd Feb 25, 2026
bf02a55
Add Attribute key removal
panglesd Feb 26, 2026
99663eb
Multiple things:
panglesd Feb 26, 2026
1e264cb
Add pause check
panglesd Feb 26, 2026
5833774
Fix use of dataurls
panglesd Feb 26, 2026
0bda543
Update docs
panglesd Feb 26, 2026
26badff
Update more docs wrt external-ids
panglesd Feb 26, 2026
fd9c9e0
Add more test for warnings
panglesd Feb 26, 2026
aad2813
Fix UnusedArgument report
panglesd Feb 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Added

- Helpful warnings at compile-time (#213)

## [v0.9.0] Manim Black (Tuesday 19th February, 2026)

### Added
Expand Down
1 change: 1 addition & 0 deletions docs/_ext/slipshowexample.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def visit_slipshow_example_node_html(self, node):
<div class="editor-preview-container">
<div class="editor"></div>
<div class="preview"></div>
<pre class="errors-el" style="background:black; margin:0; color: white; overflow-y:scroll"></pre>
</div>
<div class="source" style="display:none">""")
# Write raw, *escaped* text so it appears exactly as typed
Expand Down
20 changes: 5 additions & 15 deletions docs/_static/style.css
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
.right-panel1.active_panel, .right-panel2.active_panel {
z-index: 1;
}
.right-panel1, .right-panel2 {
z-index: 0;
width:100%;
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
border:0;
}

.preview {
position: relative;
Expand Down Expand Up @@ -64,15 +51,18 @@
.entry.show-presentation .preview,
.entry.show-editor .editor,
.entry.show-both .preview,
.entry.show-both .editor {
.entry.show-both .editor,
.entry.show-warnings .editor,
.entry.show-warnings .errors-el {
opacity: 1;
position: relative;
pointer-events: all;
}

.show-editor > .tabs > .editor-button,
.show-presentation > .tabs > .pres-button,
.show-both > .tabs > .both-button {
.show-both > .tabs > .both-button,
.show-warnings > .tabs > .warnings-button {
background: aliceblue;
}
.running-example.fullscreen {
Expand Down
129 changes: 70 additions & 59 deletions docs/doc-repl/main.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
open Code_mirror

let view ~dimension ~preview_el ~editor_el starting =
let view ~dimension ~preview_el ~errors_el ~editor_el starting =
let open Editor in
let basic_setup = Jv.get Jv.global "__CM__basic_setup" |> Extension.of_jv in
let dark_mode =
Expand All @@ -14,6 +14,7 @@ let view ~dimension ~preview_el ~editor_el starting =
let frontmatter =
(Resolved
{
external_ids = [];
toplevel_attributes = None;
math_link = None;
theme = None;
Expand All @@ -32,7 +33,8 @@ let view ~dimension ~preview_el ~editor_el starting =
basic_setup;
markdown_extension;
dark_mode;
Slipshow_communication.slipshow_plugin ~frontmatter preview_el;
Slipshow_communication.slipshow_plugin ~frontmatter ~errors_el
preview_el;
|]
()
in
Expand All @@ -42,74 +44,83 @@ let view ~dimension ~preview_el ~editor_el starting =

let ( !! ) = Jstr.v

let do_ ~dimension ~editor_el ~preview_el starting =
let _view = view ~dimension ~preview_el ~editor_el starting in
let do_ ~dimension ~editor_el ~preview_el ~errors_el starting =
let _view : Editor.View.t =
view ~dimension ~preview_el ~errors_el ~editor_el starting
in
()

type mode = Show_editor | Show_presentation | Show_both

let all_modes = [ Show_both; Show_editor; Show_presentation ]

let handle_elem =
fun el () ->
let open Brr in
let dimension =
El.at !!"dimension" el |> Option.map Jstr.to_string |> fun x ->
Option.bind x (fun s ->
match Slipshow.Frontmatter.Dimension.of_string s with
| Ok x -> Some x
| Error _ -> None)
in
let ffbs_unsafe c = El.find_first_by_selector ~root:el !!c |> Option.get in
let content =
let source = ffbs_unsafe ".source" in
Jv.get (Brr.El.to_jv source) "textContent" |> Jv.to_string
in
let editor_el = ffbs_unsafe ".editor" in
let errors_el = ffbs_unsafe ".errors-el" in
let preview_el = ffbs_unsafe ".preview" in
let editor_button = ffbs_unsafe ".editor-button" in
let pres_button = ffbs_unsafe ".pres-button" in
let both_button = ffbs_unsafe ".both-button" in
let fullscreen_button = ffbs_unsafe ".fullscreen-button" in
Comment on lines +67 to +78
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard missing child elements instead of Option.get hard-failing.

Line 67 uses Option.get; one missing selector (e.g., .errors-el) will throw and abort setup for docs examples. Prefer skipping invalid blocks gracefully.

♻️ Suggested hardening
-  let ffbs_unsafe c = El.find_first_by_selector ~root:el !!c |> Option.get in
+  let ffbs c = El.find_first_by_selector ~root:el !!c in
...
-  let content =
-    let source = ffbs_unsafe ".source" in
-    Jv.get (Brr.El.to_jv source) "textContent" |> Jv.to_string
-  in
-  let editor_el = ffbs_unsafe ".editor" in
-  let errors_el = ffbs_unsafe ".errors-el" in
-  let preview_el = ffbs_unsafe ".preview" in
+  match (ffbs ".source", ffbs ".editor", ffbs ".errors-el", ffbs ".preview") with
+  | Some source, Some editor_el, Some errors_el, Some preview_el ->
+      let content =
+        Jv.get (Brr.El.to_jv source) "textContent" |> Jv.to_string
+      in
+      (* existing logic *)
+      do_ ~dimension ~preview_el ~editor_el ~errors_el content
+  | _ -> ()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/doc-repl/main.ml` around lines 67 - 78, The code uses ffbs_unsafe which
calls Option.get and will raise if a selector is missing; change this to safely
handle missing elements by returning an option and guarding consumers: modify
ffbs_unsafe (or replace calls) to use Option.bind/Option.map (or Option.value
~default) instead of Option.get, then update usages of ffbs_unsafe for
".source", ".editor", ".errors-el", ".preview", ".editor-button",
".pres-button", ".both-button", and ".fullscreen-button" to pattern-match or
skip rendering when the result is None so the docs setup does not abort when a
child selector is absent.

let () =
let fullscreen = ref false in
Ev.(listen click)
(fun _ ->
fullscreen := not !fullscreen;
El.set_class !!"fullscreen" !fullscreen el)
(El.as_target fullscreen_button)
|> ignore
in
let new_el = ffbs_unsafe ".entry" in
(* See also the python file _ext/slipshowexample.py *)
let mode_to_string = function
| Show_editor -> Jstr.v "show-editor"
| Show_presentation -> Jstr.v "show-presentation"
| Show_both -> Jstr.v "show-both"
in
let () =
let set_class v =
let set v b = El.set_class (mode_to_string v) b new_el in
List.iter (fun m -> set m false) all_modes;
set v true
in
let listen v el =
Ev.(listen click) (fun _ -> set_class v) (El.as_target el) |> ignore
in
listen Show_editor editor_button;
listen Show_presentation pres_button;
listen Show_both both_button
in
do_ ~dimension ~preview_el ~editor_el ~errors_el content

let () =
let _ =
Brr.Ev.listen Brr.Ev.load
(fun _ ->
let () =
match Brr.El.find_first_by_selector !!".running-example" with
| None -> ()
| Some _ ->
Brr.El.append_children
(Brr.Document.body Brr.G.document)
[ Brr.El.style [ Brr.El.txt' Ansi.css ] ]
in
let _ =
Brr.El.fold_find_by_selector
(fun el () ->
let open Brr in
let dimension =
El.at !!"dimension" el |> Option.map Jstr.to_string |> fun x ->
Option.bind x (fun s ->
match Slipshow.Frontmatter.String_to.dimension s with
| Ok x -> Some x
| Error _ -> None)
in
let ffbs_unsafe c =
El.find_first_by_selector ~root:el !!c |> Option.get
in
let content =
let source = ffbs_unsafe ".source" in
Jv.get (Brr.El.to_jv source) "textContent" |> Jv.to_string
in
let editor_el = ffbs_unsafe ".editor" in
let preview_el = ffbs_unsafe ".preview" in
let editor_button = ffbs_unsafe ".editor-button" in
let pres_button = ffbs_unsafe ".pres-button" in
let both_button = ffbs_unsafe ".both-button" in
let fullscreen_button = ffbs_unsafe ".fullscreen-button" in
let () =
let fullscreen = ref false in
Ev.(listen click)
(fun _ ->
fullscreen := not !fullscreen;
El.set_class !!"fullscreen" !fullscreen el)
(El.as_target fullscreen_button)
|> ignore
in
let new_el = ffbs_unsafe ".entry" in
(* See also the python file _ext/slipshowexample.py *)
let mode_to_string = function
| Show_editor -> Jstr.v "show-editor"
| Show_presentation -> Jstr.v "show-presentation"
| Show_both -> Jstr.v "show-both"
in
let () =
let set_class v =
let set v b = El.set_class (mode_to_string v) b new_el in
List.iter (fun m -> set m false) all_modes;
set v true
in
let listen v el =
Ev.(listen click) (fun _ -> set_class v) (El.as_target el)
|> ignore
in
listen Show_editor editor_button;
listen Show_presentation pres_button;
listen Show_both both_button
in
do_ ~dimension ~preview_el ~editor_el content)
!!".running-example" ()
Brr.El.fold_find_by_selector handle_elem !!".running-example" ()
in
())
(Brr.Window.as_target Brr.G.window)
Expand Down
5 changes: 5 additions & 0 deletions docs/frontmatter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,8 @@ The current options for the frontmatter are:
a theme, corresponding to the name of a file in `this list
<https://github.com/highlightjs/highlight.js/tree/5697ae5187746c24732e62cd625f3f83004a44ce/src/styles>`_,
stripped from its extension.

- ``external-ids``, for telling the slipshow compiler which ``ids`` will be
present even if they do not seem to be present in the document. This is just
in order to silence some warnings. This is useful when including svgs or math
where some IDs are given.
18 changes: 6 additions & 12 deletions docs/manim.rst

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions docs/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,17 @@ respectively assign an identifier, and a class.

This allows to easily make them target of actions. For instance, one can use the ``pause`` action with a target to reveal content bit by bit. The ``reveal`` action and ``unrevealed`` class are also useful.

Remember to use the ``external-ids`` field of the frontmatter to tell the
compiler not to warn you that it cannot find the given ids.

.. slipshow-example::
:visible: both
:dimension: 4:3

---
external-ids: pause1 pause2
---

# Some title to make it more realistic

```math
Expand Down
5 changes: 4 additions & 1 deletion docs/tikz.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ dynamics with actions:

---
toplevel-attributes: slip enter=~duration:0 unreveal="c c-edges"
external-ids: c c-edges
---

![](triangle.svg){style="width:75%"}
Expand All @@ -113,14 +114,16 @@ dynamics with actions:

{reveal=c-edges}

Here is the final result!
The ``external-ids`` field of the frontmatter tells the compiler not to warn you
that it cannot find the given ids. Here is the final result!

.. slipshow-example::
:visible: presentation
:dimension: 4:3

---
toplevel-attributes: slip enter=~duration:0 unreveal="c c-edges"
external-ids: c c-edges
---

<!-- inlining the svg for simplicity -->
Expand Down
2 changes: 2 additions & 0 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
(depends
(ocaml (>= 4.14))
dune
(grace (>= 0.3.0))
(crunch :with-dev-setup)
(lambdasoup :with-test)
(cmdliner (>= 1.3.0))
Expand All @@ -45,6 +46,7 @@
sexplib
ppx_sexp_conv
ppx_deriving_yojson
(ansi (>= 0.7.0))
(odoc :with-doc)
(ocamlformat
(and :with-dev-setup (= 0.27.0))))
Expand Down
2 changes: 1 addition & 1 deletion example/funocaml-2025/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dimension: 16:9
> {slip #part1 style="width:49%; height:" speaker-note=initial-sn}
> {include src="slipshow.md"}
>
> {pause clear=draw-links reveal=surrprise}
> {pause reveal=surrprise}
>
> {slip #my-part2 style="width:49%"}
> {include src="three-simple-steps.md"}
Expand Down
2 changes: 1 addition & 1 deletion example/funocaml-2025/slipshow.md
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ Say: "Slipshow has support for videos"
}
</style>

{#video-demo .addons .block external}
{#video-demo .addons .block}
> ![](c6.mp4){style=width:100% #videoelem}

{play-media=videoelem}
Expand Down
2 changes: 2 additions & 0 deletions slipshow.opam
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ bug-reports: "https://github.com/panglesd/slipshow/issues"
depends: [
"ocaml" {>= "4.14"}
"dune" {>= "3.6"}
"grace" {>= "0.3.0"}
"crunch" {with-dev-setup}
"lambdasoup" {with-test}
"cmdliner" {>= "1.3.0"}
Expand All @@ -34,6 +35,7 @@ depends: [
"sexplib"
"ppx_sexp_conv"
"ppx_deriving_yojson"
"ansi" {>= "0.7.0"}
"odoc" {with-doc}
"ocamlformat" {with-dev-setup & = "0.27.0"}
]
Expand Down
Loading
Loading