<|start_filename|>vendor/github.com/gorilla/handlers/handlers.go<|end_filename|>
// Copyright 2013 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package handlers

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

// MethodHandler is an http.Handler that dispatches to a handler whose key in the MethodHandler's
// map matches the name of the HTTP request's method, eg: GET
//
// If the request's method is OPTIONS and OPTIONS is not a key in the map then the handler
// responds with a status of 200 and sets the Allow header to a comma-separated list of
// available methods.
//
// If the request's method doesn't match any of its keys the handler responds with
// a status of 405, Method not allowed and sets the Allow header to a comma-separated list
// of available methods.
type MethodHandler map[string]http.Handler

func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if handler, ok := h[req.Method]; ok {
		handler.ServeHTTP(w, req)
	} else {
		allow := []string{}
		for k := range h {
			allow = append(allow, k)
		}
		sort.Strings(allow)
		w.Header().Set("Allow", strings.Join(allow, ", "))
		if req.Method == "OPTIONS" {
			w.WriteHeader(http.StatusOK)
		} else {
			http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		}
	}
}

// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
type loggingHandler struct {
	writer  io.Writer
	handler http.Handler
}

// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
type combinedLoggingHandler struct {
	writer  io.Writer
	handler http.Handler
}

func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	t := time.Now()
	var logger loggingResponseWriter
	if _, ok := w.(http.Hijacker); ok {
		logger = &hijackLogger{responseLogger: responseLogger{w: w}}
	} else {
		logger = &responseLogger{w: w}
	}
	url := *req.URL
	h.handler.ServeHTTP(logger, req)
	writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
}

func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	t := time.Now()
	var logger loggingResponseWriter
	if _, ok := w.(http.Hijacker); ok {
		logger = &hijackLogger{responseLogger: responseLogger{w: w}}
	} else {
		logger = &responseLogger{w: w}
	}
	url := *req.URL
	h.handler.ServeHTTP(logger, req)
	writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
}

type loggingResponseWriter interface {
	http.ResponseWriter
	Status() int
	Size() int
}

// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP status
// code and body size
type responseLogger struct {
	w      http.ResponseWriter
	status int
	size   int
}

func (l *responseLogger) Header() http.Header {
	return l.w.Header()
}

func (l *responseLogger) Write(b []byte) (int, error) {
	if l.status == 0 {
		// The status will be StatusOK if WriteHeader has not been called yet
		l.status = http.StatusOK
	}
	size, err := l.w.Write(b)
	l.size += size
	return size, err
}

func (l *responseLogger) WriteHeader(s int) {
	l.w.WriteHeader(s)
	l.status = s
}

func (l *responseLogger) Status() int {
	return l.status
}

func (l *responseLogger) Size() int {
	return l.size
}

type hijackLogger struct {
	responseLogger
}

func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	h := l.responseLogger.w.(http.Hijacker)
	conn, rw, err := h.Hijack()
	if err == nil && l.responseLogger.status == 0 {
		// The status will be StatusSwitchingProtocols if there was no error and WriteHeader has not been called yet
		l.responseLogger.status = http.StatusSwitchingProtocols
	}
	return conn, rw, err
}

const lowerhex = "0123456789abcdef"

func appendQuoted(buf []byte, s string) []byte {
	var runeTmp [utf8.UTFMax]byte
	for width := 0; len(s) > 0; s = s[width:] {
		r := rune(s[0])
		width = 1
		if r >= utf8.RuneSelf {
			r, width = utf8.DecodeRuneInString(s)
		}
		if width == 1 && r == utf8.RuneError {
			buf = append(buf, `\x`...)
			buf = append(buf, lowerhex[s[0]>>4])
			buf = append(buf, lowerhex[s[0]&0xF])
			continue
		}
		if r == rune('"') || r == '\\' { // always backslashed
			buf = append(buf, '\\')
			buf = append(buf, byte(r))
			continue
		}
		if strconv.IsPrint(r) {
			n := utf8.EncodeRune(runeTmp[:], r)
			buf = append(buf, runeTmp[:n]...)
			continue
		}
		switch r {
		case '\a':
			buf = append(buf, `\a`...)
		case '\b':
			buf = append(buf, `\b`...)
		case '\f':
			buf = append(buf, `\f`...)
		case '\n':
			buf = append(buf, `\n`...)
		case '\r':
			buf = append(buf, `\r`...)
		case '\t':
			buf = append(buf, `\t`...)
		case '\v':
			buf = append(buf, `\v`...)
		default:
			switch {
			case r < ' ':
				buf = append(buf, `\x`...)
				buf = append(buf, lowerhex[s[0]>>4])
				buf = append(buf, lowerhex[s[0]&0xF])
			case r > utf8.MaxRune:
				r = 0xFFFD
				fallthrough
			case r < 0x10000:
				buf = append(buf, `\u`...)
				for s := 12; s >= 0; s -= 4 {
					buf = append(buf, lowerhex[r>>uint(s)&0xF])
				}
			default:
				buf = append(buf, `\U`...)
				for s := 28; s >= 0; s -= 4 {
					buf = append(buf, lowerhex[r>>uint(s)&0xF])
				}
			}
		}
	}
	return buf

}

// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
	username := "-"
	if url.User != nil {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	uri := url.RequestURI()

	buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
	buf = append(buf, host...)
	buf = append(buf, " - "...)
	buf = append(buf, username...)
	buf = append(buf, " ["...)
	buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
	buf = append(buf, `] "`...)
	buf = append(buf, req.Method...)
	buf = append(buf, " "...)
	buf = appendQuoted(buf, uri)
	buf = append(buf, " "...)
	buf = append(buf, req.Proto...)
	buf = append(buf, `" `...)
	buf = append(buf, strconv.Itoa(status)...)
	buf = append(buf, " "...)
	buf = append(buf, strconv.Itoa(size)...)
	return buf
}

// writeLog writes a log entry for req to w in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
	buf := buildCommonLogLine(req, url, ts, status, size)
	buf = append(buf, '\n')
	w.Write(buf)
}

// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
	buf := buildCommonLogLine(req, url, ts, status, size)
	buf = append(buf, ` "`...)
	buf = appendQuoted(buf, req.Referer())
	buf = append(buf, `" "`...)
	buf = appendQuoted(buf, req.UserAgent())
	buf = append(buf, '"', '\n')
	w.Write(buf)
}

// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Combined Log Format.
//
// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
	return combinedLoggingHandler{out, h}
}

// LoggingHandler return a http.Handler that wraps h and logs requests to out in
// Apache Common Log Format (CLF).
//
// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
//
// LoggingHandler always sets the ident field of the log to -
func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
	return loggingHandler{out, h}
}

// isContentType validates the Content-Type header
// is contentType. That is, its type and subtype match.
func isContentType(h http.Header, contentType string) bool {
	ct := h.Get("Content-Type")
	if i := strings.IndexRune(ct, ';'); i != -1 {
		ct = ct[0:i]
	}
	return ct == contentType
}

// ContentTypeHandler wraps and returns a http.Handler, validating the request content type
// is acompatible with the contentTypes list.
// It writes a HTTP 415 error if that fails.
//
// Only PUT, POST, and PATCH requests are considered.
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if !(r.Method == "PUT" || r.Method == "POST" || r.Method == "PATCH") {
			h.ServeHTTP(w, r)
			return
		}

		for _, ct := range contentTypes {
			if isContentType(r.Header, ct) {
				h.ServeHTTP(w, r)
				return
			}
		}
		http.Error(w, fmt.Sprintf("Unsupported content type %q; expected one of %q", r.Header.Get("Content-Type"), contentTypes), http.StatusUnsupportedMediaType)
	})
}

const (
	// HTTPMethodOverrideHeader is a commonly used
	// http header to override a request method.
	HTTPMethodOverrideHeader = "X-HTTP-Method-Override"
	// HTTPMethodOverrideFormKey is a commonly used
	// HTML form key to override a request method.
	HTTPMethodOverrideFormKey = "_method"
)

// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for the X-HTTP-Method-Override header
// or the _method form key, and overrides (if valid) request.Method with its value.
//
// This is especially useful for http clients that don't support many http verbs.
// It isn't secure to override e.g a GET to a POST, so only POST requests are considered.
// Likewise, the override method can only be a "write" method: PUT, PATCH or DELETE.
//
// Form method takes precedence over header method.
func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "POST" {
			om := r.FormValue(HTTPMethodOverrideFormKey)
			if om == "" {
				om = r.Header.Get(HTTPMethodOverrideHeader)
			}
			if om == "PUT" || om == "PATCH" || om == "DELETE" {
				r.Method = om
			}
		}
		h.ServeHTTP(w, r)
	})
}


<|start_filename|>web/view/viewmodel/tagcloud.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

import (
	"sort"
)

type TagCloud []TagCloudEntry

type TagCloudEntry struct {
	Name           string `json:"name"`
	Anchor         string `json:"anchor"`
	Route          string `json:"route"`
	Level          int    `json:"level"`
	NumberOfChildren int    `json:"numberofchildren"`
}

type SortTagCloudBy func(tagCloudEntry1, tagCloudEntry2 TagCloudEntry) bool

func (by SortTagCloudBy) Sort(tagCloud TagCloud) {
	sorter := &tagCloudSorter{
		tagCloud: tagCloud,
		by:       by,
	}

	sort.Sort(sorter)
}

type tagCloudSorter struct {
	tagCloud TagCloud
	by       SortTagCloudBy
}

func (sorter *tagCloudSorter) Len() int {
	return len(sorter.tagCloud)
}

func (sorter *tagCloudSorter) Swap(i, j int) {
	sorter.tagCloud[i], sorter.tagCloud[j] = sorter.tagCloud[j], sorter.tagCloud[i]
}

func (sorter *tagCloudSorter) Less(i, j int) bool {
	return sorter.by(sorter.tagCloud[i], sorter.tagCloud[j])
}


<|start_filename|>common/tree/tree_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tree

import (
	"testing"
)

func Test_New_ResultNotNil(t *testing.T) {
	// act
	tree := New("root", nil)

	// assert
	if tree == nil {
		t.Errorf("New returned %s, but New should never return nil.", tree)
	}
}

func Test_New_RootNotNil(t *testing.T) {
	// act
	tree := New("Root", nil)

	// assert
	if tree.Root() == nil {
		t.Errorf("The Root of a new tree should not be nil.")
	}
}

func Test_New_NameOfRootIsSet(t *testing.T) {
	// act
	name := "Root"
	tree := New(name, nil)

	// assert
	if tree.Root().Name() != name {
		t.Errorf("The Name of the a new tree should be %q but was %q", name, tree.Root().Name())
	}
}

func Test_Tree_String_EmptyTree(t *testing.T) {
	// arrange
	tree := &Tree{}

	// act
	result := tree.String()

	// assert
	expected := "<empty-tree>"
	if result != expected {
		t.Errorf("The string method of an empty tree should return %q but returned %q instead.", expected, result)
	}
}

func Test_Tree_String_NonEmptyTree(t *testing.T) {
	// arrange
	tree := New("root", nil)
	tree.Insert(NewPath("root level child 1", "2nd level child"), nil)
	tree.Insert(NewPath("root level child 2", "2nd level child"), nil)

	// act
	result := tree.String()

	// assert
	expected := `- root
    - root level child 1
        - 2nd level child
    - root level child 2
        - 2nd level child`
	if result != expected {
		t.Errorf("The string method of the tree should return %q but returned %q instead.", expected, result)
	}
}

func Test_Tree_Insert_ValidPath_ResultIsTrue(t *testing.T) {
	// arrange
	tree := New("root", nil)

	// act
	result, _ := tree.Insert(NewPath("child 1"), nil)

	// assert
	expected := true
	if result != expected {
		t.Errorf("The Insert method should return %q when a valid path is inserted but returned %q instead.", expected, result)
	}
}

func Test_Tree_Insert_InvalidPath_ResultIsFalse(t *testing.T) {
	// arrange
	tree := New("root", nil)

	// act
	result, _ := tree.Insert(NewPath("child 1 / dasdasd"), nil)

	// assert
	expected := false
	if result != expected {
		t.Errorf("The Insert method should return %q when an invalid path is inserted but returned %q instead.", expected, result)
	}
}

func Test_Tree_Insert_EmptyPath_ResultIsTrue(t *testing.T) {
	// arrange
	tree := New("root", nil)

	// act
	result, _ := tree.Insert(NewPath(), nil)

	// assert
	if result != true {
		t.Errorf("Inserting an empty path should be possible. The root should be overriden but wasn't.")
	}
}

func Test_Tree_Insert_TwoPaths_StructureIsAsExpected(t *testing.T) {
	// arrange
	tree := New("root", nil)

	// act
	tree.Insert(NewPath("child 1"), nil)
	tree.Insert(NewPath("child 2"), nil)

	// assert
	result := tree.String()
	expected := `- root
    - child 1
    - child 2`
	if result != expected {
		t.Errorf("The tree structure should look like this %q but actually looks loke this %q instead.", expected, result)
	}
}

func Test_Tree_Insert_ExistingTree_TreeIsUpdated(t *testing.T) {
	// arrange
	tree := New("root", nil)
	tree.Insert(NewPath("child 1"), nil)
	tree.Insert(NewPath("child 2", "sub child 1"), nil)
	tree.Insert(NewPath("child 2", "sub child 2 - to be updated"), nil)
	tree.Insert(NewPath("child 2", "sub child 3"), nil)
	tree.Insert(NewPath("child 3"), nil)

	// act
	tree.Insert(NewPath("child 2", "sub child 2 - to be updated", "new child"), nil)

	// assert
	result := tree.String()
	expected := `- root
    - child 1
    - child 2
        - sub child 1
        - sub child 2 - to be updated
            - new child
        - sub child 3
    - child 3`

	if result != expected {
		t.Errorf("The tree structure should look like this %q but actually looks loke this %q instead.", expected, result)
	}
}

func Test_Tree_Delete_ValidPath_ResultIsTrue(t *testing.T) {
	// arrange
	tree := New("root", nil)
	tree.Insert(NewPath("child 1"), nil)

	// act
	result, _ := tree.Delete(NewPath("child 1"))

	// assert
	expected := true
	if result != expected {
		t.Errorf("The Delete method should return %q when a valid path is deleted but returned %q instead.", expected, result)
	}
}

func Test_Tree_Delete_InvalidPath_ResultIsFalse(t *testing.T) {
	// arrange
	tree := New("root", nil)

	// act
	result, _ := tree.Delete(NewPath("child 1 / dasdasd"))

	// assert
	expected := false
	if result != expected {
		t.Errorf("The Delete method should return %q when an invalid path is deleted but returned %q instead.", expected, result)
	}
}

func Test_Tree_Delete_EmptyPath_ResultIsFalse(t *testing.T) {
	// arrange
	tree := New("root", nil)

	// act
	result, _ := tree.Delete(NewPath())

	// assert
	expected := false
	if result != expected {
		t.Errorf("The Delete method should return %q when an invalid path is deleted but returned %q instead.", expected, result)
	}
}

func Test_Tree_Delete_ThirdChild_StructureIsAsExpected(t *testing.T) {
	// arrange
	tree := New("root", nil)
	tree.Insert(NewPath("child 1"), nil)
	tree.Insert(NewPath("child 2"), nil)
	tree.Insert(NewPath("child 3"), nil)

	// act
	result, _ := tree.Delete(NewPath("child 3"))

	// assert result
	expected := true
	if result != expected {
		t.Errorf("The Delete method should return %q when an invalid path is deleted but returned %q instead.", expected, result)
	}

	// assert: structure
	stringResult := tree.String()
	expectedStringResult := `- root
    - child 1
    - child 2`
	if stringResult != expectedStringResult {
		t.Errorf("The tree structure should look like this %q but actually looks loke this %q instead.", expectedStringResult, stringResult)
	}
}

func Test_Tree_GetNode_EmptyTree_ResultIsNil(t *testing.T) {
	// arrange
	tree := &Tree{}

	path := NewPath("root", "child 2")
	var expected *Node

	// act
	result := tree.GetNode(path)

	// assert
	if result != expected {
		t.Errorf("Requesting a node from an empty tree should always return %q but returned %q instead.", expected, result)
	}
}

func Test_Tree_GetNode_InvalidPath_ResultIsNil(t *testing.T) {
	// arrange
	tree := New("root", nil)
	tree.Insert(NewPath("child 1"), nil)
	tree.Insert(NewPath("child 2", "sub child 1"), nil)
	tree.Insert(NewPath("child 2", "sub child 2"), nil)
	tree.Insert(NewPath("child 2", "sub child 3"), nil)
	tree.Insert(NewPath("child 3"), nil)

	path := NewPath("root", "child 2", "sad ads / dasdsadsa")
	var expected *Node

	// act
	result := tree.GetNode(path)

	// assert
	if result != expected {
		t.Errorf("Requesting a node from a tree with an invalid path %q should return %q but returned %q instead.", path, expected, result)
	}
}

func Test_Tree_GetNode_ComplexTree_ExistingPath_ResultIsNotNull(t *testing.T) {
	// arrange
	tree := New("root", nil)
	tree.Insert(NewPath("child 1"), nil)
	tree.Insert(NewPath("child 2", "sub child 1"), nil)
	tree.Insert(NewPath("child 2", "sub child 2"), nil)
	tree.Insert(NewPath("child 2", "sub child 3"), nil)
	tree.Insert(NewPath("child 3"), nil)

	path := NewPath("child 2", "sub child 2")

	// act
	result := tree.GetNode(path)

	// assert
	if result == nil {
		t.Errorf("Requesting a node from the tree %s with the path %q should return a node but returned %q instead.", tree, path, result)
	}
}


<|start_filename|>web/view/viewmodel/update.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type Update struct {
	Model

	Snippets map[string]string `json:"snippets"`
}


<|start_filename|>common/route/route_parent_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package route

import (
	"testing"
)

func Test_IsParentOf_RouteIsFirstLevelChild_ResultIsTrue(t *testing.T) {
	// arrange
	parent := NewFromRequest("/documents/Collection")
	child := NewFromRequest("/documents/Collection/Level-1")

	// act
	result := parent.IsParentOf(child)

	// assert
	if !result {
		t.Errorf("%q is a 1st level parent of %q. The result should be true but was %t.", child, parent, result)
	}
}

func Test_IsParentOf_RouteIsSecondLevelChild_ResultIsFalse(t *testing.T) {
	// arrange
	parent := NewFromRequest("/documents/Collection")
	child := NewFromRequest("/documents/Collection/Level-1/Level-2")

	// act
	result := parent.IsParentOf(child)

	// assert
	if result {
		t.Errorf("%q is only a 2nd level parent of %q. The result should be false but was %t.", child, parent, result)
	}
}

func Test_IsParentOf_RouteIsNotAParent_ResultIsFalse(t *testing.T) {
	// arrange
	parent := NewFromRequest("/documents/Collection")
	child := NewFromRequest("/pictures/Test-1")

	// act
	result := parent.IsParentOf(child)

	// assert
	if result {
		t.Errorf("%q is not a parent of %q. The result should be false but was %t.", child, parent, result)
	}
}

func Test_Parent_RouteHasAParent_ResultIsNotEmpty(t *testing.T) {
	// arrange
	route := NewFromRequest("/documents/Collection")

	// act
	result, _ := route.Parent()

	// assert
	if result.IsEmpty() {
		t.Errorf("%q does have a parent but the result was %q.", route, result)
	}
}

func Test_Parent_RouteHasAParent_ResultIsCorrect(t *testing.T) {
	// arrange
	route := NewFromRequest("/documents/Collection")

	// act
	result, _ := route.Parent()

	// assert
	expected := "documents"
	if result.String() != expected {
		t.Errorf("%q should have a parent %q but the result was %q.", route, expected, result)
	}
}

func Test_Parent_RouteHasNoParent_ResultIsEmpty(t *testing.T) {
	// arrange
	route := NewFromRequest("/documents")

	// act
	result, _ := route.Parent()

	// assert
	if !result.IsEmpty() {
		t.Errorf("%q should have no parent but the result was %q.", route, result)
	}
}


<|start_filename|>common/config/constants.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !windows

package config

const (
	DefaultConversionToolPath = "pandoc"
)


<|start_filename|>common/tree/path.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tree

import (
	"fmt"
	"strings"
)

func NewPath(component ...string) Path {
	return component
}

type Path []string

func (path Path) String() string {
	if path.IsEmpty() {
		return "<empty-path>"
	}

	return strings.Join(path, " > ")
}

func (path Path) IsEmpty() bool {
	return len(path) == 0
}

func (path Path) IsRootPath() bool {
	// contains only one component and this component is empty
	return len(path) == 1 && path[0] == ""
}

// Checks whether all components of the current path are valid (not empty, and don't contain slashes).
func (path Path) IsValid() (bool, error) {

	// abort if its a root path
	if path.IsRootPath() || path.IsEmpty() {
		return true, nil
	}

	for _, component := range path {
		if isValidComponent, errMessage := isValidPathComponent(component); !isValidComponent {
			return false, errMessage
		}
	}

	return true, nil
}

