Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
0 results Searching
Select Git revision
Loading items
Show changes
1000 files
+ 219864
66
Compare changes
  • Side-by-side
  • Inline

Files

.gitignore

0 → 100644
+325 −0
Original line number Original line Diff line number Diff line
/development/build/
node_modules/


development/temp/
development/log/
/application/source/server/web/node_modules/


##################### IDE / Tools ##


# @see https://github.com/github/gitignore/

# PHPUnit
.phpunit.result.cache

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

.cache

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Cloud9 IDE - http://c9.io
.c9revisions
.c9

##Exclipse
.metadata
#bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
#local.properties
.settings/
.loadpath
.recommenders

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# PyDev specific (Python IDE for Eclipse)
*.pydevproject

# CDT-specific (C/C++ Development Tooling)
.cproject

# CDT- autotools
.autotools

# Java annotation processor (APT)
.factorypath

# PDT-specific (PHP Development Tools)
.buildpath

# sbteclipse plugin
.target

# Tern plugin
.tern-project

# TeXlipse plugin
.texlipse

# STS (Spring Tool Suite)
.springBeans

# Code Recommenders
.recommenders/

# Annotation Processing
.apt_generated/
.apt_generated_test/

# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet

# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project

##Kate
# Swap Files #
.*.kate-swp
.swp.*

## KDEDevelop
*.kdev4
.kdev4/

## LibreOffice
# LibreOffice locks
.~lock.*#


### LINUX
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*

## Patches
*.orig
*.rej

# Private key
*.ppk

## Sublime
# Cache files for Sublime Text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache

# Workspace files are user-specific
*.sublime-workspace

# Project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using Sublime Text
# *.sublime-project

# SFTP configuration file
sftp-config.json
sftp-config-alt*.json

# Package control specific files
Package Control.last-run
Package Control.ca-list
Package Control.ca-bundle
Package Control.system-ca-bundle
Package Control.cache/
Package Control.ca-certs/
Package Control.merged-ca-bundle
Package Control.user-ca-bundle
oscrypto-ca-bundle.crt
bh_unicode_properties.cache

# Sublime-github package stores a github token in this file
# https://packagecontrol.io/packages/sublime-github
GitHub.sublime-settings

## VIM
# Swap
[._]*.s[a-v][a-z]
!*.svg  # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]

# Session
Session.vim
Sessionx.vim

# Temporary
.netrwhist
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~

# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db

# Dump file
*.stackdump

# Folder config file
[Dd]esktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp

# Windows shortcuts
*.lnk

# gitignore template for AWS Serverless Application Model project
# website: https://docs.aws.amazon.com/serverless-application-model

# Ignore build folder
.aws-sam/

# Netbeans
**/nbproject/private/
**/nbproject/Makefile-*.mk
**/nbproject/Package-*.bash
build/
nbbuild/
dist/
nbdist/
.nb-gradle/



# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn.  Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

## GOLANG
go.work
Original line number Original line Diff line number Diff line
@@ -3,7 +3,17 @@
  <component name="Go" enabled="true" />
  <component name="Go" enabled="true" />
  <component name="NewModuleRootManager" inherit-compiler-output="true">
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <exclude-output />
    <content url="file://$MODULE_DIR$" />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/application/source" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/application/source/command" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/application/source/config" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/application/source/server" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/application/source/server/web" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/application/source/server/web/app" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/application/source/utils" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/development/examples" type="java-resource" />
      <excludeFolder url="file://$MODULE_DIR$/development/build" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
  </component>
Original line number Original line Diff line number Diff line
@@ -2,7 +2,7 @@
  <configuration default="false" name="minerva serve" type="GoApplicationRunConfiguration" factoryName="Go Application">
  <configuration default="false" name="minerva serve" type="GoApplicationRunConfiguration" factoryName="Go Application">
    <module name="minerva" />
    <module name="minerva" />
    <working_directory value="$PROJECT_DIR$/application/source" />
    <working_directory value="$PROJECT_DIR$/application/source" />
    <parameters value="serve --config=../../development/examples/theme1/config.yaml" />
    <parameters value="serve --config=../../development/examples/theme1/config.yaml --path=../../development/examples/theme1/" />
    <kind value="DIRECTORY" />
    <kind value="DIRECTORY" />
    <directory value="$PROJECT_DIR$/application/source" />
    <directory value="$PROJECT_DIR$/application/source" />
    <filePath value="$PROJECT_DIR$" />
    <filePath value="$PROJECT_DIR$" />
Original line number Original line Diff line number Diff line
@@ -30,4 +30,10 @@ func intiParser() {
		config.InitializeConfigFromFile(def.Config)
		config.InitializeConfigFromFile(def.Config)
	}
	}


	cfg := config.GetConfiguration()

	if def.Serve.Path != "" {
		cfg.Server.Path = def.Serve.Path
	}

}
}
Original line number Original line Diff line number Diff line
@@ -5,24 +5,6 @@ type options struct {
	Version struct {
	Version struct {
	} `command:"version"`
	} `command:"version"`
	Serve struct {
	Serve struct {
		Path string `short:"p" long:"path" description:"Path to the project files"`
	} `command:"serve"`
	} `command:"serve"`
}
}

//// DebugLevel logs are typically voluminous, and are usually disabled in production.
// DebugLevel = zapcore.DebugLevel
//// InfoLevel is the default logging priority.
// InfoLevel = zapcore.InfoLevel
//// WarnLevel logs are more important than Info, but don't need individual
//// human review.
// WarnLevel = zapcore.WarnLevel
//// ErrorLevel logs are high-priority. If an application is running smoothly,
//// it shouldn't generate any error-level logs.
// ErrorLevel = zapcore.ErrorLevel
//// DPanicLevel logs are particularly important errors. In development the
//// logger panics after writing the message.
// DPanicLevel = zapcore.DPanicLevel
//// PanicLevel logs a message, then panics.
// PanicLevel = zapcore.PanicLevel
//// FatalLevel logs a message, then calls os.Exit(1).
// FatalLevel = zapcore.FatalLevel
// ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@ func Do() {
		printVersion()
		printVersion()


	case "serve":
	case "serve":

		serve(active)
		serve(active)


	}
	}
Original line number Original line Diff line number Diff line
package config
package config


