Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
71899b9
Add a module to open an editor if defined via env variable
ll-nick Sep 18, 2026
004de0e
Store dict of editable files in the pipeline
ll-nick Sep 18, 2026
c533e33
Set edit commands in html and handle edit requests on the server side
ll-nick Sep 18, 2026
c340a47
Add the editable files and commands to the type definitions
ll-nick Sep 18, 2026
ad56bde
Add a button to the status bar
ll-nick Sep 18, 2026
09eaa46
Style the edit button
ll-nick Sep 18, 2026
caeb1d0
Add logic behind the edit button
ll-nick Sep 18, 2026
44fcdb3
Adjust existing tests that now need to carry editable files or the ed…
ll-nick Sep 18, 2026
eacb88c
Wire up the edit button
ll-nick Sep 18, 2026
5c1cfb9
Add a test deck that varies the utilized source files
ll-nick Sep 18, 2026
3b4dac6
Find and pass also in-project parent layers to the frontend
ll-nick Sep 20, 2026
e845fc6
Add a menu coordinator to prevent multiple drop downs opened at once
ll-nick Sep 20, 2026
857831d
Use a bigger icon on the edit button
ll-nick Sep 20, 2026
6275e7a
Add a toast-style pop-up confirmation when pressing edit
ll-nick Sep 20, 2026
a49aced
Add icons, file name and improve the look of edit drop-down
ll-nick Sep 20, 2026
a03bb33
Update tests of edit button
ll-nick Sep 20, 2026
dda119d
Add a layout hierarchy to test deck
ll-nick Sep 20, 2026
14020af
Update bundles
ll-nick Sep 20, 2026
faef52e
Update docs
ll-nick Sep 20, 2026
f3f9b24
Also show deck.py in the drop down
ll-nick Sep 20, 2026
796f817
Fine-tune toast-message UI
ll-nick Sep 20, 2026
4468de6
Rename INKFLOW_EDIT_CMD_MD to INKFLOW_EDIT_CMD and use it on all file…
ll-nick Sep 20, 2026
c75b7a1
Rebuild bundles
ll-nick Sep 20, 2026
93ae864
Show error message when opening command fails
ll-nick Sep 20, 2026
e6854b3
Fix Windows CI failures from hardcoded Unix path separators
ll-nick Sep 20, 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
19 changes: 19 additions & 0 deletions docs/guides/presenter-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,25 @@ Slide("results", notes=Path("slides/results-notes.md"))
See [Authoring slides](slides.md#speaker-notes) and
[Manifest reference](../reference/manifest.md) for details.

## Editing a slide

Click the pencil-icon button in the status bar to edit the current slide's source.
It opens a small dropdown listing, top to bottom: any parent layouts
(a layout built on a project-local `inkflow:parent`), the layout itself,
a file-backed `md=` and/or `notes=` as Content and Notes,
and finally the deck script.
Each entry shows its kind and filename.
A parent layout that lives in the active theme or an installed package
is never listed, since it isn't yours to edit.

By default this copies the file's absolute path to the clipboard.
With `INKFLOW_EDIT_CMD` set, it launches that command instead
(`INKFLOW_EDIT_CMD_SVG` overrides it just for SVG files).
See [CLI reference](../reference/cli.md#editing-from-the-presenter) for details,
including suggested commands for VS Code, Neovim, and Inkscape.

This button only appears under `inkflow serve`, not in a static build.

## Using a second screen

To present on a projector while keeping the panel on your laptop screen,
Expand Down
68 changes: 68 additions & 0 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,71 @@ INKFLOW_LOG_LEVEL_FILE=debug inkflow build # same as the first, via the e
A fatal build error is shown as a full-screen overlay (and the `serve` TUI error view),
separate from these sinks; enabling the file sink also captures its traceback.

## Editing from the presenter

The presenter's Edit button (see [Presenter panel](../guides/presenter-view.md))
copies the current slide's source path to the clipboard by default.
Set `INKFLOW_EDIT_CMD` to launch an editor instead, for every file kind,
with `{path}` substituted (appended as a final argument if the template has no
`{path}` placeholder).
`INKFLOW_EDIT_CMD_SVG` overrides it specifically for SVG files,
if you want a different command there
(Inkscape instead of a text editor, say) without losing the general one
for content, notes, and the deck script itself.

```bash
INKFLOW_EDIT_CMD="code -r --goto {path}" inkflow serve deck.py
```

### Suggested editor commands

These are starting points to copy and adjust, not built-in behavior.

**VS Code** reuses an already-open window natively:

```bash
export INKFLOW_EDIT_CMD="code -r --goto {path}"
```

**Neovim** needs a fixed socket to connect to,
since its own address is otherwise random per instance.
Launch nvim with that socket, for example via a shell alias:

```bash
alias vim='nvim --listen /tmp/nvim.sock'
```

```bash
export INKFLOW_EDIT_CMD="nvim --server /tmp/nvim.sock --remote {path}"
```

If no nvim with that listen address is running,
the command fails silently (logged as a warning server-side).

**Inkscape** has no comparable built-in remote-control flag,
so this uses its D-Bus interface directly.
Set it as `INKFLOW_EDIT_CMD_SVG`, not the general `INKFLOW_EDIT_CMD`.
Save this as an executable script on your `PATH`:

```bash
#!/bin/sh
# Reuses a running Inkscape's window (a new tab on 1.5+, a new window on
# older versions) instead of spawning a second process; falls back to a
# plain `inkscape` launch if no instance is running yet.
if gdbus call --session --dest org.inkscape.Inkscape \
--object-path /org/inkscape/Inkscape \
--method org.freedesktop.Application.ActivateAction \
"file-open-window" "[<'$1'>]" "{}" >/dev/null 2>&1; then
exit 0
fi
exec inkscape "$1"
```

```bash
export INKFLOW_EDIT_CMD_SVG="inkflow-edit-svg {path}"
```

This is Linux-specific (D-Bus) and depends on Inkscape's own D-Bus interface,
which isn't part of inkflow and could change between Inkscape releases.
It degrades safely on any version, though.

72 changes: 72 additions & 0 deletions src/css/presenter/edit.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* ── Edit-source control ────────────────────────────────────────────────────── */

.edit-wrap {
position: relative;
display: inline-flex;
}

/* Dropdown: anchored above the button (status bar sits at the bottom). Sized to
its content (short generic labels) rather than a fixed width like sync-menu's,
whose rows are full sentences; a max-width plus ellipsis on the filename keeps
a long one from stretching the menu. */
#edit-menu {
display: none;
position: absolute;
bottom: calc(100% + 6px);
left: 0;
z-index: 30;
max-width: 14rem;
padding: 0.25rem;
background: var(--surface);
border: 1px solid var(--overlay);
border-radius: 6px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
}
#edit-menu.open {
display: block;
}