func isValidPathComponent(component string) (bool, error) {

	// empty
	if isEmpty := component == ""; isEmpty {
		return false, fmt.Errorf("Path component cannot be empty")
	}

	// forward slashes
	if containsForwardSlash := strings.Contains(component, "/"); containsForwardSlash {
		return false, fmt.Errorf("Path components cannot contain forward slashes (/).")
	}

	// backslash
	if containsBackslash := strings.Contains(component, `\`); containsBackslash {
		return false, fmt.Errorf(`Path components cannot contain backslashes (\).`)
	}

	return true, nil
}

func pathToNode(path Path, value interface{}) *Node {

	length := len(path)
	if length == 0 {
		return nil
	}

	var firstNode *Node

	var parent *Node
	for index, component := range path {

		var nodeValue interface{}
		if isLastComponent := index+1 == length; isLastComponent {
			nodeValue = value
		}

		node := newNode(parent, component, nodeValue)

		// capture the first node
		if isFirstNode := parent == nil; isFirstNode {
			firstNode = node
		}

		// make this node the parent for the next node
		parent = node
	}

	return firstNode
}


<|start_filename|>web/view/viewmodel/breadcrumbnavigation.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type BreadcrumbNavigation struct {
	Entries []Breadcrumb `json:"entries"`
}

func (navigation BreadcrumbNavigation) IsAvailable() bool {
	return len(navigation.Entries) > 0
}

type Breadcrumb struct {
	Level  int    `json:"level"`
	Title  string `json:"title"`
	Path   string `json:"path"`
	IsLast bool
}


<|start_filename|>services/imageconversion/resizer.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package imageconversion

import (
	"fmt"
	"github.com/nfnt/resize"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"strings"
)

func MimeTypeIsSupported(mimeType string) bool {

	switch mimeType {
	case "image/png", "image/jpeg":
		return true

	default:
		return false
	}

	panic("Unreachable")
}

func GetFileExtensionFromMimeType(mimeType string) string {
	switch mimeType {

	case "image/png":
		return "png"

	case "image/jpeg":
		return "jpg"

	default:
		return strings.ToLower(strings.Replace(mimeType, "image/", "", 1))

	}

	panic("Unreachable")
}

func Resize(source io.Reader, mimeType string, width, height uint, target io.Writer) error {

	// check the mime type
	if !MimeTypeIsSupported(mimeType) {
		return fmt.Errorf("The mime-type %q is currently not supported.", mimeType)
	}

	// read the source image
	img, err := decode(source, mimeType)
	if err != nil {
		return err
	}

	// resize the source image
	thumb := resize.Thumbnail(width, height, img, resize.Lanczos3)

	// write the thumbnail to the target
	return encode(mimeType, thumb, target)
}

func encode(mimeType string, thumb image.Image, target io.Writer) error {

	switch mimeType {

	case "image/png":
		return png.Encode(target, thumb)

	case "image/jpeg":
		return jpeg.Encode(target, thumb, nil)

	default:
		return fmt.Errorf("Unsupported mime type %s", mimeType)

	}

	panic("Unreachable")
}

func decode(source io.Reader, mimeType string) (image.Image, error) {

	switch mimeType {

	case "image/png":
		return png.Decode(source)

	case "image/jpeg":
		return jpeg.Decode(source)

	default:
		return nil, fmt.Errorf("Unsupported mime type %s", mimeType)

	}

	panic("Unreachable")
}


<|start_filename|>vendor/github.com/arnoSCC/fulltext/indexer.go<|end_filename|>
package fulltext

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"github.com/jbarham/go-cdb"
	"github.com/spf13/afero"
	"io"
)

// Size of header block to prepend - make it 4k to align disk reads
const HEADER_SIZE = 4096

// Produces a set of cdb files from a series of AddDoc() calls
type Indexer struct {
	filesystem  afero.Fs
	docTxtFile  afero.File
	wordTxtFile afero.File
	docCdbFile  afero.File
	wordCdbFile afero.File
	wordMap     map[string]map[string]int // map of [word][docId]count
	WordSplit   WordSplitter
	WordClean   WordCleaner
}

// Contents of a single document to be indexed
type IndexDoc struct {
	Id         []byte // the id, this is usually the path to the document
	IndexValue []byte // index this data
	StoreValue []byte // store this data
}

// NewIndexer creates a new indexer.
func NewIndexer() (*Indexer, error) {

	var indexFs afero.Fs = &afero.MemMapFs{}

	idx := &Indexer{}
	idx.filesystem = indexFs

	docTxtFile, err := indexFs.Create("doctmp")
	if err != nil {
		return nil, err
	}

	wordTxtFile, err := indexFs.Create("wordtmp")
	if err != nil {
		return nil, err
	}

	docCdbFile, err := indexFs.Create("doccdb")
	if err != nil {
		return nil, err
	}

	wordCdbFile, err := indexFs.Create("wordcdb")
	if err != nil {
		return nil, err
	}

	idx.docTxtFile = docTxtFile
	idx.wordTxtFile = wordTxtFile
	idx.docCdbFile = docCdbFile
	idx.wordCdbFile = wordCdbFile
	idx.wordMap = make(map[string]map[string]int)
	idx.WordSplit = Wordize
	idx.WordClean = IndexizeWord

	return idx, nil
}

// Add a document to the index - writes to temporary files and stores some data in memory while building the index.
func (idx *Indexer) AddDoc(idoc IndexDoc) error {
	// add to docs
	docId := string(idoc.Id)
	writeTextLine(idx.docTxtFile, []byte(docId), idoc.StoreValue)
	words := append(idx.WordSplit(string(idoc.IndexValue)), idx.WordSplit(string(idoc.StoreValue))...)
	for _, word := range words {
		word = idx.WordClean(word)
		// ensure nested map exists
		if idx.wordMap[word] == nil {
			idx.wordMap[word] = make(map[string]int)
		}
		// increment count by one for this combination
		c := idx.wordMap[word][docId] + 1
		idx.wordMap[word][docId] = c
	}
	return nil
}

// Builds a final single index file, which consists of some simple header info,
// followed by the cdb binary files that comprise the full index.
func (idx *Indexer) FinalizeAndWrite(w io.Writer) error {

	var buf bytes.Buffer

	// write out the word data
	for word, m := range idx.wordMap {
		enc := gob.NewEncoder(&buf)
		enc.Encode(m)
		writeTextLine(idx.wordTxtFile, []byte(word), buf.Bytes())
		buf.Reset()
	}

	var err error

	idx.docTxtFile.Write([]byte("\n"))
	idx.wordTxtFile.Write([]byte("\n"))

	_, err = idx.docTxtFile.Seek(0, 0)
	if err != nil {
		return err
	}
	_, err = idx.wordTxtFile.Seek(0, 0)
	if err != nil {
		return err
	}

	// make cdb files
	err = cdb.Make(idx.docCdbFile, idx.docTxtFile)
	if err != nil {
		return err
	}
	err = cdb.Make(idx.wordCdbFile, idx.wordTxtFile)
	if err != nil {
		return err
	}

	// make sure the contents are all settled
	_, err = idx.docCdbFile.Seek(0, 0)
	if err != nil {
		return err
	}
	_, err = idx.wordCdbFile.Seek(0, 0)
	if err != nil {
		return err
	}

	docStat, err := idx.docCdbFile.Stat()
	if err != nil {
		return err
	}
	wordStat, err := idx.wordCdbFile.Stat()
	if err != nil {
		return err
	}

	// now package it all up
	buf.Reset()
	enc := gob.NewEncoder(&buf)
	bhead := []int{int(docStat.Size()), int(wordStat.Size())}
	enc.Encode(bhead)

	// extend buffer to be HEADER_SIZE len
	bpadsize := HEADER_SIZE - buf.Len()
	buf.Write(make([]byte, bpadsize, bpadsize))
	b := buf.Bytes()

	_, err = w.Write(b)
	if err != nil {
		return err
	}

	_, err = io.Copy(w, idx.docCdbFile)
	if err != nil {
		return err
	}
	_, err = io.Copy(w, idx.wordCdbFile)
	if err != nil {
		return err
	}

	return nil
}

// close and remove all resources
func (idx *Indexer) Close() {
	idx.docTxtFile.Close()
	idx.wordTxtFile.Close()
	idx.docCdbFile.Close()
	idx.wordCdbFile.Close()
	idx.wordMap = nil
}

// Write a single line of data in cdb's text format
func writeTextLine(w io.Writer, key []byte, data []byte) (err error) {
	_, err = fmt.Fprintf(w, "+%d,%d:%s->%s\n", len(key), len(data), key, data)
	return
}


<|start_filename|>vendor/github.com/jbarham/go-cdb/make.go<|end_filename|>
package cdb

import (
	"bufio"
	"encoding/binary"
	"errors"
	"io"
	"strconv"
)

var BadFormatError = errors.New("bad format")

// Make reads cdb-formatted records from r and writes a cdb-format database
// to w.  See the documentation for Dump for details on the input record format. 
func Make(w io.WriteSeeker, r io.Reader) (err error) {
	defer func() { // Centralize error handling.
		if e := recover(); e != nil {
			err = e.(error)
		}
	}()

	if _, err = w.Seek(int64(headerSize), 0); err != nil {
		return
	}

	buf := make([]byte, 8)
	rb := bufio.NewReader(r)
	wb := bufio.NewWriter(w)
	hash := cdbHash()
	hw := io.MultiWriter(hash, wb) // Computes hash when writing record key.
	rr := &recReader{rb}
	htables := make(map[uint32][]slot)
	pos := headerSize
	// Read all records and write to output.
	for {
		// Record format is "+klen,dlen:key->data\n"
		c := rr.readByte()
		if c == '\n' { // end of records
			break
		}
		if c != '+' {
			return BadFormatError
		}
		klen, dlen := rr.readNum(','), rr.readNum(':')
		writeNums(wb, klen, dlen, buf)
		hash.Reset()
		rr.copyn(hw, klen)
		rr.eatByte('-')
		rr.eatByte('>')
		rr.copyn(wb, dlen)
		rr.eatByte('\n')
		h := hash.Sum32()
		tableNum := h % 256
		htables[tableNum] = append(htables[tableNum], slot{h, pos})
		pos += 8 + klen + dlen
	}

	// Write hash tables and header.

	// Create and reuse a single hash table.
	maxSlots := 0
	for _, slots := range htables {
		if len(slots) > maxSlots {
			maxSlots = len(slots)
		}
	}
	slotTable := make([]slot, maxSlots*2)

	header := make([]byte, headerSize)
	// Write hash tables.
	for i := uint32(0); i < 256; i++ {
		slots := htables[i]
		if slots == nil {
			putNum(header[i*8:], pos)
			continue
		}

		nslots := uint32(len(slots) * 2)
		hashSlotTable := slotTable[:nslots]
		// Reset table slots.
		for j := 0; j < len(hashSlotTable); j++ {
			hashSlotTable[j].h = 0
			hashSlotTable[j].pos = 0
		}

		for _, slot := range slots {
			slotPos := (slot.h / 256) % nslots
			for hashSlotTable[slotPos].pos != 0 {
				slotPos++
				if slotPos == uint32(len(hashSlotTable)) {
					slotPos = 0
				}
			}
			hashSlotTable[slotPos] = slot
		}

		if err = writeSlots(wb, hashSlotTable, buf); err != nil {
			return
		}

		putNum(header[i*8:], pos)
		putNum(header[i*8+4:], nslots)
		pos += 8 * nslots
	}

	if err = wb.Flush(); err != nil {
		return
	}

	if _, err = w.Seek(0, 0); err != nil {
		return
	}

	_, err = w.Write(header)

	return
}

type recReader struct {
	*bufio.Reader
}

func (rr *recReader) readByte() byte {
	c, err := rr.ReadByte()
	if err != nil {
		panic(err)
	}

	return c
}

func (rr *recReader) eatByte(c byte) {
	if rr.readByte() != c {
		panic(errors.New("unexpected character"))
	}
}

func (rr *recReader) readNum(delim byte) uint32 {
	s, err := rr.ReadString(delim)
	if err != nil {
		panic(err)
	}

	s = s[:len(s)-1] // Strip delim
	n, err := strconv.ParseUint(s, 10, 32)
	if err != nil {
		panic(err)
	}

	return uint32(n)
}

func (rr *recReader) copyn(w io.Writer, n uint32) {
	if _, err := io.CopyN(w, rr, int64(n)); err != nil {
		panic(err)
	}
}

func putNum(buf []byte, x uint32) {
	binary.LittleEndian.PutUint32(buf, x)
}

func writeNums(w io.Writer, x, y uint32, buf []byte) {
	putNum(buf, x)
	putNum(buf[4:], y)
	if _, err := w.Write(buf[:8]); err != nil {
		panic(err)
	}
}

type slot struct {
	h, pos uint32
}

func writeSlots(w io.Writer, slots []slot, buf []byte) (err error) {
	for _, np := range slots {
		putNum(buf, np.h)
		putNum(buf[4:], np.pos)
		if _, err = w.Write(buf[:8]); err != nil {
			return
		}
	}

	return nil
}


<|start_filename|>common/route/util.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package route

import (
	"strings"
)

func ToKey(route Route) string {
	return route.Value()
}

func EncodeURL(rawURL string) string {
	encodedURL := strings.Replace(rawURL, "%", "%25", -1)
	encodedURL = strings.Replace(encodedURL, "+", "%2B", -1)
	encodedURL = strings.Replace(encodedURL, " ", "+", -1)
	encodedURL = strings.Replace(encodedURL, "#", "%23", -1)
	encodedURL = strings.Replace(encodedURL, "$", "%24", -1)
	encodedURL = strings.Replace(encodedURL, "&", "%26", -1)
	encodedURL = strings.Replace(encodedURL, ",", "%2C", -1)
	encodedURL = strings.Replace(encodedURL, ":", "%3A", -1)
	encodedURL = strings.Replace(encodedURL, ";", "%3B", -1)
	encodedURL = strings.Replace(encodedURL, "=", "%3D", -1)
	encodedURL = strings.Replace(encodedURL, "?", "%3F", -1)
	encodedURL = strings.Replace(encodedURL, "@", "%40", -1)
	return encodedURL
}

func DecodeURL(encodedURL string) string {
	decodedURL := strings.Replace(encodedURL, "%25", "%", -1)
	decodedURL = strings.Replace(decodedURL, "%20", " ", -1)
	decodedURL = strings.Replace(decodedURL, "%23", "#", -1)
	decodedURL = strings.Replace(decodedURL, "%24", "$", -1)
	decodedURL = strings.Replace(decodedURL, "%26", "&", -1)
	decodedURL = strings.Replace(decodedURL, "+", " ", -1)
	decodedURL = strings.Replace(decodedURL, "%2B", "+", -1)
	decodedURL = strings.Replace(decodedURL, "%2C", ",", -1)
	decodedURL = strings.Replace(decodedURL, "%3A", ":", -1)
	decodedURL = strings.Replace(decodedURL, "%3B", ";", -1)
	decodedURL = strings.Replace(decodedURL, "%3D", "=", -1)
	decodedURL = strings.Replace(decodedURL, "%3F", "?", -1)
	decodedURL = strings.Replace(decodedURL, "%40", "@", -1)
	return decodedURL
}


<|start_filename|>vendor/github.com/jbarham/go-cdb/cdb_test.go<|end_filename|>
package cdb

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"testing"
)

type rec struct {
	key    string
	values []string
}

var records = []rec{
	{"one", []string{"1"}},
	{"two", []string{"2", "22"}},
	{"three", []string{"3", "33", "333"}},
}

var data []byte // set by init()

func TestCdb(t *testing.T) {
	tmp, err := ioutil.TempFile("", "")
	if err != nil {
		t.Fatalf("Failed to create temp file: %s", err)
	}

	defer os.Remove(tmp.Name())

	// Test Make
	err = Make(tmp, bytes.NewBuffer(data))
	if err != nil {
		t.Fatalf("Make failed: %s", err)
	}

	// Test reading records
	c, err := Open(tmp.Name())
	if err != nil {
		t.Fatalf("Error opening %s: %s", tmp.Name(), err)
	}

	_, err = c.Data([]byte("does not exist"))
	if err != io.EOF {
		t.Fatalf("non-existent key should return io.EOF")
	}

	for _, rec := range records {
		key := []byte(rec.key)
		values := rec.values

		v, err := c.Data(key)
		if err != nil {
			t.Fatalf("Record read failed: %s", err)
		}

		if !bytes.Equal(v, []byte(values[0])) {
			t.Fatal("Incorrect value returned")
		}

		c.FindStart()
		for _, value := range values {
			sr, err := c.FindNext(key)
			if err != nil {
				t.Fatalf("Record read failed: %s", err)
			}

			data := make([]byte, sr.Size())
			_, err = sr.Read(data)
			if err != nil {
				t.Fatalf("Record read failed: %s", err)
			}

			if !bytes.Equal(data, []byte(value)) {
				t.Fatal("value mismatch")
			}
		}
		// Read all values, so should get EOF
		_, err = c.FindNext(key)
		if err != io.EOF {
			t.Fatalf("Expected EOF, got %s", err)
		}
	}

	// Test Dump
	if _, err = tmp.Seek(0, 0); err != nil {
		t.Fatal(err)
	}

	buf := bytes.NewBuffer(nil)
	err = Dump(buf, tmp)
	if err != nil {
		t.Fatalf("Dump failed: %s", err)
	}

	if !bytes.Equal(buf.Bytes(), data) {
		t.Fatalf("Dump round-trip failed")
	}
}

func TestEmptyFile(t *testing.T) {
	tmp, err := ioutil.TempFile("", "")
	if err != nil {
		t.Fatalf("Failed to create temp file: %s", err)
	}

	defer os.Remove(tmp.Name())

	// Test Make
	err = Make(tmp, bytes.NewBuffer([]byte("\n\n")))
	if err != nil {
		t.Fatalf("Make failed: %s", err)
	}

	// Check that all tables are length 0
	if _, err = tmp.Seek(0, 0); err != nil {
		t.Fatal(err)
	}
	rb := bufio.NewReader(tmp)
	readNum := makeNumReader(rb)
	for i := 0; i < 256; i++ {
		_ = readNum() // table pointer
		tableLen := readNum()
		if tableLen != 0 {
			t.Fatalf("table %d has non-zero length: %d", i, tableLen)
		}
	}

	// Test reading records
	c, err := Open(tmp.Name())
	if err != nil {
		t.Fatalf("Error opening %s: %s", tmp.Name(), err)
	}

	_, err = c.Data([]byte("does not exist"))
	if err != io.EOF {
		t.Fatalf("non-existent key should return io.EOF")
	}
}

func init() {
	b := bytes.NewBuffer(nil)
	for _, rec := range records {
		key := rec.key
		for _, value := range rec.values {
			b.WriteString(fmt.Sprintf("+%d,%d:%s->%s\n", len(key), len(value), key, value))
		}
	}
	b.WriteByte('\n')
	data = b.Bytes()
}


<|start_filename|>vendor/github.com/jbarham/go-cdb/dump.go<|end_filename|>
package cdb

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"io"
)

// Dump reads the cdb-formatted data in r and dumps it as a series of formatted
// records (+klen,dlen:key->data\n) and a final newline to w.
// The output of Dump is suitable as input to Make.
// See http://cr.yp.to/cdb/cdbmake.html for details on the record format.
func Dump(w io.Writer, r io.Reader) (err error) {
	defer func() { // Centralize exception handling.
		if e := recover(); e != nil {
			err = e.(error)
		}
	}()

	rb := bufio.NewReader(r)
	readNum := makeNumReader(rb)
	rw := &recWriter{bufio.NewWriter(w)}

	eod := readNum()
	// Read rest of header.
	for i := 0; i < 511; i++ {
		readNum()
	}

	pos := headerSize
	for pos < eod {
		klen, dlen := readNum(), readNum()
		rw.writeString(fmt.Sprintf("+%d,%d:", klen, dlen))
		rw.copyn(rb, klen)
		rw.writeString("->")
		rw.copyn(rb, dlen)
		rw.writeString("\n")
		pos += 8 + klen + dlen
	}
	rw.writeString("\n")

	return rw.Flush()
}

func makeNumReader(r io.Reader) func() uint32 {
	buf := make([]byte, 4)
	return func() uint32 {
		if _, err := r.Read(buf); err != nil {
			panic(err)
		}
		return binary.LittleEndian.Uint32(buf)
	}
}

type recWriter struct {
	*bufio.Writer
}

func (rw *recWriter) writeString(s string) {
	if _, err := rw.WriteString(s); err != nil {
		panic(err)
	}
}

func (rw *recWriter) copyn(r io.Reader, n uint32) {
	if _, err := io.CopyN(rw, r, int64(n)); err != nil {
		panic(err)
	}
}


<|start_filename|>vendor/github.com/kyokomi/emoji/emoji_codemap.go<|end_filename|>
package emoji

// NOTE: THIS FILE WAS PRODUCED BY THE
// EMOJICODEMAP CODE GENERATION TOOL (github.com/kyokomi/generateEmojiCodeMap)
// DO NOT EDIT

// Mapping from character to concrete escape code.
var emojiCodeMap = map[string]string{
	":+1:":                              "\U0001f44d",
	":-1:":                              "\U0001f44e",
	":100:":                             "\U0001f4af",
	":1234:":                            "\U0001f522",
	":8ball:":                           "\U0001f3b1",
	":a:":                               "\U0001f170\ufe0f",
	":ab:":                              "\U0001f18e",
	":abc:":                             "\U0001f524",
	":abcd:":                            "\U0001f521",
	":accept:":                          "\U0001f251",
	":aerial_tramway:":                  "\U0001f6a1",
	":airplane:":                        "\u2708\ufe0f",
	":alarm_clock:":                     "\u23f0",
	":alien:":                           "\U0001f47d",
	":ambulance:":                       "\U0001f691",
	":anchor:":                          "\u2693",
	":angel:":                           "\U0001f47c",
	":anger:":                           "\U0001f4a2",
	":angry:":                           "\U0001f620",
	":anguished:":                       "\U0001f627",
	":ant:":                             "\U0001f41c",
	":apple:":                           "\U0001f34e",
	":aquarius:":                        "\u2652",
	":aries:":                           "\u2648",
	":arrow_backward:":                  "\u25c0\ufe0f",
	":arrow_double_down:":               "\u23ec",
	":arrow_double_up:":                 "\u23eb",
	":arrow_down:":                      "\u2b07\ufe0f",
	":arrow_down_small:":                "\U0001f53d",
	":arrow_forward:":                   "\u25b6\ufe0f",
	":arrow_heading_down:":              "\u2935\ufe0f",
	":arrow_heading_up:":                "\u2934\ufe0f",
	":arrow_left:":                      "\u2b05\ufe0f",
	":arrow_lower_left:":                "\u2199\ufe0f",
	":arrow_lower_right:":               "\u2198\ufe0f",
	":arrow_right:":                     "\u27a1\ufe0f",
	":arrow_right_hook:":                "\u21aa\ufe0f",
	":arrow_up:":                        "\u2b06\ufe0f",
	":arrow_up_down:":                   "\u2195\ufe0f",
	":arrow_up_small:":                  "\U0001f53c",
	":arrow_upper_left:":                "\u2196\ufe0f",
	":arrow_upper_right:":               "\u2197\ufe0f",
	":arrows_clockwise:":                "\U0001f503",
	":arrows_counterclockwise:":         "\U0001f504",
	":art:":                             "\U0001f3a8",
	":articulated_lorry:":               "\U0001f69b",
	":astonished:":                      "\U0001f632",
	":athletic_shoe:":                   "\U0001f45f",
	":atm:":                             "\U0001f3e7",
	":b:":                               "\U0001f171\ufe0f",
	":baby:":                            "\U0001f476",
	":baby_bottle:":                     "\U0001f37c",
	":baby_chick:":                      "\U0001f424",
	":baby_symbol:":                     "\U0001f6bc",
	":back:":                            "\U0001f519",
	":baggage_claim:":                   "\U0001f6c4",
	":balloon:":                         "\U0001f388",
	":ballot_box_with_check:":           "\u2611\ufe0f",
	":bamboo:":                          "\U0001f38d",
	":banana:":                          "\U0001f34c",
	":bangbang:":                        "\u203c\ufe0f",
	":bank:":                            "\U0001f3e6",
	":bar_chart:":                       "\U0001f4ca",
	":barber:":                          "\U0001f488",
	":baseball:":                        "\u26be\ufe0f",
	":basecamp:":                        "",
	":basecampy:":                       "",
	":basketball:":                      "\U0001f3c0",
	":bath:":                            "\U0001f6c0",
	":bathtub:":                         "\U0001f6c1",
	":battery:":                         "\U0001f50b",
	":bear:":                            "\U0001f43b",
	":bee:":                             "\U0001f41d",
	":beer:":                            "\U0001f37a",
	":beers:":                           "\U0001f37b",
	":beetle:":                          "\U0001f41e",
	":beginner:":                        "\U0001f530",
	":bell:":                            "\U0001f514",
	":bento:":                           "\U0001f371",
	":bicyclist:":                       "\U0001f6b4",
	":bike:":                            "\U0001f6b2",
	":bikini:":                          "\U0001f459",
	":bird:":                            "\U0001f426",
	":birthday:":                        "\U0001f382",
	":black_circle:":                    "\u26ab",
	":black_joker:":                     "\U0001f0cf",
	":black_large_square:":              "\u2b1b",
	":black_medium_small_square:":       "\u25fe",
	":black_medium_square:":             "\u25fc\ufe0f",
	":black_nib:":                       "\u2712\ufe0f",
	":black_small_square:":              "\u25aa\ufe0f",
	":black_square_button:":             "\U0001f532",
	":blossom:":                         "\U0001f33c",
	":blowfish:":                        "\U0001f421",
	":blue_book:":                       "\U0001f4d8",
	":blue_car:":                        "\U0001f699",
	":blue_heart:":                      "\U0001f499",
	":blush:":                           "\U0001f60a",
	":boar:":                            "\U0001f417",
	":boat:":                            "\u26f5",
	":bomb:":                            "\U0001f4a3",
	":book:":                            "\U0001f4d6",
	":bookmark:":                        "\U0001f516",
	":bookmark_tabs:":                   "\U0001f4d1",
	":books:":                           "\U0001f4da",
	":boom:":                            "\U0001f4a5",
	":boot:":                            "\U0001f462",
	":bouquet:":                         "\U0001f490",
	":bow:":                             "\U0001f647",
	":bowling:":                         "\U0001f3b3",
	":bowtie:":                          "",
	":boy:":                             "\U0001f466",
	":bread:":                           "\U0001f35e",
	":bride_with_veil:":                 "\U0001f470",
	":bridge_at_night:":                 "\U0001f309",
	":briefcase:":                       "\U0001f4bc",
	":broken_heart:":                    "\U0001f494",
	":bug:":                             "\U0001f41b",
	":bulb:":                            "\U0001f4a1",
	":bullettrain_front:":               "\U0001f685",
	":bullettrain_side:":                "\U0001f684",
	":bus:":                             "\U0001f68c",
	":busstop:":                         "\U0001f68f",
	":bust_in_silhouette:":              "\U0001f464",
	":busts_in_silhouette:":             "\U0001f465",
	":cactus:":                          "\U0001f335",
	":cake:":                            "\U0001f370",
	":calendar:":                        "\U0001f4c6",
	":calling:":                         "\U0001f4f2",
	":camel:":                           "\U0001f42b",
	":camera:":                          "\U0001f4f7",
	":cancer:":                          "\u264b",
	":candy:":                           "\U0001f36c",
	":capital_abcd:":                    "\U0001f520",
	":capricorn:":                       "\u2651",
	":car:":                             "\U0001f697",
	":card_index:":                      "\U0001f4c7",
	":carousel_horse:":                  "\U0001f3a0",
	":cat:":                             "\U0001f431",
	":cat2:":                            "\U0001f408",
	":cd:":                              "\U0001f4bf",
	":chart:":                           "\U0001f4b9",
	":chart_with_downwards_trend:":      "\U0001f4c9",
	":chart_with_upwards_trend:":        "\U0001f4c8",
	":checkered_flag:":                  "\U0001f3c1",
	":cherries:":                        "\U0001f352",
	":cherry_blossom:":                  "\U0001f338",
	":chestnut:":                        "\U0001f330",
	":chicken:":                         "\U0001f414",
	":children_crossing:":               "\U0001f6b8",
	":chocolate_bar:":                   "\U0001f36b",
	":christmas_tree:":                  "\U0001f384",
	":church:":                          "\u26ea",
	":cinema:":                          "\U0001f3a6",
	":circus_tent:":                     "\U0001f3aa",
	":city_sunrise:":                    "\U0001f307",
	":city_sunset:":                     "\U0001f306",
	":cl:":                              "\U0001f191",
	":clap:":                            "\U0001f44f",
	":clapper:":                         "\U0001f3ac",
	":clipboard:":                       "\U0001f4cb",
	":clock1:":                          "\U0001f550",
	":clock10:":                         "\U0001f559",
	":clock1030:":                       "\U0001f565",
	":clock11:":                         "\U0001f55a",
	":clock1130:":                       "\U0001f566",
	":clock12:":                         "\U0001f55b",
	":clock1230:":                       "\U0001f567",
	":clock130:":                        "\U0001f55c",
	":clock2:":                          "\U0001f551",
	":clock230:":                        "\U0001f55d",
	":clock3:":                          "\U0001f552",
	":clock330:":                        "\U0001f55e",
	":clock4:":                          "\U0001f553",
	":clock430:":                        "\U0001f55f",
	":clock5:":                          "\U0001f554",
	":clock530:":                        "\U0001f560",
	":clock6:":                          "\U0001f555",
	":clock630:":                        "\U0001f561",
	":clock7:":                          "\U0001f556",
	":clock730:":                        "\U0001f562",
	":clock8:":                          "\U0001f557",
	":clock830:":                        "\U0001f563",
	":clock9:":                          "\U0001f558",
	":clock930:":                        "\U0001f564",
	":closed_book:":                     "\U0001f4d5",
	":closed_lock_with_key:":            "\U0001f510",
	":closed_umbrella:":                 "\U0001f302",
	":cloud:":                           "\u2601\ufe0f",
	":clubs:":                           "\u2663\ufe0f",
	":cn:":                              "\U0001f1e8\U0001f1f3",
	":cocktail:":                        "\U0001f378",
	":coffee:":                          "\u2615",
	":cold_sweat:":                      "\U0001f630",
	":collision:":                       "\U0001f4a5",
	":computer:":                        "\U0001f4bb",
	":confetti_ball:":                   "\U0001f38a",
	":confounded:":                      "\U0001f616",
	":confused:":                        "\U0001f615",
	":congratulations:":                 "\u3297\ufe0f",
	":construction:":                    "\U0001f6a7",
	":construction_worker:":             "\U0001f477",
	":convenience_store:":               "\U0001f3ea",
	":cookie:":                          "\U0001f36a",
	":cool:":                            "\U0001f192",
	":cop:":                             "\U0001f46e",
	":copyright:":                       "\u00a9\ufe0f",
	":corn:":                            "\U0001f33d",
	":couple:":                          "\U0001f46b",
	":couple_with_heart:":               "\U0001f491",
	":couplekiss:":                      "\U0001f48f",
	":cow:":                             "\U0001f42e",
	":cow2:":                            "\U0001f404",
	":credit_card:":                     "\U0001f4b3",
	":crescent_moon:":                   "\U0001f319",
	":crocodile:":                       "\U0001f40a",
	":crossed_flags:":                   "\U0001f38c",
	":crown:":                           "\U0001f451",
	":cry:":                             "\U0001f622",
	":crying_cat_face:":                 "\U0001f63f",
	":crystal_ball:":                    "\U0001f52e",
	":cupid:":                           "\U0001f498",
	":curly_loop:":                      "\u27b0",
	":currency_exchange:":               "\U0001f4b1",
	":curry:":                           "\U0001f35b",
	":custard:":                         "\U0001f36e",
	":customs:":                         "\U0001f6c3",
	":cyclone:":                         "\U0001f300",
	":dancer:":                          "\U0001f483",
	":dancers:":                         "\U0001f46f",
	":dango:":                           "\U0001f361",
	":dart:":                            "\U0001f3af",
	":dash:":                            "\U0001f4a8",
	":date:":                            "\U0001f4c5",
	":de:":                              "\U0001f1e9\U0001f1ea",
	":deciduous_tree:":                  "\U0001f333",
	":department_store:":                "\U0001f3ec",
	":diamond_shape_with_a_dot_inside:": "\U0001f4a0",
	":diamonds:":                        "\u2666\ufe0f",
	":disappointed:":                    "\U0001f61e",
	":disappointed_relieved:":           "\U0001f625",
	":dizzy:":                           "\U0001f4ab",
	":dizzy_face:":                      "\U0001f635",
	":do_not_litter:":                   "\U0001f6af",
	":dog:":                             "\U0001f436",
	":dog2:":                            "\U0001f415",
	":dollar:":                          "\U0001f4b5",
	":dolls:":                           "\U0001f38e",
	":dolphin:":                         "\U0001f42c",
	":door:":                            "\U0001f6aa",
	":doughnut:":                        "\U0001f369",
	":dragon:":                          "\U0001f409",
	":dragon_face:":                     "\U0001f432",
	":dress:":                           "\U0001f457",
	":dromedary_camel:":                 "\U0001f42a",
	":droplet:":                         "\U0001f4a7",
	":dvd:":                             "\U0001f4c0",
	":e-mail:":                          "\U0001f4e7",
	":ear:":                             "\U0001f442",
	":ear_of_rice:":                     "\U0001f33e",
	":earth_africa:":                    "\U0001f30d",
	":earth_americas:":                  "\U0001f30e",
	":earth_asia:":                      "\U0001f30f",
	":egg:":                             "\U0001f373",
	":eggplant:":                        "\U0001f346",
	":eight:":                           "8\ufe0f\u20e3",
	":eight_pointed_black_star:":        "\u2734\ufe0f",
	":eight_spoked_asterisk:":           "\u2733\ufe0f",
	":electric_plug:":                   "\U0001f50c",
	":elephant:":                        "\U0001f418",
	":email:":                           "\u2709\ufe0f",
	":end:":                             "\U0001f51a",
	":envelope:":                        "\u2709\ufe0f",
	":envelope_with_arrow:":             "\U0001f4e9",
	":es:":                              "\U0001f1ea\U0001f1f8",
	":euro:":                            "\U0001f4b6",
	":european_castle:":                 "\U0001f3f0",
	":european_post_office:":            "\U0001f3e4",
	":evergreen_tree:":                  "\U0001f332",
	":exclamation:":                     "\u2757",
	":expressionless:":                  "\U0001f611",
	":eyeglasses:":                      "\U0001f453",
	":eyes:":                            "\U0001f440",
	":facepunch:":                       "\U0001f44a",
	":factory:":                         "\U0001f3ed",
	":fallen_leaf:":                     "\U0001f342",
	":family:":                          "\U0001f46a",
	":fast_forward:":                    "\u23e9",
	":fax:":                             "\U0001f4e0",
	":fearful:":                         "\U0001f628",
	":feelsgood:":                       "",
	":feet:":                            "\U0001f43e",
	":ferris_wheel:":                    "\U0001f3a1",
	":file_folder:":                     "\U0001f4c1",
	":finnadie:":                        "",
	":fire:":                            "\U0001f525",
	":fire_engine:":                     "\U0001f692",
	":fireworks:":                       "\U0001f386",
	":first_quarter_moon:":              "\U0001f313",
	":first_quarter_moon_with_face:":    "\U0001f31b",
	":fish:":                           "\U0001f41f",
	":fish_cake:":                      "\U0001f365",
	":fishing_pole_and_fish:":          "\U0001f3a3",
	":fist:":                           "\u270a",
	":five:":                           "5\ufe0f\u20e3",
	":flags:":                          "\U0001f38f",
	":flashlight:":                     "\U0001f526",
	":flipper:":                        "\U0001f42c",
	":floppy_disk:":                    "\U0001f4be",
	":flower_playing_cards:":           "\U0001f3b4",
	":flushed:":                        "\U0001f633",
	":foggy:":                          "\U0001f301",
	":football:":                       "\U0001f3c8",
	":footprints:":                     "\U0001f463",
	":fork_and_knife:":                 "\U0001f374",
	":fountain:":                       "\u26f2",
	":four:":                           "4\ufe0f\u20e3",
	":four_leaf_clover:":               "\U0001f340",
	":fr:":                             "\U0001f1eb\U0001f1f7",
	":free:":                           "\U0001f193",
	":fried_shrimp:":                   "\U0001f364",
	":fries:":                          "\U0001f35f",
	":frog:":                           "\U0001f438",
	":frowning:":                       "\U0001f626",
	":fu:":                             "",
	":fuelpump:":                       "\u26fd",
	":full_moon:":                      "\U0001f315",
	":full_moon_with_face:":            "\U0001f31d",
	":game_die:":                       "\U0001f3b2",
	":gb:":                             "\U0001f1ec\U0001f1e7",
	":gem:":                            "\U0001f48e",
	":gemini:":                         "\u264a",
	":ghost:":                          "\U0001f47b",
	":gift:":                           "\U0001f381",
	":gift_heart:":                     "\U0001f49d",
	":girl:":                           "\U0001f467",
	":globe_with_meridians:":           "\U0001f310",
	":goat:":                           "\U0001f410",
	":goberserk:":                      "",
	":godmode:":                        "",
	":golf:":                           "\u26f3",
	":grapes:":                         "\U0001f347",
	":green_apple:":                    "\U0001f34f",
	":green_book:":                     "\U0001f4d7",
	":green_heart:":                    "\U0001f49a",
	":grey_exclamation:":               "\u2755",
	":grey_question:":                  "\u2754",
	":grimacing:":                      "\U0001f62c",
	":grin:":                           "\U0001f601",
	":grinning:":                       "\U0001f600",
	":guardsman:":                      "\U0001f482",
	":guitar:":                         "\U0001f3b8",
	":gun:":                            "\U0001f52b",
	":haircut:":                        "\U0001f487",
	":hamburger:":                      "\U0001f354",
	":hammer:":                         "\U0001f528",
	":hamster:":                        "\U0001f439",
	":hand:":                           "\u270b",
	":handbag:":                        "\U0001f45c",
	":hankey:":                         "\U0001f4a9",
	":hash:":                           "#\ufe0f\u20e3",
	":hatched_chick:":                  "\U0001f425",
	":hatching_chick:":                 "\U0001f423",
	":headphones:":                     "\U0001f3a7",
	":hear_no_evil:":                   "\U0001f649",
	":heart:":                          "\u2764\ufe0f",
	":heart_decoration:":               "\U0001f49f",
	":heart_eyes:":                     "\U0001f60d",
	":heart_eyes_cat:":                 "\U0001f63b",
	":heartbeat:":                      "\U0001f493",
	":heartpulse:":                     "\U0001f497",
	":hearts:":                         "\u2665\ufe0f",
	":heavy_check_mark:":               "\u2714\ufe0f",
	":heavy_division_sign:":            "\u2797",
	":heavy_dollar_sign:":              "\U0001f4b2",
	":heavy_exclamation_mark:":         "\u2757",
	":heavy_minus_sign:":               "\u2796",
	":heavy_multiplication_x:":         "\u2716\ufe0f",
	":heavy_plus_sign:":                "\u2795",
	":helicopter:":                     "\U0001f681",
	":herb:":                           "\U0001f33f",
	":hibiscus:":                       "\U0001f33a",
	":high_brightness:":                "\U0001f506",
	":high_heel:":                      "\U0001f460",
	":hocho:":                          "\U0001f52a",
	":honey_pot:":                      "\U0001f36f",
	":honeybee:":                       "\U0001f41d",
	":horse:":                          "\U0001f434",
	":horse_racing:":                   "\U0001f3c7",
	":hospital:":                       "\U0001f3e5",
	":hotel:":                          "\U0001f3e8",
	":hotsprings:":                     "\u2668\ufe0f",
	":hourglass:":                      "\u231b",
	":hourglass_flowing_sand:":         "\u23f3",
	":house:":                          "\U0001f3e0",
	":house_with_garden:":              "\U0001f3e1",
	":hurtrealbad:":                    "",
	":hushed:":                         "\U0001f62f",
	":ice_cream:":                      "\U0001f368",
	":icecream:":                       "\U0001f366",
	":id:":                             "\U0001f194",
	":ideograph_advantage:":            "\U0001f250",
	":imp:":                            "\U0001f47f",
	":inbox_tray:":                     "\U0001f4e5",
	":incoming_envelope:":              "\U0001f4e8",
	":information_desk_person:":        "\U0001f481",
	":information_source:":             "\u2139\ufe0f",
	":innocent:":                       "\U0001f607",
	":interrobang:":                    "\u2049\ufe0f",
	":iphone:":                         "\U0001f4f1",
	":it:":                             "\U0001f1ee\U0001f1f9",
	":izakaya_lantern:":                "\U0001f3ee",
	":jack_o_lantern:":                 "\U0001f383",
	":japan:":                          "\U0001f5fe",
	":japanese_castle:":                "\U0001f3ef",
	":japanese_goblin:":                "\U0001f47a",
	":japanese_ogre:":                  "\U0001f479",
	":jeans:":                          "\U0001f456",
	":joy:":                            "\U0001f602",
	":joy_cat:":                        "\U0001f639",
	":jp:":                             "\U0001f1ef\U0001f1f5",
	":key:":                            "\U0001f511",
	":keycap_ten:":                     "\U0001f51f",
	":kimono:":                         "\U0001f458",
	":kiss:":                           "\U0001f48b",
	":kissing:":                        "\U0001f617",
	":kissing_cat:":                    "\U0001f63d",
	":kissing_closed_eyes:":            "\U0001f61a",
	":kissing_heart:":                  "\U0001f618",
	":kissing_smiling_eyes:":           "\U0001f619",
	":knife:":                          "\U0001f52a",
	":koala:":                          "\U0001f428",
	":koko:":                           "\U0001f201",
	":kr:":                             "\U0001f1f0\U0001f1f7",
	":lantern:":                        "\U0001f3ee",
	":large_blue_circle:":              "\U0001f535",
	":large_blue_diamond:":             "\U0001f537",
	":large_orange_diamond:":           "\U0001f536",
	":last_quarter_moon:":              "\U0001f317",
	":last_quarter_moon_with_face:":    "\U0001f31c",
	":laughing:":                       "\U0001f606",
	":leaves:":                         "\U0001f343",
	":ledger:":                         "\U0001f4d2",
	":left_luggage:":                   "\U0001f6c5",
	":left_right_arrow:":               "\u2194\ufe0f",
	":leftwards_arrow_with_hook:":      "\u21a9\ufe0f",
	":lemon:":                          "\U0001f34b",
	":leo:":                            "\u264c",
	":leopard:":                        "\U0001f406",
	":libra:":                          "\u264e",
	":light_rail:":                     "\U0001f688",
	":link:":                           "\U0001f517",
	":lips:":                           "\U0001f444",
	":lipstick:":                       "\U0001f484",
	":lock:":                           "\U0001f512",
	":lock_with_ink_pen:":              "\U0001f50f",
	":lollipop:":                       "\U0001f36d",
	":loop:":                           "\u27bf",
	":loud_sound:":                     "\U0001f50a",
	":loudspeaker:":                    "\U0001f4e2",
	":love_hotel:":                     "\U0001f3e9",
	":love_letter:":                    "\U0001f48c",
	":low_brightness:":                 "\U0001f505",
	":m:":                              "\u24c2\ufe0f",
	":mag:":                            "\U0001f50d",
	":mag_right:":                      "\U0001f50e",
	":mahjong:":                        "\U0001f004",
	":mailbox:":                        "\U0001f4eb",
	":mailbox_closed:":                 "\U0001f4ea",
	":mailbox_with_mail:":              "\U0001f4ec",
	":mailbox_with_no_mail:":           "\U0001f4ed",
	":man:":                            "\U0001f468",
	":man_with_gua_pi_mao:":            "\U0001f472",
	":man_with_turban:":                "\U0001f473",
	":mans_shoe:":                      "\U0001f45e",
	":maple_leaf:":                     "\U0001f341",
	":mask:":                           "\U0001f637",
	":massage:":                        "\U0001f486",
	":meat_on_bone:":                   "\U0001f356",
	":mega:":                           "\U0001f4e3",
	":melon:":                          "\U0001f348",
	":memo:":                           "\U0001f4dd",
	":mens:":                           "\U0001f6b9",
	":metal:":                          "",
	":metro:":                          "\U0001f687",
	":microphone:":                     "\U0001f3a4",
	":microscope:":                     "\U0001f52c",
	":milky_way:":                      "\U0001f30c",
	":minibus:":                        "\U0001f690",
	":minidisc:":                       "\U0001f4bd",
	":mobile_phone_off:":               "\U0001f4f4",
	":money_with_wings:":               "\U0001f4b8",
	":moneybag:":                       "\U0001f4b0",
	":monkey:":                         "\U0001f412",
	":monkey_face:":                    "\U0001f435",
	":monorail:":                       "\U0001f69d",
	":moon:":                           "\U0001f314",
	":mortar_board:":                   "\U0001f393",
	":mount_fuji:":                     "\U0001f5fb",
	":mountain_bicyclist:":             "\U0001f6b5",
	":mountain_cableway:":              "\U0001f6a0",
	":mountain_railway:":               "\U0001f69e",
	":mouse:":                          "\U0001f42d",
	":mouse2:":                         "\U0001f401",
	":movie_camera:":                   "\U0001f3a5",
	":moyai:":                          "\U0001f5ff",
	":muscle:":                         "\U0001f4aa",
	":mushroom:":                       "\U0001f344",
	":musical_keyboard:":               "\U0001f3b9",
	":musical_note:":                   "\U0001f3b5",
	":musical_score:":                  "\U0001f3bc",
	":mute:":                           "\U0001f507",
	":nail_care:":                      "\U0001f485",
	":name_badge:":                     "\U0001f4db",
	":neckbeard:":                      "",
	":necktie:":                        "\U0001f454",
	":negative_squared_cross_mark:":    "\u274e",
	":neutral_face:":                   "\U0001f610",
	":new:":                            "\U0001f195",
	":new_moon:":                       "\U0001f311",
	":new_moon_with_face:":             "\U0001f31a",
	":newspaper:":                      "\U0001f4f0",
	":ng:":                             "\U0001f196",
	":night_with_stars:":               "\U0001f303",
	":nine:":                           "9\ufe0f\u20e3",
	":no_bell:":                        "\U0001f515",
	":no_bicycles:":                    "\U0001f6b3",
	":no_entry:":                       "\u26d4",
	":no_entry_sign:":                  "\U0001f6ab",
	":no_good:":                        "\U0001f645",
	":no_mobile_phones:":               "\U0001f4f5",
	":no_mouth:":                       "\U0001f636",
	":no_pedestrians:":                 "\U0001f6b7",
	":no_smoking:":                     "\U0001f6ad",
	":non-potable_water:":              "\U0001f6b1",
	":nose:":                           "\U0001f443",
	":notebook:":                       "\U0001f4d3",
	":notebook_with_decorative_cover:": "\U0001f4d4",
	":notes:":                          "\U0001f3b6",
	":nut_and_bolt:":                   "\U0001f529",
	":o:":                              "\u2b55",
	":o2:":                             "\U0001f17e\ufe0f",
	":ocean:":                          "\U0001f30a",
	":octocat:":                        "",
	":octopus:":                        "\U0001f419",
	":oden:":                           "\U0001f362",
	":office:":                         "\U0001f3e2",
	":ok:":                             "\U0001f197",
	":ok_hand:":                        "\U0001f44c",
	":ok_woman:":                       "\U0001f646",
	":older_man:":                      "\U0001f474",
	":older_woman:":                    "\U0001f475",
	":on:":                             "\U0001f51b",
	":oncoming_automobile:":            "\U0001f698",
	":oncoming_bus:":                   "\U0001f68d",
	":oncoming_police_car:":            "\U0001f694",
	":oncoming_taxi:":                  "\U0001f696",
	":one:":                            "1\ufe0f\u20e3",
	":open_book:":                      "\U0001f4d6",
	":open_file_folder:":               "\U0001f4c2",
	":open_hands:":                     "\U0001f450",
	":open_mouth:":                     "\U0001f62e",
	":ophiuchus:":                      "\u26ce",
	":orange_book:":                    "\U0001f4d9",
	":outbox_tray:":                    "\U0001f4e4",
	":ox:":                             "\U0001f402",
	":package:":                        "\U0001f4e6",
	":page_facing_up:":                 "\U0001f4c4",
	":page_with_curl:":                 "\U0001f4c3",
	":pager:":                          "\U0001f4df",
	":palm_tree:":                      "\U0001f334",
	":panda_face:":                     "\U0001f43c",
	":paperclip:":                      "\U0001f4ce",
	":parking:":                        "\U0001f17f\ufe0f",
	":part_alternation_mark:":          "\u303d\ufe0f",
	":partly_sunny:":                   "\u26c5",
	":passport_control:":               "\U0001f6c2",
	":paw_prints:":                     "\U0001f43e",
	":peach:":                          "\U0001f351",
	":pear:":                           "\U0001f350",
	":pencil:":                         "\U0001f4dd",
	":pencil2:":                        "\u270f\ufe0f",
	":penguin:":                        "\U0001f427",
	":pensive:":                        "\U0001f614",
	":performing_arts:":                "\U0001f3ad",
	":persevere:":                      "\U0001f623",
	":person_frowning:":                "\U0001f64d",
	":person_with_blond_hair:":         "\U0001f471",
	":person_with_pouting_face:":       "\U0001f64e",
	":phone:":                          "\u260e\ufe0f",
	":pig:":                            "\U0001f437",
	":pig2:":                           "\U0001f416",
	":pig_nose:":                       "\U0001f43d",
	":pill:":                           "\U0001f48a",
	":pineapple:":                      "\U0001f34d",
	":pisces:":                         "\u2653",
	":pizza:":                          "\U0001f355",
	":point_down:":                     "\U0001f447",
	":point_left:":                     "\U0001f448",
	":point_right:":                    "\U0001f449",
	":point_up:":                       "\u261d\ufe0f",
	":point_up_2:":                     "\U0001f446",
	":police_car:":                     "\U0001f693",
	":poodle:":                         "\U0001f429",
	":poop:":                           "\U0001f4a9",
	":post_office:":                    "\U0001f3e3",
	":postal_horn:":                    "\U0001f4ef",
	":postbox:":                        "\U0001f4ee",
	":potable_water:":                  "\U0001f6b0",
	":pouch:":                          "\U0001f45d",
	":poultry_leg:":                    "\U0001f357",
	":pound:":                          "\U0001f4b7",
	":pouting_cat:":                    "\U0001f63e",
	":pray:":                           "\U0001f64f",
	":princess:":                       "\U0001f478",
	":punch:":                          "\U0001f44a",
	":purple_heart:":                   "\U0001f49c",
	":purse:":                          "\U0001f45b",
	":pushpin:":                        "\U0001f4cc",
	":put_litter_in_its_place:":        "\U0001f6ae",
	":question:":                       "\u2753",
	":rabbit:":                         "\U0001f430",
	":rabbit2:":                        "\U0001f407",
	":racehorse:":                      "\U0001f40e",
	":radio:":                          "\U0001f4fb",
	":radio_button:":                   "\U0001f518",
	":rage:":                           "\U0001f621",
	":rage1:":                          "",
	":rage2:":                          "",
	":rage3:":                          "",
	":rage4:":                          "",
	":railway_car:":                    "\U0001f683",
	":rainbow:":                        "\U0001f308",
	":raised_hand:":                    "\u270b",
	":raised_hands:":                   "\U0001f64c",
	":raising_hand:":                   "\U0001f64b",
	":ram:":                            "\U0001f40f",
	":ramen:":                          "\U0001f35c",
	":rat:":                            "\U0001f400",
	":recycle:":                        "\u267b\ufe0f",
	":red_car:":                        "\U0001f697",
	":red_circle:":                     "\U0001f534",
	":registered:":                     "\u00ae\ufe0f",
	":relaxed:":                        "\u263a\ufe0f",
	":relieved:":                       "\U0001f60c",
	":repeat:":                         "\U0001f501",
	":repeat_one:":                     "\U0001f502",
	":restroom:":                       "\U0001f6bb",
	":revolving_hearts:":               "\U0001f49e",
	":rewind:":                         "\u23ea",
	":ribbon:":                         "\U0001f380",
	":rice:":                           "\U0001f35a",
	":rice_ball:":                      "\U0001f359",
	":rice_cracker:":                   "\U0001f358",
	":rice_scene:":                     "\U0001f391",
	":ring:":                           "\U0001f48d",
	":rocket:":                         "\U0001f680",
	":roller_coaster:":                 "\U0001f3a2",
	":rooster:":                        "\U0001f413",
	":rose:":                           "\U0001f339",
	":rotating_light:":                 "\U0001f6a8",
	":round_pushpin:":                  "\U0001f4cd",
	":rowboat:":                        "\U0001f6a3",
	":ru:":                             "\U0001f1f7\U0001f1fa",
	":rugby_football:":                 "\U0001f3c9",
	":runner:":                         "\U0001f3c3",
	":running:":                        "\U0001f3c3",
	":running_shirt_with_sash:":        "\U0001f3bd",
	":sa:":                           "\U0001f202\ufe0f",
	":sagittarius:":                  "\u2650",
	":sailboat:":                     "\u26f5",
	":sake:":                         "\U0001f376",
	":sandal:":                       "\U0001f461",
	":santa:":                        "\U0001f385",
	":satellite:":                    "\U0001f4e1",
	":satisfied:":                    "\U0001f606",
	":saxophone:":                    "\U0001f3b7",
	":school:":                       "\U0001f3eb",
	":school_satchel:":               "\U0001f392",
	":scissors:":                     "\u2702\ufe0f",
	":scorpius:":                     "\u264f",
	":scream:":                       "\U0001f631",
	":scream_cat:":                   "\U0001f640",
	":scroll:":                       "\U0001f4dc",
	":seat:":                         "\U0001f4ba",
	":secret:":                       "\u3299\ufe0f",
	":see_no_evil:":                  "\U0001f648",
	":seedling:":                     "\U0001f331",
	":seven:":                        "7\ufe0f\u20e3",
	":shaved_ice:":                   "\U0001f367",
	":sheep:":                        "\U0001f411",
	":shell:":                        "\U0001f41a",
	":ship:":                         "\U0001f6a2",
	":shipit:":                       "",
	":shirt:":                        "\U0001f455",
	":shit:":                         "\U0001f4a9",
	":shoe:":                         "\U0001f45e",
	":shower:":                       "\U0001f6bf",
	":signal_strength:":              "\U0001f4f6",
	":six:":                          "6\ufe0f\u20e3",
	":six_pointed_star:":             "\U0001f52f",
	":ski:":                          "\U0001f3bf",
	":skull:":                        "\U0001f480",
	":sleeping:":                     "\U0001f634",
	":sleepy:":                       "\U0001f62a",
	":slot_machine:":                 "\U0001f3b0",
	":small_blue_diamond:":           "\U0001f539",
	":small_orange_diamond:":         "\U0001f538",
	":small_red_triangle:":           "\U0001f53a",
	":small_red_triangle_down:":      "\U0001f53b",
	":smile:":                        "\U0001f604",
	":smile_cat:":                    "\U0001f638",
	":smiley:":                       "\U0001f603",
	":smiley_cat:":                   "\U0001f63a",
	":smiling_imp:":                  "\U0001f608",
	":smirk:":                        "\U0001f60f",
	":smirk_cat:":                    "\U0001f63c",
	":smoking:":                      "\U0001f6ac",
	":snail:":                        "\U0001f40c",
	":snake:":                        "\U0001f40d",
	":snowboarder:":                  "\U0001f3c2",
	":snowflake:":                    "\u2744\ufe0f",
	":snowman:":                      "\u26c4",
	":sob:":                          "\U0001f62d",
	":soccer:":                       "\u26bd",
	":soon:":                         "\U0001f51c",
	":sos:":                          "\U0001f198",
	":sound:":                        "\U0001f509",
	":space_invader:":                "\U0001f47e",
	":spades:":                       "\u2660\ufe0f",
	":spaghetti:":                    "\U0001f35d",
	":sparkle:":                      "\u2747\ufe0f",
	":sparkler:":                     "\U0001f387",
	":sparkles:":                     "\u2728",
	":sparkling_heart:":              "\U0001f496",
	":speak_no_evil:":                "\U0001f64a",
	":speaker:":                      "\U0001f508",
	":speech_balloon:":               "\U0001f4ac",
	":speedboat:":                    "\U0001f6a4",
	":squirrel:":                     "",
	":star:":                         "\u2b50",
	":star2:":                        "\U0001f31f",
	":stars:":                        "\U0001f320",
	":station:":                      "\U0001f689",
	":statue_of_liberty:":            "\U0001f5fd",
	":steam_locomotive:":             "\U0001f682",
	":stew:":                         "\U0001f372",
	":straight_ruler:":               "\U0001f4cf",
	":strawberry:":                   "\U0001f353",
	":stuck_out_tongue:":             "\U0001f61b",
	":stuck_out_tongue_closed_eyes:": "\U0001f61d",
	":stuck_out_tongue_winking_eye:": "\U0001f61c",
	":sun_with_face:":                "\U0001f31e",
	":sunflower:":                    "\U0001f33b",
	":sunglasses:":                   "\U0001f60e",
	":sunny:":                        "\u2600\ufe0f",
	":sunrise:":                      "\U0001f305",
	":sunrise_over_mountains:":       "\U0001f304",
	":surfer:":                       "\U0001f3c4",
	":sushi:":                        "\U0001f363",
	":suspect:":                      "",
	":suspension_railway:":           "\U0001f69f",
	":sweat:":                        "\U0001f613",
	":sweat_drops:":                  "\U0001f4a6",
	":sweat_smile:":                  "\U0001f605",
	":sweet_potato:":                 "\U0001f360",
	":swimmer:":                      "\U0001f3ca",
	":symbols:":                      "\U0001f523",
	":syringe:":                      "\U0001f489",
	":tada:":                         "\U0001f389",
	":tanabata_tree:":                "\U0001f38b",
	":tangerine:":                    "\U0001f34a",
	":taurus:":                       "\u2649",
	":taxi:":                         "\U0001f695",
	":tea:":                          "\U0001f375",
	":telephone:":                    "\u260e\ufe0f",
	":telephone_receiver:":           "\U0001f4de",
	":telescope:":                    "\U0001f52d",
	":tennis:":                       "\U0001f3be",
	":tent:":                         "\u26fa",
	":thought_balloon:":              "\U0001f4ad",
	":three:":                        "3\ufe0f\u20e3",
	":thumbsdown:":                   "\U0001f44e",
	":thumbsup:":                     "\U0001f44d",
	":ticket:":                       "\U0001f3ab",
	":tiger:":                        "\U0001f42f",
	":tiger2:":                       "\U0001f405",
	":tired_face:":                   "\U0001f62b",
	":tm:":                           "\u2122\ufe0f",
	":toilet:":                       "\U0001f6bd",
	":tokyo_tower:":                  "\U0001f5fc",
	":tomato:":                       "\U0001f345",
	":tongue:":                       "\U0001f445",
	":top:":                          "\U0001f51d",
	":tophat:":                       "\U0001f3a9",
	":tractor:":                      "\U0001f69c",
	":traffic_light:":                "\U0001f6a5",
	":train:":                        "\U0001f68b",
	":train2:":                       "\U0001f686",
	":tram:":                         "\U0001f68a",
	":triangular_flag_on_post:":      "\U0001f6a9",
	":triangular_ruler:":             "\U0001f4d0",
	":trident:":                      "\U0001f531",
	":triumph:":                      "\U0001f624",
	":trolleybus:":                   "\U0001f68e",
	":trollface:":                    "",
	":trophy:":                       "\U0001f3c6",
	":tropical_drink:":               "\U0001f379",
	":tropical_fish:":                "\U0001f420",
	":truck:":                        "\U0001f69a",
	":trumpet:":                      "\U0001f3ba",
	":tshirt:":                       "\U0001f455",
	":tulip:":                        "\U0001f337",
	":turtle:":                       "\U0001f422",
	":tv:":                           "\U0001f4fa",
	":twisted_rightwards_arrows:": "\U0001f500",
	":two:":                     "2\ufe0f\u20e3",
	":two_hearts:":              "\U0001f495",
	":two_men_holding_hands:":   "\U0001f46c",
	":two_women_holding_hands:": "\U0001f46d",
	":u5272:":                   "\U0001f239",
	":u5408:":                   "\U0001f234",
	":u55b6:":                   "\U0001f23a",
	":u6307:":                   "\U0001f22f",
	":u6708:":                   "\U0001f237\ufe0f",
	":u6709:":                   "\U0001f236",
	":u6e80:":                   "\U0001f235",
	":u7121:":                   "\U0001f21a",
	":u7533:":                   "\U0001f238",
	":u7981:":                   "\U0001f232",
	":u7a7a:":                   "\U0001f233",
	":uk:":                      "\U0001f1ec\U0001f1e7",
	":umbrella:":                "\u2614",
	":unamused:":                "\U0001f612",
	":underage:":                "\U0001f51e",
	":unlock:":                  "\U0001f513",
	":up:":                      "\U0001f199",
	":us:":                      "\U0001f1fa\U0001f1f8",
	":v:":                       "\u270c\ufe0f",
	":vertical_traffic_light:":    "\U0001f6a6",
	":vhs:":                       "\U0001f4fc",
	":vibration_mode:":            "\U0001f4f3",
	":video_camera:":              "\U0001f4f9",
	":video_game:":                "\U0001f3ae",
	":violin:":                    "\U0001f3bb",
	":virgo:":                     "\u264d",
	":volcano:":                   "\U0001f30b",
	":vs:":                        "\U0001f19a",
	":walking:":                   "\U0001f6b6",
	":waning_crescent_moon:":      "\U0001f318",
	":waning_gibbous_moon:":       "\U0001f316",
	":warning:":                   "\u26a0\ufe0f",
	":watch:":                     "\u231a",
	":water_buffalo:":             "\U0001f403",
	":watermelon:":                "\U0001f349",
	":wave:":                      "\U0001f44b",
	":wavy_dash:":                 "\u3030\ufe0f",
	":waxing_crescent_moon:":      "\U0001f312",
	":waxing_gibbous_moon:":       "\U0001f314",
	":wc:":                        "\U0001f6be",
	":weary:":                     "\U0001f629",
	":wedding:":                   "\U0001f492",
	":whale:":                     "\U0001f433",
	":whale2:":                    "\U0001f40b",
	":wheelchair:":                "\u267f",
	":white_check_mark:":          "\u2705",
	":white_circle:":              "\u26aa",
	":white_flower:":              "\U0001f4ae",
	":white_large_square:":        "\u2b1c",
	":white_medium_small_square:": "\u25fd",
	":white_medium_square:":       "\u25fb\ufe0f",
	":white_small_square:":        "\u25ab\ufe0f",
	":white_square_button:":       "\U0001f533",
	":wind_chime:":                "\U0001f390",
	":wine_glass:":                "\U0001f377",
	":wink:":                      "\U0001f609",
	":wolf:":                      "\U0001f43a",
	":woman:":                     "\U0001f469",
	":womans_clothes:":            "\U0001f45a",
	":womans_hat:":                "\U0001f452",
	":womens:":                    "\U0001f6ba",
	":worried:":                   "\U0001f61f",
	":wrench:":                    "\U0001f527",
	":x:":                         "\u274c",
	":yellow_heart:":              "\U0001f49b",
	":yen:":                       "\U0001f4b4",
	":yum:":                       "\U0001f60b",
	":zap:":                       "\u26a1",
	":zero:":                      "0\ufe0f\u20e3",
	":zzz:":                       "\U0001f4a4",
}


<|start_filename|>web/handlers/compression.go<|end_filename|>
package handlers

import (
	gorillahandlers "github.com/gorilla/handlers"
	"net/http"
)

func CompressResponses(baseHandler http.Handler) http.Handler {
	return gorillahandlers.CompressHandler(baseHandler)
}


<|start_filename|>web/view/viewmodel/xmlsitemap.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type XMLSitemap struct {
	Entries []XmlSitemapEntry
}

type XmlSitemapEntry struct {
	Loc          string                 `json:"loc"`
	LastModified string                 `json:"lastModified"`
	Images       []XmlSitemapEntryImage `json:"image:image"`
}

type XmlSitemapEntryImage struct {
	Loc string `json:"image:loc"`
}


<|start_filename|>vendor/github.com/arnoSCC/fulltext/searcher_test.go<|end_filename|>
package fulltext

import (
	"archive/zip"
	"bytes"
	"fmt"
	"github.com/spf13/afero"
	"html/template"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"path/filepath"
	re "regexp"
	"strconv"
	"strings"
	"testing"
	"time"
)

// Extract a single file from a zip and return it's contents
func zipExtract(zfpath string, fpath string) ([]byte, error) {

	zr, err := zip.OpenReader(zfpath)
	if err != nil {
		return nil, err
	}
	defer zr.Close()

	fpath = strings.Trim(filepath.Clean(filepath.ToSlash(fpath)), "/")

	for _, f := range zr.File {

		fn := strings.Trim(filepath.Clean(filepath.ToSlash(f.Name)), "/")

		// keep going until we find it
		if fn != fpath {
			continue
		}

		rc, err := f.Open()
		if err != nil {
			panic(err)
		}
		b, err := ioutil.ReadAll(rc)
		if err != nil {
			return nil, err
		}
		rc.Close()

		return b, nil

	}

	return nil, io.EOF

}

// Index and search the complete works of <NAME>
func TestTheBardSearch(t *testing.T) {

	fmt.Println("TestTheBardIndexing")

	idx, err := NewIndexer()
	if err != nil {
		panic(err)
	}
	defer idx.Close()

	titlere := re.MustCompile("(?i)<title>([^<]+)</title>")
	zr, err := zip.OpenReader("testdata/shakespeare.mit.edu.zip")
	if err != nil {
		panic(err)
	}
	defer zr.Close()

	for _, f := range zr.File {
		fmt.Printf("indexing: %s\n", f.Name)

		rc, err := f.Open()
		if err != nil {
			panic(err)
		}
		b, err := ioutil.ReadAll(rc)
		if err != nil {
			panic(err)
		}

		// extract title tag
		tret := titlere.FindSubmatch(b)
		title := ""
		if len(tret) > 1 {
			title = strings.TrimSpace(string(tret[1]))
		}

		// strip html from entire doc and get text
		body := HTMLStripTags(string(b))

		// make a doc out of it
		doc := IndexDoc{
			Id:         []byte(f.Name),
			StoreValue: []byte(title),
			IndexValue: []byte(title + " " + title + " " + body),
		}
		idx.AddDoc(doc)

		rc.Close()
	}

	fmt.Println("Writing final index...")
	var indexFs afero.Fs = &afero.MemMapFs{}
	searchIndexFile, err := indexFs.Create("idxout")
	if err != nil {
		panic(err)
	}
	err = idx.FinalizeAndWrite(searchIndexFile)
	if err != nil {
		panic(err)
	}

	defer searchIndexFile.Close()

	fmt.Printf("Wrote index file: %s\n", searchIndexFile.Name())

	/////////////////////////////////

	start := time.Now()

	searcher, err := NewSearcher(searchIndexFile)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Opening searcher took: %s\n", time.Since(start).String())

	start = time.Now()

	sr, err := searcher.SimpleSearch("king", 20)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Searching took: %s\n", time.Since(start).String())

	fmt.Printf("Total Results for 'king': %d\n", len(sr.Items))
	for k, v := range sr.Items {
		fmt.Printf("----------- #:%d\n", k)
		fmt.Printf("Id: %s\n", v.Id)
		fmt.Printf("Score: %d\n", v.Score)
		fmt.Printf("StoreValue: %s\n", v.StoreValue)
	}

	fmt.Printf("Raw dump: %+v\n", sr)

	///////////////////////////////////////////////////

	fmt.Printf("Starting Shakespeare's very own search interface at :1414 ...")

	ln, err := net.Listen("tcp", ":1414")
	if err != nil {
		panic(err)
	}

	timeoutStr := os.Getenv("SEARCHER_WEB_TIMEOUT_SECONDS")

	timeout, err := strconv.Atoi(timeoutStr)
	if err != nil {
		timeout = 10
	}

	zfpath := "testdata/shakespeare.mit.edu.zip"

	// wait for specified time
	go func() { time.Sleep(time.Duration(timeout) * time.Second); ln.Close() }()

	// main request handler
	err = http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

		// home page redirect
		if r.URL.Path == "/" || r.URL.Path == "/Shakespeare" {
			http.Redirect(w, r, "/shakespeare.mit.edu/index.html", 302)
			return
		}

		// handle search result page
		if r.URL.Path == "/searchresults.html" {

			w.Header().Set("Content-type", "text/html")

			q := r.FormValue("q")

			// do search
			sr, err := searcher.SimpleSearch(q, 20)
			if err != nil {
				panic(err)
			}

			// render results page
			sres, err := ioutil.ReadFile("testdata/searchresults.html")
			if err != nil {
				panic(err)
			}
			t := template.Must(template.New("main").Parse(string(sres)))
			var buf bytes.Buffer
			t.Execute(&buf, &map[string]interface{}{
				"q":  q,
				"sr": sr,
			})
			sresbytes := buf.Bytes()

			w.Write(sresbytes)

			return
		}

		// by default look through zip file
		b, err := zipExtract(zfpath, r.URL.Path)
		if err != nil {
			http.Error(w, "File not found", 404)
		}
		if strings.HasSuffix(r.URL.Path, ".css") {
			w.Header().Set("Content-type", "text/css")
		}
		if strings.HasSuffix(r.URL.Path, ".gif") {
			w.Header().Set("Content-type", "image/gif")
		}
		if strings.HasSuffix(r.URL.Path, ".jpg") {
			w.Header().Set("Content-type", "image/jpeg")
		}

		// for html files we inject a search box
		if strings.HasSuffix(r.URL.Path, ".html") {
			w.Header().Set("Content-type", "text/html")

			// render search form
			sf, err := ioutil.ReadFile("testdata/searchform.html")
			if err != nil {
				panic(err)
			}
			t := template.Must(template.New("main").Parse(string(sf)))
			var buf bytes.Buffer
			t.Execute(&buf, r.FormValue("q"))
			sfbytes := buf.Bytes()

			// inject into page

			pagebytes := re.MustCompile("(<body[^>]*>)").ReplaceAllLiteral(b, []byte("<body bgcolor=\"#ffffff\" text=\"#000000\">"+string(sfbytes)))
			w.Write(pagebytes)
			return

		}

		w.Write(b)

	}))

	if err != nil {
		fmt.Printf("err from listen: %s\n", err)
	}

	searcher.Close()

}


<|start_filename|>common/config/json.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package config

import (
	"encoding/json"
	"io"
)

type JSONSerializer struct{}

func NewJSONSerializer() *JSONSerializer {
	return &JSONSerializer{}
}

func (JSONSerializer) SerializeConfig(writer io.Writer, config *Config) error {
	bytes, err := json.MarshalIndent(config, "", "\t")
	if err != nil {
		return err
	}

	writer.Write(bytes)
	return nil
}

func (JSONSerializer) DeserializeConfig(reader io.Reader) (*Config, error) {
	decoder := json.NewDecoder(reader)
	var config *Config
	err := decoder.Decode(&config)
	return config, err
}


<|start_filename|>common/route/router.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package route

type Router interface {
	Route() *Route
}


<|start_filename|>web/view/templates/templatenames/constants.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package templatenames

const (
	Master = "master"
	Error  = "error"

	OpenSearchDescription = "opensearchdescription"

	Document     = "document"
	Presentation = "presentation"
	Repository   = "repository"

	Sitemap      = "sitemap"
	SitemapEntry = "sitemap-entry"

	XMLSitemap = "xmlsitemap"
	RSSFeed    = "rssfeed"
	TagMap     = "tagmap"
	AliasIndex = "aliasindex"
	Search     = "search"
	Conversion = "converter"
	RobotsTxt  = "robotstxt"

	Aliases              = "aliases-snippet"
	Tags                 = "tags-snippet"
	Publisher            = "publisher-snippet"
	ToplevelNavigation   = "toplevelnavigation-snippet"
	BreadcrumbNavigation = "breadcrumbnavigation-snippet"
	ItemNavigation       = "itemnavigation-snippet"
	Children               = "children-snippet"
	TagCloud             = "tagcloud-snippet"
)


<|start_filename|>services/parser/pattern/pattern.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pattern

import (
	"regexp"
	"strings"
)

var (
	// Lines which contain nothing but white space characters
	// or no characters at all.
	emptyLinePattern = regexp.MustCompile(`^\s*$`)

	// Lines which a start with a hash, followed by zero or more
	// white space characters, followed by text.
	titlePattern = regexp.MustCompile(`^#\s*([\pL\pN\p{Latin}]+.+)`)

	// Lines which start with text
	lineStartsWithTextPattern = regexp.MustCompile(`^[\pL\pN\p{Latin}]+.+`)

	// Text does contain typlical markdown elements
	textContainsMarkdownElementsPattern = regexp.MustCompile(`(\!\[)|(\]\()|([\*]{1,2}.+[\*]{1,2})`)

	// Lines which nothing but dashes
	horizontalRulePattern = regexp.MustCompile(`^-{3,}\s*$`)

	// Lines with a "key: value" syntax
	singleLineMetaDataPattern = regexp.MustCompile(`^(\w+[\w\s]+\w+):\s*([\pL\pN\p{Latin}]+.+)$`)

	// Multi-line tags meta data
	multiLineTagsPattern = regexp.MustCompile(`(?is)tags:\n{0,2}(\n\s?-\s?[^\n]+)+\n*`)

	// Multi-line alias meta data
	multiLineAliasPattern = regexp.MustCompile(`(?is)alias:\n{0,2}(\n\s?-\s?[^\n]+)+\n*`)

	// Lines with a meta data label in them syntax
	metaDataLabelPattern = regexp.MustCompile(`^(\w+[\w\s]+\w+):`)

	// Meta data list item pattern
	metaDataListItemPattern = regexp.MustCompile(`^\s?[*-]\s?(.+)$`)

	// Pattern which matches all HTML/XML tags
	HtmlTagPattern = regexp.MustCompile(`\<[^\>]*\>`)

	// Markdown headline pattern
	anyLevelMarkdownHeadline = regexp.MustCompile(`^(#+?)([^#].+?[^#])(#*)$`)
)

func IsEmpty(line string) bool {
	return emptyLinePattern.MatchString(line)
}

func IsHeadline(line string) (isHeadline bool, headline string, level int) {
	matches := anyLevelMarkdownHeadline.FindStringSubmatch(line)
	if len(matches) != 4 {
		return false, "", 0
	}

	hashes := strings.TrimSpace(matches[1])

	isHeadline = true
	headline = strings.TrimSpace(matches[2])
	level = len(hashes)

	return
}

func IsHorizontalRule(line string) bool {
	return horizontalRulePattern.MatchString(line)
}

func IsMetaDataDefinition(line string) bool {
	return metaDataLabelPattern.MatchString(line)
}

func GetMetaDataKey(line string) string {
	matches := metaDataLabelPattern.FindStringSubmatch(line)
	if len(matches) > 1 {
		return matches[1]
	}

	return ""
}

func GetSingleLineMetaDataKeyAndValue(line string) (key string, value string) {
	matches := singleLineMetaDataPattern.FindStringSubmatch(line)
	if len(matches) > 2 {
		return matches[1], matches[2]
	}

	if len(matches) > 1 {
		return matches[1], ""
	}

	return "", ""
}

func IsTitle(line string) (bool, string) {
	matches := titlePattern.FindStringSubmatch(line)
	if len(matches) > 1 {
		return true, matches[1] // title was found
	}

	return false, "" // no title was found
}

func IsDescription(line string) (bool, string) {
	lineStartsWithText := lineStartsWithTextPattern.MatchString(line)
	textContainsMarkdown := textContainsMarkdownElementsPattern.MatchString(line)

	if lineStartsWithText && textContainsMarkdown == false {
		return true, line // description was found
	}

	return false, "" // no description was found
}

func IsListItem(line string) (bool, string) {
	matches := metaDataListItemPattern.FindStringSubmatch(line)
	if len(matches) > 1 {
		return true, strings.TrimSpace(matches[1]) // list item was found
	}

	return false, "" // no list item was found
}

// IsMultiLineTagDefinition returns the if the supplied text contains a
// multi-line tag definition.
func IsMultiLineTagDefinition(text string) (bool, []string) {
	return isMultiLineDefinition(multiLineTagsPattern, text)
}

// IsMultiLineAliasDefinition returns the if the supplied text contains a
// multi-line alias definition.
func IsMultiLineAliasDefinition(text string) (bool, []string) {
	return isMultiLineDefinition(multiLineAliasPattern, text)
}

func isMultiLineDefinition(pattern *regexp.Regexp, text string) (bool, []string) {
	multiLineTagLocation := pattern.FindStringSubmatchIndex(text)
	if multiLineTagLocation == nil {
		return false, []string{}
	}

	tagNames := make([]string, 0)

	multiLineTagBlock := strings.TrimSpace(text[multiLineTagLocation[0]:multiLineTagLocation[1]])
	tagLines := strings.Split(multiLineTagBlock, "\n")
	for _, line := range tagLines {
		if isListItem, tagName := IsListItem(line); isListItem {
			tagNames = append(tagNames, tagName)
		}
	}

	return true, tagNames
}


<|start_filename|>web/view/viewmodel/title.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type Title struct {
	Value  string   `json:"value"`
	Tokens []string `json:"tokens"`
	Route  string   `json:"route"`
}


<|start_filename|>web/view/themes/themefiles/githubribbonpng.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

// GithubRibbonPNG is a copy of https://s3.amazonaws.com/github/ribbons/forkme_left_darkblue_121621.png
const GithubRibbonPNG = `<KEY>`


<|start_filename|>vendor/github.com/kyokomi/emoji/emoji_test.go<|end_filename|>
package emoji

import (
	"bytes"
	"fmt"
	"testing"
)

const (
	beerKey  = ":beer:"
	beerText = " ビール!!!"
)

var testFText = "test " + emojiCodeMap[beerKey] + ReplacePadding + beerText
var testText = emojiCodeMap[beerKey] + ReplacePadding + beerText

func TestCodeMap(t *testing.T) {
	m := CodeMap()
	if &emojiCodeMap == &m {
		t.Error("emojiCodeMap != EmojiCodeMap")
	}
}

func TestPrint(t *testing.T) {
	_, err := Print(beerKey, beerText)
	if err != nil {
		t.Error("Print ", err)
	}
}

func TestPrintln(t *testing.T) {
	_, err := Println(beerKey, beerText)
	if err != nil {
		t.Error("Println ", err)
	}
}

func TestPrintf(t *testing.T) {
	_, err := Printf("%s "+beerKey+beerText, "test")
	if err != nil {
		t.Error("Printf ", err)
	}
}

func TestFprint(t *testing.T) {
	var buf bytes.Buffer
	_, err := Fprint(&buf, beerKey+beerText)
	if err != nil {
		t.Error("Fprint ", err)
	}

	if buf.String() != testText {
		t.Error("Fprint ", buf.String(), testText)
	}
}

func TestFprintln(t *testing.T) {
	var buf bytes.Buffer
	_, err := Fprintln(&buf, beerKey+beerText)
	if err != nil {
		t.Error("Fprintln ", err)
	}

	if buf.String() != (testText + "\n") {
		t.Error("Fprintln ", buf.String(), (testText + "\n"))
	}
}

func TestFprintf(t *testing.T) {
	var buf bytes.Buffer
	_, err := Fprintf(&buf, "%s "+beerKey+beerText, "test")
	if err != nil {
		t.Error("Fprintf ", err)
	}

	if buf.String() != testFText {
		t.Error("Fprintf ", buf.String(), testFText)
	}
}

func TestSprint(t *testing.T) {
	convertBeer := Sprint(beerKey, beerText)
	if convertBeer != testText {
		t.Error("Sprint ", convertBeer, testText)
	}
}

func TestSprintf(t *testing.T) {
	convertBeer := Sprintf("%s "+beerKey+beerText, "test")
	if convertBeer != testFText {
		t.Error("Sprintf ", convertBeer, testFText)
	}
}

func TestErrorf(t *testing.T) {
	error := Errorf("%s "+beerKey+beerText, "test")
	if error.Error() != testFText {
		t.Error("Errorf ", error, testFText)
	}
}

func TestSprintMulti(t *testing.T) {
	convertBeer := Sprint(beerKey, beerText, beerKey, beerText)
	if convertBeer != (testText + testText) {
		t.Error("Sprint ", convertBeer, testText)
	}
	fmt.Println(convertBeer)
}


<|start_filename|>services/parser/metadata/util_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package metadata

import (
	"testing"
)

func Test_GetMetaDataLines_SingleLine(t *testing.T) {
	// arrange
	inputLines := []string{
		"# Headline",
		"Description",
		"",
		"yada yada",
		"",
		"---",
		"type: document",
	}

	// act
	result := GetMetaDataLines(inputLines)

	// assert
	if len(result) != 1 {
		t.Errorf("The resulting line slice should contain one line but contained %d lines.", len(result))
	}
}

func Test_GetMetaDataLines_SingleLineWithWhitespace(t *testing.T) {
	// arrange
	inputLines := []string{
		"# Headline",
		"Description",
		"",
		"yada yada",
		"",
		"---",
		"",
		"type: document",
		"",
	}

	// act
	result := GetMetaDataLines(inputLines)

	// assert
	if len(result) != 3 {
		t.Errorf("The resulting line slice should contain three lines but contained %d lines.", len(result))
	}
}

func Test_GetMetaDataLines_EmptyMetaDataSection(t *testing.T) {
	// arrange
	inputLines := []string{
		"# Headline",
		"Description",
		"",
		"yada yada",
		"",
		"---",
	}

	// act
	result := GetMetaDataLines(inputLines)

	// assert
	if len(result) != 0 {
		t.Errorf("The resulting line slice should be empty but contained %d lines.", len(result))
	}
}

func Test_GetMetaDataLines_NoMetaData(t *testing.T) {
	// arrange
	inputLines := []string{
		"# Headline",
		"Description",
		"",
		"yada yada",
		"",
	}

	// act
	result := GetMetaDataLines(inputLines)

	// assert
	if len(result) != 0 {
		t.Errorf("The resulting line slice should be empty but contained %d lines.", len(result))
	}
}

func Test_GetMetaDataLines_NoInput(t *testing.T) {
	// arrange
	inputLines := []string{}

	// act
	result := GetMetaDataLines(inputLines)

	// assert
	if len(result) != 0 {
		t.Errorf("The resulting line slice should be empty but contained %d lines.", len(result))
	}
}


<|start_filename|>web/view/viewmodel/basemodel.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

import (
	"sort"
)

// Base contains the minimum set of attributes for every view model.
type Base struct {
	RepositoryName        string `json:"repositoryName"`
	RepositoryDescription string `json:"repositoryDescription"`

	Type    string  `json:"type"`
	Level   int     `json:"level"`
	Route   string  `json:"route"`
	Aliases []Alias `json:"aliases"`

	ParentRoute string `json:"parentRoute"`

	BaseURL     string `json:"baseURL"`
	PrintURL    string `json:"printURL"`
	JSONURL     string `json:"jsonURL"`
	MarkdownURL string `json:"markdownURL"`
	DOCXURL     string `json:"docxURL"`

	PageTitle   string `json:"pageTitle"`
	Title       string `json:"title"`
	Description string `json:"description"`

	LanguageTag      string `json:"languageTag"`
	CreationDate     string `json:"creationdate"`
	LastModifiedDate string `json:"lastmodifieddate"`

	LiveReloadEnabled bool
}

type SortBaseModelBy func(model1, model2 Base) bool

func (by SortBaseModelBy) Sort(models []Base) {
	sorter := &baseModelSorter{
		models: models,
		by:     by,
	}

	sort.Sort(sorter)
}

type baseModelSorter struct {
	models []Base
	by     SortBaseModelBy
}

func (sorter *baseModelSorter) Len() int {
	return len(sorter.models)
}

func (sorter *baseModelSorter) Swap(i, j int) {
	sorter.models[i], sorter.models[j] = sorter.models[j], sorter.models[i]
}

func (sorter *baseModelSorter) Less(i, j int) bool {
	return sorter.by(sorter.models[i], sorter.models[j])
}


<|start_filename|>vendor/github.com/jbarham/go-cdb/cdbdump/cdbdump.go<|end_filename|>
package main

import (
	"bufio"
	"github.com/jbarham/go-cdb"
	"os"
)

func main() {
	bin, bout := bufio.NewReader(os.Stdin), bufio.NewWriter(os.Stdout)
	err := cdb.Dump(bout, bin)
	bout.Flush()
	if err != nil {
		os.Exit(111)
	}
}


<|start_filename|>web/view/viewmodel/toplevelnavigation.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type ToplevelNavigation struct {
	Entries []ToplevelEntry `json:"entries"`
}

func (navigation *ToplevelNavigation) IsAvailable() bool {
	return len(navigation.Entries) > 0
}

type ToplevelEntry struct {
	Title string `json:"title"`
	Path  string `json:"path"`
}


<|start_filename|>common/ports/ports.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ports

import (
	"fmt"
	"net"
)

// portRangeStart defines the first port that will be assigned
var portRangeStart = 33000

// portRangeEnd  defines the highest allowed port to be used.
const portRangeEnd = 34000

// GetFreePort returns a free port for the given TCPAddr.
func GetFreePort(network string, baseAddress net.TCPAddr) int {

	for portToTest := portRangeStart; portToTest < portRangeEnd; portToTest++ {

		// Don't reuse an already used port
		// for the next call to GetFreePort
		portRangeStart = portToTest + 1

		// assign a port to the base address
		baseAddress.Port = portToTest

		if isPortFree(network, baseAddress) {
			return portToTest
		}

	}

	panic(fmt.Sprintf("No free port found between %v and %v ", portRangeStart, portRangeEnd))
}

// isPortFree checks if the port for the given network and base address is free or not.
func isPortFree(network string, baseAddress net.TCPAddr) (isFree bool) {
	addr, err := net.ResolveTCPAddr(network, baseAddress.String())
	if err != nil {
		return false
	}
	l, err := net.ListenTCP(network, addr)
	if err != nil {
		return false
	}
	defer l.Close()
	return true
}


<|start_filename|>services/converter/markdowntohtml/util/util.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package util

import (
	"fmt"
	"strings"
)

func GetHtmlLinkCode(title, path string) string {
	return fmt.Sprintf(`<a href="%s" target="_blank" title="%s">%s</a>`, path, title, title)
}

// IsInternalLink returns true if the supplied link is an internal or an external link.
func IsInternalLink(link string) bool {
	return !IsExternalLink(link)
}

func IsExternalLink(link string) bool {
	lowercase := strings.TrimSpace(strings.ToLower(link))
	isHttpLink := strings.HasPrefix(lowercase, "http:")
	isHttpsLink := strings.HasPrefix(lowercase, "https:")
	return isHttpLink || isHttpsLink
}


<|start_filename|>common/tree/node.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tree

import (
	"fmt"
)

func newRootNode(name string, value interface{}) *Node {
	return newNode(nil, name, value)
}

func newNode(parent *Node, name string, value interface{}) *Node {

	// create the node
	node := &Node{
		parent: parent,

		name:  name,
		value: value,

		children:       make(map[string]*Node),
		childrenSorted: make([]*Node, 0),
	}

	// add the new node to the parents' children
	if parent != nil {
		parent.Insert(node)
	}

	return node
}

type Node struct {
	name  string
	value interface{}

	parent *Node

	children       map[string]*Node
	childrenSorted []*Node
}

func (node *Node) String() string {
	markdownListIdentifier := "- "
	text := getIndent(node.Level()) + markdownListIdentifier + node.Name()

	for _, child := range node.Children() {
		text += "\n" + child.String()
	}

	return text
}

func (node *Node) Name() string {
	if node.name == "" {
		return "<no-name-assigned>"
	}

	return node.name
}

func (node *Node) Value() interface{} {
	return node.value
}

func (node *Node) SetValue(value interface{}) {
	node.value = value
}

func (node *Node) Parent() *Node {
	return node.parent
}

func (node *Node) setParent(childNode *Node) {
	node.parent = childNode
}

func (node *Node) Level() int {
	return getNodeLevel(node)
}

func (node *Node) Children() []*Node {
	return node.childrenSorted
}

func (parentNode *Node) Insert(nodeToInsert *Node) (bool, error) {

	if nodeToInsert == nil {
		return false, fmt.Errorf("The supplied node is nil.")
	}

	// make this node the parent for the inserted (child) node
	nodeToInsert.setParent(parentNode)

	// determine the lookup key
	key := nodeToInsert.Name()

	// check if the given node already exists
	existingNode, exists := parentNode.children[key]
	if !exists {

		// insert the child node as a new entry
		parentNode.children[key] = nodeToInsert
		parentNode.childrenSorted = append(parentNode.childrenSorted, nodeToInsert)

		return true, nil // success
	}

	// insert all sub nodes of the supplied child node
	for _, subNode := range nodeToInsert.Children() {
		if childInserted, childInsertErr := existingNode.Insert(subNode); !childInserted {
			return false, childInsertErr
		}
	}

	return true, nil // success
}

func (parentNode *Node) Delete(path Path) (bool, error) {

	if path.IsEmpty() {
		return false, fmt.Errorf("The path is empty.")
	}

	firstComponent := path[0]

	// find a matching child
	matchingChild, matchingChildExists := parentNode.children[firstComponent]
	if !matchingChildExists {
		return false, fmt.Errorf("The node %q was not found.", path)
	}

	// recurse
	if len(path) > 1 {
		return matchingChild.Delete(path[1:])
	}

	// remove the node from the children
	delete(parentNode.children, firstComponent)
	parentNode.childrenSorted = deleteFromSlice(matchingChild, parentNode.childrenSorted)

	return true, nil
}

// Get the node that matches the supplied path.
func (currentNode *Node) GetNode(path Path) *Node {

	if path.IsEmpty() {
		return nil
	}

	// determine the lookup key
	currentNodeName := currentNode.Name()

	// get the first component of the supplied path
	firstPathComponent := path[0]

	// abort if the current node name does not match the first path component
	if currentNodeName != firstPathComponent {
		return nil
	}

	// if we have reached the end of the path we have found a match
	if isLastPathComponent := len(path) == 1; isLastPathComponent {
		return currentNode
	}

	// recurse
	subPath := path[1:]
	for _, childNode := range currentNode.Children() { // todo: make more efficient. lookup instead of iterate.
		if matchingNode := childNode.GetNode(subPath); matchingNode != nil {
			return matchingNode
		}
	}

	// no match found
	return nil
}

// Walk visits the current node, then every child of the current node and then recurses down the children.
func (currentNode *Node) Walk(expression func(node *Node)) {

	// children first
	for _, child := range currentNode.Children() {
		expression(child)
	}

	// recurse
	for _, child := range currentNode.Children() {
		child.Walk(expression)
	}
}

func getNodeLevel(node *Node) int {
	if node == nil {
		panic("Node cannot be nil.")
	}

	if node.Parent() == nil {
		return 0
	}

	return 1 + getNodeLevel(node.Parent())
}

func getIndent(level int) string {
	indent := ""
	for i := 0; i < level; i++ {
		indent += "    "
	}
	return indent
}

func deleteFromSlice(nodeToDelete *Node, nodes []*Node) []*Node {
	newNodes := make([]*Node, 0)

	for _, node := range nodes {
		if node.Name() == nodeToDelete.Name() {
			continue
		}
		newNodes = append(newNodes, node)
	}

	return newNodes
}


<|start_filename|>web/orchestrator/lazyload.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package orchestrator

import (
	"fmt"
	"regexp"
	"strings"
)

var (
	imageSrcPattern    = regexp.MustCompile(`src="([^"]+)"`)
	imageSrcSetPattern = regexp.MustCompile(`srcset="([^"]+)"`)
)

func lazyLoad(html string) string {

	html = lazyLoadSrcSet(html)
	html = lazyLoadSrc(html)

	return html
}

func lazyLoadSrc(html string) string {

	allMatches := imageSrcPattern.FindAllStringSubmatch(html, -1)
	for _, matches := range allMatches {

		if len(matches) != 2 {
			continue
		}

		// components
		originalText := strings.TrimSpace(matches[0])
		path := strings.TrimSpace(matches[1])

		// assemble the new link
		newLinkText := fmt.Sprintf(`data-sizes="auto" class="lazyload" data-src="%s"`, path)

		// replace the old text
		html = strings.Replace(html, originalText, newLinkText, -1)

	}

	return html
}

func lazyLoadSrcSet(html string) string {

	allMatches := imageSrcSetPattern.FindAllStringSubmatch(html, -1)
	for _, matches := range allMatches {

		if len(matches) != 2 {
			continue
		}

		// components
		originalText := strings.TrimSpace(matches[0])
		srcSetPaths := strings.TrimSpace(matches[1])

		// assemble the new link
		newLinkText := fmt.Sprintf(`data-sizes="auto" class="lazyload" data-srcset="%s"`, srcSetPaths)

		// replace the old text
		html = strings.Replace(html, originalText, newLinkText, -1)

	}

	return html
}


<|start_filename|>common/route/route_level_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package route

import (
	"testing"
)

func Test_Level_RootItemRoute_LevelIsZero(t *testing.T) {
	// arrange
	route := NewFromRequest("/")

	// act
	result := route.Level()

	// assert
	expected := 0
	if result != expected {
		t.Errorf("The level of %q should be %d but was %d.", route, expected, result)
	}
}

func Test_Level_FirstLevelRoute_LevelIsOne(t *testing.T) {
	// arrange
	route := NewFromRequest("/documents")

	// act
	result := route.Level()

	// assert
	expected := 1
	if result != expected {
		t.Errorf("The level of %q should be %d but was %d.", route, expected, result)
	}
}

func Test_Level_SecondLevelRoute_LevelIsTwo(t *testing.T) {
	// arrange
	route := NewFromRequest("/documents/Test-123")

	// act
	result := route.Level()

	// assert
	expected := 2
	if result != expected {
		t.Errorf("The level of %q should be %d but was %d.", route, expected, result)
	}
}

func Test_Level_ThirdLevelRoute_LevelIsThree(t *testing.T) {
	// arrange
	route := NewFromRequest("/documents/Test-123/Another-Test")

	// act
	result := route.Level()

	// assert
	expected := 3
	if result != expected {
		t.Errorf("The level of %q should be %d but was %d.", route, expected, result)
	}
}


<|start_filename|>web/view/themes/themefiles/deckjs.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const DeckJs = `
/*!
Deck JS - deck.core
Copyright (c) 2011 <NAME>
Dual licensed under the MIT license and GPL license.
https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
*/

/*
The deck.core module provides all the basic functionality for creating and
moving through a deck.  It does so by applying classes to indicate the state of
the deck and its slides, allowing CSS to take care of the visual representation
of each state.  It also provides methods for navigating the deck and inspecting
its state, as well as basic key bindings for going to the next and previous
slides.  More functionality is provided by wholly separate extension modules
that use the API provided by core.
*/
(function($, deck, document, undefined) {
	var slides, // Array of all the uh, slides...
	current, // Array index of the current slide
	$container, // Keeping this cached
	
	events = {
		/*
		This event fires whenever the current slide changes, whether by way of
		next, prev, or go. The callback function is passed two parameters, from
		and to, equal to the indices of the old slide and the new slide
		respectively. If preventDefault is called on the event within this handler
		the slide change does not occur.
		
		$(document).bind('deck.change', function(event, from, to) {
		   alert('Moving from slide ' + from + ' to ' + to);
		});
		*/
		change: 'deck.change',
		
		/*
		This event fires at the beginning of deck initialization, after the options
		are set but before the slides array is created.  This event makes a good hook
		for preprocessing extensions looking to modify the deck.
		*/
		beforeInitialize: 'deck.beforeInit',
		
		/*
		This event fires at the end of deck initialization. Extensions should
		implement any code that relies on user extensible options (key bindings,
		element selectors, classes) within a handler for this event. Native
		events associated with Deck JS should be scoped under a .deck event
		namespace, as with the example below:
		
		var $d = $(document);
		$.deck.defaults.keys.myExtensionKeycode = 70; // 'h'
		$d.bind('deck.init', function() {
		   $d.bind('keydown.deck', function(event) {
		      if (event.which === $.deck.getOptions().keys.myExtensionKeycode) {
		         // Rock out
		      }
		   });
		});
		*/
		initialize: 'deck.init' 
	},
	
	options = {},
	$d = $(document),
	
	/*
	Internal function. Updates slide and container classes based on which
	slide is the current slide.
	*/
	updateStates = function() {
		var oc = options.classes,
		osc = options.selectors.container,
		old = $container.data('onSlide'),
		$all = $();
		
		// Container state
		$container.removeClass(oc.onPrefix + old)
			.addClass(oc.onPrefix + current)
			.data('onSlide', current);
		
		// Remove and re-add child-current classes for nesting
		$('.' + oc.current).parentsUntil(osc).removeClass(oc.childCurrent);
		slides[current].parentsUntil(osc).addClass(oc.childCurrent);
		
		// Remove previous states
		$.each(slides, function(i, el) {
			$all = $all.add(el);
		});
		$all.removeClass([
			oc.before,
			oc.previous,
			oc.current,
			oc.next,
			oc.after
		].join(" "));
		
		// Add new states back in
		slides[current].addClass(oc.current);
		if (current > 0) {
			slides[current-1].addClass(oc.previous);
		}
		if (current + 1 < slides.length) {
			slides[current+1].addClass(oc.next);
		}
		if (current > 1) {
			$.each(slides.slice(0, current - 1), function(i, el) {
				el.addClass(oc.before);
			});
		}
		if (current + 2 < slides.length) {
			$.each(slides.slice(current+2), function(i, el) {
				el.addClass(oc.after);
			});
		}
	},
	
	/* Methods exposed in the jQuery.deck namespace */
	methods = {
		
		/*
		jQuery.deck(selector, options)
		
		selector: string | jQuery | array
		options: object, optional
				
		Initializes the deck, using each element matched by selector as a slide.
		May also be passed an array of string selectors or jQuery objects, in
		which case each selector in the array is considered a slide. The second
		parameter is an optional options object which will extend the default
		values.
		
		$.deck('.slide');
		
		or
		
		$.deck([
		   '#first-slide',
		   '#second-slide',
		   '#etc'
		]);
		*/	
		init: function(elements, opts) {
			var startTouch,
			tolerance,
			esp = function(e) {
				e.stopPropagation();
			};
			
			options = $.extend(true, {}, $[deck].defaults, opts);
			slides = [];
			current = 0;
			$container = $(options.selectors.container);
			tolerance = options.touch.swipeTolerance;
			
			// Pre init event for preprocessing hooks
			$d.trigger(events.beforeInitialize);
			
			// Hide the deck while states are being applied to kill transitions
			$container.addClass(options.classes.loading);
			
			// Fill slides array depending on parameter type
			if ($.isArray(elements)) {
				$.each(elements, function(i, e) {
					slides.push($(e));
				});
			}
			else {
				$(elements).each(function(i, e) {
					slides.push($(e));
				});
			}
			
			/* Remove any previous bindings, and rebind key events */
			$d.unbind('keydown.deck').bind('keydown.deck', function(e) {
				if (e.which === options.keys.next || $.inArray(e.which, options.keys.next) > -1) {
					methods.next();
					e.preventDefault();
				}
				else if (e.which === options.keys.previous || $.inArray(e.which, options.keys.previous) > -1) {
					methods.prev();
					e.preventDefault();
				}
			})
			/* Stop propagation of key events within editable elements */
			.undelegate('input, textarea, select, button, meter, progress, [contentEditable]', 'keydown', esp)
			.delegate('input, textarea, select, button, meter, progress, [contentEditable]', 'keydown', esp);
			
			/* Bind touch events for swiping between slides on touch devices */
			$container.unbind('touchstart.deck').bind('touchstart.deck', function(e) {
				if (!startTouch) {
					startTouch = $.extend({}, e.originalEvent.targetTouches[0]);
				}
			})
			.unbind('touchmove.deck').bind('touchmove.deck', function(e) {
				$.each(e.originalEvent.changedTouches, function(i, t) {
					if (startTouch && t.identifier === startTouch.identifier) {
						if (t.screenX - startTouch.screenX > tolerance || t.screenY - startTouch.screenY > tolerance) {
							$[deck]('prev');
							startTouch = undefined;
						}
						else if (t.screenX - startTouch.screenX < -1 * tolerance || t.screenY - startTouch.screenY < -1 * tolerance) {
							$[deck]('next');
							startTouch = undefined;
						}
						return false;
					}
				});
				e.preventDefault();
			})
			.unbind('touchend.deck').bind('touchend.deck', function(t) {
				$.each(t.originalEvent.changedTouches, function(i, t) {
					if (startTouch && t.identifier === startTouch.identifier) {
						startTouch = undefined;
					}
				});
			})
			.scrollLeft(0).scrollTop(0);
			
			/*
			Kick iframe videos, which dont like to redraw w/ transforms.
			Remove this if Webkit ever fixes it.
			 */
			$.each(slides, function(i, $el) {
				$el.unbind('webkitTransitionEnd.deck').bind('webkitTransitionEnd.deck',
				function(event) {
					if ($el.hasClass($[deck]('getOptions').classes.current)) {
						var embeds = $(this).find('iframe').css('opacity', 0);
						window.setTimeout(function() {
							embeds.css('opacity', 1);
						}, 100);
					}
				});
			});
			
			if (slides.length) {
				updateStates();
			}
			
			// Show deck again now that slides are in place
			$container.removeClass(options.classes.loading);
			$d.trigger(events.initialize);
		},
		
		/*
		jQuery.deck('go', index)
		
		index: integer | string
		
		Moves to the slide at the specified index if index is a number. Index is
		0-based, so $.deck('go', 0); will move to the first slide. If index is a
		string this will move to the slide with the specified id. If index is out
		of bounds or doesn't match a slide id the call is ignored.
		*/
		go: function(index) {
			var e = $.Event(events.change),
			ndx;
			
			/* Number index, easy. */
			if (typeof index === 'number' && index >= 0 && index < slides.length) {
				ndx = index;
			}
			/* Id string index, search for it and set integer index */
			else if (typeof index === 'string') {
				$.each(slides, function(i, $slide) {
					if ($slide.attr('id') === index) {
						ndx = i;
						return false;
					}
				});
			};
			
			/* Out of bounds, id doesn't exist, illegal input, eject */
			if (typeof ndx === 'undefined') return;
			
			$d.trigger(e, [current, ndx]);
			if (e.isDefaultPrevented()) {
				/* Trigger the event again and undo the damage done by extensions. */
				$d.trigger(events.change, [ndx, current]);
			}
			else {
				current = ndx;
				updateStates();
			}
		},
		
		/*
		jQuery.deck('next')
		
		Moves to the next slide. If the last slide is already active, the call
		is ignored.
		*/
		next: function() {
			methods.go(current+1);
		},
		
		/*
		jQuery.deck('prev')
		
		Moves to the previous slide. If the first slide is already active, the
		call is ignored.
		*/
		prev: function() {
			methods.go(current-1);
		},
		
		/*
		jQuery.deck('getSlide', index)
		
		index: integer, optional
		
		Returns a jQuery object containing the slide at index. If index is not
		specified, the current slide is returned.
		*/
		getSlide: function(index) {
			var i = typeof index !== 'undefined' ? index : current;
			if (typeof i != 'number' || i < 0 || i >= slides.length) return null;
			return slides[i];
		},
		
		/*
		jQuery.deck('getSlides')
		
		Returns all slides as an array of jQuery objects.
		*/
		getSlides: function() {
			return slides;
		},
		
		/*
		jQuery.deck('getContainer')
		
		Returns a jQuery object containing the deck container as defined by the
		container option.
		*/
		getContainer: function() {
			return $container;
		},
		
		/*
		jQuery.deck('getOptions')
		
		Returns the options object for the deck, including any overrides that
		were defined at initialization.
		*/
		getOptions: function() {
			return options;
		},
		
		/*
		jQuery.deck('extend', name, method)
		
		name: string
		method: function
		
		Adds method to the deck namespace with the key of name. This doesn’t
		give access to any private member data — public methods must still be
		used within method — but lets extension authors piggyback on the deck
		namespace rather than pollute jQuery.
		
		$.deck('extend', 'alert', function(msg) {
		   alert(msg);
		});

		// Alerts 'boom'
		$.deck('alert', 'boom');
		*/
		extend: function(name, method) {
			methods[name] = method;
		}
	};
	
	/* jQuery extension */
	$[deck] = function(method, arg) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		}
		else {
			return methods.init(method, arg);
		}
	};
	
	/*
	The default settings object for a deck. All deck extensions should extend
	this object to add defaults for any of their options.
	
	options.classes.after
		This class is added to all slides that appear after the 'next' slide.
	
	options.classes.before
		This class is added to all slides that appear before the 'previous'
		slide.
		
	options.classes.childCurrent
		This class is added to all elements in the DOM tree between the
		'current' slide and the deck container. For standard slides, this is
		mostly seen and used for nested slides.
		
	options.classes.current
		This class is added to the current slide.
		
	options.classes.loading
		This class is applied to the deck container during loading phases and is
		primarily used as a way to short circuit transitions between states
		where such transitions are distracting or unwanted.  For example, this
		class is applied during deck initialization and then removed to prevent
		all the slides from appearing stacked and transitioning into place
		on load.
		
	options.classes.next
		This class is added to the slide immediately following the 'current'
		slide.
		
	options.classes.onPrefix
		This prefix, concatenated with the current slide index, is added to the
		deck container as you change slides.
		
	options.classes.previous
		This class is added to the slide immediately preceding the 'current'
		slide.
		
	options.selectors.container
		Elements matched by this CSS selector will be considered the deck
		container. The deck container is used to scope certain states of the
		deck, as with the onPrefix option, or with extensions such as deck.goto
		and deck.menu.
		
	options.keys.next
		The numeric keycode used to go to the next slide.
		
	options.keys.previous
		The numeric keycode used to go to the previous slide.
		
	options.touch.swipeTolerance
		The number of pixels the users finger must travel to produce a swipe
		gesture.
	*/
	$[deck].defaults = {
		classes: {
			after: 'deck-after',
			before: 'deck-before',
			childCurrent: 'deck-child-current',
			current: 'deck-current',
			loading: 'deck-loading',
			next: 'deck-next',
			onPrefix: 'on-slide-',
			previous: 'deck-previous'
		},
		
		selectors: {
			container: '.deck-container'
		},
		
		keys: {
			// enter, space, page down, right arrow, down arrow,
			next: [13, 32, 34, 39, 40],
			// backspace, page up, left arrow, up arrow
			previous: [8, 33, 37, 38]
		},
		
		touch: {
			swipeTolerance: 60
		}
	};
	
	$d.ready(function() {
		$('html').addClass('ready');
	});
	
	/*
	FF + Transforms + Flash video don't get along...
	Firefox will reload and start playing certain videos after a
	transform.  Blanking the src when a previously shown slide goes out
	of view prevents this.
	*/
	$d.bind('deck.change', function(e, from, to) {
		var oldFrames = $[deck]('getSlide', from).find('iframe'),
		newFrames = $[deck]('getSlide', to).find('iframe');
		
		oldFrames.each(function() {
	    	var $this = $(this),
	    	curSrc = $this.attr('src');
            
            if(curSrc) {
            	$this.data('deck-src', curSrc).attr('src', '');
            }
		});
		
		newFrames.each(function() {
			var $this = $(this),
			originalSrc = $this.data('deck-src');
			
			if (originalSrc) {
				$this.attr('src', originalSrc);
			}
		});
	});
})(jQuery, 'deck', document);

/*!
Deck JS - deck.goto
Copyright (c) 2011 <NAME>
Dual licensed under the MIT license and GPL license.
https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
*/

/*
This module adds the necessary methods and key bindings to show and hide a form
for jumping to any slide number/id in the deck (and processes that form
accordingly). The form-showing state is indicated by the presence of a class on
the deck container.
*/
(function($, deck, undefined) {
	var $d = $(document);
	
	/*
	Extends defaults/options.
	
	options.classes.goto
		This class is added to the deck container when showing the Go To Slide
		form.
		
	options.selectors.gotoDatalist
		The element that matches this selector is the datalist element that will
		be populated with options for each of the slide ids.  In browsers that
		support the datalist element, this provides a drop list of slide ids to
		aid the user in selecting a slide.
		
	options.selectors.gotoForm
		The element that matches this selector is the form that is submitted
		when a user hits enter after typing a slide number/id in the gotoInput
		element.
	
	options.selectors.gotoInput
		The element that matches this selector is the text input field for
		entering a slide number/id in the Go To Slide form.
		
	options.keys.goto
		The numeric keycode used to show the Go To Slide form.
		
	options.countNested
		If false, only top level slides will be counted when entering a
		slide number.
	*/
	$.extend(true, $[deck].defaults, {
		classes: {
			goto: 'deck-goto'
		},
		
		selectors: {
			gotoDatalist: '#goto-datalist',
			gotoForm: '.goto-form',
			gotoInput: '#goto-slide'
		},
		
		keys: {
			goto: 71 // g
		},
		
		countNested: true
	});

	/*
	jQuery.deck('showGoTo')
	
	Shows the Go To Slide form by adding the class specified by the goto class
	option to the deck container.
	*/
	$[deck]('extend', 'showGoTo', function() {
		$[deck]('getContainer').addClass($[deck]('getOptions').classes.goto);
		$($[deck]('getOptions').selectors.gotoInput).focus();
	});

	/*
	jQuery.deck('hideGoTo')
	
	Hides the Go To Slide form by removing the class specified by the goto class
	option from the deck container.
	*/
	$[deck]('extend', 'hideGoTo', function() {
		$($[deck]('getOptions').selectors.gotoInput).blur();
		$[deck]('getContainer').removeClass($[deck]('getOptions').classes.goto);
	});

	/*
	jQuery.deck('toggleGoTo')
	
	Toggles between showing and hiding the Go To Slide form.
	*/
	$[deck]('extend', 'toggleGoTo', function() {
		$[deck]($[deck]('getContainer').hasClass($[deck]('getOptions').classes.goto) ? 'hideGoTo' : 'showGoTo');
	});
	
	$d.bind('deck.init', function() {
		var opts = $[deck]('getOptions'),
		$datalist = $(opts.selectors.gotoDatalist),
		slideTest = $.map([
			opts.classes.before,
			opts.classes.previous,
			opts.classes.current,
			opts.classes.next,
			opts.classes.after
		], function(el, i) {
			return '.' + el;
		}).join(', '),
		rootCounter = 1;
		
		// Bind key events
		$d.unbind('keydown.deckgoto').bind('keydown.deckgoto', function(e) {
			var key = $[deck]('getOptions').keys.goto;
			
			if (e.which === key || $.inArray(e.which, key) > -1) {
				e.preventDefault();
				$[deck]('toggleGoTo');
			}
		});
		
		/* Populate datalist and work out countNested*/
		$.each($[deck]('getSlides'), function(i, $slide) {
			var id = $slide.attr('id'),
			$parentSlides = $slide.parentsUntil(opts.selectors.container, slideTest);
			
			if (id) {
				$datalist.append('<option value="' + id + '">');
			}
			
			if ($parentSlides.length) {
				$slide.removeData('rootIndex');
			}
			else if (!opts.countNested) {
				$slide.data('rootIndex', rootCounter);
				++rootCounter;
			}
		});
		
		// Process form submittal, go to the slide entered
		$(opts.selectors.gotoForm)
		.unbind('submit.deckgoto')
		.bind('submit.deckgoto', function(e) {
			var $field = $($[deck]('getOptions').selectors.gotoInput),
			ndx = parseInt($field.val(), 10);
			
			if (!$[deck]('getOptions').countNested) {
			  if (ndx >= rootCounter) return false;
				$.each($[deck]('getSlides'), function(i, $slide) {
					if ($slide.data('rootIndex') === ndx) {
						ndx = i + 1;
						return false;
					}
				});
			}
			
			$[deck]('go', isNaN(ndx) ? $field.val() : ndx - 1);
			$[deck]('hideGoTo');
			$field.val('');
			
			e.preventDefault();
		});
		
		// Dont let keys in the input trigger deck actions
		$(opts.selectors.gotoInput)
		.unbind('keydown.deckgoto')
		.bind('keydown.deckgoto', function(e) {
			e.stopPropagation();
		});
	});
})(jQuery, 'deck');

/*!
Deck JS - deck.hash
Copyright (c) 2011 <NAME>
Dual licensed under the MIT license and GPL license.
https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
*/

/*
This module adds deep linking to individual slides, enables internal links
to slides within decks, and updates the address bar with the hash as the user
moves through the deck. A permalink anchor is also updated. Standard themes
hide this link in browsers that support the History API, and show it for
those that do not. Slides that do not have an id are assigned one according to
the hashPrefix option. In addition to the on-slide container state class
kept by core, this module adds an on-slide state class that uses the id of each
slide.
*/
(function ($, deck, window, undefined) {
	var $d = $(document),
	$window = $(window),
	
	/* Collection of internal fragment links in the deck */
	$internals,
	
	/*
	Internal only function.  Given a string, extracts the id from the hash,
	matches it to the appropriate slide, and navigates there.
	*/
	goByHash = function(str) {
		var id = str.substr(str.indexOf("#") + 1),
		slides = $[deck]('getSlides');
		
		$.each(slides, function(i, $el) {
			if ($el.attr('id') === id) {
				$[deck]('go', i);
				return false;
			}
		});
		
		// If we don't set these to 0 the container scrolls due to hashchange
		$[deck]('getContainer').scrollLeft(0).scrollTop(0);
	};
	
	/*
	Extends defaults/options.
	
	options.selectors.hashLink
		The element matching this selector has its href attribute updated to
		the hash of the current slide as the user navigates through the deck.
		
	options.hashPrefix
		Every slide that does not have an id is assigned one at initialization.
		Assigned ids take the form of hashPrefix + slideIndex, e.g., slide-0,
		slide-12, etc.

	options.preventFragmentScroll
		When deep linking to a hash of a nested slide, this scrolls the deck
		container to the top, undoing the natural browser behavior of scrolling
		to the document fragment on load.
	*/
	$.extend(true, $[deck].defaults, {
		selectors: {
			hashLink: '.deck-permalink'
		},
		
		hashPrefix: 'slide-',
		preventFragmentScroll: true
	});
	
	
	$d.bind('deck.init', function() {
	   var opts = $[deck]('getOptions');
		$internals = $(),
		slides = $[deck]('getSlides');
		
		$.each(slides, function(i, $el) {
			var hash;
			
			/* Hand out ids to the unfortunate slides born without them */
			if (!$el.attr('id') || $el.data('deckAssignedId') === $el.attr('id')) {
				$el.attr('id', opts.hashPrefix + i);
				$el.data('deckAssignedId', opts.hashPrefix + i);
			}
			
			hash ='#' + $el.attr('id');
			
			/* Deep link to slides on init */
			if (hash === window.location.hash) {
				$[deck]('go', i);
			}
			
			/* Add internal links to this slide */
			$internals = $internals.add('a[href="' + hash + '"]');
		});
		
		if (!Modernizr.hashchange) {
			/* Set up internal links using click for the poor browsers
			without a hashchange event. */
			$internals.unbind('click.deckhash').bind('click.deckhash', function(e) {
				goByHash($(this).attr('href'));
			});
		}
		
		/* Set up first id container state class */
		if (slides.length) {
			$[deck]('getContainer').addClass(opts.classes.onPrefix + $[deck]('getSlide').attr('id'));
		};
	})
	/* Update permalink, address bar, and state class on a slide change */
	.bind('deck.change', function(e, from, to) {
		var hash = '#' + $[deck]('getSlide', to).attr('id'),
		hashPath = window.location.href.replace(/#.*/, '') + hash,
		opts = $[deck]('getOptions'),
		osp = opts.classes.onPrefix,
		$c = $[deck]('getContainer');
		
		$c.removeClass(osp + $[deck]('getSlide', from).attr('id'));
		$c.addClass(osp + $[deck]('getSlide', to).attr('id'));
		
		$(opts.selectors.hashLink).attr('href', hashPath);
		if (Modernizr.history) {
			window.history.replaceState({}, "", hashPath);
		}
	});
	
	/* Deals with internal links in modern browsers */
	$window.bind('hashchange.deckhash', function(e) {
		if (e.originalEvent && e.originalEvent.newURL) {
			goByHash(e.originalEvent.newURL);
		}
		else {
			goByHash(window.location.hash);
		}
	})
	/* Prevent scrolling on deep links */
	.bind('load', function() {
		if ($[deck]('getOptions').preventFragmentScroll) {
			$[deck]('getContainer').scrollLeft(0).scrollTop(0);
		}
	});
})(jQuery, 'deck', this);

/*!
Deck JS - deck.menu
Copyright (c) 2011 <NAME>
Dual licensed under the MIT license and GPL license.
https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
*/

/*
This module adds the methods and key binding to show and hide a menu of all
slides in the deck. The deck menu state is indicated by the presence of a class
on the deck container.
*/
(function($, deck, undefined) {
	var $d = $(document),
	rootSlides; // Array of top level slides
	
	/*
	Extends defaults/options.
	
	options.classes.menu
		This class is added to the deck container when showing the slide menu.
	
	options.keys.menu
		The numeric keycode used to toggle between showing and hiding the slide
		menu.
		
	options.touch.doubletapWindow
		Two consecutive touch events within this number of milliseconds will
		be considered a double tap, and will toggle the menu on touch devices.
	*/
	$.extend(true, $[deck].defaults, {
		classes: {
			menu: 'deck-menu'
		},
		
		keys: {
			menu: 77 // m
		},
		
		touch: {
			doubletapWindow: 400
		}
	});

	/*
	jQuery.deck('showMenu')
	
	Shows the slide menu by adding the class specified by the menu class option
	to the deck container.
	*/
	$[deck]('extend', 'showMenu', function() {
		var $c = $[deck]('getContainer'),
		opts = $[deck]('getOptions');
		
		if ($c.hasClass(opts.classes.menu)) return;
		
		// Hide through loading class to short-circuit transitions (perf)
		$c.addClass([opts.classes.loading, opts.classes.menu].join(' '));
		
		/* Forced to do this in JS until CSS learns second-grade math. Save old
		style value for restoration when menu is hidden. */
		if (Modernizr.csstransforms) {
			$.each(rootSlides, function(i, $slide) {
				$slide.data('oldStyle', $slide.attr('style'));
				$slide.css({
					'position': 'absolute',
					'left': ((i % 4) * 25) + '%',
					'top': (Math.floor(i / 4) * 25) + '%'
				});
			});
		}
		
		// Need to ensure the loading class renders first, then remove
		window.setTimeout(function() {
			$c.removeClass(opts.classes.loading)
				.scrollTop($[deck]('getSlide').offset().top);
		}, 0);
	});

	/*
	jQuery.deck('hideMenu')
	
	Hides the slide menu by removing the class specified by the menu class
	option from the deck container.
	*/
	$[deck]('extend', 'hideMenu', function() {
		var $c = $[deck]('getContainer'),
		opts = $[deck]('getOptions');
		
		if (!$c.hasClass(opts.classes.menu)) return;
		
		$c.removeClass(opts.classes.menu);
		$c.addClass(opts.classes.loading);
		
		/* Restore old style value */
		if (Modernizr.csstransforms) {
			$.each(rootSlides, function(i, $slide) {
				var oldStyle = $slide.data('oldStyle');

				$slide.attr('style', oldStyle ? oldStyle : '');
			});
		}
		
		window.setTimeout(function() {
			$c.removeClass(opts.classes.loading).scrollTop(0);
		}, 0);
	});

	/*
	jQuery.deck('toggleMenu')
	
	Toggles between showing and hiding the slide menu.
	*/
	$[deck]('extend', 'toggleMenu', function() {
		$[deck]('getContainer').hasClass($[deck]('getOptions').classes.menu) ?
		$[deck]('hideMenu') : $[deck]('showMenu');
	});

	$d.bind('deck.init', function() {
		var opts = $[deck]('getOptions'),
		touchEndTime = 0,
		currentSlide,
		slideTest = $.map([
			opts.classes.before,
			opts.classes.previous,
			opts.classes.current,
			opts.classes.next,
			opts.classes.after
		], function(el, i) {
			return '.' + el;
		}).join(', ');
		
		// Build top level slides array
		rootSlides = [];
		$.each($[deck]('getSlides'), function(i, $el) {
			if (!$el.parentsUntil(opts.selectors.container, slideTest).length) {
				rootSlides.push($el);
			}
		});
		
		// Bind key events
		$d.unbind('keydown.deckmenu').bind('keydown.deckmenu', function(e) {
			if (e.which === opts.keys.menu || $.inArray(e.which, opts.keys.menu) > -1) {
				$[deck]('toggleMenu');
				e.preventDefault();
			}
		});
		
		// Double tap to toggle slide menu for touch devices
		$[deck]('getContainer').unbind('touchstart.deckmenu').bind('touchstart.deckmenu', function(e) {
			currentSlide = $[deck]('getSlide');
		})
		.unbind('touchend.deckmenu').bind('touchend.deckmenu', function(e) {
			var now = Date.now();
			
			// Ignore this touch event if it caused a nav change (swipe)
			if (currentSlide !== $[deck]('getSlide')) return;
			
			if (now - touchEndTime < opts.touch.doubletapWindow) {
				$[deck]('toggleMenu');
				e.preventDefault();
			}
			touchEndTime = now;
		});
		
		// Selecting slides from the menu
		$.each($[deck]('getSlides'), function(i, $s) {
			$s.unbind('click.deckmenu').bind('click.deckmenu', function(e) {
				if (!$[deck]('getContainer').hasClass(opts.classes.menu)) return;

				$[deck]('go', i);
				$[deck]('hideMenu');
				e.stopPropagation();
				e.preventDefault();
			});
		});
	})
	.bind('deck.change', function(e, from, to) {
		var container = $[deck]('getContainer');
		
		if (container.hasClass($[deck]('getOptions').classes.menu)) {
			container.scrollTop($[deck]('getSlide', to).offset().top);
		}
	});
})(jQuery, 'deck');

/*!
Deck JS - deck.navigation
Copyright (c) 2011 <NAME>
Dual licensed under the MIT license and GPL license.
https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
*/

/*
This module adds clickable previous and next links to the deck.
*/
(function($, deck, undefined) {
	var $d = $(document),
	
	/* Updates link hrefs, and disabled states if last/first slide */
	updateButtons = function(e, from, to) {
		var opts = $[deck]('getOptions'),
		last = $[deck]('getSlides').length - 1,
		prevSlide = $[deck]('getSlide', to - 1),
		nextSlide = $[deck]('getSlide', to + 1),
		hrefBase = window.location.href.replace(/#.*/, ''),
		prevId = prevSlide ? prevSlide.attr('id') : undefined,
		nextId = nextSlide ? nextSlide.attr('id') : undefined;
		
		$(opts.selectors.previousLink)
			.toggleClass(opts.classes.navDisabled, !to)
			.attr('href', hrefBase + '#' + (prevId ? prevId : ''));
		$(opts.selectors.nextLink)
			.toggleClass(opts.classes.navDisabled, to === last)
			.attr('href', hrefBase + '#' + (nextId ? nextId : ''));
	};
	
	/*
	Extends defaults/options.
	
	options.classes.navDisabled
		This class is added to a navigation link when that action is disabled.
		It is added to the previous link when on the first slide, and to the
		next link when on the last slide.
		
	options.selectors.nextLink
		The elements that match this selector will move the deck to the next
		slide when clicked.
		
	options.selectors.previousLink
		The elements that match this selector will move to deck to the previous
		slide when clicked.
	*/
	$.extend(true, $[deck].defaults, {
		classes: {
			navDisabled: 'deck-nav-disabled'
		},
		
		selectors: {
			nextLink: '.deck-next-link',
			previousLink: '.deck-prev-link'
		}
	});

	$d.bind('deck.init', function() {
		var opts = $[deck]('getOptions'),
		slides = $[deck]('getSlides'),
		$current = $[deck]('getSlide'),
		ndx;
		
		// Setup prev/next link events
		$(opts.selectors.previousLink)
		.unbind('click.decknavigation')
		.bind('click.decknavigation', function(e) {
			$[deck]('prev');
			e.preventDefault();
		});
		
		$(opts.selectors.nextLink)
		.unbind('click.decknavigation')
		.bind('click.decknavigation', function(e) {
			$[deck]('next');
			e.preventDefault();
		});
		
		// Find where we started in the deck and set initial states
		$.each(slides, function(i, $slide) {
			if ($slide === $current) {
				ndx = i;
				return false;
			}
		});
		updateButtons(null, ndx, ndx);
	})
	.bind('deck.change', updateButtons);
})(jQuery, 'deck');

/*!
Deck JS - deck.status
Copyright (c) 2011 <NAME>
Dual licensed under the MIT license and GPL license.
https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
*/

/*
This module adds a (current)/(total) style status indicator to the deck.
*/
(function($, deck, undefined) {
	var $d = $(document),
	
	updateCurrent = function(e, from, to) {
		var opts = $[deck]('getOptions');
		
		$(opts.selectors.statusCurrent).text(opts.countNested ?
			to + 1 :
			$[deck]('getSlide', to).data('rootSlide')
		);
	};
	
	/*
	Extends defaults/options.
	
	options.selectors.statusCurrent
		The element matching this selector displays the current slide number.
		
	options.selectors.statusTotal
		The element matching this selector displays the total number of slides.
		
	options.countNested
		If false, only top level slides will be counted in the current and
		total numbers.
	*/
	$.extend(true, $[deck].defaults, {
		selectors: {
			statusCurrent: '.deck-status-current',
			statusTotal: '.deck-status-total'
		},
		
		countNested: true
	});
	
	$d.bind('deck.init', function() {
		var opts = $[deck]('getOptions'),
		slides = $[deck]('getSlides'),
		$current = $[deck]('getSlide'),
		ndx;
		
		// Set total slides once
		if (opts.countNested) {
			$(opts.selectors.statusTotal).text(slides.length);
		}
		else {
			/* Determine root slides by checking each slide's ancestor tree for
			any of the slide classes. */
			var rootIndex = 1,
			slideTest = $.map([
				opts.classes.before,
				opts.classes.previous,
				opts.classes.current,
				opts.classes.next,
				opts.classes.after
			], function(el, i) {
				return '.' + el;
			}).join(', ');
			
			/* Store the 'real' root slide number for use during slide changes. */
			$.each(slides, function(i, $el) {
				var $parentSlides = $el.parentsUntil(opts.selectors.container, slideTest);

				$el.data('rootSlide', $parentSlides.length ?
					$parentSlides.last().data('rootSlide') :
					rootIndex++
				);
			});
			
			$(opts.selectors.statusTotal).text(rootIndex - 1);
		}
		
		// Find where we started in the deck and set initial state
		$.each(slides, function(i, $el) {
			if ($el === $current) {
				ndx = i;
				return false;
			}
		});
		updateCurrent(null, ndx, ndx);
	})
	/* Update current slide number with each change event */
	.bind('deck.change', updateCurrent);
})(jQuery, 'deck');
`
const DeckCss = `

body.deck-container {
  overflow-y: auto;
  position: static;
}

.deck-container {
  position: relative;
  min-height: 100%;
  margin: 0 auto;
  padding: 0 48px;
  font-size: 16px;
  line-height: 1.25;
  overflow: hidden;
  /* Resets and base styles from HTML5 Boilerplate */
  /* End HTML5 Boilerplate adaptations */
}
.js .deck-container {
  visibility: hidden;
}
.ready .deck-container {
  visibility: visible;
}
.touch .deck-container {
  -webkit-text-size-adjust: none;
  -moz-text-size-adjust: none;
}
.deck-container div, .deck-container span, .deck-container object, .deck-container iframe,
.deck-container h1, .deck-container h2, .deck-container h3, .deck-container h4, .deck-container h5, .deck-container h6, .deck-container p, .deck-container blockquote, .deck-container pre,
.deck-container abbr, .deck-container address, .deck-container cite, .deck-container code, .deck-container del, .deck-container dfn, .deck-container em, .deck-container img, .deck-container ins, .deck-container kbd, .deck-container q, .deck-container samp,
.deck-container small, .deck-container strong, .deck-container sub, .deck-container sup, .deck-container var, .deck-container b, .deck-container i, .deck-container dl, .deck-container dt, .deck-container dd, .deck-container ol, .deck-container ul, .deck-container li,
.deck-container fieldset, .deck-container form, .deck-container label, .deck-container legend,
.deck-container table, .deck-container caption, .deck-container tbody, .deck-container tfoot, .deck-container thead, .deck-container tr, .deck-container th, .deck-container td,
.deck-container article, .deck-container aside, .deck-container canvas, .deck-container details, .deck-container figcaption, .deck-container figure,
.deck-container footer, .deck-container header, .deck-container hgroup, .deck-container menu, .deck-container nav, .deck-container section, .deck-container summary,
.deck-container time, .deck-container mark, .deck-container audio, .deck-container video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}
.deck-container article, .deck-container aside, .deck-container details, .deck-container figcaption, .deck-container figure,
.deck-container footer, .deck-container header, .deck-container hgroup, .deck-container menu, .deck-container nav, .deck-container section {
  display: block;
}
.deck-container blockquote, .deck-container q {
  quotes: none;
}
.deck-container blockquote:before, .deck-container blockquote:after, .deck-container q:before, .deck-container q:after {
  content: "";
  content: none;
}
.deck-container ins {
  background-color: #ff9;
  color: #000;
  text-decoration: none;
}
.deck-container mark {
  background-color: #ff9;
  color: #000;
  font-style: italic;
  font-weight: bold;
}
.deck-container del {
  text-decoration: line-through;
}
.deck-container abbr[title], .deck-container dfn[title] {
  border-bottom: 1px dotted;
  cursor: help;
}
.deck-container table {
  border-collapse: collapse;
  border-spacing: 0;
}
.deck-container hr {
  display: block;
  height: 1px;
  border: 0;
  border-top: 1px solid #ccc;
  margin: 1em 0;
  padding: 0;
}
.deck-container input, .deck-container select {
  vertical-align: middle;
}
.deck-container select, .deck-container input, .deck-container textarea, .deck-container button {
  font: 99% sans-serif;
}
.deck-container pre, .deck-container code, .deck-container kbd, .deck-container samp {
  font-family: monospace, sans-serif;
}
.deck-container a {
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.deck-container a:hover, .deck-container a:active {
  outline: none;
}
.deck-container ul, .deck-container ol {
  margin-left: 2em;
  vertical-align: top;
}
.deck-container ol {
  list-style-type: decimal;
}
.deck-container nav ul, .deck-container nav li {
  margin: 0;
  list-style: none;
  list-style-image: none;
}
.deck-container small {
  font-size: 85%;
}
.deck-container strong, .deck-container th {
  font-weight: bold;
}
.deck-container td {
  vertical-align: top;
}
.deck-container sub, .deck-container sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
}
.deck-container sup {
  top: -0.5em;
}
.deck-container sub {
  bottom: -0.25em;
}
.deck-container textarea {
  overflow: auto;
}
.ie6 .deck-container legend, .ie7 .deck-container legend {
  margin-left: -7px;
}
.deck-container input[type="radio"] {
  vertical-align: text-bottom;
}
.deck-container input[type="checkbox"] {
  vertical-align: bottom;
}
.ie7 .deck-container input[type="checkbox"] {
  vertical-align: baseline;
}
.ie6 .deck-container input {
  vertical-align: text-bottom;
}
.deck-container label, .deck-container input[type="button"], .deck-container input[type="submit"], .deck-container input[type="image"], .deck-container button {
  cursor: pointer;
}
.deck-container button, .deck-container input, .deck-container select, .deck-container textarea {
  margin: 0;
}
.deck-container input:invalid, .deck-container textarea:invalid {
  border-radius: 1px;
  -moz-box-shadow: 0px 0px 5px red;
  -webkit-box-shadow: 0px 0px 5px red;
  box-shadow: 0px 0px 5px red;
}
.deck-container input:invalid .no-boxshadow, .deck-container textarea:invalid .no-boxshadow {
  background-color: #f0dddd;
}
.deck-container button {
  width: auto;
  overflow: visible;
}
.ie7 .deck-container img {
  -ms-interpolation-mode: bicubic;
}
.deck-container, .deck-container select, .deck-container input, .deck-container textarea {
  color: #444;
}
.deck-container a {
  color: #607890;
}
.deck-container a:hover, .deck-container a:focus {
  color: #036;
}
.deck-container a:link {
  -webkit-tap-highlight-color: #fff;
}
.deck-container.deck-loading {
  display: none;
}

.slide {
  width: auto;
  min-height: 100%;
  position: relative;
}
.slide h1 {
  font-size: 4.5em;
}
.slide h1, .slide .vcenter {
  font-weight: bold;
  text-align: center;
  padding-top: 1em;
  max-height: 100%;
}
.csstransforms .slide h1, .csstransforms .slide .vcenter {
  padding: 0 48px;
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  -webkit-transform: translate(0, -50%);
  -moz-transform: translate(0, -50%);
  -ms-transform: translate(0, -50%);
  -o-transform: translate(0, -50%);
  transform: translate(0, -50%);
}
.slide .vcenter h1 {
  position: relative;
  top: auto;
  padding: 0;
  -webkit-transform: none;
  -moz-transform: none;
  -ms-transform: none;
  -o-transform: none;
  transform: none;
}
.slide h2 {
  font-size: 2.25em;
  font-weight: bold;
  padding-top: .5em;
  margin: 0 0 .66666em 0;
  border-bottom: 3px solid #888;
}
.slide h3 {
  font-size: 1.4375em;
  font-weight: bold;
  margin-bottom: .30435em;
}
.slide h4 {
  font-size: 1.25em;
  font-weight: bold;
  margin-bottom: .25em;
}
.slide h5 {
  font-size: 1.125em;
  font-weight: bold;
  margin-bottom: .2222em;
}
.slide h6 {
  font-size: 1em;
  font-weight: bold;
}
.slide img, .slide iframe, .slide video {
  display: block;
  max-width: 100%;
}
.slide video, .slide iframe, .slide img {
  display: block;
  margin: 0 auto;
}
.slide p, .slide blockquote, .slide iframe, .slide img, .slide ul, .slide ol, .slide pre, .slide video {
  margin-bottom: 1em;
}
.slide pre {
  white-space: pre;
  white-space: pre-wrap;
  word-wrap: break-word;
  padding: 1em;
  border: 1px solid #888;
}
.slide em {
  font-style: italic;
}
.slide li {
  padding: .25em 0;
  vertical-align: middle;
}

.deck-before, .deck-previous, .deck-next, .deck-after {
  position: absolute;
  left: -999em;
  top: -999em;
}

.deck-current {
  z-index: 2;
}

.slide .slide {
  visibility: hidden;
  position: static;
  min-height: 0;
}

.deck-child-current {
  position: static;
  z-index: 2;
}
.deck-child-current .slide {
  visibility: hidden;
}
.deck-child-current .deck-previous, .deck-child-current .deck-before, .deck-child-current .deck-current {
  visibility: visible;
}

.deck-container .goto-form {
  position: absolute;
  z-index: 3;
  bottom: 10px;
  left: 50%;
  height: 1.75em;
  margin: 0 0 0 -9.125em;
  line-height: 1.75em;
  padding: 0.625em;
  display: none;
  background: #ccc;
  overflow: hidden;
}
.borderradius .deck-container .goto-form {
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
}
.deck-container .goto-form label {
  font-weight: bold;
}
.deck-container .goto-form label, .deck-container .goto-form input {
  display: inline-block;
  font-family: inherit;
}

.deck-goto .goto-form {
  display: block;
}

#goto-slide {
  width: 8.375em;
  margin: 0 0.625em;
  height: 1.4375em;
}

.deck-container .deck-permalink {
  display: none;
  position: absolute;
  z-index: 4;
  bottom: 30px;
  right: 0;
  width: 48px;
  text-align: center;
}

.no-history .deck-container:hover .deck-permalink {
  display: block;
}

.deck-menu .slide {
  background: #eee;
  position: relative;
  left: 0;
  top: 0;
  visibility: visible;
  cursor: pointer;
}
.no-csstransforms .deck-menu > .slide {
  float: left;
  width: 22%;
  height: 22%;
  min-height: 0;
  margin: 1%;
  font-size: 0.22em;
  overflow: hidden;
  padding: 0 0.5%;
}

.deck-menu iframe, .deck-menu img, .deck-menu video {
  max-width: 100%;
}
.deck-menu .deck-current, .no-touch .deck-menu .slide:hover {
  background: #ddf;
}
.deck-menu.deck-container:hover .deck-prev-link, .deck-menu.deck-container:hover .deck-next-link {
  display: none;
}

.deck-container .deck-prev-link, .deck-container .deck-next-link {
  display: none;
  position: absolute;
  z-index: 3;
  top: 50%;
  width: 32px;
  height: 32px;
  margin-top: -16px;
  font-size: 20px;
  font-weight: bold;
  line-height: 32px;
  vertical-align: middle;
  text-align: center;
  text-decoration: none;
  color: #fff;
  background: #888;
}
.borderradius .deck-container .deck-prev-link, .borderradius .deck-container .deck-next-link {
  -webkit-border-radius: 16px;
  -moz-border-radius: 16px;
  border-radius: 16px;
}
.deck-container .deck-prev-link:hover, .deck-container .deck-prev-link:focus, .deck-container .deck-prev-link:active, .deck-container .deck-prev-link:visited, .deck-container .deck-next-link:hover, .deck-container .deck-next-link:focus, .deck-container .deck-next-link:active, .deck-container .deck-next-link:visited {
  color: #fff;
}
.deck-container .deck-prev-link {
  left: 8px;
}
.deck-container .deck-next-link {
  right: 8px;
}
.deck-container:hover .deck-prev-link, .deck-container:hover .deck-next-link {
  display: block;
}
.deck-container:hover .deck-prev-link.deck-nav-disabled, .touch .deck-container:hover .deck-prev-link, .deck-container:hover .deck-next-link.deck-nav-disabled, .touch .deck-container:hover .deck-next-link {
  display: none;
}

.deck-container .deck-status {
  position: absolute;
  bottom: 10px;
  right: 5px;
  color: #888;
  z-index: 3;
  margin: 0;
}

body.deck-container .deck-status {
  position: fixed;
}
`


<|start_filename|>common/tree/tree.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tree

import (
	"fmt"
)

func Empty() *Tree {
	return &Tree{}
}

func New(rootName string, rootValue interface{}) *Tree {
	return &Tree{
		root: newNode(nil, rootName, rootValue),
	}
}

type Tree struct {
	root *Node
}

func (tree *Tree) String() string {
	if tree.Root() == nil {
		return "<empty-tree>"
	}

	return tree.Root().String()
}

func (tree *Tree) Root() *Node {
	return tree.root
}

func (tree *Tree) Insert(path Path, value interface{}) (bool, error) {

	// validate path
	if isValidPath, pathValidationErr := path.IsValid(); !isValidPath {
		return false, pathValidationErr
	}

	// check if the path already exists
	if existingNode := tree.GetNode(path); existingNode != nil {
		existingNode.SetValue(value)
		return true, nil
	}

	if path.IsEmpty() {
		tree.root = newRootNode("", value)
		return true, nil
	}

	// convert components to node
	node := pathToNode(path, value)
	if node == nil {
		return false, fmt.Errorf("Could not convert the path %s into a node.", path)
	}

	// make the new node the root
	if tree.Root() == nil {
		tree.root = node
		return true, nil
	}

	// insert the node
	return tree.Root().Insert(node)
}

func (tree *Tree) Delete(path Path) (bool, error) {

	// validate path
	if isValidPath, pathValidationErr := path.IsValid(); !isValidPath {
		return false, pathValidationErr
	}

	if tree.Root() == nil {
		return false, fmt.Errorf("Cannot remove the path %s from this tree because the tree is empty.", path)
	}

	// delete the node
	return tree.Root().Delete(path)
}

// Get the node that matches the supplied path.
func (tree *Tree) GetNode(path Path) *Node {

	// validate path
	if isValidPath, _ := path.IsValid(); !isValidPath {
		return nil
	}

	// return nil if there is no root
	if tree.Root() == nil {
		return nil
	}

	// return the root if the path is a root path or empty
	if path.IsRootPath() || path.IsEmpty() {
		return tree.Root()
	}

	// skip the root node itself and go for its children
	for _, child := range tree.Root().Children() {
		if matchingNode := child.GetNode(path); matchingNode != nil {
			return matchingNode
		}
	}

	// no match
	return nil
}

// Walk visits every node in the current tree. Starting with the root, every child of the root and then recurses down the children.
func (tree *Tree) Walk(expression func(node *Node)) {
	if tree.Root() == nil {
		return
	}

	expression(tree.Root())

	tree.Root().Walk(expression)
}


<|start_filename|>common/config/constants_windows.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package config

const (
	DefaultConversionToolPath = "pandoc.exe"
)


<|start_filename|>web/view/themes/themefiles/favicon.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const FaviconIco = `AAABAAQAEBAAAAEAIABoBAAARgAAACAgAAABACAAqBAAAK4EAAAwMAAAAQAgAKglAABWFQAAQEAA
AAEAIAAoQgAA/joAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAACMuAAAjLgAAAAAAAAAAAADf39//
v7+//7+/v/+/v7//v7+//8zMzO////8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAgICA/wAAAP8AAAD/AAAA/wAAAO8AAAAwAAAAAAAAAAD///9AAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAICAgP8AAAD/AAAA/wAAAO8AAAAwAAAAAP///yDExMTPUFBQ/////3AAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAACAgID/AAAA/wAAAO8AAAAwAAAAAP///zCIiIjvAAAA/0BAQP////9g
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICA/wAAAO8AAAAwAAAAAP///yD///+/AAAA/wAAAP8w
MDD/5ubmnwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIiIiO8AAAAwAAAAAP///2BwcHD/AAAA/wAA
AP8AAAD/AAAA/zAwMP/m5uafAAAAAAAAAAAAAAAAAAAAAAAAAAD///9AAAAAAP///zBwcHD/AAAA
/zAwMP+qqqq/mZmZ7wAAAP8AAAD/MDAw/+bm5p8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+A
AAAA/wAAAP+ZmZnv////EP///4BQUFD/AAAA/wAAAP8wMDD/5ubmnwAAAAAAAAAAAAAAAAAAAAAA
AAAA////YCAgIP8AAAD/EBAQ/4CAgP9AQED/AAAA/2BgYP8AAAD/AAAA/2BgYP////9AAAAAAAAA
AAAAAAAAAAAAAP///xCkpKTfEBAQ/wAAAP8AAAD/ICAg/7Gxsc////9giIiI7wAAAP8AAAD/////
gAAAAAD///8gAAAAAAAAAAAAAAAA////EMzMzJ+qqqq/qqqqv////6////9AAAAAANHR0a8AAAD/
ICAg/////2AAAAAwiIiI7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///1BAQED/UFBQ/8TExM8w
MDD/AAAA/7Gxsc8AAAAwAAAA74CAgP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8gmZmZ7wAA
AP8AAAD/EBAQ/52dnc9mZmZQAAAA7wAAAP+AgID/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AP///zCZmZnvYGBg/+bm5p9AQEBAAAAA7wAAAP8AAAD/gICA/wAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA////IP///yAAAAAwAAAA7wAAAP8AAAD/AAAA/4CAgP8AAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8giIiI74CAgP+AgID/gICA/4CAgP+/v7//Af9JbgN/
bDYEP0ZhCD9seRA/IE0gH2VsQA8yIMAHZXDAA25nwAIsIOBAbnX8AGVJ/ABlbP4AUk//AFNT/4Bf
TCgAAAAgAAAAQAAAAAEAIAAAAAAAgBAAACMuAAAjLgAAAAAAAAAAAAD/////////////////////
//////////////////////////////////////////////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
//9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP9AQED/ZmZmn////yAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA/////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAJ8A
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAD///8Q////cP///2AAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAAnwAAAAAAAAAAAAAAAAAAAAAAAAAA////MP///9+fn5//z8/P////
/48AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAJ8AAAAAAAAAAAAAAAAAAAAAAAAAAP///3Dv7+//
UFBQ/wAAAP8QEBD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAD/////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAP//
/xD///+vz8/P/yAgIP8AAAD/AAAA/0BAQP/////fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAD/AAAA/wAAAP8AAAD/AAAAnwAAAAAAAAAA
AAAAAAAAAAAAAAAA////z5+fn/8AAAD/AAAA/wAAAP8AAAD/z8/P/////2AAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAP8AAAD/AAAA/wAA
AJ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAA/wAAAP8AAAD/AAAA/xAQEP/Pz8//////
nwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////
AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAP///xD///+A////39/f3/9AQED/AAAA/wAAAP8A
AAD/AAAA/xAQEP/Pz8//////nwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP////8AAAD/AAAAnwAAAAAAAAAAAAAAAAAAAAD///8w////35+fn/8wMDD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/xAQEP/Pz8//////nwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAJ8AAAAAAAAAAAAAAAAAAAAA////UO/v7/9A
QED/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/xAQEP/Pz8//////nwAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+/AAAAAAAAAAAAAAAAAAAA
AP///yD////vMDAw/wAAAP8AAAD/AAAA/wAAAP9gYGD/39/f/8/Pz/8QEBD/AAAA/wAAAP8AAAD/
AAAA/xAQEP/Pz8//////nwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA////n4CAgP8AAAD/AAAA/wAAAP8AAAD/v7+//////7////9A////n8/P
z/8QEBD/AAAA/wAAAP8AAAD/AAAA/xAQEP/Pz8//////nwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////fICAg/wAAAP8AAAD/AAAA/2BgYP////+/
AAAAAAAAAAAAAAAA////n8/Pz/8QEBD/AAAA/wAAAP8AAAD/AAAA/xAQEP/Pz8//////nwAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAD/AAAA/wAA
AP8AAAD/MDAw/////+////8wAAAAAP///1D////fn5+f/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/xAQEP/Pz8//////cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
////3yAgIP8AAAD/AAAA/wAAAP8AAAD/YGBg/+/v7//////fv7+//0BAQP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/xAQEP/v7+//////QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD///+fgICA/wAAAP8AAAD/AAAA/wAAAP8AAAD/EBAQ/zAwMP8AAAD/AAAA
/wAAAP8QEBD/n5+f/8/Pz/8QEBD/AAAA/wAAAP8AAAD/AAAA/2BgYP////+vAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yDv7+//ICAg/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/MDAw/8/Pz/////+f////n8/Pz/8QEBD/AAAA/wAAAP8AAAD/EBAQ////
/+8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///2Df39//MDAw
/wAAAP8AAAD/AAAA/wAAAP8AAAD/EBAQ/4+Pj//////v////UAAAAAAAAAAA////n4+Pj/8AAAD/
AAAA/wAAAP8AAAD//////wAAAAAAAAAAAAAAAAAAAAD///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAP///1D////vn5+f/3BwcP9AQED/gICA/6+vr///////////n////xAAAAAAAAAAAAAA
AAD///8g/////wAAAP8AAAD/AAAA/zAwMP/////PAAAAAAAAAAAAAAAAAAAAn/////8AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///xD///9g////j////7////+A////YP///3D////v
////v////zAAAAAAAAAAAP///5+fn5//AAAA/wAAAP8AAAD/n5+f/////4AAAAAAAAAAAAAAAJ8A
AAD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD///9g7+/v/zAwMP9gYGD/7+/v/////4D///+vz8/P/xAQEP8AAAD/AAAA/zAwMP/////v////
EAAAAAAAAACfAAAA/wAAAP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP///79QUFD/AAAA/wAAAP8QEBD/n5+f/4CAgP8AAAD/AAAA/wAAAP8Q
EBD/7+/v/////1AAAAAAAAAAnwAAAP8AAAD/AAAA//////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////j5+fn/8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/MDAw/9/f3/////9gAAAAAAAAAJ8AAAD/AAAA/wAAAP8AAAD//////wAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////n5+fn/8A
AAD/AAAA/wAAAP8AAAD/AAAA/1BQUP/v7+//////YAAAAAAAAACfAAAA/wAAAP8AAAD/AAAA/wAA
AP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA////n5+fn/8AAAD/AAAA/yAgIP+vr6//////z////zAAAAAAAAAAnwAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA//////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////n7+/v/+fn5//////7////4AAAAAAAAAAAAAA
AJ8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////cP///3D///8Q
AAAAAAAAAAAAAACfAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP//////AAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
//////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+A////////////////////
////////////////////////////////////////////AAf//wAH//8AH///AD4//wB8H/8A+B//
AeAf/wPgH/8H4B//DwAP/x4AB/88AAP/eAAB//gAAP/4DgB/+AQAP/gAAB/4AAAf+AAAH/wAMB7+
AHAc/wAwGP/4ABD/+AAg//gAQP/8AID//gEA//8GAP//jAD///gA///wAP//4AAoAAAAMAAAAGAA
AAABACAAAAAAAIAlAAAjLgAAIy4AAAAAAAAAAAAA////////////////////////////////////
////////////////////////////////////////////////////////////////vwAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////9/f
3/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+/
/7+/v//MzMzv////jwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA/////4CAgP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAO8AAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4CAgP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7wAAADAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
/////4CAgP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AADvAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4CAgP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAO8AAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
//8g////n////7////9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4CAgP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7wAAADAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP///2D////v7+/v/8/Pz///////////nwAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA/////4CAgP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADvAAAA
MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////j//////Pz8//EBAQ/wAAAP9gYGD/
/////////2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4CAgP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAO8AAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yD////P////
/4+Pj/8AAAD/AAAA/wAAAP8AAAD//////////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4CAgP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA7wAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA////QP///+/v7+//UFBQ/wAAAP8AAAD/AAAA/wAAAP9AQED//////////2AAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAA/////4CAgP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADvAAAAMAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+A/////8/Pz/8gICD/AAAA/wAAAP8AAAD/AAAA/wAA
AP/Pz8//////3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4CAgP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAO8AAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///2D/////n5+f/xAQEP8A
AAD/AAAA/wAAAP8AAAD/AAAA/2BgYP//////////YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
/4CAgP8AAAD/AAAA/wAAAP8AAAD/AAAA7wAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAP///6/v7+//AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/4+Pj///////////YAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/////4CAgP8AAAD/AAAA/wAAAP8AAADvAAAAMAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA////MP///7//////MDAw/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP+fn5///////////2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4CAgP8AAAD/AAAA/wAA
AO8AAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///1D////P///////////Pz8//cHBw
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/n5+f//////////9gAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAA/////4CAgP8AAAD/AAAA7wAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8Q////v///
///f39//YGBg/xAQEP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/5+fn///////////YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4CAgP8AAADvAAAAMAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAP///zD////v7+/v/3BwcP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP+fn5///////////2AAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4iIiO8AAAAw
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////MP///+/f39//MDAw/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/n5+f////
//////9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA/////////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8Q////z+/v7/8gICD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/EBAQ/4CAgP/f39//z8/P/xAQEP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/5+fn///////////YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAD///+A/////0BAQP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP9gYGD/7+/v//////////+v
////78/Pz/8QEBD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP+fn5///////////2AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////vn5+f/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/2BgYP//////////v////yAAAAAA////MP///+/Pz8//EBAQ/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/n5+f//////////9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///0D/////UFBQ/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/+/v7/////+/AAAAAAAAAAAAAAAAAAAAAP///zD////vz8/P
/xAQEP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/5+fn///////////YAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAP///3D/////EBAQ/wAAAP8AAAD/AAAA/wAAAP8AAAD/ICAg//////////+AAAAAAAAA
AAAAAAAAAAAAAAAAAAD///+f/////5+fn/8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP+fn5///////////2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4D/////AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/6+vr///////////YAAAAAAAAAAA////YP///9//////n5+f/xAQEP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/n5+f//////////9gAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///1D/////
MDAw/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/xAQEP/Pz8///////////8/////f/////9/f3/9Q
UFD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/6+v
r///////////IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAP///yD/////YGBg/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
cHBw/7+/v/+vr6//YGBg/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/4CAgP8QEBD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/xAQEP/v7+//////rwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////Pz8/P/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8gICD/
z8/P///////Pz8//EBAQ/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP+AgID//////////xAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD///9g/////3BwcP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/1BQUP/v7+//////7////4D////vz8/P/xAQEP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP9AQED//////////0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////v/////9AQED/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8QEBD/r6+v///////////P////IAAAAAD///8w////
78/Pz/8QEBD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD//////////4AAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////EP///8//
////cHBw/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/EBAQ/4CAgP/v7+//////////
/4AAAAAAAAAAAAAAAAAAAAAA////QP////+Pj4//AAAA/wAAAP8AAAD/AAAA/wAAAP8QEBD/////
/////4AAAAAAAAAAAAAAAAAAAAAAAAAAAP///2D///+/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP///xD///+v/////9/f3/9wcHD/MDAw/wAAAP8AAAD/ICAg/1BQUP+f
n5//7+/v//////////+/////IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///5/v7+//AAAA/wAA
AP8AAAD/AAAA/wAAAP9AQED//////////0AAAAAAAAAAAAAAAAAAAAAAAAAAMIiIiO//////AAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////UP///8//////
///////////////////////////////v////n////1D///9w////UAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAP///7/f39//AAAA/wAAAP8AAAD/AAAA/wAAAP+Pj4///////////xAAAAAAAAAAAAAA
AAAAAAAwAAAA74CAgP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAD///8g////YP///4D///+A////YP///0AAAAAA////YP//////////
/////////7////8gAAAAAAAAAAAAAAAA////n/////9QUFD/AAAA/wAAAP8AAAD/AAAA/xAQEP/v
7+//////nwAAAAAAAAAAAAAAAAAAADAAAADvAAAA/4CAgP//////AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAD///9g/////8/Pz/8QEBD/cHBw/+/v7//////v////cP///xD///+v/////4+Pj/8AAAD/
AAAA/wAAAP8AAAD/AAAA/5+fn///////////IAAAAAAAAAAAAAAAMAAAAO8AAAD/AAAA/4CAgP//
////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///xD////vz8/P/xAQEP8AAAD/AAAA/yAgIP+/v7//////
////////////YGBg/wAAAP8AAAD/AAAA/wAAAP8AAAD/YGBg//////////+AAAAAAAAAAAAAAAAw
AAAA7wAAAP8AAAD/AAAA/4CAgP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///0D/////QEBA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/cHBw/5+fn/8gICD/AAAA/wAAAP8AAAD/AAAA/wAAAP9gYGD/////
/////78AAAAAAAAAAAAAADAAAADvAAAA/wAAAP8AAAD/AAAA/4CAgP//////AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAP///xD////vz8/P/xAQEP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/2BgYP//////////z////xAAAAAAAAAAMAAAAO8AAAD/AAAA/wAAAP8AAAD/AAAA
/4CAgP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9g/////8/Pz/8QEBD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/cHBw///////////P////EAAAAAAAAAAwAAAA7wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/4CAgP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
////YP/////Pz8//EBAQ/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/xAQEP+vr6///////////5//
//8QAAAAAAAAADAAAADvAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/4CAgP//////AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///2D/////z8/P/xAQEP8AAAD/AAAA/wAAAP8AAAD/
cHBw/+/v7//////v////cAAAAAAAAAAAAAAAMAAAAO8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/4CAgP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9g////
/8/Pz/8QEBD/AAAA/0BAQP/Pz8///////////7////8gAAAAAAAAAAAAAAAwAAAA7wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/4CAgP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA////YP/////v7+//39/f///////////f////UAAAAAAAAAAAAAAA
AAAAADAAAADvAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/4CAgP//////
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///0D///+v////r///
/2AAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAO8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/4CAgP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAA7wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/4CAgP//////AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAA
AADvAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/4CA
gP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAMAAAAO8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/4CAgP//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9giIiI74CAgP+AgID/gICA/4CAgP+AgID/
gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/4CAgP+AgID/gICA/7+/v///////AAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+/////
////////////////////////////////////////////////////////////////////////////
////////////////AAAf////AAAAAB////8AAAAAP////wAAAAB/////AAAAAP////8AAAAB/h//
/wAAAAP8D///AAAAB/gH//8AAAAP4Af//wAAAB/AB///AAAAP4AP//8AAAB/AA///wAAAP8AD///
AAAB/gAH//8AAAP4AAP//wAAB+AAAf//AAAPwAAA//8AAB+AAAB//wAAPwAAAD//AAD/AAAAH/8A
AP8ACAAP/wAA/gA8AAf/AAD+AD4AA/8AAP4AGAAB/wAA/gAAAAD/AAD+AAAAAP8AAP8AAAAAfwAA
/wAAAAB/AAD/gAAIAH8AAP+AADwAfAAA/8AAfgB4AAD/8AB+AHAAAP/8CBwA4AAA///wAADAAAD/
/+AAAYAAAP//4AADAAAA///gAAIAAAD///AABAAAAP//+AAIAAAA///8ADAAAAD///4AYAAAAP//
/wHAAAAA////h4AAAAD/////AAAAAP////4AAAAA/////AAAAAD////4AAAAAP////gAAAAAKAAA
AEAAAACAAAAAAQAgAAAAAAAAQgAAIy4AACMuAAAAAAAAAAAAAP//////////////////////////
////////////////////////////////////////////////////////////////////////////
//////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAD/////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////9AQED/QEBA/0BAQP9A
QED/QEBA/0BAQP9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP9AQED/QEBA/0BA
QP9AQED/QEBA/0BAQP9mZmaf////QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAP//////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA//////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACf
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAD//////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA////QP///8//////////3////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////gP//////////////////
////////////nwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAP//////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD///8Q////r///////////gICA/xAQEP9AQED/7+/v//////////+PAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8w////3//////v7+//QEBA/wAAAP8AAAD/AAAA
/zAwMP//////////7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAA//////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9w////
///////Pz8//ICAg/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////8AAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAP///xD///+f//////////+Pj4//AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
QEBA///////////fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD//////////wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///zD////P/////+/v7/9QUFD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/8/Pz///////////gAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAP///0D////v/////8/Pz/8wMDD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/2BgYP//
////////3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AP//////////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////f/////5+fn/8QEBD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/xAQEP/f39///////////2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
//8w/////9/f3/8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP9AQED/////////
//////9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
//////////8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////IP/////v7+//EBAQ/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/2BgYP///////////////2AAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8g////j///
/9///////////5+fn/8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/YGBg
////////////////YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
/////////wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP///yD///+f////////////////7+/v/7+/v/+AgID/EBAQ/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP9gYGD///////////////9gAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8AAAD/AAAA/wAAAP8AAACfAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4D///////////////+fn5//UFBQ
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/2BgYP///////////////2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
////////AAAA/wAAAP8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
EP///8///////////4+Pj/8QEBD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/YGBg////////////////YAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wAAAP8AAACfAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA////EP///8//////39/f/0BAQP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP9gYGD///////////////9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
//////8AAACfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////EP///8//////
z8/P/xAQEP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/xAQEP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/2BgYP//////////////
/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP///6//////z8/P/xAQEP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8gICD/j4+P/9/f3//v7+//MDAw/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/YGBg////////////////YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9A
////QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///2D/////7+/v/yAgIP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/xAQEP+fn5///////////////////////+/v
7/8wMDD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP9gYGD/////
//////////9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAD////f/////2BgYP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/zAw
MP/v7+////////////////+f////MP///5//////7+/v/zAwMP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/2BgYP///////////////2AAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9Q/////9/f3/8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/xAQEP/v7+///////////7////8gAAAAAAAAAAAAAAAA////
n//////v7+//MDAw/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
YGBg////////////////YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA////n/////9wcHD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP+fn5//////
/////78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+f/////+/v7/8wMDD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP9gYGD///////////////9gAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///7//////QEBA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/z8/P//////////8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAP///6//////7+/v/zAwMP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/2BgYP///////////////2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAD//////////xAQEP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/6+vr///////
////nwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///3D////v/////8/Pz/8gICD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/YGBg////////////////YAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8QEBD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8wMDD///////////////+PAAAAAAAAAAAAAAAA////YP///9//
/////////5+fn/8QEBD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP9gYGD///////////////9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAP///7//////QEBA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/2BgYP//
/////////////9////+f////3///////////39/f/1BQUP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/3BwcP//////////
7////yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+f/////3BwcP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/QEBA/9/f3//////////////////f39//YGBg/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/ICAg/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/r6+v//////////+fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAA////YP////+/v7//AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/QEBA/3BwcP9AQED/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8QEBD/r6+v
/+/v7/8wMDD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/yAgIP//////
/////////yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///xD////v/////zAwMP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8wMDD/39/f////////////7+/v/zAwMP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/n5+f//////////9wAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA////gP////+/v7//AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP+AgID////////////////P
////n//////v7+//MDAw/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/1BQUP//
////////vwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///xD////v/////5+fn/8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/yAgIP+/v7////////////////+PAAAAAAAAAAD///+f/////+/v7/8wMDD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8wMDD//////////88AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA////QP//////////n5+f/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/4CAgP/v7+///////////9////9AAAAAAAAAAAAA
AAAAAAAAAP///5//////39/f/xAQEP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA////
////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///9g//////////+/v7//
ICAg/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/YGBg/9/f3///
/////////////6////8QAAAAAAAAAAAAAAAAAAAAAAAAAAD///8Q////z/////+AgID/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/zAwMP//////////3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP///0D////v/////+/v7/+Pj4//MDAw/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/0BAQP+Pj4//7+/v////////////////3////0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP///0D/////39/f/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP9QUFD/////
/////78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn///////////AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////EP///5//
///////////////v7+//v7+//7+/v/+/v7//z8/P///////////////////////////P////YAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8g/////+/v7/8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/j4+P//////////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAnwAAAP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////IP///4/////f////////////////////////
////////////z////4////8w////MP///6/////v////v////1AAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA////r/////+fn5//AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/EBAQ/+/v7///////
////MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD///////////8AAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAP///yD///9A////QP///0D///9AAAAAAAAAAAAAAAAA////MP///+//////////
////////////////r////xAAAAAAAAAAAAAAAAAAAAAA////n//////v7+//ICAg/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/4CAgP//////////vwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8A
AAD/AAAA////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA////MP///+//////n5+f/zAwMP9wcHD/7+/v///////////v////UAAAAAD///8Q
////r//////v7+//MDAw/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/yAgIP/v7+///////////0AA
AAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP///////////wAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////IP///+//////n5+f/wAAAP8AAAD/
AAAA/yAgIP+/v7////////////////+v////7//////v7+//MDAw/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP+/v7///////////68AAAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAA
AP8AAAD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAP///4D/////r6+v/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/3BwcP/v7+////////////+/
v7//ICAg/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP+fn5///////////+////8QAAAAAAAA
AAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA////////////AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+A/////4CAgP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/ICAg/5+fn/9AQED/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP+fn5///////////+////8wAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAA////YP/////Pz8//EBAQ/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP+fn5////////////////9gAAAAAAAAAAAAAAAAAAAA
nwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////8AAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////P/////8/Pz/8QEBD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/xAQEP+fn5//////
//////////9gAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA////EP///8//////z8/P/xAQEP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/yAgIP/Pz8///////////+////9AAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP///////////wAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8Q////z//////Pz8//EBAQ
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/3BwcP/v7+///////////8////8w
AAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAP///xD////P/////8/Pz/8QEBD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
ICAg/7+/v////////////////6////8QAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA////////////AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////EP///8//////
z8/P/xAQEP8AAAD/AAAA/wAAAP8QEBD/gICA////////////////7////1AAAAAAAAAAAAAAAAAA
AAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAD///8Q////z//////Pz8//ICAg/xAQEP+AgID/7+/v////////
////////n////xAAAAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////8AAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///xD/
///P//////////////////////////////+/////MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnwAA
AP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////EP///5/////v/////////6////9AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA
/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/
AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP//
/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA////
////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////
////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAP//////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//////8AAAB//////wAAAH//////AAAAf/////8AAAH//////wAAA///////AAAH//////8AAA//
/////wAAH/4P////AAA//Af///8AAH/wA////wAA/+AD////AAH/wAP///8AA/8AA////wAH/gAD
////AA/8AAf///8AH/wAB////wA/+AAH////AH/4AAP///8A/+AAAf///wH/gAAA////A/8AAAB/
//8H/AAAAD///w/4AAAAH///H/AAAAAP//8/8AAAAAf//z/gAAAAA////+AAAAAB////wAA4AAD/
///AAPwAAH///8AA/gAAP///wAD8AAAf///AAHAAAA///8AAAAAAB///wAAAAAAH///AAAAAAAP/
/8AAAAAAA///4AAAAAAD///gAAAGAAP///AAAA8AA///+AAAHwAD/P/8AAB/gAP4//4AAf+AA/D/
/4AAP4AD4P//8HAPAAfA////4AQAB4D////AAAAPAP///8AAAA4A////wAAAHAD////AAAA4AP//
/+AAAHAA////4AAA4AD////wAAHAAP////gAA4AA/////AAPAAD////+AB4AAP////8AfAAA////
/4H4AAD///////AAAP//////4AAA///////AAAD//////4AAAP//////AAAA//////4AAAD/////
/gAAAA==`


<|start_filename|>web/view/viewmodel/feed.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type Feed struct {
	FeedEntry
	Items []FeedEntry
}

type FeedEntry struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	Link        string `json:"link"`
	PubDate     string `json:"pubDate"`
}