import (
import (
	"github.com/creasty/defaults"
	"github.com/kelseyhightower/envconfig"
	"github.com/kelseyhightower/envconfig"
	"gitlab.schukai.com/oss/minerva/utils"
	"gitlab.schukai.com/oss/minerva/utils"
	"gopkg.in/yaml.v3"
	"gopkg.in/yaml.v3"
@@ -8,24 +9,44 @@ import (
	"path"
	"path"
)
)


func GetServerPort() string {
	return configuration.Server.Port
}

type Configuration struct {
type Configuration struct {
	//LogLevel string `yaml:"logLevel" envconfig:"LOG_LEVEL"`

	Server struct {
	Server struct {
		Port string `yaml:"Port" envconfig:"SERVER_PORT" default:"80"`
		Port int    `yaml:"Port" envconfig:"SERVER_PORT" default:"8080"`
		Path string `yaml:"Path" envconfig:"SERVER_PATH" default:""`
	} `yaml:"Server"`
	} `yaml:"Server"`
}

// SetDefaults implements defaults.Setter interface
func (s *Configuration) SetDefaults() {
	if defaults.CanUpdate(s.Server.Path) {
		path, err := os.Getwd()
		if err != nil {
			utils.PrintErrorAndExit("something went wrong: %s", err.Error())
		}
		s.Server.Path = path
	}
}


	Paths struct {
func GetServerPort() int {
		Web string `yaml:"Web" envconfig:"PATH_WEB" default:"/srv/web/"`
	return configuration.Server.Port
	} `yaml:"Paths"`
}

func GetServerPath() string {
	return configuration.Server.Path
}
}


var configuration *Configuration
var configuration *Configuration


func newConfiguration() *Configuration {

	config := &Configuration{}
	if err := defaults.Set(config); err != nil {
		utils.PrintErrorAndExit("we have a problem: %s", err.Error())
	}

	return config
}

func GetConfiguration() *Configuration {
func GetConfiguration() *Configuration {


	if configuration == nil {
	if configuration == nil {
@@ -63,7 +84,7 @@ func intiConfiguration() {
		return
		return
	}
	}


	configuration = &Configuration{}
	configuration = newConfiguration()


}
}


@@ -98,10 +119,10 @@ func readFile(filename string) {
		}
		}
	}()
	}()


	c := Configuration{}
	c := newConfiguration()
	err = yaml.Unmarshal([]byte(data), &c)
	err = yaml.Unmarshal([]byte(data), c)


	configuration = &c
	configuration = c


	if err != nil {
	if err != nil {
		utils.PrintErrorAndExit(err.Error())
		utils.PrintErrorAndExit(err.Error())
Original line number Original line Diff line number Diff line
@@ -13,6 +13,7 @@ require (
)
)


require (
require (
	github.com/creasty/defaults v1.6.0 // indirect
	github.com/go-chi/chi/v5 v5.0.7 // indirect
	github.com/go-chi/chi/v5 v5.0.7 // indirect
	github.com/google/uuid v1.3.0 // indirect
	github.com/google/uuid v1.3.0 // indirect
	github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
	github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
Original line number Original line Diff line number Diff line
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/creasty/defaults v1.6.0 h1:ltuE9cfphUtlrBeomuu8PEyISTXnxqkBIoQfXgv7BSc=
github.com/creasty/defaults v1.6.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+31 −0
Original line number Original line Diff line number Diff line
package server

import (
	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
	"net/http"
)

func appHandler() http.Handler {

	r := chi.NewRouter()
	r.Use(middleware.NoCache)

	r.Get("/editor", renderEditor)

	r.Handle("/web/node_modules/*",
		http.StripPrefix("/app", http.FileServer(http.FS(embeddedFiles))))

	//r.Get("/node_modules/*", serveNodeModules)

	//r.Route("/node_modules/*",  http.StripPrefix("/assets/",
	//	http.FileServer(http.Dir("assets/"))))
	//
	//http.Handle("/assets/", http.StripPrefix("/assets/",
	//	http.FileServer(http.Dir("assets/"))))

	//r.Post("/convert", doV1Convert)
	//r.Post("/create", doV1Create)

	return r
}
+49 −0
Original line number Original line Diff line number Diff line
package server

import (
	"net/http"
)

func serveNodeModules(w http.ResponseWriter, r *http.Request) {

	content := lookUp(r.URL.Path)
	if content != nil {

		//w.Header().Add("Content-Type", "application/json")

		//mimeType := ""
		//
		//ext := filepath.Ext(r.URL.Path)
		//switch ext {
		//case ".htm", ".html":
		//	return "text/html"
		//case ".css":
		//	return "text/css"
		//case ".js":
		//	return "application/javascript"
		//
		//
		//
		//filetype := http.DetectContentType(content)
		//fmt.Println(filetype)

		w.Write(content)
		return
	}

	w.WriteHeader(404)

}

func renderEditor(w http.ResponseWriter, r *http.Request) {

	content, err := embeddedFiles.ReadFile("web/app/editor.html")
	if err != nil {
		logError("something went wrong: %s", err.Error())
		w.WriteHeader(500)
		return
	}

	w.Write(content)

}
+65 −0
Original line number Original line Diff line number Diff line
package server

import (
	"net/http"
	"path"
	"strings"
)

//// FSHandler404 provides the function signature for passing to the FileServerWith404
//type handler404 = func(w http.ResponseWriter, r *http.Request) (doDefaultFileServe bool)

func fileServer(root string) http.Handler {

	fs := http.FileServer(http.Dir(root))

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		//make sure the url path starts with /
		upath := r.URL.Path
		if !strings.HasPrefix(upath, "/") {
			upath = "/" + upath
			r.URL.Path = upath
		}

		upath = path.Clean(upath)
		//
		////// attempt to open the file via the http.FileSystem
		////f, err := root.Open(upath)
		////// close if successfully opened
		////if f != nil {
		////	defer f.Close()
		////}
		//if !utils.DirectoryExists(root) {
		//	if os.IsNotExist(err) {
		//		// call handler
		//		if h404 != nil {
		//			doDefault := h404(w, r)
		//			if !doDefault {
		//				return
		//			}
		//		}
		//	}
		//}
		//
		//s, err := f.Stat()
		//
		//if err != nil {
		//	if os.IsNotExist(err) {
		//		// call handler
		//		if h404 != nil {
		//			doDefault := h404(w, r)
		//			if !doDefault {
		//				return
		//			}
		//		}
		//	}
		//}
		//
		//if s.IsDir() && false {
		//	return
		//}

		// default serve
		fs.ServeHTTP(w, r)
	})
}
Original line number Original line Diff line number Diff line
@@ -8,6 +8,10 @@ import (
	"github.com/go-chi/chi/v5/middleware"
	"github.com/go-chi/chi/v5/middleware"
	"gitlab.schukai.com/oss/minerva/config"
	"gitlab.schukai.com/oss/minerva/config"
	"net/http"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"sync"
	"sync"
)
)


@@ -17,26 +21,45 @@ var (
	embeddedFiles embed.FS
	embeddedFiles embed.FS
)
)


