Ensure file is executable for preprocessing to work

This commit is contained in:
Maas Lalani
2021-06-27 12:25:30 -04:00
parent e7274f993e
commit 742251d742
6 changed files with 114 additions and 22 deletions

View File

@@ -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
View 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
View 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 │
└───┘ └───┘
```

View File

@@ -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
}

View File

@@ -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)
}
})
}
}

View File

@@ -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) {