<|start_filename|>common/util/dateutil/date_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package dateutil

import (
	"testing"
	"time"
)

func Test_ParseIso8601Date_ValidIso8601Date_CorrectResultIsReturned(t *testing.T) {

	// Arrange
	var fallback time.Time
	dateString := "2013-07-26"
	expectedResult, err := time.Parse("2006-Jan-02", "2013-Jul-26")
	if err != nil {
		panic(err)
	}

	// Act
	result, err := ParseIso8601Date(dateString, fallback)

	// Assert
	if err != nil {
		t.Fail()
		t.Logf("Parsing the value '%v' returned an error even though no error was expected.", dateString)
	}

	if !result.Equal(expectedResult) {
		t.Fail()
		t.Logf("Parsing the value %q did not return the expected result %q.", result, expectedResult)
	}

}

func Test_ParseIso8601Date_ValidIso8601Dates_NoErrorIsReturned(t *testing.T) {

	// Arrange
	var fallback time.Time

	dateStrings := []string{
		"2013-02-08",
		"2013-01-01",
		"2013-12-31",
		"0001-01-01",
		"0001-12-31",
		"9999-01-01",
		"9999-12-31",
	}

	// Act
	for _, dateString := range dateStrings {
		_, err := ParseIso8601Date(dateString, fallback)

		// Assert
		if err != nil {
			t.Fail()
			t.Logf("Parsing the value '%v' returned an error even though no error was expected.", dateString)
		}

	}
}