func lookUp(path string) (content []byte) {
func lookUp(p string) (content []byte) {
	// Zuerst im Verzeichnis /web/asserts schauen (wird beim build inkludiert)

	c, _ := embeddedFiles.ReadFile("web" + path)
	c, _ := embeddedFiles.ReadFile("web" + p)
	if len(c) > 0 {
	if len(c) > 0 {
		return c
		return c
	}
	}


	base, err := filepath.Abs(config.GetServerPath())
	if err != nil {
		logError("%s", err.Error())
		return nil
		return nil
	}
	}


func serveStaticFiles(next http.Handler) func(http.ResponseWriter, *http.Request) {
	filename := path.Clean(path.Join(base, p))
	return func(w http.ResponseWriter, r *http.Request) {


		content := lookUp(r.URL.Path)
	data, _ := os.ReadFile(filename)
		if len(content) > 0 {
	if len(data) > 0 {
			w.Write(content)
		return data
			return
	}

	return nil
}
}


		next.ServeHTTP(w, r)
//func serveStaticFiles() func(http.ResponseWriter, *http.Request) {
//	return func(w http.ResponseWriter, r *http.Request) {
//
//		content := lookUp(r.URL.Path)
//		if content != nil {
//			w.Write(content)
//			return
//		}
//
//		w.WriteHeader(404)
//
//	}
//}
func redirectToApp() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "app/editor", http.StatusTemporaryRedirect)
	}
	}
}
}


@@ -57,21 +80,21 @@ func initRouting() *chi.Mux {
	/** x509: certificate signed by unknown authority */
	/** x509: certificate signed by unknown authority */
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}


	mux := chi.NewRouter()
	router := chi.NewRouter()


	mux.Use(waitGroupMiddleware())
	router.Use(waitGroupMiddleware())


	mux.Use(RequestIDMiddleware)
	router.Use(RequestIDMiddleware)
	mux.Use(middleware.RealIP)
	router.Use(middleware.RealIP)
	mux.Use(middleware.Heartbeat("/ping"))
	router.Use(middleware.Heartbeat("/ping"))


	mux.Use(middleware.Compress(5))
	router.Use(middleware.Compress(5))
	mux.Use(middleware.AllowContentType("application/json", "text/html"))
	router.Use(middleware.AllowContentType("application/json", "text/html"))
	mux.Use(loggerMiddleware)
	router.Use(loggerMiddleware)


	//	mux.Mount("/api/v1", v1.V1Api(cfg))
	router.Mount("/app", appHandler())


	//mux.Get("/", func(w http.ResponseWriter, r *http.Request) {
	//router.Get("/", func(w http.ResponseWriter, r *http.Request) {
	//	if negotiator.New(r.Header).Type("text/html") == "text/html" {
	//	if negotiator.New(r.Header).Type("text/html") == "text/html" {
	//		http.Redirect(w, r, "https://www.alvine.cloud/en/products/media-services/juno/", http.StatusPermanentRedirect)
	//		http.Redirect(w, r, "https://www.alvine.cloud/en/products/media-services/juno/", http.StatusPermanentRedirect)
	//	} else {
	//	} else {
@@ -92,17 +115,30 @@ func initRouting() *chi.Mux {
	//	return nil
	//	return nil
	//}
	//}


	//router.Get("/*", redirectToApp())
	//
	//router.Path("/whatever").Handler(func(writer http.ResponseWriter, req *http.Request) {
	//	http.Redirect(writer, req, "localhost:8080/whatever", http.StatusMovedPermanently)
	//	))
	//

	//d := http.Dir(p)
	//d := http.Dir(p)
	//mux.Get("/*",
	//	router.Get("/*",
	//	serveStaticFiles(fileserver.FileServerWith404(d, func(w http.ResponseWriter, r *http.Request) (doDefaultFileServe bool) {
	//serveStaticFiles(
	//		error2.StandardErrorResponse(w, r, error2.ErrorResponse{
	//	func(w http.ResponseWriter, r *http.Request) (doDefaultFileServe bool) {
	//			Status: 404,
	//
	//		})
	//	}
	//		return false
	//
	//
	//	})))
	//		)
	//		//serveStaticFiles(fileServerWith404("/tmp", func(w http.ResponseWriter, r *http.Request) (doDefaultFileServe bool) {
	//		//	error2.StandardErrorResponse(w, r, error2.ErrorResponse{
	//		//		Status: 404,
	//		//	})
	//		//	return false
	//		//
	//		//})))


	return mux
	return router


}
}


@@ -113,7 +149,7 @@ func Serve() {


	c := config.GetConfiguration()
	c := config.GetConfiguration()


	address := ":" + c.Server.Port
	address := ":" + strconv.FormatInt(int64(c.Server.Port), 10)
	logInfo("server listen on address %s", address)
	logInfo("server listen on address %s", address)


	server := http.Server{
	server := http.Server{
Original line number Original line Diff line number Diff line
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>



 
    
    
    
    <link rel="stylesheet" href="/app/web/node_modules/grapesjs/dist/css/grapes.min.css">
    <link rel="stylesheet" href="/app/web/node_modules/grapesjs-preset-webpage/dist/grapesjs-preset-webpage.min.css">

    <script src="/app/web/node_modules/grapesjs/dist/grapes.min.js"></script>
    <script src="/app/web/node_modules/grapesjs-preset-webpage/dist/grapesjs-preset-webpage.min.js"></script>

    <style>
        body,
        html {<
            height: 100%;
            margin: 0;
            overflow: hidden;
        }

        #toast-container {
            font-size: 13px;
            font-weight: lighter;
        }

        #toast-container > div {
            opacity: 0.95;
        }

        #toast-container > div,
        #toast-container > div:hover {
            box-shadow: 0 0 12px rgba(0, 0, 0, 0.1);
            font-family: Helvetica, sans-serif;
        }

        /* LOGO VERSION */

        .gjs-pn-commands .gjs-pn-buttons,
        #gjs-pn-commands .gjs-pn-buttons {
            display: none;
        }

        .gjs-logo {
            height: 25px;
        }

        .gjs-logo-cont {
            position: relative;
            display: inline-block;
            top: 3px;
        }

        .gjs-logo-version {
            position: absolute;
            font-size: 10px;
            padding: 1px 7px;
            border-radius: 15px;
            bottom: 2px;
            right: -43px;
        }

        /* INFO PANEL */

        .gjs-mdl-dialog-sm {
            width: 300px;
        }

        #info-panel {
            line-height: 17px;
        }

        .info-panel-logo {
            display: block;
            height: 90px;
            margin: 0 auto;
            width: 90px;
        }

        .info-panel-logo path {
            stroke: #eee !important;
            stroke-width: 8 !important;
        }

        .info-panel-label {
            margin-bottom: 10px;
            font-size: 13px;
        }

        .info-panel-link {
            text-decoration: none;
        }

        /* ADS */

        .gjs-pn-panel#gjs-pn-views-container,
        .gjs-pn-panel.gjs-pn-views-container {
            height: calc(100% - 150px);
        }

        .ad-cont {
            position: absolute;
            right: 0;
            bottom: 0;
            z-index: 2;
            width: 15%;
            height: 150px;
        }

        #carbonads {
            font: caption;
            padding: 20px 10px;
        }

        .carbon-link {
            text-decoration: none;
            font: caption;
        }

        .carbon-img {
            float: right;
            margin-left: 10px;
        }

        .carbon-img img {
            border-radius: 3px;
            max-width: 100px !important;
            max-height: 77px;
        }

        .carbon-text {
            color: rgba(255, 255, 255, 0.75);
            text-decoration: none;
            font-weight: lighter;
        }

        .carbon-poweredby {
            color: rgba(255, 255, 255, 0.55);
            text-decoration: none;
            float: right;
        }

        .carbon-cta-c {
            text-align: right;
            padding-top: 5px;
        }

        .carbon-cta {
            display: inline-block;
            padding: 4px 10px;
            border-radius: 3px;
            font-weight: bold;
            font-size: 12px;
        }

        .gjs-block-label svg,
        .gjs-block__media svg {
            width: 54px;
        }

        /* Temporary fix #2490 */
        .gjs-clm-tag-status,
        .gjs-clm-tag-close {
            width: 12px;
            height: 12px;
        }
        .gjs-clm-tags-btn {
            width: 24px;
        }
        
    </style>


