mirror of
https://github.com/maaslalani/slides.git
synced 2026-01-07 21:43:58 -05:00
Ensure file is executable for preprocessing to work
This commit is contained in:
23
README.md
23
README.md
@@ -65,13 +65,26 @@ Create slides and present them without ever leaving your terminal.
|
||||
|
||||
---
|
||||
|
||||
Include ASCII graphs with GraphViz + graph-easy.
|
||||
https://dot-to-ascii.ggerganov.com/
|
||||
# Pre-process slides
|
||||
|
||||
┌──────────┐ ┌────────────┐ ┌────────┐
|
||||
│ GraphViz │ ──▶ │ graph-easy │ ──▶ │ slides │
|
||||
└──────────┘ └────────────┘ └────────┘
|
||||
You can add a code block with ~~~ and write a command to run before displaying
|
||||
the slides, the text inside the code block will be passed as stdin to the command
|
||||
and the code block will be replaced with the stdout of the command.
|
||||
|
||||
~~~graph-easy --as=boxart
|
||||
[ A ] - to -> [ B ]
|
||||
~~~
|
||||
|
||||
The above will be pre-processed to look like:
|
||||
|
||||
┌───┐ to ┌───┐
|
||||
│ A │ ────> │ B │
|
||||
└───┘ └───┘
|
||||
|
||||
For security reasons, you must pass a file that has execution permissions
|
||||
for the slides to be pre-processed.
|
||||
|
||||
chmod +x file.md
|
||||
```
|
||||
|
||||
Checkout the [example slides](./examples).
|
||||
|
||||
2
examples/import.md
Normal file
2
examples/import.md
Normal file
@@ -0,0 +1,2 @@
|
||||
This is just an example of how to import text from other files with
|
||||
preprocess.md
|
||||
48
examples/preprocess.md
Normal file → Executable file
48
examples/preprocess.md
Normal file → Executable file
@@ -1,8 +1,36 @@
|
||||
# Slides
|
||||
|
||||
You can add a code block with three tildes (~) and write a command to run before displaying
|
||||
the slides, the text inside the code block will be passed as stdin to the command
|
||||
and the code block will be replaced with the stdout of the command.
|
||||
|
||||
```
|
||||
~~~graph-easy --as=boxart
|
||||
[ A ] - to -> [ B ]
|
||||
~~~
|
||||
```
|
||||
|
||||
The above will be pre-processed to look like:
|
||||
|
||||
NOTE: You need `graph-easy` installed and in your `$PATH`
|
||||
|
||||
```
|
||||
┌───┐ to ┌───┐
|
||||
│ A │ ────> │ B │
|
||||
└───┘ └───┘
|
||||
```
|
||||
|
||||
For security reasons, you must pass a file that has execution permissions
|
||||
for the slides to be pre-processed.
|
||||
|
||||
```
|
||||
chmod +x file.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
~~~sd replaced processed
|
||||
This content will be replaced and passed into stdin
|
||||
of the command above
|
||||
This content will be passed in as stdin and will be replaced.
|
||||
~~~
|
||||
|
||||
---
|
||||
@@ -11,21 +39,13 @@ Any command will work
|
||||
|
||||
~~~echo "You can do whatever, really"
|
||||
This doesn't matter, since it will be replaced by the stdout
|
||||
of the command above
|
||||
of the command above because the command will disregard stdin.
|
||||
~~~
|
||||
|
||||
---
|
||||
|
||||
Pre-process Graphs
|
||||
You can use this to import snippets of code from other files:
|
||||
|
||||
~~~graph-easy --as=boxart
|
||||
[ A ] - to -> [ B ]
|
||||
~~~xargs cat
|
||||
examples/import.md
|
||||
~~~
|
||||
|
||||
The above will be pre-processed to look like:
|
||||
|
||||
```
|
||||
┌───┐ to ┌───┐
|
||||
│ A │ ────> │ B │
|
||||
└───┘ └───┘
|
||||
```
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
)
|
||||
|
||||
@@ -16,3 +17,8 @@ func Exists(filepath string) bool {
|
||||
}
|
||||
return !info.IsDir()
|
||||
}
|
||||
|
||||
// IsExecutable returns whether a file has execution permissions
|
||||
func IsExecutable(s fs.FileInfo) bool {
|
||||
return s.Mode().Perm()&0111 == 0111
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package file_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/maaslalani/slides/internal/file"
|
||||
@@ -26,3 +29,44 @@ func TestExists(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsExecutable(t *testing.T) {
|
||||
tests := []struct {
|
||||
perm fs.FileMode
|
||||
expected bool
|
||||
}{
|
||||
{0101, false},
|
||||
{0111, true},
|
||||
{0644, false},
|
||||
{0666, false},
|
||||
{0777, true},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(fmt.Sprint(tc.perm), func(t *testing.T) {
|
||||
tmp, err := os.CreateTemp(os.TempDir(), "slides-*")
|
||||
if err != nil {
|
||||
t.Fatal("failed to create temp file")
|
||||
}
|
||||
defer os.Remove(tmp.Name())
|
||||
|
||||
err = tmp.Chmod(tc.perm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s, err := tmp.Stat()
|
||||
if err != nil {
|
||||
t.Fatal("failed to stat file")
|
||||
}
|
||||
|
||||
want := tc.expected
|
||||
got := file.IsExecutable(s)
|
||||
if tc.expected != got {
|
||||
t.Log(want)
|
||||
t.Log(got)
|
||||
t.Fatalf("IsExecutable returned an incorrect result, want: %t, got %t", want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/glamour"
|
||||
"github.com/maaslalani/slides/internal/code"
|
||||
"github.com/maaslalani/slides/internal/file"
|
||||
"github.com/maaslalani/slides/internal/meta"
|
||||
"github.com/maaslalani/slides/internal/process"
|
||||
"github.com/maaslalani/slides/styles"
|
||||
@@ -68,8 +69,6 @@ func (m *Model) Load() error {
|
||||
return err
|
||||
}
|
||||
|
||||
content = process.Pre(content)
|
||||
|
||||
slides := strings.Split(content, delimiter)
|
||||
|
||||
metaData, exists := meta.New().ParseHeader(slides[0])
|
||||
@@ -162,7 +161,15 @@ func readFile(path string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(b), err
|
||||
content := string(b)
|
||||
|
||||
// Pre-process slides if the file is executable to avoid
|
||||
// unintentional code execution when presenting slides
|
||||
if file.IsExecutable(s) {
|
||||
content = process.Pre(content)
|
||||
}
|
||||
|
||||
return content, err
|
||||
}
|
||||
|
||||
func readStdin() (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user