2024-12-05 23:29:52 +00:00
|
|
|
package compiler
|
|
|
|
|
|
|
|
import (
|
2024-12-06 01:57:48 +00:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2024-12-06 04:53:34 +00:00
|
|
|
"strings"
|
|
|
|
|
2024-12-06 01:57:48 +00:00
|
|
|
"hylia/parser"
|
2024-12-05 23:29:52 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// THE HYLIA COMPILER
|
|
|
|
|
2024-12-06 04:53:34 +00:00
|
|
|
func Compile(elements []parser.Element, variables map[string]string, outputFile string) error {
|
2024-12-06 01:57:48 +00:00
|
|
|
|
|
|
|
var head string
|
|
|
|
var body string
|
|
|
|
var other string
|
|
|
|
var errmsg string
|
|
|
|
|
|
|
|
errmsg += "Failed to write to the output file: %w"
|
2024-12-05 23:29:52 +00:00
|
|
|
|
|
|
|
for _, element := range elements {
|
2024-12-06 01:57:48 +00:00
|
|
|
switch element.Name {
|
|
|
|
case "head":
|
|
|
|
head += element.Content + "\n"
|
|
|
|
case "body":
|
|
|
|
body += element.Content + "\n"
|
|
|
|
default:
|
|
|
|
other += element.Content + "\n"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
file, err := os.Create(outputFile)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to create output file: %w", err)
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
// Write the HTML structure to compile into
|
|
|
|
|
|
|
|
_, err = file.WriteString("<!DOCTYPE html>\n<html>\n")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to write to the output file: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-12-06 04:53:34 +00:00
|
|
|
err = writeElements(elements, file, variables)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf(errmsg, err)
|
2024-12-06 01:57:48 +00:00
|
|
|
}
|
|
|
|
// Close the HTML structs
|
|
|
|
_, err = file.WriteString("</html>\n")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to write to the output file: %w", err)
|
2024-12-05 23:29:52 +00:00
|
|
|
}
|
|
|
|
|
2024-12-06 01:57:48 +00:00
|
|
|
return nil
|
|
|
|
|
2024-12-06 04:53:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func writeElements(elements []parser.Element, file *os.File, variables map[string]string) error {
|
|
|
|
for _, element := range elements {
|
2024-12-07 18:44:53 +00:00
|
|
|
|
2024-12-06 04:53:34 +00:00
|
|
|
if element.Name == "head" {
|
|
|
|
_, err := file.WriteString(fmt.Sprintf("<head>\n"))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to write element %s: %w", element.Name, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if element.Name == "body" {
|
|
|
|
_, err := file.WriteString(fmt.Sprintf("<body>\n"))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to write element %s: %w", element.Name, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
content := replaceVariables(element.Content, variables)
|
|
|
|
|
|
|
|
|
|
|
|
if strings.TrimSpace(content) != "" {
|
|
|
|
_, err := file.WriteString(strings.TrimSpace(content) + "\n")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// recursively process nested elements
|
|
|
|
if element.NestedElements != nil && len(element.NestedElements) > 0 {
|
|
|
|
err := writeElements(element.NestedElements, file, variables)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if element.Name == "head" {
|
|
|
|
_, err := file.WriteString(fmt.Sprintf("</head>\n"))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to write element %s: %w", element.Name, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if element.Name == "body" {
|
|
|
|
_, err := file.WriteString(fmt.Sprintf("</body>\n"))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Failed to write element %s: %w", element.Name, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func replaceVariables(content string, variables map[string]string) string {
|
|
|
|
for key, value := range variables {
|
|
|
|
placeholder := fmt.Sprintf("{{%s}}", key)
|
|
|
|
content = strings.ReplaceAll(content, placeholder, value)
|
|
|
|
}
|
|
|
|
return content
|
2024-12-05 23:29:52 +00:00
|
|
|
}
|