</head>
<body>


<div id="gjs"></div>
<div id="blocks"></div>

<script type="text/javascript">
    const editor = grapesjs.init({
        // Indicate where to init the editor. You can also pass an HTMLElement
        container: '#gjs',
        // Get the content for the canvas directly from the element
        // As an alternative we could use: `components: '<h1>Hello World Component!</h1>'`,
        fromElement: true,
        // Size of the editor
        height: '300px',
        width: 'auto',
        // Disable the storage manager for the moment
        storageManager: false,
        // Avoid any default panel
        panels: {defaults: []},
        blockManager: {
            appendTo: '#blocks',
            blocks: [
                {
                    id: 'section', // id is mandatory
                    label: '<b>Section</b>', // You can use HTML/SVG inside labels
                    attributes: {class: 'gjs-block-section'},
                    content: `<section>
          <h1>This is a simple title</h1>
          <div>This is just a Lorem text: Lorem ipsum dolor sit amet</div>
        </section>`,
                }, {
                    id: 'text',
                    label: 'Text',
                    content: '<div data-gjs-type="text">Insert your text here</div>',
                }, {
                    id: 'image',
                    label: 'Image',
                    // Select the component once it's dropped
                    select: true,
                    // You can pass components as a JSON instead of a simple HTML string,
                    // in this case we also use a defined component type `image`
                    content: {type: 'image'},
                    // This triggers `active` event on dropped components and the `image`
                    // reacts by opening the AssetManager
                    activate: true,
                }
            ]
        },
    });
</script>

</body>
</html>