func Test_ParseIso8601Date_ValidIso8601Date_WithValidTime_NoErrorIsReturned(t *testing.T) {

	// Arrange
	var fallback time.Time
	dateString := "2013-02-08 21:13"

	// Act
	_, err := ParseIso8601Date(dateString, fallback)

	// Assert
	if err != nil {
		t.Fail()
		t.Logf("Parsing the value '%v' returned an error even though no error was expected.", dateString)
	}
}

func Test_ParseIso8601Date_InvalidIso8601Dates_ErrorIsReturned(t *testing.T) {

	// Arrange
	var fallback time.Time
	dateStrings := []string{
		"99-02-08",
		"1-1-1",
		"2013-1-1",
		"2013-01-1",
		"2013-1-01",
		"13-01-01",
		"83-12-31",
		"21400-12-31",
	}

	// Act
	for _, dateString := range dateStrings {
		_, err := ParseIso8601Date(dateString, fallback)

		// Assert
		if err == nil {
			t.Fail()
			t.Logf("Parsing the value '%v' returned should return an error because it is not a valid date.", dateString)
		}

	}
}


<|start_filename|>services/parser/cleanup/headlines.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cleanup

import (
	"regexp"
)

var (
	// markdown headline which start with the headline text righ after the hash
	markdownHeadlineStartWhitespace = regexp.MustCompile(`^(#+)([^\s#])`)

	// match headlines which have a hash at the end
	markdownHeadlineClosingHeadline = regexp.MustCompile(`^(#+)\s*(.+?)\s*(#+)$`)
)

