#import "@preview/minicise:0.1.0": sheet #import "@preview/mitex:0.2.7": mitex #import "@preview/cmarker:0.1.10" // --------------------------------------------------------- configuration ---- #show: sheet.with( title: [Exercices de TP], course: [Objets connectés et robotique], semester: [L3 IFA, S5], date: [2026], author: [Vincent Lannurien], ) // the markdown source rendered as the body of this sheet #let md-source = "tp1.md" // set to `false` to drop the first page with the table of contents #let show-toc = true // ---------------------------------------------------------------- styles ---- #show figure.caption: set text(size: 0.9em, fill: luma(70)) // the outline picks up the headings cmarker emits further down #show outline.entry.where(level: 2): set text(weight: "semibold") // each `##` heading starts on a fresh page, except the first one, which stays // on the title page — `weak` avoids a blank page when we are already at the top #let md-section = counter("md-section") #show heading.where(level: 2, outlined: true): it => { context if md-section.get().first() > 0 { pagebreak(weak: true) } md-section.step() it } // ------------------------------------------------------------------ math ---- // hugo goldmark delimits math with `\(...\)` and `\[...\]`, while cmarker // expects the typst/markdown `$...$` and `$$...$$` forms #let goldmark-math(markdown) = { markdown .replace("\\[", "$$") .replace("\\]", "$$") .replace("\\(", "$") .replace("\\)", "$") } // ---------------------------------------------------------------- images ---- // maximum footprint of an image coming from the markdown source #let img-max-height = 6cm // set to `none` to drop the frame around screenshots #let img-stroke = 0.5pt + luma(180) // scale an image down so it fits both the available width and `img-max-height`, // without ever blowing it up past its natural size #let fitted-image(source, ..args) = layout(available => { let natural = measure(image(source, ..args)) let factor = calc.min( 1.0, available.width / natural.width, img-max-height / natural.height, ) image(source, width: natural.width * factor, ..args) }) // handle `![alt](src)` and `` #let md-image(source, alt: none, width: auto, height: auto, ..args) = { // an explicit width/height in the markdown wins over the automatic fitting let body = if width == auto and height == auto { fitted-image(source, alt: alt, ..args) } else { image(source, alt: alt, width: width, height: height, ..args) } let framed = block(stroke: img-stroke, radius: 3pt, clip: true, body) // alt text, when there is one, becomes a numbered caption if alt == none or alt == "" { align(center, framed) } else { figure(framed, caption: alt) } } // ------------------------------------------------------------------- toc ---- // outline's own title is a level-1 heading, which would outrank every heading in // the source (they start at `##`), so we emit it ourselves at the right level #if show-toc { heading(level: 2, outlined: false)[Sommaire] outline(title: none, depth: 3, indent: 1em) pagebreak() } // ------------------------------------------------------------- exercices ---- #cmarker.render(goldmark-math(read(md-source)), math: mitex, scope: (image: md-image))