.edit-row {
display: flex;
align-items: center;
gap: 0.5rem;
width: 100%;
background: transparent;
border: none;
border-radius: 4px;
color: var(--subtext);
cursor: pointer;
font-family: inherit;
padding: 0.35rem 0.5rem;
text-align: left;
transition:
background 0.12s,
color 0.12s;
}
.edit-row:hover {
background: rgba(255, 255, 255, 0.08);
color: var(--text);
}
[data-theme="light"] .edit-row:hover {
background: rgba(0, 0, 0, 0.08);
}
.edit-row svg {
flex-shrink: 0;
}

.edit-row-text {
display: flex;
flex-direction: column;
min-width: 0;
line-height: 1.3;
}
.edit-row-label {
font-size: 0.78rem;
}
.edit-row-name {
font-size: 0.68rem;
opacity: 0.65;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
1 change: 1 addition & 0 deletions src/css/presenter/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@import "./overlays.css";
@import "./picker.css";
@import "./sync.css";
@import "./edit.css";
@import "./overview.css";
@import "./pv.css";
@import "../shared/animations.css";
Expand Down
92 changes: 92 additions & 0 deletions src/css/presenter/overlays.css
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,95 @@ kbd {
#log-list li.log-error {
color: var(--red);
}

/* ── Edit-action toast (non-modal) ──
Same corner and box treatment as #log-banner (surface/border/shadow), an
accent colour instead of its warning yellow. Times itself out (edit.ts) but
also offers a close button, like #log-banner, plus a bar along the bottom
edge filling left-to-right as it approaches that — purely CSS (an animation
timed to match edit.ts's setTimeout), restarted by re-toggling .visible so a
second edit in quick succession doesn't inherit the first one's progress. */
#edit-toast {
display: none;
position: fixed;
right: 1rem;
bottom: 1rem;
z-index: 40;
flex-direction: column;
max-width: 24rem;
background: var(--surface);
border: 1px solid var(--green);
border-radius: 8px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
color: var(--text);
font-size: 0.8rem;
line-height: 1.4;
overflow: hidden;
pointer-events: none;
}
#edit-toast.visible {
display: flex;
}
#edit-toast-body {
display: flex;
align-items: flex-start;
gap: 0.4rem;
padding: 0.5rem 0.5rem 0.5rem 0.75rem;
}
#edit-toast svg {
color: var(--green);
flex-shrink: 0;
margin-top: 0.15rem;
}
#edit-toast-text {
word-break: break-word;
}
#edit-toast-close {
background: none;
border: none;
color: var(--subtext);
font-size: 1.1rem;
line-height: 1;
cursor: pointer;
padding: 0 0.25rem;
flex-shrink: 0;
pointer-events: auto;
}
#edit-toast-close:hover {
color: var(--text);
}
#edit-toast-progress {
height: 2px;
background: var(--green);
transform-origin: left;
animation: edit-toast-grow 3s linear forwards;
}
@keyframes edit-toast-grow {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
/* Error state: launching the configured command failed (e.g. the binary isn't
on PATH) — red instead of green, the error glyph instead of the checkmark,
and no progress bar, since an error toast has no auto-dismiss timer to show
the progress of. Declared last so it reliably overrides the base rules above
regardless of its own (lower) specificity. */
.edit-toast-icon-error {
display: none;
}
#edit-toast.error {
border-color: var(--red);
}
#edit-toast.error .edit-toast-icon-ok {
display: none;
}
#edit-toast.error .edit-toast-icon-error {
display: block;
color: var(--red);
}
#edit-toast.error #edit-toast-progress {
display: none;
}
Loading
Loading