func cleanupHeadlines(lines []string) []string {
	for index, line := range lines {

		fixedLine := line

		// headline start
		fixedLine = markdownHeadlineStartWhitespace.ReplaceAllString(fixedLine, "$1 $2")

		// remove closing headline hashes
		fixedLine = markdownHeadlineClosingHeadline.ReplaceAllString(fixedLine, "$1 $2")

		// same the fixed line
		if fixedLine != line {
			lines[index] = fixedLine
		}
	}

	return lines
}


<|start_filename|>web/view/themes/themefiles/printcss.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const PrintCss = `
* {
    background: #FFFFFF !important;
    color: black !important;
    filter: none !important;
    -ms-filter: none !important;
}

body {
    font: normal 18px/30px "Georgia Pro",georgia,serif;
    text-rendering: optimizeLegibility;
    cursor: default;
    max-width: 100%;
    width: 100%
    outline: none;
}

a, a:visited {
    font-weight: normal;
    text-decoration: none;
}

hr {
    height: 1px;
    border: 0;
    border-bottom: 1px solid black;
}

a[href]:after {
    content: " <" attr(href) ">";
}

a[text^="http"]:after {
    content: "";
}

abbr[title]:after {
    content: " <" attr(title) ">";
}

.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after {
    content: "";
}

pre, blockquote {
    border: 1px solid #999;
    padding: 1em;
    page-break-inside: avoid;
    white-space: pre-wrap;
}

ol, ul, tr, img {
    page-break-inside: avoid;
}

img {
    max-width: 95% !important;
}

p, h2, h3 {
    orphans: 3;
    widows: 3;
}

h2, h3, h4, h5, h6 {
    font-family: "Franklin ITC Pro Bold",sans-serif !important;
    page-break-after: avoid;
}

a.deeplink {
    display: none;
}

body>nav.toplevel {
    display: none;
}

body>nav.search {
    display: none;
}

body>nav.breadcrumb {
    display: none;
}

body>aside {
    display: none;
}

aside.sidebar {
    display: none;
}

body>footer {
    display: none;
}

.ribbon {
  display: none;
}

.allmark-promo {
  display: none;
}

.video video {
    display: none;
}

.video iframe {
    display: none;
}

.audio audio {
    display: none;
}

.presentation nav {
    display: none;
}`


<|start_filename|>common/util/hashutil/hash.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package hashutil

import (
	"fmt"
	"hash/crc32"
	"io"
	"io/ioutil"
)

func FromString(text string) string {
	return FromBytes([]byte(text))
}

func GetHash(reader io.Reader) (string, error) {

	bytes, err := ioutil.ReadAll(reader)
	if err != nil {
		return "", err
	}

	return FromBytes(bytes), nil
}

func FromBytes(bytes []byte) string {
	crc := crc32.ChecksumIEEE(bytes)
	return fmt.Sprintf(`%d-%08X`, len(bytes), crc)
}


<|start_filename|>vendor/github.com/spf13/afero/memmap.go<|end_filename|>
// Copyright © 2014 <NAME> <<EMAIL>>.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package afero

import (
	"errors"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

var mux = &sync.Mutex{}

type MemMapFs struct {
	data  map[string]File
	mutex *sync.RWMutex
}

func (m *MemMapFs) lock() {
	mx := m.getMutex()
	mx.Lock()
}
func (m *MemMapFs) unlock()  { m.getMutex().Unlock() }
func (m *MemMapFs) rlock()   { m.getMutex().RLock() }
func (m *MemMapFs) runlock() { m.getMutex().RUnlock() }

func (m *MemMapFs) getData() map[string]File {
	if m.data == nil {
		m.data = make(map[string]File)
	}
	return m.data
}

func (m *MemMapFs) getMutex() *sync.RWMutex {
	mux.Lock()
	if m.mutex == nil {
		m.mutex = &sync.RWMutex{}
	}
	mux.Unlock()
	return m.mutex
}

type MemDirMap map[string]File

func (m MemDirMap) Len() int      { return len(m) }
func (m MemDirMap) Add(f File)    { m[f.Name()] = f }
func (m MemDirMap) Remove(f File) { delete(m, f.Name()) }
func (m MemDirMap) Files() (files []File) {
	for _, f := range m {
		files = append(files, f)
	}
	return files
}

func (m MemDirMap) Names() (names []string) {
	for x := range m {
		names = append(names, x)
	}
	return names
}

func (MemMapFs) Name() string { return "MemMapFS" }

func (m *MemMapFs) Create(name string) (File, error) {
	m.lock()
	m.getData()[name] = MemFileCreate(name)
	m.unlock()
	m.registerDirs(m.getData()[name])
	return m.getData()[name], nil
}

func (m *MemMapFs) registerDirs(f File) {
	var x = f.Name()
	for x != "/" {
		f := m.registerWithParent(f)
		if f == nil {
			break
		}
		x = f.Name()
	}
}

func (m *MemMapFs) unRegisterWithParent(f File) File {
	parent := m.findParent(f)
	pmem := parent.(*InMemoryFile)
	pmem.memDir.Remove(f)
	return parent
}

func (m *MemMapFs) findParent(f File) File {
	dirs, _ := path.Split(f.Name())
	if len(dirs) > 1 {
		_, parent := path.Split(path.Clean(dirs))
		if len(parent) > 0 {
			pfile, err := m.Open(parent)
			if err != nil {
				return pfile
			}
		}
	}
	return nil
}

func (m *MemMapFs) registerWithParent(f File) File {
	if f == nil {
		return nil
	}
	parent := m.findParent(f)
	if parent != nil {
		pmem := parent.(*InMemoryFile)
		pmem.memDir.Add(f)
	} else {
		pdir := filepath.Dir(path.Clean(f.Name()))
		m.Mkdir(pdir, 0777)
	}
	return parent
}

func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
	m.rlock()
	_, ok := m.getData()[name]
	m.runlock()
	if ok {
		return ErrFileExists
	} else {
		m.lock()
		m.getData()[name] = &InMemoryFile{name: name, memDir: &MemDirMap{}, dir: true}
		m.unlock()
		m.registerDirs(m.getData()[name])
	}
	return nil
}

func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
	return m.Mkdir(path, 0777)
}

func (m *MemMapFs) Open(name string) (File, error) {
	m.rlock()
	f, ok := m.getData()[name]
	ff, ok := f.(*InMemoryFile)
	if ok {
		ff.Open()
	}
	m.runlock()

	if ok {
		return f, nil
	} else {
		return nil, ErrFileNotFound
	}
}

func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
	return m.Open(name)
}

func (m *MemMapFs) Remove(name string) error {
	m.rlock()
	defer m.runlock()

	if _, ok := m.getData()["name"]; ok {
		m.lock()
		delete(m.getData(), name)
		m.unlock()
	}
	return nil
}

func (m *MemMapFs) RemoveAll(path string) error {
	m.rlock()
	defer m.runlock()
	for p, _ := range m.getData() {
		if strings.HasPrefix(p, path) {
			m.runlock()
			m.lock()
			delete(m.getData(), p)
			m.unlock()
			m.rlock()
		}
	}
	return nil
}

func (m *MemMapFs) Rename(oldname, newname string) error {
	m.rlock()
	defer m.runlock()
	if _, ok := m.getData()[oldname]; ok {
		if _, ok := m.getData()[newname]; !ok {
			m.runlock()
			m.lock()
			m.getData()[newname] = m.getData()[oldname]
			delete(m.getData(), oldname)
			m.unlock()
			m.rlock()
		} else {
			return ErrDestinationExists
		}
	} else {
		return ErrFileNotFound
	}
	return nil
}