Original line number Original line Diff line number Diff line
{
  "name": "minerva",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "node_modules/backbone": {
      "version": "1.3.3",
      "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.3.3.tgz",
      "integrity": "sha1-TMgOp8sWMaxHSInOQPL4vGg7KZk=",
      "dependencies": {
        "underscore": ">=1.8.3"
      }
    },
    "node_modules/backbone-undo": {
      "version": "0.2.5",
      "resolved": "https://registry.npmjs.org/backbone-undo/-/backbone-undo-0.2.5.tgz",
      "integrity": "sha1-VbJSMPkDGcpiJGXomoAki4k8LOI=",
      "dependencies": {
        "backbone": "1.0.0 - 1.2.1",
        "underscore": "1.4.4 - 1.8.3"
      }
    },
    "node_modules/backbone-undo/node_modules/backbone": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.2.1.tgz",
      "integrity": "sha1-1yGcXtSeXhMdv/ryXJbW0sw8oD4=",
      "dependencies": {
        "underscore": ">=1.7.0"
      }
    },
    "node_modules/backbone-undo/node_modules/underscore": {
      "version": "1.8.3",
      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
      "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
    },
    "node_modules/codemirror": {
      "version": "5.65.3",
      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.3.tgz",
      "integrity": "sha512-kCC0iwGZOVZXHEKW3NDTObvM7pTIyowjty4BUqeREROc/3I6bWbgZDA3fGDwlA+rbgRjvnRnfqs9SfXynel1AQ=="
    },
    "node_modules/codemirror-formatting": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/codemirror-formatting/-/codemirror-formatting-1.0.0.tgz",
      "integrity": "sha1-h5zB/dkBg0PB1VEXac5TYNcF6/I="
    },
    "node_modules/core-util-is": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
    },
    "node_modules/file-saver": {
      "version": "1.3.8",
      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.8.tgz",
      "integrity": "sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg=="
    },
    "node_modules/grapesjs": {
      "version": "0.18.4",
      "resolved": "https://registry.npmjs.org/grapesjs/-/grapesjs-0.18.4.tgz",
      "integrity": "sha512-mOkmOc7Q9OyuW4H8h4NDhFK1cxBnw/En+sD60enOKQrNy5lfua6Lh5I0oTm93RU6ahQy2QPzn1ZbZWAQaDCKQw==",
      "dependencies": {
        "backbone": "1.3.3",
        "backbone-undo": "^0.2.5",
        "codemirror": "^5.63.0",
        "codemirror-formatting": "^1.0.0",
        "promise-polyfill": "^8.1.3",
        "underscore": "^1.13.1"
      }
    },
    "node_modules/grapesjs-aviary": {
      "version": "0.1.2",
      "resolved": "https://registry.npmjs.org/grapesjs-aviary/-/grapesjs-aviary-0.1.2.tgz",
      "integrity": "sha512-F7sYQWj5s9eyUqoOX6q1z2J06AqgXhQqdjQhM8b5BptxlbDsvDTCbqSRmLGkEQKaIF1ca5o9FFi9eKBeUAfLEw==",
      "peerDependencies": {
        "grapesjs": "0.x"
      }
    },
    "node_modules/grapesjs-blocks-basic": {
      "version": "0.1.8",
      "resolved": "https://registry.npmjs.org/grapesjs-blocks-basic/-/grapesjs-blocks-basic-0.1.8.tgz",
      "integrity": "sha512-Iy5M4qGkEE2llb5ZFxitDolRJ3CrQkcK1SQIjRRlkWIAC99On3T/09iFR7NkpTBfsgfdNwcwnSVOMOhSnVLDtw==",
      "peerDependencies": {
        "grapesjs": "0.x"
      }
    },
    "node_modules/grapesjs-component-countdown": {
      "version": "0.1.3",
      "resolved": "https://registry.npmjs.org/grapesjs-component-countdown/-/grapesjs-component-countdown-0.1.3.tgz",
      "integrity": "sha512-TmxDETedUDv1jGqNLn6E768iyp+xAK/XcTId5WpLrmKPFB6aCuWqfTowhtSvyRJJs83OAFMiQIwIu+tEtSWOeA==",
      "peerDependencies": {
        "grapesjs": "0.x"
      }
    },
    "node_modules/grapesjs-navbar": {
      "version": "0.1.5",
      "resolved": "https://registry.npmjs.org/grapesjs-navbar/-/grapesjs-navbar-0.1.5.tgz",
      "integrity": "sha512-tVKPtzlTUNCpzk3lHW69II2NsSzLNQd3K32CXssWCP3M1V8fvc9jG/MQECBkd/gMS+DjldD4/4b00ri9F3tKSg==",
      "peerDependencies": {
        "grapesjs": "0.x"
      }
    },
    "node_modules/grapesjs-plugin-export": {
      "version": "0.1.5",
      "resolved": "https://registry.npmjs.org/grapesjs-plugin-export/-/grapesjs-plugin-export-0.1.5.tgz",
      "integrity": "sha512-BgvPY68vIDxVv0Z3v1TTikHseMxbfvUvhk5qUHq3a9kFmc2sFfNA6f5NHP9A4v3Tnd4kuwOd2aIn+QNutZrLRg==",
      "dependencies": {
        "file-saver": "^1.3.2",
        "jszip": "^3.0.0"
      },
      "peerDependencies": {
        "grapesjs": "0.x"
      }
    },
    "node_modules/grapesjs-plugin-filestack": {
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/grapesjs-plugin-filestack/-/grapesjs-plugin-filestack-0.1.1.tgz",
      "integrity": "sha512-zRwgHUZd7qDVk92dtizOHxnPiCjBBmsA2BHm0J86tz8uiXf6ou0OoQiB4x4UDewb9ipTkBI6X5nGh/0YET6WLw==",
      "peerDependencies": {
        "grapesjs": "0.x"
      }
    },
    "node_modules/grapesjs-plugin-forms": {
      "version": "0.3.6",
      "resolved": "https://registry.npmjs.org/grapesjs-plugin-forms/-/grapesjs-plugin-forms-0.3.6.tgz",
      "integrity": "sha512-JGIxky3if7FLlXBDuX2T2UoWQnvm55PcNp5P2qoX64zlA0+2npz9zbPcj9g1PUHXVPlTXwTr2qu5x3U/pb+xdw==",
      "peerDependencies": {
        "grapesjs": "0.x"
      }
    },
    "node_modules/grapesjs-preset-webpage": {
      "version": "0.1.11",
      "resolved": "https://registry.npmjs.org/grapesjs-preset-webpage/-/grapesjs-preset-webpage-0.1.11.tgz",
      "integrity": "sha512-36SuSPwu3a09R6YR31Sklmowz/LvzxzGM74WcPd8KPwbs1mAQ4fFuqWKkX/wv8+GhY58Se9EO42yQVMwsZzELA==",
      "dependencies": {
        "grapesjs-aviary": "^0.1.2",
        "grapesjs-blocks-basic": "^0.1.7",
        "grapesjs-component-countdown": "^0.1.2",
        "grapesjs-navbar": "^0.1.5",
        "grapesjs-plugin-export": "^0.1.5",
        "grapesjs-plugin-filestack": "^0.1.1",
        "grapesjs-plugin-forms": "^0.3.5"
      },
      "peerDependencies": {
        "grapesjs": "0.x"
      }
    },
    "node_modules/immediate": {
      "version": "3.0.6",
      "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
      "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
    },
    "node_modules/inherits": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
    },
    "node_modules/isarray": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
    },
    "node_modules/jszip": {
      "version": "3.9.1",
      "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.9.1.tgz",
      "integrity": "sha512-H9A60xPqJ1CuC4Ka6qxzXZeU8aNmgOeP5IFqwJbQQwtu2EUYxota3LdsiZWplF7Wgd9tkAd0mdu36nceSaPuYw==",
      "dependencies": {
        "lie": "~3.3.0",
        "pako": "~1.0.2",
        "readable-stream": "~2.3.6",
        "set-immediate-shim": "~1.0.1"
      }
    },
    "node_modules/lie": {
      "version": "3.3.0",
      "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
      "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
      "dependencies": {
        "immediate": "~3.0.5"
      }
    },
    "node_modules/pako": {
      "version": "1.0.11",
      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
    },
    "node_modules/process-nextick-args": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
    },
    "node_modules/promise-polyfill": {
      "version": "8.2.3",
      "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.3.tgz",
      "integrity": "sha512-Og0+jCRQetV84U8wVjMNccfGCnMQ9mGs9Hv78QFe+pSDD3gWTpz0y+1QCuxy5d/vBFuZ3iwP2eycAkvqIMPmWg=="
    },
    "node_modules/readable-stream": {
      "version": "2.3.7",
      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
      "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
      "dependencies": {
        "core-util-is": "~1.0.0",
        "inherits": "~2.0.3",
        "isarray": "~1.0.0",
        "process-nextick-args": "~2.0.0",
        "safe-buffer": "~5.1.1",
        "string_decoder": "~1.1.1",
        "util-deprecate": "~1.0.1"
      }
    },
    "node_modules/safe-buffer": {
      "version": "5.1.2",
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
    },
    "node_modules/set-immediate-shim": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/string_decoder": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
      "dependencies": {
        "safe-buffer": "~5.1.0"
      }
    },
    "node_modules/underscore": {
      "version": "1.13.3",
      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.3.tgz",
      "integrity": "sha512-QvjkYpiD+dJJraRA8+dGAU4i7aBbb2s0S3jA45TFOvg2VgqvdCDd/3N6CqA8gluk1W91GLoXg5enMUx560QzuA=="
    },
    "node_modules/util-deprecate": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
    }
  }
}
Original line number Original line Diff line number Diff line
<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>UndoManager Tests</title>
	<link rel="stylesheet" href="resources/qunit.css">
</head>
<body>
	<div id="qunit"></div>
	<div id="qunit-fixture"></div>
	<script src="resources/jquery-1.9.1.js"></script>
	<script src="resources/underscore.js"></script>
	<script src="resources/backbone.js"></script>

	<script src="../Backbone.Undo.js"></script>

	<script src="resources/qunit.js"></script>
	<script src="Backbone.Undo.Tests.js"></script>
</body>
</html>
 No newline at end of file
Original line number Original line Diff line number Diff line
test("Register and unregister", function () {
	var UndoManager = new Backbone.UndoManager;

	var model = new Backbone.Model,
	collection = new Backbone.Collection;

	UndoManager.register(model, collection);

	function getRegisteredObjects () {
		return UndoManager.objectRegistry.get();
	}

	strictEqual(getRegisteredObjects().length, 2, "Registering objects with the register method was successful");

	UndoManager.unregister(model);

	deepEqual(getRegisteredObjects(), [collection], "Unregistering an object with the unregister method was successful");

	UndoManager.register(model);
	UndoManager.unregisterAll();

	strictEqual(getRegisteredObjects().length, 0, "The unregisterAll function worked properly");

	var u1 = new Backbone.UndoManager({
		register: model
	}),
	u2 = new Backbone.UndoManager({
		register: collection
	}),
	u3 = new Backbone.UndoManager({
		register: [model, collection]
	});

	deepEqual(u1.objectRegistry.get(), [model], "Registering a single model over the 'register' attribute on instantiation was successful");
	deepEqual(u2.objectRegistry.get(), [collection], "Registering a single collection over the 'register' attribute on instantiation was successful");
	deepEqual(u3.objectRegistry.get(), [model, collection], "Registering multiple objects over the 'register' attribute on instantiation was successful");
})

