78 lines
2.1 KiB
Go
78 lines
2.1 KiB
Go
// Package parser provides functions for parsing Markdown templates into
|
|
// structured JSON objects that conform to a JSON Schema.
|
|
package parser
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.max-richter.dev/max/marka/parser/decoders"
|
|
"git.max-richter.dev/max/marka/parser/matcher"
|
|
"git.max-richter.dev/max/marka/registry"
|
|
"git.max-richter.dev/max/marka/template"
|
|
)
|
|
|
|
func DetectType(markdownContent string) (string, error) {
|
|
defaultSchemaContent, err := registry.GetTemplate("_default")
|
|
if err != nil {
|
|
return "", fmt.Errorf("could not get schema: %w", err)
|
|
}
|
|
|
|
defaultSchema, err := template.CompileTemplate(defaultSchemaContent)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to compile template: %w", err)
|
|
}
|
|
|
|
blocks := matcher.MatchBlocksFuzzy(markdownContent, defaultSchema, 0.3)
|
|
|
|
result, err := decoders.Parse(blocks)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to parse blocks: %w", err)
|
|
}
|
|
|
|
if result, ok := result.(map[string]any); ok {
|
|
if contentType, ok := result["@type"]; ok {
|
|
return contentType.(string), nil
|
|
} else {
|
|
return "", fmt.Errorf("frontmatter did not contain '@type'")
|
|
}
|
|
} else {
|
|
return "", fmt.Errorf("could not parse frontmatter")
|
|
}
|
|
}
|
|
|
|
func prepareMarkdown(input string) string {
|
|
input = strings.TrimSuffix(input, "\n")
|
|
input = strings.ReplaceAll(input, "@type:", `"@type":`)
|
|
input = strings.ReplaceAll(input, "@context:", `"@context":`)
|
|
return input
|
|
}
|
|
|
|
func ParseFile(markdownContent string) (any, error) {
|
|
markdownContent = prepareMarkdown(markdownContent)
|
|
|
|
contentType, err := DetectType(markdownContent)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not detect type: %w", err)
|
|
}
|
|
|
|
templateContent, err := registry.GetTemplate(contentType)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get schema: %w", err)
|
|
}
|
|
|
|
template, err := template.CompileTemplate(templateContent)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to compile template: %w", err)
|
|
}
|
|
|
|
blocks := matcher.MatchBlocksFuzzy(markdownContent, template, 0.3)
|
|
|
|
result, err := decoders.Parse(blocks)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse blocks: %w", err)
|
|
}
|
|
|
|
return result, nil
|
|
}
|