func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
	f, err := m.Open(name)
	if err != nil {
		return nil, err
	}
	return &InMemoryFileInfo{file: f.(*InMemoryFile)}, nil
}

func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
	f, ok := m.getData()[name]
	if !ok {
		return &os.PathError{"chmod", name, ErrFileNotFound}
	}

	ff, ok := f.(*InMemoryFile)
	if ok {
		m.lock()
		ff.mode = mode
		m.unlock()
	} else {
		return errors.New("Unable to Chmod Memory File")
	}
	return nil
}

func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
	f, ok := m.getData()[name]
	if !ok {
		return &os.PathError{"chtimes", name, ErrFileNotFound}
	}

	ff, ok := f.(*InMemoryFile)
	if ok {
		m.lock()
		ff.modtime = mtime
		m.unlock()
	} else {
		return errors.New("Unable to Chtime Memory File")
	}
	return nil
}

func (m *MemMapFs) List() {
	for _, x := range m.data {
		y, _ := x.Stat()
		fmt.Println(x.Name(), y.Size())
	}
}


<|start_filename|>vendor/github.com/arnoSCC/fulltext/indexer_test.go<|end_filename|>
package fulltext

import (
	"fmt"
	"github.com/spf13/afero"
	"io/ioutil"
	"os"
	"path/filepath"
	re "regexp"
	"testing"
)

func TestIndexer(t *testing.T) {
	fmt.Printf("TestIndexer\n")

	idx, err := NewIndexer()
	if err != nil {
		panic(err)
	}

	idx.AddDoc(IndexDoc{Id: []byte(`blah1`), StoreValue: []byte(`store this`), IndexValue: []byte(`test of the emergency broadcast system`)})
	idx.AddDoc(IndexDoc{Id: []byte(`blah2`), StoreValue: []byte(`store this stuff too, yeah store it`), IndexValue: []byte(`every good boy does fine`)})
	idx.AddDoc(IndexDoc{Id: []byte(`blah3`), StoreValue: []byte(`more storage here`), IndexValue: []byte(`a taco in the hand is worth two in the truck`)})

	var indexFs afero.Fs = &afero.MemMapFs{}

	f, err := indexFs.Create("idxout")
	if err != nil {
		panic(err)
	}
	err = idx.FinalizeAndWrite(f)
	if err != nil {
		panic(err)
	}
	f.Close()

	fmt.Printf("Wrote index file: %s\n", f.Name())

}

// A more extensive test - index the complete works of William Shakespeare
func NoTestTheBardIndexing(t *testing.T) {

	fmt.Println("TestTheBardIndexing")

	idx, err := NewIndexer()
	if err != nil {
		panic(err)
	}
	defer idx.Close()

	titlere := re.MustCompile("(?i)<title>([^<]+)</title>")

	n := 0

	filepath.Walk("testdata/shakespeare.mit.edu/", func(path string, f os.FileInfo, err error) error {
		if !f.IsDir() /*&& n < 5*/ {
			n++
			fmt.Printf("indexing: %s\n", path)
			b, err := ioutil.ReadFile(path)
			if err != nil {
				panic(err)
			}
			title := string(titlere.Find(b))
			body := HTMLStripTags(string(b))
			doc := IndexDoc{
				Id:         []byte(path),
				StoreValue: []byte(title),
				IndexValue: []byte(title + " " + title + " " + body),
			}
			idx.AddDoc(doc)
		}
		return nil
	})

	fmt.Println("Writing final index...")
	f, err := ioutil.TempFile("", "idxout")
	if err != nil {
		panic(err)
	}
	err = idx.FinalizeAndWrite(f)
	if err != nil {
		panic(err)
	}
	f.Close()

	fmt.Printf("Wrote index file: %s\n", f.Name())

}


<|start_filename|>web/view/viewmodel/file.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

import (
	"time"
)

type File struct {
	Parent string `json:"parent"`
	Path   string `json:"path"`
	Route  string `json:"route"`
	Name   string `json:"name"`

	Hash         string    `json:"hash"`
	LastModified time.Time `json:"lastModified"`
	MimeType     string    `json:"mimeType"`
}


<|start_filename|>services/parser/metadata/position_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package metadata

import (
	"testing"
)

func Test_GetMetaDataPosition_SingleLine(t *testing.T) {
	// arrange
	inputLines := []string{
		"# Headline",     // Line number: 0
		"Description",    // Line number: 1
		"",               // Line number: 2
		"yada yada",      // Line number: 3
		"",               // Line number: 4
		"---",            // Line number: 5
		"type: document", // Line number: 6
	}
	expectedResult := 5

	// act
	result, _ := GetMetaDataPosition(inputLines)

	// assert
	if result != expectedResult {
		t.Errorf("The location of the meta data should be %d but was %d.", expectedResult, result)
	}
}


<|start_filename|>services/parser/pattern/pattern_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pattern

import (
	"fmt"
	"testing"
)

func Test_IsEmpty_NotEmpty(t *testing.T) {
	// arrange
	input := " asdas "

	// act
	result := IsEmpty(input)

	// assert
	if result != false {
		t.Errorf("The result should be false. The supplied string %q is NOT empty.", input)
	}
}

func Test_IsEmpty_EmptyString(t *testing.T) {
	// arrange
	input := ""

	// act
	result := IsEmpty(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is empty.", input)
	}
}

func Test_IsEmpty_Süaces(t *testing.T) {
	// arrange
	input := "     "

	// act
	result := IsEmpty(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is empty.", input)
	}
}

func Test_IsEmpty_SpacesAndTabs(t *testing.T) {
	// arrange
	input := "     \t   \t "

	// act
	result := IsEmpty(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is empty.", input)
	}
}

func Test_IsEmpty_SpacesAndLineEndings(t *testing.T) {
	// arrange
	input := "     \t   \t \r\n \t   "

	// act
	result := IsEmpty(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is empty.", input)
	}
}

func Test_IsHorizontalRule_ThreeDashes(t *testing.T) {
	// arrange
	input := "---"

	// act
	result := IsHorizontalRule(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is a horizontal rule.", input)
	}
}

func Test_IsHorizontalRule_MultipleDashes(t *testing.T) {
	// arrange
	input := "--------"

	// act
	result := IsHorizontalRule(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is a horizontal rule.", input)
	}
}

func Test_IsHorizontalRule_ThreeDashesWithWhitespaceBehind(t *testing.T) {
	// arrange
	input := "--- "

	// act
	result := IsHorizontalRule(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is a horizontal rule.", input)
	}
}

func Test_IsHorizontalRule_ThreeDashesWithWhitespaceInFront(t *testing.T) {
	// arrange
	input := " ---"

	// act
	result := IsHorizontalRule(input)

	// assert
	if result != false {
		t.Errorf("The result should be false. The supplied string %q is NOT a horizontal rule.", input)
	}
}

func Test_IsHorizontalRule_TwoDashes(t *testing.T) {
	// arrange
	input := "--"

	// act
	result := IsHorizontalRule(input)

	// assert
	if result != false {
		t.Errorf("The result should be false. The supplied string %q is NOT a horizontal rule.", input)
	}
}

func Test_IsMetaDataDefinition_RandomText(t *testing.T) {
	// arrange
	input := "yada yada"

	// act
	result := IsMetaDataDefinition(input)

	// assert
	if result != false {
		t.Errorf("The result should be false. The supplied string %q is NOT a meta data defintion.", input)
	}
}

func Test_IsMetaDataDefinition_KeyOnly(t *testing.T) {
	// arrange
	input := "type:"

	// act
	result := IsMetaDataDefinition(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is a meta data defintion.", input)
	}
}

func Test_IsMetaDataDefinition_KeyFollowedByWhitespace(t *testing.T) {
	// arrange
	input := "type:  "

	// act
	result := IsMetaDataDefinition(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is a meta data defintion.", input)
	}
}

func Test_IsMetaDataDefinition_KeyValue(t *testing.T) {
	// arrange
	input := "type: document"

	// act
	result := IsMetaDataDefinition(input)

	// assert
	if result != true {
		t.Errorf("The result should be true. The supplied string %q is a meta data defintion.", input)
	}
}

func Test_GetMetaDataKey_KeyValue(t *testing.T) {
	// arrange
	key := "type"
	value := "document"
	input := fmt.Sprintf("%s: %s", key, value)

	// act
	result := GetMetaDataKey(input)

	// assert
	if result == "" {
		t.Errorf("The result should be %s but was %s.", key, result)
	}
}

func Test_GetMetaDataKey_KeyOnly(t *testing.T) {
	// arrange
	key := "type"
	input := fmt.Sprintf("%s:  ", key)

	// act
	result := GetMetaDataKey(input)

	// assert
	if result == "" {
		t.Errorf("The result should be %s but was %s.", key, result)
	}
}

func Test_GetMetaDataKey_NoLabel(t *testing.T) {
	// arrange
	input := "sadsa dasdasds"

	// act
	result := GetMetaDataKey(input)

	// assert
	if result != "" {
		t.Errorf("The result should be empty but was %s.", result)
	}
}

func Test_GetSingleLineMetaDataKeyAndValue_KeyValue(t *testing.T) {
	// arrange
	key := "type"
	value := "document"
	input := fmt.Sprintf("%s: %s", key, value)

	// act
	resultKey, resultValue := GetSingleLineMetaDataKeyAndValue(input)

	// assert
	if resultKey != key {
		t.Errorf("The result key should be %s but was %s.", key, resultKey)
	}

	if resultValue != value {
		t.Errorf("The result value should be %s but was %s.", key, resultValue)
	}
}

func Test_GetSingleLineMetaDataKeyAndValue_KeyMultipleValues(t *testing.T) {
	// arrange
	key := "tags"
	value := "tag1, tag2, tag3"
	input := fmt.Sprintf("%s: %s", key, value)

	// act
	resultKey, resultValue := GetSingleLineMetaDataKeyAndValue(input)

	// assert
	if resultKey != key {
		t.Errorf("The result key should be %s but was %s.", key, resultKey)
	}

	if resultValue != value {
		t.Errorf("The result value should be %s but was %s.", key, resultValue)
	}
}

func Test_GetSingleLineMetaDataKeyAndValue_NoKeyValue(t *testing.T) {
	// arrange
	input := "Yada Yada"

	// act
	resultKey, resultValue := GetSingleLineMetaDataKeyAndValue(input)

	// assert
	if resultKey != "" {
		t.Errorf("The result key should be empty but was %s.", resultKey)
	}

	if resultValue != "" {
		t.Errorf("The result value should be empty but was %s.", resultValue)
	}
}

func Test_IsMultiLineTagDefinition_True(t *testing.T) {
	// arrange
	expected := true
	input := `tags:
- tag1
- tag2
- tag3`

	// act
	result, _ := IsMultiLineTagDefinition(input)

	// assert
	if result != expected {
		t.Errorf("The text %q is a multi-line tag definition, but the result was %v (expected: %v).", input, result, expected)
	}
}

func Test_IsMultiLineTagDefinition_AllTagsAreReturned(t *testing.T) {
	// arrange
	expected := 3
	input := `tags:
- tag1
- tag2
- tag3`

	// act
	_, matches := IsMultiLineTagDefinition(input)

	// assert
	if len(matches) != expected {
		t.Errorf("The text %q should return %d matches but returned %d. Result: %#v", input, expected, len(matches), matches)
	}
}

func Test_IsDescription_TextContainsNoMarkdown_ResultIsTrue(t *testing.T) {
	// arrange
	input := "Yada Yada Some Text that does not contain markdown."
	expected := true

	// act
	result, _ := IsDescription(input)

	// assert
	if result != expected {
		t.Errorf("The text %q is not a description because it contains markdown but the IsDescription function returned %v (expected: %v).", input, result, expected)
	}
}

func Test_IsDescription_TextContainsMarkdown_ResultIsFalse(t *testing.T) {
	// arrange
	input := "Yada Yada Some Text that looks like a description but suddenly contains an ![image](files/image.png). And then some more text."
	expected := false

	// act
	result, _ := IsDescription(input)

	// assert
	if result != expected {
		t.Errorf("The text %q is not a description because it contains markdown but the IsDescription function returned %v (expected: %v).", input, result, expected)
	}
}


<|start_filename|>web/view/viewmodel/sitemap.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type Sitemap struct {
	Model
	Tree string
}

type SitemapEntry struct {
	Path        string         `json:"path"`
	Title       string         `json:"title"`
	Description string         `json:"description"`
	Children      []SitemapEntry `json:"children"`
}


<|start_filename|>web/view/viewmodel/itemnavigation.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type ItemNavigation struct {
	Parent   NavEntry `json:"parent"`
	Previous NavEntry `json:"previous"`
	Next     NavEntry `json:"next"`
}

// IsAvailable returns a flag indicating whether the item navigation model is initialized or not.
func (nav ItemNavigation) IsAvailable() bool {
	return nav.Parent.Path != "" || nav.Previous.Path != "" || nav.Next.Path != ""
}

type NavEntry struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	Path        string `json:"path"`
}


<|start_filename|>services/parser/cleanup/cleanup.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cleanup

func Cleanup(lines []string) []string {
	return cleanupHeadlines(lines)
}


<|start_filename|>web/webpaths/util.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package webpaths

import (
	"regexp"
)

var (
	// A pattern matching prococol prefixes (e.g. http://, https://, ftp://, bitcoin:, mailto: and any other)
	protocolPrefixPattern = regexp.MustCompile(`^\w+:`)
)

// IsAbsoluteURI checks if the given uri is absolute or not.
func IsAbsoluteURI(uri string) bool {
	uriHasProtocolPrefix := protocolPrefixPattern.MatchString(uri)
	return uriHasProtocolPrefix
}


<|start_filename|>web/view/themes/themefiles/latest.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const LatestJs = `
$(function() {

	/**
	 * Get the currently opened web route
	 * @return string The currently opened web route (e.g. "documents/Sample-Document")
	 */
	var getURL = function() {
	    var url = document.location.pathname;

	    // remove leading slash
	    var leadingSlash = /^\//;
	    url = url.replace(leadingSlash, "");

	    if (url === "") {
	    	return "/latest"
	    }

	    return "/" + url + ".latest";
	};

	var markup = '<li><h1><a href="${route}">${title}</a></h1><p><a href="${route}">${description}</a></p><section>{{html content}}</section></li>';

	$.template( "itemTemplate", markup );

	$.ajax({
		url: getURL(),
		success: function(items) {
			$.each(items, function(index, item) {
				$.tmpl( "itemTemplate", item).appendTo( "article>.preview>ul" );
			});
		},
		dataType: "json"
	});

});
`


<|start_filename|>common/tree/node_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tree

import (
	"strings"
	"testing"
)

func Test_newNode_ResultNotNil(t *testing.T) {
	// arrange
	var parent *Node
	name := ""

	// act
	result := newNode(parent, name, nil)

	// assert
	if result == nil {
		t.Errorf("The result of newNode should never be nil.")
	}
}

func Test_Node_String_SingleNode_ResultMarkdownListStyle(t *testing.T) {
	// arrange
	name := "<NAME>"
	node := newNode(nil, name, nil)

	// act
	result := node.String()

	// assert
	expected := "- " + name
	if result != expected {
		t.Errorf("The String method of the node should return %q but returned %q instead.", expected, result)
	}
}

func Test_Node_String_MultipleNodes_ResultIsIndentedMarkdownList(t *testing.T) {
	// arrange
	rootNode := newNode(nil, "root", nil)
	firstLevelNode := newNode(rootNode, "first level node", nil)
	newNode(firstLevelNode, "first level child node 1", nil)
	newNode(firstLevelNode, "first level child node 2", nil)

	// act
	result := rootNode.String()

	// assert
	expected := `- root
    - first level node
        - first level child node 1
        - first level child node 2`
	if strings.TrimSpace(result) != strings.TrimSpace(expected) {
		t.Errorf(`The String method of the node should return %q but returned %q instead.`, expected, result)
	}
}

func Test_Node_Name_EmptyNode_ResultIsSpecifiedNodeName(t *testing.T) {
	// arrange
	node := &Node{}

	// act
	result := node.Name()

	// assert
	expected := "<no-name-assigned>"
	if result != expected {
		t.Errorf("The name of an empty node should be %q but was %q instead.", expected, result)
	}
}

func Test_Node_Name_NonEmptyNode_ResultIsSpecifiedNodeName(t *testing.T) {
	// arrange
	name := "<NAME>"
	node := newNode(nil, name, nil)

	// act
	result := node.Name()

	// assert
	if result != name {
		t.Errorf("The name of the node should be %q but was %q.", name, result)
	}
}

func Test_Node_Value_IsNil_ResultIsNil(t *testing.T) {
	// arrange
	var expected interface{}
	node := newRootNode("root", expected)

	// act
	result := node.Value()

	// assert
	if result != expected {
		t.Errorf("The node value should be %q but was %q instead.", expected, result)
	}
}

func Test_Node_Value_IsNotNull_ResultAsSpecified(t *testing.T) {
	// arrange
	expected := new(interface{})
	node := newRootNode("root", expected)

	// act
	result := node.Value()

	// assert
	if result != expected {
		t.Errorf("The node value should be %q but was %q instead.", expected, result)
	}
}

func Test_Node_Parent_NoParentSpecified_ResultIsNil(t *testing.T) {
	// arrange
	node := newNode(nil, "<NAME>", nil)

	// act
	result := node.Parent()

	// assert
	if result != nil {
		t.Errorf("The parent of the node should be %q but was %q.", nil, result)
	}
}

func Test_Node_Parent_ParentSpecified_ResultIsSpecifiedParent(t *testing.T) {
	// arrange
	parent := newNode(nil, "root", nil)
	node := newNode(parent, "<NAME>", nil)

	// act
	result := node.Parent()

	// assert
	if result != parent {
		t.Errorf("The parent of the node should be %q but was %q.", parent, result)
	}
}

func Test_Node_GetNode_ThreeLevelNode_EmptyPath_ResultIsNil(t *testing.T) {
	// arrange
	rootNode := newNode(nil, "root", nil)
	nodeLevel1 := newNode(rootNode, "level 1", nil)
	newNode(nodeLevel1, "level 2", nil)

	path := NewPath()
	var expectedResult *Node

	// act
	result := rootNode.GetNode(path)

	// assert
	if result != expectedResult {
		t.Errorf("The GetNode method executed on the node %q should return %s for the path %q but returned %s instead.", rootNode, expectedResult, path, result)
	}
}

func Test_Node_GetNode_ThreeLevelNode_FirstNodeIsRequested_ResultIsFirstNode(t *testing.T) {
	// arrange
	rootNode := newNode(nil, "root", nil)
	nodeLevel1 := newNode(rootNode, "level 1", nil)
	newNode(nodeLevel1, "level 2", nil)

	path := NewPath("root")
	expectedResult := rootNode

	// act
	result := rootNode.GetNode(path)

	// assert
	if result != expectedResult {
		t.Errorf("The GetNode method executed on the node %q should return %s for the path %q but returned %s instead.", rootNode, expectedResult.Name(), path, result.Name())
	}
}

func Test_Node_GetNode_ThreeLevelNode_SecondlastNodeIsRequested_ResultIsSecondlastNode(t *testing.T) {
	// arrange
	rootNode := newNode(nil, "root", nil)
	nodeLevel1 := newNode(rootNode, "level 1", nil)
	newNode(nodeLevel1, "level 2", nil)

	path := NewPath("root", "level 1")
	expectedResult := nodeLevel1

	// act
	result := rootNode.GetNode(path)

	// assert
	if result != expectedResult {
		t.Errorf("The GetNode method executed on the node %q should return %s for the path %q but returned %s instead.", rootNode, expectedResult.Name(), path, result.Name())
	}
}

func Test_Node_GetNode_ThreeLevelNode_LastNodeIsRequested_ResultIsLastNode(t *testing.T) {
	// arrange
	rootNode := newNode(nil, "root", nil)
	nodeLevel1 := newNode(rootNode, "level 1", nil)
	nodeLevel2 := newNode(nodeLevel1, "level 2", nil)

	path := NewPath("root", "level 1", "level 2")
	expectedResult := nodeLevel2

	// act
	result := rootNode.GetNode(path)

	// assert
	if result != expectedResult {
		t.Errorf("The GetNode method executed on the node %q should return %s for the path %q but returned %s instead.", rootNode, expectedResult.Name(), path, result.Name())
	}
}

func Test_Node_GetNode_ComplextNode_ComplextPath_ResultIsCorrect(t *testing.T) {
	// arrange
	rootNode := newNode(nil, "root", nil)
	newNode(rootNode, "child1", nil)
	newNode(rootNode, "child2", nil)
	newNode(rootNode, "child3", nil)

	nodeLevel1 := newNode(rootNode, "level 1", nil)
	newNode(nodeLevel1, "level 1 child 1", nil)
	newNode(nodeLevel1, "level 1 child 2", nil)
	nodeLevel1Child3 := newNode(nodeLevel1, "level 1 child 3", nil)
	targetNode := newNode(nodeLevel1Child3, "another child", nil)

	newNode(nodeLevel1, "level 2", nil)

	path := NewPath("root", "level 1", "level 1 child 3", "another child")
	expectedResult := targetNode

	// act
	result := rootNode.GetNode(path)

	// assert
	if result != expectedResult {
		t.Errorf("The GetNode method executed on the node %q should return %s for the path %q but returned %s instead.", rootNode, expectedResult.Name(), path, result.Name())
	}
}

func Test_getNodeLevel_RootNode_ResultIsZero(t *testing.T) {
	// arrange
	node := newNode(nil, "node", nil)

	// act
	result := getNodeLevel(node)

	// assert
	expected := 0
	if result != expected {
		t.Errorf("The level of a root node should be %v but was %v.", expected, result)
	}
}

func Test_getNodeLevel_OneParent_ResultIsOne(t *testing.T) {
	// arrange
	firstParent := newNode(nil, "first parent", nil)
	node := newNode(firstParent, "node", nil)

	// act
	result := getNodeLevel(node)

	// assert
	expected := 1
	if result != expected {
		t.Errorf("The level of a root node should be %v but was %v.", expected, result)
	}
}

func Test_getNodeLevel_TwoParents_ResultIsTwo(t *testing.T) {
	// arrange
	firstParent := newNode(nil, "first parent", nil)
	secondParent := newNode(firstParent, "second parent", nil)
	node := newNode(secondParent, "node", nil)

	// act
	result := getNodeLevel(node)

	// assert
	expected := 2
	if result != expected {
		t.Errorf("The level of a root node should be %v but was %v.", expected, result)
	}
}

func Test_getNodeLevel_ThreeParents_ResultIsThree(t *testing.T) {
	// arrange
	firstParent := newNode(nil, "first parent", nil)
	secondParent := newNode(firstParent, "second parent", nil)
	thirdParent := newNode(secondParent, "third parent", nil)
	node := newNode(thirdParent, "node", nil)

	// act
	result := getNodeLevel(node)

	// assert
	expected := 3
	if result != expected {
		t.Errorf("The level of a root node should be %v but was %v.", expected, result)
	}
}

func Test_Node_Delete(t *testing.T) {
	// arrange
	rootNode := newNode(nil, "root", nil)
	firstLevelNode := newNode(rootNode, "first level node", nil)
	secondLevelNode := newNode(firstLevelNode, "first level child node 1", nil)
	newNode(secondLevelNode, "Third level node 1", nil)
	newNode(firstLevelNode, "first level child node 2", nil)

	// act
	rootNode.Delete(Path{"first level node", "first level child node 1", "Third level node 1"})
	result := rootNode.String()

	// assert
	expected := `- root
    - first level node
        - first level child node 1
        - first level child node 2`
	if strings.TrimSpace(result) != strings.TrimSpace(expected) {
		t.Errorf(`The String method of the node should return %q but returned %q instead.`, expected, result)
	}
}


<|start_filename|>web/view/themes/themefiles/treeimages.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

var VerticalLinePng = `iVBORw0KGgoAAAANSUhEUgAAAAEAAAAKAQMAAABPHKYJAAAAA1BMVEWIiIhYZW6zAAAACXBIWXMA
AAsTAAALEwEAmpwYAAAAB3RJTUUH1ggGExMZBky19AAAAAtJREFUCNdjYMAEAAAUAAHlhrBKAAAA
AElFTkSuQmCC`

var LastNodePng = `iVBORw0KGgoAAAANSUhEUgAAAAgAAAAUAQMAAACK1e4oAAAABlBMVEUAAwCIiIgd2JB2AAAAAXRS
TlMAQObYZgAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YIBhQIIhs+gc8AAAAQSURBVAjX
Y2hgQIf/GbAAAKCTBYBUjWvCAAAAAElFTkSuQmCC`

var NodePng = `iVBORw0KGgoAAA<KEY>wCIiIgd2JB2AAAAAXRS
TlMAQObYZgAAAAlwSFlzAAALEwAACxMBAJqcGAAAA<KEY>YVaFGwAAAARSURBVAjX
Y2hgQIf/GTDFGgDSkwqATqpCHAAAAABJRU5ErkJggg==`


<|start_filename|>web/view/viewmodel/analytics.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type Analytics struct {
	Enabled         bool            `json:"enabled"`
	GoogleAnalytics GoogleAnalytics `json:"googleAnalytics"`
}

type GoogleAnalytics struct {
	Enabled    bool   `json:"enabled"`
	TrackingID string `json:"trackingId"`
}


<|start_filename|>common/route/route_subroute_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package route

import (
	"testing"
)

func Test_SubRoute_TwoLevelRoute_RequestLevelZero_LevelZeroIsReturned(t *testing.T) {
	// arrange
	level := 0
	expected := ""
	route := NewFromRequest("/documents/Test-1")

	// act
	result, _ := route.SubRoute(level)

	// assert
	if !result.IsEmpty() || result.Value() != expected {
		t.Errorf("The level-%d sub route should be %q, but was %q.", level, expected, result.Value())
	}
}

func Test_SubRoute_TwoLevelRoute_RequestFirstLevel_FirstLevelIsReturned(t *testing.T) {
	// arrange
	level := 1
	expected := "documents"
	route := NewFromRequest("/documents/Test-1")

	// act
	result, _ := route.SubRoute(level)

	// assert
	if result.IsEmpty() || result.Value() != expected {
		t.Errorf("The level-%d sub route should be %q, but was %q.", level, expected, result.Value())
	}
}

func Test_SubRoute_TwoLevelRoute_RequestSecondLevel_SecondLevelIsReturned(t *testing.T) {
	// arrange
	level := 2
	expected := "documents/Test-1"
	route := NewFromRequest("/documents/Test-1")

	// act
	result, _ := route.SubRoute(level)

	// assert
	if result.IsEmpty() || result.Value() != expected {
		t.Errorf("The level-%d sub route should be %q, but was %q.", level, expected, result.Value())
	}
}


<|start_filename|>vendor/github.com/jbarham/go-cdb/hash.go<|end_filename|>
package cdb

import "hash"

const (
	start = 5381 // Initial cdb checksum value.
)

// digest represents the partial evaluation of a checksum.
type digest struct {
	h uint32
}

func (d *digest) Reset() { d.h = start }

// New returns a new hash computing the cdb checksum.
func cdbHash() hash.Hash32 {
	d := new(digest)
	d.Reset()
	return d
}

func (d *digest) Size() int { return 4 }

func update(h uint32, p []byte) uint32 {
	for i := 0; i < len(p); i++ {
		h = ((h << 5) + h) ^ uint32(p[i])
	}
	return h
}

func (d *digest) Write(p []byte) (int, error) {
	d.h = update(d.h, p)
	return len(p), nil
}

func (d *digest) Sum32() uint32 { return d.h }

func (d *digest) Sum(in []byte) []byte {
	s := d.Sum32()
	in = append(in, byte(s>>24))
	in = append(in, byte(s>>16))
	in = append(in, byte(s>>8))
	in = append(in, byte(s))
	return in
}

func (d *digest) BlockSize() int { return 1 }

func checksum(data []byte) uint32 { return update(start, data) }


<|start_filename|>vendor/github.com/spf13/afero/fs.go<|end_filename|>
// Copyright © 2014 <NAME> <<EMAIL>>.
// Copyright 2013 tsuru authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package afero provides types and methods for interacting with the filesystem,
// as an abstraction layer.

// Afero also provides a few implementations that are mostly interoperable. One that
// uses the operating system filesystem, one that uses memory to store files
// (cross platform) and an interface that should be implemented if you want to
// provide your own filesystem.

package afero

import (
	"errors"
	"io"
	"os"
	"sort"
	"time"
)

// File represents a file in the filesystem.
type File interface {
	io.Closer
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Writer
	io.WriterAt
	//Fd() uintptr
	Stat() (os.FileInfo, error)
	Readdir(count int) ([]os.FileInfo, error)
	Readdirnames(n int) ([]string, error)
	WriteString(s string) (ret int, err error)
	Truncate(size int64) error
	Name() string
}

// Fs is the filesystem interface.
//
// Any simulated or real filesystem should implement this interface.
type Fs interface {
	// Create creates a file in the filesystem, returning the file and an
	// error, if any happens.
	Create(name string) (File, error)

	// Mkdir creates a directory in the filesystem, return an error if any
	// happens.
	Mkdir(name string, perm os.FileMode) error

	// MkdirAll creates a directory path and all parents that does not exist
	// yet.
	MkdirAll(path string, perm os.FileMode) error

	// Open opens a file, returning it or an error, if any happens.
	Open(name string) (File, error)

	// OpenFile opens a file using the given flags and the given mode.
	OpenFile(name string, flag int, perm os.FileMode) (File, error)

	// Remove removes a file identified by name, returning an error, if any
	// happens.
	Remove(name string) error

	// RemoveAll removes a directory path and all any children it contains. It
	// does not fail if the path does not exist (return nil).
	RemoveAll(path string) error

	// Rename renames a file.
	Rename(oldname, newname string) error

	// Stat returns a FileInfo describing the named file, or an error, if any
	// happens.
	Stat(name string) (os.FileInfo, error)

	// The name of this FileSystem
	Name() string

	//Chmod changes the mode of the named file to mode.
	Chmod(name string, mode os.FileMode) error

	//Chtimes changes the access and modification times of the named file
	Chtimes(name string, atime time.Time, mtime time.Time) error
}

var (
	ErrFileClosed        = errors.New("File is closed")
	ErrOutOfRange        = errors.New("Out of range")
	ErrTooLarge          = errors.New("Too large")
	ErrFileNotFound      = os.ErrNotExist
	ErrFileExists        = os.ErrExist
	ErrDestinationExists = os.ErrExist
)

// ReadDir reads the directory named by dirname and returns
// a list of sorted directory entries.
func ReadDir(dirname string, fs Fs) ([]os.FileInfo, error) {
	f, err := fs.Open(dirname)
	if err != nil {
		return nil, err
	}
	list, err := f.Readdir(-1)
	f.Close()
	if err != nil {
		return nil, err
	}
	sort.Sort(byName(list))
	return list, nil
}

// byName implements sort.Interface.
type byName []os.FileInfo

func (f byName) Len() int           { return len(f) }
func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }


<|start_filename|>vendor/github.com/jbarham/go-cdb/cdb.go<|end_filename|>
// Package cdb reads and writes cdb ("constant database") files.
//
// See the original cdb specification and C implementation by <NAME>
// at http://cr.yp.to/cdb.html.
package cdb

import (
	"bytes"
	"encoding/binary"
	"io"
	"os"
	"runtime"
)

const (
	headerSize = uint32(256 * 8)
)

type Cdb struct {
	r      io.ReaderAt
	closer io.Closer
	buf    []byte
	loop   uint32 // number of hash slots searched under this key
	khash  uint32 // initialized if loop is nonzero
	kpos   uint32 // initialized if loop is nonzero
	hpos   uint32 // initialized if loop is nonzero
	hslots uint32 // initialized if loop is nonzero
	dpos   uint32 // initialized if FindNext() returns true
	dlen   uint32 // initialized if FindNext() returns true
}

// Open opens the named file read-only and returns a new Cdb object.  The file
// should exist and be a cdb-format database file.
func Open(name string) (*Cdb, error) {
	f, err := os.Open(name)
	if err != nil {
		return nil, err
	}
	c := New(f)
	c.closer = f
	runtime.SetFinalizer(c, (*Cdb).Close)
	return c, nil
}

// Close closes the cdb for any further reads.
func (c *Cdb) Close() (err error) {
	if c.closer != nil {
		err = c.closer.Close()
		c.closer = nil
		runtime.SetFinalizer(c, nil)
	}
	return err
}

// New creates a new Cdb from the given ReaderAt, which should be a cdb format database.
func New(r io.ReaderAt) *Cdb {
	c := new(Cdb)
	c.r = r
	c.buf = make([]byte, 64)
	return c
}

// Data returns the first data value for the given key.
// If no such record exists, it returns EOF.
func (c *Cdb) Data(key []byte) (data []byte, err error) {
	c.FindStart()
	if err = c.find(key); err != nil {
		return nil, err
	}

	data = make([]byte, c.dlen)
	err = c.read(data, c.dpos)

	return
}

// FindStart resets the cdb to search for the first record under a new key.
func (c *Cdb) FindStart() { c.loop = 0 }

// FindNext returns the next data value for the given key as a SectionReader.
// If there are no more records for the given key, it returns EOF.
// FindNext acts as an iterator: The iteration should be initialized by calling
// FindStart and all subsequent calls to FindNext should use the same key value.
func (c *Cdb) FindNext(key []byte) (rdata *io.SectionReader, err error) {
	if err := c.find(key); err != nil {
		return nil, err
	}
	return io.NewSectionReader(c.r, int64(c.dpos), int64(c.dlen)), nil
}

// Find returns the first data value for the given key as a SectionReader.
// Find is the same as FindStart followed by FindNext.
func (c *Cdb) Find(key []byte) (rdata *io.SectionReader, err error) {
	c.FindStart()
	return c.FindNext(key)
}

func (c *Cdb) find(key []byte) (err error) {
	defer func() {
		if e := recover(); e != nil {
			err = e.(error)
		}
	}()

	var pos, h uint32

	klen := uint32(len(key))
	if c.loop == 0 {
		h = checksum(key)
		c.hpos, c.hslots = c.readNums((h << 3) & 2047)
		if c.hslots == 0 {
			return io.EOF
		}
		c.khash = h
		h >>= 8
		h %= c.hslots
		h <<= 3
		c.kpos = c.hpos + h
	}

	for c.loop < c.hslots {
		h, pos = c.readNums(c.kpos)
		if pos == 0 {
			return io.EOF
		}
		c.loop++
		c.kpos += 8
		if c.kpos == c.hpos+(c.hslots<<3) {
			c.kpos = c.hpos
		}
		if h == c.khash {
			rklen, rdlen := c.readNums(pos)
			if rklen == klen {
				if c.match(key, pos+8) {
					c.dlen = rdlen
					c.dpos = pos + 8 + klen
					return nil
				}
			}
		}
	}

	return io.EOF
}

func (c *Cdb) read(buf []byte, pos uint32) error {
	_, err := c.r.ReadAt(buf, int64(pos))
	return err
}

func (c *Cdb) match(key []byte, pos uint32) bool {
	buf := c.buf
	klen := len(key)
	for n := 0; n < klen; n += len(buf) {
		nleft := klen - n
		if len(buf) > nleft {
			buf = buf[:nleft]
		}
		if err := c.read(buf, pos); err != nil {
			panic(err)
		}
		if !bytes.Equal(buf, key[n:n+len(buf)]) {
			return false
		}
		pos += uint32(len(buf))
	}
	return true
}

func (c *Cdb) readNums(pos uint32) (uint32, uint32) {
	if _, err := c.r.ReadAt(c.buf[:8], int64(pos)); err != nil {
		panic(err)
	}
	return binary.LittleEndian.Uint32(c.buf), binary.LittleEndian.Uint32(c.buf[4:])
}


<|start_filename|>web/view/viewmodel/typeahead.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type TypeAhead struct {
	Index int `json:"index"`

	Title       string `json:"title"`
	Description string `json:"description"`
	Route       string `json:"route"`
	Path        string `json:"path"`

	Value  string   `json:"value"`
	Tokens []string `json:"tokens"`
}


<|start_filename|>web/view/themes/themefiles/highlightjs.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const HighlightJs = `<KEY>
<KEY>

const HighlightCss = `/* Original style from softwaremaniacs.org (c) <NAME> <<EMAIL>> v.8.3 */

.hljs {
  display: block;
  overflow-x: auto;
  padding: 0.5em;
  background: #f0f0f0;
  -webkit-text-size-adjust: none;
}

.hljs,
.hljs-subst,
.hljs-tag .hljs-title,
.nginx .hljs-title {
  color: black;
}

.hljs-string,
.hljs-title,
.hljs-constant,
.hljs-parent,
.hljs-tag .hljs-value,
.hljs-rules .hljs-value,
.hljs-preprocessor,
.hljs-pragma,
.haml .hljs-symbol,
.ruby .hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.hljs-template_tag,
.django .hljs-variable,
.smalltalk .hljs-class,
.hljs-addition,
.hljs-flow,
.hljs-stream,
.bash .hljs-variable,
.apache .hljs-tag,
.apache .hljs-cbracket,
.tex .hljs-command,
.tex .hljs-special,
.erlang_repl .hljs-function_or_atom,
.asciidoc .hljs-header,
.markdown .hljs-header,
.coffeescript .hljs-attribute {
  color: #800;
}

.smartquote,
.hljs-comment,
.hljs-annotation,
.hljs-template_comment,
.diff .hljs-header,
.hljs-chunk,
.asciidoc .hljs-blockquote,
.markdown .hljs-blockquote {
  color: #888;
}

.hljs-number,
.hljs-date,
.hljs-regexp,
.hljs-literal,
.hljs-hexcolor,
.smalltalk .hljs-symbol,
.smalltalk .hljs-char,
.go .hljs-constant,
.hljs-change,
.lasso .hljs-variable,
.makefile .hljs-variable,
.asciidoc .hljs-bullet,
.markdown .hljs-bullet,
.asciidoc .hljs-link_url,
.markdown .hljs-link_url {
  color: #080;
}

.hljs-label,
.hljs-javadoc,
.ruby .hljs-string,
.hljs-decorator,
.hljs-filter .hljs-argument,
.hljs-localvars,
.hljs-array,
.hljs-attr_selector,
.hljs-important,
.hljs-pseudo,
.hljs-pi,
.haml .hljs-bullet,
.hljs-doctype,
.hljs-deletion,
.hljs-envvar,
.hljs-shebang,
.apache .hljs-sqbracket,
.nginx .hljs-built_in,
.tex .hljs-formula,
.erlang_repl .hljs-reserved,
.hljs-prompt,
.asciidoc .hljs-link_label,
.markdown .hljs-link_label,
.vhdl .hljs-attribute,
.clojure .hljs-attribute,
.asciidoc .hljs-attribute,
.lasso .hljs-attribute,
.coffeescript .hljs-property,
.hljs-phony {
  color: #88f;
}

.hljs-keyword,
.hljs-id,
.hljs-title,
.hljs-built_in,
.css .hljs-tag,
.hljs-javadoctag,
.hljs-phpdoc,
.hljs-dartdoc,
.hljs-yardoctag,
.smalltalk .hljs-class,
.hljs-winutils,
.bash .hljs-variable,
.apache .hljs-tag,
.hljs-type,
.hljs-typename,
.tex .hljs-command,
.asciidoc .hljs-strong,
.markdown .hljs-strong,
.hljs-request,
.hljs-status {
  font-weight: bold;
}

