parent
							
								
									ccff4e56c0
								
							
						
					
					
						commit
						380a5b9223
					
				@ -101,24 +101,24 @@ func (this *Environment) parse (name string, modTime time.Time, input io.Reader)
 | 
				
			|||||||
	// read entire file and split into front matter and body
 | 
						// read entire file and split into front matter and body
 | 
				
			||||||
	buffer, err := io.ReadAll(input)
 | 
						buffer, err := io.ReadAll(input)
 | 
				
			||||||
	if err != nil { return nil, err }
 | 
						if err != nil { return nil, err }
 | 
				
			||||||
	frontMatter, body, err := SplitMeta(string(buffer))
 | 
						meta, body, err := SplitMeta(string(buffer))
 | 
				
			||||||
	if err != nil { return nil, err }
 | 
						if err != nil { return nil, err }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// assemble the document struct
 | 
						// assemble the document struct
 | 
				
			||||||
	document := &Document {
 | 
						document := &Document {
 | 
				
			||||||
		Meta:        frontMatter,
 | 
							Meta:        meta,
 | 
				
			||||||
		environment: this,
 | 
							environment: this,
 | 
				
			||||||
		name:        name,
 | 
							name:        name,
 | 
				
			||||||
		parseTime:   time.Now(),
 | 
							parseTime:   time.Now(),
 | 
				
			||||||
		template:    template.New(name),
 | 
							template:    template.New(name),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if author, ok := frontMatter["author"]; ok {
 | 
						if author := meta.Get("author"); author != "" {
 | 
				
			||||||
		document.Author = author
 | 
							document.Author = author
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if title, ok := frontMatter["title"]; ok {
 | 
						if title := meta.Get("title"); title != "" {
 | 
				
			||||||
		document.Title = title
 | 
							document.Title = title
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if extends, ok := frontMatter["extends"]; ok {
 | 
						if extends := meta.Get("extends"); extends != "" {
 | 
				
			||||||
		document.Extends = extends
 | 
							document.Extends = extends
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								error.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								error.go
									
									
									
									
									
								
							@ -5,7 +5,6 @@ type Error string; const (
 | 
				
			|||||||
	ErrCircularInheritance Error = "circular inheritance"
 | 
						ErrCircularInheritance Error = "circular inheritance"
 | 
				
			||||||
	ErrMetaMalformed       Error = "metadata is malformed"
 | 
						ErrMetaMalformed       Error = "metadata is malformed"
 | 
				
			||||||
	ErrMetaNeverClosed     Error = "metadata is never closed"
 | 
						ErrMetaNeverClosed     Error = "metadata is never closed"
 | 
				
			||||||
	ErrMetaDuplicateKey    Error = "duplicate key in front matter"
 | 
					 | 
				
			||||||
	ErrTypeMismatch        Error = "type mismatch"
 | 
						ErrTypeMismatch        Error = "type mismatch"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -112,10 +112,10 @@ func (this *Handler) serveDocument (
 | 
				
			|||||||
		recorder.Reset()
 | 
							recorder.Reset()
 | 
				
			||||||
		recorder.Head = res.Header().Clone()
 | 
							recorder.Head = res.Header().Clone()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if contentType, ok := document.Meta["content-type"]; ok {
 | 
						if contentType := document.Meta.Get("content-type"); contentType != "" {
 | 
				
			||||||
		recorder.Header().Set("Content-Type", contentType)
 | 
							recorder.Header().Set("Content-Type", contentType)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if status, ok := document.Meta["status"]; ok {
 | 
						if status := document.Meta.Get("status"); status != "" {
 | 
				
			||||||
		if status, err := strconv.Atoi(status); err == nil {
 | 
							if status, err := strconv.Atoi(status); err == nil {
 | 
				
			||||||
			recorder.Status = status
 | 
								recorder.Status = status
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										53
									
								
								meta.go
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								meta.go
									
									
									
									
									
								
							@ -1,6 +1,7 @@
 | 
				
			|||||||
package step
 | 
					package step
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "io"
 | 
					import "io"
 | 
				
			||||||
 | 
					import "slices"
 | 
				
			||||||
import "strconv"
 | 
					import "strconv"
 | 
				
			||||||
import "strings"
 | 
					import "strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -8,7 +9,7 @@ const metaRule = "---"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Meta represents optional metadata that can occur at the very start of
 | 
					// Meta represents optional metadata that can occur at the very start of
 | 
				
			||||||
// a document.
 | 
					// a document.
 | 
				
			||||||
type Meta = map[string] string
 | 
					type Meta map[string] []string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SplitMeta parses the metadata (if it exists), returning a map representing it
 | 
					// SplitMeta parses the metadata (if it exists), returning a map representing it
 | 
				
			||||||
// along with the rest of the input as a string. If there is no metadata, an
 | 
					// along with the rest of the input as a string. If there is no metadata, an
 | 
				
			||||||
@ -52,7 +53,7 @@ func ParseMeta (input string) (Meta, error) {
 | 
				
			|||||||
		if !ok {
 | 
							if !ok {
 | 
				
			||||||
			return nil, ErrMetaMalformed
 | 
								return nil, ErrMetaMalformed
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		key   = strings.ToLower(strings.TrimSpace(key))
 | 
							key   = strings.TrimSpace(key)
 | 
				
			||||||
		value = strings.TrimSpace(value)
 | 
							value = strings.TrimSpace(value)
 | 
				
			||||||
		if strings.HasPrefix(value, "\"") || strings.HasPrefix(value, "'") {
 | 
							if strings.HasPrefix(value, "\"") || strings.HasPrefix(value, "'") {
 | 
				
			||||||
			unquoted, err := strconv.Unquote(value)
 | 
								unquoted, err := strconv.Unquote(value)
 | 
				
			||||||
@ -64,10 +65,7 @@ func ParseMeta (input string) (Meta, error) {
 | 
				
			|||||||
		if key == "" {
 | 
							if key == "" {
 | 
				
			||||||
			return nil, ErrMetaMalformed
 | 
								return nil, ErrMetaMalformed
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if _, exists := meta[key]; exists {
 | 
							meta.Add(key, value)
 | 
				
			||||||
			return nil, ErrMetaDuplicateKey
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		meta[key] = value
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return meta, nil
 | 
						return meta, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -78,3 +76,46 @@ func DecodeMeta (input io.Reader) (Meta, error) {
 | 
				
			|||||||
	if err != nil { return nil, err }
 | 
						if err != nil { return nil, err }
 | 
				
			||||||
	return ParseMeta(string(buffer))
 | 
						return ParseMeta(string(buffer))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Add adds the key/value pair to the metadata. It appends to any existing
 | 
				
			||||||
 | 
					// values associated with the key. The key is case insensitive.
 | 
				
			||||||
 | 
					func (meta Meta) Add (key, value string) {
 | 
				
			||||||
 | 
						key = canonicalMetaKey(key)
 | 
				
			||||||
 | 
						meta[key] = append(meta[key], value)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Clone returns a deep copy of the metadata.
 | 
				
			||||||
 | 
					func (meta Meta) Clone () Meta {
 | 
				
			||||||
 | 
						clone := make(Meta, len(meta))
 | 
				
			||||||
 | 
						for key, value := range meta {
 | 
				
			||||||
 | 
							clone[key] = slices.Clone(value)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return clone
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Del deletes the values associated with the key. The key is case insensitive.
 | 
				
			||||||
 | 
					func (meta Meta) Del (key string) {
 | 
				
			||||||
 | 
						key = canonicalMetaKey(key)
 | 
				
			||||||
 | 
						delete(meta, key)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get gets the first value associated with the key. The key is case
 | 
				
			||||||
 | 
					// insensitive.
 | 
				
			||||||
 | 
					func (meta Meta) Get (key string) string {
 | 
				
			||||||
 | 
						key = canonicalMetaKey(key)
 | 
				
			||||||
 | 
						slice, ok := meta[key]
 | 
				
			||||||
 | 
						if !ok             { return "" }
 | 
				
			||||||
 | 
						if len(slice) == 0 { return "" }
 | 
				
			||||||
 | 
						return slice[0]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Set replaces all values currently associated with key with the single element
 | 
				
			||||||
 | 
					// value. The key is case insensitive.
 | 
				
			||||||
 | 
					func (meta Meta) Set (key, value string) {
 | 
				
			||||||
 | 
						key = canonicalMetaKey(key)
 | 
				
			||||||
 | 
						meta[key] = []string { value }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func canonicalMetaKey (key string) string {
 | 
				
			||||||
 | 
						return strings.ToLower(key)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										86
									
								
								meta_test.go
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								meta_test.go
									
									
									
									
									
								
							@ -13,7 +13,7 @@ theres another hr that shouldnt
 | 
				
			|||||||
break anything
 | 
					break anything
 | 
				
			||||||
break: anything
 | 
					break: anything
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
	frontMatter, body, err := SplitMeta(
 | 
						meta, body, err := SplitMeta(
 | 
				
			||||||
`---
 | 
					`---
 | 
				
			||||||
FOO: baR
 | 
					FOO: baR
 | 
				
			||||||
   fOoo: Bar
 | 
					   fOoo: Bar
 | 
				
			||||||
@ -34,27 +34,27 @@ Sentence: ` + quickBrownFox + `
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	test.Log("META:")
 | 
						test.Log("META:")
 | 
				
			||||||
	test.Log(frontMatter)
 | 
						test.Log(meta)
 | 
				
			||||||
	value0, ok := frontMatter["foo"]
 | 
						if meta.Get("foo") != "baR" {
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	value1, ok := frontMatter["fooo"]
 | 
						}
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
						if meta.Get("fooo") != "Bar" {
 | 
				
			||||||
	value2, ok := frontMatter["shouldn't break anything"]
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
						}
 | 
				
			||||||
	value3, ok := frontMatter["this"]
 | 
						if meta.Get("shouldn't break anything") != "---" {
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	value4, ok := frontMatter["sentence"]
 | 
						}
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
						if meta.Get("this") != "that" {
 | 
				
			||||||
	if value0 != "baR"         { test.Fatal("value is not correct") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	if value1 != "Bar"         { test.Fatal("value is not correct") }
 | 
						}
 | 
				
			||||||
	if value2 != "---"         { test.Fatal("value is not correct") }
 | 
						if meta.Get("sentence") != quickBrownFox {
 | 
				
			||||||
	if value3 != "that"        { test.Fatal("value is not correct") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	if value4 != quickBrownFox { test.Fatal("value is not correct") }
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestSplitMetaCRLF (test *testing.T) {
 | 
					func TestSplitMetaCRLF (test *testing.T) {
 | 
				
			||||||
	correctBody := "this is some sample text\r\n---\r\ntheres another hr that shouldnt\r\nbreak anything\r\nbreak: anything\r\n"
 | 
						correctBody := "this is some sample text\r\n---\r\ntheres another hr that shouldnt\r\nbreak anything\r\nbreak: anything\r\n"
 | 
				
			||||||
	frontMatter, body, err := SplitMeta(
 | 
						meta, body, err := SplitMeta(
 | 
				
			||||||
"---\r\nFOO: baR\r\n   fOoo: Bar\r\nShouldn't break anything: ---\r\n\r\nthis :  that\r\nSentence: " + quickBrownFox + "\r\n---\r\n" + correctBody)
 | 
					"---\r\nFOO: baR\r\n   fOoo: Bar\r\nShouldn't break anything: ---\r\n\r\nthis :  that\r\nSentence: " + quickBrownFox + "\r\n---\r\n" + correctBody)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		test.Fatal(err)
 | 
							test.Fatal(err)
 | 
				
			||||||
@ -68,22 +68,22 @@ func TestSplitMetaCRLF (test *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	test.Log("META:")
 | 
						test.Log("META:")
 | 
				
			||||||
	test.Log(frontMatter)
 | 
						test.Log(meta)
 | 
				
			||||||
	value0, ok := frontMatter["foo"]
 | 
						if meta.Get("foo") != "baR" {
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	value1, ok := frontMatter["fooo"]
 | 
						}
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
						if meta.Get("fooo") != "Bar" {
 | 
				
			||||||
	value2, ok := frontMatter["shouldn't break anything"]
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
						}
 | 
				
			||||||
	value3, ok := frontMatter["this"]
 | 
						if meta.Get("shouldn't break anything") != "---" {
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	value4, ok := frontMatter["sentence"]
 | 
						}
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
						if meta.Get("this") != "that" {
 | 
				
			||||||
	if value0 != "baR"         { test.Fatal("value is not correct") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	if value1 != "Bar"         { test.Fatal("value is not correct") }
 | 
						}
 | 
				
			||||||
	if value2 != "---"         { test.Fatal("value is not correct") }
 | 
						if meta.Get("sentence") != quickBrownFox {
 | 
				
			||||||
	if value3 != "that"        { test.Fatal("value is not correct") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	if value4 != quickBrownFox { test.Fatal("value is not correct") }
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestParseMeta (test *testing.T) {
 | 
					func TestParseMeta (test *testing.T) {
 | 
				
			||||||
@ -99,13 +99,13 @@ number: 3849
 | 
				
			|||||||
	
 | 
						
 | 
				
			||||||
	test.Log("META:")
 | 
						test.Log("META:")
 | 
				
			||||||
	test.Log(meta)
 | 
						test.Log(meta)
 | 
				
			||||||
	value0, ok := meta["thing"]
 | 
						if meta.Get("thing") != "\tQuoted string!!!!!   " {
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	value1, ok := meta["other-thing"]
 | 
						}
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
						if meta.Get("other-thing") != "askdjlksajd" {
 | 
				
			||||||
	value2, ok := meta["number"]
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	if !ok { test.Fatal("missing key") }
 | 
						}
 | 
				
			||||||
	if value0 != "\tQuoted string!!!!!m   " { test.Fatal("value is not correct") }
 | 
						if meta.Get("number") != "3849" {
 | 
				
			||||||
	if value1 != "askdjlksajd"              { test.Fatal("value is not correct") }
 | 
							test.Fatal("value is not correct")
 | 
				
			||||||
	if value2 != "3849"                     { test.Fatal("value is not correct") }
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user