Merge pull request #953 from jthack/latex-pdfs

Latex pdfs
This commit is contained in:
xssdoctor 2024-09-12 19:58:03 -04:00 committed by GitHub
commit d25ea0e88b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 155 additions and 0 deletions

View File

@ -314,6 +314,34 @@ go install github.com/danielmiessler/yt@latest
Be sure to add your `YOUTUBE_API_KEY` to `~/.config/fabric/.env`. Be sure to add your `YOUTUBE_API_KEY` to `~/.config/fabric/.env`.
### `to_pdf`
`to_pdf` is a helper command that converts LaTeX files to PDF format. You can use it like this:
```bash
to_pdf input.tex
```
This will create a PDF file from the input LaTeX file in the same directory.
You can also use it with stdin which works perfectly with the `write_latex` pattern:
```bash
echo "ai security primer" | fabric --pattern write_latex | to_pdf
```
This will create a PDF file named `output.pdf` in the current directory.
### `to_pdf` Installation
To install `to_pdf`, install it the same way as you install Fabric, just with a different repo name.
```bash
go install github.com/danielmiessler/fabric/to_pdf/to_pdf@latest
```
Make sure you have a LaTeX distribution (like TeX Live or MiKTeX) installed on your system, as `to_pdf` requires `pdflatex` to be available in your system's PATH.
## Meta ## Meta
> [!NOTE] > [!NOTE]

View File

@ -0,0 +1,22 @@
You are an expert at outputting syntactically correct LaTeX for a new .tex document. Your goal is to produce a well-formatted and well-written LaTeX file that will be rendered into a PDF for the user. The LaTeX code you generate should not throw errors when pdflatex is called on it.
Follow these steps to create the LaTeX document:
1. Begin with the document class and preamble. Include necessary packages based on the user's request.
2. Use the \begin{document} command to start the document body.
3. Create the content of the document based on the user's request. Use appropriate LaTeX commands and environments to structure the document (e.g., \section, \subsection, itemize, tabular, equation).
4. End the document with the \end{document} command.
Important notes:
- Do not output anything besides the valid LaTeX code. Any additional thoughts or comments should be placed within \iffalse ... \fi sections.
- Do not use fontspec as it can make it fail to run.
- For sections and subsections, append an asterisk like this \section* in order to prevent everything from being numbered unless the user asks you to number the sections.
- Ensure all LaTeX commands and environments are properly closed.
- Use appropriate indentation for better readability.
Begin your output with the LaTeX code for the requested document. Do not include any explanations or comments outside of the LaTeX code itself.
The user's request for the LaTeX document will be included here.

105
to_pdf/to_pdf.go Normal file
View File

@ -0,0 +1,105 @@
package main
import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
)
func main() {
var input io.Reader
var outputFile string
if len(os.Args) > 1 {
// File input mode
file, err := os.Open(os.Args[1])
if err != nil {
fmt.Fprintf(os.Stderr, "Error opening file: %v\n", err)
os.Exit(1)
}
defer file.Close()
input = file
outputFile = strings.TrimSuffix(os.Args[1], filepath.Ext(os.Args[1])) + ".pdf"
} else {
// Stdin mode
input = os.Stdin
outputFile = "output.pdf"
}
// Check if pdflatex is installed
if _, err := exec.LookPath("pdflatex"); err != nil {
fmt.Fprintln(os.Stderr, "Error: pdflatex is not installed or not in your PATH.")
fmt.Fprintln(os.Stderr, "Please install a LaTeX distribution (e.g., TeX Live or MiKTeX) and ensure pdflatex is in your PATH.")
os.Exit(1)
}
// Create a temporary directory
tmpDir, err := os.MkdirTemp("", "latex_")
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating temporary directory: %v\n", err)
os.Exit(1)
}
defer os.RemoveAll(tmpDir)
// Create a temporary .tex file
tmpFile, err := os.Create(filepath.Join(tmpDir, "input.tex"))
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating temporary file: %v\n", err)
os.Exit(1)
}
// Copy input to the temporary file
_, err = io.Copy(tmpFile, input)
if err != nil {
fmt.Fprintf(os.Stderr, "Error writing to temporary file: %v\n", err)
os.Exit(1)
}
tmpFile.Close()
// Run pdflatex with nonstopmode
cmd := exec.Command("pdflatex", "-interaction=nonstopmode", "-output-directory", tmpDir, tmpFile.Name())
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Fprintf(os.Stderr, "Error running pdflatex: %v\n", err)
fmt.Fprintf(os.Stderr, "pdflatex output:\n%s\n", output)
os.Exit(1)
}
// Check if PDF was actually created
pdfPath := filepath.Join(tmpDir, "input.pdf")
if _, err := os.Stat(pdfPath); os.IsNotExist(err) {
fmt.Fprintln(os.Stderr, "Error: PDF file was not created. There might be an issue with your LaTeX source.")
fmt.Fprintf(os.Stderr, "pdflatex output:\n%s\n", output)
os.Exit(1)
}
// Move the output PDF to the current directory
err = os.Rename(pdfPath, outputFile)
if err != nil {
fmt.Fprintf(os.Stderr, "Error moving output file: %v\n", err)
os.Exit(1)
}
// Clean up temporary files
cleanupTempFiles(tmpDir)
fmt.Printf("PDF created: %s\n", outputFile)
}
func cleanupTempFiles(dir string) {
extensions := []string{".aux", ".log", ".out", ".toc", ".lof", ".lot", ".bbl", ".blg"}
for _, ext := range extensions {
files, err := filepath.Glob(filepath.Join(dir, "*"+ext))
if err != nil {
fmt.Fprintf(os.Stderr, "Error finding %s files: %v\n", ext, err)
continue
}
for _, file := range files {
if err := os.Remove(file); err != nil {
fmt.Fprintf(os.Stderr, "Error removing file %s: %v\n", file, err)
}
}
}
}