test("Start and stop tracking", function () {
	var model = new Backbone.Model({
		"foo": "bar"
	})

	var collection = new Backbone.Collection([{"a": "b"}, {"c": "d"}]);

	var UndoManager = new Backbone.UndoManager({
		register: [model, collection]
	});

	var before = UndoManager.stack.length;

	model.set("hello", "world");
	collection.add({"e": "f"});

	strictEqual(UndoManager.stack.length, before, "Actions weren't added to the stack, because tracking hasn't started yet");

	ok(!UndoManager.isTracking(), "Tracking has not started yet");

	UndoManager.startTracking();

	ok(UndoManager.isTracking(), "Tracking has now started");

	model.set("hello", "you");
	collection.remove(collection.last());

	var after = UndoManager.stack.length;

	strictEqual(after, 2, "Two actions have been added to the stack, because tracking has started");

	UndoManager.stopTracking();

	model.set("hello", "kitty");
	collection.add({"e": "f"});
	model.set("hello", "you");
	collection.remove(collection.last());

	UndoManager.startTracking();

	strictEqual(UndoManager.stack.length, after, "No actions were added, because tracking was paused");

	UndoManager.unregisterAll();

	UndoManager = new Backbone.UndoManager({track: true});

	UndoManager.register(model, collection);

	model.set("hello", "hello");
	collection.add({"g": "h"});

	strictEqual(UndoManager.stack.length, 2, "{track:true} on instantiation started tracking at once");
});

test("Undo and redo Model-Changes", function () {
	var model = new Backbone.Model({
		"t": 1
	});

	var UndoManager = new Backbone.UndoManager({
		track: true,
		register: model
	});

	model.set("t", 2);

	UndoManager.undo();

	deepEqual(model.toJSON(), {"t": 1}, "Undoing changing a model attribute was successful");

	UndoManager.redo();

	deepEqual(model.toJSON(), {"t": 2}, "Redoing changing a model attribute was successful");

	model.set("x", 1);

	UndoManager.undo();

	deepEqual(model.toJSON(), {"t": 2}, "Undoing setting a model attribute was successful");

	UndoManager.redo();

	deepEqual(model.toJSON(), {"t": 2, "x": 1}, "Redoing setting a model attribute was successful");

	model.set({
		"y": 1,
		"x": 2
	})

	UndoManager.undo();

	deepEqual(model.toJSON(), {"t": 2, "x": 1}, "Undoing multiple changes at once was successful");

	UndoManager.redo();

	deepEqual(model.toJSON(), {"t": 2, "x": 2, "y": 1}, "Redoing multiple changes at once was successful");

	UndoManager.undo();
	UndoManager.undo();
	UndoManager.undo();

	deepEqual(model.toJSON(), {"t": 1}, "Calling undo consecutively several times was successful");

	UndoManager.undo();

	deepEqual(model.toJSON(), {"t": 1}, "Additional undo calls that would be out of the stack's bounds were successfully ignored");

	UndoManager.redo();
	UndoManager.redo();
	UndoManager.redo();

	deepEqual(model.toJSON(), {"t": 2, "x": 2, "y": 1}, "Calling redo consecutively several times was successful");

	UndoManager.redo();

	deepEqual(model.toJSON(), {"t": 2, "x": 2, "y": 1}, "Additional redo calls that would be out of the stack's bounds were successfully ignored");	
})

test("Undo and redo Collection-changes", function () {
	var collection = new Backbone.Collection([{"t": 1}, {"t": 2}, {"t": 3}]),
	UndoManager = new Backbone.UndoManager({
		track: true,
		register: collection
	});

	collection.add({"t": 4});

	UndoManager.undo();

	deepEqual(collection.toJSON(), [{"t": 1}, {"t": 2}, {"t": 3}], "Adding a model to the collection was successfully undone");

	UndoManager.redo();

	deepEqual(collection.toJSON(), [{"t": 1}, {"t": 2}, {"t": 3}, {"t": 4}], "Adding a model to the collection was successfully redone");

	collection.remove(collection.first());

	UndoManager.undo();

	deepEqual(collection.toJSON(), [{"t": 1}, {"t": 2}, {"t": 3}, {"t": 4}], "Removing a model from the collection was successfully undone");

	UndoManager.redo();

	deepEqual(collection.toJSON(), [{"t": 2}, {"t": 3}, {"t": 4}], "Removing a model from the collection was successfully redone");

	collection.reset([{"a": 1}, {"a": 2}, {"a": 3}]);

	UndoManager.undo();

	deepEqual(collection.toJSON(), [{"t": 2}, {"t": 3}, {"t": 4}], "Resetting the collection was successfully undone");

	UndoManager.redo();

	deepEqual(collection.toJSON(), [{"a": 1}, {"a": 2}, {"a": 3}], "Resetting the collection was successfully redone");

	collection.first().destroy();

	UndoManager.undo();

	deepEqual(collection.toJSON(), [{"a": 1}, {"a": 2}, {"a": 3}], "Destroying a model in the collection was successfully undone");

	UndoManager.redo();

	deepEqual(collection.toJSON(), [{"a": 2}, {"a": 3}], "Destroying a model in the collection was successfully redone");
})

test("ObjectRegistry", function () {
	var model = new Backbone.Model,
	collection = new Backbone.Collection,
	nonBackboneObject = {"something":"else"},
	UndoManager = new Backbone.UndoManager,
	objectRegistry = UndoManager.objectRegistry;

	function compare (arr1, arr2) {
		return _.all(arr1, function (v) {
			return _.contains(arr2, v);
		});
	}

	objectRegistry.register(model);

	ok(objectRegistry.isRegistered(model), "The isRegistered method returns true");

	objectRegistry.register(collection);

	ok(compare(objectRegistry.get(), [model, collection]), "The get method rightfully returns a list of the registered objects");

	objectRegistry.register(model);
	objectRegistry.register(collection);

	equal(objectRegistry.get().length, 2, "Redundant registrations are correctly ignored");

	objectRegistry.register(nonBackboneObject);

	ok(compare(objectRegistry.get(), [model, collection, nonBackboneObject]), "Non-Backbone objects are also correctly registered");

	objectRegistry.unregister(model);
	objectRegistry.unregister(collection);
	objectRegistry.unregister(nonBackboneObject);

	equal(objectRegistry.get().length, 0, "Unregistering objects works properly");
})

test("Merging UndoManagers", 2, function () {
	var main = new Backbone.UndoManager({track:true}),
	special = new Backbone.UndoManager({track:true}),
	model1 = new Backbone.Model({
		"t": 1
	}),
	model2 = new Backbone.Model,
	obj = {
		object: model1,
		before: {"a": 1},
		after: {"b": 1}
	};

	main.id = main.stack.id = "main";
	special.id = special.stack.id = "special";
	
	special.changeUndoType("change", {
		"on": function () {
			return obj;
		}
	});

	special.register(model1);
	main.register(model2);

	main.merge(special);

	model1.set("t", 2); // Here we're triggering a change event

	// Now, the stack-length of main must have been changed
	deepEqual(main.stack.at(0).toJSON(), obj, "The action data was manipulated by the changed undotype")

	model2.set("t", 2); // Here we're checking if the main undoManager can still write on its stack

	deepEqual(main.stack.at(1).toJSON().after, {"t": 2}, "The main undomanager can still write on its own stack")
})