.asciidoc .hljs-emphasis,
.markdown .hljs-emphasis {
  font-style: italic;
}

.nginx .hljs-built_in {
  font-weight: normal;
}

.coffeescript .javascript,
.javascript .xml,
.lasso .markup,
.tex .hljs-formula,
.xml .javascript,
.xml .vbscript,
.xml .css,
.xml .hljs-cdata {
  opacity: 0.5;
}
`


<|start_filename|>common/config/json_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package config

import (
	"bytes"
	"strings"
	"testing"
)

func Test_SerializeConfig_NoErrorIsReturned(t *testing.T) {
	// arrange
	writeBuffer := new(bytes.Buffer)

	config := &Config{
		Server: Server{
			ThemeFolderName: "/some/folder",
			HTTP: HTTP{
				Enabled: true,
			},
		},
	}

	serializer := JSONSerializer{}

	// act
	err := serializer.SerializeConfig(writeBuffer, config)

	// assert
	if err != nil {
		t.Fail()
		t.Logf("The serialization of the config object return an error. %s", err)
	}
}

func Test_SerializeConfig_JSONContainsConfigValues(t *testing.T) {
	// arrange
	writeBuffer := new(bytes.Buffer)

	config := &Config{
		Server: Server{
			ThemeFolderName: "/some/folder",
			HTTP: HTTP{
				Enabled: true,
			},
		},
	}

	serializer := JSONSerializer{}

	// act
	serializer.SerializeConfig(writeBuffer, config)

	// assert
	json := writeBuffer.String()

	// assert: json contains theme folder
	if !strings.Contains(json, config.Server.ThemeFolderName) {
		t.Fail()
		t.Logf("The produced json does not contain the 'ThemeFolderName' value %q. The produced JSON is this: %s", config.Server.ThemeFolderName, json)
	}

	// assert: json contains http enabled
	if !strings.Contains(json, "true") {
		t.Fail()
		t.Logf("The produced json does not contain the 'Http Enabled' value %q. The produced JSON is this: %s", config.Server.HTTP.Enabled, json)
	}
}

func Test_SerializeConfig_JSONIsFormatted(t *testing.T) {
	// arrange
	writeBuffer := new(bytes.Buffer)

	config := &Config{
		Server: Server{
			ThemeFolderName: "/some/folder",
			HTTP: HTTP{
				Enabled: true,
			},
		},
	}

	serializer := JSONSerializer{}

	// act
	serializer.SerializeConfig(writeBuffer, config)

	// assert
	json := writeBuffer.String()

	// assert: json contains theme folder
	if !strings.Contains(json, "\n") {
		t.Fail()
		t.Logf("The produced json does not seem to be formatted. The produced JSON is this: %s", json)
	}
}

func Test_DeserializeConfig_EmptyObjectString_NoErrorIsReturned(t *testing.T) {
	// arrange
	json := `{}`
	jsonReader := bytes.NewBuffer([]byte(json))

	serializer := JSONSerializer{}

	// act
	_, err := serializer.DeserializeConfig(jsonReader)

	// assert
	if err != nil {
		t.Fail()
		t.Logf("The deserialization of %q should not produce an error. But it did produce this error: %s", json, err)
	}
}

func Test_DeserializeConfig_FullConfigString_AllFieldsAreSet(t *testing.T) {
	// arrange
	json := `{
		"Server": {
			"ThemeFolderName": "/some/folder",
			"HTTP": {
				"Enabled": true
			}
		}
	}`
	jsonReader := bytes.NewBuffer([]byte(json))

	serializer := JSONSerializer{}

	// act
	config, _ := serializer.DeserializeConfig(jsonReader)

	// assert: Theme folder
	if config.Server.ThemeFolderName == "" {
		t.Fail()
		t.Logf("The deserialized config object should have the %q field properly initialized. Deserialization result: %#v", "ThemeFolderName", config)
	}

	// assert: http enabled
	if config.Server.HTTP.Enabled != true {
		t.Fail()
		t.Logf("The deserialized config object should have the %q field properly initialized. Deserialization result: %#v", "Http.Enabled", config)
	}
}

func Test_DeserializeConfig_ObjectWithDifferentFields_ConfigWithDefaultValuesIsReturned(t *testing.T) {
	// arrange
	json := `{
		"Name": "<NAME>",
		"AnotherField": {
		},
		"SomeList": [ "1", "2", "3" ]
	}
	`
	jsonReader := bytes.NewBuffer([]byte(json))

	serializer := JSONSerializer{}

	// act
	config, _ := serializer.DeserializeConfig(jsonReader)

	// assert
	emptyConfig := Config{}
	if config.Server.ThemeFolderName != emptyConfig.Server.ThemeFolderName {
		t.Fail()
		t.Logf("When the JSON cannot be mapped to the Config type the deserializer should return an uninitialized config object.")
	}
}

func Test_DeserializeConfig_EmptyString_ErrorIsReturned(t *testing.T) {
	// arrange
	json := ""
	jsonReader := bytes.NewBuffer([]byte(json))

	serializer := JSONSerializer{}

	// act
	_, err := serializer.DeserializeConfig(jsonReader)

	// assert
	if err == nil {
		t.Fail()
		t.Logf("DeserializeConfig should return an error if supplied JSON is invalid")
	}
}

func Test_DeserializeConfig_InvalidJSON_ErrorIsReturned(t *testing.T) {
	// arrange
	json := `dsajdklasdj/(/)(=7897402
		38748902
		;;;
	`
	jsonReader := bytes.NewBuffer([]byte(json))

	serializer := JSONSerializer{}

	// act
	_, err := serializer.DeserializeConfig(jsonReader)

	// assert
	if err == nil {
		t.Fail()
		t.Logf("DeserializeConfig should return an error if supplied JSON is invalid")
	}
}


<|start_filename|>model/geoinformation.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package model

type GeoInformation struct {
	Street    string
	City      string
	Postcode  string
	Country   string
	Latitude  string
	Longitude string
	MapType   string
	Zoom      int
}


<|start_filename|>common/route/route_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package route

import (
	"testing"
)

func Test_EmptyRoute_String_ReturnsEmptyString(t *testing.T) {

	// arrange
	route := Route{}

	// act
	result := route.String()

	// assert
	expected := ""
	if result != expected {
		t.Errorf("The String method of an empty route should return %q but returned %q instead.", expected, result)
	}

}

// Testing the NewFromRequest Route functon: The constructor function should return a Route object for the supplied path.
func Test_NewFromRequest_ValidPathReturnsRoute(t *testing.T) {
	// arrange
	inputPath := "document/Test"

	// act
	result := NewFromRequest(inputPath)

	// assert
	if result.IsEmpty() {
		t.Errorf("The constructor function should return a Route object for the path %q.", inputPath)
	}
}

// Testing the normalize function: The function returns an empty route.
func Test_normalize_EmptyString_RouteIsReturned(t *testing.T) {
	// arrange
	inputPath := " "
	expected := ""

	// act
	result := normalize(inputPath)

	// assert
	if result != expected {
		t.Errorf("The normalze function should have returned %q but retured %q instead.", expected, result)
	}
}

// Testing the normalize function: Remove leading and trailing white space.
func Test_normalize_TrimEnd(t *testing.T) {
	// arrange
	inputPath := " documents/Test "
	expectedResult := "documents/Test"

	// act
	result := normalize(inputPath)

	// assert
	if result != expectedResult {
		t.Errorf("Should have removed leading and trailing white space (Expected: %s, Actual: %s)", expectedResult, result)
	}
}

// Testing the normalize function: Remove a trailing slash.
func Test_normalize_RemoveTrailingSlashes(t *testing.T) {
	// arrange
	inputPath := "documents/Test/"
	expectedResult := "documents/Test"

	// act
	result := normalize(inputPath)

	// assert
	if result != expectedResult {
		t.Errorf("Should have removed the trailing slash (Expected: %s, Actual: %s)", expectedResult, result)
	}
}

// Testing the normalize function: Remove a trailing slash.
func Test_normalize_RemoveLeadingSlashes(t *testing.T) {
	// arrange
	inputPath := "/documents/Test/"
	expectedResult := "documents/Test"

	// act
	result := normalize(inputPath)

	// assert
	if result != expectedResult {
		t.Errorf("Should have removed the leading slash (Expected: %s, Actual: %s)", expectedResult, result)
	}
}

// Testing the normalize function: Replace all backslashes with forward slashes.
func Test_normalize_NormalizeSlashes(t *testing.T) {
	// arrange
	inputPath := "documents\\Test"
	expectedResult := "documents/Test"

	// act
	result := normalize(inputPath)

	// assert
	if result != expectedResult {
		t.Errorf("Should have replaced all backslashes with forward slashes (Expected: %s, Actual: %s)", expectedResult, result)
	}
}

// Testing the normalize function: Replace all double white spaces
func Test_normalize_ReplaceDoubleWhitespace(t *testing.T) {
	// arrange
	inputPath := "my    documents/A  Test"
	expectedResult := "my documents/A Test"

	// act
	result := normalize(inputPath)

	// assert
	if result != expectedResult {
		t.Errorf("Should have replaced all double white spaces with a single url safe characters (Expected: %s, Actual: %s)", expectedResult, result)
	}
}

// Testing the normalize function: Two almost identify paths get a different route.
func Test_normalize_UniqueResultsForUniquePaths(t *testing.T) {
	// arrange
	inputPath1 := "/Images/Hurricane-Festival"
	inputPath2 := "/Images/Hur<NAME>"

	// act
	result1 := normalize(inputPath1)
	result2 := normalize(inputPath2)

	// assert
	if result1 == result2 {
		t.Errorf("normalize should always return a unique route for a unique path. But normalize returned the same result for two different paths. normalize(%q)=%q  == normalize(%q)=%q", inputPath1, result1, inputPath2, result2)
	}
}

// Testing the toURL function: Replace white space with url safe characters.
func Test_toURL_ReplaceWhitespaceWithURLSafeCharacters(t *testing.T) {
	// arrange
	inputPath := "documents/A Test"
	expectedResult := "documents/A+Test"

	// act
	result := toURL(inputPath)

	// assert
	if result != expectedResult {
		t.Errorf("Should have replaced all white space characters with url safe characters (Expected: %s, Actual: %s)", expectedResult, result)
	}
}


<|start_filename|>web/view/viewmodel/geolocation.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type GeoLocation struct {
	PlaceName   string `json:"placename"`
	Address     string `json:"address"`
	Coordinates string `json:"coordinates"`

	Street    string `json:"street"`
	City      string `json:"city"`
	Postcode  string `json:"postcode"`
	Country   string `json:"country"`
	Latitude  string `json:"latitude"`
	Longitude string `json:"longitude"`
	MapType   string `json:"mapType"`
	Zoom      int    `json:"zoom"`
}


<|start_filename|>web/view/viewmodel/conversion.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type ConversionModel struct {
	Base

	Content string `json:"content"`

	Files []File `json:"files"`
}


<|start_filename|>web/webpaths/absolute_test.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package webpaths

import (
	"testing"
)

func Test_AbsoluteWebPathProvider_NoPrefix_Path_ReturnsPathWithoutModification(t *testing.T) {
	// arrange
	prefix := ""
	pathProvider := newAbsoluteWebPathProvider(prefix)
	inputPath := "yada/yada.html"
	expected := "yada/yada.html"

	// act
	result := pathProvider.Path(inputPath)

	// assert
	if result != expected {
		t.Errorf("The result for pathProvider.Path(%q) with a prefix of %q should be %q but was %q.", inputPath, prefix, expected, result)
	}
}

func Test_AbsoluteWebPathProvider_SlashPrefix_Path_ReturnsPathWithSlash(t *testing.T) {
	// arrange
	prefix := "/"
	pathProvider := newAbsoluteWebPathProvider(prefix)
	inputPath := "yada/yada.html"
	expected := "/yada/yada.html"

	// act
	result := pathProvider.Path(inputPath)

	// assert
	if result != expected {
		t.Errorf("The result for pathProvider.Path(%q) with a prefix of %q should be %q but was %q.", inputPath, prefix, expected, result)
	}
}

func Test_AbsoluteWebPathProvider_Path_ParameterIsAbsolute_ReturnsPathWithoutModification(t *testing.T) {
	// arrange
	prefix := "/"
	pathProvider := newAbsoluteWebPathProvider(prefix)
	inputPath := "http://example.com/yada/yada.html"
	expected := "http://example.com/yada/yada.html"

	// act
	result := pathProvider.Path(inputPath)

	// assert
	if result != expected {
		t.Errorf("The result for pathProvider.Path(%q) with a prefix of %q should be %q but was %q.", inputPath, prefix, expected, result)
	}
}


<|start_filename|>common/content/contentprovider.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package content

import (
	"fmt"
	"io"
	"time"
)

type ContentProviderInterface interface {
	Data(contentReader func(content io.ReadSeeker) error) error
	Hash() (string, error)
	LastModified() (time.Time, error)
	MimeType() (string, error)
}

type MimeTypeProviderFunc func() (string, error)

type LastModifiedProviderFunc func() (time.Time, error)

type DataProviderFunc func(contentReader func(content io.ReadSeeker) error) error

type HashProviderFunc func() (string, error)

// NewContentProvider creates a new content provider with the given mimeType, data provider, hash provider and last modified provider.
func NewContentProvider(mimeType MimeTypeProviderFunc, data DataProviderFunc, hash HashProviderFunc, lastModified LastModifiedProviderFunc) (*ContentProvider, error) {

	currentHash, err := hash()
	if err != nil {
		return nil, fmt.Errorf("Cannot create content provider because hash() returned an error: %s", err.Error())
	}

	return &ContentProvider{
		mimeTypeProviderFunc:     mimeType,
		dataProviderFunc:         data,
		hashProviderFunc:         hash,
		lastModifiedProviderFunc: lastModified,
		lastHash:                 currentHash,
	}, nil
}

type ContentProvider struct {
	mimeTypeProviderFunc     MimeTypeProviderFunc
	dataProviderFunc         DataProviderFunc
	hashProviderFunc         HashProviderFunc
	lastModifiedProviderFunc LastModifiedProviderFunc
	lastHash                 string
}

func (provider *ContentProvider) Data(contentReader func(content io.ReadSeeker) error) error {
	return provider.dataProviderFunc(contentReader)
}

func (provider *ContentProvider) Hash() (string, error) {
	hash, err := provider.hashProviderFunc()
	if err != nil {
		return hash, err
	}

	provider.lastHash = hash
	return hash, nil
}

func (provider *ContentProvider) LastModified() (time.Time, error) {
	return provider.lastModifiedProviderFunc()
}

func (provider *ContentProvider) MimeType() (string, error) {
	return provider.mimeTypeProviderFunc()
}

func (provider *ContentProvider) LastHash() string {
	return provider.lastHash
}


<|start_filename|>web/view/viewmodel/alias.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

import (
	"sort"
)

type AliasIndex struct {
	Model

	Aliases []Alias
}

// Alias represents an alias-index entry with a name, route and target route.
type Alias struct {
	Name        string
	Route       string
	TargetRoute string
}

// SortAliasBy can be used to sort two aliases.
type SortAliasBy func(alias1, alias2 Alias) bool

// Sort sorts the supplied list of aliases.
func (by SortAliasBy) Sort(aliases []Alias) {
	sorter := &aliasSorter{
		aliases: aliases,
		by:      by,
	}

	sort.Sort(sorter)
}

type aliasSorter struct {
	aliases []Alias
	by      SortAliasBy
}

func (sorter *aliasSorter) Len() int {
	return len(sorter.aliases)
}

func (sorter *aliasSorter) Swap(i, j int) {
	sorter.aliases[i], sorter.aliases[j] = sorter.aliases[j], sorter.aliases[i]
}

func (sorter *aliasSorter) Less(i, j int) bool {
	return sorter.by(sorter.aliases[i], sorter.aliases[j])
}


<|start_filename|>common/util/dateutil/date.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package dateutil

import (
	"errors"
	"fmt"
	"regexp"
	"strconv"
	"time"
)

// The regular expression which matches ISO 8601 date format pattern (e.g. 2013-02-08).
var iso8601DateFormatPattern = regexp.MustCompile("^(\\d{4})-(\\d{2})-(\\d{2})")

// The regular expression which matches a hh:mm time format pattern (e.g 21:13).
var timeFormatPattern = regexp.MustCompile("\\s(\\d{2}):(\\d{2})(:\\d{2})?")

// ParseIso8601Date parses a ISO 8601 date string (e.g. 2013-02-08 21:13)
// and returns the time value it represents.
func ParseIso8601Date(value string, fallback time.Time) (time.Time, error) {

	// Parse the date component (e.g. "2013-02-08")
	// check if the value matches the ISO 8601 Date pattern
	dateComponents := iso8601DateFormatPattern.FindStringSubmatch(value)
	if len(dateComponents) < 4 {
		return fallback, errors.New(fmt.Sprintf("\"%v\" is not a valid ISO 8601 date", value))
	}

	// parse year
	yearString := dateComponents[1]
	yearInt64, parseYearError := strconv.ParseInt(yearString, 10, 16)
	if parseYearError != nil || yearInt64 < 1 || yearInt64 > 9999 {
		return time.Time{}, fmt.Errorf("\"%v\" is not a valid value for a year. Valid values are in the range between 1 and 9999.", yearString)
	}

	// parse month
	monthString := dateComponents[2]
	monthInt64, parseMonthErr := strconv.ParseInt(monthString, 10, 8)
	if parseMonthErr != nil || monthInt64 < 1 || monthInt64 > 12 {
		return time.Time{}, fmt.Errorf("\"%v\" is not a valid value for a month. Valid values are in the range between 1 and 12.", monthString)
	}

	month, parseErrMonth := GetMonth(int(monthInt64))
	if parseErrMonth != nil {
		return time.Time{}, parseErrMonth
	}

	// parse day
	dayString := dateComponents[3]
	dayInt64, parseDayErr := strconv.ParseInt(dayString, 10, 8)
	if parseDayErr != nil || dayInt64 < 1 || dayInt64 > 31 {
		return time.Time{}, fmt.Errorf("\"%v\" is not a valid value for a day. Valid values are in the range between 1 and 31.", dayString)
	}

	// Parse the time component  (e.g. "21:13")
	var (
		hour        int
		minute      int
		second      int
		millisecond int
	)

	// check if the value matches the 24 hour time format pattern

	if timeComponents := timeFormatPattern.FindStringSubmatch(value); len(timeComponents) > 3 {

		// parse hours
		hourString := timeComponents[1]
		hourInt64, parseHourError := strconv.ParseInt(hourString, 10, 16)
		if parseHourError != nil || hourInt64 < 0 || hourInt64 > 23 {
			return time.Time{}, fmt.Errorf("\"%v\" is not a valid value for an hour in a 24h time format. Valid values are in the range between 0 and 23.", hourString)
		}
		hour = int(hourInt64)

		// parse minutes
		minuteString := timeComponents[2]
		minuteInt64, parseMinuteError := strconv.ParseInt(minuteString, 10, 16)
		if parseMinuteError != nil || minuteInt64 < 0 || minuteInt64 > 59 {
			return time.Time{}, fmt.Errorf("\"%v\" is not a valid value for an minute in a 24h time format. Valid values are in the range between 0 and 59.", minuteString)
		}
		minute = int(minuteInt64)

	}

	return time.Date(int(yearInt64), month, int(dayInt64), hour, minute, second, millisecond, time.UTC), nil
}

// GetMonth returns the time.Month value for
// a given integer value in the range between 1 and 12.
func GetMonth(value int) (time.Month, error) {
	switch value {
	case 1:
		return time.January, nil
	case 2:
		return time.February, nil
	case 3:
		return time.March, nil
	case 4:
		return time.April, nil
	case 5:
		return time.May, nil
	case 6:
		return time.June, nil
	case 7:
		return time.July, nil
	case 8:
		return time.August, nil
	case 9:
		return time.September, nil
	case 10:
		return time.October, nil
	case 11:
		return time.November, nil
	case 12:
		return time.December, nil
	}

	return time.January, fmt.Errorf("\"%v\" is not a valid value for a month.", value)
}


<|start_filename|>common/util/fsutil/filesystem.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package fsutil

import (
	"bufio"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// readLine returns a single line (without the ending \n)
// from the input buffered reader.
// An error is returned iff there is an error with the
// buffered reader.
func readLine(bufferedReader *bufio.Reader) (string, error) {
	var (
		isPrefix bool  = true
		err      error = nil
		line, ln []byte
	)

	for isPrefix && err == nil {
		line, isPrefix, err = bufferedReader.ReadLine()
		ln = append(ln, line...)
	}

	return string(ln), err
}

// Get all lines of a given file
func GetLines(inFile io.Reader) []string {

	lines := make([]string, 0, 10)
	bufferedReader := bufio.NewReader(inFile)
	line, err := readLine(bufferedReader)
	for err == nil {
		lines = append(lines, line)
		line, err = readLine(bufferedReader)
	}

	return lines
}

func CreateDirectory(path string) bool {
	err := os.MkdirAll(path, 0700)
	return err == nil
}

func OpenFile(filepath string) (*os.File, error) {
	if !FileExists(filepath) {
		return nil, fmt.Errorf("The file %q does not exist.", filepath)
	}

	return os.OpenFile(filepath, os.O_RDWR, 0644)
}

func CreateFile(filePath string) (success bool, err error) {

	// make sure the parent directory exists
	directory := filepath.Dir(filePath)
	if !DirectoryExists(directory) {
		if !CreateDirectory(directory) {
			return false, fmt.Errorf("Cannot create the directory for the given file %q.", filePath)
		}
	}

	// create the file
	if _, err := os.Create(filePath); err != nil {
		return false, fmt.Errorf("Could not create file %q. Error: ", filePath, err)
	}

	return true, nil
}

func PathExists(path string) bool {
	if strings.TrimSpace(path) == "" {
		return false
	}

	if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
		return false
	}

	return true
}

func FileExists(path string) bool {
	if strings.TrimSpace(path) == "" {
		return false
	}

	file, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		return false
	}

	return !file.IsDir()
}

func DirectoryExists(path string) bool {
	if strings.TrimSpace(path) == "" {
		return false
	}

	file, err := os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		return false
	}

	return file.IsDir()
}

func IsFile(path string) (bool, error) {

	fileInfo, err := os.Stat(path)
	if err != nil {
		return false, err
	}

	return fileInfo.IsDir() == false, nil
}

func IsDirectory(path string) (bool, error) {

	fileInfo, err := os.Stat(path)
	if err != nil {
		return false, err
	}

	return fileInfo.IsDir(), nil
}

// Gets the current working directory in which this application is being executed.
func GetWorkingDirectory() string {
	workingDirectory, err := os.Getwd()
	if err != nil {
		return "."
	}

	return workingDirectory
}

func GetSubDirectories(path string) []string {

	directories := make([]string, 0)

	if ok, _ := IsDirectory(path); !ok {
		fmt.Errorf("%q is not a directory.\n", path)
		return directories
	}

	directoryEntries, err := ioutil.ReadDir(path)
	if err != nil {
		fmt.Errorf("Cannot read directory %q.\n", path)
		return directories
	}

	for _, entry := range directoryEntries {
		if !entry.IsDir() {
			continue // skip files
		}

		subDirectory := filepath.Join(path, entry.Name())
		directories = append(directories, subDirectory)
	}

	return directories
}

func GetModificationTime(path string) (time.Time, error) {
	info, err := os.Stat(path)
	if err != nil {
		var t time.Time
		return t, err
	}

	return info.ModTime(), nil
}

// GetTempDirectory returns the path to a new temparory directory.
func GetTempDirectory() string {
	randomString := rand_str()
	tempDir := filepath.Join(os.TempDir(), randomString)

	if !CreateDirectory(tempDir) {
		panic(fmt.Sprintf("Cannot create temp directory %q.", tempDir))
	}

	return tempDir
}

func rand_str() string {
	size := 8
	rb := make([]byte, size)
	_, err := rand.Read(rb)
	if err != nil {
		panic(err)
	}

	rs := base64.URLEncoding.EncodeToString(rb)
	return rs
}


<|start_filename|>web/view/templates/defaulttheme/defaulttheme.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package defaulttheme

var (
	templates = make(map[string]string)
)

// RawTemplates returns a map of all raw templates in this theme by their name.
func RawTemplates() map[string]string {
	return templates
}


<|start_filename|>web/view/viewmodel/image.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type Image struct {
	File
}


<|start_filename|>web/view/themes/themefiles/searchjs.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const SearchJs = `
// data source: titles
var titlesDataSource = new Bloodhound({
	datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
	queryTokenizer: Bloodhound.tokenizers.whitespace,
	limit: 10,
	prefetch: {
		url: '/titles.json',
	}
});

titlesDataSource.initialize();

// data source: search
var searchDataSource = new Bloodhound({
	datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
	queryTokenizer: Bloodhound.tokenizers.whitespace,
	remote: '/search.json?q=%QUERY'
});

searchDataSource.initialize();

$('.typeahead').typeahead(
	{
		minLength: 1,
		items: 10,
		highlight: true,
	},
	{
		name: 'item-titles',
		displayKey: 'value',
		source: titlesDataSource.ttAdapter(),
		templates: {
			header: '<h3>Items</h3>'
		}
	},
	{
		name: 'searchresults',
		displayKey: 'value',
		source: searchDataSource.ttAdapter(),
		templates: {
			header: '<h3>Search Results</h3>'
		}
	}
).on('typeahead:selected', function(event, datum) {
	window.location = datum.route;
});
`


<|start_filename|>web/view/themes/themefiles/presentationjs.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const PresentationJs = `
$(function() {

  var presentationSelector = 'article.presentation > .content';

  // abort if the presentation selector is not found
  if ($(presentationSelector).length === 0) {
    return;
  }

  /**
   * Split the document body into separate slides
   */
  var transformPresentationStructure = function() {
    var presentationContent = $(presentationSelector).html();
    var slides = presentationContent.split("<hr>")
    var newHtml = '<section class="slide">' + slides.join('</section><section class="slide">') + '</section>';
    $(presentationSelector).html(newHtml);
  };

  var originalWidth = "";
  var originalFontSize = "";


  /**
   * Toggle the page header elements
   */
  var togglePresentationMode = function() {
    $("body>nav.toplevel").toggle();
    $("body>nav.breadcrumb").toggle();
    $("body>nav.search").toggle();
    $("aside.sidebar").toggle();
    $(".publisher").toggle();
    $("article.presentation").toggleClass("presentation-mode");
    $("article.presentation>header").toggle();
    $("article.presentation>nav").toggle();
    $("article.presentation>.description").toggle();
    $("article.presentation>.aliases").toggle();
    $("article.presentation>.tags").toggle();
    $("aside.export").toggle();
    $("body>footer").toggle();
    $(".ribbon").toggle();
    $(".allmark-promo").toggle();

    // toggle width and font size
    if (originalWidth === "" && originalFontSize === "") {
      originalWidth = $("body").css("width");
      originalFontSize = $("body").css("font-size");

      $("body").css("width", "95%");
      $("body").css("font-size", "1.5em");
    } else {
      $("body").css("width", originalWidth);
      $("body").css("font-size", originalFontSize);

      originalWidth = "";
      originalFontSize = "";
    }
  };

  /**
   * Transform all slides into a presentation
   */
  var renderPresentation = function() {


    if ($(presentationSelector).length == 0) {
      // this document is not a presentation
      return;
    }

    // transform the content
    transformPresentationStructure();

    // render the presentation
    $.deck('.slide', {
      selectors: {
        container: presentationSelector
      },

      keys: {
        goto: 71 // 'g'
      }
    });

  };

  // handle keyboard shortcuts
  $(document).keydown(function(e) {

    /* <ctrl> + <shift> */
    if (e.ctrlKey && (e.which === 16) ) {
      console.log( "You pressed Ctrl + Shift" );
      togglePresentationMode();
    }

  });

    // load deck.js
    appendStyleSheet("/theme/deck.css");
    $.getScript("/theme/deck.js", function(){

    // render the presentaton
    renderPresentation();

      // register a on change listener
      if (typeof(autoupdate) === 'object' && typeof(autoupdate.onchange) === 'function') {
          autoupdate.onchange(
              "Render Presentation",
              function() {
                  renderPresentation();
              }
          );
      }

    });


});
`


<|start_filename|>common/shutdown/shutdown.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package shutdown

import (
	"fmt"
)

var (
	callbacks = make([]func() error, 0)
)

func Register(callback func() error) {
	callbacks = append(callbacks, callback)
}

func Shutdown() {

	for _, callback := range callbacks {
		err := callback()
		if err != nil {
			fmt.Println(err.Error())
		}
	}

}


<|start_filename|>web/view/viewmodel/opensearchdescription.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type OpenSearchDescription struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	FavIconURL  string `json:"favIconURL"`
	SearchURL   string `json:"searchURL"`
	Tags        string `json:"tags"`
}


<|start_filename|>web/handlers/logging.go<|end_filename|>
package handlers

import (
	gorillahandlers "github.com/gorilla/handlers"
	"net/http"
	"os"
)

func LogRequests(baseHandler http.Handler) http.Handler {
	return gorillahandlers.LoggingHandler(os.Stdout, baseHandler)
}


<|start_filename|>common/logger/loglevel/loglevel.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package loglevel

import (
	"strings"
)

type LogLevel byte

const (
	Off LogLevel = iota
	Debug
	Info
	Statistics
	Warn
	Error
	Fatal
)

func (logLevel LogLevel) String() string {
	switch logLevel {

	case Debug:
		return "Debug"

	case Info:
		return "Info"

	case Statistics:
		return "Statistics"

	case Warn:
		return "Warn"

	case Error:
		return "Error"

	case Fatal:
		return "Fatal"

	case Off:
		return "Off"

	default:
		return "Off"

	}

	panic("Unreachable")
}

func FromString(levelString string) LogLevel {

	switch strings.ToLower(strings.TrimSpace(levelString)) {

	case "debug":
		return Debug

	case "info":
		return Info

	case "statistics":
		return Statistics

	case "warn":
		return Warn

	case "error":
		return Error

	case "fatal":
		return Fatal

	case "off":
		return Off

	default:
		return Info

	}

	panic("Unreachable")
}


<|start_filename|>vendor/github.com/jbarham/go-cdb/cdbmake/cdbmake.go<|end_filename|>
package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/jbarham/go-cdb"
	"io/ioutil"
	"log"
	"os"
	"path"
)

func exitOnErr(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func usage() {
	fmt.Fprint(os.Stderr, "usage: cdbmake f [ftmp]\n")
	os.Exit(2)
}

func main() {
	var tmp *os.File
	var err error

	flag.Parse()
	args := flag.Args()
	if len(args) == 1 {
		dir, _ := path.Split(args[0])
		tmp, err = ioutil.TempFile(dir, "")
		exitOnErr(err)
	} else if len(args) == 2 {
		tmp, err = os.OpenFile(args[1], os.O_RDWR|os.O_CREATE, 0644)
		exitOnErr(err)
	} else {
		usage()
	}

	fname := args[0]
	tmpname := tmp.Name()

	exitOnErr(cdb.Make(tmp, bufio.NewReader(os.Stdin)))
	exitOnErr(tmp.Sync())
	exitOnErr(tmp.Close())
	exitOnErr(os.Rename(tmpname, fname))
}


<|start_filename|>services/parser/util.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package parser

import (
	"bufio"
	"io"
)

// readLine returns a single line (without the ending \n)
// from the input buffered reader.
// An error is returned iff there is an error with the
// buffered reader.
func readLine(bufferedReader *bufio.Reader) (string, error) {
	var (
		isPrefix bool  = true
		err      error = nil
		line, ln []byte
	)

	for isPrefix && err == nil {
		line, isPrefix, err = bufferedReader.ReadLine()
		ln = append(ln, line...)
	}

	return string(ln), err
}

// Get all lines of a given file
func getLines(inFile io.Reader) []string {

	lines := make([]string, 0, 10)
	bufferedReader := bufio.NewReader(inFile)
	line, err := readLine(bufferedReader)
	for err == nil {
		lines = append(lines, line)
		line, err = readLine(bufferedReader)
	}

	return lines
}


<|start_filename|>Makefile<|end_filename|>
build:
	go build -o bin/files/allmark ./cli

install:
	go build -o bin/files/allmark ./cli

test:
	go test ./cli ./common/... ./dataaccess/... ./model/... ./services/... ./web/...

crosscompile:
	GOOS=linux GOARCH=amd64 go build -o bin/files/allmark_linux_amd64 ./cli
	GOOS=linux GOARCH=arm GOARM=5 go build -o bin/files/allmark_linux_arm_5 ./cli
	GOOS=linux GOARCH=arm GOARM=6 go build -o bin/files/allmark_linux_arm_6 ./cli
	GOOS=linux GOARCH=arm GOARM=7 go build -o bin/files/allmark_linux_arm_7 ./cli
	GOOS=darwin GOARCH=amd64 go build -o bin/files/allmark_darwin_amd64 ./cli
	GOOS=windows GOARCH=amd64 go build -o bin/files/allmark_windows_amd64 ./cli


<|start_filename|>web/view/themes/theme.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themes

func GetTheme() *Theme {
	return defaultTheme
}

type Theme struct {
	Name  string
	Files []*ThemeFile
}

// Get the theme file that matches the specified uri (e.g. "favicon.ico"); returns nil if the theme file was not found.
func (theme *Theme) Get(uri string) *ThemeFile {
	for _, themeFile := range theme.Files {
		if themeFile.Path() == uri {
			return themeFile
		}
	}

	return nil
}

func (theme *Theme) StoreOnDisc(baseFolder string) (success bool, err error) {
	for _, file := range theme.Files {
		if ok, err := file.StoreOnDisc(baseFolder); !ok {
			return false, err
		}
	}

	return true, nil
}


<|start_filename|>web/view/viewmodel/model.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

import (
	"sort"
)

type Model struct {
	Base

	Content  string `json:"content"`
	Markdown string `json:"markdown"`

	Publisher Publisher `json:"publisher"`
	Author    Author    `json:"author"`

	Children []Base `json:"children"`

	ToplevelNavigation   ToplevelNavigation   `json:"toplevelNavigation"`
	BreadcrumbNavigation BreadcrumbNavigation `json:"breadcrumbNavigation"`
	ItemNavigation       ItemNavigation       `json:"itemNavigation"`

	Tags     []Tag    `json:"tags"`
	TagCloud TagCloud `json:"tagCloud"`

	Files  []File  `json:"files"`
	Images []Image `json:"images"`

	GeoLocation GeoLocation `json:"geoLocation"`

	Analytics Analytics `json:"-"`

	Hash string `json:"hash"`

	IsRepositoryItem bool
}

func Error(title, content, route string) Model {
	return Model{
		Base: Base{
			Level:   0,
			Title:   title,
			Route:   route,
			Type:    "error",
			BaseURL: "/",
		},
		Content: content,
	}
}

type SortModelBy func(model1, model2 Model) bool

func (by SortModelBy) Sort(models []Model) {
	sorter := &modelSorter{
		models: models,
		by:     by,
	}

	sort.Sort(sorter)
}

type modelSorter struct {
	models []Model
	by     SortModelBy
}

func (sorter *modelSorter) Len() int {
	return len(sorter.models)
}

func (sorter *modelSorter) Swap(i, j int) {
	sorter.models[i], sorter.models[j] = sorter.models[j], sorter.models[i]
}

func (sorter *modelSorter) Less(i, j int) bool {
	return sorter.by(sorter.models[i], sorter.models[j])
}


<|start_filename|>web/view/viewmodel/robotstxt.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

// RobotsTxtDisallow is the definition of disallow-section of a robots.txt
type RobotsTxtDisallow struct {
	UserAgent string
	Paths     []string
}

// RobotsTxt represents the content of a robots.txt file
type RobotsTxt struct {
	Disallows  []RobotsTxtDisallow
	SitemapURL string
}


<|start_filename|>web/webpaths/util_test.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package webpaths

import (
	"testing"
)

func Test_IsAbsoluteURI_ParameterIsRelativeURI_ResultIsFalse(t *testing.T) {
	// arrange
	input := "/yadayada.html"
	expected := false

	// act
	result := IsAbsoluteURI(input)

	// assert
	if result != expected {
		t.Errorf("The result for IsAbsoluteURI(%q) should be %v but was %v.", input, expected, result)
	}
}

func Test_IsAbsoluteURI_ParameterIsHTTPURL_ResultIsTrue(t *testing.T) {
	// arrange
	input := "http://example.com/yadayada.html"
	expected := true

	// act
	result := IsAbsoluteURI(input)

	// assert
	if result != expected {
		t.Errorf("The result for IsAbsoluteURI(%q) should be %v but was %v.", input, expected, result)
	}
}

func Test_IsAbsoluteURI_ParameterIsHTTPURL_Uppercase_ResultIsTrue(t *testing.T) {
	// arrange
	input := "HTTP://example.com/yadayada.html"
	expected := true

	// act
	result := IsAbsoluteURI(input)

	// assert
	if result != expected {
		t.Errorf("The result for IsAbsoluteURI(%q) should be %v but was %v.", input, expected, result)
	}
}

func Test_IsAbsoluteURI_ParameterIsHTTPsURL_ResultIsTrue(t *testing.T) {
	// arrange
	input := "https://example.com/yadayada.html"
	expected := true

	// act
	result := IsAbsoluteURI(input)

	// assert
	if result != expected {
		t.Errorf("The result for IsAbsoluteURI(%q) should be %v but was %v.", input, expected, result)
	}
}

func Test_IsAbsoluteURI_ParametersAreAbsoluteURLs_ResultIsTrue(t *testing.T) {
	// arrange
	inputs := []string{
		"ftp://example.com",
		"sftp://example.com",
		"ssh://example.com",
		"bitcoin:example.com",
		"mailto:<EMAIL>",
	}
	expected := true

	for _, input := range inputs {
		// act
		result := IsAbsoluteURI(input)

		// assert
		if result != expected {
			t.Errorf("The result for IsAbsoluteURI(%q) should be %v but was %v.", input, expected, result)
		}
	}
}


<|start_filename|>web/view/viewmodel/publisher.go<|end_filename|>
// Copyright 2013 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type Publisher struct {
	Name  string `json:"name"`
	Email string `json:"email"`
	URL   string `json:"url"`

	GooglePlusHandle string `json:"googlePlusHandle"`
	TwitterHandle    string `json:"twitterHandle"`
	FacebookHandle   string `json:"facebookHandle"`
}


<|start_filename|>web/view/viewmodel/search.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

type Search struct {
	Model
	Results SearchResults
}

type SearchResults struct {
	Query   string         `json:"query"`
	Results []SearchResult `json:"results"`

	Page         int `json:"page"`
	ItemsPerPage int `json:"itemPerPage"`

	StartIndex       int `json:"startIndex"`
	ResultCount      int `json:"resultCount"`
	TotalResultCount int `json:"totalResultCount"`
}

type SearchResult struct {
	Index int `json:"index"`

	Title       string `json:"title"`
	Description string `json:"description"`
	Route       string `json:"route"`
	Path        string `json:"path"`
}


<|start_filename|>vendor/github.com/arnoSCC/fulltext/testdata/searchresults.html<|end_filename|>
<html>
<head>
	<title>Search Results</title>
</head>
<body>

<form method="GET" action="/searchresults.html" style="float:right;display:block;width:300px">
	Search Again:
	<input type="text" name="q" value="{{.q}}"/> <input type="submit" value="Search"/>
</form>

<div>

<h1>Search Results:</h1>

<div><a href="/">[return home]</a><br/>&nbsp;</div>

{{range .sr.Items}}

<div>
	<a href="/{{printf "%s" .Id}}">{{printf "%s" .StoreValue}}</a> (Score: {{printf "%d" .Score}})
	<br/>&nbsp;
</div>

{{else}}

No results found.
Now is the winter of our discontent.

{{end}}

</div>


</body>
</html>


<|start_filename|>files/design/logo/ICO/bundle.cmd<|end_filename|>
icobundl -o allmark.ico allmark-16x16.ico allmark-32x32.ico allmark-48x48.ico allmark-64x64.ico

<|start_filename|>web/header/header.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package header

import (
	"fmt"
	"net/http"
)

const (
	CONTENTTYPE_HTML = "text/html; charset=utf-8"
	CONTENTTYPE_TEXT = "text/plain; charset=utf-8"
	CONTENTTYPE_XML  = "text/xml; charset=utf-8"
	CONTENTTYPE_JSON = "application/json; charset=utf-8"
	CONTENTTYPE_DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=utf-8"
)

func Cache(w http.ResponseWriter, seconds int) {
	w.Header().Add("Cache-Control", fmt.Sprintf("public, max-age=%d", seconds))
}

func ETag(w http.ResponseWriter, hash string) {
	if hash == "" {
		return
	}

	w.Header().Add("ETag", hash)
}

func NoCache(w http.ResponseWriter) {
	w.Header().Add("Cache-Control", "no-cache")
}

func ContentType(w http.ResponseWriter, contentType string) {
	if contentType == "" {
		return
	}

	w.Header().Set("Content-Type", contentType)
}

func VaryAcceptEncoding(w http.ResponseWriter) {
	w.Header().Set("Vary", "Accept-Encoding")
}

// configurable header writer
type configurableHeaderWriter struct {
	cacheDuration int
}

func (headerWriter configurableHeaderWriter) Write(w http.ResponseWriter, contentType string) {
	Cache(w, headerWriter.cacheDuration)
	ContentType(w, contentType)
	VaryAcceptEncoding(w)
}

// no-cache header writer
type noCacheHeaderWriter struct {
}

func (headerWriter noCacheHeaderWriter) Write(w http.ResponseWriter, contentType string) {
	NoCache(w)
	ContentType(w, contentType)
	VaryAcceptEncoding(w)
}

type HeaderWriter interface {
	Write(w http.ResponseWriter, contentType string)
}

// HeaderWriter factory
func NewHeaderWriterFactory(reindexIntervalInSeconds int) WriterFactory {

	// default cache durations
	cacheDurationDynamic := 86400   // 1 day
	cacheDurationStatic := 31536000 // 1 year

	reindexingIsEnabled := reindexIntervalInSeconds > 0
	if reindexingIsEnabled {

		// cache durations based on the reindex interval
		cacheDurationDynamic = reindexIntervalInSeconds / 2
		cacheDurationStatic = reindexIntervalInSeconds / 2

	}

	// create the header writers
	static := configurableHeaderWriter{cacheDurationStatic}
	dynamic := configurableHeaderWriter{cacheDurationDynamic}
	noCache := noCacheHeaderWriter{}

	// create the factory with the given parameters
	return WriterFactory{
		static,
		dynamic,
		noCache,
	}

}

type WriterFactory struct {
	static  HeaderWriter
	dynamic HeaderWriter
	noCache HeaderWriter
}

func (writerFactory *WriterFactory) Static() HeaderWriter {
	return writerFactory.static
}

func (writerFactory *WriterFactory) Dynamic() HeaderWriter {
	return writerFactory.dynamic
}

func (writerFactory *WriterFactory) NoCache() HeaderWriter {
	return writerFactory.noCache
}


<|start_filename|>web/orchestrator/util_test.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package orchestrator

import (
	"testing"
	"time"
)

func Test_getFormattedDate_DateIsZero_ReturnsEmptyString(t *testing.T) {
	// arrange
	inputDate := time.Time{}
	expected := ""

	// act
	result := getFormattedDate(inputDate)

	// assert
	if result != expected {
		t.Errorf("The result of getFormattedDate(%q) should be %q but was %q.", inputDate, expected, result)
	}
}


<|start_filename|>web/view/viewmodel/tag.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package viewmodel

import (
	"sort"
)

type Tags struct {
	Model
	Tags []Tag
}

type Tag struct {
	Name     string  `json:"name"`
	Anchor   string  `json:"anchor"`
	Route    string  `json:"route"`
	Children []Model `json:"children"`
}

type SortTagBy func(tag1, tag2 Tag) bool

func (by SortTagBy) Sort(tags []Tag) {
	sorter := &tagSorter{
		tags: tags,
		by:   by,
	}

	sort.Sort(sorter)
}

type tagSorter struct {
	tags []Tag
	by   SortTagBy
}

func (sorter *tagSorter) Len() int {
	return len(sorter.tags)
}

func (sorter *tagSorter) Swap(i, j int) {
	sorter.tags[i], sorter.tags[j] = sorter.tags[j], sorter.tags[i]
}

func (sorter *tagSorter) Less(i, j int) bool {
	return sorter.by(sorter.tags[i], sorter.tags[j])
}


<|start_filename|>common/route/route_child_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package route

import (
	"testing"
)

func Test_IsChildOf_ParentRouteIsEmpty_ResultIsTrue(t *testing.T) {
	// arrange
	parent := NewFromRequest("/")
	child := NewFromRequest("/documents/Test-1")

	// act
	result := child.IsChildOf(parent)

	// assert
	if !result {
		t.Errorf("%q is a direct child of %q. The result should be true but was %t.", child, parent, result)
	}
}

func Test_IsChildOf_RouteIsFirstLevelChild_ResultIsTrue(t *testing.T) {
	// arrange
	parent := NewFromRequest("/documents/Collection")
	child := NewFromRequest("/documents/Collection/Level-1")

	// act
	result := child.IsChildOf(parent)

	// assert
	if !result {
		t.Errorf("%q is a 1st level child of %q. The result should be true but was %t.", child, parent, result)
	}
}

func Test_IsChildOf_RouteIsSecondLevelChild_ResultIsTrue(t *testing.T) {
	// arrange
	parent := NewFromRequest("/documents/Collection")
	child := NewFromRequest("/documents/Collection/Level-1/Level-2")

	// act
	result := child.IsChildOf(parent)

	// assert
	if !result {
		t.Errorf("%q is a 2nd level child of %q. The result should be true but was %t.", child, parent, result)
	}
}

func Test_IsChildOf_RouteIsNotAChild_ResultIsFalse(t *testing.T) {
	// arrange
	parent := NewFromRequest("/documents/Collection")
	child := NewFromRequest("/pictures/Test-1")

	// act
	result := child.IsChildOf(parent)

	// assert
	if result {
		t.Errorf("%q is not a child of %q. The result should be false but was %t.", child, parent, result)
	}
}


<|start_filename|>model/metadata.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package model

import (
	"time"
)

// MetaData defines meta-attributes of repository items.
type MetaData struct {
	Language         string
	CreationDate     time.Time
	LastModifiedDate time.Time
	Tags             []string
	Aliases          []string
	Author           string
	GeoInformation   GeoInformation
}

// NewMetaData creates a new instance of the the MetaData struct.
func NewMetaData() *MetaData {
	return &MetaData{}
}


<|start_filename|>web/view/themes/themefiles/autoupdatejs.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const AutoupdateJs = `var Autoupdate = (function () {
    function Autoupdate() { }

    var self = this;

    /**
     * Get the currently opened web route
     * @return string The currently opened web route (e.g. "documents/Sample-Document")
     */
    var getCurrentRoute = function() {
        var url = document.location.pathname;

        // remove leading slash
        var leadingSlash = /^\//;
        url = url.replace(leadingSlash, "");

        return url;
    };

    /**
     * Get the URL for the web socket connection
     * @return string The url for the web socket connection (e.g. "ws://example.com:8080/documents/Sample-Document.ws")
     */
    var getWebSocketURL = function() {
        var routeParameter = getCurrentRoute();
        var host = document.location.host;
        var protocol = "ws";
        if (location.protocol === 'https:') {
            protocol = "wss";
        }

        if (routeParameter === "") {
            return protocol + "://" + host + "/" + "ws";
        }

        return protocol + "://" + host + "/" + routeParameter + ".ws";
    };

    /**
     * Execute all on change callbacks
     */
    var executeOnChangeCallbacks = function() {
        if (typeof(self.changeCallbacks) !== 'object') {
            return;
        }

        for (var callbackName in self.changeCallbacks) {
            console.log("Executing on change callback: " + callbackName);
            self.changeCallbacks[callbackName]();
        }
    };

    /**
     * cleanupSnippetCode removes newline characters from the given snippet code
     * @param string snippetCode Code of a snippet that might contain newline characters
     * @return string
     */
    var cleanupSnippetCode = function(snippetCode) {
      return snippetCode.replace('\\n', "");
    };

    /**
     * getCSSSelectorFromSnippetName returns the proper CSS selector for the snippet with the given name.
     * @param string snippetName The name of a snippet (e.g. "toplevelnavigation")
     * @return string A CSS selector that matches the snippet with the given snippetName.
     */
    var getCSSSelectorFromSnippetName = function(snippetName) {
      switch(snippetName) {
        case "aliases":
          return "body > article > section.aliases";

        case "tags":
          return "body > article > section.tags";

        case "publisher":
          return "body > article > section.publisher";

        case "toplevelnavigation":
          return "body>nav.toplevel";

        case "breadcrumbnavigation":
          return "body>nav.breadcrumb";

        case "itemnavigation":
          return "aside.sidebar>nav.navigation";

        case "children":
          return "aside.sidebar>.children";

        case "tagcloud":
          return "aside.sidebar>.tagcloud";

        default:
          return "#" + snippetName;
      }
    };

    /**
     * Connect to the server
     * @param string webSocketURL The url of the web-socket to connect to
     */
    var connect = function(webSocketURL) {
        var reconnectionTimeInSeconds = 3;
        var connection = new WebSocket(webSocketURL);

        connection.onclose = function(evt) {
            console.log("Connection closed. Trying to reconnect in " + reconnectionTimeInSeconds + " seconds.");

            setTimeout(function() {

                console.log("Reconnecting");
                connect(webSocketURL);

            }, (reconnectionTimeInSeconds * 1000));
        };

        connection.onopen = function() {
            console.log("Connection established.")
        };

        connection.onmessage = function(evt) {

            // validate event data
            if (typeof(evt) !== 'object' || typeof(evt.data) !== 'string') {
                console.log("Invalid data from server.");
                return;
            }

            // unwrap the message
            message = JSON.parse(evt.data);

            // check if all required fields are present
            if (message === null || typeof(message) !== 'object' || typeof(message.route) !== 'string' || message.model === null || typeof(message.model) !== 'object') {
                console.log("Invalid response format.", message);
                return;
            }

            // check the model structure
            var model = message.model;
            if (typeof(model.content) !== 'string' || typeof(model.description) !== 'string' || typeof(model.title) !== 'string') {
                console.log("Cannot update the view with the given model object. Missing some required fields.", model);
                return;
            }

            // update the title
            $('title').html(model.title);
            $('.title').html(model.title);

            // update the description
            $('.description').html(model.description);

            // update the content
            $('.content').html(model.content);

            // on-change handlers
            executeOnChangeCallbacks();

            // snippets
            if (typeof(model.snippets) !== 'object') {
              return;
            }

            for (var snippetName in model.snippets) {

              // the new snippet content
              var snippetContent = cleanupSnippetCode(model.snippets[snippetName]);

              // get the CSS selector of the snippet
              var cssSelector = getCSSSelectorFromSnippetName(snippetName);

              // check if the snippet exists
              var elementExists = $(cssSelector).length > 0;
              if (elementExists == false) {
                continue;
              }

              // replace the existing snippet
              $(cssSelector).replaceWith(snippetContent);
            }

        };
    };

    Autoupdate.prototype.start = function () {

        // check if websockets are supported
        if(!window["WebSocket"]) {
            console.log("Your browser does not support WebSockets.");
            return;
        }

        // establish the connection
        connect(getWebSocketURL());
    };

    Autoupdate.prototype.onchange = function(name, callback) {
        if (typeof(self.changeCallbacks) !== 'object') {
            self.changeCallbacks = {};
        }

        self.changeCallbacks[name] = callback;
    };

    return Autoupdate;
})();

autoupdate = new Autoupdate();
autoupdate.start();
`


<|start_filename|>common/route/route.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package route

import (
	"fmt"
	"regexp"
	"strings"
)

var (
	regexpWhitespacePattern          = regexp.MustCompile(`\s+`)
	regexpBackSlashPattern           = regexp.MustCompile(`\\+`)
	regexpdoubleForwardSlashPattern  = regexp.MustCompile(`/+`)
	regexpForbiddenCharactersPattern = regexp.MustCompile(`[&%§\)\(}{\]\["|]`)
)

type Route struct {
	value         string
	originalValue string
	isFileRoute   bool
}

// Creates a new route from the given base directory (e.g. "/home/user/repository") and item path (e.g. "/home/user/repository/documents/sample/document.md") and strips the file name from the route.
func NewFromItemPath(baseDirectory, itemPath string) Route {

	// normalize the base path
	normalizedBasePath := normalize(baseDirectory)

	// normalize the item path
	normalizedItemPath := normalize(itemPath)

	// return a root if both paths are the same
	if normalizedItemPath == normalizedBasePath {
		return New()
	}

	// prepare the route value:
	// strip the repository path from the item path
	routeValue := strings.Replace(normalizedItemPath, normalizedBasePath, "", 1)

	// strip the file name
	routeValue = routeValue[:strings.LastIndex(routeValue, "/")]

	// trim leading slashes
	routeValue = strings.TrimLeft(routeValue, "/")

	return Route{
		value:         toURL(routeValue),
		originalValue: routeValue,
		isFileRoute:   true,
	}
}

// Creates a new route from the given base directory (e.g. "/home/user/repository") and item directory (e.g. "/home/user/repository/documents/sample").
func NewFromItemDirectory(baseDirectory, itemDirectory string) Route {

	// normalize the base path
	normalizedBasePath := normalize(baseDirectory)

	// normalize the item path
	normalizedItemPath := normalize(itemDirectory)

	// return a root if both paths are the same
	if normalizedItemPath == normalizedBasePath {
		return New()
	}

	// prepare the route value:
	// strip the repository path from the item path
	routeValue := strings.Replace(normalizedItemPath, normalizedBasePath, "", 1)

	// trim leading slashes
	routeValue = strings.TrimLeft(routeValue, "/")

	return Route{
		value:         toURL(routeValue),
		originalValue: routeValue,
		isFileRoute:   false,
	}
}

// Creates a new route from the given base directory (e.g. "/home/user/repository") and item path (e.g. "/home/user/repository/documents/sample/files/image.jpg").
func NewFromFilePath(baseDirectory, itemPath string) Route {

	// normalize the base path
	normalizedBasePath := normalize(baseDirectory)

	// normalize the item path
	normalizedItemPath := normalize(itemPath)

	// return a root if both paths are the same
	if normalizedItemPath == normalizedBasePath {
		return New()
	}

	// prepare the route value:
	// strip the repository path from the item path
	routeValue := strings.Replace(normalizedItemPath, normalizedBasePath, "", 1)

	// trim leading slashes
	routeValue = strings.TrimLeft(routeValue, "/")

	return Route{
		value:         toURL(routeValue),
		originalValue: routeValue,
		isFileRoute:   true,
	}
}

// Create a new route from the given request path.
func NewFromRequest(requestPath string) Route {

	// normalize the request path
	routeValue := normalize(requestPath)

	return Route{
		value:         toURL(routeValue),
		originalValue: routeValue,
	}
}

// Create an empty route.
func New() Route {

	// normalize the request path
	routeValue := normalize("")

	return Route{
		value:         toURL(routeValue),
		originalValue: routeValue,
		isFileRoute:   false,
	}
}

// combines two routes
func Combine(route1, route2 Route) Route {
	return NewFromRequest(route1.OriginalValue() + "/" + route2.OriginalValue())
}

func Intersect(baseRoute, subRoute Route) Route {

	// abort if the base route is empty
	if baseRoute.IsEmpty() {
		return baseRoute
	}

	// abort if the subroute is empty
	if subRoute.IsEmpty() {
		return baseRoute
	}

	baseDirectory := baseRoute.OriginalValue()
	itemDirectory := subRoute.OriginalValue()

	// normalize the base path
	normalizedBasePath := normalize(baseDirectory)

	// normalize the item path
	normalizedItemPath := normalize(itemDirectory)

	// return the base if the sub-route is the same
	if normalizedItemPath == normalizedBasePath {
		return baseRoute
	}

	// prepare the route value:
	// strip the repository path from the item path
	routeValue := strings.Replace(normalizedItemPath, normalizedBasePath, "", 1)

	// trim leading slashes
	routeValue = strings.TrimLeft(routeValue, "/")

	return Route{
		value:         toURL(routeValue),
		originalValue: routeValue,
	}
}

func (route Route) String() string {
	return strings.Join(route.Components(), " > ")
}

// Equals compares the current route with the supplied route. Returns true if the routes are alike; otherwise false.
func (route Route) Equals(otherRoute Route) bool {
	return route.String() == otherRoute.String()
}

func (route Route) OriginalValue() string {
	return route.originalValue
}

func (route Route) Components() []string {
	return strings.Split(route.OriginalValue(), "/")
}

func (route Route) Value() string {
	return route.value
}

func (route Route) IsEmpty() bool {
	return len(route.value) == 0
}

func (route Route) IsFileRoute() bool {
	return route.isFileRoute
}

func (route Route) Path() string {
	lastSlashPosition := strings.LastIndex(route.originalValue, "/")
	if lastSlashPosition == -1 {
		return route.originalValue
	}

	return strings.TrimSuffix(route.originalValue[:lastSlashPosition], "/")
}

func (route Route) FirstComponentName() string {

	if route.Level() == 0 {
		return ""
	}

	// handle root-level routes
	if route.Level() == 1 {

		if route.IsFileRoute() {
			return ""
		}

		return route.originalValue
	}

	firstSlashPosition := strings.Index(route.originalValue, "/")
	return strings.TrimSuffix(route.originalValue[:firstSlashPosition], "/")
}

func (route Route) LastComponentName() string {
	lastSlashPosition := strings.LastIndex(route.originalValue, "/")
	if lastSlashPosition == -1 {
		return route.originalValue
	}

	return strings.TrimPrefix(route.originalValue[lastSlashPosition:], "/")
}

func (route Route) Level() int {

	// empty routes have the level 0
	if route.value == "" {
		return 0
	}

	// routes without a slash are 1st level
	if !strings.Contains(route.value, "/") {
		return 1
	}

	// routes with slashes have a level equal to the number of slashes
	return strings.Count(route.value, "/") + 1
}

func (route Route) SubRoute(level int) (Route, error) {

	// root level
	if level == 0 {
		return NewFromRequest(""), nil
	}

	// same level
	if level == route.Level() {
		return route, nil
	}

	// split path into components
	components := strings.Split(route.value, "/")

	// abort if the requested level is out of range
	if level > len(components)-1 {
		return Route{}, fmt.Errorf("The route %q does nof a have a sub-route with the level %d.", route, level)
	}

	// assemble the sub route
	subset := components[0:level]
	subRoutePath := strings.Join(subset, "/")

	subRoute := NewFromRequest(subRoutePath)
	return subRoute, nil
}

func (route Route) IsMatch(path string) bool {
	cleanedRoute := strings.ToLower(route.Value())
	normalizedPath := strings.ToLower(toURL(normalize(path)))

	// check if the current route ends with the supplied path
	routeEndsWithSpecifiedPath := strings.HasSuffix(cleanedRoute, normalizedPath)

	return routeEndsWithSpecifiedPath
}

func (route Route) Parent() (parent Route, exists bool) {

	if route.IsEmpty() {
		return parent, false
	}

	routeValue := route.Value()

	// if there is no slash, the parent must be the root
	if !strings.Contains(routeValue, "/") {
		return New(), true
	}

	positionOfLastSlash := strings.LastIndex(routeValue, "/")
	parentRouteValue := routeValue[:positionOfLastSlash]

	parentRoute := NewFromRequest(parentRouteValue)
	return parentRoute, true
}

// Check if the the current route is direct parent for the supplied (child) route.
func (parent Route) IsParentOf(child Route) bool {
	parentRoute := parent.Value()
	childRoute := child.Value()

	// the current route cannot be a parent for the supplied (child) route if the parent route length greater or equal than the child route length.
	if len(parentRoute) >= len(childRoute) {
		return false
	}

	// if the parent route is not the start of the child route it cannot be its parent
	if !strings.HasPrefix(childRoute, parentRoute) {
		return false
	}

	// if there is more than one slash in the relative child route, the child is not a direct descendant of the parent route
	relativeChildRoute := strings.TrimLeft(strings.Replace(childRoute, parentRoute, "", 1), "/")
	if strings.Count(relativeChildRoute, "/") > 0 {
		return false
	}

	// the child is a direct desecendant of the parent
	return true

}

// Check if the current route is a child of the supplied (parent) route.
func (child Route) IsChildOf(parent Route) bool {
	childRoute := child.Value()
	parentRoute := parent.Value()

	// the current route cannot be a child of the supplied (parent) route if the child route length less or equal than the parent route length.
	if len(childRoute) <= len(parentRoute) {
		return false
	}

	// if the child route does not start with the parent route it cannot be a child
	if !strings.HasPrefix(childRoute, parentRoute) {
		return false
	}

	return true
}

// Returns a normalized version of the supplied path
func normalize(path string) string {

	// trim spaces
	path = strings.TrimSpace(path)

	// check if the path is empty
	if path == "" {
		return ""
	}

	path = fromURL(path)

	// replace all forbidden characters
	path = regexpForbiddenCharactersPattern.ReplaceAllString(path, "")

	// replace all backslashes with a (single) forward slash
	path = regexpBackSlashPattern.ReplaceAllString(path, "/")

	// replace multiple forward slashes with a single forward slash
	path = regexpdoubleForwardSlashPattern.ReplaceAllString(path, "/")

	// remove leading slashes
	path = strings.TrimLeft(path, "/")

	// remove trailing slashes
	path = strings.TrimRight(path, "/")

	// replace duplicate spaces
	path = regexpWhitespacePattern.ReplaceAllString(path, " ")

	return path
}

// Returns an "url-safe" version of the supplied path
func toURL(path string) string {

	// replace duplicate spaces with a (single) url safe character
	path = strings.Replace(path, " ", "+", -1)

	// replace brackets
	path = strings.Replace(path, "(", "%28", -1)
	path = strings.Replace(path, ")", "%29", -1)

	return path
}

// Returns an "url-safe" version of the supplied path
func fromURL(path string) string {

	// replace duplicate spaces with a (single) url safe character
	path = strings.Replace(path, "+", " ", -1)

	// replace brackets
	path = strings.Replace(path, "%28", "(", -1)
	path = strings.Replace(path, "%29", ")", -1)

	return path
}


<|start_filename|>common/util/hashutil/hash_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package hashutil

import (
	"bytes"
	"testing"
)

func Test_GetHash_ResultIsNotEmpty(t *testing.T) {

	// arrange
	inputString := "La di da"
	input := bytes.NewReader([]byte(inputString))

	// act
	result, _ := GetHash(input)

	// assert
	if result == "" {
		t.Errorf("The GetHash function should be able to calculate a hash for the supplied text %q, but the result was empty.", inputString)
	}
}

func Test_GetHash_CorrectSHA1IsReturned(t *testing.T) {

	// arrange
	inputString := "La di da"
	input := bytes.NewReader([]byte(inputString))
	expectedResult := "8-18889A25"

	// act
	result, _ := GetHash(input)

	// assert
	if result != expectedResult {
		t.Errorf("The GetHash function should return the correct hash for the string %q. (Expected: %q, Actual: %q)", inputString, expectedResult, result)
	}
}


<|start_filename|>vendor/github.com/spf13/afero/fs_test.go<|end_filename|>
// Copyright © 2014 <NAME> <<EMAIL>>.
// Copyright 2009 The Go Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package afero

import (
	"bytes"
	"io"
	"io/ioutil"
	"os"
	"path"
	"runtime"
	"strings"
	"syscall"
	"testing"
)

var dot = []string{
	"fs.go",
	"fs_test.go",
	"httpFs.go",
	"memfile.go",
	"memmap.go",
}

var testDir = "/tmp/fun"
var testName = "test.txt"
var Fss = []Fs{&MemMapFs{}, &OsFs{}}

//var Fss = []Fs{OsFs{}}

//Read with length 0 should not return EOF.
func TestRead0(t *testing.T) {
	for _, fs := range Fss {
		path := testDir + "/" + testName
		if err := fs.MkdirAll(testDir, 0777); err != nil {
			t.Fatal(fs.Name(), "unable to create dir", err)
		}

		f, err := fs.Create(path)
		if err != nil {
			t.Fatal(fs.Name(), "create failed:", err)
		}
		defer f.Close()
		f.WriteString("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")

		b := make([]byte, 0)
		n, err := f.Read(b)
		if n != 0 || err != nil {
			t.Errorf("%v: Read(0) = %d, %v, want 0, nil", fs.Name(), n, err)
		}
		f.Seek(0, 0)
		b = make([]byte, 100)
		n, err = f.Read(b)
		if n <= 0 || err != nil {
			t.Errorf("%v: Read(100) = %d, %v, want >0, nil", fs.Name(), n, err)
		}
	}
}

func TestMemFileRead(t *testing.T) {
	f := MemFileCreate("testfile")
	f.WriteString("abcd")
	f.Seek(0, 0)
	b := make([]byte, 8)
	n, err := f.Read(b)
	if n != 4 {
		t.Errorf("didn't read all bytes: %v %v %v", n, err, b)
	}
	if err != nil {
		t.Errorf("err is not nil: %v %v %v", n, err, b)
	}
	n, err = f.Read(b)
	if n != 0 {
		t.Errorf("read more bytes: %v %v %v", n, err, b)
	}
	if err != io.EOF {
		t.Errorf("error is not EOF: %v %v %v", n, err, b)
	}
}

func TestRename(t *testing.T) {
	for _, fs := range Fss {
		from, to := testDir+"/renamefrom", testDir+"/renameto"
		fs.Remove(to)              // Just in case.
		fs.MkdirAll(testDir, 0777) // Just in case.
		file, err := fs.Create(from)
		if err != nil {
			t.Fatalf("open %q failed: %v", to, err)
		}
		if err = file.Close(); err != nil {
			t.Errorf("close %q failed: %v", to, err)
		}
		err = fs.Rename(from, to)
		if err != nil {
			t.Fatalf("rename %q, %q failed: %v", to, from, err)
		}
		defer fs.Remove(to)
		_, err = fs.Stat(to)
		if err != nil {
			t.Errorf("stat %q failed: %v", to, err)
		}
	}
}

func TestTruncate(t *testing.T) {
	for _, fs := range Fss {
		f := newFile("TestTruncate", fs, t)
		defer fs.Remove(f.Name())
		defer f.Close()

		checkSize(t, f, 0)
		f.Write([]byte("hello, world\n"))
		checkSize(t, f, 13)
		f.Truncate(10)
		checkSize(t, f, 10)
		f.Truncate(1024)
		checkSize(t, f, 1024)
		f.Truncate(0)
		checkSize(t, f, 0)
		_, err := f.Write([]byte("surprise!"))
		if err == nil {
			checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
		}
	}
}

func TestSeek(t *testing.T) {
	for _, fs := range Fss {
		f := newFile("TestSeek", fs, t)
		defer fs.Remove(f.Name())
		defer f.Close()

		const data = "hello, world\n"
		io.WriteString(f, data)

		type test struct {
			in     int64
			whence int
			out    int64
		}
		var tests = []test{
			{0, 1, int64(len(data))},
			{0, 0, 0},
			{5, 0, 5},
			{0, 2, int64(len(data))},
			{0, 0, 0},
			{-1, 2, int64(len(data)) - 1},
			{1 << 33, 0, 1 << 33},
			{1 << 33, 2, 1<<33 + int64(len(data))},
		}
		for i, tt := range tests {
			off, err := f.Seek(tt.in, tt.whence)
			if off != tt.out || err != nil {
				if e, ok := err.(*os.PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 {
					// Reiserfs rejects the big seeks.
					// http://code.google.com/p/go/issues/detail?id=91
					break
				}
				t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
			}
		}
	}
}

func TestReadAt(t *testing.T) {
	for _, fs := range Fss {
		f := newFile("TestReadAt", fs, t)
		defer fs.Remove(f.Name())
		defer f.Close()

		const data = "hello, world\n"
		io.WriteString(f, data)

		b := make([]byte, 5)
		n, err := f.ReadAt(b, 7)
		if err != nil || n != len(b) {
			t.Fatalf("ReadAt 7: %d, %v", n, err)
		}
		if string(b) != "world" {
			t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
		}
	}
}

func TestWriteAt(t *testing.T) {
	for _, fs := range Fss {
		f := newFile("TestWriteAt", fs, t)
		defer fs.Remove(f.Name())
		defer f.Close()

		const data = "hello, world\n"
		io.WriteString(f, data)

		n, err := f.WriteAt([]byte("WORLD"), 7)
		if err != nil || n != 5 {
			t.Fatalf("WriteAt 7: %d, %v", n, err)
		}

		f2, err := fs.Open(f.Name())
		defer f2.Close()
		buf := new(bytes.Buffer)
		buf.ReadFrom(f2)
		b := buf.Bytes()
		if err != nil {
			t.Fatalf("%v: ReadFile %s: %v", fs.Name(), f.Name(), err)
		}
		if string(b) != "hello, WORLD\n" {
			t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n")
		}

	}
}

//func TestReaddirnames(t *testing.T) {
//for _, fs := range Fss {
//testReaddirnames(fs, ".", dot, t)
////testReaddirnames(sysdir.name, fs, sysdir.files, t)
//}
//}

//func TestReaddir(t *testing.T) {
//for _, fs := range Fss {
//testReaddir(fs, ".", dot, t)
////testReaddir(sysdir.name, fs, sysdir.files, t)
//}
//}

func newFile(testName string, fs Fs, t *testing.T) (f File) {
	// Use a local file system, not NFS.
	// On Unix, override $TMPDIR in case the user
	// has it set to an NFS-mounted directory.
	dir := ""
	if runtime.GOOS != "windows" {
		dir = "/tmp"
	}
	fs.MkdirAll(dir, 0777)
	f, err := fs.Create(path.Join(dir, testName))
	if err != nil {
		t.Fatalf("%v: open %s: %s", fs.Name(), testName, err)
	}
	return f
}

func writeFile(t *testing.T, fs Fs, fname string, flag int, text string) string {
	f, err := fs.OpenFile(fname, flag, 0666)
	if err != nil {
		t.Fatalf("Open: %v", err)
	}
	n, err := io.WriteString(f, text)
	if err != nil {
		t.Fatalf("WriteString: %d, %v", n, err)
	}
	f.Close()
	data, err := ioutil.ReadFile(fname)
	if err != nil {
		t.Fatalf("ReadFile: %v", err)
	}
	return string(data)
}

func testReaddirnames(fs Fs, dir string, contents []string, t *testing.T) {
	file, err := fs.Open(dir)
	if err != nil {
		t.Fatalf("open %q failed: %v", dir, err)
	}
	defer file.Close()
	s, err2 := file.Readdirnames(-1)
	if err2 != nil {
		t.Fatalf("readdirnames %q failed: %v", dir, err2)
	}
	for _, m := range contents {
		found := false
		for _, n := range s {
			if n == "." || n == ".." {
				t.Errorf("got %s in directory", n)
			}
			if equal(m, n) {
				if found {
					t.Error("present twice:", m)
				}
				found = true
			}
		}
		if !found {
			t.Error("could not find", m)
		}
	}
}

func testReaddir(fs Fs, dir string, contents []string, t *testing.T) {
	file, err := fs.Open(dir)
	if err != nil {
		t.Fatalf("open %q failed: %v", dir, err)
	}
	defer file.Close()
	s, err2 := file.Readdir(-1)
	if err2 != nil {
		t.Fatalf("readdir %q failed: %v", dir, err2)
	}
	for _, m := range contents {
		found := false
		for _, n := range s {
			if equal(m, n.Name()) {
				if found {
					t.Error("present twice:", m)
				}
				found = true
			}
		}
		if !found {
			t.Error("could not find", m)
		}
	}
}

func equal(name1, name2 string) (r bool) {
	switch runtime.GOOS {
	case "windows":
		r = strings.ToLower(name1) == strings.ToLower(name2)
	default:
		r = name1 == name2
	}
	return
}

func checkSize(t *testing.T, f File, size int64) {
	dir, err := f.Stat()
	if err != nil {
		t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
	}
	if dir.Size() != size {
		t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size)
	}
}


<|start_filename|>common/tree/path_test.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tree

import (
	"testing"
)

func Test_Path_String_EmptyPath_ResultIsDefaultString(t *testing.T) {
	// arrange
	path := Path{}

	// act
	result := path.String()

	// assert
	expected := "<empty-path>"
	if result != expected {
		t.Errorf("The String method of an empty path should return %q but returned %q instead.", expected, result)
	}
}

func Test_Path_String_NonEmptyPath_ResultIsCompoentsConnectedByArrows(t *testing.T) {
	// arrange
	path := Path{"root", "level 1", "level 2"}

	// act
	result := path.String()

	// assert
	expected := "root > level 1 > level 2"
	if result != expected {
		t.Errorf("The String method of the Path should return %q but returned %q instead.", expected, result)
	}
}

func Test_Path_IsEmpty_EmptyPath_ResultIsTrue(t *testing.T) {
	// arrange
	path := Path{}

	// act
	result := path.IsEmpty()

	// assert
	expected := true
	if result != expected {
		t.Errorf("The IsEmpty method of an empty path should return %v but returned %v instead.", expected, result)
	}
}

func Test_Path_IsEmpty_NonEmptyPath_ResultIsFalse(t *testing.T) {
	// arrange
	path := Path{"root", "level 1"}

	// act
	result := path.IsEmpty()

	// assert
	expected := false
	if result != expected {
		t.Errorf("The IsEmpty method of a non-empty path should return %v but returned %v instead.", expected, result)
	}
}

func Test_Path_IsValid_AllValidComponents_ResultIsTrue(t *testing.T) {
	// arrange
	path := Path{"root", "level 1", "öäöölasdalsöä", " dsad&42323", "5666%", "_dasdsadas_dsaasd-dasdas?&"}

	// act
	result, _ := path.IsValid()

	// assert
	expected := true
	if result != expected {
		t.Errorf("The IsValid method of the path %q should return %v but returned %v instead.", path, expected, result)
	}
}

func Test_Path_IsValid_ASingleInvalidComponent_ResultIsFalse(t *testing.T) {
	// arrange
	path := Path{"root", "level 1", "öäöölasdalsöä", " dsad / 42323", "5666%", "_dasdsadas_dsaasd-dasdas?&"}

	// act
	result, _ := path.IsValid()

	// assert
	expected := false
	if result != expected {
		t.Errorf("The IsValid method of the path %q should return %v but returned %v instead.", path, expected, result)
	}
}

func Test_pathToNode_EmptyComponentsSlice_ResultIsNil(t *testing.T) {
	// arrange
	components := []string{}

	// act
	result := pathToNode(components, nil)

	// assert
	if result != nil {
		t.Errorf("An empty component list should not be converted into a node, but the result was %q", result)
	}
}

func Test_pathToNode_NonEmptyComponentsSlice_ResultNotNil(t *testing.T) {
	// arrange
	components := []string{"root", "level 1", "level 2"}

	// act
	result := pathToNode(components, nil)

	// assert
	if result == nil {
		t.Errorf("The components %s should be converted to a node but the result was %q.", components, result)
	}
}

func Test_isValidPathComponent_PlainText_ResultIsTrue(t *testing.T) {
	// arrange
	component := "Sample Component-Näme 38712903 & 3223 dsad_123"

	// act
	result, _ := isValidPathComponent(component)

	// assert
	expected := true
	if result != expected {
		t.Errorf("The component %q is a valid component but but the function returned %v (Expected: %v).", component, result, expected)
	}
}

func Test_isValidPathComponent_EmptyString_ResultIsFalse(t *testing.T) {
	// arrange
	component := ""

	// act
	result, _ := isValidPathComponent(component)

	// assert
	expected := false
	if result != expected {
		t.Errorf("An empty string is not a valid path component but the function returned %v (Expected: %v).", result, expected)
	}
}

func Test_isValidPathComponent_ForwardSlash_ResultIsFalse(t *testing.T) {
	// arrange
	component := "a / test"

	// act
	result, _ := isValidPathComponent(component)

	// assert
	expected := false
	if result != expected {
		t.Errorf("Components with forward slashes are not valid path components but the function returned %v (Expected: %v).", result, expected)
	}
}

func Test_isValidPathComponent_Backslash_ResultIsFalse(t *testing.T) {
	// arrange
	component := `a \ test`

	// act
	result, _ := isValidPathComponent(component)

	// assert
	expected := false
	if result != expected {
		t.Errorf("Components with backslashes are not valid path components but the function returned %v (Expected: %v).", result, expected)
	}
}


<|start_filename|>services/converter/markdowntohtml/postprocessor/emoji.go<|end_filename|>
// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package postprocessor

import (
	"github.com/kyokomi/emoji"
	"regexp"
	"strings"
)

var (
	emojiPattern = regexp.MustCompile(`:[\w\d_]+:`)
)

// addEmojis searches the supplied HTML code for supported emojis
// and replaces them with the respective emoji icon (see: http://www.emoji-cheat-sheet.com/).
// Example: :dancers: becomes 👯
func addEmojis(html string) string {

	allMatches := emojiPattern.FindAllStringSubmatch(html, -1)
	for _, matches := range allMatches {
		if len(matches) == 0 {
			continue
		}

		originalText := strings.TrimSpace(matches[0])
		emojifiedText := emoji.Sprint(originalText)

		// replace all occurances
		html = strings.Replace(html, originalText, emojifiedText, -1)

	}

	return emoji.Sprint(html)
}


<|start_filename|>web/view/themes/themefiles/sitejs.go<|end_filename|>
// Copyright 2014 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const SiteJs = `
/**
 * appendStyleSheet adds the style sheet with the given path to the page
 * @param {string} path The style-sheet file path
 */
function appendStyleSheet(path) {
	$('<link/>', {
		rel: 'stylesheet',
		type: 'text/css',
		href: path,
	}).appendTo('head');
}

/**
 * getAnchorNameFromText returnes a normalized anchor name for the given text
 * @param {string} text
 * @return {string}
 */
function getAnchorNameFromText(text) {
	var anchorName = text.replace(/[\s]/g, "-");
	anchorName = anchorName.replace(/-{2,}/g, "-");
	return anchorName.replace(/[^\w\d-]/g, "");
}

/**
 * addDeepLinksToElements adds anchor links to the elements with the given selector
 * @param {string} cssSelector A CSS-selector
 */
function addDeepLinksToElements(cssSelector) {
	$(cssSelector).each(function() {
		var headlineText = $(this).text();

		var tagName = this.tagName;
		var headlineLevel = tagName.replace(/[^\d]/g, "");

		var anchorText = headlineLevel + "-" + getAnchorNameFromText(headlineText);

		$(this).before('<a class="deeplink" name="' + anchorText + '">' + headlineText + '</a>');
		$(this).wrap('<a href="#' +anchorText + '"></a>')
	});
}
`
