initial commit
This commit is contained in:
commit
e157883c90
12
Containerfile
Normal file
12
Containerfile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
FROM docker.io/golang:1.21-alpine3.19 AS builder
|
||||||
|
|
||||||
|
ADD md2gmi.go /md2gmi.go
|
||||||
|
RUN go build -o /md2gmi /md2gmi.go
|
||||||
|
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=builder /md2gmi /md2gmi
|
||||||
|
|
||||||
|
ENTRYPOINT ["/md2gmi"]
|
||||||
|
CMD ["${INPUT_DIR}", "${OUTPUT_DIR}"]
|
12
action.yml
Normal file
12
action.yml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
name: "Markdown2Gemini"
|
||||||
|
description: "Simple conversion of a tree of markdown files to the gemini format."
|
||||||
|
inputs:
|
||||||
|
input-dir:
|
||||||
|
description: "Path to the input directory"
|
||||||
|
required: true
|
||||||
|
output-dir:
|
||||||
|
description: "Path to the output directory"
|
||||||
|
required: true
|
||||||
|
runs:
|
||||||
|
using: "docker"
|
||||||
|
image: "Containerfile"
|
197
md2gmi.go
Normal file
197
md2gmi.go
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type link struct {
|
||||||
|
full string
|
||||||
|
title string
|
||||||
|
url string
|
||||||
|
}
|
||||||
|
|
||||||
|
func procAudio(fileContent string, audioRegex *regexp.Regexp) string {
|
||||||
|
audios := audioRegex.FindAllStringSubmatch(fileContent, -1)
|
||||||
|
|
||||||
|
if audios != nil {
|
||||||
|
for i := range audios {
|
||||||
|
full := audios[i][0]
|
||||||
|
url := audios[i][1]
|
||||||
|
link := link{full, "audio", url}
|
||||||
|
|
||||||
|
replacement := fmt.Sprintf("=> %s", link.url)
|
||||||
|
fileContent = strings.Replace(fileContent, link.full, replacement, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileContent
|
||||||
|
}
|
||||||
|
|
||||||
|
func procVideos(fileContent string, videoRegex *regexp.Regexp) string {
|
||||||
|
videos := videoRegex.FindAllStringSubmatch(fileContent, -1)
|
||||||
|
|
||||||
|
if videos != nil {
|
||||||
|
for i := range videos {
|
||||||
|
full := videos[i][0]
|
||||||
|
url := videos[i][1]
|
||||||
|
url = fmt.Sprintf("%s.webm", url)
|
||||||
|
link := link{full, "video", url}
|
||||||
|
|
||||||
|
replacement := fmt.Sprintf("=> %s", link.url)
|
||||||
|
fileContent = strings.Replace(fileContent, link.full, replacement, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileContent
|
||||||
|
}
|
||||||
|
|
||||||
|
func procImages(fileContent string, imgRegex *regexp.Regexp) string {
|
||||||
|
images := imgRegex.FindAllStringSubmatch(fileContent, -1)
|
||||||
|
|
||||||
|
if images != nil {
|
||||||
|
for i := range images {
|
||||||
|
full := images[i][1]
|
||||||
|
title := images[i][2]
|
||||||
|
url := images[i][3]
|
||||||
|
urlParts := strings.Split(url, " ")
|
||||||
|
link := link{full, title, urlParts[0]}
|
||||||
|
|
||||||
|
replacement := fmt.Sprintf("%s\n=> %s", link.title, link.url)
|
||||||
|
fileContent = strings.Replace(fileContent, link.full, replacement, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileContent
|
||||||
|
}
|
||||||
|
|
||||||
|
func procLinks(fileContent string, linkRegex *regexp.Regexp) string {
|
||||||
|
links := linkRegex.FindAllStringSubmatch(fileContent, -1)
|
||||||
|
linkUrls := make([]link, len(links))
|
||||||
|
|
||||||
|
if links != nil {
|
||||||
|
for i := range links {
|
||||||
|
full := links[i][1]
|
||||||
|
title := links[i][2]
|
||||||
|
url := links[i][3]
|
||||||
|
link := link{full, title, url}
|
||||||
|
|
||||||
|
replacement := fmt.Sprintf("*%s*", link.title)
|
||||||
|
fileContent = strings.Replace(fileContent, link.full, replacement, 1)
|
||||||
|
|
||||||
|
linkUrls[i] = link
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb strings.Builder
|
||||||
|
for _, link := range linkUrls {
|
||||||
|
fmtLink := fmt.Sprintf("=> %s %s\n", link.url, link.title)
|
||||||
|
sb.WriteString(fmtLink)
|
||||||
|
}
|
||||||
|
fmtLinks := sb.String()
|
||||||
|
fileContent += fmt.Sprintf("\n%s", fmtLinks)
|
||||||
|
|
||||||
|
return fileContent
|
||||||
|
}
|
||||||
|
|
||||||
|
func procFile(src string, linkRegex *regexp.Regexp, imgRegex *regexp.Regexp, videoRegex *regexp.Regexp, audioRegex *regexp.Regexp) (string, error) {
|
||||||
|
fileData, err := ioutil.ReadFile(src)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileContent := string(fileData)
|
||||||
|
fileContent = procLinks(fileContent, linkRegex)
|
||||||
|
fileContent = procImages(fileContent, imgRegex)
|
||||||
|
fileContent = procVideos(fileContent, videoRegex)
|
||||||
|
fileContent = procAudio(fileContent, audioRegex)
|
||||||
|
|
||||||
|
return fileContent, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func procFiles(srcDir string, destDir string) error {
|
||||||
|
libRegex := regexp.MustCompile("^.+\\.(md)$")
|
||||||
|
linkRegex := regexp.MustCompile("[^!](\\[(.+?)\\]\\((.+?)\\))")
|
||||||
|
imgRegex := regexp.MustCompile("([!]\\[(.+?)\\]\\((.+?)\\))")
|
||||||
|
videoRegex := regexp.MustCompile("{{< video src=\"(.*)\" >}}")
|
||||||
|
audioRegex := regexp.MustCompile("{{< audio src=\"(.*)\" >}}")
|
||||||
|
|
||||||
|
srcDir, err := filepath.Abs(srcDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
destDir, err = filepath.Abs(destDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err == nil && libRegex.MatchString(info.Name()) {
|
||||||
|
processedFile, err := procFile(path, linkRegex, imgRegex, videoRegex, audioRegex)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err = filepath.Abs(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
srcFile := strings.Replace(path, srcDir, "", 1)
|
||||||
|
destFile := filepath.Join(destDir, srcFile)
|
||||||
|
destDir := filepath.Dir(destFile)
|
||||||
|
|
||||||
|
err = os.MkdirAll(destDir, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(destFile, []byte(processedFile), 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Printf("processed %s", path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
log.Fatal("no source directory specified")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(os.Args) < 3 {
|
||||||
|
log.Fatal("no dest directory specified")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
srcDir := os.Args[1]
|
||||||
|
srcInfo, err := os.Stat(srcDir)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
log.Fatalf("source directory %s does not exist", srcDir)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !srcInfo.IsDir() {
|
||||||
|
log.Fatalf("%s is not a directory", srcDir)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
destDir := os.Args[2]
|
||||||
|
|
||||||
|
err = procFiles(srcDir, destDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user