test("Clearing all actions", function () {
	var model = new Backbone.Model({
		"t": 1
	});

	var UndoManager = new Backbone.UndoManager({
		track: true,
		register: model
	});

	model.set("t", 2);
	model.set("t", 3);
	model.set("t", 4);

	UndoManager.clear();

	UndoManager.undo();

	deepEqual(model.toJSON(), {"t": 4}, "Clearing actions before undoing was successful");

	model.set("t", 2);
	model.set("t", 3);
	model.set("t", 4);

	UndoManager.undo();
	UndoManager.undo();

	UndoManager.clear();

	UndoManager.redo();

	deepEqual(model.toJSON(), {"t": 2}, "Clearing actions before redoing was successful");
})

test("Undoing all actions", function () {
	var model = new Backbone.Model({
		"t": 1
	});

	var UndoManager = new Backbone.UndoManager({
		track: true,
		register: model
	});

	model.set("t", 2);
	model.set("t", 3);
	model.set("t", 4);

	UndoManager.undoAll();

	deepEqual(model.toJSON(), {"t": 1}, "Calling undoAll was successful");

	UndoManager.redoAll();

	deepEqual(model.toJSON(), {"t": 4}, "Calling redoAll was successful");

	UndoManager.undo();
	UndoManager.undoAll();
	UndoManager.undo(true);

	deepEqual(model.toJSON(), {"t": 1}, "Mixing undoAll with undo doesn't cause any problems");
	
	UndoManager.undoAll(); // back to the stack's beginning

	UndoManager.redo();
	UndoManager.redoAll();
	UndoManager.redo(true);

	deepEqual(model.toJSON(), {"t": 4}, "Mixing redoAll with redo doesn't cause any problems");

	UndoManager.undoAll();
	UndoManager.undoAll();
	UndoManager.redoAll();
	UndoManager.redoAll();

	deepEqual(model.toJSON(), {"t": 4}, "Calling undoAll and redoAll multiple times doesn't cause any problems");

})

/**
 * Async tests for magic fusion
 */

var deferQueue = [];
function defer(fn) {
	var args = [].slice.call(arguments);
	deferQueue.push(fn, args);
}
function flushDeferQueue() {
	_.defer(function () {
		var fn = deferQueue.shift(),
			args = deferQueue.shift();
		if (fn) {
			fn.apply(null, args);
			flushDeferQueue();
		}
	})
}

asyncTest("Magic Fusion", 4, function () {
	var model = new Backbone.Model({
		"t": 1
	}), collection = new Backbone.Collection([{"a": 3}]),
	UndoManager = new Backbone.UndoManager({
		track: true,
		register: [model, collection]
	}), i;

	defer(function () {
		start();
		// Undo / Redo several changes
		for (i = 3; i < 10; i++) {
			model.set("t", i);
		}

		UndoManager.undo(true);

		equal(model.get("t"), 1, "Undoing all changes that happened on a model at once succeeded");

		UndoManager.redo(true);

		equal(model.get("t"), 9, "Redoing all changes that happened on a model at once succeeded");
	})

	defer(function () {
		stop();
		collection.add([{"a": 4}, {"a": 5}]);

		UndoManager.undo(true);

		equal(collection.length, 1, "Undoing adding several models to a collection succeeded");

		UndoManager.redo(true);

		equal(collection.length, 3, "Redoing adding several models to a collection succeeded");
		start();
	})

	flushDeferQueue();
})
Original line number Original line Diff line number Diff line
/**
 * QUnit v1.11.0 - A JavaScript Unit Testing Framework
 *
 * http://qunitjs.com
 *
 * Copyright 2012 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

/** Font Family and Sizes */

#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
	font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
}

#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
#qunit-tests { font-size: smaller; }


/** Resets */

#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
	margin: 0;
	padding: 0;
}


/** Header */

#qunit-header {
	padding: 0.5em 0 0.5em 1em;

	color: #8699a4;
	background-color: #0d3349;

	font-size: 1.5em;
	line-height: 1em;
	font-weight: normal;

	border-radius: 5px 5px 0 0;
	-moz-border-radius: 5px 5px 0 0;
	-webkit-border-top-right-radius: 5px;
	-webkit-border-top-left-radius: 5px;
}

#qunit-header a {
	text-decoration: none;
	color: #c2ccd1;
}

#qunit-header a:hover,
#qunit-header a:focus {
	color: #fff;
}

#qunit-testrunner-toolbar label {
	display: inline-block;
	padding: 0 .5em 0 .1em;
}

#qunit-banner {
	height: 5px;
}

#qunit-testrunner-toolbar {
	padding: 0.5em 0 0.5em 2em;
	color: #5E740B;
	background-color: #eee;
	overflow: hidden;
}

#qunit-userAgent {
	padding: 0.5em 0 0.5em 2.5em;
	background-color: #2b81af;
	color: #fff;
	text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}

#qunit-modulefilter-container {
	float: right;
}

/** Tests: Pass/Fail */

#qunit-tests {
	list-style-position: inside;
}

#qunit-tests li {
	padding: 0.4em 0.5em 0.4em 2.5em;
	border-bottom: 1px solid #fff;
	list-style-position: inside;
}

#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {
	display: none;
}

#qunit-tests li strong {
	cursor: pointer;
}

#qunit-tests li a {
	padding: 0.5em;
	color: #c2ccd1;
	text-decoration: none;
}
#qunit-tests li a:hover,
#qunit-tests li a:focus {
	color: #000;
}

#qunit-tests li .runtime {
	float: right;
	font-size: smaller;
}

.qunit-assert-list {
	margin-top: 0.5em;
	padding: 0.5em;

	background-color: #fff;

	border-radius: 5px;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
}

.qunit-collapsed {
	display: none;
}

#qunit-tests table {
	border-collapse: collapse;
	margin-top: .2em;
}

#qunit-tests th {
	text-align: right;
	vertical-align: top;
	padding: 0 .5em 0 0;
}

#qunit-tests td {
	vertical-align: top;
}

#qunit-tests pre {
	margin: 0;
	white-space: pre-wrap;
	word-wrap: break-word;
}

#qunit-tests del {
	background-color: #e0f2be;
	color: #374e0c;
	text-decoration: none;
}

#qunit-tests ins {
	background-color: #ffcaca;
	color: #500;
	text-decoration: none;
}

/*** Test Counts */

#qunit-tests b.counts                       { color: black; }
#qunit-tests b.passed                       { color: #5E740B; }
#qunit-tests b.failed                       { color: #710909; }

#qunit-tests li li {
	padding: 5px;
	background-color: #fff;
	border-bottom: none;
	list-style-position: inside;
}

/*** Passing Styles */

#qunit-tests li li.pass {
	color: #3c510c;
	background-color: #fff;
	border-left: 10px solid #C6E746;
}

#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
#qunit-tests .pass .test-name               { color: #366097; }

#qunit-tests .pass .test-actual,
#qunit-tests .pass .test-expected           { color: #999999; }

#qunit-banner.qunit-pass                    { background-color: #C6E746; }

/*** Failing Styles */

#qunit-tests li li.fail {
	color: #710909;
	background-color: #fff;
	border-left: 10px solid #EE5757;
	white-space: pre;
}

#qunit-tests > li:last-child {
	border-radius: 0 0 5px 5px;
	-moz-border-radius: 0 0 5px 5px;
	-webkit-border-bottom-right-radius: 5px;
	-webkit-border-bottom-left-radius: 5px;
}

#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }
#qunit-tests .fail .test-name,
#qunit-tests .fail .module-name             { color: #000000; }

#qunit-tests .fail .test-actual             { color: #EE5757; }
#qunit-tests .fail .test-expected           { color: green;   }

#qunit-banner.qunit-fail                    { background-color: #EE5757; }


/** Result */

#qunit-testresult {
	padding: 0.5em 0.5em 0.5em 2.5em;

	color: #2b81af;
	background-color: #D2E0E6;

	border-bottom: 1px solid white;
}
#qunit-testresult .module-name {
	font-weight: bold;
}

/** Fixture */

#qunit-fixture {
	position: absolute;
	top: -10000px;
	left: -10000px;
	width: 1000px;
	height: 1000px;
}
Original line number Original line Diff line number Diff line
{
  "name": "Backbone.Undo.js",
  "version": "0.2.5",
  "main": "Backbone.Undo.js",
  "license": "MIT license",
  "homepage": "http://backbone.undojs.com/",
  "authors": [
    "Oliver Sartun <osartun@gmail.com> (http://css3-html5.de)",
    "creynders <info@creynders.be> (http://www.creynders.be)",
    "Anton Shuvalov <anton_shuvalov@me.com> (http://anton-shuvalov.info)",
    "Marcin Lawrowski",
    "Vladislav Botvin <darkvlados@me.com>"
  ],
  "description": "A simple Backbone undo-manager for simple apps",
  "keywords": [
    "Backbone", "undo"
  ],
  "dependencies" :{
    "underscore": "1.4.4 - 1.8.3",
    "backbone": "1.0.0 - 1.2.1"
  },
  "ignore": [
    "Tests",
    ".gitignore",
    "sample",
    "README.md"
  ]
}
Original line number Original line Diff line number Diff line
Copyright (c) 2010-2015 Jeremy Ashkenas, DocumentCloud

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Original line number Original line Diff line number Diff line
     ____                     __      __
    /\  _`\                  /\ \    /\ \                                   __
    \ \ \ \ \     __      ___\ \ \/'\\ \ \____    ___     ___      __      /\_\    ____
     \ \  _ <'  /'__`\   /'___\ \ , < \ \ '__`\  / __`\ /' _ `\  /'__`\    \/\ \  /',__\
      \ \ \ \ \/\ \ \.\_/\ \__/\ \ \\`\\ \ \ \ \/\ \ \ \/\ \/\ \/\  __/  __ \ \ \/\__, `\
       \ \____/\ \__/.\_\ \____\\ \_\ \_\ \_,__/\ \____/\ \_\ \_\ \____\/\_\_\ \ \/\____/
        \/___/  \/__/\/_/\/____/ \/_/\/_/\/___/  \/___/  \/_/\/_/\/____/\/_/\ \_\ \/___/
                                                                           \ \____/
                                                                            \/___/
    (_'_______________________________________________________________________________'_)
    (_.———————————————————————————————————————————————————————————————————————————————._)


Backbone supplies structure to JavaScript-heavy applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface.

For Docs, License, Tests, pre-packed downloads, and everything else, really, see:
http://backbonejs.org

To suggest a feature, report a bug, or general discussion:
https://github.com/jashkenas/backbone/issues

Backbone is an open-sourced component of DocumentCloud:
https://github.com/documentcloud

Many thanks to our contributors:
https://github.com/jashkenas/backbone/graphs/contributors

Special thanks to Robert Kieffer for the original philosophy behind Backbone.
https://github.com/broofa
Original line number Original line Diff line number Diff line
{
  "name"          : "backbone",
  "description"   : "Give your JS App some Backbone with Models, Views, Collections, and Events.",
  "url"           : "http://backbonejs.org",
  "keywords"      : ["model", "view", "controller", "router", "server", "client", "browser"],
  "author"        : "Jeremy Ashkenas <jeremy@documentcloud.org>",
  "dependencies"  : {
    "underscore"  : ">=1.7.0"
  },
  "devDependencies": {
    "coffee-script": "1.7.1",
    "docco": "0.7.0",
    "karma": "^0.12.31",
    "karma-phantomjs-launcher": "^0.1.4",
    "karma-qunit": "^0.1.4",
    "uglify-js": "^2.4.17"
  },
  "scripts": {
    "test": "./node_modules/karma/bin/karma start && coffee test/model.coffee",
    "build": "uglifyjs backbone.js --mangle --source-map backbone-min.map -o backbone-min.js",
    "doc": "docco backbone.js && docco examples/todos/todos.js examples/backbone.localStorage.js",
    "lint": "jsl -nofilelisting -nologo -conf docs/jsl.conf -process backbone.js"
  },
  "main"          : "backbone.js",
  "version"       : "1.2.1",
  "license"       : "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/jashkenas/backbone.git"
  },
  "files": [
    "backbone.js", "backbone-min.js", "backbone-min.map", "LICENSE"
  ]
}
Original line number Original line Diff line number Diff line
Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative
Reporters & Editors

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Original line number Original line Diff line number Diff line
                       __
                      /\ \                                                         __
     __  __    ___    \_\ \     __   _ __   ____    ___    ___   _ __    __       /\_\    ____
    /\ \/\ \ /' _ `\  /'_  \  /'__`\/\  __\/ ,__\  / ___\ / __`\/\  __\/'__`\     \/\ \  /',__\
    \ \ \_\ \/\ \/\ \/\ \ \ \/\  __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\  __/  __  \ \ \/\__, `\
     \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
      \/___/  \/_/\/_/\/__,_ /\/____/ \/_/ \/___/  \/____/\/___/  \/_/ \/____/\/_//\ \_\ \/___/
                                                                                  \ \____/
                                                                                   \/___/

Underscore.js is a utility-belt library for JavaScript that provides
support for the usual functional suspects (each, map, reduce, filter...)
without extending any core JavaScript objects.

For Docs, License, Tests, and pre-packed downloads, see:
http://underscorejs.org

Underscore is an open-sourced component of DocumentCloud:
https://github.com/documentcloud

Many thanks to our contributors:
https://github.com/jashkenas/underscore/contributors
Original line number Original line Diff line number Diff line
//     Underscore.js 1.8.3
//     http://underscorejs.org
//     (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
//     Underscore may be freely distributed under the MIT license.
(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.indexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this);
//# sourceMappingURL=underscore-min.map
 No newline at end of file